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