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