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