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
46 public class HttpNTLMAuthLogicHandler extends AbstractAuthLogicHandler {
47
48 private final static Logger logger = LoggerFactory
49 .getLogger(HttpNTLMAuthLogicHandler.class);
50
51
52
53
54 private byte[] challengePacket = null;
55
56 public HttpNTLMAuthLogicHandler(final ProxyIoSession proxyIoSession)
57 throws ProxyAuthException {
58 super(proxyIoSession);
59
60 if (request == null || !(request instanceof HttpProxyRequest)) {
61 throw new IllegalArgumentException(
62 "request parameter should be a non null HttpProxyRequest instance");
63 }
64
65 HttpProxyRequest req = (HttpProxyRequest) request;
66 req.checkRequiredProperty(HttpProxyConstants.USER_PROPERTY);
67 req.checkRequiredProperty(HttpProxyConstants.PWD_PROPERTY);
68 req.checkRequiredProperty(HttpProxyConstants.DOMAIN_PROPERTY);
69 req.checkRequiredProperty(HttpProxyConstants.WORKSTATION_PROPERTY);
70 }
71
72 @Override
73 public void doHandshake(NextFilter nextFilter) throws ProxyAuthException {
74 logger.debug(" doHandshake()");
75
76 if (step > 0 && challengePacket == null) {
77 throw new IllegalStateException("Challenge packet not received");
78 } else {
79 HttpProxyRequest req = (HttpProxyRequest) request;
80 Map<String, List<String>> headers = req.getHeaders() != null ? req
81 .getHeaders() : new HashMap<String, List<String>>();
82
83 String domain = req.getProperties().get(
84 HttpProxyConstants.DOMAIN_PROPERTY);
85 String workstation = req.getProperties().get(
86 HttpProxyConstants.WORKSTATION_PROPERTY);
87
88 if (step > 0) {
89 logger.debug(" sending NTLM challenge response");
90
91 byte[] challenge = NTLMUtilities
92 .extractChallengeFromType2Message(challengePacket);
93 int serverFlags = NTLMUtilities
94 .extractFlagsFromType2Message(challengePacket);
95
96 String username = req.getProperties().get(
97 HttpProxyConstants.USER_PROPERTY);
98 String password = req.getProperties().get(
99 HttpProxyConstants.PWD_PROPERTY);
100
101 byte[] authenticationPacket = NTLMUtilities.createType3Message(
102 username, password, challenge, domain, workstation,
103 serverFlags, null);
104
105 StringUtilities.addValueToHeader(headers,
106 "Proxy-Authorization", "NTLM "
107 + new String(Base64
108 .encodeBase64(authenticationPacket)),
109 true);
110
111 } else {
112 logger.debug(" sending HTTP request");
113
114 byte[] negotiationPacket = NTLMUtilities.createType1Message(
115 workstation, domain, null, null);
116 StringUtilities
117 .addValueToHeader(
118 headers,
119 "Proxy-Authorization",
120 "NTLM "
121 + new String(
122 Base64
123 .encodeBase64(negotiationPacket)),
124 true);
125 }
126
127 StringUtilities.addValueToHeader(headers, "Keep-Alive",
128 HttpProxyConstants.DEFAULT_KEEP_ALIVE_TIME, true);
129 StringUtilities.addValueToHeader(headers, "Proxy-Connection",
130 "keep-Alive", true);
131 req.setHeaders(headers);
132
133 writeRequest(nextFilter, req);
134 step++;
135 }
136 }
137
138
139
140
141 private String getNTLMHeader(final HttpProxyResponse response) {
142 List<String> values = response.getHeaders().get("Proxy-Authenticate");
143
144 for (String s : values) {
145 if (s.startsWith("NTLM")) {
146 return s;
147 }
148 }
149
150 return null;
151 }
152
153 @Override
154 public void handleResponse(final HttpProxyResponse response)
155 throws ProxyAuthException {
156 if (step == 0) {
157 String challengeResponse = getNTLMHeader(response);
158 step = 1;
159
160 if (challengeResponse == null || challengeResponse.length() < 5) {
161
162 return;
163 }
164
165
166 }
167
168 if (step == 1) {
169
170
171 String challengeResponse = getNTLMHeader(response);
172
173 if (challengeResponse == null || challengeResponse.length() < 5) {
174 throw new ProxyAuthException(
175 "Unexpected error while reading server challenge !");
176 }
177
178 try {
179 challengePacket = Base64
180 .decodeBase64(challengeResponse.substring(5).getBytes(
181 proxyIoSession.getCharsetName()));
182 } catch (IOException e) {
183 throw new ProxyAuthException(
184 "Unable to decode the base64 encoded NTLM challenge", e);
185 }
186 step = 2;
187 } else {
188 throw new ProxyAuthException("Received unexpected response code ("
189 + response.getStatusLine() + ").");
190 }
191 }
192 }