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;
021
022
023 import java.io.Externalizable;
024 import java.io.IOException;
025 import java.io.ObjectInput;
026 import java.io.ObjectOutput;
027 import java.security.Principal;
028
029 import org.apache.directory.server.i18n.I18n;
030 import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
031 import org.apache.directory.shared.ldap.name.DN;
032 import org.apache.directory.shared.ldap.util.StringTools;
033
034
035 /**
036 * An alternative X500 user implementation that has access to the distinguished
037 * name of the principal as well as the String representation.
038 *
039 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
040 * @version $Rev: 918766 $
041 */
042 public final class LdapPrincipal implements Principal, Cloneable, Externalizable
043 {
044 private static final long serialVersionUID = 3906650782395676720L;
045
046 /** the normalized distinguished name of the principal */
047 private DN name;
048
049 /** the no name anonymous user whose DN is the empty String */
050 public static final LdapPrincipal ANONYMOUS = new LdapPrincipal();
051
052 /** the authentication level for this principal */
053 private AuthenticationLevel authenticationLevel;
054
055 /** The userPassword
056 * @todo security risk remove this immediately
057 * The field is transient to avoid being serialized
058 */
059 transient private byte[] userPassword;
060
061
062 /**
063 * Creates a new LDAP/X500 principal without any group associations. Keep
064 * this package friendly so only code in the package can create a
065 * trusted principal.
066 *
067 * @param name the normalized distinguished name of the principal
068 * @param authenticationLevel the authentication level for this principal
069 */
070 public LdapPrincipal( DN name, AuthenticationLevel authenticationLevel )
071 {
072 this.name = name;
073
074 if ( ! name.isNormalized() )
075 {
076 throw new IllegalStateException( I18n.err( I18n.ERR_436 ) );
077 }
078
079 this.authenticationLevel = authenticationLevel;
080 this.userPassword = null;
081 }
082
083 /**
084 * Creates a new LDAP/X500 principal without any group associations. Keep
085 * this package friendly so only code in the package can create a
086 * trusted principal.
087 *
088 * @param name the normalized distinguished name of the principal
089 * @param authenticationLevel the authentication level for this principal
090 * @param userPassword The user password
091 */
092 public LdapPrincipal( DN name, AuthenticationLevel authenticationLevel, byte[] userPassword )
093 {
094 this.name = name;
095 this.authenticationLevel = authenticationLevel;
096 this.userPassword = new byte[ userPassword.length ];
097 System.arraycopy( userPassword, 0, this.userPassword, 0, userPassword.length );
098 }
099
100
101 /**
102 * Creates a principal for the no name anonymous user whose DN is the empty
103 * String.
104 */
105 public LdapPrincipal()
106 {
107 name = new DN();
108 authenticationLevel = AuthenticationLevel.NONE;
109 userPassword = null;
110 }
111
112
113 /**
114 * Gets a cloned copy of the normalized distinguished name of this
115 * principal as a {@link DN}.
116 *
117 * @return the cloned distinguished name of the principal as a {@link DN}
118 */
119 public DN getClonedName()
120 {
121 return ( DN ) name.clone();
122 }
123
124
125 /**
126 * Returns the normalized distinguished name of the principal as a String.
127 */
128 public String getName()
129 {
130 return name.getNormName();
131 }
132
133
134 /**
135 * Gets the authentication level associated with this LDAP principle.
136 *
137 * @return the authentication level
138 */
139 public AuthenticationLevel getAuthenticationLevel()
140 {
141 return authenticationLevel;
142 }
143
144
145 /**
146 * Returns string representation of the normalized distinguished name
147 * of this principal.
148 */
149 public String toString()
150 {
151 return "['" + name.getName() + "', '" + StringTools.utf8ToString( userPassword ) +"']'";
152 }
153
154
155 public byte[] getUserPassword()
156 {
157 return userPassword;
158 }
159
160
161 public void setUserPassword( byte[] userPassword )
162 {
163 this.userPassword = new byte[ userPassword.length ];
164 System.arraycopy( userPassword, 0, this.userPassword, 0, userPassword.length );
165 }
166
167
168 /**
169 * Clone the object. This is done so that we don't store the
170 * password in a LdapPrincipal more than necessary.
171 */
172 public Object clone() throws CloneNotSupportedException
173 {
174 LdapPrincipal clone = (LdapPrincipal)super.clone();
175
176 if ( userPassword != null )
177 {
178 clone.setUserPassword( userPassword );
179 }
180
181 return clone;
182 }
183
184
185 /**
186 * @see Externalizable#readExternal(ObjectInput)
187 *
188 * @param in The stream from which the LdapPrincipal is read
189 * @throws IOException If the stream can't be read
190 * @throws ClassNotFoundException If the LdapPrincipal can't be created
191 */
192 public void readExternal( ObjectInput in ) throws IOException , ClassNotFoundException
193 {
194 // Read the name
195 name = (DN)in.readObject();
196
197 // read the authentication level
198 int level = in.readInt();
199
200 authenticationLevel = AuthenticationLevel.getLevel( level );
201 }
202
203
204 /**
205 * @see Externalizable#readExternal(ObjectInput)<p>
206 *
207 *@param out The stream in which the LdapPrincipal will be serialized.
208 *The password won't be written !
209 *
210 *@throws IOException If the serialization fail
211 */
212 public void writeExternal( ObjectOutput out ) throws IOException
213 {
214 // Write the name
215 if ( name == null )
216 {
217 out.writeObject( DN.EMPTY_DN );
218 }
219 else
220 {
221 out.writeObject( name );
222 }
223
224 // write the authentication level
225 if ( authenticationLevel == null )
226 {
227 out.writeInt( AuthenticationLevel.NONE.getLevel() );
228 }
229 else
230 {
231 out.writeInt( authenticationLevel.getLevel() );
232 }
233
234 // and flush the result
235 //out.flush();
236 }
237 }