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 */ 020 package org.apache.directory.server.core.interceptor.context; 021 022 023 import java.util.Collection; 024 import java.util.Collections; 025 import java.util.HashMap; 026 import java.util.List; 027 import java.util.Map; 028 029 import org.apache.commons.lang.NotImplementedException; 030 import org.apache.directory.server.core.CoreSession; 031 import org.apache.directory.server.core.LdapPrincipal; 032 import org.apache.directory.server.core.ReferralHandlingMode; 033 import org.apache.directory.server.core.entry.ClonedServerEntry; 034 import org.apache.directory.server.i18n.I18n; 035 import org.apache.directory.shared.ldap.codec.MessageTypeEnum; 036 import org.apache.directory.shared.ldap.constants.AuthenticationLevel; 037 import org.apache.directory.shared.ldap.entry.Modification; 038 import org.apache.directory.shared.ldap.entry.ServerEntry; 039 import org.apache.directory.shared.ldap.message.control.Control; 040 import org.apache.directory.shared.ldap.name.DN; 041 import org.apache.directory.shared.ldap.util.StringTools; 042 043 044 /** 045 * A Bind context used for Interceptors. It contains all the informations 046 * needed for the bind operation, and used by all the interceptors 047 * 048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 049 * @version $Rev$, $Date$ 050 */ 051 public class BindOperationContext implements OperationContext 052 { 053 /** The password */ 054 private byte[] credentials; 055 056 /** The SASL mechanism */ 057 private String saslMechanism; 058 059 /** The SASL identifier */ 060 private String saslAuthId; 061 062 private static final Control[] EMPTY_CONTROLS = new Control[0]; 063 064 /** The DN associated with the context */ 065 private DN dn; 066 067 /** The associated request's controls */ 068 private Map<String, Control> requestControls = new HashMap<String, Control>(4); 069 070 /** The associated response's controls */ 071 private Map<String, Control> responseControls = new HashMap<String, Control>(4); 072 073 /** A flag to tell that this is a collateral operation */ 074 private boolean collateralOperation; 075 076 /** the Interceptors bypassed by this operation */ 077 private Collection<String> bypassed; 078 079 private CoreSession session; 080 081 private LdapPrincipal authorizedPrincipal; 082 083 private OperationContext next; 084 085 private OperationContext previous; 086 087 private ReferralHandlingMode referralHandlingMode; 088 089 private ClonedServerEntry entry; 090 091 092 /** 093 * Creates a new instance of BindOperationContext. 094 */ 095 public BindOperationContext( CoreSession session ) 096 { 097 this.session = session; 098 } 099 100 101 /** 102 * @return The authentication level. One of : 103 * <li>ANONYMOUS</li> 104 * <li>SIMPLE</li> 105 * <li>STRONG (sasl)</li> 106 * <li>UNAUTHENT</li> 107 * <li>INVALID</li> 108 */ 109 public AuthenticationLevel getAuthenticationLevel() 110 { 111 if ( ( saslMechanism == null ) ) 112 { 113 if ( dn.isEmpty() ) 114 { 115 if ( StringTools.isEmpty( credentials ) ) 116 { 117 // Dn and Credentials are empty, this is an anonymous authent 118 return AuthenticationLevel.NONE; 119 } 120 else 121 { 122 // If we have a password but no DN, this is invalid 123 return AuthenticationLevel.INVALID; 124 } 125 } 126 else if ( StringTools.isEmpty( credentials ) ) 127 { 128 return AuthenticationLevel.UNAUTHENT; 129 } 130 else 131 { 132 return AuthenticationLevel.SIMPLE; 133 } 134 } 135 else 136 { 137 return AuthenticationLevel.STRONG; 138 } 139 } 140 141 142 /** 143 * @return the SASL mechanisms 144 */ 145 public String getSaslMechanism() 146 { 147 return saslMechanism; 148 } 149 150 151 public void setSaslMechanism( String saslMechanism ) 152 { 153 this.saslMechanism = saslMechanism; 154 } 155 156 157 /** 158 * @return The principal password 159 */ 160 public byte[] getCredentials() 161 { 162 return credentials; 163 } 164 165 166 public void setCredentials( byte[] credentials ) 167 { 168 this.credentials = credentials; 169 } 170 171 172 /** 173 * @return The SASL authentication ID 174 */ 175 public String getSaslAuthId() 176 { 177 return saslAuthId; 178 } 179 180 181 public void setSaslAuthId( String saslAuthId ) 182 { 183 this.saslAuthId = saslAuthId; 184 } 185 186 187 public boolean isSaslBind() 188 { 189 return saslMechanism != null; 190 } 191 192 193 /** 194 * @return the operation name 195 */ 196 public String getName() 197 { 198 return MessageTypeEnum.BIND_REQUEST.name(); 199 } 200 201 202 /** 203 * @see Object#toString() 204 */ 205 public String toString() 206 { 207 return "BindContext for DN '" + getDn().getName() + "', credentials <" + 208 ( credentials != null ? StringTools.dumpBytes( credentials ) : "" ) + ">" + 209 ( saslMechanism != null ? ", saslMechanism : <" + saslMechanism + ">" : "" ) + 210 ( saslAuthId != null ? ", saslAuthId <" + saslAuthId + ">" : "" ); 211 } 212 213 214 public CoreSession getSession() 215 { 216 return session; 217 } 218 219 220 public void setSession( CoreSession session ) 221 { 222 this.session = session; 223 } 224 225 226 /** 227 * Tells if the current operation is considered a side effect of the 228 * current context 229 */ 230 public boolean isCollateralOperation() 231 { 232 return collateralOperation; 233 } 234 235 236 public void setCollateralOperation( boolean collateralOperation ) 237 { 238 this.collateralOperation = collateralOperation; 239 } 240 241 242 /** 243 * @return The associated DN 244 */ 245 public DN getDn() 246 { 247 return dn; 248 } 249 250 251 /** 252 * Set the context DN 253 * 254 * @param dn The DN to set 255 */ 256 public void setDn( DN dn ) 257 { 258 this.dn = dn; 259 } 260 261 262 public void addRequestControl( Control requestControl ) 263 { 264 requestControls.put( requestControl.getOid(), requestControl ); 265 } 266 267 268 public Control getRequestControl( String numericOid ) 269 { 270 return requestControls.get( numericOid ); 271 } 272 273 274 public boolean hasRequestControl( String numericOid ) 275 { 276 return requestControls.containsKey( numericOid ); 277 } 278 279 280 public boolean hasRequestControls() 281 { 282 return ! requestControls.isEmpty(); 283 } 284 285 286 public void addResponseControl( Control responseControl ) 287 { 288 responseControls.put( responseControl.getOid(), responseControl ); 289 } 290 291 292 public Control getResponseControl( String numericOid ) 293 { 294 return responseControls.get( numericOid ); 295 } 296 297 298 public boolean hasResponseControl( String numericOid ) 299 { 300 return responseControls.containsKey( numericOid ); 301 } 302 303 304 public Control[] getResponseControls() 305 { 306 if ( responseControls.isEmpty() ) 307 { 308 return EMPTY_CONTROLS; 309 } 310 311 return responseControls.values().toArray( EMPTY_CONTROLS ); 312 } 313 314 315 public boolean hasResponseControls() 316 { 317 return ! responseControls.isEmpty(); 318 } 319 320 321 public int getResponseControlCount() 322 { 323 return responseControls.size(); 324 } 325 326 327 public void addRequestControls( Control[] requestControls ) 328 { 329 for ( Control c : requestControls ) 330 { 331 this.requestControls.put( c.getOid(), c ); 332 } 333 } 334 335 336 /** 337 * Gets the set of bypassed Interceptors. 338 * 339 * @return the set of bypassed Interceptors 340 */ 341 public Collection<String> getByPassed() 342 { 343 if ( bypassed == null ) 344 { 345 return Collections.emptyList(); 346 } 347 348 return Collections.unmodifiableCollection( bypassed ); 349 } 350 351 352 /** 353 * Sets the set of bypassed Interceptors. 354 * 355 * @param byPassed the set of bypassed Interceptors 356 */ 357 public void setByPassed( Collection<String> byPassed ) 358 { 359 this.bypassed = byPassed; 360 } 361 362 363 /** 364 * Checks to see if an Interceptor is bypassed for this operation. 365 * 366 * @param interceptorName the interceptorName of the Interceptor to check for bypass 367 * @return true if the Interceptor should be bypassed, false otherwise 368 */ 369 public boolean isBypassed( String interceptorName ) 370 { 371 return bypassed != null && bypassed.contains( interceptorName ); 372 } 373 374 375 /** 376 * Checks to see if any Interceptors are bypassed by this operation. 377 * 378 * @return true if at least one bypass exists 379 */ 380 public boolean hasBypass() 381 { 382 return bypassed != null && !bypassed.isEmpty(); 383 } 384 385 386 public LookupOperationContext newLookupContext( DN dn ) 387 { 388 return new LookupOperationContext( session, dn ); 389 } 390 391 392 public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception 393 { 394 return session.getDirectoryService().getOperationManager().lookup( opContext ); 395 } 396 397 398 public ClonedServerEntry lookup( DN dn, Collection<String> byPassed ) throws Exception 399 { 400 LookupOperationContext opContext = newLookupContext( dn ); 401 opContext.setByPassed( byPassed ); 402 return session.getDirectoryService().getOperationManager().lookup( opContext ); 403 } 404 405 406 public LdapPrincipal getEffectivePrincipal() 407 { 408 if ( authorizedPrincipal != null ) 409 { 410 return authorizedPrincipal; 411 } 412 413 return session.getEffectivePrincipal(); 414 } 415 416 417 // ----------------------------------------------------------------------- 418 // OperationContext Linked List Methods 419 // ----------------------------------------------------------------------- 420 421 422 public boolean isFirstOperation() 423 { 424 return previous == null; 425 } 426 427 428 public OperationContext getFirstOperation() 429 { 430 if ( previous == null ) 431 { 432 return this; 433 } 434 435 return previous.getFirstOperation(); 436 } 437 438 439 public OperationContext getLastOperation() 440 { 441 if ( next == null ) 442 { 443 return this; 444 } 445 446 return next.getLastOperation(); 447 } 448 449 450 public OperationContext getNextOperation() 451 { 452 return next; 453 } 454 455 456 public OperationContext getPreviousOperation() 457 { 458 return previous; 459 } 460 461 462 public void add( ServerEntry entry, Collection<String> bypass ) throws Exception 463 { 464 throw new NotImplementedException(); 465 } 466 467 468 public void delete( DN dn, Collection<String> bypass ) throws Exception 469 { 470 throw new NotImplementedException(); 471 } 472 473 474 public void modify( DN dn, List<Modification> mods, Collection<String> bypass ) throws Exception 475 { 476 throw new NotImplementedException(); 477 } 478 479 480 private void setup( AbstractOperationContext opContext ) 481 { 482 opContext.setPreviousOperation( this ); 483 next = opContext; 484 opContext.setByPassed( opContext.getByPassed() ); 485 opContext.setAuthorizedPrincipal( authorizedPrincipal ); 486 } 487 488 489 public boolean hasEntry( DN dn, Collection<String> byPassed ) throws Exception 490 { 491 EntryOperationContext opContext = new EntryOperationContext( session, dn ); 492 setup( opContext ); 493 opContext.setByPassed( byPassed ); 494 return session.getDirectoryService().getOperationManager().hasEntry( opContext ); 495 } 496 497 498 public ReferralHandlingMode getReferralHandlingMode() 499 { 500 return referralHandlingMode; 501 } 502 503 504 public void setReferralHandlingMode( ReferralHandlingMode referralHandlingMode ) 505 { 506 this.referralHandlingMode = referralHandlingMode; 507 } 508 509 510 public ClonedServerEntry getEntry() 511 { 512 return entry; 513 } 514 515 516 public void setEntry( ClonedServerEntry entry ) 517 { 518 this.entry = entry; 519 } 520 521 522 /** 523 * {@inheritDoc} 524 */ 525 public void throwReferral() 526 { 527 throw new NotImplementedException( I18n.err( I18n.ERR_320 ) ); 528 } 529 530 531 /** 532 * {@inheritDoc} 533 */ 534 public boolean isReferralThrown() 535 { 536 throw new NotImplementedException( I18n.err( I18n.ERR_321 ) ); 537 } 538 539 540 /** 541 * {@inheritDoc} 542 */ 543 public void ignoreReferral() 544 { 545 throw new NotImplementedException( I18n.err( I18n.ERR_322 ) ); 546 } 547 548 549 /** 550 * {@inheritDoc} 551 */ 552 public boolean isReferralIgnored() 553 { 554 throw new NotImplementedException( I18n.err( I18n.ERR_323 ) ); 555 } 556 }