package com.hwlcn.ldap.ldap.sdk.controls; import com.hwlcn.ldap.asn1.ASN1Element; import com.hwlcn.ldap.asn1.ASN1OctetString; import com.hwlcn.ldap.asn1.ASN1Sequence; import com.hwlcn.ldap.ldap.sdk.Control; import com.hwlcn.ldap.ldap.sdk.DN; import com.hwlcn.ldap.ldap.sdk.LDAPException; import com.hwlcn.ldap.ldap.sdk.ResultCode; import com.hwlcn.core.annotation.NotMutable; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.ldap.sdk.controls.ControlMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.Validator.*; /** * This class provides an implementation of the proxied authorization V1 * request control, which may be used to request that the associated operation * be performed as if it had been requested by some other user. It is based on * the specification provided in early versions of the * draft-weltman-ldapv3-proxy Internet Draft (this implementation is based on * the "-04" revision). Later versions of the draft, and subsequently * <A HREF="http://www.ietf.org/rfc/rfc4370.txt">RFC 4370</A>, define a second * version of the proxied authorization control with a different OID and * different value format. This control is supported primarily for legacy * purposes, and it is recommended that new applications use the * {@link ProxiedAuthorizationV2RequestControl} instead if this version. * <BR><BR> * The value of this control includes the DN of the user as whom the operation * should be performed. Note that it should be a distinguished name, and not an * authzId value as is used in the proxied authorization V2 control. * <BR><BR> * This control may be used in conjunction with add, delete, compare, delete, * extended, modify, modify DN, and search requests. In that case, the * associated operation will be processed under the authority of the specified * authorization identity rather than the identity associated with the client * connection (i.e., the user as whom that connection is bound). Note that * because of the inherent security risks associated with the use of the proxied * authorization control, most directory servers which support its use enforce * strict restrictions on the users that are allowed to request this control. * Note that while the directory server should return a * {@link ResultCode#AUTHORIZATION_DENIED} result for a proxied authorization V2 * control if the requester does not have the appropriate permission to use that * control, this result will not necessarily be used for the same condition with * the proxied authorization V1 control because this result code was not defined * until the release of the proxied authorization V2 specification. * code. * <BR><BR> * There is no corresponding response control for this request control. * <BR><BR> * <H2>Example</H2> * The following example demonstrates the use of the proxied authorization V1 * control to delete an entry under the authority of the user with DN * "uid=john.doe,ou=People,dc=example,dc=com": * <PRE> * DeleteRequest deleteRequest = * new DeleteRequest("cn=no longer needed,dc=example,dc=com"); * deleteRequest.addControl(new ProxiedAuthorizationV1RequestControl( * "uid=john.doe,ou=People,dc=example,dc=com")); * * try * { * LDAPResult deleteResult = connection.delete(deleteRequest); * // If we got here, then the delete was successful. * } * catch (LDAPException le) * { * // The delete failed for some reason. It may or may not have been * // because the authenticated user does not have permission to use the * // proxied authorization V1 control. * } * </PRE> */ @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) public final class ProxiedAuthorizationV1RequestControl extends Control { public static final String PROXIED_AUTHORIZATION_V1_REQUEST_OID = "2.16.840.1.113730.3.4.12"; private static final long serialVersionUID = 7312632337431962774L; private final String proxyDN; public ProxiedAuthorizationV1RequestControl(final String proxyDN) { super(PROXIED_AUTHORIZATION_V1_REQUEST_OID, true, encodeValue(proxyDN)); ensureNotNull(proxyDN); this.proxyDN = proxyDN; } public ProxiedAuthorizationV1RequestControl(final DN proxyDN) { super(PROXIED_AUTHORIZATION_V1_REQUEST_OID, true, encodeValue(proxyDN.toString())); this.proxyDN = proxyDN.toString(); } public ProxiedAuthorizationV1RequestControl(final Control control) throws LDAPException { super(control); final ASN1OctetString value = control.getValue(); if (value == null) { throw new LDAPException(ResultCode.DECODING_ERROR, ERR_PROXY_V1_NO_VALUE.get()); } try { final ASN1Element valueElement = ASN1Element.decode(value.getValue()); final ASN1Element[] elements = ASN1Sequence.decodeAsSequence(valueElement).elements(); proxyDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); } catch (Exception e) { debugException(e); throw new LDAPException(ResultCode.DECODING_ERROR, ERR_PROXYV1_DECODE_ERROR.get(e), e); } } private static ASN1OctetString encodeValue(final String proxyDN) { final ASN1Element[] valueElements = { new ASN1OctetString(proxyDN) }; return new ASN1OctetString(new ASN1Sequence(valueElements).encode()); } public String getProxyDN() { return proxyDN; } @Override() public String getControlName() { return INFO_CONTROL_NAME_PROXIED_AUTHZ_V1_REQUEST.get(); } @Override() public void toString(final StringBuilder buffer) { buffer.append("ProxiedAuthorizationV1RequestControl(proxyDN='"); buffer.append(proxyDN); buffer.append("')"); } }