001/* 002 * Copyright 2009-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 Ping Identity Corporation 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.unboundidds.logs; 022 023 024 025import java.util.Collections; 026import java.util.LinkedList; 027import java.util.List; 028import java.util.StringTokenizer; 029 030import com.unboundid.ldap.sdk.ResultCode; 031import com.unboundid.util.NotMutable; 032import com.unboundid.util.ThreadSafety; 033import com.unboundid.util.ThreadSafetyLevel; 034 035 036 037/** 038 * This class provides a data structure that holds information about a log 039 * message that may appear in the Directory Server access log about the result 040 * of a bind operation processed by the Directory Server. 041 * <BR> 042 * <BLOCKQUOTE> 043 * <B>NOTE:</B> This class, and other classes within the 044 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 045 * supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661 046 * server products. These classes provide support for proprietary 047 * functionality or for external specifications that are not considered stable 048 * or mature enough to be guaranteed to work in an interoperable way with 049 * other types of LDAP servers. 050 * </BLOCKQUOTE> 051 */ 052@NotMutable() 053@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 054public final class BindResultAccessLogMessage 055 extends BindRequestAccessLogMessage 056 implements OperationResultAccessLogMessage 057{ 058 /** 059 * The serial version UID for this serializable class. 060 */ 061 private static final long serialVersionUID = -5612410738721878134L; 062 063 064 065 // Indicates whether a retired password was used to perform the bind. 066 private final Boolean retiredPasswordUsed; 067 068 // Indicates whether the any uncached data was accessed in the course of 069 // processing this operation. 070 private final Boolean uncachedDataAccessed; 071 072 // The processing time for the operation. 073 private final Double processingTime; 074 075 // The queue time for the operation. 076 private final Double queueTime; 077 078 // The list of privileges required for processing the operation that the 079 // requester did not have. 080 private final List<String> missingPrivileges; 081 082 // The list of privileges used during the course of processing the operation 083 // before an alternate authorization identity was assigned. 084 private final List<String> preAuthZUsedPrivileges; 085 086 // The list of referral URLs for the operation. 087 private final List<String> referralURLs; 088 089 // The list of response control OIDs for the operation. 090 private final List<String> responseControlOIDs; 091 092 // The list of servers accessed while processing the operation. 093 private final List<String> serversAccessed; 094 095 // The list of privileges used during the course of processing the operation. 096 private final List<String> usedPrivileges; 097 098 // The numeric identifier for the authentication failure reason. 099 private final Long authFailureID; 100 101 // The number of intermediate response messages returned to the client. 102 private final Long intermediateResponsesReturned; 103 104 // The result code for the operation. 105 private final ResultCode resultCode; 106 107 // Additional information about the operation result. 108 private final String additionalInformation; 109 110 // The DN of the authenticated user. 111 private final String authDN; 112 113 // A message with information about the reason for the authentication failure. 114 private final String authFailureReason; 115 116 // The DN of the alternate authorization identity. 117 private final String authzDN; 118 119 // The name of the client connection policy selected for the client. 120 private final String clientConnectionPolicy; 121 122 // The diagnostic message for the operation. 123 private final String diagnosticMessage; 124 125 // The intermediate client result for the operation. 126 private final String intermediateClientResult; 127 128 // The matched DN for the operation. 129 private final String matchedDN; 130 131 // The port of the backend server to which the request has been forwarded. 132 private final Integer targetPort; 133 134 // The address of the backend server to which the request has been forwarded. 135 private final String targetHost; 136 137 // The protocol used to forward the request to the backend server. 138 private final String targetProtocol; 139 140 141 142 /** 143 * Creates a new bind result access log message from the provided message 144 * string. 145 * 146 * @param s The string to be parsed as a bind result access log message. 147 * 148 * @throws LogException If the provided string cannot be parsed as a valid 149 * log message. 150 */ 151 public BindResultAccessLogMessage(final String s) 152 throws LogException 153 { 154 this(new LogMessage(s)); 155 } 156 157 158 159 /** 160 * Creates a new bind result access log message from the provided log message. 161 * 162 * @param m The log message to be parsed as a bind result access log 163 * message. 164 */ 165 public BindResultAccessLogMessage(final LogMessage m) 166 { 167 super(m); 168 169 diagnosticMessage = getNamedValue("message"); 170 additionalInformation = getNamedValue("additionalInfo"); 171 matchedDN = getNamedValue("matchedDN"); 172 processingTime = getNamedValueAsDouble("etime"); 173 queueTime = getNamedValueAsDouble("qtime"); 174 intermediateClientResult = getNamedValue("from"); 175 authDN = getNamedValue("authDN"); 176 authzDN = getNamedValue("authzDN"); 177 authFailureID = getNamedValueAsLong("authFailureID"); 178 authFailureReason = getNamedValue("authFailureReason"); 179 targetHost = getNamedValue("targetHost"); 180 targetPort = getNamedValueAsInteger("targetPort"); 181 targetProtocol = getNamedValue("targetProtocol"); 182 clientConnectionPolicy = getNamedValue("clientConnectionPolicy"); 183 184 intermediateResponsesReturned = 185 getNamedValueAsLong("intermediateResponsesReturned"); 186 187 final Integer rcInteger = getNamedValueAsInteger("resultCode"); 188 if (rcInteger == null) 189 { 190 resultCode = null; 191 } 192 else 193 { 194 resultCode = ResultCode.valueOf(rcInteger); 195 } 196 197 final String refStr = getNamedValue("referralURLs"); 198 if ((refStr == null) || (refStr.length() == 0)) 199 { 200 referralURLs = Collections.emptyList(); 201 } 202 else 203 { 204 final LinkedList<String> refs = new LinkedList<String>(); 205 int startPos = 0; 206 while (true) 207 { 208 final int commaPos = refStr.indexOf(",ldap", startPos); 209 if (commaPos < 0) 210 { 211 refs.add(refStr.substring(startPos)); 212 break; 213 } 214 else 215 { 216 refs.add(refStr.substring(startPos, commaPos)); 217 startPos = commaPos+1; 218 } 219 } 220 referralURLs = Collections.unmodifiableList(refs); 221 } 222 223 final String controlStr = getNamedValue("responseControls"); 224 if (controlStr == null) 225 { 226 responseControlOIDs = Collections.emptyList(); 227 } 228 else 229 { 230 final LinkedList<String> controlList = new LinkedList<String>(); 231 final StringTokenizer t = new StringTokenizer(controlStr, ","); 232 while (t.hasMoreTokens()) 233 { 234 controlList.add(t.nextToken()); 235 } 236 responseControlOIDs = Collections.unmodifiableList(controlList); 237 } 238 239 final String serversAccessedStr = getNamedValue("serversAccessed"); 240 if ((serversAccessedStr == null) || (serversAccessedStr.length() == 0)) 241 { 242 serversAccessed = Collections.emptyList(); 243 } 244 else 245 { 246 final LinkedList<String> servers = new LinkedList<String>(); 247 final StringTokenizer tokenizer = 248 new StringTokenizer(serversAccessedStr, ","); 249 while (tokenizer.hasMoreTokens()) 250 { 251 servers.add(tokenizer.nextToken()); 252 } 253 serversAccessed = Collections.unmodifiableList(servers); 254 } 255 256 uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed"); 257 retiredPasswordUsed = getNamedValueAsBoolean("retiredPasswordUsed"); 258 259 final String usedPrivilegesStr = getNamedValue("usedPrivileges"); 260 if ((usedPrivilegesStr == null) || (usedPrivilegesStr.length() == 0)) 261 { 262 usedPrivileges = Collections.emptyList(); 263 } 264 else 265 { 266 final LinkedList<String> privileges = new LinkedList<String>(); 267 final StringTokenizer tokenizer = 268 new StringTokenizer(usedPrivilegesStr, ","); 269 while (tokenizer.hasMoreTokens()) 270 { 271 privileges.add(tokenizer.nextToken()); 272 } 273 usedPrivileges = Collections.unmodifiableList(privileges); 274 } 275 276 final String preAuthZUsedPrivilegesStr = 277 getNamedValue("preAuthZUsedPrivileges"); 278 if ((preAuthZUsedPrivilegesStr == null) || 279 (preAuthZUsedPrivilegesStr.length() == 0)) 280 { 281 preAuthZUsedPrivileges = Collections.emptyList(); 282 } 283 else 284 { 285 final LinkedList<String> privileges = new LinkedList<String>(); 286 final StringTokenizer tokenizer = 287 new StringTokenizer(preAuthZUsedPrivilegesStr, ","); 288 while (tokenizer.hasMoreTokens()) 289 { 290 privileges.add(tokenizer.nextToken()); 291 } 292 preAuthZUsedPrivileges = Collections.unmodifiableList(privileges); 293 } 294 295 final String missingPrivilegesStr = getNamedValue("missingPrivileges"); 296 if ((missingPrivilegesStr == null) || (missingPrivilegesStr.length() == 0)) 297 { 298 missingPrivileges = Collections.emptyList(); 299 } 300 else 301 { 302 final LinkedList<String> privileges = new LinkedList<String>(); 303 final StringTokenizer tokenizer = 304 new StringTokenizer(missingPrivilegesStr, ","); 305 while (tokenizer.hasMoreTokens()) 306 { 307 privileges.add(tokenizer.nextToken()); 308 } 309 missingPrivileges = Collections.unmodifiableList(privileges); 310 } 311 } 312 313 314 315 /** 316 * Retrieves the result code for the operation. 317 * 318 * @return The result code for the operation, or {@code null} if it is not 319 * included in the log message. 320 */ 321 public ResultCode getResultCode() 322 { 323 return resultCode; 324 } 325 326 327 328 /** 329 * Retrieves the diagnostic message for the operation. 330 * 331 * @return The diagnostic message for the operation, or {@code null} if it is 332 * not included in the log message. 333 */ 334 public String getDiagnosticMessage() 335 { 336 return diagnosticMessage; 337 } 338 339 340 341 /** 342 * Retrieves a message with additional information about the result of the 343 * operation. 344 * 345 * @return A message with additional information about the result of the 346 * operation, or {@code null} if it is not included in the log 347 * message. 348 */ 349 public String getAdditionalInformation() 350 { 351 return additionalInformation; 352 } 353 354 355 356 /** 357 * Retrieves the matched DN for the operation. 358 * 359 * @return The matched DN for the operation, or {@code null} if it is not 360 * included in the log message. 361 */ 362 public String getMatchedDN() 363 { 364 return matchedDN; 365 } 366 367 368 369 /** 370 * Retrieves the list of referral URLs for the operation. 371 * 372 * @return The list of referral URLs for the operation, or an empty list if 373 * it is not included in the log message. 374 */ 375 public List<String> getReferralURLs() 376 { 377 return referralURLs; 378 } 379 380 381 382 /** 383 * Retrieves the number of intermediate response messages returned in the 384 * course of processing the operation. 385 * 386 * @return The number of intermediate response messages returned to the 387 * client in the course of processing the operation, or {@code null} 388 * if it is not included in the log message. 389 */ 390 public Long getIntermediateResponsesReturned() 391 { 392 return intermediateResponsesReturned; 393 } 394 395 396 397 /** 398 * Retrieves the length of time in milliseconds required to process the 399 * operation. 400 * 401 * @return The length of time in milliseconds required to process the 402 * operation, or {@code null} if it is not included in the log 403 * message. 404 */ 405 public Double getProcessingTimeMillis() 406 { 407 return processingTime; 408 } 409 410 411 412 /** 413 * Retrieves the length of time in milliseconds the operation was required to 414 * wait on the work queue. 415 * 416 * @return The length of time in milliseconds the operation was required to 417 * wait on the work queue, or {@code null} if it is not included in 418 * the log message. 419 */ 420 public Double getQueueTimeMillis() 421 { 422 return queueTime; 423 } 424 425 426 427 /** 428 * Retrieves the OIDs of any response controls contained in the log message. 429 * 430 * @return The OIDs of any response controls contained in the log message, or 431 * an empty list if it is not included in the log message. 432 */ 433 public List<String> getResponseControlOIDs() 434 { 435 return responseControlOIDs; 436 } 437 438 439 440 /** 441 * Retrieves a list of the additional servers that were accessed in the course 442 * of processing the operation. For example, if the access log message is 443 * from a Directory Proxy Server instance, then this may contain a list of the 444 * backend servers used to process the operation. 445 * 446 * @return A list of the additional servers that were accessed in the course 447 * of processing the operation, or an empty list if it is not 448 * included in the log message. 449 */ 450 public List<String> getServersAccessed() 451 { 452 return serversAccessed; 453 } 454 455 456 457 /** 458 * Indicates whether the server accessed any uncached data in the course of 459 * processing the operation. 460 * 461 * @return {@code true} if the server was known to access uncached data in 462 * the course of processing the operation, {@code false} if the 463 * server was known not to access uncached data, or {@code null} if 464 * it is not included in the log message (and the server likely did 465 * not access uncached data). 466 */ 467 public Boolean getUncachedDataAccessed() 468 { 469 return uncachedDataAccessed; 470 } 471 472 473 474 /** 475 * Retrieves the content of the intermediate client result for the 476 * operation. 477 * 478 * @return The content of the intermediate client result for the operation, 479 * or {@code null} if it is not included in the log message. 480 */ 481 public String getIntermediateClientResult() 482 { 483 return intermediateClientResult; 484 } 485 486 487 488 /** 489 * Retrieves the DN of the user authenticated by the bind operation. 490 * 491 * @return The DN of the user authenticated by the bind operation, or 492 * {@code null} if it is not included in the log message. 493 */ 494 public String getAuthenticationDN() 495 { 496 return authDN; 497 } 498 499 500 501 /** 502 * Retrieves the DN of the alternate authorization identity for the bind 503 * operation. 504 * 505 * @return The DN of the alternate authorization identity for the bind 506 * operation, or {@code null} if it is not included in the log 507 * message. 508 */ 509 public String getAuthorizationDN() 510 { 511 return authzDN; 512 } 513 514 515 516 /** 517 * Retrieves the numeric identifier for the authentication failure reason. 518 * 519 * @return The numeric identifier for the authentication failure reason, or 520 * {@code null} if it is not included in the log message. 521 */ 522 public Long getAuthenticationFailureID() 523 { 524 return authFailureID; 525 } 526 527 528 529 /** 530 * Retrieves a message with information about the reason that the 531 * authentication attempt failed. 532 * 533 * @return A message with information about the reason that the 534 * authentication attempt failed, or {@code null} if it is not 535 * included in the log message. 536 */ 537 public String getAuthenticationFailureReason() 538 { 539 return authFailureReason; 540 } 541 542 543 544 /** 545 * Indicates whether a retired password was used in the course of processing 546 * the bind. 547 * 548 * @return {@code true} if a retired password was used in the course of 549 * processing the bind, {@code false} if a retired password was not 550 * used in the course of processing the bind, or {@code null} if 551 * this was not included in the log message (and a retired password 552 * was likely not used in the course of processing the operation). 553 */ 554 public Boolean getRetiredPasswordUsed() 555 { 556 return retiredPasswordUsed; 557 } 558 559 560 561 /** 562 * Retrieves the address of the backend server to which the request has been 563 * forwarded. 564 * 565 * @return The address of the backend server to which the request has been 566 * forwarded, or {@code null} if it is not included in the log 567 * message. 568 */ 569 public String getTargetHost() 570 { 571 return targetHost; 572 } 573 574 575 576 /** 577 * Retrieves the port of the backend server to which the request has been 578 * forwarded. 579 * 580 * @return The port of the backend server to which the request has been 581 * forwarded, or {@code null} if it is not included in the log 582 * message. 583 */ 584 public Integer getTargetPort() 585 { 586 return targetPort; 587 } 588 589 590 591 /** 592 * Retrieves the protocol used to forward the request to the backend server. 593 * 594 * @return The protocol used to forward the request to the backend server, or 595 * {@code null} if it is not included in the log message. 596 */ 597 public String getTargetProtocol() 598 { 599 return targetProtocol; 600 } 601 602 603 604 /** 605 * Retrieves the name of the client connection policy that was selected for 606 * the client connection. 607 * 608 * @return The name of the client connection policy that was selected for the 609 * client connection, or {@code null} if it is not included in the 610 * log message. 611 */ 612 public String getClientConnectionPolicy() 613 { 614 return clientConnectionPolicy; 615 } 616 617 618 619 /** 620 * Retrieves the names of any privileges used during the course of processing 621 * the operation. 622 * 623 * @return The names of any privileges used during the course of processing 624 * the operation, or an empty list if no privileges were used or this 625 * is not included in the log message. 626 */ 627 public List<String> getUsedPrivileges() 628 { 629 return usedPrivileges; 630 } 631 632 633 634 /** 635 * Retrieves the names of any privileges used during the course of processing 636 * the operation before an alternate authorization identity was assigned. 637 * 638 * @return The names of any privileges used during the course of processing 639 * the operation before an alternate authorization identity was 640 * assigned, or an empty list if no privileges were used or this is 641 * not included in the log message. 642 */ 643 public List<String> getPreAuthorizationUsedPrivileges() 644 { 645 return preAuthZUsedPrivileges; 646 } 647 648 649 650 /** 651 * Retrieves the names of any privileges that would have been required for 652 * processing the operation but that the requester did not have. 653 * 654 * @return The names of any privileges that would have been required for 655 * processing the operation but that the requester did not have, or 656 * an empty list if there were no missing privileges or this is not 657 * included in the log message. 658 */ 659 public List<String> getMissingPrivileges() 660 { 661 return missingPrivileges; 662 } 663 664 665 666 /** 667 * {@inheritDoc} 668 */ 669 @Override() 670 public AccessLogMessageType getMessageType() 671 { 672 return AccessLogMessageType.RESULT; 673 } 674}