001/* 002 * Copyright 2008-2022 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2008-2022 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) 2008-2022 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.unboundidds.controls; 037 038 039 040import com.unboundid.asn1.ASN1Element; 041import com.unboundid.asn1.ASN1OctetString; 042import com.unboundid.asn1.ASN1Sequence; 043import com.unboundid.ldap.sdk.Control; 044import com.unboundid.ldap.sdk.LDAPException; 045import com.unboundid.ldap.sdk.ResultCode; 046import com.unboundid.util.NotMutable; 047import com.unboundid.util.NotNull; 048import com.unboundid.util.Nullable; 049import com.unboundid.util.ThreadSafety; 050import com.unboundid.util.ThreadSafetyLevel; 051 052import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*; 053 054 055 056/** 057 * This class defines an intermediate client request control, which can be used 058 * to provide a server with information about the client and any downstream 059 * clients that it may have. It can be used to help trace operations from the 060 * client to the directory server, potentially through any intermediate hops 061 * (like proxy servers) that may also support the intermediate client controls. 062 * <BR> 063 * <BLOCKQUOTE> 064 * <B>NOTE:</B> This class, and other classes within the 065 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 066 * supported for use against Ping Identity, UnboundID, and 067 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 068 * for proprietary functionality or for external specifications that are not 069 * considered stable or mature enough to be guaranteed to work in an 070 * interoperable way with other types of LDAP servers. 071 * </BLOCKQUOTE> 072 * <BR> 073 * This control is not based on any public standard. It was originally 074 * developed for use with the Ping Identity, UnboundID, and Nokia/Alcatel-Lucent 075 * 8661 Directory Server. The value of this control uses the following 076 * encoding: 077 * <BR><BR> 078 * <PRE> 079 * IntermediateClientRequest ::= SEQUENCE { 080 * downstreamRequest [0] IntermediateClientRequest OPTIONAL, 081 * downstreamClientAddress [1] OCTET STRING OPTIONAL, 082 * downstreamClientSecure [2] BOOLEAN DEFAULT FALSE, 083 * clientIdentity [3] authzId OPTIONAL, 084 * clientName [4] OCTET STRING OPTIONAL, 085 * clientSessionID [5] OCTET STRING OPTIONAL, 086 * clientRequestID [6] OCTET STRING OPTIONAL, 087 * ... } 088 * </PRE> 089 * <H2>Example</H2> 090 * The following example demonstrates the use of the intermediate client 091 * controls to perform a search operation in the directory server. The request 092 * will be from an application named "my client" with a session ID of 093 * "session123" and a request ID of "request456": 094 * <PRE> 095 * SearchRequest searchRequest = new SearchRequest("dc=example,dc=com", 096 * SearchScope.SUB, Filter.createEqualityFilter("uid", "john.doe")); 097 * searchRequest.addControl(new IntermediateClientRequestControl(null, null, 098 * null, null, "my client", "session123", "request456")); 099 * SearchResult searchResult = connection.search(searchRequest); 100 * 101 * IntermediateClientResponseControl c = 102 * IntermediateClientResponseControl.get(searchResult); 103 * if (c != null) 104 * { 105 * // There was an intermediate client response control. 106 * IntermediateClientResponseValue responseValue = c.getResponseValue(); 107 * } 108 * </PRE> 109 */ 110@NotMutable() 111@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 112public final class IntermediateClientRequestControl 113 extends Control 114{ 115 /** 116 * The OID (1.3.6.1.4.1.30221.2.5.2) for the intermediate client request 117 * control. 118 */ 119 @NotNull public static final String INTERMEDIATE_CLIENT_REQUEST_OID = 120 "1.3.6.1.4.1.30221.2.5.2"; 121 122 123 124 /** 125 * The serial version UID for this serializable class. 126 */ 127 private static final long serialVersionUID = 4883725840393001578L; 128 129 130 131 // The value for this intermediate client request control. 132 @NotNull private final IntermediateClientRequestValue value; 133 134 135 136 /** 137 * Creates a new intermediate client request control with the provided 138 * information. It will be marked critical. 139 * 140 * @param downstreamRequest A wrapped intermediate client request from 141 * a downstream client. It may be 142 * {@code null} if there is no downstream 143 * request. 144 * @param downstreamClientAddress The IP address or resolvable name of the 145 * downstream client system. It may be 146 * {@code null} if there is no downstream 147 * client or its address is not available. 148 * @param downstreamClientSecure Indicates whether communication with the 149 * downstream client is secure. It may be 150 * {@code null} if there is no downstream 151 * client or it is not known whether the 152 * communication is secure. 153 * @param clientIdentity The requested client authorization 154 * identity. It may be {@code null} if there 155 * is no requested authorization identity. 156 * @param clientName An identifier string that summarizes the 157 * client application that created this 158 * intermediate client request. It may be 159 * {@code null} if that information is not 160 * available. 161 * @param clientSessionID A string that may be used to identify the 162 * session in the client application. It may 163 * be {@code null} if there is no available 164 * session identifier. 165 * @param clientRequestID A string that may be used to identify the 166 * request in the client application. It may 167 * be {@code null} if there is no available 168 * request identifier. 169 */ 170 public IntermediateClientRequestControl( 171 @Nullable final IntermediateClientRequestValue downstreamRequest, 172 @Nullable final String downstreamClientAddress, 173 @Nullable final Boolean downstreamClientSecure, 174 @Nullable final String clientIdentity, 175 @Nullable final String clientName, 176 @Nullable final String clientSessionID, 177 @Nullable final String clientRequestID) 178 { 179 this(true, 180 new IntermediateClientRequestValue(downstreamRequest, 181 downstreamClientAddress, downstreamClientSecure, 182 clientIdentity, clientName, clientSessionID, 183 clientRequestID)); 184 } 185 186 187 188 /** 189 * Creates a new intermediate client request control with the provided value. 190 * It will be marked critical. 191 * 192 * @param value The value to use for this intermediate client request 193 * control. It must not be {@code null}. 194 */ 195 public IntermediateClientRequestControl( 196 @NotNull final IntermediateClientRequestValue value) 197 { 198 this(true, value); 199 } 200 201 202 203 /** 204 * Creates a new intermediate client request control with the provided value. 205 * 206 * @param isCritical Indicates whether the control should be marked 207 * critical. 208 * @param value The value to use for this intermediate client request 209 * control. It must not be {@code null}. 210 */ 211 public IntermediateClientRequestControl(final boolean isCritical, 212 @NotNull final IntermediateClientRequestValue value) 213 { 214 super(INTERMEDIATE_CLIENT_REQUEST_OID, isCritical, 215 new ASN1OctetString(value.encode().encode())); 216 217 this.value = value; 218 } 219 220 221 222 /** 223 * Creates a new intermediate client request control which is decoded from the 224 * provided generic control. 225 * 226 * @param control The generic control to be decoded as an intermediate 227 * client request control. 228 * 229 * @throws LDAPException If the provided control cannot be decoded as an 230 * intermediate client request control. 231 */ 232 public IntermediateClientRequestControl(@NotNull final Control control) 233 throws LDAPException 234 { 235 super(control); 236 237 final ASN1OctetString controlValue = control.getValue(); 238 if (controlValue == null) 239 { 240 throw new LDAPException(ResultCode.DECODING_ERROR, 241 ERR_ICREQ_CONTROL_NO_VALUE.get()); 242 } 243 244 final ASN1Sequence valueSequence; 245 try 246 { 247 final ASN1Element valueElement = 248 ASN1Element.decode(controlValue.getValue()); 249 valueSequence = ASN1Sequence.decodeAsSequence(valueElement); 250 } 251 catch (final Exception e) 252 { 253 throw new LDAPException(ResultCode.DECODING_ERROR, 254 ERR_ICREQ_CONTROL_VALUE_NOT_SEQUENCE.get(e), e); 255 } 256 257 value = IntermediateClientRequestValue.decode(valueSequence); 258 } 259 260 261 262 /** 263 * Retrieves the value for this intermediate client request. 264 * 265 * @return The value for this intermediate client request. 266 */ 267 @NotNull() 268 public IntermediateClientRequestValue getRequestValue() 269 { 270 return value; 271 } 272 273 274 275 /** 276 * Retrieves the wrapped request from a downstream client, if available. 277 * 278 * @return The wrapped request from a downstream client, or {@code null} if 279 * there is none. 280 */ 281 @Nullable() 282 public IntermediateClientRequestValue getDownstreamRequest() 283 { 284 return value.getDownstreamRequest(); 285 } 286 287 288 289 /** 290 * Retrieves the requested client authorization identity, if available. 291 * 292 * @return The requested client authorization identity, or {@code null} if 293 * there is none. 294 */ 295 @Nullable() 296 public String getClientIdentity() 297 { 298 return value.getClientIdentity(); 299 } 300 301 302 303 /** 304 * Retrieves the IP address or resolvable name of the downstream client 305 * system, if available. 306 * 307 * @return The IP address or resolvable name of the downstream client system, 308 * or {@code null} if there is no downstream client or its address is 309 * not available. 310 */ 311 @Nullable() 312 public String getDownstreamClientAddress() 313 { 314 return value.getDownstreamClientAddress(); 315 } 316 317 318 319 /** 320 * Indicates whether the communication with the communication with the 321 * downstream client is secure (i.e., whether communication between the 322 * client application and the downstream client is safe from interpretation or 323 * undetectable alteration by a third party observer or interceptor). 324 * 325 * 326 * @return {@code Boolean.TRUE} if communication with the downstream client 327 * is secure, {@code Boolean.FALSE} if it is not secure, or 328 * {@code null} if there is no downstream client or it is not known 329 * whether the communication is secure. 330 */ 331 @Nullable() 332 public Boolean downstreamClientSecure() 333 { 334 return value.downstreamClientSecure(); 335 } 336 337 338 339 /** 340 * Retrieves a string that identifies the client application that created this 341 * intermediate client request value. 342 * 343 * @return A string that may be used to identify the client application that 344 * created this intermediate client request value. 345 */ 346 @Nullable() 347 public String getClientName() 348 { 349 return value.getClientName(); 350 } 351 352 353 354 /** 355 * Retrieves a string that may be used to identify the session in the client 356 * application. 357 * 358 * @return A string that may be used to identify the session in the client 359 * application, or {@code null} if there is none. 360 */ 361 @Nullable() 362 public String getClientSessionID() 363 { 364 return value.getClientSessionID(); 365 } 366 367 368 369 /** 370 * Retrieves a string that may be used to identify the request in the client 371 * application. 372 * 373 * @return A string that may be used to identify the request in the client 374 * application, or {@code null} if there is none. 375 */ 376 @Nullable() 377 public String getClientRequestID() 378 { 379 return value.getClientRequestID(); 380 } 381 382 383 384 /** 385 * {@inheritDoc} 386 */ 387 @Override() 388 @NotNull() 389 public String getControlName() 390 { 391 return INFO_CONTROL_NAME_INTERMEDIATE_CLIENT_REQUEST.get(); 392 } 393 394 395 396 /** 397 * {@inheritDoc} 398 */ 399 @Override() 400 public void toString(@NotNull final StringBuilder buffer) 401 { 402 buffer.append("IntermediateClientRequestControl(isCritical="); 403 buffer.append(isCritical()); 404 buffer.append(", value="); 405 value.toString(buffer); 406 buffer.append(')'); 407 } 408}