s3:smbd/sesssetup: use a helper variable 'action' to mark guest access
[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         uint16_t action = 0;
404
405         NTSTATUS nt_status;
406         struct smbd_server_connection *sconn = req->sconn;
407
408         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
409         bool signing_allowed = false;
410         bool signing_mandatory = false;
411
412         START_PROFILE(SMBsesssetupX);
413
414         ZERO_STRUCT(lm_resp);
415         ZERO_STRUCT(nt_resp);
416         ZERO_STRUCT(plaintext_password);
417
418         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
419
420         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
421                 signing_allowed = true;
422         }
423         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
424                 signing_mandatory = true;
425         }
426
427         /*
428          * We can call srv_set_signing_negotiated() each time.
429          * It finds out when it needs to turn into a noop
430          * itself.
431          */
432         srv_set_signing_negotiated(req->sconn,
433                                    signing_allowed,
434                                    signing_mandatory);
435
436         /* a SPNEGO session setup has 12 command words, whereas a normal
437            NT1 session setup has 13. See the cifs spec. */
438         if (req->wct == 12 &&
439             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
440
441                 if (!sconn->smb1.negprot.spnego) {
442                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
443                                  "at SPNEGO session setup when it was not "
444                                  "negotiated.\n"));
445                         reply_nterror(req, nt_status_squash(
446                                               NT_STATUS_LOGON_FAILURE));
447                         END_PROFILE(SMBsesssetupX);
448                         return;
449                 }
450
451                 if (SVAL(req->vwv+4, 0) == 0) {
452                         setup_new_vc_session(req->sconn);
453                 }
454
455                 reply_sesssetup_and_X_spnego(req);
456                 END_PROFILE(SMBsesssetupX);
457                 return;
458         }
459
460         smb_bufsize = SVAL(req->vwv+2, 0);
461
462         if (get_Protocol() < PROTOCOL_NT1) {
463                 uint16 passlen1 = SVAL(req->vwv+7, 0);
464
465                 /* Never do NT status codes with protocols before NT1 as we
466                  * don't get client caps. */
467                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
468
469                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
470                         reply_nterror(req, nt_status_squash(
471                                               NT_STATUS_INVALID_PARAMETER));
472                         END_PROFILE(SMBsesssetupX);
473                         return;
474                 }
475
476                 if (doencrypt) {
477                         lm_resp = data_blob(req->buf, passlen1);
478                 } else {
479                         plaintext_password = data_blob(req->buf, passlen1+1);
480                         /* Ensure null termination */
481                         plaintext_password.data[passlen1] = 0;
482                 }
483
484                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
485                                        req->buf + passlen1, STR_TERMINATE);
486                 user = tmp ? tmp : "";
487
488                 domain = "";
489
490         } else {
491                 uint16 passlen1 = SVAL(req->vwv+7, 0);
492                 uint16 passlen2 = SVAL(req->vwv+8, 0);
493                 enum remote_arch_types ra_type = get_remote_arch();
494                 const uint8_t *p = req->buf;
495                 const uint8_t *save_p = req->buf;
496                 uint16 byte_count;
497
498
499                 if(global_client_caps == 0) {
500                         global_client_caps = IVAL(req->vwv+11, 0);
501
502                         if (!(global_client_caps & CAP_STATUS32)) {
503                                 remove_from_common_flags2(
504                                                 FLAGS2_32_BIT_ERROR_CODES);
505                         }
506
507                         /* client_caps is used as final determination if
508                          * client is NT or Win95. This is needed to return
509                          * the correct error codes in some circumstances.
510                         */
511
512                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
513                                         ra_type == RA_WIN95) {
514                                 if(!(global_client_caps & (CAP_NT_SMBS|
515                                                         CAP_STATUS32))) {
516                                         set_remote_arch( RA_WIN95);
517                                 }
518                         }
519                 }
520
521                 if (!doencrypt) {
522                         /* both Win95 and WinNT stuff up the password
523                          * lengths for non-encrypting systems. Uggh.
524
525                            if passlen1==24 its a win95 system, and its setting
526                            the password length incorrectly. Luckily it still
527                            works with the default code because Win95 will null
528                            terminate the password anyway
529
530                            if passlen1>0 and passlen2>0 then maybe its a NT box
531                            and its setting passlen2 to some random value which
532                            really stuffs things up. we need to fix that one.  */
533
534                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
535                                         passlen2 != 1) {
536                                 passlen2 = 0;
537                         }
538                 }
539
540                 /* check for nasty tricks */
541                 if (passlen1 > MAX_PASS_LEN
542                     || passlen1 > smbreq_bufrem(req, p)) {
543                         reply_nterror(req, nt_status_squash(
544                                               NT_STATUS_INVALID_PARAMETER));
545                         END_PROFILE(SMBsesssetupX);
546                         return;
547                 }
548
549                 if (passlen2 > MAX_PASS_LEN
550                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
551                         reply_nterror(req, nt_status_squash(
552                                               NT_STATUS_INVALID_PARAMETER));
553                         END_PROFILE(SMBsesssetupX);
554                         return;
555                 }
556
557                 /* Save the lanman2 password and the NT md4 password. */
558
559                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
560                         doencrypt = False;
561                 }
562
563                 if (doencrypt) {
564                         lm_resp = data_blob(p, passlen1);
565                         nt_resp = data_blob(p+passlen1, passlen2);
566                 } else {
567                         char *pass = NULL;
568                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
569
570                         if (unic && (passlen2 == 0) && passlen1) {
571                                 /* Only a ascii plaintext password was sent. */
572                                 (void)srvstr_pull_talloc(talloc_tos(),
573                                                         req->inbuf,
574                                                         req->flags2,
575                                                         &pass,
576                                                         req->buf,
577                                                         passlen1,
578                                                         STR_TERMINATE|STR_ASCII);
579                         } else {
580                                 (void)srvstr_pull_talloc(talloc_tos(),
581                                                         req->inbuf,
582                                                         req->flags2,
583                                                         &pass,
584                                                         req->buf,
585                                                         unic ? passlen2 : passlen1,
586                                                         STR_TERMINATE);
587                         }
588                         if (!pass) {
589                                 reply_nterror(req, nt_status_squash(
590                                               NT_STATUS_INVALID_PARAMETER));
591                                 END_PROFILE(SMBsesssetupX);
592                                 return;
593                         }
594                         plaintext_password = data_blob(pass, strlen(pass)+1);
595                 }
596
597                 p += passlen1 + passlen2;
598
599                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
600                                             STR_TERMINATE);
601                 user = tmp ? tmp : "";
602
603                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
604                                             STR_TERMINATE);
605                 domain = tmp ? tmp : "";
606
607                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
608                                             STR_TERMINATE);
609                 native_os = tmp ? tmp : "";
610
611                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
612                                             STR_TERMINATE);
613                 native_lanman = tmp ? tmp : "";
614
615                 /* not documented or decoded by Ethereal but there is one more
616                  * string in the extra bytes which is the same as the
617                  * PrimaryDomain when using extended security.  Windows NT 4
618                  * and 2003 use this string to store the native lanman string.
619                  * Windows 9x does not include a string here at all so we have
620                  * to check if we have any extra bytes left */
621
622                 byte_count = SVAL(req->vwv+13, 0);
623                 if ( PTR_DIFF(p, save_p) < byte_count) {
624                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
625                                                     STR_TERMINATE);
626                         primary_domain = tmp ? tmp : "";
627                 } else {
628                         primary_domain = talloc_strdup(talloc_tos(), "null");
629                 }
630
631                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
632                         "PrimaryDomain=[%s]\n",
633                         domain, native_os, native_lanman, primary_domain));
634
635                 if ( ra_type == RA_WIN2K ) {
636                         if ( strlen(native_lanman) == 0 )
637                                 ra_lanman_string( primary_domain );
638                         else
639                                 ra_lanman_string( native_lanman );
640                 }
641
642         }
643
644         if (SVAL(req->vwv+4, 0) == 0) {
645                 setup_new_vc_session(req->sconn);
646         }
647
648         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
649                                 domain, user, get_remote_machine_name()));
650
651         if (*user) {
652                 if (sconn->smb1.negprot.spnego) {
653
654                         /* This has to be here, because this is a perfectly
655                          * valid behaviour for guest logons :-( */
656
657                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
658                                 "at 'normal' session setup after "
659                                 "negotiating spnego.\n"));
660                         reply_nterror(req, nt_status_squash(
661                                               NT_STATUS_LOGON_FAILURE));
662                         END_PROFILE(SMBsesssetupX);
663                         return;
664                 }
665                 fstrcpy(sub_user, user);
666         } else {
667                 fstrcpy(sub_user, "");
668         }
669
670         sub_set_smb_name(sub_user);
671
672         reload_services(sconn, conn_snum_used, true);
673
674         if (!*user) {
675
676                 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
677
678         } else if (doencrypt) {
679                 struct auth4_context *negprot_auth_context = NULL;
680                 negprot_auth_context = sconn->smb1.negprot.auth_context;
681                 if (!negprot_auth_context) {
682                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
683                                 "session setup without negprot denied!\n"));
684                         reply_nterror(req, nt_status_squash(
685                                               NT_STATUS_LOGON_FAILURE));
686                         END_PROFILE(SMBsesssetupX);
687                         return;
688                 }
689                 nt_status = make_user_info_for_reply_enc(&user_info, user,
690                                                 domain,
691                                                 sconn->remote_address,
692                                                 lm_resp, nt_resp);
693                 if (NT_STATUS_IS_OK(nt_status)) {
694                         nt_status = auth_check_password_session_info(negprot_auth_context, 
695                                                                      req, user_info, &session_info);
696                 }
697         } else {
698                 struct auth4_context *plaintext_auth_context = NULL;
699
700                 nt_status = make_auth4_context(
701                         talloc_tos(), &plaintext_auth_context);
702
703                 if (NT_STATUS_IS_OK(nt_status)) {
704                         uint8_t chal[8];
705
706                         plaintext_auth_context->get_ntlm_challenge(
707                                         plaintext_auth_context, chal);
708
709                         if (!make_user_info_for_reply(&user_info,
710                                                       user, domain,
711                                                       sconn->remote_address,
712                                                       chal,
713                                                       plaintext_password)) {
714                                 nt_status = NT_STATUS_NO_MEMORY;
715                         }
716
717                         if (NT_STATUS_IS_OK(nt_status)) {
718                                 nt_status = auth_check_password_session_info(plaintext_auth_context, 
719                                                                              req, user_info, &session_info);
720                         }
721                         TALLOC_FREE(plaintext_auth_context);
722                 }
723         }
724
725         free_user_info(&user_info);
726
727         if (!NT_STATUS_IS_OK(nt_status)) {
728                 data_blob_free(&nt_resp);
729                 data_blob_free(&lm_resp);
730                 data_blob_clear_free(&plaintext_password);
731                 reply_nterror(req, nt_status_squash(nt_status));
732                 END_PROFILE(SMBsesssetupX);
733                 return;
734         }
735
736         data_blob_clear_free(&plaintext_password);
737
738         /* it's ok - setup a reply */
739         reply_outbuf(req, 3, 0);
740         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
741         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
742
743         if (get_Protocol() >= PROTOCOL_NT1) {
744                 push_signature(&req->outbuf);
745                 /* perhaps grab OS version here?? */
746         }
747
748         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
749                 action = 1;
750         }
751
752         /* register the name and uid as being validated, so further connections
753            to a uid can get through without a password, on the same VC */
754
755         /* Ignore the initial vuid. */
756         sess_vuid = register_initial_vuid(sconn);
757         if (sess_vuid == UID_FIELD_INVALID) {
758                 data_blob_free(&nt_resp);
759                 data_blob_free(&lm_resp);
760                 reply_nterror(req, nt_status_squash(
761                                       NT_STATUS_LOGON_FAILURE));
762                 END_PROFILE(SMBsesssetupX);
763                 return;
764         }
765         /* register_existing_vuid keeps the session_info */
766         sess_vuid = register_existing_vuid(sconn, sess_vuid,
767                                            session_info,
768                                            nt_resp.data ? nt_resp : lm_resp);
769         if (sess_vuid == UID_FIELD_INVALID) {
770                 data_blob_free(&nt_resp);
771                 data_blob_free(&lm_resp);
772                 reply_nterror(req, nt_status_squash(
773                                       NT_STATUS_LOGON_FAILURE));
774                 END_PROFILE(SMBsesssetupX);
775                 return;
776         }
777
778         /* current_user_info is changed on new vuid */
779         reload_services(sconn, conn_snum_used, true);
780
781         data_blob_free(&nt_resp);
782         data_blob_free(&lm_resp);
783
784         SSVAL(req->outbuf,smb_vwv2,action);
785         SSVAL(req->outbuf,smb_uid,sess_vuid);
786         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
787         req->vuid = sess_vuid;
788
789         if (!sconn->smb1.sessions.done_sesssetup) {
790                 sconn->smb1.sessions.max_send =
791                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
792         }
793         sconn->smb1.sessions.done_sesssetup = true;
794
795         END_PROFILE(SMBsesssetupX);
796 }