001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.server.core.authn; 021 022 023import java.net.SocketAddress; 024 025import javax.net.ssl.TrustManager; 026 027import org.apache.directory.api.ldap.model.constants.AuthenticationLevel; 028import org.apache.directory.api.ldap.model.entry.Entry; 029import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException; 030import org.apache.directory.api.ldap.model.exception.LdapException; 031import org.apache.directory.api.ldap.model.name.Dn; 032import org.apache.directory.api.util.Strings; 033import org.apache.directory.ldap.client.api.LdapConnectionConfig; 034import org.apache.directory.ldap.client.api.LdapNetworkConnection; 035import org.apache.directory.server.core.api.LdapPrincipal; 036import org.apache.directory.server.core.api.interceptor.context.BindOperationContext; 037import org.apache.directory.server.i18n.I18n; 038import org.apache.mina.core.session.IoSession; 039 040 041/** 042 * Authenticator delegating to another LDAP server. 043 * 044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 045 */ 046public class DelegatingAuthenticator extends AbstractAuthenticator 047{ 048 /** A speedup for logger in debug mode */ 049 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 050 051 /** The host in charge of delegated authentication */ 052 private String delegateHost; 053 054 /** The associated port */ 055 private int delegatePort; 056 057 /** Tells if we use SSL to connect */ 058 private boolean delegateSsl; 059 060 /** Tells if we use StartTLS to connect */ 061 private boolean delegateTls; 062 063 /** The SSL TrustManager FQCN to use */ 064 private String delegateSslTrustManagerFQCN; 065 066 /** The startTLS TrustManager FQCN to use */ 067 private String delegateTlsTrustManagerFQCN; 068 069 070 /** 071 * Creates a new instance. 072 */ 073 public DelegatingAuthenticator() 074 { 075 super( AuthenticationLevel.SIMPLE ); 076 } 077 078 079 /** 080 * Creates a new instance. 081 * @see AbstractAuthenticator 082 * @param baseDn The base Dn 083 */ 084 public DelegatingAuthenticator( Dn baseDn ) 085 { 086 super( AuthenticationLevel.SIMPLE, baseDn ); 087 } 088 089 090 /** 091 * Creates a new instance, for a specific authentication level. 092 * @see AbstractAuthenticator 093 * @param type The relevant AuthenticationLevel 094 * @param baseDn The base Dn 095 */ 096 protected DelegatingAuthenticator( AuthenticationLevel type, Dn baseDn ) 097 { 098 super( type, baseDn ); 099 } 100 101 102 /** 103 * @return the delegateHost 104 */ 105 public String getDelegateHost() 106 { 107 return delegateHost; 108 } 109 110 111 /** 112 * @param delegateHost the delegateHost to set 113 */ 114 public void setDelegateHost( String delegateHost ) 115 { 116 this.delegateHost = delegateHost; 117 } 118 119 120 /** 121 * @return the delegatePort 122 */ 123 public int getDelegatePort() 124 { 125 return delegatePort; 126 } 127 128 129 /** 130 * @param delegatePort the delegatePort to set 131 */ 132 public void setDelegatePort( int delegatePort ) 133 { 134 this.delegatePort = delegatePort; 135 } 136 137 138 /** 139 * @return the delegateSsl 140 */ 141 public boolean isDelegateSsl() 142 { 143 return delegateSsl; 144 } 145 146 147 /** 148 * @param delegateSsl the delegateSsl to set 149 */ 150 public void setDelegateSsl( boolean delegateSsl ) 151 { 152 this.delegateSsl = delegateSsl; 153 } 154 155 156 /** 157 * @return the delegateBaseDn 158 */ 159 public String getDelegateBaseDn() 160 { 161 return getBaseDn().toString(); 162 } 163 164 165 /** 166 * @return the delegateTls 167 */ 168 public boolean isDelegateTls() 169 { 170 return delegateTls; 171 } 172 173 174 /** 175 * @param delegateTls the delegateTls to set 176 */ 177 public void setDelegateTls( boolean delegateTls ) 178 { 179 this.delegateTls = delegateTls; 180 } 181 182 183 /** 184 * @return the delegateSslTrustManagerFQCN 185 */ 186 public String getDelegateSslTrustManagerFQCN() 187 { 188 return delegateSslTrustManagerFQCN; 189 } 190 191 192 /** 193 * @param delegateSslTrustManagerFQCN the delegateSslTrustManagerFQCN to set 194 */ 195 public void setDelegateSslTrustManagerFQCN( String delegateSslTrustManagerFQCN ) 196 { 197 this.delegateSslTrustManagerFQCN = delegateSslTrustManagerFQCN; 198 } 199 200 201 /** 202 * @return the delegateTlsTrustManagerFQCN 203 */ 204 public String getDelegateTlsTrustManagerFQCN() 205 { 206 return delegateTlsTrustManagerFQCN; 207 } 208 209 210 /** 211 * @param delegateTlsTrustManagerFQCN the delegateTlsTrustManagerFQCN to set 212 */ 213 public void setDelegateTlsTrustManagerFQCN( String delegateTlsTrustManagerFQCN ) 214 { 215 this.delegateTlsTrustManagerFQCN = delegateTlsTrustManagerFQCN; 216 } 217 218 219 /** 220 * {@inheritDoc} 221 */ 222 @Override 223 public LdapPrincipal authenticate( BindOperationContext bindContext ) 224 throws LdapException 225 { 226 LdapPrincipal principal = null; 227 228 if ( IS_DEBUG ) 229 { 230 LOG.debug( "Authenticating {}", bindContext.getDn() ); 231 } 232 233 // First, check that the Bind DN is under the delegateBaseDn 234 Dn bindDn = bindContext.getDn(); 235 236 // Don't authenticate using this authenticator if the Bind ND is not a descendant of the 237 // configured delegate base DN (or if it's null) 238 if ( ( getBaseDn() == null ) || ( !bindDn.isDescendantOf( getBaseDn() ) ) ) 239 { 240 return null; 241 } 242 243 LdapConnectionConfig connectionConfig; 244 LdapNetworkConnection ldapConnection; 245 246 // Create a connection on the remote host 247 if ( delegateTls ) 248 { 249 connectionConfig = new LdapConnectionConfig(); 250 connectionConfig.setLdapHost( delegateHost ); 251 connectionConfig.setLdapPort( delegatePort ); 252 if ( delegateTlsTrustManagerFQCN != null && !"".equals( delegateTlsTrustManagerFQCN ) ) 253 { 254 try 255 { 256 Class<?> trustManagerClass = Class.forName( delegateTlsTrustManagerFQCN ); 257 TrustManager trustManager = ( TrustManager ) trustManagerClass.newInstance(); 258 connectionConfig.setTrustManagers( trustManager ); 259 } 260 catch ( ClassNotFoundException | InstantiationException | IllegalAccessException e ) 261 { 262 String message = "Cannot load " + delegateTlsTrustManagerFQCN; 263 LOG.error( message ); 264 throw new LdapException( message ); 265 } 266 } 267 268 ldapConnection = new LdapNetworkConnection( connectionConfig ); 269 ldapConnection.connect(); 270 ldapConnection.startTls(); 271 } 272 else if ( delegateSsl ) 273 { 274 connectionConfig = new LdapConnectionConfig(); 275 connectionConfig.setLdapHost( delegateHost ); 276 connectionConfig.setUseSsl( true ); 277 connectionConfig.setLdapPort( delegatePort ); 278 if ( delegateSslTrustManagerFQCN != null && !"".equals( delegateSslTrustManagerFQCN ) ) 279 { 280 try 281 { 282 Class<?> trustManagerClass = Class.forName( delegateSslTrustManagerFQCN ); 283 TrustManager trustManager = ( TrustManager ) trustManagerClass.newInstance(); 284 connectionConfig.setTrustManagers( trustManager ); 285 } 286 catch ( ClassNotFoundException | InstantiationException | IllegalAccessException e ) 287 { 288 String message = "Cannot load " + delegateSslTrustManagerFQCN; 289 LOG.error( message ); 290 throw new LdapException( message ); 291 } 292 } 293 294 ldapConnection = new LdapNetworkConnection( connectionConfig ); 295 ldapConnection.connect(); 296 } 297 else 298 { 299 connectionConfig = new LdapConnectionConfig(); 300 connectionConfig.setLdapHost( delegateHost ); 301 connectionConfig.setLdapPort( delegatePort ); 302 303 ldapConnection = new LdapNetworkConnection( delegateHost, delegatePort ); 304 ldapConnection.connect(); 305 } 306 307 ldapConnection.setTimeOut( 0L ); 308 309 try 310 { 311 // Try to bind 312 try 313 { 314 ldapConnection.bind( bindDn, Strings.utf8ToString( bindContext.getCredentials() ) ); 315 } 316 catch ( LdapException le ) 317 { 318 String message = I18n.err( I18n.ERR_230, bindDn.getName() ); 319 LOG.info( message ); 320 throw new LdapAuthenticationException( message ); 321 } 322 finally 323 { 324 // no need to remain bound to delegate host 325 ldapConnection.unBind(); 326 327 if ( IS_DEBUG ) 328 { 329 LOG.debug( "Authenticated successfully {}", bindContext.getDn() ); 330 } 331 } 332 333 // Create the new principal 334 principal = new LdapPrincipal( getDirectoryService().getSchemaManager(), bindDn, 335 AuthenticationLevel.SIMPLE, 336 bindContext.getCredentials() ); 337 338 IoSession session = bindContext.getIoSession(); 339 340 if ( session != null ) 341 { 342 SocketAddress clientAddress = session.getRemoteAddress(); 343 principal.setClientAddress( clientAddress ); 344 SocketAddress serverAddress = session.getServiceAddress(); 345 principal.setServerAddress( serverAddress ); 346 } 347 348 return principal; 349 } 350 catch ( LdapException e ) 351 { 352 // Bad password ... 353 String message = I18n.err( I18n.ERR_230, bindDn.getName() ); 354 LOG.info( message ); 355 throw new LdapAuthenticationException( message ); 356 } 357 finally 358 { 359 ldapConnection.close(); 360 } 361 } 362 363 364 /** 365 * We don't handle any password policy when using a delegated authentication 366 */ 367 @Override 368 public void checkPwdPolicy( Entry userEntry ) throws LdapException 369 { 370 // no check for delegating authentication 371 } 372 373 374 /** 375 * We don't handle any cache when using a delegated authentication 376 */ 377 @Override 378 public void invalidateCache( Dn bindDn ) 379 { 380 // cache is not implemented here 381 } 382}