check pointer before dereferencing it
[gd/samba-autobuild/.git] / source3 / smbd / sesssetup.c
1 /* 
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough        2002
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 uint32 global_client_caps = 0;
26
27 static struct auth_ntlmssp_state *global_ntlmssp_state;
28
29 /*
30   on a logon error possibly map the error to success if "map to guest"
31   is set approriately
32 */
33 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
34                                 const char *user, const char *domain)
35 {
36         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
37                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
38                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
39                         DEBUG(3,("No such user %s [%s] - using guest account\n",
40                                  user, domain));
41                         make_server_info_guest(server_info);
42                         status = NT_STATUS_OK;
43                 }
44         }
45
46         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
47                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
48                         DEBUG(3,("Registered username %s for guest access\n",user));
49                         make_server_info_guest(server_info);
50                         status = NT_STATUS_OK;
51                 }
52         }
53
54         return status;
55 }
56
57
58 /****************************************************************************
59  Add the standard 'Samba' signature to the end of the session setup.
60 ****************************************************************************/
61 static void add_signature(char *outbuf) 
62 {
63         char *p;
64         p = smb_buf(outbuf);
65         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
66         p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
67         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
68         set_message_end(outbuf,p);
69 }
70
71 /****************************************************************************
72 send a security blob via a session setup reply
73 ****************************************************************************/
74 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
75                                  DATA_BLOB blob, NTSTATUS nt_status)
76 {
77         char *p;
78
79         set_message(outbuf,4,0,True);
80
81         /* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
82            that we aren't finished yet */
83
84         nt_status = nt_status_squash(nt_status);
85         SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
86         SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
87         SSVAL(outbuf, smb_vwv3, blob.length);
88         p = smb_buf(outbuf);
89
90         /* should we cap this? */
91         memcpy(p, blob.data, blob.length);
92         p += blob.length;
93
94         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
95         p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
96         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
97         set_message_end(outbuf,p);
98
99         return send_smb(smbd_server_fd(),outbuf);
100 }
101
102 /****************************************************************************
103  Do a 'guest' logon, getting back the 
104 ****************************************************************************/
105 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
106 {
107         struct auth_context *auth_context;
108         auth_usersupplied_info *user_info = NULL;
109         
110         NTSTATUS nt_status;
111         unsigned char chal[8];
112
113         ZERO_STRUCT(chal);
114
115         DEBUG(3,("Got anonymous request\n"));
116
117         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
118                 return nt_status;
119         }
120
121         if (!make_user_info_guest(&user_info)) {
122                 (auth_context->free)(&auth_context);
123                 return NT_STATUS_NO_MEMORY;
124         }
125         
126         nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
127         (auth_context->free)(&auth_context);
128         free_user_info(&user_info);
129         return nt_status;
130 }
131
132
133 #ifdef HAVE_KRB5
134 /****************************************************************************
135 reply to a session setup spnego negotiate packet for kerberos
136 ****************************************************************************/
137 static int reply_spnego_kerberos(connection_struct *conn, 
138                                  char *inbuf, char *outbuf,
139                                  int length, int bufsize,
140                                  DATA_BLOB *secblob)
141 {
142         DATA_BLOB ticket;
143         char *client, *p;
144         const struct passwd *pw;
145         char *user;
146         int sess_vuid;
147         NTSTATUS ret;
148         DATA_BLOB auth_data;
149         auth_serversupplied_info *server_info = NULL;
150         ADS_STRUCT *ads;
151
152         if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
153                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
154         }
155
156         ads = ads_init_simple();
157
158         if (!ads) {
159                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
160         }
161
162         ads->auth.realm = strdup(lp_realm());
163
164         ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
165         if (!NT_STATUS_IS_OK(ret)) {
166                 DEBUG(1,("Failed to verify incoming ticket!\n"));       
167                 ads_destroy(&ads);
168                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
169         }
170
171         DEBUG(3,("Ticket name is [%s]\n", client));
172
173         p = strchr_m(client, '@');
174         if (!p) {
175                 DEBUG(3,("Doesn't look like a valid principal\n"));
176                 ads_destroy(&ads);
177                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
178         }
179
180         *p = 0;
181         if (strcasecmp(p+1, ads->auth.realm) != 0) {
182                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
183                 if (!lp_allow_trusted_domains()) {
184                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
185                 }
186                 /* this gives a fully qualified user name (ie. with full realm).
187                    that leads to very long usernames, but what else can we do? */
188                 asprintf(&user, "%s%s%s", p+1, lp_winbind_separator(), client);
189         } else {
190                 user = strdup(client);
191         }
192         ads_destroy(&ads);
193
194         /* setup the string used by %U */
195         sub_set_smb_name(user);
196
197         reload_services(True);
198
199         /* the password is good - let them in */
200         pw = Get_Pwnam(user);
201         if (!pw && !strstr(user, lp_winbind_separator())) {
202                 char *user2;
203                 /* try it with a winbind domain prefix */
204                 asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
205                 pw = Get_Pwnam(user2);
206                 if (pw) {
207                         free(user);
208                         user = user2;
209                 }
210         }
211
212         if (!pw) {
213                 DEBUG(1,("Username %s is invalid on this system\n",user));
214                 return ERROR_NT(NT_STATUS_NO_SUCH_USER);
215         }
216
217         if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
218                 DEBUG(1,("make_server_info_from_pw failed!\n"));
219                 return ERROR_NT(ret);
220         }
221         
222         sess_vuid = register_vuid(server_info, user);
223
224         free(user);
225         free_server_info(&server_info);
226
227         if (sess_vuid == -1) {
228                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
229         }
230
231         set_message(outbuf,4,0,True);
232         SSVAL(outbuf, smb_vwv3, 0);
233         add_signature(outbuf);
234  
235         SSVAL(outbuf,smb_uid,sess_vuid);
236         SSVAL(inbuf,smb_uid,sess_vuid);
237         
238         return chain_reply(inbuf,outbuf,length,bufsize);
239 }
240 #endif
241
242
243 /****************************************************************************
244  send a session setup reply, wrapped in SPNEGO.
245  get vuid and check first.
246  end the NTLMSSP exchange context if we are OK/complete fail
247 ***************************************************************************/
248 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf,
249                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
250                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) 
251 {
252         BOOL ret;
253         DATA_BLOB response;
254         struct auth_serversupplied_info *server_info;
255         server_info = (*auth_ntlmssp_state)->server_info;
256
257         if (!NT_STATUS_IS_OK(nt_status)) {
258                 nt_status = do_map_to_guest(nt_status, 
259                                             &server_info, 
260                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
261                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
262         }
263
264         if (NT_STATUS_IS_OK(nt_status)) {
265                 int sess_vuid;
266                 sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user /* check this for weird */);
267                 
268                 if (sess_vuid == -1) {
269                         nt_status = NT_STATUS_LOGON_FAILURE;
270                 } else {
271                         
272                         set_message(outbuf,4,0,True);
273                         SSVAL(outbuf, smb_vwv3, 0);
274                         
275                         if ((*auth_ntlmssp_state)->server_info && (*auth_ntlmssp_state)->server_info->guest) {
276                                 SSVAL(outbuf,smb_vwv2,1);
277                         }
278                         
279                         SSVAL(outbuf,smb_uid,sess_vuid);
280                 }
281         }
282
283         response = spnego_gen_auth_response(ntlmssp_blob, nt_status);
284         ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
285         data_blob_free(&response);
286
287         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
288                 auth_ntlmssp_end(&global_ntlmssp_state);
289         }
290
291         return ret;
292 }
293
294 /****************************************************************************
295 reply to a session setup spnego negotiate packet
296 ****************************************************************************/
297 static int reply_spnego_negotiate(connection_struct *conn, 
298                                   char *inbuf,
299                                   char *outbuf,
300                                   int length, int bufsize,
301                                   DATA_BLOB blob1)
302 {
303         char *OIDs[ASN1_MAX_OIDS];
304         DATA_BLOB secblob;
305         int i;
306         DATA_BLOB chal;
307         BOOL got_kerberos = False;
308         NTSTATUS nt_status;
309
310         /* parse out the OIDs and the first sec blob */
311         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
312                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
313         }
314         
315         for (i=0;OIDs[i];i++) {
316                 DEBUG(3,("Got OID %s\n", OIDs[i]));
317                 if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 ||
318                     strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) {
319                         got_kerberos = True;
320                 }
321                 free(OIDs[i]);
322         }
323         DEBUG(3,("Got secblob of size %d\n", secblob.length));
324
325 #ifdef HAVE_KRB5
326         if (got_kerberos && (SEC_ADS == lp_security())) {
327                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
328                                                 length, bufsize, &secblob);
329                 data_blob_free(&secblob);
330                 return ret;
331         }
332 #endif
333
334         if (global_ntlmssp_state) {
335                 auth_ntlmssp_end(&global_ntlmssp_state);
336         }
337
338         nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
339         if (!NT_STATUS_IS_OK(nt_status)) {
340                 return ERROR_NT(nt_status);
341         }
342
343         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
344                                         secblob, &chal);
345
346         data_blob_free(&secblob);
347
348         reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
349                              &chal, nt_status);
350                 
351         data_blob_free(&chal);
352
353         /* already replied */
354         return -1;
355 }
356
357         
358 /****************************************************************************
359 reply to a session setup spnego auth packet
360 ****************************************************************************/
361 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
362                              int length, int bufsize,
363                              DATA_BLOB blob1)
364 {
365         DATA_BLOB auth, auth_reply;
366         NTSTATUS nt_status;
367
368         if (!spnego_parse_auth(blob1, &auth)) {
369 #if 0
370                 file_save("auth.dat", blob1.data, blob1.length);
371 #endif
372                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
373         }
374
375         nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
376                                           auth, &auth_reply);
377
378         data_blob_free(&auth);
379
380         reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state,
381                              &auth_reply, nt_status);
382                 
383         data_blob_free(&auth_reply);
384
385         /* and tell smbd that we have already replied to this packet */
386         return -1;
387 }
388
389
390 /****************************************************************************
391 reply to a session setup command
392 ****************************************************************************/
393 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
394                                         char *outbuf,
395                                         int length,int bufsize)
396 {
397         uint8 *p;
398         DATA_BLOB blob1;
399         int ret;
400         size_t bufrem;
401
402         DEBUG(3,("Doing spnego session setup\n"));
403
404         if (global_client_caps == 0) {
405                 global_client_caps = IVAL(inbuf,smb_vwv10);
406         }
407                 
408         p = (uint8 *)smb_buf(inbuf);
409
410         if (SVAL(inbuf, smb_vwv7) == 0) {
411                 /* an invalid request */
412                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
413         }
414
415         bufrem = smb_bufrem(inbuf, p);
416         /* pull the spnego blob */
417         blob1 = data_blob(p, MIN(bufrem, SVAL(inbuf, smb_vwv7)));
418
419 #if 0
420         file_save("negotiate.dat", blob1.data, blob1.length);
421 #endif
422
423         if (blob1.data[0] == ASN1_APPLICATION(0)) {
424                 /* its a negTokenTarg packet */
425                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
426                 data_blob_free(&blob1);
427                 return ret;
428         }
429
430         if (blob1.data[0] == ASN1_CONTEXT(1)) {
431                 /* its a auth packet */
432                 ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
433                 data_blob_free(&blob1);
434                 return ret;
435         }
436
437         /* what sort of packet is this? */
438         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
439
440         data_blob_free(&blob1);
441
442         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
443 }
444
445
446 /****************************************************************************
447 reply to a session setup command
448 ****************************************************************************/
449 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
450                           int length,int bufsize)
451 {
452         int sess_vuid;
453         int   smb_bufsize;    
454         DATA_BLOB lm_resp;
455         DATA_BLOB nt_resp;
456         DATA_BLOB plaintext_password;
457         fstring user;
458         fstring sub_user; /* Sainitised username for substituion */
459         fstring domain;
460         fstring native_os;
461         fstring native_lanman;
462         static BOOL done_sesssetup = False;
463         extern BOOL global_encrypted_passwords_negotiated;
464         extern BOOL global_spnego_negotiated;
465         extern int Protocol;
466         extern userdom_struct current_user_info;
467         extern int max_send;
468
469         auth_usersupplied_info *user_info = NULL;
470         extern struct auth_context *negprot_global_auth_context;
471         auth_serversupplied_info *server_info = NULL;
472
473         NTSTATUS nt_status;
474
475         BOOL doencrypt = global_encrypted_passwords_negotiated;
476         
477         START_PROFILE(SMBsesssetupX);
478
479         ZERO_STRUCT(lm_resp);
480         ZERO_STRUCT(nt_resp);
481         ZERO_STRUCT(plaintext_password);
482
483         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
484
485         /* a SPNEGO session setup has 12 command words, whereas a normal
486            NT1 session setup has 13. See the cifs spec. */
487         if (CVAL(inbuf, smb_wct) == 12 &&
488             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
489                 if (!global_spnego_negotiated) {
490                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
491                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
492                 }
493
494                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
495         }
496
497         smb_bufsize = SVAL(inbuf,smb_vwv2);
498
499         if (Protocol < PROTOCOL_NT1) {
500                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
501                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
502                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
503                 }
504
505                 if (doencrypt) {
506                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
507                 } else {
508                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
509                         /* Ensure null termination */
510                         plaintext_password.data[passlen1] = 0;
511                 }
512
513                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
514                 *domain = 0;
515   
516         } else {
517                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
518                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
519                 enum remote_arch_types ra_type = get_remote_arch();
520                 char *p = smb_buf(inbuf);    
521
522                 if(global_client_caps == 0)
523                         global_client_caps = IVAL(inbuf,smb_vwv11);
524                 
525                 /* client_caps is used as final determination if client is NT or Win95. 
526                    This is needed to return the correct error codes in some
527                    circumstances.
528                 */
529                 
530                 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
531                         if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
532                                 set_remote_arch( RA_WIN95);
533                         }
534                 }
535                 
536                 if (!doencrypt) {
537                         /* both Win95 and WinNT stuff up the password lengths for
538                            non-encrypting systems. Uggh. 
539                            
540                            if passlen1==24 its a win95 system, and its setting the
541                            password length incorrectly. Luckily it still works with the
542                            default code because Win95 will null terminate the password
543                            anyway 
544                            
545                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
546                            setting passlen2 to some random value which really stuffs
547                            things up. we need to fix that one.  */
548                         
549                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
550                                 passlen2 = 0;
551                 }
552                 
553                 /* check for nasty tricks */
554                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
555                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
556                 }
557
558                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
559                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
560                 }
561
562                 /* Save the lanman2 password and the NT md4 password. */
563                 
564                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
565                         doencrypt = False;
566                 }
567
568                 if (doencrypt) {
569                         lm_resp = data_blob(p, passlen1);
570                         nt_resp = data_blob(p+passlen1, passlen2);
571                 } else {
572                         pstring pass;
573                         srvstr_pull(inbuf, pass, smb_buf(inbuf), 
574                                     sizeof(pass),  passlen1, STR_TERMINATE);
575                         plaintext_password = data_blob(pass, strlen(pass)+1);
576                 }
577                 
578                 p += passlen1 + passlen2;
579                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
580                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
581                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
582                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
583                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s]\n",
584                          domain,native_os,native_lanman));
585         }
586         
587         /* don't allow for weird usernames or domains */
588         alpha_strcpy(user, user, ". _-$", sizeof(user));
589         alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
590         if (strstr(user, "..") || strstr(domain,"..")) {
591                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
592         }
593
594         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
595
596         if (*user) {
597                 if (global_spnego_negotiated) {
598                         
599                         /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */
600                         
601                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
602                         return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
603                 }
604                 fstrcpy(sub_user, user);
605
606                 /* setup the string used by %U */
607                 sub_set_smb_name(user);
608         } else {
609                 fstrcpy(sub_user, lp_guestaccount());
610         }
611
612         fstrcpy(current_user_info.smb_name,sub_user);
613
614         reload_services(True);
615         
616         if (lp_security() == SEC_SHARE) {
617                 /* in share level we should ignore any passwords */
618
619                 data_blob_free(&lm_resp);
620                 data_blob_free(&nt_resp);
621                 data_blob_clear_free(&plaintext_password);
622
623                 map_username(sub_user);
624                 add_session_user(sub_user);
625                 /* Then force it to null for the benfit of the code below */
626                 *user = 0;
627         }
628         
629         if (!*user) {
630
631                 nt_status = check_guest_password(&server_info);
632
633         } else if (doencrypt) {
634                 if (!negprot_global_auth_context) {
635                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
636                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
637                 }
638                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
639                                                          lm_resp, nt_resp);
640                 if (NT_STATUS_IS_OK(nt_status)) {
641                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
642                                                                                      user_info, 
643                                                                                      &server_info);
644                 }
645         } else {
646                 struct auth_context *plaintext_auth_context = NULL;
647                 const uint8 *chal;
648                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
649                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
650                         
651                         if (!make_user_info_for_reply(&user_info, 
652                                                       user, domain, chal,
653                                                       plaintext_password)) {
654                                 nt_status = NT_STATUS_NO_MEMORY;
655                         }
656                 
657                         if (NT_STATUS_IS_OK(nt_status)) {
658                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
659                                                                                         user_info, 
660                                                                                         &server_info); 
661                                 
662                                 (plaintext_auth_context->free)(&plaintext_auth_context);
663                         }
664                 }
665         }
666
667         free_user_info(&user_info);
668         
669         data_blob_free(&lm_resp);
670         data_blob_free(&nt_resp);
671         data_blob_clear_free(&plaintext_password);
672         
673         if (!NT_STATUS_IS_OK(nt_status)) {
674                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
675         }
676         
677         if (!NT_STATUS_IS_OK(nt_status)) {
678                 return ERROR_NT(nt_status_squash(nt_status));
679         }
680         
681         /* it's ok - setup a reply */
682         set_message(outbuf,3,0,True);
683         if (Protocol >= PROTOCOL_NT1) {
684                 add_signature(outbuf);
685                 /* perhaps grab OS version here?? */
686         }
687         
688         if (server_info->guest) {
689                 SSVAL(outbuf,smb_vwv2,1);
690         }
691
692         /* register the name and uid as being validated, so further connections
693            to a uid can get through without a password, on the same VC */
694
695         sess_vuid = register_vuid(server_info, sub_user);
696
697         free_server_info(&server_info);
698   
699         if (sess_vuid == -1) {
700                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
701         }
702
703  
704         SSVAL(outbuf,smb_uid,sess_vuid);
705         SSVAL(inbuf,smb_uid,sess_vuid);
706         
707         if (!done_sesssetup)
708                 max_send = MIN(max_send,smb_bufsize);
709         
710         done_sesssetup = True;
711         
712         END_PROFILE(SMBsesssetupX);
713         return chain_reply(inbuf,outbuf,length,bufsize);
714 }