blob: 90e6247ea9197c8c091ceb697ef76af57e9bd319 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/* **************************************************************************
2 * $OpenLDAP: /com/novell/sasl/client/DigestChallenge.java,v 1.3 2005/01/17 15:00:54 sunilk Exp $
3 *
4 * Copyright (C) 2003 Novell, Inc. All Rights Reserved.
5 *
6 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
7 * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
8 * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
9 * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
10 * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
11 * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
12 * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
13 * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
14 ******************************************************************************/
15package com.novell.sasl.client;
16
17import java.util.*;
18import org.apache.harmony.javax.security.sasl.*;
19
20/**
21 * Implements the DigestChallenge class which will be used by the
22 * DigestMD5SaslClient class
23 */
24class DigestChallenge extends Object
25{
26 public static final int QOP_AUTH = 0x01;
27 public static final int QOP_AUTH_INT = 0x02;
28 public static final int QOP_AUTH_CONF = 0x04;
29 public static final int QOP_UNRECOGNIZED = 0x08;
30
31 private static final int CIPHER_3DES = 0x01;
32 private static final int CIPHER_DES = 0x02;
33 private static final int CIPHER_RC4_40 = 0x04;
34 private static final int CIPHER_RC4 = 0x08;
35 private static final int CIPHER_RC4_56 = 0x10;
36 private static final int CIPHER_UNRECOGNIZED = 0x20;
37 private static final int CIPHER_RECOGNIZED_MASK =
38 CIPHER_3DES | CIPHER_DES | CIPHER_RC4_40 | CIPHER_RC4 | CIPHER_RC4_56;
39
40 private ArrayList m_realms;
41 private String m_nonce;
42 private int m_qop;
43 private boolean m_staleFlag;
44 private int m_maxBuf;
45 private String m_characterSet;
46 private String m_algorithm;
47 private int m_cipherOptions;
48
49 DigestChallenge(
50 byte[] challenge)
51 throws SaslException
52 {
53 m_realms = new ArrayList(5);
54 m_nonce = null;
55 m_qop = 0;
56 m_staleFlag = false;
57 m_maxBuf = -1;
58 m_characterSet = null;
59 m_algorithm = null;
60 m_cipherOptions = 0;
61
62 DirectiveList dirList = new DirectiveList(challenge);
63 try
64 {
65 dirList.parseDirectives();
66 checkSemantics(dirList);
67 }
68 catch (SaslException e)
69 {
70 }
71 }
72
73 /**
74 * Checks the semantics of the directives in the directive list as parsed
75 * from the digest challenge byte array.
76 *
77 * @param dirList the list of directives parsed from the digest challenge
78 *
79 * @exception SaslException If a semantic error occurs
80 */
81 void checkSemantics(
82 DirectiveList dirList) throws SaslException
83 {
84 Iterator directives = dirList.getIterator();
85 ParsedDirective directive;
86 String name;
87
88 while (directives.hasNext())
89 {
90 directive = (ParsedDirective)directives.next();
91 name = directive.getName();
92 if (name.equals("realm"))
93 handleRealm(directive);
94 else if (name.equals("nonce"))
95 handleNonce(directive);
96 else if (name.equals("qop"))
97 handleQop(directive);
98 else if (name.equals("maxbuf"))
99 handleMaxbuf(directive);
100 else if (name.equals("charset"))
101 handleCharset(directive);
102 else if (name.equals("algorithm"))
103 handleAlgorithm(directive);
104 else if (name.equals("cipher"))
105 handleCipher(directive);
106 else if (name.equals("stale"))
107 handleStale(directive);
108 }
109
110 /* post semantic check */
111 if (-1 == m_maxBuf)
112 m_maxBuf = 65536;
113
114 if (m_qop == 0)
115 m_qop = QOP_AUTH;
116 else if ( (m_qop & QOP_AUTH) != QOP_AUTH )
117 throw new SaslException("Only qop-auth is supported by client");
118 else if ( ((m_qop & QOP_AUTH_CONF) == QOP_AUTH_CONF) &&
119 (0 == (m_cipherOptions & CIPHER_RECOGNIZED_MASK)) )
120 throw new SaslException("Invalid cipher options");
121 else if (null == m_nonce)
122 throw new SaslException("Missing nonce directive");
123 else if (m_staleFlag)
124 throw new SaslException("Unexpected stale flag");
125 else if ( null == m_algorithm )
126 throw new SaslException("Missing algorithm directive");
127 }
128
129 /**
130 * This function implements the semenatics of the nonce directive.
131 *
132 * @param pd ParsedDirective
133 *
134 * @exception SaslException If an error occurs due to too many nonce
135 * values
136 */
137 void handleNonce(
138 ParsedDirective pd) throws SaslException
139 {
140 if (null != m_nonce)
141 throw new SaslException("Too many nonce values.");
142
143 m_nonce = pd.getValue();
144 }
145
146 /**
147 * This function implements the semenatics of the realm directive.
148 *
149 * @param pd ParsedDirective
150 */
151 void handleRealm(
152 ParsedDirective pd)
153 {
154 m_realms.add(pd.getValue());
155 }
156
157 /**
158 * This function implements the semenatics of the qop (quality of protection)
159 * directive. The value of the qop directive is as defined below:
160 * qop-options = "qop" "=" <"> qop-list <">
161 * qop-list = 1#qop-value
162 * qop-value = "auth" | "auth-int" | "auth-conf" | token
163 *
164 * @param pd ParsedDirective
165 *
166 * @exception SaslException If an error occurs due to too many qop
167 * directives
168 */
169 void handleQop(
170 ParsedDirective pd) throws SaslException
171 {
172 String token;
173 TokenParser parser;
174
175 if (m_qop != 0)
176 throw new SaslException("Too many qop directives.");
177
178 parser = new TokenParser(pd.getValue());
179 for (token = parser.parseToken();
180 token != null;
181 token = parser.parseToken())
182 {
183 if (token.equals("auth"))
184 m_qop |= QOP_AUTH;
185 else if (token.equals("auth-int"))
186 m_qop |= QOP_AUTH_INT;
187 else if (token.equals("auth-conf"))
188 m_qop |= QOP_AUTH_CONF;
189 else
190 m_qop |= QOP_UNRECOGNIZED;
191 }
192 }
193
194 /**
195 * This function implements the semenatics of the Maxbuf directive.
196 * the value is defined as: 1*DIGIT
197 *
198 * @param pd ParsedDirective
199 *
200 * @exception SaslException If an error occur
201 */
202 void handleMaxbuf(
203 ParsedDirective pd) throws SaslException
204 {
205 if (-1 != m_maxBuf) /*it's initialized to -1 */
206 throw new SaslException("Too many maxBuf directives.");
207
208 m_maxBuf = Integer.parseInt(pd.getValue());
209
210 if (0 == m_maxBuf)
211 throw new SaslException("Max buf value must be greater than zero.");
212 }
213
214 /**
215 * This function implements the semenatics of the charset directive.
216 * the value is defined as: 1*DIGIT
217 *
218 * @param pd ParsedDirective
219 *
220 * @exception SaslException If an error occurs dur to too many charset
221 * directives or Invalid character encoding
222 * directive
223 */
224 void handleCharset(
225 ParsedDirective pd) throws SaslException
226 {
227 if (null != m_characterSet)
228 throw new SaslException("Too many charset directives.");
229
230 m_characterSet = pd.getValue();
231
232 if (!m_characterSet.equals("utf-8"))
233 throw new SaslException("Invalid character encoding directive");
234 }
235
236 /**
237 * This function implements the semenatics of the charset directive.
238 * the value is defined as: 1*DIGIT
239 *
240 * @param pd ParsedDirective
241 *
242 * @exception SaslException If an error occurs due to too many algorith
243 * directive or Invalid algorithm directive
244 * value
245 */
246 void handleAlgorithm(
247 ParsedDirective pd) throws SaslException
248 {
249 if (null != m_algorithm)
250 throw new SaslException("Too many algorithm directives.");
251
252 m_algorithm = pd.getValue();
253
254 if (!"md5-sess".equals(m_algorithm))
255 throw new SaslException("Invalid algorithm directive value: " +
256 m_algorithm);
257 }
258
259 /**
260 * This function implements the semenatics of the cipher-opts directive
261 * directive. The value of the qop directive is as defined below:
262 * qop-options = "qop" "=" <"> qop-list <">
263 * qop-list = 1#qop-value
264 * qop-value = "auth" | "auth-int" | "auth-conf" | token
265 *
266 * @param pd ParsedDirective
267 *
268 * @exception SaslException If an error occurs due to Too many cipher
269 * directives
270 */
271 void handleCipher(
272 ParsedDirective pd) throws SaslException
273 {
274 String token;
275 TokenParser parser;
276
277 if (0 != m_cipherOptions)
278 throw new SaslException("Too many cipher directives.");
279
280 parser = new TokenParser(pd.getValue());
281 token = parser.parseToken();
282 for (token = parser.parseToken();
283 token != null;
284 token = parser.parseToken())
285 {
286 if ("3des".equals(token))
287 m_cipherOptions |= CIPHER_3DES;
288 else if ("des".equals(token))
289 m_cipherOptions |= CIPHER_DES;
290 else if ("rc4-40".equals(token))
291 m_cipherOptions |= CIPHER_RC4_40;
292 else if ("rc4".equals(token))
293 m_cipherOptions |= CIPHER_RC4;
294 else if ("rc4-56".equals(token))
295 m_cipherOptions |= CIPHER_RC4_56;
296 else
297 m_cipherOptions |= CIPHER_UNRECOGNIZED;
298 }
299
300 if (m_cipherOptions == 0)
301 m_cipherOptions = CIPHER_UNRECOGNIZED;
302 }
303
304 /**
305 * This function implements the semenatics of the stale directive.
306 *
307 * @param pd ParsedDirective
308 *
309 * @exception SaslException If an error occurs due to Too many stale
310 * directives or Invalid stale directive value
311 */
312 void handleStale(
313 ParsedDirective pd) throws SaslException
314 {
315 if (false != m_staleFlag)
316 throw new SaslException("Too many stale directives.");
317
318 if ("true".equals(pd.getValue()))
319 m_staleFlag = true;
320 else
321 throw new SaslException("Invalid stale directive value: " +
322 pd.getValue());
323 }
324
325 /**
326 * Return the list of the All the Realms
327 *
328 * @return List of all the realms
329 */
330 public ArrayList getRealms()
331 {
332 return m_realms;
333 }
334
335 /**
336 * @return Returns the Nonce
337 */
338 public String getNonce()
339 {
340 return m_nonce;
341 }
342
343 /**
344 * Return the quality-of-protection
345 *
346 * @return The quality-of-protection
347 */
348 public int getQop()
349 {
350 return m_qop;
351 }
352
353 /**
354 * @return The state of the Staleflag
355 */
356 public boolean getStaleFlag()
357 {
358 return m_staleFlag;
359 }
360
361 /**
362 * @return The Maximum Buffer value
363 */
364 public int getMaxBuf()
365 {
366 return m_maxBuf;
367 }
368
369 /**
370 * @return character set values as string
371 */
372 public String getCharacterSet()
373 {
374 return m_characterSet;
375 }
376
377 /**
378 * @return The String value of the algorithm
379 */
380 public String getAlgorithm()
381 {
382 return m_algorithm;
383 }
384
385 /**
386 * @return The cipher options
387 */
388 public int getCipherOptions()
389 {
390 return m_cipherOptions;
391 }
392}
393