package com.hwlcn.ldap.ldap.protocol; import com.hwlcn.ldap.asn1.ASN1Buffer; import com.hwlcn.ldap.asn1.ASN1BufferSequence; import com.hwlcn.ldap.asn1.ASN1Element; import com.hwlcn.ldap.asn1.ASN1Integer; import com.hwlcn.ldap.asn1.ASN1OctetString; import com.hwlcn.ldap.asn1.ASN1Sequence; import com.hwlcn.ldap.asn1.ASN1StreamReader; import com.hwlcn.ldap.asn1.ASN1StreamReaderSequence; import com.hwlcn.ldap.ldap.sdk.BindRequest; import com.hwlcn.ldap.ldap.sdk.Control; import com.hwlcn.ldap.ldap.sdk.GenericSASLBindRequest; import com.hwlcn.ldap.ldap.sdk.LDAPException; import com.hwlcn.ldap.ldap.sdk.ResultCode; import com.hwlcn.ldap.ldap.sdk.SimpleBindRequest; import com.hwlcn.ldap.util.LDAPSDKUsageException; import com.hwlcn.core.annotation.NotMutable; import com.hwlcn.core.annotation.InternalUseOnly; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.ldap.protocol.ProtocolMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.StaticUtils.*; import static com.hwlcn.ldap.util.Validator.*; @InternalUseOnly() @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) public final class BindRequestProtocolOp implements ProtocolOp { public static final byte CRED_TYPE_SIMPLE = (byte) 0x80; public static final byte CRED_TYPE_SASL = (byte) 0xA3; private static final long serialVersionUID = 6661208657485444954L; private final ASN1OctetString saslCredentials; private final ASN1OctetString simplePassword; private final byte credentialsType; private final int version; private final String bindDN; private final String saslMechanism; public BindRequestProtocolOp(final String bindDN, final String password) { if (bindDN == null) { this.bindDN = ""; } else { this.bindDN = bindDN; } if (password == null) { simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE); } else { simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE, password); } version = 3; credentialsType = CRED_TYPE_SIMPLE; saslMechanism = null; saslCredentials = null; } public BindRequestProtocolOp(final String bindDN, final byte[] password) { if (bindDN == null) { this.bindDN = ""; } else { this.bindDN = bindDN; } if (password == null) { simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE); } else { simplePassword = new ASN1OctetString(CRED_TYPE_SIMPLE, password); } version = 3; credentialsType = CRED_TYPE_SIMPLE; saslMechanism = null; saslCredentials = null; } public BindRequestProtocolOp(final String bindDN, final String saslMechanism, final ASN1OctetString saslCredentials) { this.saslMechanism = saslMechanism; this.saslCredentials = saslCredentials; if (bindDN == null) { this.bindDN = ""; } else { this.bindDN = bindDN; } version = 3; credentialsType = CRED_TYPE_SASL; simplePassword = null; } public BindRequestProtocolOp(final SimpleBindRequest request) throws LDAPSDKUsageException { version = 3; credentialsType = CRED_TYPE_SIMPLE; bindDN = request.getBindDN(); simplePassword = request.getPassword(); saslMechanism = null; saslCredentials = null; if (simplePassword == null) { throw new LDAPSDKUsageException( ERR_BIND_REQUEST_CANNOT_CREATE_WITH_PASSWORD_PROVIDER.get()); } } public BindRequestProtocolOp(final GenericSASLBindRequest request) { version = 3; credentialsType = CRED_TYPE_SASL; bindDN = request.getBindDN(); simplePassword = null; saslMechanism = request.getSASLMechanismName(); saslCredentials = request.getCredentials(); } BindRequestProtocolOp(final ASN1StreamReader reader) throws LDAPException { try { reader.beginSequence(); version = reader.readInteger(); bindDN = reader.readString(); credentialsType = (byte) reader.peek(); ensureNotNull(bindDN); switch (credentialsType) { case CRED_TYPE_SIMPLE: simplePassword = new ASN1OctetString(credentialsType, reader.readBytes()); saslMechanism = null; saslCredentials = null; ensureNotNull(bindDN); break; case CRED_TYPE_SASL: final ASN1StreamReaderSequence saslSequence = reader.beginSequence(); saslMechanism = reader.readString(); ensureNotNull(saslMechanism); if (saslSequence.hasMoreElements()) { saslCredentials = new ASN1OctetString(reader.readBytes()); } else { saslCredentials = null; } simplePassword = null; break; default: throw new LDAPException(ResultCode.DECODING_ERROR, ERR_BIND_REQUEST_INVALID_CRED_TYPE.get(toHex(credentialsType))); } } catch (LDAPException le) { debugException(le); throw le; } catch (Exception e) { debugException(e); throw new LDAPException(ResultCode.DECODING_ERROR, ERR_BIND_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e); } } private BindRequestProtocolOp(final int version, final String bindDN, final byte credentialsType, final ASN1OctetString simplePassword, final String saslMechanism, final ASN1OctetString saslCredentials) { this.version = version; this.bindDN = bindDN; this.credentialsType = credentialsType; this.simplePassword = simplePassword; this.saslMechanism = saslMechanism; this.saslCredentials = saslCredentials; } public int getVersion() { return version; } public String getBindDN() { return bindDN; } public byte getCredentialsType() { return credentialsType; } public ASN1OctetString getSimplePassword() { return simplePassword; } public String getSASLMechanism() { return saslMechanism; } public ASN1OctetString getSASLCredentials() { return saslCredentials; } public byte getProtocolOpType() { return LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST; } public ASN1Element encodeProtocolOp() { final ASN1Element credentials; if (credentialsType == CRED_TYPE_SIMPLE) { credentials = simplePassword; } else { if (saslCredentials == null) { credentials = new ASN1Sequence(CRED_TYPE_SASL, new ASN1OctetString(saslMechanism)); } else { credentials = new ASN1Sequence(CRED_TYPE_SASL, new ASN1OctetString(saslMechanism), saslCredentials); } } return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST, new ASN1Integer(version), new ASN1OctetString(bindDN), credentials); } public static BindRequestProtocolOp decodeProtocolOp( final ASN1Element element) throws LDAPException { try { final ASN1Element[] elements = ASN1Sequence.decodeAsSequence(element).elements(); final int version = ASN1Integer.decodeAsInteger(elements[0]).intValue(); final String bindDN = ASN1OctetString.decodeAsOctetString(elements[1]).stringValue(); final ASN1OctetString saslCredentials; final ASN1OctetString simplePassword; final String saslMechanism; switch (elements[2].getType()) { case CRED_TYPE_SIMPLE: simplePassword = ASN1OctetString.decodeAsOctetString(elements[2]); saslMechanism = null; saslCredentials = null; break; case CRED_TYPE_SASL: final ASN1Element[] saslElements = ASN1Sequence.decodeAsSequence(elements[2]).elements(); saslMechanism = ASN1OctetString.decodeAsOctetString(saslElements[0]). stringValue(); if (saslElements.length == 1) { saslCredentials = null; } else { saslCredentials = ASN1OctetString.decodeAsOctetString(saslElements[1]); } simplePassword = null; break; default: throw new LDAPException(ResultCode.DECODING_ERROR, ERR_BIND_REQUEST_INVALID_CRED_TYPE.get( toHex(elements[2].getType()))); } return new BindRequestProtocolOp(version, bindDN, elements[2].getType(), simplePassword, saslMechanism, saslCredentials); } catch (final LDAPException le) { debugException(le); throw le; } catch (final Exception e) { debugException(e); throw new LDAPException(ResultCode.DECODING_ERROR, ERR_BIND_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e); } } public void writeTo(final ASN1Buffer buffer) { final ASN1BufferSequence opSequence = buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_BIND_REQUEST); buffer.addInteger(version); buffer.addOctetString(bindDN); if (credentialsType == CRED_TYPE_SIMPLE) { buffer.addElement(simplePassword); } else { final ASN1BufferSequence saslSequence = buffer.beginSequence(CRED_TYPE_SASL); buffer.addOctetString(saslMechanism); if (saslCredentials != null) { buffer.addElement(saslCredentials); } saslSequence.end(); } opSequence.end(); buffer.setZeroBufferOnClear(); } public BindRequest toBindRequest(final Control... controls) { if (credentialsType == CRED_TYPE_SIMPLE) { return new SimpleBindRequest(bindDN, simplePassword.getValue(), controls); } else { return new GenericSASLBindRequest(bindDN, saslMechanism, saslCredentials, controls); } } @Override() public String toString() { final StringBuilder buffer = new StringBuilder(); toString(buffer); return buffer.toString(); } public void toString(final StringBuilder buffer) { buffer.append("BindRequestProtocolOp(version="); buffer.append(version); buffer.append(", bindDN='"); buffer.append(bindDN); buffer.append("', type="); if (credentialsType == CRED_TYPE_SIMPLE) { buffer.append("simple"); } else { buffer.append("SASL, mechanism="); buffer.append(saslMechanism); } buffer.append(')'); } }