001/*
002 * Copyright 2009-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2019 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
046 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
047 *   for proprietary functionality or for external specifications that are not
048 *   considered stable or mature enough to be guaranteed to work in an
049 *   interoperable way with 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.isEmpty())
199    {
200      referralURLs = Collections.emptyList();
201    }
202    else
203    {
204      final LinkedList<String> refs = new LinkedList<>();
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<>();
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.isEmpty())
241    {
242      serversAccessed = Collections.emptyList();
243    }
244    else
245    {
246      final LinkedList<String> servers = new LinkedList<>();
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.isEmpty())
261    {
262      usedPrivileges = Collections.emptyList();
263    }
264    else
265    {
266      final LinkedList<String> privileges = new LinkedList<>();
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.isEmpty())
280    {
281      preAuthZUsedPrivileges = Collections.emptyList();
282    }
283    else
284    {
285      final LinkedList<String> privileges = new LinkedList<>();
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.isEmpty())
297    {
298      missingPrivileges = Collections.emptyList();
299    }
300    else
301    {
302      final LinkedList<String> privileges = new LinkedList<>();
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  @Override()
322  public ResultCode getResultCode()
323  {
324    return resultCode;
325  }
326
327
328
329  /**
330   * Retrieves the diagnostic message for the operation.
331   *
332   * @return  The diagnostic message for the operation, or {@code null} if it is
333   *          not included in the log message.
334   */
335  @Override()
336  public String getDiagnosticMessage()
337  {
338    return diagnosticMessage;
339  }
340
341
342
343  /**
344   * Retrieves a message with additional information about the result of the
345   * operation.
346   *
347   * @return  A message with additional information about the result of the
348   *          operation, or {@code null} if it is not included in the log
349   *          message.
350   */
351  @Override()
352  public String getAdditionalInformation()
353  {
354    return additionalInformation;
355  }
356
357
358
359  /**
360   * Retrieves the matched DN for the operation.
361   *
362   * @return  The matched DN for the operation, or {@code null} if it is not
363   *          included in the log message.
364   */
365  @Override()
366  public String getMatchedDN()
367  {
368    return matchedDN;
369  }
370
371
372
373  /**
374   * Retrieves the list of referral URLs for the operation.
375   *
376   * @return  The list of referral URLs for the operation, or an empty list if
377   *          it is not included in the log message.
378   */
379  @Override()
380  public List<String> getReferralURLs()
381  {
382    return referralURLs;
383  }
384
385
386
387  /**
388   * Retrieves the number of intermediate response messages returned in the
389   * course of processing the operation.
390   *
391   * @return  The number of intermediate response messages returned to the
392   *          client in the course of processing the operation, or {@code null}
393   *          if it is not included in the log message.
394   */
395  @Override()
396  public Long getIntermediateResponsesReturned()
397  {
398    return intermediateResponsesReturned;
399  }
400
401
402
403  /**
404   * Retrieves the length of time in milliseconds required to process the
405   * operation.
406   *
407   * @return  The length of time in milliseconds required to process the
408   *          operation, or {@code null} if it is not included in the log
409   *          message.
410   */
411  @Override()
412  public Double getProcessingTimeMillis()
413  {
414    return processingTime;
415  }
416
417
418
419  /**
420   * Retrieves the length of time in milliseconds the operation was required to
421   * wait on the work queue.
422   *
423   * @return  The length of time in milliseconds the operation was required to
424   *          wait on the work queue, or {@code null} if it is not included in
425   *          the log message.
426   */
427  @Override()
428  public Double getQueueTimeMillis()
429  {
430    return queueTime;
431  }
432
433
434
435  /**
436   * Retrieves the OIDs of any response controls contained in the log message.
437   *
438   * @return  The OIDs of any response controls contained in the log message, or
439   *          an empty list if it is not included in the log message.
440   */
441  @Override()
442  public List<String> getResponseControlOIDs()
443  {
444    return responseControlOIDs;
445  }
446
447
448
449  /**
450   * Retrieves a list of the additional servers that were accessed in the course
451   * of processing the operation.  For example, if the access log message is
452   * from a Directory Proxy Server instance, then this may contain a list of the
453   * backend servers used to process the operation.
454   *
455   * @return  A list of the additional servers that were accessed in the course
456   *          of processing the operation, or an empty list if it is not
457   *          included in the log message.
458   */
459  @Override()
460  public List<String> getServersAccessed()
461  {
462    return serversAccessed;
463  }
464
465
466
467  /**
468   * Indicates whether the server accessed any uncached data in the course of
469   * processing the operation.
470   *
471   * @return  {@code true} if the server was known to access uncached data in
472   *          the course of processing the operation, {@code false} if the
473   *          server was known not to access uncached data, or {@code null} if
474   *          it is not included in the log message (and the server likely did
475   *          not access uncached data).
476   */
477  public Boolean getUncachedDataAccessed()
478  {
479    return uncachedDataAccessed;
480  }
481
482
483
484  /**
485   * Retrieves the content of the intermediate client result for the
486   * operation.
487   *
488   * @return  The content of the intermediate client result for the operation,
489   *          or {@code null} if it is not included in the log message.
490   */
491  @Override()
492  public String getIntermediateClientResult()
493  {
494    return intermediateClientResult;
495  }
496
497
498
499  /**
500   * Retrieves the DN of the user authenticated by the bind operation.
501   *
502   * @return  The DN of the user authenticated by the bind operation, or
503   *          {@code null} if it is not included in the log message.
504   */
505  public String getAuthenticationDN()
506  {
507    return authDN;
508  }
509
510
511
512  /**
513   * Retrieves the DN of the alternate authorization identity for the bind
514   * operation.
515   *
516   * @return  The DN of the alternate authorization identity for the bind
517   *          operation, or {@code null} if it is not included in the log
518   *          message.
519   */
520  public String getAuthorizationDN()
521  {
522    return authzDN;
523  }
524
525
526
527  /**
528   * Retrieves the numeric identifier for the authentication failure reason.
529   *
530   * @return  The numeric identifier for the authentication failure reason, or
531   *          {@code null} if it is not included in the log message.
532   */
533  public Long getAuthenticationFailureID()
534  {
535    return authFailureID;
536  }
537
538
539
540  /**
541   * Retrieves a message with information about the reason that the
542   * authentication attempt failed.
543   *
544   * @return  A message with information about the reason that the
545   *          authentication attempt failed, or {@code null} if it is not
546   *          included in the log message.
547   */
548  public String getAuthenticationFailureReason()
549  {
550    return authFailureReason;
551  }
552
553
554
555  /**
556   * Indicates whether a retired password was used in the course of processing
557   * the bind.
558   *
559   * @return  {@code true} if a retired password was used in the course of
560   *          processing the bind, {@code false} if a retired password was not
561   *          used in the course of processing the bind, or {@code null} if
562   *          this was not included in the log message (and a retired password
563   *          was likely not used in the course of processing the operation).
564   */
565  public Boolean getRetiredPasswordUsed()
566  {
567    return retiredPasswordUsed;
568  }
569
570
571
572  /**
573   * Retrieves the address of the backend server to which the request has been
574   * forwarded.
575   *
576   * @return  The address of the backend server to which the request has been
577   *          forwarded, or {@code null} if it is not included in the log
578   *          message.
579   */
580  public String getTargetHost()
581  {
582    return targetHost;
583  }
584
585
586
587  /**
588   * Retrieves the port of the backend server to which the request has been
589   * forwarded.
590   *
591   * @return  The port 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 Integer getTargetPort()
596  {
597    return targetPort;
598  }
599
600
601
602  /**
603   * Retrieves the protocol used to forward the request to the backend server.
604   *
605   * @return  The protocol used to forward the request to the backend server, or
606   *          {@code null} if it is not included in the log message.
607   */
608  public String getTargetProtocol()
609  {
610    return targetProtocol;
611  }
612
613
614
615  /**
616   * Retrieves the name of the client connection policy that was selected for
617   * the client connection.
618   *
619   * @return  The name of the client connection policy that was selected for the
620   *          client connection, or {@code null} if it is not included in the
621   *          log message.
622   */
623  public String getClientConnectionPolicy()
624  {
625    return clientConnectionPolicy;
626  }
627
628
629
630  /**
631   * Retrieves the names of any privileges used during the course of processing
632   * the operation.
633   *
634   * @return  The names of any privileges used during the course of processing
635   *          the operation, or an empty list if no privileges were used or this
636   *          is not included in the log message.
637   */
638  public List<String> getUsedPrivileges()
639  {
640    return usedPrivileges;
641  }
642
643
644
645  /**
646   * Retrieves the names of any privileges used during the course of processing
647   * the operation before an alternate authorization identity was assigned.
648   *
649   * @return  The names of any privileges used during the course of processing
650   *          the operation before an alternate authorization identity was
651   *          assigned, or an empty list if no privileges were used or this is
652   *          not included in the log message.
653   */
654  public List<String> getPreAuthorizationUsedPrivileges()
655  {
656    return preAuthZUsedPrivileges;
657  }
658
659
660
661  /**
662   * Retrieves the names of any privileges that would have been required for
663   * processing the operation but that the requester did not have.
664   *
665   * @return  The names of any privileges that would have been required for
666   *          processing the operation but that the requester did not have, or
667   *          an empty list if there were no missing privileges or this is not
668   *          included in the log message.
669   */
670  public List<String> getMissingPrivileges()
671  {
672    return missingPrivileges;
673  }
674
675
676
677  /**
678   * {@inheritDoc}
679   */
680  @Override()
681  public AccessLogMessageType getMessageType()
682  {
683    return AccessLogMessageType.RESULT;
684  }
685}