1/*
2* Conditions Of Use
3*
4* This software was developed by employees of the National Institute of
5* Standards and Technology (NIST), an agency of the Federal Government.
6* Pursuant to title 15 Untied States Code Section 105, works of NIST
7* employees are not subject to copyright protection in the United States
8* and are considered to be in the public domain.  As a result, a formal
9* license is not needed to use the software.
10*
11* This software is provided by NIST as a service and is expressly
12* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15* AND DATA ACCURACY.  NIST does not warrant or make any representations
16* regarding the use of the software or the results thereof, including but
17* not limited to the correctness, accuracy, reliability or usefulness of
18* the software.
19*
20* Permission to use this software is contingent upon your acceptance
21* of the terms of this agreement.
22*
23*/
24/*****************************************************************************
25 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).     *
26******************************************************************************/
27package gov.nist.javax.sip.header;
28
29import gov.nist.core.*;
30import gov.nist.javax.sip.header.ims.ParameterNamesIms;
31
32import java.text.ParseException;
33 /*
34 * 2005/06/12: geir.hedemark@telio.no: Changed behaviour of qop parameter in
35 *           Authorization header - removed quoting of string according to
36 *          RFC3261, BNF element "message-qop" (as opposed to "qop-options",
37 *           which is quoted.
38 */
39
40/**
41 * The generic AuthenticationHeader
42 *
43 * @author Olivier Deruelle
44 * @author M. Ranganathan <br/>
45 * @since 1.1
46 * @version 1.2 $Revision: 1.13 $ $Date: 2009/10/18 13:46:32 $
47 *
48 *
49 */
50public abstract class AuthenticationHeader extends ParametersHeader {
51
52    public static final String DOMAIN = ParameterNames.DOMAIN;
53
54    public static final String REALM = ParameterNames.REALM;
55
56    public static final String OPAQUE = ParameterNames.OPAQUE;
57
58    public static final String ALGORITHM = ParameterNames.ALGORITHM;
59
60    public static final String QOP = ParameterNames.QOP;
61
62    public static final String STALE = ParameterNames.STALE;
63
64    public static final String SIGNATURE = ParameterNames.SIGNATURE;
65
66    public static final String RESPONSE = ParameterNames.RESPONSE;
67
68    public static final String SIGNED_BY = ParameterNames.SIGNED_BY;
69
70    public static final String NC = ParameterNames.NC;
71
72    public static final String URI = ParameterNames.URI;
73
74    public static final String USERNAME = ParameterNames.USERNAME;
75
76    public static final String CNONCE = ParameterNames.CNONCE;
77
78    public static final String NONCE = ParameterNames.NONCE;
79
80    public static final String IK = ParameterNamesIms.IK;
81    public static final String CK = ParameterNamesIms.CK;
82    public static final String INTEGRITY_PROTECTED = ParameterNamesIms.INTEGRITY_PROTECTED;
83
84    protected String scheme;
85
86    public AuthenticationHeader(String name) {
87        super(name);
88        parameters.setSeparator(Separators.COMMA); // oddball
89        this.scheme = ParameterNames.DIGEST;
90    }
91
92    public AuthenticationHeader() {
93        super();
94        parameters.setSeparator(Separators.COMMA);
95    }
96
97    /**
98     * set the specified parameter. Bug reported by Dominic Sparks.
99     *
100     * @param name --
101     *            name of the parameter
102     * @param value --
103     *            value of the parameter.
104     */
105    public void setParameter(String name, String value) throws ParseException {
106        NameValue nv = super.parameters.getNameValue(name.toLowerCase());
107        if (nv == null) {
108            nv = new NameValue(name, value);
109            if (name.equalsIgnoreCase(ParameterNames.QOP)
110                    || name.equalsIgnoreCase(ParameterNames.REALM)
111                    || name.equalsIgnoreCase(ParameterNames.CNONCE)
112                    || name.equalsIgnoreCase(ParameterNames.NONCE)
113                    || name.equalsIgnoreCase(ParameterNames.USERNAME)
114                    || name.equalsIgnoreCase(ParameterNames.DOMAIN)
115                    || name.equalsIgnoreCase(ParameterNames.OPAQUE)
116                    || name.equalsIgnoreCase(ParameterNames.NEXT_NONCE)
117                    || name.equalsIgnoreCase(ParameterNames.URI)
118                    || name.equalsIgnoreCase(ParameterNames.RESPONSE )
119                    ||name.equalsIgnoreCase(ParameterNamesIms.IK)
120                    || name.equalsIgnoreCase(ParameterNamesIms.CK)
121                    || name.equalsIgnoreCase(ParameterNamesIms.INTEGRITY_PROTECTED)) {
122                if (((this instanceof Authorization) || (this instanceof ProxyAuthorization))
123                        && name.equalsIgnoreCase(ParameterNames.QOP)) {
124                    // NOP, QOP not quoted in authorization headers
125                } else {
126                    nv.setQuotedValue();
127                }
128                if (value == null)
129                    throw new NullPointerException("null value");
130                if (value.startsWith(Separators.DOUBLE_QUOTE))
131                    throw new ParseException(value
132                            + " : Unexpected DOUBLE_QUOTE", 0);
133            }
134            super.setParameter(nv);
135        } else
136            nv.setValueAsObject(value);
137
138    }
139
140    /**
141     * This is only used for the parser interface.
142     *
143     * @param challenge --
144     *            the challenge from which the parameters are extracted.
145     */
146    public void setChallenge(Challenge challenge) {
147        this.scheme = challenge.scheme;
148        super.parameters = challenge.authParams;
149    }
150
151    /**
152     * Encode in canonical form.
153     *
154     * @return canonical string.
155     */
156    public String encodeBody() {
157        this.parameters.setSeparator(Separators.COMMA);
158        return this.scheme + SP + parameters.encode();
159    }
160
161    /**
162     * Sets the scheme of the challenge information for this
163     * AuthenticationHeaderHeader. For example, Digest.
164     *
165     * @param scheme -
166     *            the new string value that identifies the challenge information
167     *            scheme.
168     */
169    public void setScheme(String scheme) {
170        this.scheme = scheme;
171    }
172
173    /**
174     * Returns the scheme of the challenge information for this
175     * AuthenticationHeaderHeader.
176     *
177     * @return the string value of the challenge information.
178     */
179    public String getScheme() {
180        return scheme;
181    }
182
183    /**
184     * Sets the Realm of the WWWAuthenicateHeader to the <var>realm</var>
185     * parameter value. Realm strings MUST be globally unique. It is RECOMMENDED
186     * that a realm string contain a hostname or domain name. Realm strings
187     * SHOULD present a human-readable identifier that can be rendered to a
188     * user.
189     *
190     * @param realm
191     *            the new Realm String of this WWWAuthenicateHeader.
192     * @throws ParseException
193     *             which signals that an error has been reached unexpectedly
194     *             while parsing the realm.
195     */
196    public void setRealm(String realm) throws ParseException {
197        if (realm == null)
198            throw new NullPointerException(
199                    "JAIN-SIP Exception, "
200                            + " AuthenticationHeader, setRealm(), The realm parameter is null");
201        setParameter(ParameterNames.REALM, realm);
202    }
203
204    /**
205     * Returns the Realm value of this WWWAuthenicateHeader. This convenience
206     * method returns only the realm of the complete Challenge.
207     *
208     * @return the String representing the Realm information, null if value is
209     *         not set.
210     * @since v1.1
211     */
212    public String getRealm() {
213        return getParameter(ParameterNames.REALM);
214    }
215
216    /**
217     * Sets the Nonce of the WWWAuthenicateHeader to the <var>nonce</var>
218     * parameter value.
219     *
220     * @param nonce -
221     *            the new nonce String of this WWWAuthenicateHeader.
222     * @throws ParseException
223     *             which signals that an error has been reached unexpectedly
224     *             while parsing the nonce value.
225     * @since v1.1
226     */
227    public void setNonce(String nonce) throws ParseException {
228        if (nonce == null)
229            throw new NullPointerException(
230                    "JAIN-SIP Exception, "
231                            + " AuthenticationHeader, setNonce(), The nonce parameter is null");
232        setParameter(NONCE, nonce);
233    }
234
235    /**
236     * Returns the Nonce value of this WWWAuthenicateHeader.
237     *
238     * @return the String representing the nonce information, null if value is
239     *         not set.
240     * @since v1.1
241     */
242    public String getNonce() {
243        return getParameter(ParameterNames.NONCE);
244    }
245
246    /**
247     * Sets the URI of the WWWAuthenicateHeader to the <var>uri</var> parameter
248     * value.
249     *
250     * @param uri -
251     *            the new URI of this AuthenicationHeader.
252     * @since v1.1
253     *
254     * Note that since 1.2 this is no longer applicable to the WWW-Authenticate
255     * and Proxy-Authenticate headers
256     */
257    public void setURI(javax.sip.address.URI uri) {
258        if (uri != null) {
259            NameValue nv = new NameValue(ParameterNames.URI, uri);
260            nv.setQuotedValue();
261            super.parameters.set(nv);
262        } else {
263            throw new NullPointerException("Null URI");
264        }
265    }
266
267    /**
268     * Returns the URI value of this WWWAuthenicateHeader, for example
269     * DigestURI.
270     *
271     * @return the URI representing the URI information, null if value is not
272     *         set.
273     * @since v1.1
274     *
275     * Note that since 1.2 this is no longer applicable to the WWW-Authenticate
276     * and Proxy-Authenticate headers
277     */
278    public javax.sip.address.URI getURI() {
279        return getParameterAsURI(ParameterNames.URI);
280    }
281
282    /**
283     * Sets the Algorithm of the WWWAuthenicateHeader to the new <var>algorithm</var>
284     * parameter value.
285     *
286     * @param algorithm -
287     *            the new algorithm String of this WWWAuthenicateHeader.
288     * @throws ParseException
289     *             which signals that an error has been reached unexpectedly
290     *             while parsing the algorithm value.
291     * @since v1.1
292     */
293    public void setAlgorithm(String algorithm) throws ParseException {
294        if (algorithm == null)
295            throw new NullPointerException("null arg");
296        setParameter(ParameterNames.ALGORITHM, algorithm);
297    }
298
299    /**
300     * Returns the Algorithm value of this WWWAuthenicateHeader.
301     *
302     * @return the String representing the Algorithm information, null if the
303     *         value is not set.
304     * @since v1.1
305     */
306    public String getAlgorithm() {
307        return getParameter(ParameterNames.ALGORITHM);
308    }
309
310    /**
311     * Sets the Qop value of the WWWAuthenicateHeader to the new <var>qop</var>
312     * parameter value.
313     *
314     * @param qop -
315     *            the new Qop string of this WWWAuthenicateHeader.
316     * @throws ParseException
317     *             which signals that an error has been reached unexpectedly
318     *             while parsing the Qop value.
319     * @since v1.1
320     */
321    public void setQop(String qop) throws ParseException {
322        if (qop == null)
323            throw new NullPointerException("null arg");
324        setParameter(ParameterNames.QOP, qop);
325    }
326
327    /**
328     * Returns the Qop value of this WWWAuthenicateHeader.
329     *
330     * @return the string representing the Qop information, null if the value is
331     *         not set.
332     * @since v1.1
333     */
334    public String getQop() {
335        return getParameter(ParameterNames.QOP);
336    }
337
338    /**
339     * Sets the Opaque value of the WWWAuthenicateHeader to the new <var>opaque</var>
340     * parameter value.
341     *
342     * @param opaque -
343     *            the new Opaque string of this WWWAuthenicateHeader.
344     * @throws ParseException
345     *             which signals that an error has been reached unexpectedly
346     *             while parsing the opaque value.
347     * @since v1.1
348     */
349    public void setOpaque(String opaque) throws ParseException {
350        if (opaque == null)
351            throw new NullPointerException("null arg");
352        setParameter(ParameterNames.OPAQUE, opaque);
353    }
354
355    /**
356     * Returns the Opaque value of this WWWAuthenicateHeader.
357     *
358     * @return the String representing the Opaque information, null if the value
359     *         is not set.
360     * @since v1.1
361     */
362    public String getOpaque() {
363        return getParameter(ParameterNames.OPAQUE);
364    }
365
366    /**
367     * Sets the Domain of the WWWAuthenicateHeader to the <var>domain</var>
368     * parameter value.
369     *
370     * @param domain -
371     *            the new Domain string of this WWWAuthenicateHeader.
372     * @throws ParseException
373     *             which signals that an error has been reached unexpectedly
374     *             while parsing the domain.
375     * @since v1.1
376     */
377    public void setDomain(String domain) throws ParseException {
378        if (domain == null)
379            throw new NullPointerException("null arg");
380        setParameter(ParameterNames.DOMAIN, domain);
381    }
382
383    /**
384     * Returns the Domain value of this WWWAuthenicateHeader.
385     *
386     * @return the String representing the Domain information, null if value is
387     *         not set.
388     * @since v1.1
389     */
390    public String getDomain() {
391        return getParameter(ParameterNames.DOMAIN);
392    }
393
394    /**
395     * Sets the value of the stale parameter of the WWWAuthenicateHeader to the
396     * <var>stale</var> parameter value.
397     *
398     * @param stale -
399     *            the Boolean.valueOf value of the stale parameter.
400     * @since v1.1
401     */
402    public void setStale(boolean stale) {
403        setParameter(new NameValue(ParameterNames.STALE, Boolean.valueOf(stale)));
404    }
405
406    /**
407     * Returns the boolean value of the state paramater of this
408     * WWWAuthenicateHeader.
409     *
410     * @return the boolean representing if the challenge is stale.
411     * @since v1.1
412     */
413    public boolean isStale() {
414        return this.getParameterAsBoolean(ParameterNames.STALE);
415    }
416
417    /**
418     * Set the CNonce.
419     *
420     * @param cnonce --
421     *            a nonce string.
422     */
423    public void setCNonce(String cnonce) throws ParseException {
424        this.setParameter(ParameterNames.CNONCE, cnonce);
425    }
426
427    /**
428     * Get the CNonce.
429     *
430     * @return the cnonce value.
431     */
432    public String getCNonce() {
433        return getParameter(ParameterNames.CNONCE);
434    }
435
436    public int getNonceCount() {
437        return this.getParameterAsHexInt(ParameterNames.NC);
438
439    }
440
441    /**
442     * Set the nonce count pakrameter. Bug fix sent in by Andreas Bystr�m
443     */
444
445    public void setNonceCount(int param) throws java.text.ParseException {
446        if (param < 0)
447            throw new ParseException("bad value", 0);
448
449        String nc = Integer.toHexString(param);
450
451        String base = "00000000";
452        nc = base.substring(0, 8 - nc.length()) + nc;
453        this.setParameter(ParameterNames.NC, nc);
454
455    }
456
457    /**
458     * Get the RESPONSE value (or null if it does not exist).
459     *
460     * @return String response parameter value.
461     */
462    public String getResponse() {
463        return (String) getParameterValue(ParameterNames.RESPONSE);
464    }
465
466    /**
467     * Set the Response.
468     *
469     * @param response
470     *            to set.
471     */
472    public void setResponse(String response) throws ParseException {
473        if (response == null)
474            throw new NullPointerException("Null parameter");
475        // Bug fix from Andreas Bystr�m
476        this.setParameter(RESPONSE, response);
477    }
478
479    /**
480     * Returns the Username value of this AuthorizationHeader. This convenience
481     * method returns only the username of the complete Response.
482     *
483     * @return the String representing the Username information, null if value
484     *         is not set.
485     *
486     *
487     *
488     */
489    public String getUsername() {
490        return (String) getParameter(ParameterNames.USERNAME);
491    }
492
493    /**
494     * Sets the Username of the AuthorizationHeader to the <var>username</var>
495     * parameter value.
496     *
497     * @param username
498     *            the new Username String of this AuthorizationHeader.
499     *
500     * @throws ParseException
501     *             which signals that an error has been reached
502     *
503     * unexpectedly while parsing the username.
504     *
505     *
506     *
507     */
508    public void setUsername(String username) throws ParseException {
509        this.setParameter(ParameterNames.USERNAME, username);
510    }
511
512    public void setIK(String ik) throws ParseException {
513        if (ik == null)
514            throw new NullPointerException(
515                "JAIN-SIP Exception, "
516                    + " AuthenticationHeader, setIk(), The auth-param IK parameter is null");
517        setParameter(IK, ik);
518    }
519
520    public String getIK() {
521        return getParameter(ParameterNamesIms.IK);
522    }
523
524    public void setCK(String ck) throws ParseException {
525        if (ck == null)
526            throw new NullPointerException(
527                "JAIN-SIP Exception, "
528                    + " AuthenticationHeader, setCk(), The auth-param CK parameter is null");
529        setParameter(CK, ck);
530    }
531
532    public String getCK() {
533        return getParameter(ParameterNamesIms.CK);
534    }
535
536
537    public void setIntegrityProtected(String integrityProtected) throws ParseException
538    {
539        if (integrityProtected == null)
540            throw new NullPointerException(
541                "JAIN-SIP Exception, "
542                    + " AuthenticationHeader, setIntegrityProtected(), The integrity-protected parameter is null");
543
544        setParameter(INTEGRITY_PROTECTED, integrityProtected);
545    }
546
547
548
549    public String getIntegrityProtected() {
550        return getParameter(ParameterNamesIms.INTEGRITY_PROTECTED);
551    }
552
553}
554