1
2
3
4
5
6
7 package org.mule.transport.http.ntlm;
8
9 import jcifs.ntlmssp.NtlmMessage;
10 import jcifs.ntlmssp.Type2Message;
11 import org.apache.commons.httpclient.Credentials;
12 import org.apache.commons.httpclient.HttpMethod;
13 import org.apache.commons.httpclient.NTCredentials;
14 import org.apache.commons.httpclient.auth.AuthChallengeParser;
15 import org.apache.commons.httpclient.auth.AuthScheme;
16 import org.apache.commons.httpclient.auth.AuthenticationException;
17 import org.apache.commons.httpclient.auth.InvalidCredentialsException;
18 import org.apache.commons.httpclient.auth.MalformedChallengeException;
19
20 import static jcifs.util.Base64.encode;
21
22
23
24
25
26
27
28
29
30 public class NTLMScheme implements AuthScheme
31 {
32
33 private static enum AUTHENTICATION_STATE
34 {
35 UNINITIATED, INITIATED, TYPE1_MSG_GENERATED, TYPE2_MSG_RECEIVED, TYPE3_MSG_GENERATED, FAILED
36 }
37
38 private static final String NOT_IMPLEMENTED_ERROR = "Not implemented as it is deprecated anyway in Httpclient 3.x";
39
40
41
42
43 private AUTHENTICATION_STATE authenticationState = AUTHENTICATION_STATE.UNINITIATED;
44
45
46
47
48 private String receivedNtlmChallenge = null;
49
50
51
52
53 private final NtlmMessageFactory ntlmMessageFactory = new NtlmMessageFactory();
54
55 public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException
56 {
57 if (authenticationState == AUTHENTICATION_STATE.UNINITIATED)
58 {
59 throw new IllegalStateException("NTLM authentication process has not been initiated");
60 }
61
62 NtlmMessage response;
63
64 NTCredentials ntcredentials = getNTCredentials(credentials);
65 if (authenticationState == AUTHENTICATION_STATE.INITIATED || authenticationState == AUTHENTICATION_STATE.FAILED)
66 {
67
68 response = ntlmMessageFactory.createType1Message(null, null);
69 authenticationState = AUTHENTICATION_STATE.TYPE1_MSG_GENERATED;
70 }
71 else
72 {
73 Type2Message type2MessageFromChallenge = ntlmMessageFactory.createType2Message(receivedNtlmChallenge);
74 response = ntlmMessageFactory.createType3Message(ntcredentials, type2MessageFromChallenge);
75 authenticationState = AUTHENTICATION_STATE.TYPE3_MSG_GENERATED;
76 }
77
78 return ntlmMessageToString(response);
79 }
80
81 private NTCredentials getNTCredentials(Credentials credentials) throws InvalidCredentialsException
82 {
83 try
84 {
85 return (NTCredentials) credentials;
86 }
87 catch (ClassCastException e)
88 {
89 throw new InvalidCredentialsException("Credentials cannot be used for NTLM authentication: "
90 + credentials.getClass().getName());
91 }
92 }
93
94 public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException
95 {
96 throw new RuntimeException(NOT_IMPLEMENTED_ERROR);
97 }
98
99 public String getID()
100 {
101 throw new RuntimeException(NOT_IMPLEMENTED_ERROR);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115 public String getParameter(String name)
116 {
117 if (name == null)
118 {
119 throw new IllegalArgumentException("Parameter name may not be null");
120 }
121
122 return null;
123 }
124
125
126
127
128
129
130
131
132 public String getRealm()
133 {
134 return null;
135 }
136
137
138
139
140
141
142 public String getSchemeName()
143 {
144 return "ntlm";
145 }
146
147
148
149
150
151
152
153 public boolean isComplete()
154 {
155 return authenticationState == AUTHENTICATION_STATE.TYPE3_MSG_GENERATED || authenticationState == AUTHENTICATION_STATE.FAILED;
156 }
157
158
159
160
161
162
163 public boolean isConnectionBased()
164 {
165 return true;
166 }
167
168
169
170
171
172
173
174 public void processChallenge(final String challenge) throws MalformedChallengeException
175 {
176 String s = AuthChallengeParser.extractScheme(challenge);
177
178 if (!s.equalsIgnoreCase(getSchemeName()))
179 {
180 throw new MalformedChallengeException("Invalid NTLM challenge: " + challenge);
181 }
182
183 int i = challenge.indexOf(' ');
184
185 if (i != -1)
186 {
187 s = challenge.substring(i, challenge.length());
188 receivedNtlmChallenge = s.trim();
189 authenticationState = AUTHENTICATION_STATE.TYPE2_MSG_RECEIVED;
190 }
191 else
192 {
193 receivedNtlmChallenge = null;
194 authenticationState = authenticationState == AUTHENTICATION_STATE.UNINITIATED ? AUTHENTICATION_STATE.INITIATED : AUTHENTICATION_STATE.FAILED;
195 }
196 }
197
198 private String ntlmMessageToString(NtlmMessage ntlmMessage)
199 {
200 return "NTLM " + encode(ntlmMessage.toByteArray());
201 }
202 }