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.Map;
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 public class DigestUtilities {
41
42 public static final String SESSION_HA1 = DigestUtilities.class + ".SessionHA1";
43
44 private static MessageDigest md5;
45
46 static {
47
48 try {
49 md5 = MessageDigest.getInstance("MD5");
50 } catch (NoSuchAlgorithmException e) {
51 throw new RuntimeException(e);
52 }
53 }
54
55
56
57
58 public static final String[] SUPPORTED_QOPS = new String[] { "auth", "auth-int" };
59
60 private DigestUtilities() {
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 public static String computeResponseValue(IoSession session, Map<String, String> map, String method,
78 String pwd, String charsetName, String body) throws AuthenticationException, UnsupportedEncodingException{
79
80 byte[] hA1;
81 StringBuilder sb;
82 boolean isMD5Sess = "md5-sess".equalsIgnoreCase(StringUtilities.getDirectiveValue(map, "algorithm", false));
83
84 if (!isMD5Sess || (session.getAttribute(SESSION_HA1) == null)) {
85
86 sb = new StringBuilder();
87 sb.append(StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "username", true))).append(
88 ':');
89
90 String realm = StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "realm", false));
91
92 if (realm != null) {
93 sb.append(realm);
94 }
95
96 sb.append(':').append(pwd);
97
98 if (isMD5Sess) {
99 byte[] prehA1;
100
101 synchronized (md5) {
102 md5.reset();
103 prehA1 = md5.digest(sb.toString().getBytes(charsetName));
104 }
105
106 sb = new StringBuilder();
107 sb.append(ByteUtilities.asHex(prehA1));
108 sb.append(':').append(
109 StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "nonce", true)));
110 sb.append(':').append(
111 StringUtilities.stringTo8859_1(StringUtilities.getDirectiveValue(map, "cnonce", true)));
112
113 synchronized (md5) {
114 md5.reset();
115 hA1 = md5.digest(sb.toString().getBytes(charsetName));
116 }
117
118 session.setAttribute(SESSION_HA1, hA1);
119 } else {
120 synchronized (md5) {
121 md5.reset();
122 hA1 = md5.digest(sb.toString().getBytes(charsetName));
123 }
124 }
125 } else {
126 hA1 = (byte[]) session.getAttribute(SESSION_HA1);
127 }
128
129 sb = new StringBuilder(method);
130 sb.append(':');
131 sb.append(StringUtilities.getDirectiveValue(map, "uri", false));
132
133 String qop = StringUtilities.getDirectiveValue(map, "qop", false);
134
135 if ("auth-int".equalsIgnoreCase(qop)) {
136 ProxyIoSession./../org/apache/mina/proxy/session/ProxyIoSession.html#ProxyIoSession">ProxyIoSession proxyIoSession = (ProxyIoSession) session.getAttribute(ProxyIoSession.PROXY_SESSION);
137 byte[] hEntity;
138
139 synchronized (md5) {
140 md5.reset();
141 hEntity = md5.digest(body.getBytes(proxyIoSession.getCharsetName()));
142 }
143
144 sb.append(':').append(hEntity);
145 }
146
147 byte[] hA2;
148 synchronized (md5) {
149 md5.reset();
150 hA2 = md5.digest(sb.toString().getBytes(charsetName));
151 }
152
153 sb = new StringBuilder();
154 sb.append(ByteUtilities.asHex(hA1));
155 sb.append(':').append(StringUtilities.getDirectiveValue(map, "nonce", true));
156 sb.append(":00000001:");
157
158 sb.append(StringUtilities.getDirectiveValue(map, "cnonce", true));
159 sb.append(':').append(qop).append(':');
160 sb.append(ByteUtilities.asHex(hA2));
161
162 byte[] hFinal;
163
164 synchronized (md5) {
165 md5.reset();
166 hFinal = md5.digest(sb.toString().getBytes(charsetName));
167 }
168
169 return ByteUtilities.asHex(hFinal);
170 }
171 }