s3: Make sure the andX chains are ended correctly
[metze/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 <jmcd@us.ibm.com> 2002
7    Copyright (C) Luke Howard          2003
8    Copyright (C) Volker Lendecke      2007
9    Copyright (C) Jeremy Allison       2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
39
40 /****************************************************************************
41  Add the standard 'Samba' signature to the end of the session setup.
42 ****************************************************************************/
43
44 static int push_signature(uint8 **outbuf)
45 {
46         char *lanman;
47         int result, tmp;
48
49         result = 0;
50
51         tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
52
53         if (tmp == -1) return -1;
54         result += tmp;
55
56         if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
57                 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
58                 SAFE_FREE(lanman);
59         }
60         else {
61                 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
62         }
63
64         if (tmp == -1) return -1;
65         result += tmp;
66
67         tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
68
69         if (tmp == -1) return -1;
70         result += tmp;
71
72         return result;
73 }
74
75 /****************************************************************************
76  Do a 'guest' logon, getting back the
77 ****************************************************************************/
78
79 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
80                                      TALLOC_CTX *mem_ctx, 
81                                      struct auth_session_info **session_info)
82 {
83         struct auth4_context *auth_context;
84         struct auth_usersupplied_info *user_info = NULL;
85         uint8_t chal[8];
86         NTSTATUS nt_status;
87
88         DEBUG(3,("Got anonymous request\n"));
89
90         nt_status = make_auth4_context(talloc_tos(), &auth_context);
91         if (!NT_STATUS_IS_OK(nt_status)) {
92                 return nt_status;
93         }
94
95         auth_context->get_ntlm_challenge(auth_context,
96                                          chal);
97
98         if (!make_user_info_guest(remote_address, &user_info)) {
99                 TALLOC_FREE(auth_context);
100                 return NT_STATUS_NO_MEMORY;
101         }
102
103         nt_status = auth_check_password_session_info(auth_context, 
104                                                      mem_ctx, user_info, session_info);
105         free_user_info(&user_info);
106         TALLOC_FREE(auth_context);
107         return nt_status;
108 }
109
110 /****************************************************************************
111  Reply to a session setup command.
112  conn POINTER CAN BE NULL HERE !
113 ****************************************************************************/
114
115 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
116 {
117         const uint8 *p;
118         DATA_BLOB in_blob;
119         DATA_BLOB out_blob = data_blob_null;
120         size_t bufrem;
121         char *tmp;
122         const char *native_os;
123         const char *native_lanman;
124         const char *primary_domain;
125         const char *p2;
126         uint16 data_blob_len = SVAL(req->vwv+7, 0);
127         enum remote_arch_types ra_type = get_remote_arch();
128         int vuid = req->vuid;
129         user_struct *vuser = NULL;
130         NTSTATUS status = NT_STATUS_OK;
131         struct smbd_server_connection *sconn = req->sconn;
132         uint16_t action = 0;
133
134         DEBUG(3,("Doing spnego session setup\n"));
135
136         if (global_client_caps == 0) {
137                 global_client_caps = IVAL(req->vwv+10, 0);
138
139                 if (!(global_client_caps & CAP_STATUS32)) {
140                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
141                 }
142         }
143
144         p = req->buf;
145
146         if (data_blob_len == 0) {
147                 /* an invalid request */
148                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
149                 return;
150         }
151
152         bufrem = smbreq_bufrem(req, p);
153         /* pull the spnego blob */
154         in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
155
156 #if 0
157         file_save("negotiate.dat", in_blob.data, in_blob.length);
158 #endif
159
160         p2 = (const char *)req->buf + in_blob.length;
161
162         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
163                                      STR_TERMINATE);
164         native_os = tmp ? tmp : "";
165
166         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
167                                      STR_TERMINATE);
168         native_lanman = tmp ? tmp : "";
169
170         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
171                                      STR_TERMINATE);
172         primary_domain = tmp ? tmp : "";
173
174         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
175                 native_os, native_lanman, primary_domain));
176
177         if ( ra_type == RA_WIN2K ) {
178                 /* Vista sets neither the OS or lanman strings */
179
180                 if ( !strlen(native_os) && !strlen(native_lanman) )
181                         set_remote_arch(RA_VISTA);
182
183                 /* Windows 2003 doesn't set the native lanman string,
184                    but does set primary domain which is a bug I think */
185
186                 if ( !strlen(native_lanman) ) {
187                         ra_lanman_string( primary_domain );
188                 } else {
189                         ra_lanman_string( native_lanman );
190                 }
191         } else if ( ra_type == RA_VISTA ) {
192                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
193                         set_remote_arch(RA_OSX);
194                 }
195         }
196
197         vuser = get_valid_user_struct(sconn, vuid);
198         if (vuser != NULL) {
199                 reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
200                 return;
201         }
202
203         /* Do we have a valid vuid now ? */
204         if (!is_partial_auth_vuid(sconn, vuid)) {
205                 /* No, start a new authentication setup. */
206                 vuid = register_initial_vuid(sconn);
207                 if (vuid == UID_FIELD_INVALID) {
208                         reply_nterror(req, nt_status_squash(
209                                               NT_STATUS_INVALID_PARAMETER));
210                         return;
211                 }
212         }
213
214         vuser = get_partial_auth_user_struct(sconn, vuid);
215         /* This MUST be valid. */
216         if (!vuser) {
217                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
218         }
219
220         if (!vuser->gensec_security) {
221                 status = auth_generic_prepare(vuser, sconn->remote_address,
222                                               &vuser->gensec_security);
223                 if (!NT_STATUS_IS_OK(status)) {
224                         /* Kill the intermediate vuid */
225                         invalidate_vuid(sconn, vuid);
226                         reply_nterror(req, nt_status_squash(status));
227                         return;
228                 }
229
230                 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
231                 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
232
233                 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
234                 if (!NT_STATUS_IS_OK(status)) {
235                         DEBUG(0, ("Failed to start SPNEGO handler!\n"));
236                         /* Kill the intermediate vuid */
237                         invalidate_vuid(sconn, vuid);
238                         reply_nterror(req, nt_status_squash(status));
239                         return;
240                 }
241         }
242
243         status = gensec_update(vuser->gensec_security,
244                                talloc_tos(), NULL,
245                                in_blob, &out_blob);
246         if (!NT_STATUS_IS_OK(status) &&
247             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
248                 /* Kill the intermediate vuid */
249                 invalidate_vuid(sconn, vuid);
250                 reply_nterror(req, nt_status_squash(status));
251                 return;
252         }
253
254         if (NT_STATUS_IS_OK(status)) {
255                 struct auth_session_info *session_info = NULL;
256                 int tmp_vuid;
257
258                 status = gensec_session_info(vuser->gensec_security,
259                                              talloc_tos(),
260                                              &session_info);
261                 if (!NT_STATUS_IS_OK(status)) {
262                         DEBUG(1,("Failed to generate session_info "
263                                  "(user and group token) for session setup: %s\n",
264                                  nt_errstr(status)));
265                         /* Kill the intermediate vuid */
266                         data_blob_free(&out_blob);
267                         invalidate_vuid(sconn, vuid);
268                         reply_nterror(req, nt_status_squash(status));
269                         return;
270                 }
271
272                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
273                         action = 1;
274                 }
275
276                 /* register_existing_vuid keeps the server info */
277                 tmp_vuid = register_existing_vuid(sconn, vuid,
278                                                   session_info,
279                                                   data_blob_null);
280                 if (tmp_vuid != vuid) {
281                         data_blob_free(&out_blob);
282                         invalidate_vuid(sconn, vuid);
283                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
284                         return;
285                 }
286
287                 /* current_user_info is changed on new vuid */
288                 reload_services(sconn, conn_snum_used, true);
289         }
290
291         reply_outbuf(req, 4, 0);
292
293         SSVAL(req->outbuf, smb_uid, vuid);
294         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
295         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
296         SSVAL(req->outbuf, smb_vwv2, action);
297         SSVAL(req->outbuf, smb_vwv3, out_blob.length);
298
299         if (message_push_blob(&req->outbuf, out_blob) == -1) {
300                 data_blob_free(&out_blob);
301                 invalidate_vuid(sconn, vuid);
302                 reply_nterror(req, NT_STATUS_NO_MEMORY);
303                 return;
304         }
305         data_blob_free(&out_blob);
306
307         if (push_signature(&req->outbuf) == -1) {
308                 invalidate_vuid(sconn, vuid);
309                 reply_nterror(req, NT_STATUS_NO_MEMORY);
310                 return;
311         }
312 }
313
314 /****************************************************************************
315  On new VC == 0, shutdown *all* old connections and users.
316  It seems that only NT4.x does this. At W2K and above (XP etc.).
317  a new session setup with VC==0 is ignored.
318 ****************************************************************************/
319
320 struct shutdown_state {
321         const char *ip;
322         struct messaging_context *msg_ctx;
323 };
324
325 static int shutdown_other_smbds(const struct connections_key *key,
326                                 const struct connections_data *crec,
327                                 void *private_data)
328 {
329         struct shutdown_state *state = (struct shutdown_state *)private_data;
330
331         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
332                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
333
334         if (!process_exists(crec->pid)) {
335                 DEBUG(10, ("process does not exist\n"));
336                 return 0;
337         }
338
339         if (procid_is_me(&crec->pid)) {
340                 DEBUG(10, ("It's me\n"));
341                 return 0;
342         }
343
344         if (strcmp(state->ip, crec->addr) != 0) {
345                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
346                 return 0;
347         }
348
349         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
350                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
351                   state->ip));
352
353         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
354                        &data_blob_null);
355         return 0;
356 }
357
358 static void setup_new_vc_session(struct smbd_server_connection *sconn)
359 {
360         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
361                 "compatible we would close all old resources.\n"));
362 #if 0
363         conn_close_all();
364         invalidate_all_vuids();
365 #endif
366         if (lp_reset_on_zero_vc()) {
367                 char *addr;
368                 struct shutdown_state state;
369
370                 addr = tsocket_address_inet_addr_string(
371                         sconn->remote_address, talloc_tos());
372                 if (addr == NULL) {
373                         return;
374                 }
375                 state.ip = addr;
376                 state.msg_ctx = sconn->msg_ctx;
377                 connections_forall_read(shutdown_other_smbds, &state);
378                 TALLOC_FREE(addr);
379         }
380 }
381
382 /****************************************************************************
383  Reply to a session setup command.
384 ****************************************************************************/
385
386 void reply_sesssetup_and_X(struct smb_request *req)
387 {
388         int sess_vuid;
389         int smb_bufsize;
390         DATA_BLOB lm_resp;
391         DATA_BLOB nt_resp;
392         DATA_BLOB plaintext_password;
393         char *tmp;
394         const char *user;
395         fstring sub_user; /* Sanitised username for substituion */
396         const char *domain;
397         const char *native_os;
398         const char *native_lanman;
399         const char *primary_domain;
400         struct auth_usersupplied_info *user_info = NULL;
401         struct auth_session_info *session_info = NULL;
402         uint16 smb_flag2 = req->flags2;
403
404         NTSTATUS nt_status;
405         struct smbd_server_connection *sconn = req->sconn;
406
407         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
408         bool signing_allowed = false;
409         bool signing_mandatory = false;
410
411         START_PROFILE(SMBsesssetupX);
412
413         ZERO_STRUCT(lm_resp);
414         ZERO_STRUCT(nt_resp);
415         ZERO_STRUCT(plaintext_password);
416
417         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
418
419         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
420                 signing_allowed = true;
421         }
422         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
423                 signing_mandatory = true;
424         }
425
426         /*
427          * We can call srv_set_signing_negotiated() each time.
428          * It finds out when it needs to turn into a noop
429          * itself.
430          */
431         srv_set_signing_negotiated(req->sconn,
432                                    signing_allowed,
433                                    signing_mandatory);
434
435         /* a SPNEGO session setup has 12 command words, whereas a normal
436            NT1 session setup has 13. See the cifs spec. */
437         if (req->wct == 12 &&
438             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
439
440                 if (!sconn->smb1.negprot.spnego) {
441                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
442                                  "at SPNEGO session setup when it was not "
443                                  "negotiated.\n"));
444                         reply_nterror(req, nt_status_squash(
445                                               NT_STATUS_LOGON_FAILURE));
446                         END_PROFILE(SMBsesssetupX);
447                         return;
448                 }
449
450                 if (SVAL(req->vwv+4, 0) == 0) {
451                         setup_new_vc_session(req->sconn);
452                 }
453
454                 reply_sesssetup_and_X_spnego(req);
455                 END_PROFILE(SMBsesssetupX);
456                 return;
457         }
458
459         smb_bufsize = SVAL(req->vwv+2, 0);
460
461         if (get_Protocol() < PROTOCOL_NT1) {
462                 uint16 passlen1 = SVAL(req->vwv+7, 0);
463
464                 /* Never do NT status codes with protocols before NT1 as we
465                  * don't get client caps. */
466                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
467
468                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
469                         reply_nterror(req, nt_status_squash(
470                                               NT_STATUS_INVALID_PARAMETER));
471                         END_PROFILE(SMBsesssetupX);
472                         return;
473                 }
474
475                 if (doencrypt) {
476                         lm_resp = data_blob(req->buf, passlen1);
477                 } else {
478                         plaintext_password = data_blob(req->buf, passlen1+1);
479                         /* Ensure null termination */
480                         plaintext_password.data[passlen1] = 0;
481                 }
482
483                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
484                                        req->buf + passlen1, STR_TERMINATE);
485                 user = tmp ? tmp : "";
486
487                 domain = "";
488
489         } else {
490                 uint16 passlen1 = SVAL(req->vwv+7, 0);
491                 uint16 passlen2 = SVAL(req->vwv+8, 0);
492                 enum remote_arch_types ra_type = get_remote_arch();
493                 const uint8_t *p = req->buf;
494                 const uint8_t *save_p = req->buf;
495                 uint16 byte_count;
496
497
498                 if(global_client_caps == 0) {
499                         global_client_caps = IVAL(req->vwv+11, 0);
500
501                         if (!(global_client_caps & CAP_STATUS32)) {
502                                 remove_from_common_flags2(
503                                                 FLAGS2_32_BIT_ERROR_CODES);
504                         }
505
506                         /* client_caps is used as final determination if
507                          * client is NT or Win95. This is needed to return
508                          * the correct error codes in some circumstances.
509                         */
510
511                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
512                                         ra_type == RA_WIN95) {
513                                 if(!(global_client_caps & (CAP_NT_SMBS|
514                                                         CAP_STATUS32))) {
515                                         set_remote_arch( RA_WIN95);
516                                 }
517                         }
518                 }
519
520                 if (!doencrypt) {
521                         /* both Win95 and WinNT stuff up the password
522                          * lengths for non-encrypting systems. Uggh.
523
524                            if passlen1==24 its a win95 system, and its setting
525                            the password length incorrectly. Luckily it still
526                            works with the default code because Win95 will null
527                            terminate the password anyway
528
529                            if passlen1>0 and passlen2>0 then maybe its a NT box
530                            and its setting passlen2 to some random value which
531                            really stuffs things up. we need to fix that one.  */
532
533                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
534                                         passlen2 != 1) {
535                                 passlen2 = 0;
536                         }
537                 }
538
539                 /* check for nasty tricks */
540                 if (passlen1 > MAX_PASS_LEN
541                     || passlen1 > smbreq_bufrem(req, p)) {
542                         reply_nterror(req, nt_status_squash(
543                                               NT_STATUS_INVALID_PARAMETER));
544                         END_PROFILE(SMBsesssetupX);
545                         return;
546                 }
547
548                 if (passlen2 > MAX_PASS_LEN
549                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
550                         reply_nterror(req, nt_status_squash(
551                                               NT_STATUS_INVALID_PARAMETER));
552                         END_PROFILE(SMBsesssetupX);
553                         return;
554                 }
555
556                 /* Save the lanman2 password and the NT md4 password. */
557
558                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
559                         doencrypt = False;
560                 }
561
562                 if (doencrypt) {
563                         lm_resp = data_blob(p, passlen1);
564                         nt_resp = data_blob(p+passlen1, passlen2);
565                 } else {
566                         char *pass = NULL;
567                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
568
569                         if (unic && (passlen2 == 0) && passlen1) {
570                                 /* Only a ascii plaintext password was sent. */
571                                 (void)srvstr_pull_talloc(talloc_tos(),
572                                                         req->inbuf,
573                                                         req->flags2,
574                                                         &pass,
575                                                         req->buf,
576                                                         passlen1,
577                                                         STR_TERMINATE|STR_ASCII);
578                         } else {
579                                 (void)srvstr_pull_talloc(talloc_tos(),
580                                                         req->inbuf,
581                                                         req->flags2,
582                                                         &pass,
583                                                         req->buf,
584                                                         unic ? passlen2 : passlen1,
585                                                         STR_TERMINATE);
586                         }
587                         if (!pass) {
588                                 reply_nterror(req, nt_status_squash(
589                                               NT_STATUS_INVALID_PARAMETER));
590                                 END_PROFILE(SMBsesssetupX);
591                                 return;
592                         }
593                         plaintext_password = data_blob(pass, strlen(pass)+1);
594                 }
595
596                 p += passlen1 + passlen2;
597
598                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
599                                             STR_TERMINATE);
600                 user = tmp ? tmp : "";
601
602                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
603                                             STR_TERMINATE);
604                 domain = tmp ? tmp : "";
605
606                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
607                                             STR_TERMINATE);
608                 native_os = tmp ? tmp : "";
609
610                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
611                                             STR_TERMINATE);
612                 native_lanman = tmp ? tmp : "";
613
614                 /* not documented or decoded by Ethereal but there is one more
615                  * string in the extra bytes which is the same as the
616                  * PrimaryDomain when using extended security.  Windows NT 4
617                  * and 2003 use this string to store the native lanman string.
618                  * Windows 9x does not include a string here at all so we have
619                  * to check if we have any extra bytes left */
620
621                 byte_count = SVAL(req->vwv+13, 0);
622                 if ( PTR_DIFF(p, save_p) < byte_count) {
623                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
624                                                     STR_TERMINATE);
625                         primary_domain = tmp ? tmp : "";
626                 } else {
627                         primary_domain = talloc_strdup(talloc_tos(), "null");
628                 }
629
630                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
631                         "PrimaryDomain=[%s]\n",
632                         domain, native_os, native_lanman, primary_domain));
633
634                 if ( ra_type == RA_WIN2K ) {
635                         if ( strlen(native_lanman) == 0 )
636                                 ra_lanman_string( primary_domain );
637                         else
638                                 ra_lanman_string( native_lanman );
639                 }
640
641         }
642
643         if (SVAL(req->vwv+4, 0) == 0) {
644                 setup_new_vc_session(req->sconn);
645         }
646
647         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
648                                 domain, user, get_remote_machine_name()));
649
650         if (*user) {
651                 if (sconn->smb1.negprot.spnego) {
652
653                         /* This has to be here, because this is a perfectly
654                          * valid behaviour for guest logons :-( */
655
656                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
657                                 "at 'normal' session setup after "
658                                 "negotiating spnego.\n"));
659                         reply_nterror(req, nt_status_squash(
660                                               NT_STATUS_LOGON_FAILURE));
661                         END_PROFILE(SMBsesssetupX);
662                         return;
663                 }
664                 fstrcpy(sub_user, user);
665         } else {
666                 fstrcpy(sub_user, "");
667         }
668
669         sub_set_smb_name(sub_user);
670
671         reload_services(sconn, conn_snum_used, true);
672
673         if (!*user) {
674
675                 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
676
677         } else if (doencrypt) {
678                 struct auth4_context *negprot_auth_context = NULL;
679                 negprot_auth_context = sconn->smb1.negprot.auth_context;
680                 if (!negprot_auth_context) {
681                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
682                                 "session setup without negprot denied!\n"));
683                         reply_nterror(req, nt_status_squash(
684                                               NT_STATUS_LOGON_FAILURE));
685                         END_PROFILE(SMBsesssetupX);
686                         return;
687                 }
688                 nt_status = make_user_info_for_reply_enc(&user_info, user,
689                                                 domain,
690                                                 sconn->remote_address,
691                                                 lm_resp, nt_resp);
692                 if (NT_STATUS_IS_OK(nt_status)) {
693                         nt_status = auth_check_password_session_info(negprot_auth_context, 
694                                                                      req, user_info, &session_info);
695                 }
696         } else {
697                 struct auth4_context *plaintext_auth_context = NULL;
698
699                 nt_status = make_auth4_context(
700                         talloc_tos(), &plaintext_auth_context);
701
702                 if (NT_STATUS_IS_OK(nt_status)) {
703                         uint8_t chal[8];
704
705                         plaintext_auth_context->get_ntlm_challenge(
706                                         plaintext_auth_context, chal);
707
708                         if (!make_user_info_for_reply(&user_info,
709                                                       user, domain,
710                                                       sconn->remote_address,
711                                                       chal,
712                                                       plaintext_password)) {
713                                 nt_status = NT_STATUS_NO_MEMORY;
714                         }
715
716                         if (NT_STATUS_IS_OK(nt_status)) {
717                                 nt_status = auth_check_password_session_info(plaintext_auth_context, 
718                                                                              req, user_info, &session_info);
719                         }
720                         TALLOC_FREE(plaintext_auth_context);
721                 }
722         }
723
724         free_user_info(&user_info);
725
726         if (!NT_STATUS_IS_OK(nt_status)) {
727                 data_blob_free(&nt_resp);
728                 data_blob_free(&lm_resp);
729                 data_blob_clear_free(&plaintext_password);
730                 reply_nterror(req, nt_status_squash(nt_status));
731                 END_PROFILE(SMBsesssetupX);
732                 return;
733         }
734
735         data_blob_clear_free(&plaintext_password);
736
737         /* it's ok - setup a reply */
738         reply_outbuf(req, 3, 0);
739         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
740         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
741
742         if (get_Protocol() >= PROTOCOL_NT1) {
743                 push_signature(&req->outbuf);
744                 /* perhaps grab OS version here?? */
745         }
746
747         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
748                 SSVAL(req->outbuf,smb_vwv2,1);
749         }
750
751         /* register the name and uid as being validated, so further connections
752            to a uid can get through without a password, on the same VC */
753
754         /* Ignore the initial vuid. */
755         sess_vuid = register_initial_vuid(sconn);
756         if (sess_vuid == UID_FIELD_INVALID) {
757                 data_blob_free(&nt_resp);
758                 data_blob_free(&lm_resp);
759                 reply_nterror(req, nt_status_squash(
760                                       NT_STATUS_LOGON_FAILURE));
761                 END_PROFILE(SMBsesssetupX);
762                 return;
763         }
764         /* register_existing_vuid keeps the session_info */
765         sess_vuid = register_existing_vuid(sconn, sess_vuid,
766                                            session_info,
767                                            nt_resp.data ? nt_resp : lm_resp);
768         if (sess_vuid == UID_FIELD_INVALID) {
769                 data_blob_free(&nt_resp);
770                 data_blob_free(&lm_resp);
771                 reply_nterror(req, nt_status_squash(
772                                       NT_STATUS_LOGON_FAILURE));
773                 END_PROFILE(SMBsesssetupX);
774                 return;
775         }
776
777         /* current_user_info is changed on new vuid */
778         reload_services(sconn, conn_snum_used, true);
779
780         data_blob_free(&nt_resp);
781         data_blob_free(&lm_resp);
782
783         SSVAL(req->outbuf,smb_uid,sess_vuid);
784         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
785         req->vuid = sess_vuid;
786
787         if (!sconn->smb1.sessions.done_sesssetup) {
788                 sconn->smb1.sessions.max_send =
789                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
790         }
791         sconn->smb1.sessions.done_sesssetup = true;
792
793         END_PROFILE(SMBsesssetupX);
794         chain_reply(req);
795         return;
796 }