1 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 ; 38 import java.security.NoSuchAlgorithmException ; 39 40 public class Authentication 41 { 42 46 public static String getAuthorization(String user, 47 String pass, 48 String requestMethod, 49 String uri, 50 String 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 61 public static String basic(String user, String pass) 62 { 63 StringBuilder sb = new StringBuilder (); 64 65 sb.append(user); 66 sb.append(':'); 67 sb.append(pass); 68 69 return basic(sb.toString()); 70 } 71 72 public static String basic(String usernamePassword) 73 { 74 StringBuilder sb = new StringBuilder (); 75 76 sb.append("Basic "); 77 sb.append(Base64.encode(usernamePassword)); 78 79 return sb.toString(); 80 } 81 82 85 public static String digest(String user, 86 String pass, 87 String requestMethod, 88 String uri, 89 String header) 90 { 91 StringBuilder sb = new StringBuilder (); 92 93 sb.append("Digest "); 94 sb.append("username=\""); 95 sb.append(user); 96 97 Scanner scanner = new Scanner(header); 98 99 String realm = ""; 100 String nonce = ""; 101 String qop = ""; 102 String opaque = null; 103 String algorithm = null; 104 105 String key; 106 while ((key = scanner.readKey())!= null) { 107 String 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 cnonce = Base64.encode(String.valueOf(RandomUtil.getRandomLong())); 136 sb.append("\", cnonce=\""); 137 sb.append(cnonce); 138 139 String 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 175 private static void appendResponse(StringBuilder sb, 176 String user, 177 String realm, 178 String pass, 179 String requestMethod, 180 String uri, 181 String nonce, 182 String nc, 183 String cnonce, 184 String qop, 185 String algorithm) 186 { 187 MessageDigest resultDigest = null; 188 MessageDigest scratchDigest = null; 189 190 try { 191 resultDigest = MessageDigest.getInstance(algorithm); 192 scratchDigest = MessageDigest.getInstance(algorithm); 193 } 194 catch (NoSuchAlgorithmException 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 240 private static void md5(MessageDigest md, 241 String 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 252 private static void update(MessageDigest 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 267 private static void appendHex(StringBuilder 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 294 class Scanner { 295 String _header; 296 int _position; 297 int _length; 298 299 CharBuffer _cb; 300 301 Scanner(String 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 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 read(); 326 327 String key = _cb.toString(); 328 _cb.clear(); 329 330 return key; 331 } 332 333 String readValue() 334 { 335 int ch; 336 while ((ch = read()) != '"') { 337 _cb.append((char)ch); 338 } 339 340 String 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 |