001: /*
002: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
003: * Reserved. Use is subject to license terms.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025: /*
026: */
027: package gov.nist.siplite.header;
028:
029: import gov.nist.core.*;
030: import gov.nist.siplite.address.*;
031:
032: /**
033: * The generic AuthenticationHeader
034: *
035: *
036: * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
037: *
038: */
039: public abstract class AuthenticationHeader extends ParametersHeader {
040: /** Domain header label. */
041: public static String DOMAIN = "domain";
042: /** Realm header label. */
043: public static String REALM = "realm";
044: /** Opaque header. */
045: public static String OPAQUE = "opaque";
046: /** Algorithm header label. */
047: public static String ALGORITHM = "algorithm";
048: /** Qop header (RFC?). */
049: public static String QOP = "qop";
050: /** Stale header (RFC?). */
051: public static String STALE = "stale";
052: /** Signature header. */
053: public static String SIGNATURE = "signature";
054: /** Response header. */
055: public static String RESPONSE = "response";
056: /** Signed byte header. */
057: public static String SIGNED_BY = "signed-by";
058: /** NC header (RFC?). */
059: public static String NC = "nc";
060: /** URI header. */
061: public static String URI = "uri";
062: /** User name header. */
063: public static String USERNAME = "username";
064: /** C-nonce header. */
065: public static String CNONCE = "cnonce";
066: /** Nonce header. */
067: public static String NONCE = "nonce";
068: /** Digest header. */
069: public static String DIGEST = "Digest";
070: /** Next nonce header. */
071: public static String NEXT_NONCE = "next-nonce";
072:
073: /** Current protocol scheme. */
074: protected String scheme;
075:
076: /**
077: * Constructor with header name.
078: * @param name header to process
079: */
080: public AuthenticationHeader(String name) {
081: super (name);
082: parameters.setSeparator(Separators.COMMA); // oddball
083: this .scheme = DIGEST;
084: }
085:
086: /** Default constructor. */
087: public AuthenticationHeader() {
088: super ();
089: parameters.setSeparator(Separators.COMMA);
090: }
091:
092: /**
093: * Sets the specified parameter.
094: * @param nv parameter's name/value pair
095: */
096: public void setParameter(NameValue nv) {
097: Object val = nv.getValue();
098: setParameter(nv.getName(), (val == null) ? null : val
099: .toString());
100: }
101:
102: /**
103: * Sets the specified parameter.
104: * @param name name of the parameter
105: * @param value value of the parameter.
106: */
107: public void setParameter(String name, String value)
108: throws IllegalArgumentException {
109: NameValue nv = super .parameters
110: .getNameValue(name.toLowerCase());
111:
112: boolean quotedParam = false;
113:
114: if (isQuoted(name)) {
115:
116: if (value == null) {
117: throw new NullPointerException("null value");
118: }
119:
120: quotedParam = true;
121: boolean quoteStart = value
122: .startsWith(Separators.DOUBLE_QUOTE);
123: boolean quoteEnd = value.endsWith(Separators.DOUBLE_QUOTE);
124:
125: if ((quoteStart && !quoteEnd) || (!quoteStart && quoteEnd)) {
126: throw new IllegalArgumentException(value
127: + " : Unexpected DOUBLE_QUOTE");
128: }
129:
130: if (quoteStart) { // quoteEnd is true in this case
131: value = value.substring(1, value.length() - 1);
132: }
133: }
134:
135: if (nv == null) {
136: nv = new NameValue(name.toLowerCase(), value);
137:
138: if (quotedParam) {
139: nv.setQuotedValue();
140: }
141:
142: super .setParameter(nv);
143: } else {
144: nv.setValue(value);
145: }
146:
147: }
148:
149: /**
150: * Returns the value of the named parameter, or null if it is not set. A
151: * zero-length String indicates flag parameter.
152: *
153: * @param name name of parameter to retrieve
154: * @return the value of specified parameter
155: */
156: public String getParameter(String name) {
157: String returnValue = super .getParameter(name);
158: if ((returnValue != null) && isQuoted(name)) { // remove quotes
159: returnValue = returnValue.substring(1,
160: returnValue.length() - 1);
161: }
162: return returnValue;
163:
164: }
165:
166: /**
167: * Returns true if parameter must be quoted, else - false.
168: * zero-length String indicates flag parameter.
169: *
170: * @param name name of parameter to retrieve
171: * @return flag of parameter (quoted or not)
172: */
173: private boolean isQuoted(String name) {
174: if (equalsIgnoreCase(name, QOP)
175: || equalsIgnoreCase(name, REALM)
176: || equalsIgnoreCase(name, URI)
177: || equalsIgnoreCase(name, CNONCE)
178: || equalsIgnoreCase(name, NONCE)
179: || equalsIgnoreCase(name, USERNAME)
180: || equalsIgnoreCase(name, DOMAIN)
181: || equalsIgnoreCase(name, OPAQUE)
182: || equalsIgnoreCase(name, NEXT_NONCE)
183: || equalsIgnoreCase(name, RESPONSE)) {
184: return true;
185: }
186: return false;
187: }
188:
189: /**
190: * Encodes in canonical form.
191: * @return canonical string.
192: */
193: public String encodeBody() {
194: return this .scheme + Separators.SP + parameters.encode();
195: }
196:
197: /**
198: * Sets the scheme of the challenge information for this
199: * AuthenticationHeaderHeader. For example, Digest.
200: *
201: * @param scheme - the new string value that identifies the challenge
202: * information scheme.
203: * @since v1.1
204: */
205: public void setScheme(String scheme) {
206: this .scheme = scheme;
207: }
208:
209: /**
210: * Returns the scheme of the challenge information for this
211: * AuthenticationHeaderHeader.
212: *
213: * @return the string value of the challenge information.
214: * @since v1.1
215: */
216: public String getScheme() {
217: return scheme;
218: }
219:
220: /**
221: * Sets the Realm of the WWWAuthenicateHeader to the <var>realm</var>
222: * parameter value. Realm strings MUST be globally unique. It is
223: * RECOMMENDED that a realm string contain a hostname or domain name.
224: * Realm strings SHOULD present a human-readable identifier that can be
225: * rendered to a user.
226: *
227: * @param realm the new Realm String of this WWWAuthenicateHeader.
228: * @throws ParseException which signals that an error has been reached
229: * unexpectedly while parsing the realm.
230: * @since v1.1
231: */
232: public void setRealm(String realm) {
233: if (realm == null)
234: throw new NullPointerException("null realm");
235: setParameter(REALM, realm);
236: }
237:
238: /**
239: * Returns the Realm value of this WWWAuthenicateHeader. This convenience
240: * method returns only the realm of the complete Challenge.
241: *
242: * @return the String representing the Realm information, null if value is
243: * not set.
244: * @since v1.1
245: */
246: public String getRealm() {
247: return getParameter(REALM);
248: }
249:
250: /**
251: * Sets the Nonce of the WWWAuthenicateHeader to the <var>nonce</var>
252: * parameter value.
253: *
254: * @param nonce - the new nonce String of this WWWAuthenicateHeader.
255: * @throws ParseException which signals that an error has been reached
256: * unexpectedly while parsing the nonce value.
257: * @since v1.1
258: */
259: public void setNonce(String nonce) {
260: if (nonce == null)
261: throw new NullPointerException("null nonce");
262: setParameter(NONCE, nonce);
263: }
264:
265: /**
266: * Returns the Nonce value of this WWWAuthenicateHeader.
267: *
268: * @return the String representing the nonce information, null if value is
269: * not set.
270: * @since v1.1
271: */
272: public String getNonce() {
273: return getParameter(NONCE);
274: }
275:
276: /**
277: * Sets the URI of the WWWAuthenicateHeader to the <var>uri</var>
278: * parameter value.
279: *
280: * @param uri - the new URI of this WWWAuthenicateHeader.
281: * @since v1.1
282: */
283: public void setURI(URI uri) {
284: if (uri != null) {
285: NameValue nv = new NameValue(URI, uri);
286: nv.setQuotedValue();
287: super .parameters.set(nv);
288: } else {
289: throw new NullPointerException("Null URI");
290: }
291: }
292:
293: /**
294: * Returns the URI value of this WWWAuthenicateHeader,
295: * for example DigestURI.
296: *
297: * @return the URI representing the URI information, null if value is
298: * not set.
299: * @since v1.1
300: */
301: public URI getURI() {
302: return getParameterAsURI(URI);
303: }
304:
305: /**
306: * Sets the Algorithm of the WWWAuthenicateHeader to the new
307: * <var>algorithm</var> parameter value.
308: *
309: * @param algorithm - the new algorithm String of this WWWAuthenicateHeader.
310: * @throws ParseException which signals that an error has been reached
311: * unexpectedly while parsing the algorithm value.
312: * @since v1.1
313: */
314: public void setAlgorithm(String algorithm) throws ParseException {
315: if (algorithm == null)
316: throw new NullPointerException("null arg");
317: setParameter(ALGORITHM, algorithm);
318: }
319:
320: /**
321: * Returns the Algorithm value of this WWWAuthenicateHeader.
322: *
323: * @return the String representing the Algorithm information, null if the
324: * value is not set.
325: * @since v1.1
326: */
327: public String getAlgorithm() {
328: return getParameter(ALGORITHM);
329: }
330:
331: /**
332: * Sets the Qop value of the WWWAuthenicateHeader to the new
333: * <var>qop</var> parameter value.
334: *
335: * @param qop - the new Qop string of this WWWAuthenicateHeader.
336: * @throws ParseException which signals that an error has been reached
337: * unexpectedly while parsing the Qop value.
338: * @since v1.1
339: */
340: public void setQop(String qop) throws ParseException {
341: if (qop == null)
342: throw new NullPointerException("null arg");
343: setParameter(QOP, qop);
344: }
345:
346: /**
347: * Returns the Qop value of this WWWAuthenicateHeader.
348: *
349: * @return the string representing the Qop information, null if the
350: * value is not set.
351: * @since v1.1
352: */
353: public String getQop() {
354: return getParameter(QOP);
355: }
356:
357: /**
358: * Sets the Opaque value of the WWWAuthenicateHeader to the new
359: * <var>opaque</var> parameter value.
360: *
361: * @param opaque - the new Opaque string of this WWWAuthenicateHeader.
362: * @throws ParseException which signals that an error has been reached
363: * unexpectedly while parsing the opaque value.
364: * @since v1.1
365: */
366: public void setOpaque(String opaque) throws ParseException {
367: if (opaque == null)
368: throw new NullPointerException("null arg");
369: setParameter(OPAQUE, opaque);
370: }
371:
372: /**
373: * Returns the Opaque value of this WWWAuthenicateHeader.
374: *
375: * @return the String representing the Opaque information, null if the
376: * value is not set.
377: * @since v1.1
378: */
379: public String getOpaque() {
380: return getParameter(OPAQUE);
381: }
382:
383: /**
384: * Sets the Domain of the WWWAuthenicateHeader to the <var>domain</var>
385: * parameter value.
386: *
387: * @param domain - the new Domain string of this WWWAuthenicateHeader.
388: * @throws ParseException which signals that an error has been reached
389: * unexpectedly while parsing the domain.
390: * @since v1.1
391: */
392: public void setDomain(String domain) throws ParseException {
393: if (domain == null)
394: throw new NullPointerException("null arg");
395: setParameter(DOMAIN, domain);
396: }
397:
398: /**
399: * Returns the Domain value of this WWWAuthenicateHeader.
400: *
401: * @return the String representing the Domain information, null if value is
402: * not set.
403: * @since v1.1
404: */
405: public String getDomain() {
406: return getParameter(DOMAIN);
407: }
408:
409: /**
410: * Sets the value of the stale parameter of the WWWAuthenicateHeader to the
411: * <var>stale</var> parameter value.
412: *
413: * @param stale - the new boolean value of the stale parameter.
414: * @since v1.1
415: */
416: public void setStale(boolean stale) {
417: setParameter(new NameValue(STALE, new Boolean(stale)));
418: }
419:
420: /**
421: * Returns the boolean value of the state paramater of this
422: * WWWAuthenicateHeader.
423: *
424: * @return the boolean representing if the challenge is stale.
425: * @since v1.1
426: */
427: public boolean isStale() {
428: return this .getParameterAsBoolean(STALE);
429: }
430:
431: /**
432: * Set the CNonce.
433: *
434: * @param cnonce -- a nonce string.
435: */
436: public void setCNonce(String cnonce) throws ParseException {
437: this .setParameter(CNONCE, cnonce);
438: }
439:
440: /**
441: * Get the CNonce.
442: *
443: * @return the cnonce value.
444: */
445: public String getCNonce() {
446: return getParameter(CNONCE);
447: }
448:
449: /**
450: * Counts the nonce.
451: * @return the count of nonces
452: */
453: public int getNonceCount() {
454: return this .getParameterAsHexInt(NC);
455:
456: }
457:
458: /**
459: * Set the nonce count parameter.
460: *
461: * @param nonceCount -- nonce count to set.
462: */
463:
464: public void setNonceCount(int nonceCount) throws ParseException,
465: IllegalArgumentException {
466: if (nonceCount < 0)
467: throw new IllegalArgumentException("bad value");
468:
469: String nc = Integer.toHexString(nonceCount);
470:
471: String base = "00000000";
472: nc = base.substring(0, 8 - nc.length()) + nc;
473: this .setParameter(NC, nc);
474:
475: }
476:
477: /**
478: * Gets the RESPONSE value (or null if it does not exist).
479: *
480: * @return String response parameter value.
481: */
482: public String getResponse() {
483: return (String) getParameterValue(RESPONSE);
484: }
485:
486: /**
487: * Sets the Response.
488: *
489: * @param response to set.
490: */
491: public void setResponse(String response) throws ParseException {
492: if (response == null)
493: throw new NullPointerException("Null parameter");
494: this .setParameter(RESPONSE, response);
495: }
496:
497: /**
498: * Returns the Username value of this AuthorizationHeader.
499: * This convenience method returns only the username of the
500: * complete Response.
501: *
502: * @return the String representing the Username information,
503: * null if value is not set.
504: *
505: * @since JAIN SIP v1.1
506: *
507: */
508: public String getUsername() {
509: return (String) getParameter(USERNAME);
510: }
511:
512: /**
513: * Sets the Username of the AuthorizationHeader to
514: * the <var>username</var> parameter value.
515: *
516: * @param username the new Username String of this AuthorizationHeader.
517: *
518: * @throws ParseException which signals that an error has been reached
519: *
520: * unexpectedly while parsing the username.
521: *
522: * @since JAIN SIP v1.1
523: *
524: */
525: public void setUsername(String username) {
526: this .setParameter(USERNAME, username);
527: }
528:
529: /**
530: * Clone - do a deep copy.
531: * @return Object Authorization
532: */
533: public Object clone() {
534: Exception ex = null;
535: try {
536: AuthenticationHeader retval = (AuthenticationHeader) this
537: .getClass().newInstance();
538: if (this .scheme != null)
539: retval.scheme = new String(this .scheme);
540: if (this .parameters != null)
541: retval.parameters = (NameValueList) parameters.clone();
542: return retval;
543: } catch (InstantiationException ie) {
544: ex = ie;
545: } catch (IllegalAccessException iae) {
546: ex = iae;
547: }
548: if (ex != null) {
549: InternalErrorHandler.handleException(ex);
550: }
551: return null;
552: }
553:
554: /**
555: * Compares for equivalence.
556: * @param that object to compare
557: * @return true if object matches
558: */
559: public boolean equals(Object that) {
560: if (!that.getClass().equals(this .getClass())) {
561: return false;
562: } else {
563: AuthenticationHeader other = (AuthenticationHeader) that;
564: return (equalsIgnoreCase(this .scheme, other.scheme) && this .parameters
565: .equals(other.parameters));
566: }
567: }
568:
569: /**
570: * Gets the value of the header (just returns the scheme).
571: * @return the scheme object.
572: */
573: public Object getValue() {
574: return getScheme();
575:
576: }
577:
578: }
|