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