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