r6463: Move NTLM2 and NTLM (v1) specific variables into a union for DCE/RPC.
[samba.git] / source / auth / ntlmssp / ntlmssp_server.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle NLTMSSP, client server side parsing
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
8    Copyright (C) Stefan Metzmacher 2005
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "auth/auth.h"
27 #include "auth/ntlmssp/ntlmssp.h"
28 #include "lib/crypto/crypto.h"
29 #include "pstring.h"
30
31 /** 
32  * Set a username on an NTLMSSP context - ensures it is talloc()ed 
33  *
34  */
35
36 static NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user) 
37 {
38         if (!user) {
39                 /* it should be at least "" */
40                 DEBUG(1, ("NTLMSSP failed to set username - cannot accept NULL username\n"));
41                 return NT_STATUS_INVALID_PARAMETER;
42         }
43         ntlmssp_state->user = talloc_strdup(ntlmssp_state, user);
44         if (!ntlmssp_state->user) {
45                 return NT_STATUS_NO_MEMORY;
46         }
47         return NT_STATUS_OK;
48 }
49
50 /** 
51  * Set a domain on an NTLMSSP context - ensures it is talloc()ed 
52  *
53  */
54 static NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain) 
55 {
56         ntlmssp_state->domain = talloc_strdup(ntlmssp_state, domain);
57         if (!ntlmssp_state->domain) {
58                 return NT_STATUS_NO_MEMORY;
59         }
60         return NT_STATUS_OK;
61 }
62
63 /** 
64  * Set a workstation on an NTLMSSP context - ensures it is talloc()ed 
65  *
66  */
67 static NTSTATUS ntlmssp_set_workstation(struct ntlmssp_state *ntlmssp_state, const char *workstation) 
68 {
69         ntlmssp_state->workstation = talloc_strdup(ntlmssp_state, workstation);
70         if (!ntlmssp_state->workstation) {
71                 return NT_STATUS_NO_MEMORY;
72         }
73         return NT_STATUS_OK;
74 }
75
76 /**
77  * Default challenge generation code.
78  *
79  */
80    
81 static const uint8_t *get_challenge(const struct ntlmssp_state *ntlmssp_state)
82 {
83         uint8_t *chal = talloc_size(ntlmssp_state, 8);
84         generate_random_buffer(chal, 8);
85
86         return chal;
87 }
88
89 /**
90  * Default 'we can set the challenge to anything we like' implementation
91  *
92  */
93    
94 static BOOL may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
95 {
96         return True;
97 }
98
99 /**
100  * Default 'we can set the challenge to anything we like' implementation
101  *
102  * Does not actually do anything, as the value is always in the structure anyway.
103  *
104  */
105    
106 static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
107 {
108         SMB_ASSERT(challenge->length == 8);
109         return NT_STATUS_OK;
110 }
111
112 /**
113  * Determine correct target name flags for reply, given server role 
114  * and negotiated flags
115  * 
116  * @param ntlmssp_state NTLMSSP State
117  * @param neg_flags The flags from the packet
118  * @param chal_flags The flags to be set in the reply packet
119  * @return The 'target name' string.
120  */
121
122 static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
123                                        uint32_t neg_flags, uint32_t *chal_flags) 
124 {
125         if (neg_flags & NTLMSSP_REQUEST_TARGET) {
126                 *chal_flags |= NTLMSSP_CHAL_TARGET_INFO;
127                 *chal_flags |= NTLMSSP_REQUEST_TARGET;
128                 if (ntlmssp_state->server_role == ROLE_STANDALONE) {
129                         *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
130                         return ntlmssp_state->server_name;
131                 } else {
132                         *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
133                         return ntlmssp_state->get_domain();
134                 };
135         } else {
136                 return "";
137         }
138 }
139
140 /**
141  * Next state function for the Negotiate packet
142  * 
143  * @param ntlmssp_state NTLMSSP State
144  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
145  * @param in The request, as a DATA_BLOB
146  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
147  * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent. 
148  */
149
150 NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security, 
151                                   TALLOC_CTX *out_mem_ctx, 
152                                   const DATA_BLOB in, DATA_BLOB *out) 
153 {
154         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
155         struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
156         DATA_BLOB struct_blob;
157         fstring dnsname, dnsdomname;
158         uint32_t neg_flags = 0;
159         uint32_t ntlmssp_command, chal_flags;
160         char *cliname=NULL, *domname=NULL;
161         const uint8_t *cryptkey;
162         const char *target_name;
163
164         /* parse the NTLMSSP packet */
165 #if 0
166         file_save("ntlmssp_negotiate.dat", request.data, request.length);
167 #endif
168
169         if (in.length) {
170                 if (!msrpc_parse(ntlmssp_state, 
171                                  &in, "CddAA",
172                                  "NTLMSSP",
173                                  &ntlmssp_command,
174                                  &neg_flags,
175                                  &cliname,
176                                  &domname)) {
177                         DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n"));
178                         dump_data(2, in.data, in.length);
179                         return NT_STATUS_INVALID_PARAMETER;
180                 }
181                 
182                 debug_ntlmssp_flags(neg_flags);
183         }
184         
185         ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key);
186
187         /* Ask our caller what challenge they would like in the packet */
188         cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);
189
190         /* Check if we may set the challenge */
191         if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {
192                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
193         }
194
195         /* The flags we send back are not just the negotiated flags,
196          * they are also 'what is in this packet'.  Therfore, we
197          * operate on 'chal_flags' from here on 
198          */
199
200         chal_flags = ntlmssp_state->neg_flags;
201
202         /* get the right name to fill in as 'target' */
203         target_name = ntlmssp_target_name(ntlmssp_state, 
204                                           neg_flags, &chal_flags); 
205         if (target_name == NULL) 
206                 return NT_STATUS_INVALID_PARAMETER;
207
208         ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
209         ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
210
211         /* This should be a 'netbios domain -> DNS domain' mapping */
212         dnsdomname[0] = '\0';
213         get_mydomname(dnsdomname);
214         strlower_m(dnsdomname);
215         
216         dnsname[0] = '\0';
217         get_myfullname(dnsname);
218         
219         /* This creates the 'blob' of names that appears at the end of the packet */
220         if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) 
221         {
222                 const char *target_name_dns = "";
223                 if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) {
224                         target_name_dns = dnsdomname;
225                 } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) {
226                         target_name_dns = dnsname;
227                 }
228
229                 msrpc_gen(out_mem_ctx, 
230                           &struct_blob, "aaaaa",
231                           NTLMSSP_NAME_TYPE_DOMAIN, target_name,
232                           NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->server_name,
233                           NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname,
234                           NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname,
235                           0, "");
236         } else {
237                 struct_blob = data_blob(NULL, 0);
238         }
239
240         {
241                 /* Marshel the packet in the right format, be it unicode or ASCII */
242                 const char *gen_string;
243                 if (ntlmssp_state->unicode) {
244                         gen_string = "CdUdbddB";
245                 } else {
246                         gen_string = "CdAdbddB";
247                 }
248                 
249                 msrpc_gen(out_mem_ctx, 
250                           out, gen_string,
251                           "NTLMSSP", 
252                           NTLMSSP_CHALLENGE,
253                           target_name,
254                           chal_flags,
255                           cryptkey, 8,
256                           0, 0,
257                           struct_blob.data, struct_blob.length);
258         }
259                 
260         ntlmssp_state->expected_state = NTLMSSP_AUTH;
261
262         return NT_STATUS_MORE_PROCESSING_REQUIRED;
263 }
264
265 /**
266  * Next state function for the Authenticate packet
267  * 
268  * @param ntlmssp_state NTLMSSP State
269  * @param request The request, as a DATA_BLOB
270  * @return Errors or NT_STATUS_OK. 
271  */
272
273 static NTSTATUS ntlmssp_server_preauth(struct ntlmssp_state *ntlmssp_state,
274                                        const DATA_BLOB request) 
275 {
276         uint32_t ntlmssp_command, auth_flags;
277         NTSTATUS nt_status;
278
279         uint8_t session_nonce_hash[16];
280
281         const char *parse_string;
282         char *domain = NULL;
283         char *user = NULL;
284         char *workstation = NULL;
285
286 #if 0
287         file_save("ntlmssp_auth.dat", request.data, request.length);
288 #endif
289
290         if (ntlmssp_state->unicode) {
291                 parse_string = "CdBBUUUBd";
292         } else {
293                 parse_string = "CdBBAAABd";
294         }
295
296         /* zero these out */
297         data_blob_free(&ntlmssp_state->lm_resp);
298         data_blob_free(&ntlmssp_state->nt_resp);
299
300         ntlmssp_state->user = NULL;
301         ntlmssp_state->domain = NULL;
302         ntlmssp_state->workstation = NULL;
303
304         /* now the NTLMSSP encoded auth hashes */
305         if (!msrpc_parse(ntlmssp_state, 
306                          &request, parse_string,
307                          "NTLMSSP", 
308                          &ntlmssp_command, 
309                          &ntlmssp_state->lm_resp,
310                          &ntlmssp_state->nt_resp,
311                          &domain, 
312                          &user, 
313                          &workstation,
314                          &ntlmssp_state->encrypted_session_key,
315                          &auth_flags)) {
316                 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
317                 dump_data(10, request.data, request.length);
318
319                 /* zero this out */
320                 data_blob_free(&ntlmssp_state->encrypted_session_key);
321                 auth_flags = 0;
322                 
323                 /* Try again with a shorter string (Win9X truncates this packet) */
324                 if (ntlmssp_state->unicode) {
325                         parse_string = "CdBBUUU";
326                 } else {
327                         parse_string = "CdBBAAA";
328                 }
329
330                 /* now the NTLMSSP encoded auth hashes */
331                 if (!msrpc_parse(ntlmssp_state, 
332                                  &request, parse_string,
333                                  "NTLMSSP", 
334                                  &ntlmssp_command, 
335                                  &ntlmssp_state->lm_resp,
336                                  &ntlmssp_state->nt_resp,
337                                  &domain, 
338                                  &user, 
339                                  &workstation)) {
340                         DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
341                         dump_data(2, request.data, request.length);
342
343                         return NT_STATUS_INVALID_PARAMETER;
344                 }
345         }
346
347         if (auth_flags)
348                 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, ntlmssp_state->allow_lm_key);
349
350         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
351                 /* zero this out */
352                 data_blob_free(&ntlmssp_state->encrypted_session_key);
353                 return nt_status;
354         }
355
356         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
357                 /* zero this out */
358                 data_blob_free(&ntlmssp_state->encrypted_session_key);
359                 return nt_status;
360         }
361
362         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) {
363                 /* zero this out */
364                 data_blob_free(&ntlmssp_state->encrypted_session_key);
365                 return nt_status;
366         }
367
368         DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
369                  ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));
370
371 #if 0
372         file_save("nthash1.dat",  &ntlmssp_state->nt_resp.data,  &ntlmssp_state->nt_resp.length);
373         file_save("lmhash1.dat",  &ntlmssp_state->lm_resp.data,  &ntlmssp_state->lm_resp.length);
374 #endif
375
376         /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a 
377            client challenge 
378         
379            However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
380         */
381         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
382                 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
383                         struct MD5Context md5_session_nonce_ctx;
384                         SMB_ASSERT(ntlmssp_state->internal_chal.data 
385                                    && ntlmssp_state->internal_chal.length == 8);
386                         
387                         ntlmssp_state->doing_ntlm2 = True;
388
389                         memcpy(ntlmssp_state->ntlm2.session_nonce, ntlmssp_state->internal_chal.data, 8);
390                         memcpy(&ntlmssp_state->ntlm2.session_nonce[8], ntlmssp_state->lm_resp.data, 8);
391                         
392                         MD5Init(&md5_session_nonce_ctx);
393                         MD5Update(&md5_session_nonce_ctx, ntlmssp_state->ntlm2.session_nonce, 16);
394                         MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
395                         
396                         ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, 
397                                                                session_nonce_hash, 8);
398
399                         /* LM response is no longer useful, zero it out */
400                         data_blob_free(&ntlmssp_state->lm_resp);
401
402                         /* We changed the effective challenge - set it */
403                         if (!NT_STATUS_IS_OK(nt_status = 
404                                              ntlmssp_state->set_challenge(ntlmssp_state, 
405                                                                           &ntlmssp_state->chal))) {
406                                 /* zero this out */
407                                 data_blob_free(&ntlmssp_state->encrypted_session_key);
408                                 return nt_status;
409                         }
410
411                         /* LM Key is incompatible... */
412                         ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
413                 }
414         }
415         return NT_STATUS_OK;
416 }
417
418 /**
419  * Next state function for the Authenticate packet 
420  * (after authentication - figures out the session keys etc)
421  * 
422  * @param ntlmssp_state NTLMSSP State
423  * @return Errors or NT_STATUS_OK. 
424  */
425
426 static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state,
427                                         DATA_BLOB *user_session_key, 
428                                         DATA_BLOB *lm_session_key) 
429 {
430         NTSTATUS nt_status;
431         DATA_BLOB session_key = data_blob(NULL, 0);
432
433         if (user_session_key)
434                 dump_data_pw("USER session key:\n", user_session_key->data, user_session_key->length);
435
436         if (lm_session_key) 
437                 dump_data_pw("LM first-8:\n", lm_session_key->data, lm_session_key->length);
438
439         /* Handle the different session key derivation for NTLM2 */
440         if (ntlmssp_state->doing_ntlm2) {
441                 if (user_session_key && user_session_key->data && user_session_key->length == 16) {
442                         session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
443                         hmac_md5(user_session_key->data, ntlmssp_state->ntlm2.session_nonce, 
444                                  sizeof(ntlmssp_state->ntlm2.session_nonce), session_key.data);
445                         DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
446                         dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
447                         
448                 } else {
449                         DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
450                         session_key = data_blob(NULL, 0);
451                 }
452         } else if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
453                 /* Ensure we can never get here on NTLMv2 */
454                 && (ntlmssp_state->nt_resp.length == 0 || ntlmssp_state->nt_resp.length == 24)) {
455
456                 if (lm_session_key && lm_session_key->data && lm_session_key->length >= 8) {
457                         if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
458                                 session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
459                                 SMBsesskeygen_lm_sess_key(lm_session_key->data, ntlmssp_state->lm_resp.data, 
460                                                           session_key.data);
461                                 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
462                                 dump_data_pw("LM session key:\n", session_key.data, session_key.length);
463                         } else {
464                                 
465                                 /* When there is no LM response, just use zeros */
466                                 static const uint8_t zeros[24];
467                                 session_key = data_blob_talloc(ntlmssp_state, NULL, 16);
468                                 SMBsesskeygen_lm_sess_key(zeros, zeros, 
469                                                           session_key.data);
470                                 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
471                                 dump_data_pw("LM session key:\n", session_key.data, session_key.length);
472                         }
473                 } else {
474                         /* LM Key not selected */
475                         ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
476
477                         DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
478                         session_key = data_blob(NULL, 0);
479                 }
480
481         } else if (user_session_key && user_session_key->data) {
482                 session_key = *user_session_key;
483                 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
484                 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
485
486                 /* LM Key not selected */
487                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
488
489         } else if (lm_session_key && lm_session_key->data) {
490                 /* Very weird to have LM key, but no user session key, but anyway.. */
491                 session_key = *lm_session_key;
492                 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
493                 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
494
495                 /* LM Key not selected */
496                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
497
498         } else {
499                 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
500                 session_key = data_blob(NULL, 0);
501
502                 /* LM Key not selected */
503                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
504         }
505
506         /* With KEY_EXCH, the client supplies the proposed session key, 
507            but encrypts it with the long-term key */
508         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
509                 if (!ntlmssp_state->encrypted_session_key.data 
510                     || ntlmssp_state->encrypted_session_key.length != 16) {
511                         data_blob_free(&ntlmssp_state->encrypted_session_key);
512                         DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", 
513                                   ntlmssp_state->encrypted_session_key.length));
514                         return NT_STATUS_INVALID_PARAMETER;
515                 } else if (!session_key.data || session_key.length != 16) {
516                         DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 
517                                   session_key.length));
518                         ntlmssp_state->session_key = session_key;
519                 } else {
520                         dump_data_pw("KEY_EXCH session key (enc):\n", 
521                                      ntlmssp_state->encrypted_session_key.data, 
522                                      ntlmssp_state->encrypted_session_key.length);
523                         arcfour_crypt(ntlmssp_state->encrypted_session_key.data, 
524                                       session_key.data, 
525                                       ntlmssp_state->encrypted_session_key.length);
526                         ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state, 
527                                                                       ntlmssp_state->encrypted_session_key.data, 
528                                                                       ntlmssp_state->encrypted_session_key.length);
529                         dump_data_pw("KEY_EXCH session key:\n", ntlmssp_state->encrypted_session_key.data, 
530                                      ntlmssp_state->encrypted_session_key.length);
531                 }
532         } else {
533                 ntlmssp_state->session_key = session_key;
534         }
535
536         /* The server might need us to use a partial-strength session key */
537         ntlmssp_weaken_keys(ntlmssp_state);
538
539         nt_status = ntlmssp_sign_init(ntlmssp_state);
540
541         data_blob_free(&ntlmssp_state->encrypted_session_key);
542         
543         /* allow arbitarily many authentications, but watch that this will cause a 
544            memory leak, until the ntlmssp_state is shutdown 
545         */
546
547         if (ntlmssp_state->server_multiple_authentications) {
548                 ntlmssp_state->expected_state = NTLMSSP_AUTH;
549         } else {
550                 ntlmssp_state->expected_state = NTLMSSP_DONE;
551         }
552
553         return nt_status;
554 }
555
556
557 /**
558  * Next state function for the Authenticate packet
559  * 
560  * @param ntlmssp_state NTLMSSP State
561  * @param in The packet in from the NTLMSSP partner, as a DATA_BLOB
562  * @param out The reply, as an allocated DATA_BLOB, caller to free.
563  * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK. 
564  */
565
566 NTSTATUS ntlmssp_server_auth(struct gensec_security *gensec_security, 
567                              TALLOC_CTX *out_mem_ctx, 
568                              const DATA_BLOB in, DATA_BLOB *out) 
569 {
570         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
571         struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
572         DATA_BLOB user_session_key = data_blob(NULL, 0);
573         DATA_BLOB lm_session_key = data_blob(NULL, 0);
574         NTSTATUS nt_status;
575
576         /* zero the outbound NTLMSSP packet */
577         *out = data_blob_talloc(out_mem_ctx, NULL, 0);
578
579         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_preauth(ntlmssp_state, in))) {
580                 return nt_status;
581         }
582
583         /*
584          * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
585          * is required (by "ntlm auth = no" and "lm auth = no" being set in the
586          * smb.conf file) and no NTLMv2 response was sent then the password check
587          * will fail here. JRA.
588          */
589
590         /* Finally, actually ask if the password is OK */
591
592         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, 
593                                                                        &user_session_key, &lm_session_key))) {
594                 return nt_status;
595         }
596         
597         if (ntlmssp_state->server_use_session_keys) {
598                 return ntlmssp_server_postauth(ntlmssp_state, &user_session_key, &lm_session_key);
599         } else {
600                 ntlmssp_state->session_key = data_blob(NULL, 0);
601                 return NT_STATUS_OK;
602         }
603 }
604
605 /**
606  * Create an NTLMSSP state machine
607  * 
608  * @param ntlmssp_state NTLMSSP State, allocated by this function
609  */
610
611 static NTSTATUS ntlmssp_server_start(TALLOC_CTX *mem_ctx, struct ntlmssp_state **ntlmssp_state)
612 {
613         *ntlmssp_state = talloc(mem_ctx, struct ntlmssp_state);
614         if (!*ntlmssp_state) {
615                 DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
616                 return NT_STATUS_NO_MEMORY;
617         }
618         ZERO_STRUCTP(*ntlmssp_state);
619
620         (*ntlmssp_state)->role = NTLMSSP_SERVER;
621
622         (*ntlmssp_state)->get_challenge = get_challenge;
623         (*ntlmssp_state)->set_challenge = set_challenge;
624         (*ntlmssp_state)->may_set_challenge = may_set_challenge;
625
626         (*ntlmssp_state)->workstation = NULL;
627         (*ntlmssp_state)->server_name = lp_netbios_name();
628
629         (*ntlmssp_state)->get_domain = lp_workgroup;
630         (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */
631
632         (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE;
633
634         (*ntlmssp_state)->allow_lm_key = (lp_lanman_auth() 
635                                           && lp_parm_bool(-1, "ntlmssp_server", "allow_lm_key", False));
636
637         (*ntlmssp_state)->server_use_session_keys = True;
638         (*ntlmssp_state)->server_multiple_authentications = False;
639         
640         (*ntlmssp_state)->neg_flags = 
641                 NTLMSSP_NEGOTIATE_NTLM;
642
643         if (lp_parm_bool(-1, "ntlmssp_server", "128bit", True)) {
644                 (*ntlmssp_state)->neg_flags |= NTLMSSP_NEGOTIATE_128;           
645         }
646
647         if (lp_parm_bool(-1, "ntlmssp_server", "keyexchange", True)) {
648                 (*ntlmssp_state)->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;              
649         }
650
651         if (lp_parm_bool(-1, "ntlmssp_server", "ntlm2", True)) {
652                 (*ntlmssp_state)->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;         
653         }
654
655         return NT_STATUS_OK;
656 }
657
658 /**
659  * Return the challenge as determined by the authentication subsystem 
660  * @return an 8 byte random challenge
661  */
662
663 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
664 {
665         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
666         NTSTATUS status;
667         const uint8_t *chal;
668
669         status = auth_get_challenge(gensec_ntlmssp_state->auth_context, &chal);
670         if (!NT_STATUS_IS_OK(status)) {
671                 return NULL;
672         }
673
674         return chal;
675 }
676
677 /**
678  * Some authentication methods 'fix' the challenge, so we may not be able to set it
679  *
680  * @return If the effective challenge used by the auth subsystem may be modified
681  */
682 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
683 {
684         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
685
686         return auth_challenge_may_be_modified(gensec_ntlmssp_state->auth_context);
687 }
688
689 /**
690  * NTLM2 authentication modifies the effective challenge, 
691  * @param challenge The new challenge value
692  */
693 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
694 {
695         NTSTATUS nt_status;
696         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
697         struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
698         const uint8_t *chal;
699
700         if (challenge->length != 8) {
701                 return NT_STATUS_INVALID_PARAMETER;
702         }
703
704         chal = challenge->data;
705
706         nt_status = auth_context_set_challenge(auth_context, chal, "NTLMSSP callback (NTLM2)");
707
708         return nt_status;
709 }
710
711 /**
712  * Check the password on an NTLMSSP login.  
713  *
714  * Return the session keys used on the connection.
715  */
716
717 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
718 {
719         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
720         struct auth_usersupplied_info *user_info = NULL;
721         NTSTATUS nt_status;
722
723         nt_status = make_user_info_map(ntlmssp_state, 
724                                        gensec_ntlmssp_state->ntlmssp_state->user, 
725                                        gensec_ntlmssp_state->ntlmssp_state->domain, 
726                                        gensec_ntlmssp_state->ntlmssp_state->workstation, 
727                                        gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
728                                        gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
729                                        NULL, NULL, NULL, True,
730                                        &user_info);
731         NT_STATUS_NOT_OK_RETURN(nt_status);
732
733         nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, gensec_ntlmssp_state,
734                                         user_info, &gensec_ntlmssp_state->server_info);
735         talloc_free(user_info);
736         NT_STATUS_NOT_OK_RETURN(nt_status);
737
738         if (gensec_ntlmssp_state->server_info->user_session_key.length) {
739                 DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length));
740                 *user_session_key = data_blob_talloc(ntlmssp_state, 
741                                                    gensec_ntlmssp_state->server_info->user_session_key.data,
742                                                    gensec_ntlmssp_state->server_info->user_session_key.length);
743         }
744         if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
745                 DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length));
746                 *lm_session_key = data_blob_talloc(ntlmssp_state, 
747                                                    gensec_ntlmssp_state->server_info->lm_session_key.data,
748                                                    gensec_ntlmssp_state->server_info->lm_session_key.length);
749         }
750         return nt_status;
751 }
752
753 NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
754 {
755         NTSTATUS nt_status;
756         struct ntlmssp_state *ntlmssp_state;
757         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
758
759         nt_status = gensec_ntlmssp_start(gensec_security);
760         NT_STATUS_NOT_OK_RETURN(nt_status);
761
762         gensec_ntlmssp_state = gensec_security->private_data;
763
764         nt_status = ntlmssp_server_start(gensec_ntlmssp_state, &gensec_ntlmssp_state->ntlmssp_state);
765         NT_STATUS_NOT_OK_RETURN(nt_status);
766
767         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
768                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
769         }
770         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
771                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
772         }
773
774         nt_status = auth_context_create(gensec_ntlmssp_state, lp_auth_methods(), &gensec_ntlmssp_state->auth_context);
775         NT_STATUS_NOT_OK_RETURN(nt_status);
776
777         ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
778         ntlmssp_state->auth_context = gensec_ntlmssp_state;
779         ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
780         ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
781         ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
782         ntlmssp_state->check_password = auth_ntlmssp_check_password;
783         ntlmssp_state->server_role = lp_server_role();
784
785         return NT_STATUS_OK;
786 }
787
788 /** 
789  * Return the credentials of a logged on user, including session keys
790  * etc.
791  *
792  * Only valid after a successful authentication
793  *
794  * May only be called once per authentication.
795  *
796  */
797
798 NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
799                                      struct auth_session_info **session_info) 
800 {
801         NTSTATUS nt_status;
802         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
803
804         nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
805         NT_STATUS_NOT_OK_RETURN(nt_status);
806
807         (*session_info)->session_key = data_blob_talloc(*session_info, 
808                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.data,
809                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.length);
810
811         return NT_STATUS_OK;
812 }