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.ntlm;
21
22 import java.io.IOException;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.mina.core.filterchain.IoFilter.NextFilter;
28 import org.apache.mina.proxy.ProxyAuthException;
29 import org.apache.mina.proxy.handlers.http.AbstractAuthLogicHandler;
30 import org.apache.mina.proxy.handlers.http.HttpProxyConstants;
31 import org.apache.mina.proxy.handlers.http.HttpProxyRequest;
32 import org.apache.mina.proxy.handlers.http.HttpProxyResponse;
33 import org.apache.mina.proxy.session.ProxyIoSession;
34 import org.apache.mina.proxy.utils.StringUtilities;
35 import org.apache.mina.util.Base64;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39
40
41
42
43
44
45 public class HttpNTLMAuthLogicHandler extends AbstractAuthLogicHandler {
46
47 private static final Logger LOGGER = LoggerFactory.getLogger(HttpNTLMAuthLogicHandler.class);
48
49
50
51
52 private byte[] challengePacket = null;
53
54
55
56
57
58
59
60 public HttpNTLMAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException {
61 super(proxyIoSession);
62
63 ((HttpProxyRequest) request).checkRequiredProperties(HttpProxyConstants.USER_PROPERTY,
64 HttpProxyConstants.PWD_PROPERTY, HttpProxyConstants.DOMAIN_PROPERTY,
65 HttpProxyConstants.WORKSTATION_PROPERTY);
66 }
67
68
69
70
71 @Override
72 public void doHandshake(NextFilter nextFilter) throws ProxyAuthException {
73 if (LOGGER.isDebugEnabled()) {
74 LOGGER.debug(" doHandshake()");
75 }
76
77 if (step > 0 && challengePacket == null) {
78 throw new IllegalStateException("NTLM Challenge packet not received");
79 }
80
81 HttpProxyRequest./../../../../org/apache/mina/proxy/handlers/http/HttpProxyRequest.html#HttpProxyRequest">HttpProxyRequest req = (HttpProxyRequest) request;
82 Map<String, List<String>> headers = req.getHeaders() != null ? req.getHeaders()
83 : new HashMap<String, List<String>>();
84
85 String domain = req.getProperties().get(HttpProxyConstants.DOMAIN_PROPERTY);
86 String workstation = req.getProperties().get(HttpProxyConstants.WORKSTATION_PROPERTY);
87
88 if (step > 0) {
89 if (LOGGER.isDebugEnabled()) {
90 LOGGER.debug(" sending NTLM challenge response");
91 }
92
93 byte[] challenge = NTLMUtilities.extractChallengeFromType2Message(challengePacket);
94 int serverFlags = NTLMUtilities.extractFlagsFromType2Message(challengePacket);
95
96 String username = req.getProperties().get(HttpProxyConstants.USER_PROPERTY);
97 String password = req.getProperties().get(HttpProxyConstants.PWD_PROPERTY);
98
99 byte[] authenticationPacket = NTLMUtilities.createType3Message(username, password, challenge, domain,
100 workstation, serverFlags, null);
101
102 StringUtilities.addValueToHeader(headers, "Proxy-Authorization",
103 "NTLM " + new String(Base64.encodeBase64(authenticationPacket)), true);
104
105 } else {
106 if (LOGGER.isDebugEnabled()) {
107 LOGGER.debug(" sending NTLM negotiation packet");
108 }
109
110 byte[] negotiationPacket = NTLMUtilities.createType1Message(workstation, domain, null, null);
111 StringUtilities.addValueToHeader(headers, "Proxy-Authorization",
112 "NTLM " + new String(Base64.encodeBase64(negotiationPacket)), true);
113 }
114
115 addKeepAliveHeaders(headers);
116 req.setHeaders(headers);
117
118 writeRequest(nextFilter, req);
119 step++;
120 }
121
122
123
124
125
126
127 private String getNTLMHeader(final HttpProxyResponse response) {
128 List<String> values = response.getHeaders().get("Proxy-Authenticate");
129
130 for (String s : values) {
131 if (s.startsWith("NTLM")) {
132 return s;
133 }
134 }
135
136 return null;
137 }
138
139
140
141
142 @Override
143 public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException {
144 if (step == 0) {
145 String challengeResponse = getNTLMHeader(response);
146 step = 1;
147
148 if (challengeResponse == null || challengeResponse.length() < 5) {
149
150
151 return;
152 }
153
154
155 }
156
157 if (step == 1) {
158
159
160 String challengeResponse = getNTLMHeader(response);
161
162 if (challengeResponse == null || challengeResponse.length() < 5) {
163 throw new ProxyAuthException("Unexpected error while reading server challenge !");
164 }
165
166 try {
167 challengePacket = Base64.decodeBase64(challengeResponse.substring(5).getBytes(
168 proxyIoSession.getCharsetName()));
169 } catch (IOException e) {
170 throw new ProxyAuthException("Unable to decode the base64 encoded NTLM challenge", e);
171 }
172 step = 2;
173 } else {
174 throw new ProxyAuthException("Received unexpected response code (" + response.getStatusLine() + ").");
175 }
176 }
177 }