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