r4355: More work from the elves on Christmas eve:
[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 int gensec_ntlmssp_destroy(void *ptr)
146 {
147         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ptr;
148
149         if (gensec_ntlmssp_state->ntlmssp_state) {
150                 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
151         }
152
153         if (gensec_ntlmssp_state->auth_context) {
154                 free_auth_context(&gensec_ntlmssp_state->auth_context);
155         }
156         if (gensec_ntlmssp_state->server_info) {
157                 free_server_info(&gensec_ntlmssp_state->server_info);
158         }
159         return 0;
160 }
161
162 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
163 {
164         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
165         
166         gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
167         if (!gensec_ntlmssp_state) {
168                 return NT_STATUS_NO_MEMORY;
169         }
170
171         gensec_ntlmssp_state->ntlmssp_state = NULL;
172         gensec_ntlmssp_state->auth_context = NULL;
173         gensec_ntlmssp_state->server_info = NULL;
174
175         talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy); 
176
177         gensec_security->private_data = gensec_ntlmssp_state;
178         return NT_STATUS_OK;
179 }
180
181 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
182 {
183         NTSTATUS nt_status;
184         NTSTATUS status;
185         struct ntlmssp_state *ntlmssp_state;
186         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
187
188         status = gensec_ntlmssp_start(gensec_security);
189         if (!NT_STATUS_IS_OK(status)) {
190                 return status;
191         }
192
193         gensec_ntlmssp_state = gensec_security->private_data;
194
195         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_ntlmssp_state,
196                                                               &gensec_ntlmssp_state->ntlmssp_state))) {
197                 return nt_status;
198         }
199
200         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
201                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
202         }
203         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
204                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
205         }
206
207         ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
208         nt_status = make_auth_context_subsystem(gensec_ntlmssp_state, &gensec_ntlmssp_state->auth_context);
209         if (!NT_STATUS_IS_OK(nt_status)) {
210                 return nt_status;
211         }
212
213         ntlmssp_state->auth_context = gensec_ntlmssp_state;
214         ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
215         ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
216         ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
217         ntlmssp_state->check_password = auth_ntlmssp_check_password;
218         ntlmssp_state->server_role = lp_server_role();
219         
220         return NT_STATUS_OK;
221 }
222
223 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
224 {
225         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
226         char *password = NULL;
227         
228         NTSTATUS status;
229         status = gensec_ntlmssp_start(gensec_security);
230         if (!NT_STATUS_IS_OK(status)) {
231                 return status;
232         }
233
234         gensec_ntlmssp_state = gensec_security->private_data;
235         status = ntlmssp_client_start(gensec_ntlmssp_state,
236                                       &gensec_ntlmssp_state->ntlmssp_state);
237         if (!NT_STATUS_IS_OK(status)) {
238                 return status;
239         }
240
241         if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
242                 /*
243                  * We need to set this to allow a later SetPassword
244                  * via the SAMR pipe to succeed. Strange.... We could
245                  * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
246                  * 
247                  * Without this, Windows will not create the master key
248                  * that it thinks is only used for NTLMSSP signing and 
249                  * sealing.  (It is actually pulled out and used directly) 
250                  */
251                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
252         }
253         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
254                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
255         }
256         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
257                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
258         }
259
260         status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, 
261                                     gensec_security->user.domain);
262         if (!NT_STATUS_IS_OK(status)) {
263                 return status;
264         }
265         
266         status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, 
267                                       gensec_security->user.name);
268         if (!NT_STATUS_IS_OK(status)) {
269                 return status;
270         }
271
272         if (gensec_security->user.name) {
273                 status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
274                 if (!NT_STATUS_IS_OK(status)) {
275                         return status;
276                 }
277         }
278
279         if (password) {
280                 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, 
281                                               password);
282                 if (!NT_STATUS_IS_OK(status)) {
283                         return status;
284                 }
285         }
286
287         gensec_security->private_data = gensec_ntlmssp_state;
288
289         return status;
290 }
291
292 /*
293   wrappers for the ntlmssp_*() functions
294 */
295 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
296                                              TALLOC_CTX *mem_ctx, 
297                                              uint8_t *data, size_t length, 
298                                              const uint8_t *whole_pdu, size_t pdu_length, 
299                                              DATA_BLOB *sig)
300 {
301         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
302
303         return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
304 }
305
306 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
307                                             TALLOC_CTX *mem_ctx, 
308                                             const uint8_t *data, size_t length, 
309                                             const uint8_t *whole_pdu, size_t pdu_length, 
310                                             const DATA_BLOB *sig)
311 {
312         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
313
314         return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
315 }
316
317 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
318                                            TALLOC_CTX *mem_ctx, 
319                                            uint8_t *data, size_t length, 
320                                            const uint8_t *whole_pdu, size_t pdu_length, 
321                                            DATA_BLOB *sig)
322 {
323         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
324
325         return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
326 }
327
328 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
329                                            TALLOC_CTX *mem_ctx, 
330                                            const uint8_t *data, size_t length, 
331                                            const uint8_t *whole_pdu, size_t pdu_length, 
332                                            DATA_BLOB *sig)
333 {
334         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
335
336         return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
337 }
338
339 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
340 {
341         return NTLMSSP_SIG_SIZE;
342 }
343
344 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
345                                            DATA_BLOB *session_key)
346 {
347         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
348
349         return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
350 }
351
352 /**
353  * Next state function for the wrapped NTLMSSP state machine
354  * 
355  * @param gensec_security GENSEC state, initialised to NTLMSSP
356  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
357  * @param in The request, as a DATA_BLOB
358  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
359  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
360  *                or NT_STATUS_OK if the user is authenticated. 
361  */
362
363 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
364                                       const DATA_BLOB in, DATA_BLOB *out) 
365 {
366         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
367         NTSTATUS status;
368
369         status = ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
370
371         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
372                 return status;
373         }
374
375         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
376                 gensec_security->have_features |= GENSEC_FEATURE_SIGN;
377         }
378
379         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
380                 gensec_security->have_features |= GENSEC_FEATURE_SEAL;
381         }
382
383         if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) {
384                 gensec_security->have_features |= GENSEC_FEATURE_SESSION_KEY;
385         }
386
387         return status;
388 }
389
390 /** 
391  * Return the credentials of a logged on user, including session keys
392  * etc.
393  *
394  * Only valid after a successful authentication
395  *
396  * May only be called once per authentication.
397  *
398  */
399
400 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
401                                             struct auth_session_info **session_info) 
402 {
403         NTSTATUS nt_status;
404         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
405         nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
406
407         if (!NT_STATUS_IS_OK(nt_status)) {
408                 return nt_status;
409         }
410
411         (*session_info)->session_key = data_blob_talloc(*session_info, 
412                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.data,
413                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.length);
414
415         (*session_info)->workstation = talloc_strdup(*session_info, 
416                                                      gensec_ntlmssp_state->ntlmssp_state->workstation);
417
418         return NT_STATUS_OK;
419 }
420
421 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
422         .name           = "ntlmssp",
423         .sasl_name      = "NTLM",
424         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
425         .oid            = GENSEC_OID_NTLMSSP,
426         .client_start   = gensec_ntlmssp_client_start,
427         .server_start   = gensec_ntlmssp_server_start,
428         .update         = gensec_ntlmssp_update,
429         .seal_packet    = gensec_ntlmssp_seal_packet,
430         .sig_size       = gensec_ntlmssp_sig_size,
431         .sign_packet    = gensec_ntlmssp_sign_packet,
432         .check_packet   = gensec_ntlmssp_check_packet,
433         .unseal_packet  = gensec_ntlmssp_unseal_packet,
434         .session_key    = gensec_ntlmssp_session_key,
435         .session_info   = gensec_ntlmssp_session_info,
436 };
437
438
439 NTSTATUS gensec_ntlmssp_init(void)
440 {
441         NTSTATUS ret;
442         ret = gensec_register(&gensec_ntlmssp_security_ops);
443         if (!NT_STATUS_IS_OK(ret)) {
444                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
445                         gensec_ntlmssp_security_ops.name));
446                 return ret;
447         }
448
449         return ret;
450 }