001/* 002 * Copyright 2011-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2011-2017 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 */ 021package com.unboundid.ldap.sdk; 022 023 024 025import java.util.ArrayList; 026import java.util.List; 027 028import com.unboundid.asn1.ASN1OctetString; 029import com.unboundid.util.NotMutable; 030import com.unboundid.util.ThreadSafety; 031import com.unboundid.util.ThreadSafetyLevel; 032import com.unboundid.util.Validator; 033 034 035 036/** 037 * This class provides a mechanism for performing SASL authentication in a 038 * generic manner. The caller is responsible for properly encoding the 039 * credentials (if any) and interpreting the result. Further, if the requested 040 * SASL mechanism is one that requires multiple stages, then the caller is 041 * responsible for all processing in each stage. 042 */ 043@NotMutable() 044@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 045public final class GenericSASLBindRequest 046 extends SASLBindRequest 047{ 048 /** 049 * The serial version UID for this serializable class. 050 */ 051 private static final long serialVersionUID = 7740968332104559230L; 052 053 054 055 // The SASL credentials that should be used for the bind request. 056 private final ASN1OctetString credentials; 057 058 // The bind DN to use for the bind request. 059 private final String bindDN; 060 061 // The name of the SASL mechanism that should be used for the bind request. 062 private final String mechanism; 063 064 065 066 /** 067 * Creates a new generic SASL bind request with the provided information. 068 * 069 * @param bindDN The bind DN that should be used for the request. It 070 * may be {@code null} if the target identity should be 071 * derived from the credentials or some other source. 072 * @param mechanism The name of the mechanism that should be used for the 073 * SASL bind. It must not be {@code null}. 074 * @param credentials The credentials that should be used for the SASL bind. 075 * It may be {@code null} if no credentials should be 076 * used. 077 * @param controls The set of controls to include in the SASL bind 078 * request. It may be {@code null} or empty if no 079 * request controls are needed. 080 */ 081 public GenericSASLBindRequest(final String bindDN, final String mechanism, 082 final ASN1OctetString credentials, 083 final Control... controls) 084 { 085 super(controls); 086 087 Validator.ensureNotNull(mechanism); 088 089 this.bindDN = bindDN; 090 this.mechanism = mechanism; 091 this.credentials = credentials; 092 } 093 094 095 096 /** 097 * Retrieves the bind DN for this SASL bind request, if any. 098 * 099 * @return The bind DN for this SASL bind request, or {@code null} if the 100 * target identity should be determined from the credentials or some 101 * other mechanism. 102 */ 103 public String getBindDN() 104 { 105 return bindDN; 106 } 107 108 109 110 /** 111 * {@inheritDoc} 112 */ 113 @Override() 114 public String getSASLMechanismName() 115 { 116 return mechanism; 117 } 118 119 120 121 /** 122 * Retrieves the credentials for the SASL bind request, if any. 123 * 124 * @return The credentials for the SASL bind request, or {@code null} if 125 * there are none. 126 */ 127 public ASN1OctetString getCredentials() 128 { 129 return credentials; 130 } 131 132 133 134 /** 135 * {@inheritDoc} 136 */ 137 @Override() 138 protected BindResult process(final LDAPConnection connection, final int depth) 139 throws LDAPException 140 { 141 return sendBindRequest(connection, bindDN, credentials, getControls(), 142 getResponseTimeoutMillis(connection)); 143 } 144 145 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override() 151 public GenericSASLBindRequest duplicate() 152 { 153 return duplicate(getControls()); 154 } 155 156 157 158 /** 159 * {@inheritDoc} 160 */ 161 @Override() 162 public GenericSASLBindRequest duplicate(final Control[] controls) 163 { 164 return new GenericSASLBindRequest(bindDN, mechanism, credentials, 165 controls); 166 } 167 168 169 170 /** 171 * {@inheritDoc} 172 */ 173 @Override() 174 public void toString(final StringBuilder buffer) 175 { 176 buffer.append("GenericSASLBindRequest(mechanism='"); 177 buffer.append(mechanism); 178 buffer.append('\''); 179 180 if (bindDN != null) 181 { 182 buffer.append(", bindDN='"); 183 buffer.append(bindDN); 184 buffer.append('\''); 185 } 186 187 if (credentials != null) 188 { 189 buffer.append(", credentials=byte["); 190 buffer.append(credentials.getValueLength()); 191 buffer.append(']'); 192 } 193 194 final Control[] controls = getControls(); 195 if (controls.length > 0) 196 { 197 buffer.append(", controls={"); 198 for (int i=0; i < controls.length; i++) 199 { 200 if (i > 0) 201 { 202 buffer.append(", "); 203 } 204 205 buffer.append(controls[i]); 206 } 207 buffer.append('}'); 208 } 209 210 buffer.append(')'); 211 } 212 213 214 215 /** 216 * {@inheritDoc} 217 */ 218 @Override() 219 public void toCode(final List<String> lineList, final String requestID, 220 final int indentSpaces, final boolean includeProcessing) 221 { 222 // Create the request variable. 223 final ArrayList<ToCodeArgHelper> constructorArgs = 224 new ArrayList<ToCodeArgHelper>(4); 225 constructorArgs.add(ToCodeArgHelper.createString(bindDN, "Bind DN")); 226 constructorArgs.add(ToCodeArgHelper.createString(mechanism, 227 "SASL Mechanism Name")); 228 constructorArgs.add(ToCodeArgHelper.createByteArray( 229 "---redacted-SASL-credentials".getBytes(), true, 230 "SASL Credentials")); 231 232 final Control[] controls = getControls(); 233 if (controls.length > 0) 234 { 235 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 236 "Bind Controls")); 237 } 238 239 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 240 "GenericSASLBindRequest", requestID + "Request", 241 "new GenericSASLBindRequest", constructorArgs); 242 243 244 // Add lines for processing the request and obtaining the result. 245 if (includeProcessing) 246 { 247 // Generate a string with the appropriate indent. 248 final StringBuilder buffer = new StringBuilder(); 249 for (int i=0; i < indentSpaces; i++) 250 { 251 buffer.append(' '); 252 } 253 final String indent = buffer.toString(); 254 255 lineList.add(""); 256 lineList.add(indent + '{'); 257 lineList.add(indent + " BindResult " + requestID + 258 "Result = connection.bind(" + requestID + "Request);"); 259 lineList.add(indent + " // The bind was processed successfully."); 260 lineList.add(indent + '}'); 261 lineList.add(indent + "catch (SASLBindInProgressException e)"); 262 lineList.add(indent + '{'); 263 lineList.add(indent + " // The SASL bind requires multiple stages. " + 264 "Continue it here."); 265 lineList.add(indent + " // Do not attempt to use the connection for " + 266 "any other purpose until bind processing has completed."); 267 lineList.add(indent + '}'); 268 lineList.add(indent + "catch (LDAPException e)"); 269 lineList.add(indent + '{'); 270 lineList.add(indent + " // The bind failed. Maybe the following will " + 271 "help explain why."); 272 lineList.add(indent + " // Note that the connection is now likely in " + 273 "an unauthenticated state."); 274 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 275 lineList.add(indent + " String message = e.getMessage();"); 276 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 277 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 278 lineList.add(indent + " Control[] responseControls = " + 279 "e.getResponseControls();"); 280 lineList.add(indent + '}'); 281 } 282 } 283}