1 31 32 package org.apache.commons.httpclient.auth; 33 34 import java.util.Map ; 35 import java.security.MessageDigest ; 36 37 import org.apache.commons.httpclient.HttpConstants; 38 import org.apache.commons.httpclient.Credentials; 39 import org.apache.commons.httpclient.UsernamePasswordCredentials; 40 import org.apache.commons.logging.Log; 41 import org.apache.commons.logging.LogFactory; 42 43 57 58 public class DigestScheme extends RFC2617Scheme { 59 60 61 private static final Log LOG = LogFactory.getLog(DigestScheme.class); 62 63 69 private static final char[] HEXADECIMAL = { 70 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 71 'e', 'f' 72 }; 73 74 81 public String getID() { 82 83 String id = getRealm(); 84 String nonce = getParameter("nonce"); 85 if (nonce != null) { 86 id += "-" + nonce; 87 } 88 89 return id; 90 } 91 92 100 public DigestScheme(final String challenge) 101 throws MalformedChallengeException { 102 super(challenge); 103 if (this.getParameter("realm") == null) { 104 throw new MalformedChallengeException("realm missing"); 105 } 106 if (this.getParameter("nonce") == null) { 107 throw new MalformedChallengeException("nonce missing"); 108 } 109 this.getParameters().put("nc", "00000001"); 110 } 111 112 113 118 public String getSchemeName() { 119 return "digest"; 120 } 121 122 138 public String authenticate(Credentials credentials, String method, String uri) 139 throws AuthenticationException { 140 141 LOG.trace("enter DigestScheme.authenticate(Credentials, String, String)"); 142 143 UsernamePasswordCredentials usernamepassword = null; 144 try { 145 usernamepassword = (UsernamePasswordCredentials) credentials; 146 } catch (ClassCastException e) { 147 throw new AuthenticationException( 148 "Credentials cannot be used for digest authentication: " 149 + credentials.getClass().getName()); 150 } 151 this.getParameters().put("cnonce", createCnonce()); 152 this.getParameters().put("methodname", method); 153 this.getParameters().put("uri", uri); 154 return DigestScheme.authenticate(usernamepassword, getParameters()); 155 } 156 157 172 public static String authenticate(UsernamePasswordCredentials credentials, 173 Map params) throws AuthenticationException { 174 175 LOG.trace("enter DigestScheme.authenticate(UsernamePasswordCredentials, Map)"); 176 177 String digest = createDigest(credentials.getUserName(), 178 credentials.getPassword(), params); 179 180 return "Digest " + createDigestHeader(credentials.getUserName(), 181 params, digest); 182 } 183 184 198 public static String createDigest(String uname, String pwd, 199 Map params) throws AuthenticationException { 200 201 LOG.trace("enter DigestScheme.createDigest(String, String, Map)"); 202 203 final String digAlg = "MD5"; 204 205 String uri = (String ) params.get("uri"); 207 String realm = (String ) params.get("realm"); 208 String nonce = (String ) params.get("nonce"); 209 String nc = (String ) params.get("nc"); 210 String cnonce = (String ) params.get("cnonce"); 211 String qop = (String ) params.get("qop"); 212 String method = (String ) params.get("methodname"); 213 String algorithm = (String ) params.get("algorithm"); 214 215 if(algorithm == null) { 217 algorithm="MD5"; 218 } 219 220 if (qop != null) { 221 qop = "auth"; 222 } 223 224 MessageDigest md5Helper; 225 226 try { 227 md5Helper = MessageDigest.getInstance(digAlg); 228 } catch (Exception e) { 229 throw new AuthenticationException( 230 "Unsupported algorithm in HTTP Digest authentication: " 231 + digAlg); 232 } 233 234 236 String a1 = null; 237 if(algorithm.equals("MD5")) { 238 a1 = uname + ":" + realm + ":" + pwd; 240 } else if(algorithm.equals("MD5-sess")) { 241 245 String tmp=encode(md5Helper.digest(HttpConstants.getContentBytes( 246 uname + ":" + realm + ":" + pwd))); 247 248 a1 = tmp + ":" + nonce + ":" + cnonce; 249 } else { 250 LOG.warn("Unhandled algorithm " + algorithm + " requested"); 251 a1 = uname + ":" + realm + ":" + pwd; 252 } 253 String md5a1 = encode(md5Helper.digest(HttpConstants.getContentBytes(a1))); 254 String serverDigestValue; 255 256 String a2 = method + ":" + uri; 257 String md5a2 = encode(md5Helper.digest(HttpConstants.getBytes(a2))); 258 259 if (qop == null) { 260 LOG.debug("Using null qop method"); 261 serverDigestValue = md5a1 + ":" + nonce + ":" + md5a2; 262 } else { 263 LOG.debug("Using qop method " + qop); 264 serverDigestValue = md5a1 + ":" + nonce + ":" + nc + ":" + cnonce 265 + ":" + qop + ":" + md5a2; 266 } 267 268 String serverDigest = 269 encode(md5Helper.digest(HttpConstants.getBytes(serverDigestValue))); 270 271 return serverDigest; 272 } 273 274 286 public static String createDigestHeader(String uname, Map params, 287 String digest) { 288 289 LOG.trace("enter DigestScheme.createDigestHeader(String, Map, " 290 + "String)"); 291 292 StringBuffer sb = new StringBuffer (); 293 String uri = (String ) params.get("uri"); 294 String realm = (String ) params.get("realm"); 295 String nonce = (String ) params.get("nonce"); 296 String nc = (String ) params.get("nc"); 297 String cnonce = (String ) params.get("cnonce"); 298 String opaque = (String ) params.get("opaque"); 299 String response = digest; 300 String qop = (String ) params.get("qop"); 301 String algorithm = (String ) params.get("algorithm"); 302 303 if (qop != null) { 304 qop = "auth"; } 306 307 sb.append("username=\"" + uname + "\"") 308 .append(", realm=\"" + realm + "\"") 309 .append(", nonce=\"" + nonce + "\"") 310 .append(", uri=\"" + uri + "\"") 311 .append(((qop == null) ? "" : ", qop=\"" + qop + "\"")) 312 .append((algorithm == null) ? "" : ", algorithm=\"" + algorithm + "\"") 313 .append(((qop == null) ? "" : ", nc=" + nc)) 314 .append(((qop == null) ? "" : ", cnonce=\"" + cnonce + "\"")) 315 .append(", response=\"" + response + "\"") 316 .append((opaque == null) ? "" : ", opaque=\"" + opaque + "\""); 317 318 return sb.toString(); 319 } 320 321 322 329 private static String encode(byte[] binaryData) { 330 LOG.trace("enter DigestScheme.encode(byte[])"); 331 332 if (binaryData.length != 16) { 333 return null; 334 } 335 336 char[] buffer = new char[32]; 337 for (int i = 0; i < 16; i++) { 338 int low = (int) (binaryData[i] & 0x0f); 339 int high = (int) ((binaryData[i] & 0xf0) >> 4); 340 buffer[i * 2] = HEXADECIMAL[high]; 341 buffer[(i * 2) + 1] = HEXADECIMAL[low]; 342 } 343 344 return new String (buffer); 345 } 346 347 348 354 public static String createCnonce() throws AuthenticationException { 355 LOG.trace("enter DigestScheme.createCnonce()"); 356 357 String cnonce; 358 final String digAlg = "MD5"; 359 MessageDigest md5Helper; 360 361 try { 362 md5Helper = MessageDigest.getInstance(digAlg); 363 } catch (Exception e) { 364 throw new AuthenticationException( 365 "Unsupported algorithm in HTTP Digest authentication: " 366 + digAlg); 367 } 368 369 cnonce = Long.toString(System.currentTimeMillis()); 370 cnonce = encode(md5Helper.digest(HttpConstants.getBytes(cnonce))); 371 372 return cnonce; 373 } 374 } 375 | Popular Tags |