001/*
002 * Copyright 2015-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.controls;
022
023
024
025import java.io.Serializable;
026import java.util.StringTokenizer;
027
028import com.unboundid.ldap.sdk.LDAPException;
029import com.unboundid.ldap.sdk.ResultCode;
030import com.unboundid.util.Debug;
031import com.unboundid.util.NotMutable;
032import com.unboundid.util.StaticUtils;
033import com.unboundid.util.ThreadSafety;
034import com.unboundid.util.ThreadSafetyLevel;
035import com.unboundid.util.Validator;
036
037import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
038
039
040
041/**
042 * This class defines a data structure that will provide information about
043 * errors that could cause an authentication attempt to fail.  It includes a
044 * number of predefined failure types, but but also allows for the possibility
045 * of additional failure types that have not been defined.
046 * <BR>
047 * <BLOCKQUOTE>
048 *   <B>NOTE:</B>  This class, and other classes within the
049 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
050 *   supported for use against Ping Identity, UnboundID, and
051 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
052 *   for proprietary functionality or for external specifications that are not
053 *   considered stable or mature enough to be guaranteed to work in an
054 *   interoperable way with other types of LDAP servers.
055 * </BLOCKQUOTE>
056 */
057@NotMutable()
058@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
059public final class AuthenticationFailureReason
060       implements Serializable
061{
062  /**
063   * The numeric value for the failure type that indicates the user's account
064   * is not in a usable state.  Examining the set of account usability errors
065   * should provide more specific information about the nature of the error.
066   */
067  public static final int FAILURE_TYPE_ACCOUNT_NOT_USABLE = 1;
068
069
070
071  /**
072   * The name for the failure type that indicates the user's account is not in a
073   * usable state.  Examining the set of account usability errors should provide
074   * more specific information about the nature of the error.
075   */
076  public static final String FAILURE_NAME_ACCOUNT_NOT_USABLE =
077       "account-not-usable";
078
079
080
081  /**
082   * The numeric value for the failure type that indicates that the server was
083   * unable to assign a client connection policy for the user.
084   */
085  public static final int FAILURE_TYPE_CANNOT_ASSIGN_CLIENT_CONNECTION_POLICY =
086       3;
087
088
089
090  /**
091   * The name for the failure type that indicates that the server was unable to
092   * assign a client connection policy for the user.
093   */
094  public static final String
095       FAILURE_NAME_CANNOT_ASSIGN_CLIENT_CONNECTION_POLICY =
096       "cannot-assign-client-connection-policy";
097
098
099
100  /**
101   * The numeric value for the failure type that indicates that the server was
102   * unable to identify the user specified as the authentication or
103   * authorization identity.
104   */
105  public static final int FAILURE_TYPE_CANNOT_IDENTIFY_USER = 4;
106
107
108
109  /**
110   * The numeric value for the failure type that indicates that the server was
111   * unable to identify the user specified as the authentication or
112   * authorization identity.
113   */
114  public static final String FAILURE_NAME_CANNOT_IDENTIFY_USER =
115       "cannot-identify-user";
116
117
118
119  /**
120   * The numeric value for the failure type that indicates that bind was not
121   * permitted by some constraint defined in the server (password policy,
122   * client connection policy, operational attributes in the user entry, etc.).
123   */
124  public static final int FAILURE_TYPE_CONSTRAINT_VIOLATION = 5;
125
126
127
128  /**
129   * The name for the failure type that indicates that bind was not permitted by
130   * some constraint defined in the server (password policy, client connection
131   * policy, operational attributes in the user entry, etc.).
132   */
133  public static final String FAILURE_NAME_CONSTRAINT_VIOLATION =
134       "constraint-violation";
135
136
137
138  /**
139   * The numeric value for the failure type that indicates that there was a
140   * problem with a control included in the bind request.
141   */
142  public static final int FAILURE_TYPE_CONTROL_PROBLEM = 6;
143
144
145
146  /**
147   * The name for the failure type that indicates that there was a problem with
148   * a control included in the bind request.
149   */
150  public static final String FAILURE_NAME_CONTROL_PROBLEM = "control-problem";
151
152
153
154  /**
155   * The numeric value for the failure type that indicates that there was a
156   * problem with the SASL credentials provided to the server (e.g., they were
157   * malformed, out of sequence, or otherwise invalid).
158   */
159  public static final int FAILURE_TYPE_IMPROPER_SASL_CREDENTIALS = 7;
160
161
162
163  /**
164   * The name for the failure type that indicates that there was a problem with
165   * the SASL credentials provided to the server (e.g., they were malformed, out
166   * of sequence, or otherwise invalid).
167   */
168  public static final String FAILURE_NAME_IMPROPER_SASL_CREDENTIALS =
169       "improper-sasl-credentials";
170
171
172
173  /**
174   * The numeric value for the failure type that indicates that the bind was
175   * not permitted by the server's access control configuration.
176   */
177  public static final int FAILURE_TYPE_INSUFFICIENT_ACCESS_RIGHTS = 8;
178
179
180
181  /**
182   * The name for the failure type that indicates that the bind was not
183   * permitted by the server's access control configuration.
184   */
185  public static final String FAILURE_NAME_INSUFFICIENT_ACCESS_RIGHTS =
186       "insufficient-access-rights";
187
188
189
190  /**
191   * The numeric value for the failure type that indicates that the user
192   * provided an incorrect password or other form of invalid credentials.
193   */
194  public static final int FAILURE_TYPE_INVALID_CREDENTIALS = 9;
195
196
197
198  /**
199   * The name for the failure type that indicates that the user provided an
200   * incorrect password or other form of invalid credentials.
201   */
202  public static final String FAILURE_NAME_INVALID_CREDENTIALS =
203       "invalid-credentials";
204
205
206
207  /**
208   * The numeric value for the failure type that indicates that the server is in
209   * lockdown mode and will only permit authentication for a limited set of
210   * administrators.
211   */
212  public static final int FAILURE_TYPE_LOCKDOWN_MODE = 10;
213
214
215
216  /**
217   * The name for the failure type that indicates that the server is in lockdown
218   * mode and will only permit authentication for a limited set of
219   * administrators.
220   */
221  public static final String FAILURE_NAME_LOCKDOWN_MODE = "lockdown-mode";
222
223
224
225  /**
226   * The numeric value for the failure type that indicates that the user will
227   * only be permitted to authenticate in a secure manner.
228   */
229  public static final int FAILURE_TYPE_SECURE_AUTHENTICATION_REQUIRED = 11;
230
231
232
233  /**
234   * The name for the failure type that indicates that the user will only be
235   * permitted to authenticate in a secure manner.
236   */
237  public static final String FAILURE_NAME_SECURE_AUTHENTICATION_REQUIRED =
238       "secure-authentication-required";
239
240
241
242  /**
243   * The numeric value for the failure type that indicates that a server error
244   * occurred while processing the bind operation.
245   */
246  public static final int FAILURE_TYPE_SERVER_ERROR = 12;
247
248
249
250  /**
251   * The name for the failure type that indicates that a server error occurred
252   * while processing the bind operation.
253   */
254  public static final String FAILURE_NAME_SERVER_ERROR = "server-error";
255
256
257
258  /**
259   * The numeric value for the failure type that indicates that a third-party
260   * SASL mechanism handler failed to authenticate the user.
261   */
262  public static final int FAILURE_TYPE_THIRD_PARTY_SASL_AUTHENTICATION_FAILURE =
263       13;
264
265
266
267  /**
268   * The name for the failure type that indicates that a third-party SASL
269   * mechanism handler failed to authenticate the user.
270   */
271  public static final String
272       FAILURE_NAME_THIRD_PARTY_SASL_AUTHENTICATION_FAILURE =
273       "third-party-sasl-authentication-failure";
274
275
276
277  /**
278   * The numeric value for the failure type that indicates that attempted
279   * authentication type is not available for the target user.
280   */
281  public static final int FAILURE_TYPE_UNAVAILABLE_AUTHENTICATION_TYPE = 14;
282
283
284
285  /**
286   * The name for the failure type that indicates that attempted authentication
287   * type is not available for the target user.
288   */
289  public static final  String FAILURE_NAME_UNAVAILABLE_AUTHENTICATION_TYPE =
290       "unavailable-authentication-type";
291
292
293
294  /**
295   * The numeric value for a failure type that does not fit into any other of
296   * the defined failure types.
297   */
298  public static final int FAILURE_TYPE_OTHER = 15;
299
300
301
302  /**
303   * The name for a failure type that does not fit into any other of the defined
304   * failure types.
305   */
306  public static final String FAILURE_NAME_OTHER = "other";
307
308
309
310  /**
311   * The serial version UID for this serializable class.
312   */
313  private static final long serialVersionUID = -5752716527356924347L;
314
315
316
317  // The integer value for this account usability error.
318  private final int intValue;
319
320  // A human-readable message that provides specific details about this account
321  // usability error.
322  private final String message;
323
324  // The name for this account usability error.
325  private final String name;
326
327  // The encoded string representation for this account usability error.
328  private final String stringRepresentation;
329
330
331
332  /**
333   * Creates a new authentication failure reason with the provided information.
334   *
335   * @param  intValue  The integer value for this authentication failure reason.
336   * @param  name      The name for this authentication failure reason.  It must
337   *                   not be {@code null}.
338   * @param  message   A human-readable message that provides specific details
339   *                   about this account usability error.  It may be
340   *                   {@code null} if no message is available.
341   */
342  public AuthenticationFailureReason(final int intValue, final String name,
343                                     final String message)
344  {
345    Validator.ensureNotNull(name);
346
347    this.intValue = intValue;
348    this.name = name;
349    this.message = message;
350
351    final StringBuilder buffer = new StringBuilder();
352    buffer.append("code=");
353    buffer.append(intValue);
354    buffer.append("\tname=");
355    buffer.append(name);
356
357    if (message != null)
358    {
359      buffer.append("\tmessage=");
360      buffer.append(message);
361    }
362
363    stringRepresentation = buffer.toString();
364  }
365
366
367
368  /**
369   * Creates a new authentication failure reason that is decoded from the
370   * provided string representation.
371   *
372   * @param  stringRepresentation  The string representation of the
373   *                               authentication failure reason to decode.  It
374   *                               must not be {@code null}.
375   *
376   * @throws LDAPException  If the provided string cannot be decoded as a valid
377   *                         authentication failure reason.
378   */
379  public AuthenticationFailureReason(final String stringRepresentation)
380       throws LDAPException
381  {
382    this.stringRepresentation = stringRepresentation;
383
384    try
385    {
386      Integer i = null;
387      String n = null;
388      String m = null;
389
390      final StringTokenizer tokenizer =
391           new StringTokenizer(stringRepresentation, "\t");
392      while (tokenizer.hasMoreTokens())
393      {
394        final String token = tokenizer.nextToken();
395        final int equalPos = token.indexOf('=');
396        final String fieldName = token.substring(0, equalPos);
397        final String fieldValue = token.substring(equalPos+1);
398        if (fieldName.equals("code"))
399        {
400          i = Integer.valueOf(fieldValue);
401        }
402        else if (fieldName.equals("name"))
403        {
404          n = fieldValue;
405        }
406        else if (fieldName.equals("message"))
407        {
408          m = fieldValue;
409        }
410      }
411
412      if (i == null)
413      {
414        throw new LDAPException(ResultCode.DECODING_ERROR,
415             ERR_AUTH_FAILURE_REASON_CANNOT_DECODE.get(stringRepresentation,
416                  ERR_AUTH_FAILURE_REASON_NO_CODE.get()));
417      }
418
419      if (n == null)
420      {
421        throw new LDAPException(ResultCode.DECODING_ERROR,
422             ERR_AUTH_FAILURE_REASON_CANNOT_DECODE.get(stringRepresentation,
423                  ERR_AUTH_FAILURE_REASON_NO_NAME.get()));
424      }
425
426      intValue = i;
427      name     = n;
428      message  = m;
429    }
430    catch (final LDAPException le)
431    {
432      Debug.debugException(le);
433
434      throw le;
435    }
436    catch (final Exception e)
437    {
438      Debug.debugException(e);
439
440      throw new LDAPException(ResultCode.DECODING_ERROR,
441           ERR_AUTH_FAILURE_REASON_CANNOT_DECODE.get(stringRepresentation,
442                StaticUtils.getExceptionMessage(e)),
443           e);
444    }
445  }
446
447
448
449  /**
450   * Retrieves the integer value for this authentication failure reason.
451   *
452   * @return  The integer value for this authentication failure reason.
453   */
454  public int getIntValue()
455  {
456    return intValue;
457  }
458
459
460
461  /**
462   * Retrieves the name for this authentication failure reason.
463   *
464   * @return  The name for this authentication failure reason.
465   */
466  public String getName()
467  {
468    return name;
469  }
470
471
472
473  /**
474   * Retrieves a human-readable message that provides specific details about
475   * this authentication failure reason.
476   *
477   * @return  A human-readable message that provides specific details about this
478   *          authentication failure reason, or {@code null} if no message is
479   *          available.
480   */
481  public String getMessage()
482  {
483    return message;
484  }
485
486
487
488  /**
489   * Retrieves a string representation of this authentication failure reason.
490   *
491   * @return  A string representation of this authentication failure reason.
492   */
493  @Override()
494  public String toString()
495  {
496    return stringRepresentation;
497  }
498}