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 org.apache.directory.api.ldap.model.constants.AuthenticationLevel; 026import org.apache.directory.api.ldap.model.entry.Entry; 027import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException; 028import org.apache.directory.api.ldap.model.exception.LdapException; 029import org.apache.directory.api.ldap.model.name.Dn; 030import org.apache.directory.api.util.Strings; 031import org.apache.directory.ldap.client.api.LdapConnectionConfig; 032import org.apache.directory.ldap.client.api.LdapNetworkConnection; 033import org.apache.directory.ldap.client.api.NoVerificationTrustManager; 034import org.apache.directory.server.core.api.LdapPrincipal; 035import org.apache.directory.server.core.api.interceptor.context.BindOperationContext; 036import org.apache.directory.server.i18n.I18n; 037import org.apache.mina.core.session.IoSession; 038 039 040/** 041 * Authenticator delegating to another LDAP server. 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 */ 045public class DelegatingAuthenticator extends AbstractAuthenticator 046{ 047 /** A speedup for logger in debug mode */ 048 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 049 050 /** The host in charge of delegated authentication */ 051 private String delegateHost; 052 053 /** The associated port */ 054 private int delegatePort; 055 056 /** Tells if we use SSL to connect */ 057 private boolean delegateSsl; 058 059 /** Tells if we use StartTLS to connect */ 060 private boolean delegateTls; 061 062 /** The SSL TrustManager FQCN to use */ 063 private String delegateSslTrustManagerFQCN; 064 065 /** The startTLS TrustManager FQCN to use */ 066 private String delegateTlsTrustManagerFQCN; 067 068 069 /** 070 * Creates a new instance. 071 */ 072 public DelegatingAuthenticator() 073 { 074 super( AuthenticationLevel.SIMPLE ); 075 } 076 077 078 /** 079 * Creates a new instance. 080 * @see AbstractAuthenticator 081 * @param baseDn The base Dn 082 */ 083 public DelegatingAuthenticator( Dn baseDn ) 084 { 085 super( AuthenticationLevel.SIMPLE, baseDn ); 086 } 087 088 089 /** 090 * Creates a new instance, for a specific authentication level. 091 * @see AbstractAuthenticator 092 * @param type The relevant AuthenticationLevel 093 * @param baseDn The base Dn 094 */ 095 protected DelegatingAuthenticator( AuthenticationLevel type, Dn baseDn ) 096 { 097 super( type, baseDn ); 098 } 099 100 101 /** 102 * @return the delegateHost 103 */ 104 public String getDelegateHost() 105 { 106 return delegateHost; 107 } 108 109 110 /** 111 * @param delegateHost the delegateHost to set 112 */ 113 public void setDelegateHost( String delegateHost ) 114 { 115 this.delegateHost = delegateHost; 116 } 117 118 119 /** 120 * @return the delegatePort 121 */ 122 public int getDelegatePort() 123 { 124 return delegatePort; 125 } 126 127 128 /** 129 * @param delegatePort the delegatePort to set 130 */ 131 public void setDelegatePort( int delegatePort ) 132 { 133 this.delegatePort = delegatePort; 134 } 135 136 137 /** 138 * @return the delegateSsl 139 */ 140 public boolean isDelegateSsl() 141 { 142 return delegateSsl; 143 } 144 145 146 /** 147 * @param delegateSsl the delegateSsl to set 148 */ 149 public void setDelegateSsl( boolean delegateSsl ) 150 { 151 this.delegateSsl = delegateSsl; 152 } 153 154 155 /** 156 * @return the delegateBaseDn 157 */ 158 public String getDelegateBaseDn() 159 { 160 return getBaseDn().toString(); 161 } 162 163 164 /** 165 * @return the delegateTls 166 */ 167 public boolean isDelegateTls() 168 { 169 return delegateTls; 170 } 171 172 173 /** 174 * @param delegateTls the delegateTls to set 175 */ 176 public void setDelegateTls( boolean delegateTls ) 177 { 178 this.delegateTls = delegateTls; 179 } 180 181 182 /** 183 * @return the delegateSslTrustManagerFQCN 184 */ 185 public String getDelegateSslTrustManagerFQCN() 186 { 187 return delegateSslTrustManagerFQCN; 188 } 189 190 191 /** 192 * @param delegateSslTrustManagerFQCN the delegateSslTrustManagerFQCN to set 193 */ 194 public void setDelegateSslTrustManagerFQCN( String delegateSslTrustManagerFQCN ) 195 { 196 this.delegateSslTrustManagerFQCN = delegateSslTrustManagerFQCN; 197 } 198 199 200 /** 201 * @return the delegateTlsTrustManagerFQCN 202 */ 203 public String getDelegateTlsTrustManagerFQCN() 204 { 205 return delegateTlsTrustManagerFQCN; 206 } 207 208 209 /** 210 * @param delegateTlsTrustManagerFQCN the delegateTlsTrustManagerFQCN to set 211 */ 212 public void setDelegateTlsTrustManagerFQCN( String delegateTlsTrustManagerFQCN ) 213 { 214 this.delegateTlsTrustManagerFQCN = delegateTlsTrustManagerFQCN; 215 } 216 217 218 /** 219 * {@inheritDoc} 220 */ 221 @Override 222 public LdapPrincipal authenticate( BindOperationContext bindContext ) 223 throws LdapException 224 { 225 LdapPrincipal principal = null; 226 227 if ( IS_DEBUG ) 228 { 229 LOG.debug( "Authenticating {}", bindContext.getDn() ); 230 } 231 232 // First, check that the Bind DN is under the delegateBaseDn 233 Dn bindDn = bindContext.getDn(); 234 235 // Don't authenticate using this authenticator if the Bind ND is not a descendant of the 236 // configured delegate base DN (or if it's null) 237 if ( ( getBaseDn() == null ) || ( !bindDn.isDescendantOf( getBaseDn() ) ) ) 238 { 239 return null; 240 } 241 242 LdapConnectionConfig connectionConfig; 243 LdapNetworkConnection ldapConnection; 244 245 // Create a connection on the remote host 246 if ( delegateTls ) 247 { 248 connectionConfig = new LdapConnectionConfig(); 249 connectionConfig.setLdapHost( delegateHost ); 250 connectionConfig.setLdapPort( delegatePort ); 251 connectionConfig.setTrustManagers( new NoVerificationTrustManager() ); 252 253 ldapConnection = new LdapNetworkConnection( connectionConfig ); 254 ldapConnection.connect(); 255 ldapConnection.startTls(); 256 } 257 else if ( delegateSsl ) 258 { 259 connectionConfig = new LdapConnectionConfig(); 260 connectionConfig.setLdapHost( delegateHost ); 261 connectionConfig.setUseSsl( true ); 262 connectionConfig.setLdapPort( delegatePort ); 263 connectionConfig.setTrustManagers( new NoVerificationTrustManager() ); 264 265 ldapConnection = new LdapNetworkConnection( connectionConfig ); 266 ldapConnection.connect(); 267 } 268 else 269 { 270 connectionConfig = new LdapConnectionConfig(); 271 connectionConfig.setLdapHost( delegateHost ); 272 connectionConfig.setLdapPort( delegatePort ); 273 274 ldapConnection = new LdapNetworkConnection( delegateHost, delegatePort ); 275 ldapConnection.connect(); 276 } 277 278 ldapConnection.setTimeOut( 0L ); 279 280 try 281 { 282 // Try to bind 283 try 284 { 285 ldapConnection.bind( bindDn, Strings.utf8ToString( bindContext.getCredentials() ) ); 286 } 287 catch ( LdapException le ) 288 { 289 String message = I18n.err( I18n.ERR_230, bindDn.getName() ); 290 LOG.info( message ); 291 throw new LdapAuthenticationException( message ); 292 } 293 finally 294 { 295 // no need to remain bound to delegate host 296 ldapConnection.unBind(); 297 298 if ( IS_DEBUG ) 299 { 300 LOG.debug( "Authenticated successfully {}", bindContext.getDn() ); 301 } 302 } 303 304 // Create the new principal 305 principal = new LdapPrincipal( getDirectoryService().getSchemaManager(), bindDn, 306 AuthenticationLevel.SIMPLE, 307 bindContext.getCredentials() ); 308 309 IoSession session = bindContext.getIoSession(); 310 311 if ( session != null ) 312 { 313 SocketAddress clientAddress = session.getRemoteAddress(); 314 principal.setClientAddress( clientAddress ); 315 SocketAddress serverAddress = session.getServiceAddress(); 316 principal.setServerAddress( serverAddress ); 317 } 318 319 return principal; 320 } 321 catch ( LdapException e ) 322 { 323 // Bad password ... 324 String message = I18n.err( I18n.ERR_230, bindDn.getName() ); 325 LOG.info( message ); 326 throw new LdapAuthenticationException( message ); 327 } 328 finally 329 { 330 ldapConnection.close(); 331 } 332 } 333 334 335 /** 336 * We don't handle any password policy when using a delegated authentication 337 */ 338 @Override 339 public void checkPwdPolicy( Entry userEntry ) throws LdapException 340 { 341 // no check for delegating authentication 342 } 343 344 345 /** 346 * We don't handle any cache when using a delegated authentication 347 */ 348 @Override 349 public void invalidateCache( Dn bindDn ) 350 { 351 // cache is not implemented here 352 } 353}