001 /* 002 * Copyright 2012-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2015 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021 package com.unboundid.ldap.sdk.unboundidds; 022 023 024 025 import com.unboundid.asn1.ASN1OctetString; 026 import com.unboundid.ldap.sdk.BindResult; 027 import com.unboundid.ldap.sdk.Control; 028 import com.unboundid.ldap.sdk.InternalSDKHelper; 029 import com.unboundid.ldap.sdk.LDAPConnection; 030 import com.unboundid.ldap.sdk.LDAPException; 031 import com.unboundid.ldap.sdk.SASLBindRequest; 032 import com.unboundid.util.ThreadSafety; 033 import com.unboundid.util.ThreadSafetyLevel; 034 import com.unboundid.util.Validator; 035 036 037 038 /** 039 * <BLOCKQUOTE> 040 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID 041 * LDAP SDK for Java. It is not available for use in applications that 042 * include only the Standard Edition of the LDAP SDK, and is not supported for 043 * use in conjunction with non-UnboundID products. 044 * </BLOCKQUOTE> 045 * This class provides support for an UnboundID-proprietary SASL mechanism that 046 * provides multifactor authentication using the combination of a client 047 * certificate (presented during SSL/TLS negotiation) and a static password. 048 * <BR><BR> 049 * The name for this SASL mechanism is "UNBOUNDID-CERTIFICATE-PLUS-PASSWORD". 050 * The SASL credentials consist simply of the static password for the user 051 * identified by the certificate, to make the SASL mechanism as easy as possible 052 * to use from other client APIs. 053 */ 054 @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 055 public final class UnboundIDCertificatePlusPasswordBindRequest 056 extends SASLBindRequest 057 { 058 /** 059 * The name for the UnboundID certificate plus password SASL mechanism. 060 */ 061 public static final String UNBOUNDID_CERT_PLUS_PW_MECHANISM_NAME = 062 "UNBOUNDID-CERTIFICATE-PLUS-PASSWORD"; 063 064 065 066 /** 067 * The serial version UID for this serializable class. 068 */ 069 private static final long serialVersionUID = 8863298749835036708L; 070 071 072 073 // The password to use to authenticate. 074 private final ASN1OctetString password; 075 076 // The message ID from the last LDAP message sent from this request. 077 private volatile int messageID = -1; 078 079 080 081 /** 082 * Creates a new certificate plus password bind request with the provided 083 * information. 084 * 085 * @param password The password to use to authenticate as user identified by 086 * the certificate. It must not be {@code null} or empty. 087 * @param controls The set of controls to include in the bind request. It 088 * may be {@code null} or empty if no request controls are 089 * needed. 090 */ 091 public UnboundIDCertificatePlusPasswordBindRequest(final String password, 092 final Control... controls) 093 { 094 this(new ASN1OctetString(CRED_TYPE_SASL, password), controls); 095 } 096 097 098 099 /** 100 * Creates a new certificate plus password bind request with the provided 101 * information. 102 * 103 * @param password The password to use to authenticate as user identified by 104 * the certificate. It must not be {@code null} or empty. 105 * @param controls The set of controls to include in the bind request. It 106 * may be {@code null} or empty if no request controls are 107 * needed. 108 */ 109 public UnboundIDCertificatePlusPasswordBindRequest(final byte[] password, 110 final Control... controls) 111 { 112 this(new ASN1OctetString(CRED_TYPE_SASL, password), controls); 113 } 114 115 116 117 /** 118 * Creates a new certificate plus password bind request with the provided 119 * information. 120 * 121 * @param password The password to use to authenticate as user identified by 122 * the certificate. It must not be {@code null} or empty. 123 * @param controls The set of controls to include in the bind request. It 124 * may be {@code null} or empty if no request controls are 125 * needed. 126 */ 127 private UnboundIDCertificatePlusPasswordBindRequest( 128 final ASN1OctetString password, final Control... controls) 129 { 130 super(controls); 131 132 Validator.ensureFalse((password.getValueLength() == 0), 133 "The bind password must not be empty"); 134 135 this.password = password; 136 } 137 138 139 140 /** 141 * Retrieves the password to use to authenticate as the user identified by the 142 * certificate. 143 * 144 * @return The password to use to authenticate as the user identified by the 145 * certificate. 146 */ 147 public ASN1OctetString getPassword() 148 { 149 return password; 150 } 151 152 153 154 /** 155 * {@inheritDoc} 156 */ 157 @Override() 158 public String getSASLMechanismName() 159 { 160 return UNBOUNDID_CERT_PLUS_PW_MECHANISM_NAME; 161 } 162 163 164 165 /** 166 * {@inheritDoc} 167 */ 168 @Override() 169 protected BindResult process(final LDAPConnection connection, final int depth) 170 throws LDAPException 171 { 172 messageID = InternalSDKHelper.nextMessageID(connection); 173 return sendBindRequest(connection, "", password, getControls(), 174 getResponseTimeoutMillis(connection)); 175 } 176 177 178 179 /** 180 * {@inheritDoc} 181 */ 182 @Override() 183 public int getLastMessageID() 184 { 185 return messageID; 186 } 187 188 189 190 /** 191 * {@inheritDoc} 192 */ 193 @Override() 194 public UnboundIDCertificatePlusPasswordBindRequest duplicate() 195 { 196 return duplicate(getControls()); 197 } 198 199 200 201 /** 202 * {@inheritDoc} 203 */ 204 @Override() 205 public UnboundIDCertificatePlusPasswordBindRequest duplicate( 206 final Control[] controls) 207 { 208 final UnboundIDCertificatePlusPasswordBindRequest bindRequest = 209 new UnboundIDCertificatePlusPasswordBindRequest(password, controls); 210 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 211 return bindRequest; 212 } 213 214 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override() 220 public UnboundIDCertificatePlusPasswordBindRequest getRebindRequest( 221 final String host, final int port) 222 { 223 return duplicate(); 224 } 225 226 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override() 232 public void toString(final StringBuilder buffer) 233 { 234 buffer.append("UnboundIDCertificatePlusPasswordBindRequest("); 235 236 final Control[] controls = getControls(); 237 if (controls.length > 0) 238 { 239 buffer.append("controls={"); 240 for (int i=0; i < controls.length; i++) 241 { 242 if (i > 0) 243 { 244 buffer.append(", "); 245 } 246 247 buffer.append(controls[i]); 248 } 249 buffer.append('}'); 250 } 251 252 buffer.append(')'); 253 } 254 }