001: package examples.authorization;
002:
003: import java.security.*;
004: import java.util.*;
005:
006: import javax.sip.*;
007: import javax.sip.message.*;
008: import javax.sip.header.*;
009: import javax.sip.address.*;
010:
011: /**
012: * Implements the HTTP digest authentication method.
013: * @author M. Ranganathan
014: * @author Marc Bednarek
015: */
016: public class DigestServerAuthenticationMethod implements
017: AuthenticationMethod {
018:
019: public static final String DEFAULT_SCHEME = "Digest";
020:
021: public static final String DEFAULT_DOMAIN = "127.0.0.1";
022:
023: public static final String DEFAULT_ALGORITHM = "MD5";
024:
025: public static String DEFAULT_REALM = "nist.gov";
026:
027: String USER_AUTH = "auth";
028:
029: String PASS_AUTH = "pass";
030:
031: private MessageDigest messageDigest;
032:
033: /** to hex converter */
034: private static final char[] toHex = { '0', '1', '2', '3', '4', '5',
035: '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
036:
037: /**
038: * Default constructor.
039: */
040: public DigestServerAuthenticationMethod() {
041: try {
042: messageDigest = MessageDigest
043: .getInstance(DEFAULT_ALGORITHM);
044: } catch (NoSuchAlgorithmException ex) {
045: System.out.println("Algorithm not found " + ex);
046: ex.printStackTrace();
047: }
048: }
049:
050: public static String toHexString(byte b[]) {
051: int pos = 0;
052: char[] c = new char[b.length * 2];
053: for (int i = 0; i < b.length; i++) {
054: c[pos++] = toHex[(b[i] >> 4) & 0x0F];
055: c[pos++] = toHex[b[i] & 0x0f];
056: }
057: return new String(c);
058: }
059:
060: /**
061: * Initialize
062: */
063: public void initialize() {
064: System.out
065: .println("DEBUG, DigestAuthenticationMethod, initialize(),"
066: + " the realm is:" + DEFAULT_REALM);
067: }
068:
069: /**
070: * Get the authentication scheme
071: *
072: * @return the scheme name
073: */
074: public String getScheme() {
075: return DEFAULT_SCHEME;
076: }
077:
078: /**
079: * get the authentication realm
080: *
081: * @return the realm name
082: */
083: public String getRealm(String resource) {
084: return DEFAULT_REALM;
085: }
086:
087: /**
088: * get the authentication domain.
089: *
090: * @return the domain name
091: */
092: public String getDomain() {
093: return DEFAULT_DOMAIN;
094: }
095:
096: /**
097: * Get the authentication Algorithm
098: *
099: * @return the alogirithm name (i.e. Digest).
100: */
101: public String getAlgorithm() {
102: return DEFAULT_ALGORITHM;
103: }
104:
105: /**
106: * Generate the challenge string.
107: *
108: * @return a generated nonce.
109: */
110: public String generateNonce() {
111: // Get the time of day and run MD5 over it.
112: Date date = new Date();
113: long time = date.getTime();
114: Random rand = new Random();
115: long pad = rand.nextLong();
116: String nonceString = (new Long(time)).toString()
117: + (new Long(pad)).toString();
118: byte mdbytes[] = messageDigest.digest(nonceString.getBytes());
119: // Convert the mdbytes array into a hex string.
120: return toHexString(mdbytes);
121: }
122:
123: /**
124: * Check the response and answer true if authentication succeeds. We are
125: * making simplifying assumptions here and assuming that the password is
126: * available to us for computation of the MD5 hash. We also dont cache
127: * authentications so that the user has to authenticate on each
128: * registration.
129: *
130: * @param user
131: * is the username
132: * @param authHeader
133: * is the Authroization header from the SIP request.
134: * @param requestLine
135: * is the SIP Request line from the SIP request.
136: * @exception SIPAuthenticationException
137: * is thrown when authentication fails or message is bad
138: */
139: public boolean doAuthenticate(String user,
140: AuthorizationHeader authHeader, Request request) {
141: String realm = authHeader.getRealm();
142: String username = authHeader.getUsername();
143: URI requestURI = request.getRequestURI();
144:
145: if (username == null) {
146: System.out
147: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
148: + "WARNING: userName parameter not set in the header received!!!");
149: username = user;
150: }
151: if (realm == null) {
152: System.out
153: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
154: + "WARNING: realm parameter not set in the header received!!! WE use the default one");
155: realm = DEFAULT_REALM;
156: }
157:
158: System.out
159: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
160: + "Trying to authenticate user: "
161: + username
162: + " for " + " the realm: " + realm);
163:
164: String nonce = authHeader.getNonce();
165: // If there is a URI parameter in the Authorization header,
166: // then use it.
167: URI uri = authHeader.getURI();
168: // There must be a URI parameter in the authorization header.
169: if (uri == null) {
170: System.out
171: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
172: + "ERROR: uri paramater not set in the header received!");
173: return false;
174: }
175: System.out
176: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), username:"
177: + username + "!");
178: System.out
179: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), realm:"
180: + realm + "!");
181: System.out
182: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), password:"
183: + PASS_AUTH + "!");
184: System.out
185: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), uri:"
186: + uri + "!");
187: System.out
188: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), nonce:"
189: + nonce + "!");
190: System.out
191: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), method:"
192: + request.getMethod() + "!");
193:
194: String A1 = username + ":" + realm + ":" + PASS_AUTH;
195: String A2 = request.getMethod().toUpperCase() + ":"
196: + uri.toString();
197: byte mdbytes[] = messageDigest.digest(A1.getBytes());
198: String HA1 = toHexString(mdbytes);
199:
200: System.out
201: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), HA1:"
202: + HA1 + "!");
203: mdbytes = messageDigest.digest(A2.getBytes());
204: String HA2 = toHexString(mdbytes);
205: System.out
206: .println("DEBUG, DigestAuthenticationMethod, doAuthenticate(), HA2:"
207: + HA2 + "!");
208: String cnonce = authHeader.getCNonce();
209: String KD = HA1 + ":" + nonce;
210: if (cnonce != null) {
211: KD += ":" + cnonce;
212: }
213: KD += ":" + HA2;
214: mdbytes = messageDigest.digest(KD.getBytes());
215: String mdString = toHexString(mdbytes);
216: String response = authHeader.getResponse();
217: System.out
218: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
219: + "we have to compare his response: "
220: + response
221: + " with our computed"
222: + " response: " + mdString);
223:
224: int res = (mdString.compareTo(response));
225: if (res == 0) {
226: System.out
227: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
228: + "User authenticated...");
229: } else {
230: System.out
231: .println("DEBUG, DigestAuthenticateMethod, doAuthenticate(): "
232: + "User not authenticated...");
233: }
234: return res == 0;
235: }
236:
237: }
|