001/*
002 * Copyright 2014-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2014-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) 2014-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;
037
038
039
040import java.util.ArrayList;
041import java.util.Iterator;
042import java.util.List;
043import java.util.StringTokenizer;
044
045import com.unboundid.util.NotNull;
046import com.unboundid.util.Nullable;
047import com.unboundid.util.StaticUtils;
048import com.unboundid.util.ThreadSafety;
049import com.unboundid.util.ThreadSafetyLevel;
050
051
052
053/**
054 * This enum defines the set of supported SASL quality of protection values.
055 */
056@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
057public enum SASLQualityOfProtection
058{
059  /**
060   * The quality of protection value that indicates that only authentication is
061   * to be performed, with no integrity or confidentiality protection for
062   * subsequent communication.
063   */
064  AUTH("auth"),
065
066
067
068  /**
069   * The quality of protection value that indicates that integrity protection
070   * will be provided for subsequent communication after authentication has
071   * completed.  While integrity protection does not ensure that third-party
072   * observers cannot decipher communication between the client and server, it
073   * does ensure that the communication cannot be altered in an undetectable
074   * manner.
075   */
076  AUTH_INT("auth-int"),
077
078
079
080  /**
081   * The quality of protection value that indicates that confidentiality
082   * protection will be provided for subsequent communication after
083   * authentication has completed.  This ensures that third-party observers will
084   * not be able to decipher communication between the client and server (i.e.,
085   * that the communication will be encrypted).
086   */
087  AUTH_CONF("auth-conf");
088
089
090
091  // The string representation that should be used for this QoP when interacting
092  // with the Java SASL framework.
093  @NotNull private final String qopString;
094
095
096
097  /**
098   * Creates a new SASL quality of protection value with the provided string
099   * representation.
100   *
101   * @param  qopString  The string representation for this quality of protection
102   *                    that should be used when interacting with the Java SASL
103   *                    framework.
104   */
105  SASLQualityOfProtection(@NotNull final String qopString)
106  {
107    this.qopString = qopString;
108  }
109
110
111
112  /**
113   * Retrieves the SASL quality of protection value with the given name.
114   *
115   * @param  name  The name of the SASL quality of protection value to retrieve.
116   *               It must not be {@code null}.
117   *
118   * @return  The requested SASL quality of protection value, or {@code null} if
119   *          there is no value with the provided name.
120   */
121  @Nullable()
122  public static SASLQualityOfProtection forName(@NotNull final String name)
123  {
124    switch (StaticUtils.toLowerCase(name))
125    {
126      case "auth":
127        return AUTH;
128      case "authint":
129      case "auth-int":
130      case "auth_int":
131        return AUTH_INT;
132      case "authconf":
133      case "auth-conf":
134      case "auth_conf":
135        return AUTH_CONF;
136      default:
137        return null;
138    }
139  }
140
141
142
143  /**
144   * Decodes the provided string as a comma-delimited list of SASL quality of
145   * protection values.
146   *
147   * @param  s  The string to be decoded.
148   *
149   * @return  The decoded list of SASL quality of protection values.  It will
150   *          not be {@code null} but may be empty if the provided string was
151   *          {@code null} or empty.
152   *
153   * @throws  LDAPException  If the provided string cannot be decoded as a valid
154   *                         list of SASL quality of protection values.
155   */
156  @NotNull()
157  public static List<SASLQualityOfProtection> decodeQoPList(
158                                                   @Nullable final String s)
159         throws LDAPException
160  {
161    final ArrayList<SASLQualityOfProtection> qopValues = new ArrayList<>(3);
162    if ((s == null) || s.isEmpty())
163    {
164      return qopValues;
165    }
166
167    final StringTokenizer tokenizer = new StringTokenizer(s, ",");
168    while (tokenizer.hasMoreTokens())
169    {
170      final String token = tokenizer.nextToken().trim();
171      final SASLQualityOfProtection qop = forName(token);
172      if (qop == null)
173      {
174        throw new LDAPException(ResultCode.PARAM_ERROR,
175             LDAPMessages.ERR_SASL_QOP_DECODE_LIST_INVALID_ELEMENT.get(
176                  token, AUTH.qopString, AUTH_INT.qopString,
177                  AUTH_CONF.qopString));
178      }
179      else
180      {
181        qopValues.add(qop);
182      }
183    }
184
185    return qopValues;
186  }
187
188
189
190  /**
191   * Retrieves a string representation of this SASL quality of protection.
192   *
193   * @return  A string representation of this SASL quality of protection.
194   */
195  @Override()
196  @NotNull()
197  public String toString()
198  {
199    return qopString;
200  }
201
202
203
204  /**
205   * Retrieves a string representation of the provided list of quality of
206   * protection values, as may be provided to a Java {@code SaslClient}.
207   *
208   * @param  qopValues  The list of values for which to create the string
209   *                    representation.
210   *
211   * @return  A string representation of the provided list of quality of
212   *          protection values, as may be provided to a Java
213   *          {@code SaslClient}.
214   */
215  @NotNull()
216  public static String toString(
217              @NotNull final List<SASLQualityOfProtection> qopValues)
218  {
219    if ((qopValues == null) || qopValues.isEmpty())
220    {
221      return AUTH.qopString;
222    }
223
224    final StringBuilder buffer = new StringBuilder(23);
225    final Iterator<SASLQualityOfProtection> iterator = qopValues.iterator();
226    while (iterator.hasNext())
227    {
228      buffer.append(iterator.next().qopString);
229      if (iterator.hasNext())
230      {
231        buffer.append(',');
232      }
233    }
234    return buffer.toString();
235  }
236}