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