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 }