View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.core.authn;
21  
22  
23  import java.io.Externalizable;
24  import java.io.IOException;
25  import java.io.ObjectInput;
26  import java.io.ObjectOutput;
27  import java.security.Principal;
28  
29  import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
30  import org.apache.directory.shared.ldap.name.LdapDN;
31  import org.apache.directory.shared.ldap.util.StringTools;
32  
33  
34  /**
35   * An alternative X500 user implementation that has access to the distinguished
36   * name of the principal as well as the String representation.
37   *
38   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
39   * @version $Rev: 686316 $
40   */
41  public final class LdapPrincipal implements Principal, Cloneable, Externalizable
42  {
43      private static final long serialVersionUID = 3906650782395676720L;
44  
45      /** the normalized distinguished name of the principal */
46      private LdapDN name;
47  
48      /** the no name anonymous user whose DN is the empty String */
49      public static final LdapPrincipal ANONYMOUS = new LdapPrincipal();
50  
51      /** the authentication level for this principal */
52      private AuthenticationLevel authenticationLevel;
53      
54      /** The userPassword
55       * @todo security risk remove this immediately
56       * The field is transient to avoid being serialized
57       */
58      transient private byte[] userPassword;
59  
60  
61      /**
62       * Creates a new LDAP/X500 principal without any group associations.  Keep
63       * this package friendly so only code in the package can create a
64       * trusted principal.
65       *
66       * @param name the normalized distinguished name of the principal
67       * @param authenticationLevel the authentication level for this principal
68       */
69      public LdapPrincipal( LdapDN name, AuthenticationLevel authenticationLevel )
70      {
71          this.name = name;
72          
73          if ( ! name.isNormalized() )
74          {
75              throw new IllegalStateException( "Names used for principals must be normalized!" );
76          }
77          
78          this.authenticationLevel = authenticationLevel;
79          this.userPassword = null;
80      }
81  
82      /**
83       * Creates a new LDAP/X500 principal without any group associations.  Keep
84       * this package friendly so only code in the package can create a
85       * trusted principal.
86       *
87       * @param name the normalized distinguished name of the principal
88       * @param authenticationLevel the authentication level for this principal
89       * @param userPassword The user password
90       */
91      public LdapPrincipal( LdapDN name, AuthenticationLevel authenticationLevel, byte[] userPassword )
92      {
93          this.name = name;
94          this.authenticationLevel = authenticationLevel;
95          this.userPassword = new byte[ userPassword.length ];
96          System.arraycopy( userPassword, 0, this.userPassword, 0, userPassword.length );
97      }
98  
99  
100     /**
101      * Creates a principal for the no name anonymous user whose DN is the empty
102      * String.
103      */
104     public LdapPrincipal()
105     {
106         name = new LdapDN();
107         authenticationLevel = AuthenticationLevel.NONE;
108         userPassword = null;
109     }
110 
111 
112     /**
113      * Gets a cloned copy of the normalized distinguished name of this
114      * principal as a JNDI {@link LdapDN}.
115      *
116      * @return the normalized distinguished name of the principal as a JNDI {@link LdapDN}
117      */
118     public LdapDN getJndiName()
119     {
120         return ( LdapDN ) name.clone();
121     }
122 
123 
124     /**
125      * Returns the normalized distinguished name of the principal as a String.
126      */
127     public String getName()
128     {
129         return name.getNormName();
130     }
131 
132 
133     /**
134      * Gets the authentication level associated with this LDAP principle.
135      *
136      * @return the authentication level
137      */
138     public AuthenticationLevel getAuthenticationLevel()
139     {
140         return authenticationLevel;
141     }
142 
143 
144     /**
145      * Returns string representation of the normalized distinguished name
146      * of this principal.
147      */
148     public String toString()
149     {
150         return "['" + name.getUpName() + "', '" + StringTools.utf8ToString( userPassword ) +"']'";
151     }
152 
153 
154     public byte[] getUserPassword()
155     {
156         return userPassword;
157     }
158 
159 
160     public void setUserPassword( byte[] userPassword )
161     {
162         this.userPassword = new byte[ userPassword.length ];
163         System.arraycopy( userPassword, 0, this.userPassword, 0, userPassword.length );
164     }
165     
166     
167     /**
168      * Clone the object. This is done so that we don't store the 
169      * password in a LdapPrincipal more than necessary.
170      */
171     public Object clone() throws CloneNotSupportedException
172     {
173         LdapPrincipal clone = (LdapPrincipal)super.clone();
174         
175         if ( userPassword != null )
176         {
177             clone.setUserPassword( userPassword );
178         }
179         
180         return clone;
181     }
182     
183     
184     /**
185      * @see Externalizable#readExternal(ObjectInput)
186      * 
187      * @param in The stream from which the LdapPrincipal is read
188      * @throws IOException If the stream can't be read
189      * @throws ClassNotFoundException If the LdapPrincipal can't be created 
190      */
191     public void readExternal( ObjectInput in ) throws IOException , ClassNotFoundException
192     {
193         // Read the name
194         name = (LdapDN)in.readObject();
195         
196         // read the authentication level
197         int level = in.readInt();
198         
199         authenticationLevel = AuthenticationLevel.getLevel( level );
200     }
201 
202 
203     /**
204      * @see Externalizable#readExternal(ObjectInput)<p>
205      *
206      *@param out The stream in which the LdapPrincipal will be serialized. 
207      *The password won't be written !
208      *
209      *@throws IOException If the serialization fail
210      */
211     public void writeExternal( ObjectOutput out ) throws IOException
212     {
213         // Write the name
214         if ( name == null )
215         {
216             out.writeObject( LdapDN.EMPTY_LDAPDN );
217         }
218         else
219         {
220             out.writeObject( name );
221         }
222         
223         // write the authentication level
224         if ( authenticationLevel == null )
225         {
226             out.writeInt( AuthenticationLevel.NONE.getLevel() );
227         }
228         else
229         {
230             out.writeInt( authenticationLevel.getLevel() );
231         }
232         
233         // and flush the result
234         //out.flush();
235     }
236 }