07dacfb5e06af7d7fd7cabafddcc5c197103730e
[samba.git] / source4 / libcli / auth / gensec_ntlmssp.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc authentication operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "auth/auth.h"
26
27 struct gensec_ntlmssp_state {
28         struct auth_context *auth_context;
29         struct auth_serversupplied_info *server_info;
30         struct ntlmssp_state *ntlmssp_state;
31 };
32
33
34 /**
35  * Return the challenge as determined by the authentication subsystem 
36  * @return an 8 byte random challenge
37  */
38
39 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
40 {
41         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
42
43         return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
44 }
45
46 /**
47  * Some authentication methods 'fix' the challenge, so we may not be able to set it
48  *
49  * @return If the effective challenge used by the auth subsystem may be modified
50  */
51 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
52 {
53         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
54
55         return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
56 }
57
58 /**
59  * NTLM2 authentication modifies the effective challenge, 
60  * @param challenge The new challenge value
61  */
62 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
63 {
64         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
65         struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
66
67         SMB_ASSERT(challenge->length == 8);
68
69         auth_context->challenge = data_blob_talloc(auth_context, 
70                                                    challenge->data, challenge->length);
71
72         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
73
74         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
75         DEBUG(5, ("challenge is: \n"));
76         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
77         return NT_STATUS_OK;
78 }
79
80 /**
81  * Check the password on an NTLMSSP login.  
82  *
83  * Return the session keys used on the connection.
84  */
85
86 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
87 {
88         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
89         struct auth_usersupplied_info *user_info = NULL;
90         NTSTATUS nt_status;
91
92 #if 0
93         /* the client has given us its machine name (which we otherwise would not get on port 445).
94            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
95
96         set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
97
98         /* setup the string used by %U */
99         /* sub_set_smb_name checks for weird internally */
100         sub_set_smb_name(gensec_ntlmssp_state->ntlmssp_state->user);
101
102         reload_services(True);
103
104 #endif
105         nt_status = make_user_info_map(ntlmssp_state,
106                                        &user_info, 
107                                        gensec_ntlmssp_state->ntlmssp_state->user, 
108                                        gensec_ntlmssp_state->ntlmssp_state->domain, 
109                                        gensec_ntlmssp_state->ntlmssp_state->workstation, 
110                                        gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
111                                        gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
112                                        NULL, NULL, NULL,
113                                        True);
114
115         if (!NT_STATUS_IS_OK(nt_status)) {
116                 return nt_status;
117         }
118
119         nt_status = gensec_ntlmssp_state->
120                 auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context, 
121                                                   user_info, 
122                                                   gensec_ntlmssp_state, 
123                                                   &gensec_ntlmssp_state->server_info); 
124
125         free_user_info(&user_info);
126
127         if (!NT_STATUS_IS_OK(nt_status)) {
128                 return nt_status;
129         }
130         if (gensec_ntlmssp_state->server_info->user_session_key.length) {
131                 DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length));
132                 *user_session_key = data_blob_talloc(ntlmssp_state, 
133                                                    gensec_ntlmssp_state->server_info->user_session_key.data,
134                                                    gensec_ntlmssp_state->server_info->user_session_key.length);
135         }
136         if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
137                 DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length));
138                 *lm_session_key = data_blob_talloc(ntlmssp_state, 
139                                                    gensec_ntlmssp_state->server_info->lm_session_key.data,
140                                                    gensec_ntlmssp_state->server_info->lm_session_key.length);
141         }
142         return nt_status;
143 }
144
145 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
146 {
147         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
148         
149         gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
150         if (!gensec_ntlmssp_state) {
151                 return NT_STATUS_NO_MEMORY;
152         }
153
154         gensec_ntlmssp_state->ntlmssp_state = NULL;
155         gensec_ntlmssp_state->auth_context = NULL;
156         gensec_ntlmssp_state->server_info = NULL;
157
158         gensec_security->private_data = gensec_ntlmssp_state;
159         return NT_STATUS_OK;
160 }
161
162 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
163 {
164         NTSTATUS nt_status;
165         NTSTATUS status;
166         struct ntlmssp_state *ntlmssp_state;
167         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
168
169         status = gensec_ntlmssp_start(gensec_security);
170         if (!NT_STATUS_IS_OK(status)) {
171                 return status;
172         }
173
174         gensec_ntlmssp_state = gensec_security->private_data;
175
176         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_security,
177                                                               &gensec_ntlmssp_state->ntlmssp_state))) {
178                 return nt_status;
179         }
180
181         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
182                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
183         }
184         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
185                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
186         }
187
188         ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
189         nt_status = make_auth_context_subsystem(gensec_security, &gensec_ntlmssp_state->auth_context);
190         if (!NT_STATUS_IS_OK(nt_status)) {
191                 return nt_status;
192         }
193
194         ntlmssp_state->auth_context = gensec_ntlmssp_state;
195         ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
196         ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
197         ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
198         ntlmssp_state->check_password = auth_ntlmssp_check_password;
199         ntlmssp_state->server_role = lp_server_role();
200         
201         return NT_STATUS_OK;
202 }
203
204 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
205 {
206         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
207         char *password = NULL;
208         
209         NTSTATUS status;
210         status = gensec_ntlmssp_start(gensec_security);
211         if (!NT_STATUS_IS_OK(status)) {
212                 return status;
213         }
214
215         gensec_ntlmssp_state = gensec_security->private_data;
216         status = ntlmssp_client_start(gensec_security, 
217                                       &gensec_ntlmssp_state->ntlmssp_state);
218         if (!NT_STATUS_IS_OK(status)) {
219                 return status;
220         }
221
222         if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
223                 /*
224                  * We need to set this to allow a later SetPassword
225                  * via the SAMR pipe to succeed. Strange.... We could
226                  * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
227                  * 
228                  * Without this, Windows will not create the master key
229                  * that it thinks is only used for NTLMSSP signing and 
230                  * sealing.  (It is actually pulled out and used directly) 
231                  */
232                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
233         }
234         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
235                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
236         }
237         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
238                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
239         }
240
241         status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, 
242                                     gensec_security->user.domain);
243         if (!NT_STATUS_IS_OK(status)) {
244                 return status;
245         }
246         
247         status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, 
248                                       gensec_security->user.name);
249         if (!NT_STATUS_IS_OK(status)) {
250                 return status;
251         }
252
253         status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
254         if (!NT_STATUS_IS_OK(status)) {
255                 return status;
256         }
257
258         if (password) {
259                 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, 
260                                               password);
261                 if (!NT_STATUS_IS_OK(status)) {
262                         return status;
263                 }
264         }
265
266         gensec_security->private_data = gensec_ntlmssp_state;
267
268         return status;
269 }
270
271 /*
272   wrappers for the ntlmssp_*() functions
273 */
274 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
275                                              TALLOC_CTX *mem_ctx, 
276                                              uint8_t *data, size_t length, 
277                                              const uint8_t *whole_pdu, size_t pdu_length, 
278                                              DATA_BLOB *sig)
279 {
280         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
281
282         return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
283 }
284
285 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
286                                             TALLOC_CTX *mem_ctx, 
287                                             const uint8_t *data, size_t length, 
288                                             const uint8_t *whole_pdu, size_t pdu_length, 
289                                             const DATA_BLOB *sig)
290 {
291         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
292
293         return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
294 }
295
296 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
297                                            TALLOC_CTX *mem_ctx, 
298                                            uint8_t *data, size_t length, 
299                                            const uint8_t *whole_pdu, size_t pdu_length, 
300                                            DATA_BLOB *sig)
301 {
302         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
303
304         return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
305 }
306
307 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
308                                            TALLOC_CTX *mem_ctx, 
309                                            const uint8_t *data, size_t length, 
310                                            const uint8_t *whole_pdu, size_t pdu_length, 
311                                            DATA_BLOB *sig)
312 {
313         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
314
315         return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
316 }
317
318 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
319 {
320         return NTLMSSP_SIG_SIZE;
321 }
322
323 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
324                                            DATA_BLOB *session_key)
325 {
326         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
327
328         return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
329 }
330
331 /**
332  * Next state function for the wrapped NTLMSSP state machine
333  * 
334  * @param gensec_security GENSEC state, initialised to NTLMSSP
335  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
336  * @param in The request, as a DATA_BLOB
337  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
338  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
339  *                or NT_STATUS_OK if the user is authenticated. 
340  */
341
342 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
343                                       const DATA_BLOB in, DATA_BLOB *out) 
344 {
345         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
346         NTSTATUS status;
347
348         status = ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
349
350         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
351                 return status;
352         }
353
354         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
355                 gensec_security->have_features |= GENSEC_FEATURE_SIGN;
356         }
357
358         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
359                 gensec_security->have_features |= GENSEC_FEATURE_SEAL;
360         }
361
362         if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) {
363                 gensec_security->have_features |= GENSEC_FEATURE_SESSION_KEY;
364         }
365
366         return status;
367 }
368
369 /** 
370  * Return the credentials of a logged on user, including session keys
371  * etc.
372  *
373  * Only valid after a successful authentication
374  *
375  * May only be called once per authentication.
376  *
377  */
378
379 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
380                                             struct auth_session_info **session_info) 
381 {
382         NTSTATUS nt_status;
383         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
384         nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
385
386         if (!NT_STATUS_IS_OK(nt_status)) {
387                 return nt_status;
388         }
389
390         (*session_info)->session_key = data_blob_talloc(*session_info, 
391                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.data,
392                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.length);
393
394         (*session_info)->workstation = talloc_strdup(*session_info, 
395                                                      gensec_ntlmssp_state->ntlmssp_state->workstation);
396
397         return NT_STATUS_OK;
398 }
399
400 static void gensec_ntlmssp_end(struct gensec_security *gensec_security)
401 {
402         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
403
404         if (gensec_ntlmssp_state->ntlmssp_state) {
405                 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
406         }
407
408         if (gensec_ntlmssp_state->auth_context) {
409                 free_auth_context(&gensec_ntlmssp_state->auth_context);
410         }
411         if (gensec_ntlmssp_state->server_info) {
412                 free_server_info(&gensec_ntlmssp_state->server_info);
413         }
414         talloc_free(gensec_ntlmssp_state);
415         gensec_security->private_data = NULL;
416 }
417
418 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
419         .name           = "ntlmssp",
420         .sasl_name      = "NTLM",
421         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
422         .oid            = GENSEC_OID_NTLMSSP,
423         .client_start   = gensec_ntlmssp_client_start,
424         .server_start   = gensec_ntlmssp_server_start,
425         .update         = gensec_ntlmssp_update,
426         .seal_packet    = gensec_ntlmssp_seal_packet,
427         .sig_size       = gensec_ntlmssp_sig_size,
428         .sign_packet    = gensec_ntlmssp_sign_packet,
429         .check_packet   = gensec_ntlmssp_check_packet,
430         .unseal_packet  = gensec_ntlmssp_unseal_packet,
431         .session_key    = gensec_ntlmssp_session_key,
432         .session_info   = gensec_ntlmssp_session_info,
433         .end            = gensec_ntlmssp_end
434 };
435
436
437 NTSTATUS gensec_ntlmssp_init(void)
438 {
439         NTSTATUS ret;
440         ret = gensec_register(&gensec_ntlmssp_security_ops);
441         if (!NT_STATUS_IS_OK(ret)) {
442                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
443                         gensec_ntlmssp_security_ops.name));
444                 return ret;
445         }
446
447         return ret;
448 }