001/* 002 * Copyright 2007-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2007-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk; 037 038 039 040import java.util.ArrayList; 041import java.util.List; 042 043import com.unboundid.asn1.ASN1OctetString; 044import com.unboundid.util.NotMutable; 045import com.unboundid.util.NotNull; 046import com.unboundid.util.Nullable; 047import com.unboundid.util.ThreadSafety; 048import com.unboundid.util.ThreadSafetyLevel; 049 050 051 052/** 053 * This class provides a SASL ANONYMOUS bind request implementation as described 054 * in <A HREF="http://www.ietf.org/rfc/rfc4505.txt">RFC 4505</A>. Binding with 055 * The ANONYMOUS SASL mechanism is essentially equivalent to using an anonymous 056 * simple bind (i.e., a simple bind with an empty password), although the SASL 057 * ANONYMOUS mechanism does provide the ability to include additional trace 058 * information with the request that may be logged or otherwise handled by 059 * the server. 060 * <BR><BR> 061 * <H2>Example</H2> 062 * The following example demonstrates the process for performing an ANONYMOUS 063 * bind, including a trace string of "Demo Application" against a directory 064 * server: 065 * <PRE> 066 * ANONYMOUSBindRequest bindRequest = 067 * new ANONYMOUSBindRequest("Demo Application"); 068 * BindResult bindResult; 069 * try 070 * { 071 * bindResult = connection.bind(bindRequest); 072 * // If we get here, then the bind was successful. 073 * } 074 * catch (LDAPException le) 075 * { 076 * // The bind failed for some reason. 077 * bindResult = new BindResult(le.toLDAPResult()); 078 * ResultCode resultCode = le.getResultCode(); 079 * String errorMessageFromServer = le.getDiagnosticMessage(); 080 * } 081 * </PRE> 082 */ 083@NotMutable() 084@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 085public final class ANONYMOUSBindRequest 086 extends SASLBindRequest 087{ 088 /** 089 * The name for the ANONYMOUS SASL mechanism. 090 */ 091 @NotNull public static final String ANONYMOUS_MECHANISM_NAME = "ANONYMOUS"; 092 093 094 095 /** 096 * The serial version UID for this serializable class. 097 */ 098 private static final long serialVersionUID = 4259102841471750866L; 099 100 101 102 // The trace string that should be included in the bind request, if available. 103 @Nullable private final String traceString; 104 105 106 107 /** 108 * Creates a new SASL ANONYMOUS bind request with no trace string and no 109 * controls. 110 */ 111 public ANONYMOUSBindRequest() 112 { 113 this(null, NO_CONTROLS); 114 } 115 116 117 118 /** 119 * Creates a new SASL ANONYMOUS bind request with the provided trace string 120 * and no controls. 121 * 122 * @param traceString The trace string to include in the bind request, or 123 * {@code null} if no trace string is to be provided. 124 */ 125 public ANONYMOUSBindRequest(@Nullable final String traceString) 126 { 127 this(traceString, NO_CONTROLS); 128 } 129 130 131 132 /** 133 * Creates a new SASL ANONYMOUS bind request with the provided set of controls 134 * and no trace string. 135 * 136 * @param controls The set of controls to include in the request. 137 */ 138 public ANONYMOUSBindRequest(@Nullable final Control... controls) 139 { 140 this(null, controls); 141 } 142 143 144 145 /** 146 * Creates a new SASL ANONYMOUS bind request with the provided trace string 147 * and controls. 148 * 149 * @param traceString The trace string to include in the bind request, or 150 * {@code null} if no trace string is to be provided. 151 * @param controls The set of controls to include in the request. 152 */ 153 public ANONYMOUSBindRequest(@Nullable final String traceString, 154 @Nullable final Control... controls) 155 { 156 super(controls); 157 158 this.traceString = traceString; 159 } 160 161 162 163 /** 164 * {@inheritDoc} 165 */ 166 @Override() 167 @NotNull() 168 public String getSASLMechanismName() 169 { 170 return ANONYMOUS_MECHANISM_NAME; 171 } 172 173 174 175 /** 176 * Retrieves the trace string that will be included with the bind request. 177 * 178 * @return The trace string that will be included with the bind request, or 179 * {@code null} if there is to be no trace string. 180 */ 181 @Nullable() 182 public String getTraceString() 183 { 184 return traceString; 185 } 186 187 188 189 /** 190 * Sends this bind request to the target server over the provided connection 191 * and returns the corresponding response. 192 * 193 * @param connection The connection to use to send this bind request to the 194 * server and read the associated response. 195 * @param depth The current referral depth for this request. It should 196 * always be one for the initial request, and should only 197 * be incremented when following referrals. 198 * 199 * @return The bind response read from the server. 200 * 201 * @throws LDAPException If a problem occurs while sending the request or 202 * reading the response. 203 */ 204 @Override() 205 @NotNull() 206 protected BindResult process(@NotNull final LDAPConnection connection, 207 final int depth) 208 throws LDAPException 209 { 210 setReferralDepth(depth); 211 212 ASN1OctetString credentials = null; 213 if ((traceString != null) && (! traceString.isEmpty())) 214 { 215 credentials = new ASN1OctetString(traceString); 216 } 217 218 return sendBindRequest(connection, null, credentials, getControls(), 219 getResponseTimeoutMillis(connection)); 220 } 221 222 223 224 /** 225 * {@inheritDoc} 226 */ 227 @Override() 228 @NotNull() 229 public ANONYMOUSBindRequest getRebindRequest(@NotNull final String host, 230 final int port) 231 { 232 return new ANONYMOUSBindRequest(traceString, getControls()); 233 } 234 235 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override() 241 @NotNull() 242 public ANONYMOUSBindRequest duplicate() 243 { 244 return duplicate(getControls()); 245 } 246 247 248 249 /** 250 * {@inheritDoc} 251 */ 252 @Override() 253 @NotNull() 254 public ANONYMOUSBindRequest duplicate(@Nullable final Control[] controls) 255 { 256 final ANONYMOUSBindRequest bindRequest = 257 new ANONYMOUSBindRequest(traceString, controls); 258 bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 259 bindRequest.setIntermediateResponseListener( 260 getIntermediateResponseListener()); 261 bindRequest.setReferralDepth(getReferralDepth()); 262 bindRequest.setReferralConnector(getReferralConnectorInternal()); 263 return bindRequest; 264 } 265 266 267 268 /** 269 * {@inheritDoc} 270 */ 271 @Override() 272 public void toString(@NotNull final StringBuilder buffer) 273 { 274 buffer.append("ANONYMOUSBindRequest("); 275 if (traceString != null) 276 { 277 buffer.append(", trace='"); 278 buffer.append(traceString); 279 buffer.append('\''); 280 } 281 282 final Control[] controls = getControls(); 283 if (controls.length > 0) 284 { 285 buffer.append(", controls={"); 286 for (int i=0; i < controls.length; i++) 287 { 288 if (i > 0) 289 { 290 buffer.append(", "); 291 } 292 293 buffer.append(controls[i]); 294 } 295 buffer.append('}'); 296 } 297 298 buffer.append(')'); 299 } 300 301 302 303 /** 304 * {@inheritDoc} 305 */ 306 @Override() 307 public void toCode(@NotNull final List<String> lineList, 308 @NotNull final String requestID, 309 final int indentSpaces, final boolean includeProcessing) 310 { 311 // Create the request variable. 312 final ArrayList<ToCodeArgHelper> constructorArgs = new ArrayList<>(2); 313 constructorArgs.add(ToCodeArgHelper.createString(traceString, 314 "Trace String")); 315 316 final Control[] controls = getControls(); 317 if (controls.length > 0) 318 { 319 constructorArgs.add(ToCodeArgHelper.createControlArray(controls, 320 "Bind Controls")); 321 } 322 323 ToCodeHelper.generateMethodCall(lineList, indentSpaces, 324 "ANONYMOUSBindRequest", requestID + "Request", 325 "new ANONYMOUSBindRequest", constructorArgs); 326 327 328 // Add lines for processing the request and obtaining the result. 329 if (includeProcessing) 330 { 331 // Generate a string with the appropriate indent. 332 final StringBuilder buffer = new StringBuilder(); 333 for (int i=0; i < indentSpaces; i++) 334 { 335 buffer.append(' '); 336 } 337 final String indent = buffer.toString(); 338 339 lineList.add(""); 340 lineList.add(indent + "try"); 341 lineList.add(indent + '{'); 342 lineList.add(indent + " BindResult " + requestID + 343 "Result = connection.bind(" + requestID + "Request);"); 344 lineList.add(indent + " // The bind was processed successfully."); 345 lineList.add(indent + '}'); 346 lineList.add(indent + "catch (LDAPException e)"); 347 lineList.add(indent + '{'); 348 lineList.add(indent + " // The bind failed. Maybe the following will " + 349 "help explain why."); 350 lineList.add(indent + " // Note that the connection is now likely in " + 351 "an unauthenticated state."); 352 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 353 lineList.add(indent + " String message = e.getMessage();"); 354 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 355 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 356 lineList.add(indent + " Control[] responseControls = " + 357 "e.getResponseControls();"); 358 lineList.add(indent + '}'); 359 } 360 } 361}