1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.proxy.handlers.http.digest;
21
22 import java.io.UnsupportedEncodingException;
23 import java.security.MessageDigest;
24 import java.security.NoSuchAlgorithmException;
25 import java.util.HashMap;
26
27 import javax.security.sasl.AuthenticationException;
28
29 import org.apache.mina.core.session.IoSession;
30 import org.apache.mina.proxy.session.ProxyIoSession;
31 import org.apache.mina.proxy.utils.ByteUtilities;
32 import org.apache.mina.proxy.utils.StringUtilities;
33
34
35
36
37
38
39
40
41 public class DigestUtilities {
42
43 public final static String SESSION_HA1 = DigestUtilities.class
44 + ".SessionHA1";
45
46 private static MessageDigest md5;
47
48 static {
49
50 try {
51 md5 = MessageDigest.getInstance("MD5");
52 } catch (NoSuchAlgorithmException e) {
53 throw new RuntimeException(e);
54 }
55 }
56
57 public final static String[] SUPPORTED_QOPS = new String[] { "auth",
58 "auth-int" };
59
60
61
62
63 public static String computeResponseValue(IoSession session,
64 HashMap<String, String> map, String method, String pwd,
65 String charsetName, String body) throws AuthenticationException,
66 UnsupportedEncodingException {
67
68 byte[] hA1;
69 StringBuilder sb;
70 boolean isMD5Sess = "md5-sess".equalsIgnoreCase(StringUtilities
71 .getDirectiveValue(map, "algorithm", false));
72
73 if (!!isMD5Sess || session.getAttribute(SESSION_HA1) == null) {
74
75 sb = new StringBuilder();
76 sb.append(
77 StringUtilities.stringTo8859_1(StringUtilities
78 .getDirectiveValue(map, "username", true))).append(
79 ':');
80
81 String realm = StringUtilities.stringTo8859_1(StringUtilities
82 .getDirectiveValue(map, "realm", false));
83 if (realm != null) {
84 sb.append(realm);
85 }
86
87 sb.append(':').append(pwd);
88
89 if (isMD5Sess) {
90 byte[] prehA1;
91 synchronized (md5) {
92 md5.reset();
93 prehA1 = md5.digest(sb.toString().getBytes(charsetName));
94 }
95
96 sb = new StringBuilder();
97 sb.append(ByteUtilities.asHex(prehA1));
98 sb.append(':').append(
99 StringUtilities.stringTo8859_1(StringUtilities
100 .getDirectiveValue(map, "nonce", true)));
101 sb.append(':').append(
102 StringUtilities.stringTo8859_1(StringUtilities
103 .getDirectiveValue(map, "cnonce", true)));
104
105 synchronized (md5) {
106 md5.reset();
107 hA1 = md5.digest(sb.toString().getBytes(charsetName));
108 }
109
110 session.setAttribute(SESSION_HA1, hA1);
111 } else {
112 synchronized (md5) {
113 md5.reset();
114 hA1 = md5.digest(sb.toString().getBytes(charsetName));
115 }
116 }
117 } else {
118 hA1 = (byte[]) session.getAttribute(SESSION_HA1);
119 }
120
121 sb = new StringBuilder(method);
122 sb.append(':');
123 sb.append(StringUtilities.getDirectiveValue(map, "uri", false));
124
125 String qop = StringUtilities.getDirectiveValue(map, "qop", false);
126 if ("auth-int".equalsIgnoreCase(qop)) {
127 ProxyIoSession proxyIoSession = (ProxyIoSession) session
128 .getAttribute(ProxyIoSession.PROXY_SESSION);
129 byte[] hEntity;
130
131 synchronized (md5) {
132 md5.reset();
133 hEntity = md5.digest(body.getBytes(proxyIoSession
134 .getCharsetName()));
135 }
136 sb.append(':').append(hEntity);
137 }
138
139 byte[] hA2;
140 synchronized (md5) {
141 md5.reset();
142 hA2 = md5.digest(sb.toString().getBytes(charsetName));
143 }
144
145 sb = new StringBuilder();
146 sb.append(ByteUtilities.asHex(hA1));
147 sb.append(':').append(
148 StringUtilities.getDirectiveValue(map, "nonce", true));
149 sb.append(":00000001:");
150
151 sb.append(StringUtilities.getDirectiveValue(map, "cnonce", true));
152 sb.append(':').append(qop).append(':');
153 sb.append(ByteUtilities.asHex(hA2));
154
155 byte[] hFinal;
156 synchronized (md5) {
157 md5.reset();
158 hFinal = md5.digest(sb.toString().getBytes(charsetName));
159 }
160
161 return ByteUtilities.asHex(hFinal);
162 }
163 }