KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > curl > Authentication


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Nam Nguyen
28  */

29
30 package com.caucho.quercus.lib.curl;
31
32 import com.caucho.quercus.QuercusModuleException;
33 import com.caucho.util.Base64;
34 import com.caucho.util.CharBuffer;
35 import com.caucho.util.RandomUtil;
36
37 import java.security.MessageDigest JavaDoc;
38 import java.security.NoSuchAlgorithmException JavaDoc;
39
40 public class Authentication
41 {
42   /**
43    * Returns an authorization response string.
44    * Supports digest and basic only.
45    */

46   public static String JavaDoc getAuthorization(String JavaDoc user,
47                               String JavaDoc pass,
48                               String JavaDoc requestMethod,
49                               String JavaDoc uri,
50                               String JavaDoc header)
51   {
52     if (header.startsWith("Digest"))
53       return digest(user, pass, requestMethod, uri, header);
54     else
55       return basic(user, pass);
56   }
57
58   /**
59    * Returns a basic encoded response string.
60    */

61   public static String JavaDoc basic(String JavaDoc user, String JavaDoc pass)
62   {
63     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
64
65     sb.append(user);
66     sb.append(':');
67     sb.append(pass);
68
69     return basic(sb.toString());
70   }
71
72   public static String JavaDoc basic(String JavaDoc usernamePassword)
73   {
74     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
75
76     sb.append("Basic ");
77     sb.append(Base64.encode(usernamePassword));
78
79     return sb.toString();
80   }
81
82   /**
83    * Returns a digest encoded response string.
84    */

85   public static String JavaDoc digest(String JavaDoc user,
86                               String JavaDoc pass,
87                               String JavaDoc requestMethod,
88                               String JavaDoc uri,
89                               String JavaDoc header)
90   {
91     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
92
93     sb.append("Digest ");
94     sb.append("username=\"");
95     sb.append(user);
96
97     Scanner scanner = new Scanner(header);
98
99     String JavaDoc realm = "";
100     String JavaDoc nonce = "";
101     String JavaDoc qop = "";
102     String JavaDoc opaque = null;
103     String JavaDoc algorithm = null;
104
105     String JavaDoc key;
106     while ((key = scanner.readKey())!= null) {
107       String JavaDoc value = scanner.readValue();
108
109       if (key.equals("realm"))
110         realm = value;
111       else if (key.equals("nonce"))
112         nonce = value;
113       else if (key.equals("qop"))
114         qop = value;
115       else if (key.equals("opaque"))
116         opaque = value;
117       else if (key.equals("algorithm"))
118         algorithm = value;
119     }
120
121     scanner.close();
122
123     sb.append("\", realm=\"");
124     sb.append(realm);
125
126     sb.append("\", nonce=\"");
127     sb.append(nonce);
128
129     sb.append("\", uri=\"");
130     sb.append(uri);
131
132     sb.append("\", qop=\"");
133     sb.append("auth");
134
135     String JavaDoc cnonce = Base64.encode(String.valueOf(RandomUtil.getRandomLong()));
136     sb.append("\", cnonce=\"");
137     sb.append(cnonce);
138
139     String JavaDoc nc = "00000001";
140     sb.append("\", nc=\"");
141     sb.append(nc);
142
143     if (opaque != null) {
144       sb.append("\", opaque=\"");
145       sb.append(opaque);
146     }
147
148     if (algorithm != null) {
149       sb.append("\", algorithm=\"");
150       sb.append(algorithm);
151     }
152     else
153       algorithm = "MD5";
154
155     sb.append("\", response=\"");
156     appendResponse(sb,
157                    user,
158                    realm,
159                    pass,
160                    requestMethod,
161                    uri,
162                    nonce,
163                    nc,
164                    cnonce,
165                    qop,
166                    algorithm);
167
168     sb.append('"');
169     return sb.toString();
170   }
171
172   /**
173    * Appends the authorization string to the StringBuilder.
174    */

175   private static void appendResponse(StringBuilder JavaDoc sb,
176                               String JavaDoc user,
177                               String JavaDoc realm,
178                               String JavaDoc pass,
179                               String JavaDoc requestMethod,
180                               String JavaDoc uri,
181                               String JavaDoc nonce,
182                               String JavaDoc nc,
183                               String JavaDoc cnonce,
184                               String JavaDoc qop,
185                               String JavaDoc algorithm)
186   {
187     MessageDigest JavaDoc resultDigest = null;
188     MessageDigest JavaDoc scratchDigest = null;
189
190     try {
191       resultDigest = MessageDigest.getInstance(algorithm);
192       scratchDigest = MessageDigest.getInstance(algorithm);
193     }
194     catch (NoSuchAlgorithmException JavaDoc e) {
195       throw new QuercusModuleException(e);
196     }
197
198     {
199       md5(scratchDigest, user);
200       scratchDigest.update((byte)':');
201
202       md5(scratchDigest, realm);
203       scratchDigest.update((byte)':');
204
205       md5(scratchDigest, pass);
206
207       update(resultDigest, scratchDigest.digest());
208       resultDigest.update((byte)':');
209     }
210
211     md5(resultDigest, nonce);
212     resultDigest.update((byte)':');
213
214     md5(resultDigest, nc);
215     resultDigest.update((byte)':');
216
217     md5(resultDigest, cnonce);
218     resultDigest.update((byte)':');
219
220     md5(resultDigest, qop);
221     resultDigest.update((byte)':');
222
223     {
224       scratchDigest.reset();
225
226       md5(scratchDigest, requestMethod);
227       scratchDigest.update((byte)':');
228
229       md5(scratchDigest, uri);
230
231       update(resultDigest, scratchDigest.digest());
232     }
233
234     appendHex(sb, resultDigest.digest());
235   }
236
237   /**
238    * Updates MD5 hash.
239    */

240   private static void md5(MessageDigest JavaDoc md,
241                               String JavaDoc string)
242   {
243     int length = string.length();
244     for (int i = 0; i < length; i++) {
245       md.update((byte)string.charAt(i));
246     }
247   }
248
249   /**
250    * Updates MD5 hash result.
251    */

252   private static void update(MessageDigest JavaDoc resultDigest,
253                               byte[] digest)
254   {
255     for (int i = 0; i < digest.length; i++) {
256       int d1 = (digest[i] >> 4) & 0xf;
257       int d2 = (digest[i] & 0xf);
258     
259       resultDigest.update((byte)toHexChar(d1));
260       resultDigest.update((byte)toHexChar(d2));
261     }
262   }
263
264   /**
265    * Appends hex characters to StringBuilder.
266    */

267   private static void appendHex(StringBuilder JavaDoc sb,
268                               byte[] digest)
269   {
270     for (int i = 0; i < digest.length; i++) {
271       int d1 = (digest[i] >> 4) & 0xf;
272       int d2 = (digest[i] & 0xf);
273     
274       sb.append(toHexChar(d1));
275       sb.append(toHexChar(d2));
276     }
277   }
278
279   private static char toHexChar(int d)
280   {
281     d &= 0xf;
282     
283     if (d < 10)
284       return (char) (d + '0');
285     else
286       return (char) (d - 10 + 'a');
287   }
288
289 }
290
291   /**
292    * Represents a HTTP header field values scanner.
293    */

294   class Scanner {
295     String JavaDoc _header;
296     int _position;
297     int _length;
298
299     CharBuffer _cb;
300
301     Scanner(String JavaDoc header)
302     {
303       _header = header;
304       _position = header.indexOf("Digest") + "Digest".length();
305       _length = header.length();
306
307       _cb = CharBuffer.allocate();
308     }
309
310     String JavaDoc readKey()
311     {
312       int ch = skipWhitespace();
313
314       if (ch < 0)
315         return null;
316
317       if (ch == ',')
318         ch = skipWhitespace();
319
320       do {
321         _cb.append((char)ch);
322       } while ((ch = read()) != '=');
323
324       // discard quote
325
read();
326
327       String JavaDoc key = _cb.toString();
328       _cb.clear();
329
330       return key;
331     }
332
333     String JavaDoc readValue()
334     {
335       int ch;
336       while ((ch = read()) != '"') {
337         _cb.append((char)ch);
338       }
339
340       String JavaDoc value = _cb.toString();
341       _cb.clear();
342
343       return value;
344     }
345
346     int skipWhitespace()
347     {
348       int ch;
349
350       while ((ch = read()) >= 0) {
351         if (ch != ' ' &&
352             ch != '\t' &&
353             ch != '\r' &&
354             ch != '\n' &&
355             ch != '\f')
356           break;
357       }
358
359       return ch;
360     }
361
362     int read()
363     {
364       if (_position >= _length)
365         return -1;
366       else
367         return _header.charAt(_position++);
368     }
369
370     void close()
371     {
372       _cb.free();
373     }
374   }
375
Popular Tags