001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.types;
028    
029    
030    
031    import java.util.Collection;
032    import java.util.HashSet;
033    import java.util.Iterator;
034    import java.util.Set;
035    
036    import static org.opends.server.util.Validator.*;
037    
038    
039    
040    /**
041     * This class defines a data structure that may be used to store
042     * information about an authenticated user.  Note that structures in
043     * this class allow for multiple authentication types for the same
044     * user, which is not currently supported by LDAP but may be offered
045     * through some type of extension.
046     */
047    @org.opends.server.types.PublicAPI(
048         stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
049         mayInstantiate=true,
050         mayExtend=false,
051         mayInvoke=true)
052    public final class AuthenticationInfo
053    {
054      // The password used to authenticate using simple authentication.
055      private ByteString simplePassword;
056    
057      // Indicates whether this connection is currently authenticated.
058      private boolean isAuthenticated;
059    
060      // Indicates whether this connection is authenticated as a root
061      // user.
062      private boolean isRoot;
063    
064      // Indicates whether the user's password must be changed before any
065      // other operation will be allowed.
066      private boolean mustChangePassword;
067    
068      // The entry of the user that is currently authenticated.
069      private Entry authenticationEntry;
070    
071      // The entry of the user that will be used as the default
072      // authorization identity.
073      private Entry authorizationEntry;
074    
075      // The type of authentication performed on this connection.
076      private Set<AuthenticationType> authenticationTypes;
077    
078      // The SASL mechanism used to authenticate.
079      private Set<String> saslMechanisms;
080    
081    
082    
083      /**
084       * Creates a new set of authentication information to be used for
085       * unauthenticated clients.
086       */
087      public AuthenticationInfo()
088      {
089        isAuthenticated     = false;
090        isRoot              = false;
091        mustChangePassword  = false;
092        simplePassword      = null;
093        authenticationTypes = new HashSet<AuthenticationType>(0);
094        authenticationEntry = null;
095        authorizationEntry  = null;
096        saslMechanisms      = new HashSet<String>(0);
097      }
098    
099    
100    
101      /**
102       * Creates a new set of authentication information to be used for
103       * clients that are authenticated internally.
104       *
105       * @param  authenticationEntry  The entry of the user that has
106       *                              authenticated, or {@code null} to
107       *                              indicate an unauthenticated user.
108       * @param  isRoot               Indicates whether the authenticated
109       *                              user is a root user.
110       */
111      public AuthenticationInfo(Entry authenticationEntry, boolean isRoot)
112      {
113        this.authenticationEntry = authenticationEntry;
114        this.isRoot              = isRoot;
115    
116        isAuthenticated     = (authenticationEntry != null);
117        mustChangePassword  = false;
118        simplePassword      = null;
119        authorizationEntry  = authenticationEntry;
120        saslMechanisms      = new HashSet<String>(0);
121        authenticationTypes = new HashSet<AuthenticationType>(1);
122    
123        authenticationTypes.add(AuthenticationType.INTERNAL);
124      }
125    
126    
127    
128      /**
129       * Creates a new set of authentication information to be used for
130       * clients that have successfully performed simple authentication.
131       *
132       * @param  authenticationEntry  The entry of the user that has
133       *                              authenticated.  It must not be
134       *                              {@code null}.
135       * @param  simplePassword       The password that was used to
136       *                              perform the simple authentication.
137       *                              It must not be {@code null}.
138       * @param  isRoot               Indicates whether the authenticated
139       *                              user is a root user.
140       */
141      public AuthenticationInfo(Entry authenticationEntry,
142                                ByteString simplePassword, boolean isRoot)
143      {
144        ensureNotNull(authenticationEntry, simplePassword);
145    
146        this.authenticationEntry = authenticationEntry;
147        this.simplePassword      = simplePassword;
148        this.isRoot              = isRoot;
149    
150        isAuthenticated     = true;
151        mustChangePassword  = false;
152        authorizationEntry  = authenticationEntry;
153        saslMechanisms      = new HashSet<String>(0);
154        authenticationTypes = new HashSet<AuthenticationType>(1);
155    
156        authenticationTypes.add(AuthenticationType.SIMPLE);
157      }
158    
159    
160    
161      /**
162       * Creates a new set of authentication information to be used for
163       * clients that have authenticated using a SASL mechanism.
164       *
165       * @param  authenticationEntry  The entry of the user that has
166       *                              authenticated.  It must not be
167       *                              {@code null}.
168       * @param  saslMechanism        The SASL mechanism used to
169       *                              authenticate.  This must be provided
170       *                              in all-uppercase characters and must
171       *                              not be {@code null}.
172       * @param  isRoot               Indicates whether the authenticated
173       *                              user is a root user.
174       */
175      public AuthenticationInfo(Entry authenticationEntry,
176                                String saslMechanism, boolean isRoot)
177      {
178        ensureNotNull(authenticationEntry, saslMechanism);
179    
180        this.authenticationEntry = authenticationEntry;
181        this.isRoot              = isRoot;
182    
183        isAuthenticated    = true;
184        mustChangePassword = false;
185        authorizationEntry = authenticationEntry;
186        simplePassword     = null;
187    
188        authenticationTypes = new HashSet<AuthenticationType>(1);
189        authenticationTypes.add(AuthenticationType.SASL);
190    
191        saslMechanisms = new HashSet<String>(1);
192        saslMechanisms.add(saslMechanism);
193      }
194    
195    
196    
197      /**
198       * Creates a new set of authentication information to be used for
199       * clients that have authenticated using a SASL mechanism.
200       *
201       * @param  authenticationEntry  The entry of the user that has
202       *                              authenticated.  It must not be
203       *                              {@code null}.
204       * @param  authorizationEntry   The entry of the user that will be
205       *                              used as the default authorization
206       *                              identity, or {@code null} to
207       *                              indicate that the authorization
208       *                              identity should be the
209       *                              unauthenticated user.
210       * @param  saslMechanism        The SASL mechanism used to
211       *                              authenticate.  This must be provided
212       *                              in all-uppercase characters and must
213       *                              not be {@code null}.
214       * @param  isRoot               Indicates whether the authenticated
215       *                              user is a root user.
216       */
217      public AuthenticationInfo(Entry authenticationEntry,
218                                Entry authorizationEntry,
219                                String saslMechanism, boolean isRoot)
220      {
221        ensureNotNull(authenticationEntry, saslMechanism);
222    
223        this.authenticationEntry = authenticationEntry;
224        this.authorizationEntry  = authorizationEntry;
225        this.isRoot              = isRoot;
226    
227        isAuthenticated    = true;
228        mustChangePassword = false;
229        simplePassword     = null;
230    
231        authenticationTypes = new HashSet<AuthenticationType>(1);
232        authenticationTypes.add(AuthenticationType.SASL);
233    
234        saslMechanisms = new HashSet<String>(1);
235        saslMechanisms.add(saslMechanism);
236      }
237    
238    
239    
240      /**
241       * Indicates whether this client has successfully authenticated to
242       * the server.
243       *
244       * @return  {@code true} if this client has successfully
245       *          authenticated to the server, or {@code false} if not.
246       */
247      public boolean isAuthenticated()
248      {
249        return isAuthenticated;
250      }
251    
252    
253    
254      /**
255       * Sets this authentication info structure to reflect that the
256       * client is not authenticated.
257       */
258      public void setUnauthenticated()
259      {
260        isAuthenticated     = false;
261        isRoot              = false;
262        mustChangePassword  = false;
263        simplePassword      = null;
264        authenticationEntry = null;
265        authorizationEntry  = null;
266    
267        authenticationTypes.clear();
268        saslMechanisms.clear();
269      }
270    
271    
272    
273      /**
274       * Indicates whether this client should be considered a root user.
275       *
276       * @return  {@code true} if this client should be considered a root
277       *          user, or {@code false} if not.
278       */
279      public boolean isRoot()
280      {
281        return isRoot;
282      }
283    
284    
285    
286      /**
287       * Indicates whether the authenticated user must change his/her
288       * password before any other operation will be allowed.
289       *
290       * @return  {@code true} if the user must change his/her password
291       *          before any other operation will be allowed, or
292       *          {@code false} if not.
293       */
294      public boolean mustChangePassword()
295      {
296        return mustChangePassword;
297      }
298    
299    
300    
301      /**
302       * Specifies whether the authenticated user must change his/her
303       * password before any other operation will be allowed.
304       *
305       * @param  mustChangePassword  Specifies whether the authenticated
306       *                             user must change his/her password
307       *                             before any other operation will be
308       *                             allowed.
309       */
310      public void setMustChangePassword(boolean mustChangePassword)
311      {
312        this.mustChangePassword = mustChangePassword;
313      }
314    
315    
316    
317      /**
318       * Indicates whether this client has authenticated using the
319       * specified authentication type.
320       *
321       * @param  authenticationType  The authentication type for which to
322       *                             make the determination.
323       *
324       * @return  {@code true} if the client has authenticated using the
325       *          specified authentication type, or {@code false} if not.
326       */
327      public boolean hasAuthenticationType(AuthenticationType
328                                                authenticationType)
329      {
330        return authenticationTypes.contains(authenticationType);
331      }
332    
333    
334    
335      /**
336       * Indicates whether this client has authenticated using any of the
337       * authentication types in the given collection.
338       *
339       * @param  types  The collection of authentication types for which
340       *                to make the determination.
341       *
342       * @return  {@code true} if the client has authenticated using any
343       *          of the specified authentication types, or {@code false}
344       *          if not.
345       */
346      public boolean hasAnyAuthenticationType(
347                          Collection<AuthenticationType> types)
348      {
349        for (AuthenticationType t : types)
350        {
351          if (authenticationTypes.contains(t))
352          {
353            return true;
354          }
355        }
356    
357        return false;
358      }
359    
360    
361    
362      /**
363       * Retrieves the set of authentication types performed by the
364       * client.
365       *
366       * @return  The set of authentication types performed by the client.
367       */
368      public Set<AuthenticationType> getAuthenticationTypes()
369      {
370        return authenticationTypes;
371      }
372    
373    
374    
375      /**
376       * Adds the provided authentication type to the set of
377       * authentication types completed by the client.  This should only
378       * be used in conjunction with multi-factor or step-up
379       * authentication mechanisms.
380       *
381       * @param  authenticationType  The authentication type to add for
382       *                             this client.
383       */
384      public void addAuthenticationType(AuthenticationType
385                                             authenticationType)
386      {
387        authenticationTypes.add(authenticationType);
388      }
389    
390    
391    
392      /**
393       * Retrieves the entry for the user as whom the client is
394       * authenticated.
395       *
396       * @return  The entry for the user as whom the client is
397       *          authenticated, or {@code null} if the client is
398       *          unauthenticated.
399       */
400      public Entry getAuthenticationEntry()
401      {
402        return authenticationEntry;
403      }
404    
405    
406    
407      /**
408       * Retrieves the DN of the user as whom the client is authenticated.
409       *
410       * @return  The DN of the user as whom the client is authenticated,
411       *          or {@code null} if the client is unauthenticated.
412       */
413      public DN getAuthenticationDN()
414      {
415        if (authenticationEntry == null)
416        {
417          return null;
418        }
419        else
420        {
421          return authenticationEntry.getDN();
422        }
423      }
424    
425    
426    
427      /**
428       * Retrieves the entry for the user that should be used as the
429       * default authorization identity.
430       *
431       * @return  The entry for the user that should be used as the
432       *          default authorization identity, or {@code null} if the
433       *          authorization identity should be the unauthenticated
434       *          user.
435       */
436      public Entry getAuthorizationEntry()
437      {
438        return authorizationEntry;
439      }
440    
441    
442    
443      /**
444       * Retrieves the DN for the user that should be used as the default
445       * authorization identity.
446       *
447       * @return  The DN for the user that should be used as the default
448       *          authorization identity, or {@code null} if the
449       *          authorization identity should be the unauthenticated
450       *          user.
451       */
452      public DN getAuthorizationDN()
453      {
454        if (authorizationEntry == null)
455        {
456          return null;
457        }
458        else
459        {
460          return authorizationEntry.getDN();
461        }
462      }
463    
464    
465    
466      /**
467       * Retrieves the password that the client used for simple
468       * authentication.
469       *
470       * @return  The password that the client used for simple
471       *          authentication, or {@code null} if the client is not
472       *          authenticated using simple authentication.
473       */
474      public ByteString getSimplePassword()
475      {
476        return simplePassword;
477      }
478    
479    
480    
481      /**
482       * Indicates whether the client is currently authenticated using the
483       * specified SASL mechanism.
484       *
485       * @param  saslMechanism  The SASL mechanism for which to make the
486       *                        determination.  Note that this must be
487       *                        provided in all uppercase characters.
488       *
489       * @return  {@code true} if the client is authenticated using the
490       *          specified SASL mechanism, or {@code false} if not.
491       */
492      public boolean hasSASLMechanism(String saslMechanism)
493      {
494        return saslMechanisms.contains(saslMechanism);
495      }
496    
497    
498    
499      /**
500       * Indicates whether this client has authenticated using any of the
501       * SASL mechanisms in the given collection.
502       *
503       * @param  mechanisms  The collection of SASL mechanisms for which
504       *                     to make the determination.
505       *
506       * @return  {@code true} if the client has authenticated using any
507       *          of the provided SASL mechanisms, or {@code false} if
508       *          not.
509       */
510      public boolean hasAnySASLMechanism(Collection<String> mechanisms)
511      {
512        for (String s : mechanisms)
513        {
514          if (saslMechanisms.contains(s))
515          {
516            return true;
517          }
518        }
519    
520        return false;
521      }
522    
523    
524    
525      /**
526       * Retrieves the set of mechanisms that the client used for SASL
527       * authentication.
528       *
529       * @return  The set of mechanisms that the client used for SASL
530       *          authentication, or an empty set if SASL mechanism has
531       *          not been used.
532       */
533      public Set<String> getSASLMechanisms()
534      {
535        return saslMechanisms;
536      }
537    
538    
539    
540      /**
541       * Adds the provided mechanism to the set of SASL mechanisms used by
542       * the client.  This should only be used in conjunction with
543       * multi-factor or step-up authentication mechanisms.
544       *
545       * @param  saslMechanism  The SASL mechanism to add to set of
546       *                        mechanisms for this client.  Note that
547       *                        this must be provided in all uppercase
548       *                        characters.
549       */
550      public void addSASLMechanism(String saslMechanism)
551      {
552        saslMechanisms.add(saslMechanism);
553      }
554    
555    
556    
557      /**
558       * Retrieves a string representation of this authentication info
559       * structure.
560       *
561       * @return  A string representation of this authentication info
562       *          structure.
563       */
564      public String toString()
565      {
566        StringBuilder buffer = new StringBuilder();
567        toString(buffer);
568    
569        return buffer.toString();
570      }
571    
572    
573    
574      /**
575       * Appends a string representation of this authentication info
576       * structure to the provided buffer.
577       *
578       * @param  buffer  The buffer to which the information is to be
579       *                 appended.
580       */
581      public void toString(StringBuilder buffer)
582      {
583        buffer.append("AuthenticationInfo(isAuthenticated=");
584        buffer.append(isAuthenticated);
585        buffer.append(",isRoot=");
586        buffer.append(isRoot);
587        buffer.append(",mustChangePassword=");
588        buffer.append(mustChangePassword);
589        buffer.append(",authenticationDN=\"");
590    
591        if (authenticationEntry != null)
592        {
593          authenticationEntry.getDN().toString(buffer);
594        }
595    
596        if (authorizationEntry == null)
597        {
598          buffer.append("\",authorizationDN=\"\"");
599        }
600        else
601        {
602          buffer.append("\",authorizationDN=\"");
603          authorizationEntry.getDN().toString(buffer);
604          buffer.append("\"");
605        }
606    
607        if (! authenticationTypes.isEmpty())
608        {
609          Iterator<AuthenticationType> iterator =
610               authenticationTypes.iterator();
611          AuthenticationType authType = iterator.next();
612    
613          if (iterator.hasNext())
614          {
615            buffer.append(",authTypes={");
616            buffer.append(authType);
617    
618            while (iterator.hasNext())
619            {
620              buffer.append(",");
621              buffer.append(iterator.next());
622            }
623    
624            buffer.append("}");
625          }
626          else
627          {
628            buffer.append(",authType=");
629            buffer.append(authType);
630          }
631        }
632    
633        if (! saslMechanisms.isEmpty())
634        {
635          Iterator<String> iterator = saslMechanisms.iterator();
636          String mech = iterator.next();
637    
638          if (iterator.hasNext())
639          {
640            buffer.append(",saslMechanisms={");
641            buffer.append(mech);
642    
643            while (iterator.hasNext())
644            {
645              buffer.append(",");
646              buffer.append(iterator.next());
647            }
648    
649            buffer.append("}");
650          }
651          else
652          {
653            buffer.append(",saslMechanism=");
654            buffer.append(mech);
655          }
656        }
657    
658        buffer.append(")");
659      }
660    
661    
662    
663      /**
664       * Creates a duplicate of this {@code AuthenticationInfo} object
665       * with the new authentication and authorization entries.
666       *
667       * @param  newAuthenticationEntry  The updated entry for the user
668       *                                 as whom the associated client
669       *                                 connection is authenticated.
670       * @param  newAuthorizationEntry   The updated entry for the default
671       *                                 authorization identity for the
672       *                                 associated client connection.
673       *
674       * @return  The duplicate of this {@code AuthenticationInfo} object
675       *          with the specified authentication and authorization
676       *          entries.
677       */
678      public AuthenticationInfo duplicate(Entry newAuthenticationEntry,
679                                          Entry newAuthorizationEntry)
680      {
681        AuthenticationInfo authInfo = new AuthenticationInfo();
682    
683        authInfo.simplePassword      = simplePassword;
684        authInfo.isAuthenticated     = isAuthenticated;
685        authInfo.isRoot              = isRoot;
686        authInfo.mustChangePassword  = mustChangePassword;
687        authInfo.authenticationEntry = newAuthenticationEntry;
688        authInfo.authorizationEntry  = newAuthorizationEntry;
689    
690        authInfo.authenticationTypes.addAll(authenticationTypes);
691        authInfo.saslMechanisms.addAll(saslMechanisms);
692    
693        return authInfo;
694      }
695    }
696