001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.server.controls; 018 019import java.io.IOException; 020import org.forgerock.i18n.LocalizableMessage; 021import org.opends.server.api.AuthenticationPolicyState; 022import org.opends.server.core.DirectoryServer; 023import org.opends.server.core.PasswordPolicyState; 024import org.forgerock.i18n.slf4j.LocalizedLogger; 025import org.forgerock.opendj.io.ASN1; 026import org.forgerock.opendj.io.ASN1Reader; 027import org.forgerock.opendj.io.ASN1Writer; 028import org.opends.server.types.*; 029import org.forgerock.opendj.ldap.DN; 030import org.forgerock.opendj.ldap.ResultCode; 031import org.forgerock.opendj.ldap.ByteString; 032import static org.opends.messages.ProtocolMessages.*; 033import static org.opends.server.util.ServerConstants.*; 034import static org.opends.server.util.StaticUtils.*; 035 036/** 037 * This class implements version 1 of the proxied authorization control as 038 * defined in early versions of draft-weltman-ldapv3-proxy (this implementation 039 * is based on the "-04" revision). It makes it possible for one user to 040 * request that an operation be performed under the authorization of another. 041 * The target user is specified as a DN in the control value, which 042 * distinguishes it from later versions of the control (which used a different 043 * OID) in which the target user was specified using an authorization ID. 044 */ 045public class ProxiedAuthV1Control 046 extends Control 047{ 048 /** 049 * ControlDecoder implementation to decode this control from a ByteString. 050 */ 051 private static final class Decoder 052 implements ControlDecoder<ProxiedAuthV1Control> 053 { 054 /** {@inheritDoc} */ 055 @Override 056 public ProxiedAuthV1Control decode(boolean isCritical, ByteString value) 057 throws DirectoryException 058 { 059 if (!isCritical) 060 { 061 LocalizableMessage message = ERR_PROXYAUTH1_CONTROL_NOT_CRITICAL.get(); 062 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 063 } 064 065 if (value == null) 066 { 067 LocalizableMessage message = ERR_PROXYAUTH1_NO_CONTROL_VALUE.get(); 068 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 069 } 070 071 ASN1Reader reader = ASN1.getReader(value); 072 DN authorizationDN; 073 try 074 { 075 reader.readStartSequence(); 076 authorizationDN = DN.valueOf(reader.readOctetString()); 077 reader.readEndSequence(); 078 } 079 catch (Exception e) 080 { 081 logger.traceException(e); 082 083 LocalizableMessage message = 084 ERR_PROXYAUTH1_CANNOT_DECODE_VALUE.get(getExceptionMessage(e)); 085 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 086 } 087 088 return new ProxiedAuthV1Control(isCritical, authorizationDN); 089 } 090 091 @Override 092 public String getOID() 093 { 094 return OID_PROXIED_AUTH_V1; 095 } 096 097 } 098 099 /** 100 * The Control Decoder that can be used to decode this control. 101 */ 102 public static final ControlDecoder<ProxiedAuthV1Control> DECODER = 103 new Decoder(); 104 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 105 106 107 108 109 /** The raw, unprocessed authorization DN from the control value. */ 110 private ByteString rawAuthorizationDN; 111 112 /** The processed authorization DN from the control value. */ 113 private DN authorizationDN; 114 115 116 117 /** 118 * Creates a new instance of the proxied authorization v1 control with the 119 * provided information. 120 * 121 * @param rawAuthorizationDN The raw, unprocessed authorization DN from the 122 * control value. It must not be {@code null}. 123 */ 124 public ProxiedAuthV1Control(ByteString rawAuthorizationDN) 125 { 126 this(true, rawAuthorizationDN); 127 } 128 129 130 131 /** 132 * Creates a new instance of the proxied authorization v1 control with the 133 * provided information. 134 * 135 * @param authorizationDN The authorization DN from the control value. It 136 * must not be {@code null}. 137 */ 138 public ProxiedAuthV1Control(DN authorizationDN) 139 { 140 this(true, authorizationDN); 141 } 142 143 144 145 /** 146 * Creates a new instance of the proxied authorization v1 control with the 147 * provided information. 148 * 149 * @param isCritical Indicates whether support for this control 150 * should be considered a critical part of the 151 * server processing. 152 * @param rawAuthorizationDN The raw, unprocessed authorization DN from the 153 * control value. 154 */ 155 public ProxiedAuthV1Control(boolean isCritical, ByteString rawAuthorizationDN) 156 { 157 super(OID_PROXIED_AUTH_V1, isCritical); 158 159 160 this.rawAuthorizationDN = rawAuthorizationDN; 161 162 authorizationDN = null; 163 } 164 165 166 167 /** 168 * Creates a new instance of the proxied authorization v1 control with the 169 * provided information. 170 * 171 * @param isCritical Indicates whether support for this control 172 * should be considered a critical part of the 173 * server processing. 174 * @param authorizationDN The authorization DN from the control value. 175 * It must not be {@code null}. 176 */ 177 public ProxiedAuthV1Control(boolean isCritical, DN authorizationDN) 178 { 179 super(OID_PROXIED_AUTH_V1, isCritical); 180 181 182 this.authorizationDN = authorizationDN; 183 184 rawAuthorizationDN = ByteString.valueOfUtf8(authorizationDN.toString()); 185 } 186 187 188 189 /** 190 * Writes this control's value to an ASN.1 writer. The value (if any) must be 191 * written as an ASN1OctetString. 192 * 193 * @param writer The ASN.1 writer to use. 194 * @throws IOException If a problem occurs while writing to the stream. 195 */ 196 @Override 197 protected void writeValue(ASN1Writer writer) throws IOException { 198 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 199 200 writer.writeStartSequence(); 201 writer.writeOctetString(rawAuthorizationDN); 202 writer.writeEndSequence(); 203 204 writer.writeEndSequence(); 205 } 206 207 208 209 /** 210 * Retrieves the raw, unprocessed authorization DN from the control value. 211 * 212 * @return The raw, unprocessed authorization DN from the control value. 213 */ 214 public ByteString getRawAuthorizationDN() 215 { 216 return rawAuthorizationDN; 217 } 218 219 220 221 /** 222 * Retrieves the authorization DN from the control value. 223 * 224 * @return The authorization DN from the control value. 225 * 226 * @throws DirectoryException If a problem occurs while attempting to decode 227 * the raw authorization DN as a DN. 228 */ 229 public DN getAuthorizationDN() 230 throws DirectoryException 231 { 232 if (authorizationDN == null) 233 { 234 authorizationDN = DN.valueOf(rawAuthorizationDN); 235 } 236 237 return authorizationDN; 238 } 239 240 241 242 /** 243 * Retrieves the authorization entry for this proxied authorization V1 244 * control. It will also perform any necessary password policy checks to 245 * ensure that the associated user account is suitable for use in performing 246 * this processing. 247 * 248 * @return The entry for user specified as the authorization identity in this 249 * proxied authorization V1 control, or {@code null} if the 250 * authorization DN is the null DN. 251 * 252 * @throws DirectoryException If the target user does not exist or is not 253 * available for use, or if a problem occurs 254 * while making the determination. 255 */ 256 public Entry getAuthorizationEntry() 257 throws DirectoryException 258 { 259 DN authzDN = getAuthorizationDN(); 260 if (authzDN.isRootDN()) 261 { 262 return null; 263 } 264 265 266 // See if the authorization DN is one of the alternate bind DNs for one of 267 // the root users and if so then map it accordingly. 268 DN actualDN = DirectoryServer.getActualRootBindDN(authzDN); 269 if (actualDN != null) 270 { 271 authzDN = actualDN; 272 } 273 274 275 Entry userEntry = DirectoryServer.getEntry(authzDN); 276 if (userEntry == null) 277 { 278 // The requested user does not exist. 279 LocalizableMessage message = ERR_PROXYAUTH1_NO_SUCH_USER.get(authzDN); 280 throw new DirectoryException(ResultCode.AUTHORIZATION_DENIED, message); 281 } 282 283 284 // FIXME -- We should provide some mechanism for enabling debug 285 // processing. 286 AuthenticationPolicyState state = AuthenticationPolicyState.forUser( 287 userEntry, false); 288 289 if (state.isDisabled()) 290 { 291 LocalizableMessage message = ERR_PROXYAUTH1_UNUSABLE_ACCOUNT.get(userEntry.getName()); 292 throw new DirectoryException(ResultCode.AUTHORIZATION_DENIED, message); 293 } 294 295 if (state.isPasswordPolicy()) 296 { 297 PasswordPolicyState pwpState = (PasswordPolicyState) state; 298 if (pwpState.isAccountExpired() || pwpState.isLocked() || pwpState.isPasswordExpired()) 299 { 300 LocalizableMessage message = ERR_PROXYAUTH1_UNUSABLE_ACCOUNT.get(authzDN); 301 throw new DirectoryException(ResultCode.AUTHORIZATION_DENIED, message); 302 } 303 } 304 305 // If we've made it here, then the user is acceptable. 306 return userEntry; 307 } 308 309 310 311 /** 312 * Appends a string representation of this proxied auth v1 control to the 313 * provided buffer. 314 * 315 * @param buffer The buffer to which the information should be appended. 316 */ 317 @Override 318 public void toString(StringBuilder buffer) 319 { 320 buffer.append("ProxiedAuthorizationV1Control(authorizationDN=\""); 321 buffer.append(rawAuthorizationDN); 322 buffer.append("\")"); 323 } 324} 325