From 40d0ff9f62a141d408a0e237016cbe832b4d09b4 Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Fri, 27 Mar 2015 22:56:51 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud) 99768: Merged 5.0.N (5.0.2) to HEAD-BUG-FIX (5.1/Cloud) 99699: Merged V4.2-BUG-FIX (4.2.5) to 5.0.N (5.0.2) 99634: Merged V4.1-BUG-FIX (4.1.10) to V4.2-BUG-FIX (4.2.5) 99442: Merged DEV to V4.1-BUG-FIX (4.1.10) 99036: MNT-13357: LDAP SSL Certificate not checked. - Create custom socket factory for LDAPS. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@100495 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../Authentication/common-ldap-context.xml | 13 ++ .../ldap-ad/ldap-ad-authentication.properties | 3 + .../ldap/ldap-authentication.properties | 3 + .../ldap/AlfrescoLdapSSLSocketFactory.java | 125 ++++++++++++++++++ .../LDAPInitialDirContextFactoryImpl.java | 2 + 5 files changed, 146 insertions(+) create mode 100755 source/java/org/alfresco/repo/security/authentication/ldap/AlfrescoLdapSSLSocketFactory.java diff --git a/config/alfresco/subsystems/Authentication/common-ldap-context.xml b/config/alfresco/subsystems/Authentication/common-ldap-context.xml index 744dc2b9fc..9208a160e3 100644 --- a/config/alfresco/subsystems/Authentication/common-ldap-context.xml +++ b/config/alfresco/subsystems/Authentication/common-ldap-context.xml @@ -127,6 +127,12 @@ ${ldap.authentication.java.naming.provider.url} + + + ${ldap.java.naming.ldap.factory.socket:#{null}} + + + @@ -165,6 +171,13 @@ ${ldap.authentication.java.naming.provider.url} + + + + ${ldap.java.naming.ldap.factory.socket:#{null}} + + + diff --git a/config/alfresco/subsystems/Authentication/ldap-ad/ldap-ad-authentication.properties b/config/alfresco/subsystems/Authentication/ldap-ad/ldap-ad-authentication.properties index 0a93ee02e9..4de2b1f0bd 100644 --- a/config/alfresco/subsystems/Authentication/ldap-ad/ldap-ad-authentication.properties +++ b/config/alfresco/subsystems/Authentication/ldap-ad/ldap-ad-authentication.properties @@ -19,6 +19,9 @@ ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory # The URL to connect to the LDAP server ldap.authentication.java.naming.provider.url=ldap://domaincontroller.company.com:389 +#Custom Socket Factory. +#ldap.java.naming.ldap.factory.socket=org.alfresco.repo.security.authentication.ldap.AlfrescoLdapSSLSocketFactory + # The authentication mechanism to use for password validation ldap.authentication.java.naming.security.authentication=simple diff --git a/config/alfresco/subsystems/Authentication/ldap/ldap-authentication.properties b/config/alfresco/subsystems/Authentication/ldap/ldap-authentication.properties index 0fa288ce9a..13c5336c43 100644 --- a/config/alfresco/subsystems/Authentication/ldap/ldap-authentication.properties +++ b/config/alfresco/subsystems/Authentication/ldap/ldap-authentication.properties @@ -25,6 +25,9 @@ ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory # The URL to connect to the LDAP server ldap.authentication.java.naming.provider.url=ldap://openldap.domain.com:389 +#Custom Socket Factory. +#ldap.java.naming.ldap.factory.socket=org.alfresco.repo.security.authentication.ldap.AlfrescoLdapSSLSocketFactory + # The authentication mechanism to use for password validation ldap.authentication.java.naming.security.authentication=simple diff --git a/source/java/org/alfresco/repo/security/authentication/ldap/AlfrescoLdapSSLSocketFactory.java b/source/java/org/alfresco/repo/security/authentication/ldap/AlfrescoLdapSSLSocketFactory.java new file mode 100755 index 0000000000..c6be543d0a --- /dev/null +++ b/source/java/org/alfresco/repo/security/authentication/ldap/AlfrescoLdapSSLSocketFactory.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.security.authentication.ldap; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * SSL Socket Factory that adds Hostname Verification to sockets + */ + +public class AlfrescoLdapSSLSocketFactory extends SocketFactory +{ + private static Log logger = LogFactory.getLog(AlfrescoLdapSSLSocketFactory.class); + + private static Boolean useJava6CodeBase = null; + private static Boolean useJava7CodeBase = null; + + public static SocketFactory getDefault() + + { + return new AlfrescoLdapSSLSocketFactory(); + } + + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException + { + SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(host, port); + addHostNameVerification(sslSocket); + return sslSocket; + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException + { + SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(host, port); + addHostNameVerification(sslSocket); + return sslSocket; + } + + @Override + public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws IOException, UnknownHostException + { + SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(address, port, localAddress, localPort); + addHostNameVerification(sslSocket); + return sslSocket; + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException + { + SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(address, port, localAddress, localPort); + addHostNameVerification(sslSocket); + return sslSocket; + } + + private void addHostNameVerification(SSLSocket sslSocket) + { + if (useJava6CodeBase == null || useJava6CodeBase) + { + //Try to use SSLSocketImpl.trySetHostnameVerification method that is supported by java6 and lower + try + { + Method m = sslSocket.getClass().getMethod("trySetHostnameVerification", String.class); + m.invoke(sslSocket, "LDAP"); + useJava6CodeBase = true; + useJava7CodeBase = false; + } + catch (Throwable e) + { + useJava6CodeBase = false; + } + } + + if (useJava7CodeBase == null || useJava7CodeBase) + { + //Try to use sslParams.setEndpointIdentificationAlgorithm method that is supported by java 7 and higher + try + { + SSLParameters sslParams = new SSLParameters(); + Method m = sslParams.getClass().getMethod("setEndpointIdentificationAlgorithm", String.class); + m.invoke(sslParams, "LDAPS"); + sslSocket.setSSLParameters(sslParams); + useJava6CodeBase = false; + useJava7CodeBase = true; + } + catch (Throwable ee) + { + useJava7CodeBase = false; + + if(useJava6CodeBase == false && logger.isWarnEnabled()) + { + logger.warn("AlfrescoLdapSSLSocketFactory: Unable to turn on Hostname Verification"); + } + } + } + } +} diff --git a/source/java/org/alfresco/repo/security/authentication/ldap/LDAPInitialDirContextFactoryImpl.java b/source/java/org/alfresco/repo/security/authentication/ldap/LDAPInitialDirContextFactoryImpl.java index 9b730b5aa0..6c6bb8a204 100644 --- a/source/java/org/alfresco/repo/security/authentication/ldap/LDAPInitialDirContextFactoryImpl.java +++ b/source/java/org/alfresco/repo/security/authentication/ldap/LDAPInitialDirContextFactoryImpl.java @@ -123,6 +123,7 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa public void setInitialDirContextEnvironment(Map initialDirContextEnvironment) { this.authenticatedEnvironment = initialDirContextEnvironment; + this.authenticatedEnvironment.values().removeAll(Collections.singleton(null)); } public Map getInitialDirContextEnvironment() @@ -133,6 +134,7 @@ public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFa public void setDefaultIntialDirContextEnvironment(Map defaultEnvironment) { this.defaultEnvironment = defaultEnvironment; + this.defaultEnvironment.values().removeAll(Collections.singleton(null)); } public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException