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