/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (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.mozilla.org/MPL/ * * 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. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package netscape.ldap; import java.io.*; import java.net.*; import java.util.Hashtable; /** * Creates an SSL socket connection to an LDAP Server. This class is provided * by the package in which the SSL socket does not extend Socket object. * The class internally provides a wrapper to convert the SSL socket extending * the Object class to the one extending the Socket class. * This factory class implements the LDAPSocketFactory interface. *

* * To use this class, pass the instance of this factory object to the * LDAPConnection constructor. * * @version 1.0 * @see LDAPSocketFactory * @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory) */ public class LDAPSSLSocketWrapFactory implements LDAPSSLSocketFactoryExt, java.io.Serializable { static final long serialVersionUID = -4171548771815037740L; /** * The constructor with the specified package for security * @param className the name of a class which has an implementation * of the SSL Socket extending Object class */ public LDAPSSLSocketWrapFactory(String className) { m_packageName = new String(className); } /** * The constructor with the specified package for security and the * specified cipher suites. * @param className the name of a class which has an implementation * of the SSL Socket extending Object class * @param cipherSuites the cipher suites */ public LDAPSSLSocketWrapFactory(String className, Object cipherSuites) { m_packageName = new String(className); m_cipherSuites = cipherSuites; } /** * Returns socket to the specified host name and port number. * @param host the host to connect to * @param port the port number * @return the socket to the host name and port number as passed in. * @exception LDAPException A socket to the specified host and port * could not be created. */ public Socket makeSocket(String host, int port) throws LDAPException { LDAPSSLSocket s = null; try { if (m_cipherSuites == null) s = new LDAPSSLSocket(host, port, m_packageName); else s = new LDAPSSLSocket(host, port, m_packageName, m_cipherSuites); return s; } catch (Exception e) { System.err.println("Exception: "+e.toString()); throw new LDAPException("Failed to create SSL socket", LDAPException.CONNECT_ERROR); } } /** * Returns true if client authentication is to be used. * @return true if client authentication is enabled; * falseif client authentication is disabled. */ public boolean isClientAuth() { return m_clientAuth; } /** * (Not implemented yet)
* Enables client authentication for an application running in * a java VM which provides transparent certificate database management. * Calling this method has no effect after makeSocket() has been * called. * @exception LDAPException Since this method is not yet implemented, * calling this method throws an exception. */ public void enableClientAuth() throws LDAPException { throw new LDAPException("Client Authentication is not implemented yet."); } /** * Returns the name of the class that implements SSL sockets for this factory. * * @return the name of the class that implements SSL sockets for this factory. */ public String getSSLSocketImpl() { return m_packageName; } /** * Returns the suite of ciphers used for SSL connections made through * sockets created by this factory. * * @return the suite of ciphers used. */ public Object getCipherSuites() { return m_cipherSuites; } /** * Indicates if client authentication is on. */ private boolean m_clientAuth = false; /** * Name of class implementing SSLSocket. */ private String m_packageName = null; /** * The cipher suites */ private Object m_cipherSuites = null; } // LDAPSSLSocket class wraps the implementation of the SSL socket class LDAPSSLSocket extends Socket { public LDAPSSLSocket(String host, int port, String packageName) throws LDAPException { super(); m_packageName = packageName; try { // instantiate the SSLSocketFactory implementation, and // find the right constructor Class c = Class.forName(m_packageName); java.lang.reflect.Constructor[] m = c.getConstructors(); for (int i = 0; i < m.length; i++) { /* Check if the signature is right: String, int */ Class[] params = m[i].getParameterTypes(); if ((params.length == 2) && (params[0].getName().equals("java.lang.String")) && (params[1].getName().equals("int"))) { Object[] args = new Object[2]; args[0] = host; args[1] = new Integer(port); m_socket = (Object)(m[i].newInstance(args)); return; } } throw new LDAPException("No appropriate constructor in " + m_packageName, LDAPException.PARAM_ERROR); } catch (ClassNotFoundException e) { throw new LDAPException("Class " + m_packageName + " not found", LDAPException.OTHER); } catch (Exception e) { throw new LDAPException("Failed to create SSL socket", LDAPException.CONNECT_ERROR); } } public LDAPSSLSocket(String host, int port, String packageName, Object cipherSuites) throws LDAPException { super(); m_packageName = packageName; String cipherClassName = null; if (cipherSuites != null) cipherClassName = cipherSuites.getClass().getName(); try { // instantiate the SSLSocketFactory implementation, and // find the right constructor Class c = Class.forName(m_packageName); java.lang.reflect.Constructor[] m = c.getConstructors(); for (int i = 0; i < m.length; i++) { /* Check if the signature is right: String, int */ Class[] params = m[i].getParameterTypes(); if (cipherSuites == null) throw new LDAPException("Cipher Suites is required"); if ((params.length == 3) && (params[0].getName().equals("java.lang.String")) && (params[1].getName().equals("int")) && (params[2].getName().equals(cipherClassName))) { Object[] args = new Object[3]; args[0] = host; args[1] = new Integer(port); args[2] = cipherSuites; m_socket = (Object)(m[i].newInstance(args)); return; } } throw new LDAPException("No appropriate constructor in " + m_packageName, LDAPException.PARAM_ERROR); } catch (ClassNotFoundException e) { throw new LDAPException("Class " + m_packageName + " not found", LDAPException.OTHER); } catch (Exception e) { throw new LDAPException("Failed to create SSL socket", LDAPException.CONNECT_ERROR); } } public InputStream getInputStream() { try { Object obj = invokeMethod(m_socket, "getInputStream", null); return (InputStream)obj; } catch (LDAPException e) { printDebug(e.toString()); } return null; } public OutputStream getOutputStream() { try { Object obj = invokeMethod(m_socket, "getOutputStream", null); return (OutputStream)obj; } catch (LDAPException e) { printDebug(e.toString()); } return null; } public void close() throws IOException { try { invokeMethod(m_socket, "close", null); } catch (LDAPException e) { printDebug(e.toString()); } } public void close(boolean wait) throws IOException { try { Object[] args = new Object[1]; args[0] = new Boolean(wait); invokeMethod(m_socket, "close", args); } catch (LDAPException e) { printDebug(e.toString()); } } public InetAddress getInetAddress() { try { Object obj = invokeMethod(m_socket, "getInetAddress", null); return (InetAddress)obj; } catch (LDAPException e) { printDebug(e.toString()); } return null; } public int getLocalPort() { try { Object obj = invokeMethod(m_socket, "getLocalPort", null); return ((Integer)obj).intValue(); } catch (LDAPException e) { printDebug(e.toString()); } return -1; } public int getPort() { try { Object obj = invokeMethod(m_socket, "getPort", null); return ((Integer)obj).intValue(); } catch (LDAPException e) { printDebug(e.toString()); } return -1; } private Object invokeMethod(Object obj, String name, Object[] args) throws LDAPException { try { java.lang.reflect.Method m = getMethod(name); if (m != null) { return (m.invoke(obj, args)); } } catch (Exception e) { throw new LDAPException("Invoking "+name+": "+ e.toString(), LDAPException.PARAM_ERROR); } return null; } private java.lang.reflect.Method getMethod(String name) throws LDAPException { try { java.lang.reflect.Method method = null; if ((method = (java.lang.reflect.Method)(m_methodLookup.get(name))) != null) return method; Class c = Class.forName(m_packageName); java.lang.reflect.Method[] m = c.getMethods(); for (int i = 0; i < m.length; i++ ) { if (m[i].getName().equals(name)) { m_methodLookup.put(name, m[i]); return m[i]; } } throw new LDAPException("Method " + name + " not found in " + m_packageName); } catch (ClassNotFoundException e) { throw new LDAPException("Class "+ m_packageName + " not found"); } } private void printDebug(String msg) { if (m_debug) { System.out.println(msg); } } private final boolean m_debug = true; private Object m_socket; private Hashtable m_methodLookup = new Hashtable(); private String m_packageName = null; }