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 }