/* -*- mode: java; c-basic-offset: 4; indent-tabs-mode: nil -*- * * Copyright (C) 2001 ArsDigita Corporation. All Rights Reserved. * * The contents of this file are subject to the ArsDigita Public * License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of * the License at http://www.arsdigita.com/ADPL.txt * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * */ package com.arsdigita.auth.http; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import java.security.GeneralSecurityException; import java.security.PrivateKey; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.ShortBufferException; import sun.misc.BASE64Encoder; /** *

* Attempt to authenticate a user against an IIS server. *

* *

* This servlet runs on an IIS server and is used as part of * the mechanism for automatically authenticating IE users on * CCM. *

* *

Managing the public and private keys

* *

* The IIS server needs to send a signed cookie to the CCM server. * To do this, the IIS server needs a private key, and the CCM * server needs the corresponding public key. This section * describes how to generate and distribute the keys. *

* *

* On the IIS server, you need to generate the private/public key * pair using the Java keytool utility. Run * keytool like this: *

* *
 * keytool -genkey -keyalg rsa -validity 365 -keypass 123456 \
 *         -dname 'cn=jones' -alias ccmkey
 * 
* *

* The -dname field does not matter. Make sure the * key store has password 123456 (or change the * HTTPAuthServlet to use a different password). *

* *

* The resultant keystore (or .keystore) * file must be copied to $webappdir/WEB-INF/keystore * (on the IIS server). *

* *

* Now on the IIS server export the public key into a separate * file like this: *

* *
 * keytool -export -alias ccmkey -file c:\temp\public_cert
 * 
* *

* You will need to type the keystore password in (123456). * *

* Copy the public key to the CCM server, and import it into the * keystore file on the CCM server like this: *

* *

* keytool -import -alias ccmkey -file /tmp/public_cert *

* *

* Make sure the keystore (or .keystore) * file on the CCM file is copied to $webappdir/WEB-INF/keystore. *

* *

* Ensure that the public key has alias ccmkey * and password 123456. *

* * @author Matt Booth, documentation by Richard W.M. Jones. * @see com.arsdigita.auth.ntlm.NTLMLoginModule */ public class HTTPAuthServlet extends HttpServlet { private Cipher m_encrypt; // Leave same for backwards compatability public static final String AUTH = "__camden_auth"; public static final String MAGIC = "camden"; /** * Open the keystore and look for a key with the given alias. Create * the encryption (ie. signing) cipher object. */ public void init() throws ServletException { // Create the encryption cypher. PrivateKey privateKey = HTTPAuth.getConfig().getPrivateKey(); try { m_encrypt = Cipher.getInstance(HTTPAuth.getConfig().getKeyCypher()); m_encrypt.init (Cipher.ENCRYPT_MODE, privateKey); } catch (GeneralSecurityException ex) { throw new ServletException (ex); } } public void doGet( HttpServletRequest req, HttpServletResponse res ) throws IOException, ServletException { String nonce = req.getParameter ("nonce"); // If no nonce, just return the public key if ( nonce == null ) { throw new ServletException ("nonce parameter missing"); } String returnURL = req.getParameter ("returnURL"); if ( returnURL == null ) { throw new ServletException( "returnURL was not specified" ); } // Generate an authorisation string of the form MAGICnonce|USERIDENT String authString = MAGIC + nonce + "|" + getRemoteUser (req); try { byte[] encBytes = new byte[ m_encrypt.getOutputSize( authString.length() ) ]; m_encrypt.doFinal( authString.getBytes(), 0, authString.length(), encBytes ); authString = new BASE64Encoder().encode( encBytes ); authString = URLEncoder.encode( authString ); } catch( IllegalBlockSizeException e ) { throw new ServletException( e ); } catch( BadPaddingException e ) { throw new ServletException( e ); } catch( ShortBufferException e ) { throw new ServletException( e ); } if ( returnURL.indexOf( "?" ) == -1 ) { returnURL += "?"; } else { returnURL += "&"; } returnURL += AUTH + "=" + authString; res.sendRedirect( returnURL ); } /** * Note by RWMJ: I separated this out into a separate function just * to make it simpler to test by hacking in hard-coded values. */ private String getRemoteUser (HttpServletRequest req) { if (HTTPAuth.getConfig().isDebugMode()) { return "example\\\\administrator"; } else { return req.getRemoteUser (); } } }