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