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}