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 }