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}