s3-smbd Remove unused code now we always have SPNEGO via gensec
[ira/wip.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                                      struct auth_serversupplied_info **server_info)
81 {
82         struct auth_context *auth_context;
83         struct auth_usersupplied_info *user_info = NULL;
84
85         NTSTATUS nt_status;
86         static unsigned char chal[8] = { 0, };
87
88         DEBUG(3,("Got anonymous request\n"));
89
90         nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
91         if (!NT_STATUS_IS_OK(nt_status)) {
92                 return nt_status;
93         }
94
95         if (!make_user_info_guest(remote_address, &user_info)) {
96                 TALLOC_FREE(auth_context);
97                 return NT_STATUS_NO_MEMORY;
98         }
99
100         nt_status = auth_context->check_ntlm_password(auth_context,
101                                                 user_info,
102                                                 server_info);
103         TALLOC_FREE(auth_context);
104         free_user_info(&user_info);
105         return nt_status;
106 }
107
108 /****************************************************************************
109  Reply to a session setup command.
110  conn POINTER CAN BE NULL HERE !
111 ****************************************************************************/
112
113 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
114 {
115         const uint8 *p;
116         DATA_BLOB in_blob;
117         DATA_BLOB out_blob = data_blob_null;
118         size_t bufrem;
119         char *tmp;
120         const char *native_os;
121         const char *native_lanman;
122         const char *primary_domain;
123         const char *p2;
124         uint16 data_blob_len = SVAL(req->vwv+7, 0);
125         enum remote_arch_types ra_type = get_remote_arch();
126         int vuid = req->vuid;
127         user_struct *vuser = NULL;
128         NTSTATUS status = NT_STATUS_OK;
129         struct smbd_server_connection *sconn = req->sconn;
130         uint16_t action = 0;
131
132         DEBUG(3,("Doing spnego session setup\n"));
133
134         if (global_client_caps == 0) {
135                 global_client_caps = IVAL(req->vwv+10, 0);
136
137                 if (!(global_client_caps & CAP_STATUS32)) {
138                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
139                 }
140         }
141
142         p = req->buf;
143
144         if (data_blob_len == 0) {
145                 /* an invalid request */
146                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
147                 return;
148         }
149
150         bufrem = smbreq_bufrem(req, p);
151         /* pull the spnego blob */
152         in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
153
154 #if 0
155         file_save("negotiate.dat", in_blob.data, in_blob.length);
156 #endif
157
158         p2 = (const char *)req->buf + in_blob.length;
159
160         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
161                                      STR_TERMINATE);
162         native_os = tmp ? tmp : "";
163
164         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
165                                      STR_TERMINATE);
166         native_lanman = tmp ? tmp : "";
167
168         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
169                                      STR_TERMINATE);
170         primary_domain = tmp ? tmp : "";
171
172         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
173                 native_os, native_lanman, primary_domain));
174
175         if ( ra_type == RA_WIN2K ) {
176                 /* Vista sets neither the OS or lanman strings */
177
178                 if ( !strlen(native_os) && !strlen(native_lanman) )
179                         set_remote_arch(RA_VISTA);
180
181                 /* Windows 2003 doesn't set the native lanman string,
182                    but does set primary domain which is a bug I think */
183
184                 if ( !strlen(native_lanman) ) {
185                         ra_lanman_string( primary_domain );
186                 } else {
187                         ra_lanman_string( native_lanman );
188                 }
189         } else if ( ra_type == RA_VISTA ) {
190                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
191                         set_remote_arch(RA_OSX);
192                 }
193         }
194
195         vuser = get_valid_user_struct(sconn, vuid);
196         if (vuser != NULL) {
197                 reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
198                 return;
199         }
200
201         /* Do we have a valid vuid now ? */
202         if (!is_partial_auth_vuid(sconn, vuid)) {
203                 /* No, start a new authentication setup. */
204                 vuid = register_initial_vuid(sconn);
205                 if (vuid == UID_FIELD_INVALID) {
206                         reply_nterror(req, nt_status_squash(
207                                               NT_STATUS_INVALID_PARAMETER));
208                         return;
209                 }
210         }
211
212         vuser = get_partial_auth_user_struct(sconn, vuid);
213         /* This MUST be valid. */
214         if (!vuser) {
215                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
216         }
217
218         if (!vuser->gensec_security) {
219                 status = auth_generic_prepare(vuser, sconn->remote_address,
220                                               &vuser->gensec_security);
221                 if (!NT_STATUS_IS_OK(status)) {
222                         /* Kill the intermediate vuid */
223                         invalidate_vuid(sconn, vuid);
224                         reply_nterror(req, nt_status_squash(status));
225                         return;
226                 }
227
228                 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
229                 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
230
231                 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
232                 if (!NT_STATUS_IS_OK(status)) {
233                         DEBUG(0, ("Failed to start SPNEGO handler!\n"));
234                         /* Kill the intermediate vuid */
235                         invalidate_vuid(sconn, vuid);
236                         reply_nterror(req, nt_status_squash(status));
237                         return;
238                 }
239         }
240
241         status = gensec_update(vuser->gensec_security,
242                                talloc_tos(), NULL,
243                                in_blob, &out_blob);
244         if (!NT_STATUS_IS_OK(status) &&
245             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
246                 /* Kill the intermediate vuid */
247                 invalidate_vuid(sconn, vuid);
248                 reply_nterror(req, nt_status_squash(status));
249                 return;
250         }
251
252         if (NT_STATUS_IS_OK(status)) {
253                 struct auth_session_info *session_info = NULL;
254                 int tmp_vuid;
255
256                 status = gensec_session_info(vuser->gensec_security,
257                                              talloc_tos(),
258                                              &session_info);
259                 if (!NT_STATUS_IS_OK(status)) {
260                         /* Kill the intermediate vuid */
261                         data_blob_free(&out_blob);
262                         invalidate_vuid(sconn, vuid);
263                         reply_nterror(req, nt_status_squash(status));
264                         return;
265                 }
266
267                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
268                         action = 1;
269                 }
270
271                 /* register_existing_vuid keeps the server info */
272                 tmp_vuid = register_existing_vuid(sconn, vuid,
273                                                   session_info,
274                                                   data_blob_null);
275                 if (tmp_vuid != vuid) {
276                         data_blob_free(&out_blob);
277                         invalidate_vuid(sconn, vuid);
278                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
279                         return;
280                 }
281
282                 /* current_user_info is changed on new vuid */
283                 reload_services(sconn, conn_snum_used, true);
284         }
285
286         reply_outbuf(req, 4, 0);
287
288         SSVAL(req->outbuf, smb_uid, vuid);
289         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
290         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
291         SSVAL(req->outbuf, smb_vwv2, action);
292         SSVAL(req->outbuf, smb_vwv3, out_blob.length);
293
294         if (message_push_blob(&req->outbuf, out_blob) == -1) {
295                 data_blob_free(&out_blob);
296                 invalidate_vuid(sconn, vuid);
297                 reply_nterror(req, NT_STATUS_NO_MEMORY);
298                 return;
299         }
300         data_blob_free(&out_blob);
301
302         if (push_signature(&req->outbuf) == -1) {
303                 invalidate_vuid(sconn, vuid);
304                 reply_nterror(req, NT_STATUS_NO_MEMORY);
305                 return;
306         }
307 }
308
309 /****************************************************************************
310  On new VC == 0, shutdown *all* old connections and users.
311  It seems that only NT4.x does this. At W2K and above (XP etc.).
312  a new session setup with VC==0 is ignored.
313 ****************************************************************************/
314
315 struct shutdown_state {
316         const char *ip;
317         struct messaging_context *msg_ctx;
318 };
319
320 static int shutdown_other_smbds(const struct connections_key *key,
321                                 const struct connections_data *crec,
322                                 void *private_data)
323 {
324         struct shutdown_state *state = (struct shutdown_state *)private_data;
325
326         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
327                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
328
329         if (!process_exists(crec->pid)) {
330                 DEBUG(10, ("process does not exist\n"));
331                 return 0;
332         }
333
334         if (procid_is_me(&crec->pid)) {
335                 DEBUG(10, ("It's me\n"));
336                 return 0;
337         }
338
339         if (strcmp(state->ip, crec->addr) != 0) {
340                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
341                 return 0;
342         }
343
344         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
345                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
346                   state->ip));
347
348         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
349                        &data_blob_null);
350         return 0;
351 }
352
353 static void setup_new_vc_session(struct smbd_server_connection *sconn)
354 {
355         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
356                 "compatible we would close all old resources.\n"));
357 #if 0
358         conn_close_all();
359         invalidate_all_vuids();
360 #endif
361         if (lp_reset_on_zero_vc()) {
362                 char *addr;
363                 struct shutdown_state state;
364
365                 addr = tsocket_address_inet_addr_string(
366                         sconn->remote_address, talloc_tos());
367                 if (addr == NULL) {
368                         return;
369                 }
370                 state.ip = addr;
371                 state.msg_ctx = sconn->msg_ctx;
372                 connections_forall_read(shutdown_other_smbds, &state);
373                 TALLOC_FREE(addr);
374         }
375 }
376
377 /****************************************************************************
378  Reply to a session setup command.
379 ****************************************************************************/
380
381 void reply_sesssetup_and_X(struct smb_request *req)
382 {
383         int sess_vuid;
384         int smb_bufsize;
385         DATA_BLOB lm_resp;
386         DATA_BLOB nt_resp;
387         DATA_BLOB plaintext_password;
388         char *tmp;
389         const char *user;
390         fstring sub_user; /* Sanitised username for substituion */
391         const char *domain;
392         const char *native_os;
393         const char *native_lanman;
394         const char *primary_domain;
395         struct auth_usersupplied_info *user_info = NULL;
396         struct auth_serversupplied_info *server_info = NULL;
397         struct auth_session_info *session_info = NULL;
398         uint16 smb_flag2 = req->flags2;
399
400         NTSTATUS nt_status;
401         struct smbd_server_connection *sconn = req->sconn;
402
403         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
404         bool signing_allowed = false;
405         bool signing_mandatory = false;
406
407         START_PROFILE(SMBsesssetupX);
408
409         ZERO_STRUCT(lm_resp);
410         ZERO_STRUCT(nt_resp);
411         ZERO_STRUCT(plaintext_password);
412
413         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
414
415         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
416                 signing_allowed = true;
417         }
418         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
419                 signing_mandatory = true;
420         }
421
422         /*
423          * We can call srv_set_signing_negotiated() each time.
424          * It finds out when it needs to turn into a noop
425          * itself.
426          */
427         srv_set_signing_negotiated(req->sconn,
428                                    signing_allowed,
429                                    signing_mandatory);
430
431         /* a SPNEGO session setup has 12 command words, whereas a normal
432            NT1 session setup has 13. See the cifs spec. */
433         if (req->wct == 12 &&
434             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
435
436                 if (!sconn->smb1.negprot.spnego) {
437                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
438                                  "at SPNEGO session setup when it was not "
439                                  "negotiated.\n"));
440                         reply_nterror(req, nt_status_squash(
441                                               NT_STATUS_LOGON_FAILURE));
442                         END_PROFILE(SMBsesssetupX);
443                         return;
444                 }
445
446                 if (SVAL(req->vwv+4, 0) == 0) {
447                         setup_new_vc_session(req->sconn);
448                 }
449
450                 reply_sesssetup_and_X_spnego(req);
451                 END_PROFILE(SMBsesssetupX);
452                 return;
453         }
454
455         smb_bufsize = SVAL(req->vwv+2, 0);
456
457         if (get_Protocol() < PROTOCOL_NT1) {
458                 uint16 passlen1 = SVAL(req->vwv+7, 0);
459
460                 /* Never do NT status codes with protocols before NT1 as we
461                  * don't get client caps. */
462                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
463
464                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
465                         reply_nterror(req, nt_status_squash(
466                                               NT_STATUS_INVALID_PARAMETER));
467                         END_PROFILE(SMBsesssetupX);
468                         return;
469                 }
470
471                 if (doencrypt) {
472                         lm_resp = data_blob(req->buf, passlen1);
473                 } else {
474                         plaintext_password = data_blob(req->buf, passlen1+1);
475                         /* Ensure null termination */
476                         plaintext_password.data[passlen1] = 0;
477                 }
478
479                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
480                                        req->buf + passlen1, STR_TERMINATE);
481                 user = tmp ? tmp : "";
482
483                 domain = "";
484
485         } else {
486                 uint16 passlen1 = SVAL(req->vwv+7, 0);
487                 uint16 passlen2 = SVAL(req->vwv+8, 0);
488                 enum remote_arch_types ra_type = get_remote_arch();
489                 const uint8_t *p = req->buf;
490                 const uint8_t *save_p = req->buf;
491                 uint16 byte_count;
492
493
494                 if(global_client_caps == 0) {
495                         global_client_caps = IVAL(req->vwv+11, 0);
496
497                         if (!(global_client_caps & CAP_STATUS32)) {
498                                 remove_from_common_flags2(
499                                                 FLAGS2_32_BIT_ERROR_CODES);
500                         }
501
502                         /* client_caps is used as final determination if
503                          * client is NT or Win95. This is needed to return
504                          * the correct error codes in some circumstances.
505                         */
506
507                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
508                                         ra_type == RA_WIN95) {
509                                 if(!(global_client_caps & (CAP_NT_SMBS|
510                                                         CAP_STATUS32))) {
511                                         set_remote_arch( RA_WIN95);
512                                 }
513                         }
514                 }
515
516                 if (!doencrypt) {
517                         /* both Win95 and WinNT stuff up the password
518                          * lengths for non-encrypting systems. Uggh.
519
520                            if passlen1==24 its a win95 system, and its setting
521                            the password length incorrectly. Luckily it still
522                            works with the default code because Win95 will null
523                            terminate the password anyway
524
525                            if passlen1>0 and passlen2>0 then maybe its a NT box
526                            and its setting passlen2 to some random value which
527                            really stuffs things up. we need to fix that one.  */
528
529                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
530                                         passlen2 != 1) {
531                                 passlen2 = 0;
532                         }
533                 }
534
535                 /* check for nasty tricks */
536                 if (passlen1 > MAX_PASS_LEN
537                     || passlen1 > smbreq_bufrem(req, p)) {
538                         reply_nterror(req, nt_status_squash(
539                                               NT_STATUS_INVALID_PARAMETER));
540                         END_PROFILE(SMBsesssetupX);
541                         return;
542                 }
543
544                 if (passlen2 > MAX_PASS_LEN
545                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
546                         reply_nterror(req, nt_status_squash(
547                                               NT_STATUS_INVALID_PARAMETER));
548                         END_PROFILE(SMBsesssetupX);
549                         return;
550                 }
551
552                 /* Save the lanman2 password and the NT md4 password. */
553
554                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
555                         doencrypt = False;
556                 }
557
558                 if (doencrypt) {
559                         lm_resp = data_blob(p, passlen1);
560                         nt_resp = data_blob(p+passlen1, passlen2);
561                 } else if (lp_security() != SEC_SHARE) {
562                         /*
563                          * In share level we should ignore any passwords, so
564                          * only read them if we're not.
565                          */
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 (lp_security() == SEC_SHARE) {
674                 char *sub_user_mapped = NULL;
675                 /* In share level we should ignore any passwords */
676
677                 data_blob_free(&lm_resp);
678                 data_blob_free(&nt_resp);
679                 data_blob_clear_free(&plaintext_password);
680
681                 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
682                 if (!sub_user_mapped) {
683                         reply_nterror(req, NT_STATUS_NO_MEMORY);
684                         END_PROFILE(SMBsesssetupX);
685                         return;
686                 }
687                 fstrcpy(sub_user, sub_user_mapped);
688                 add_session_user(sconn, sub_user);
689                 add_session_workgroup(sconn, domain);
690                 /* Then force it to null for the benfit of the code below */
691                 user = "";
692         }
693
694         if (!*user) {
695
696                 nt_status = check_guest_password(sconn->remote_address, &server_info);
697
698         } else if (doencrypt) {
699                 struct auth_context *negprot_auth_context = NULL;
700                 negprot_auth_context = sconn->smb1.negprot.auth_context;
701                 if (!negprot_auth_context) {
702                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
703                                 "session setup without negprot denied!\n"));
704                         reply_nterror(req, nt_status_squash(
705                                               NT_STATUS_LOGON_FAILURE));
706                         END_PROFILE(SMBsesssetupX);
707                         return;
708                 }
709                 nt_status = make_user_info_for_reply_enc(&user_info, user,
710                                                 domain,
711                                                 sconn->remote_address,
712                                                 lm_resp, nt_resp);
713                 if (NT_STATUS_IS_OK(nt_status)) {
714                         nt_status = negprot_auth_context->check_ntlm_password(
715                                         negprot_auth_context,
716                                         user_info,
717                                         &server_info);
718                 }
719         } else {
720                 struct auth_context *plaintext_auth_context = NULL;
721
722                 nt_status = make_auth_context_subsystem(
723                         talloc_tos(), &plaintext_auth_context);
724
725                 if (NT_STATUS_IS_OK(nt_status)) {
726                         uint8_t chal[8];
727
728                         plaintext_auth_context->get_ntlm_challenge(
729                                         plaintext_auth_context, chal);
730
731                         if (!make_user_info_for_reply(&user_info,
732                                                       user, domain,
733                                                       sconn->remote_address,
734                                                       chal,
735                                                       plaintext_password)) {
736                                 nt_status = NT_STATUS_NO_MEMORY;
737                         }
738
739                         if (NT_STATUS_IS_OK(nt_status)) {
740                                 nt_status = plaintext_auth_context->check_ntlm_password(
741                                                 plaintext_auth_context,
742                                                 user_info,
743                                                 &server_info);
744
745                                 TALLOC_FREE(plaintext_auth_context);
746                         }
747                 }
748         }
749
750         free_user_info(&user_info);
751
752         if (!NT_STATUS_IS_OK(nt_status)) {
753                 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
754                                                         user, domain);
755         }
756
757         if (!NT_STATUS_IS_OK(nt_status)) {
758                 data_blob_free(&nt_resp);
759                 data_blob_free(&lm_resp);
760                 data_blob_clear_free(&plaintext_password);
761                 reply_nterror(req, nt_status_squash(nt_status));
762                 END_PROFILE(SMBsesssetupX);
763                 return;
764         }
765
766         nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
767         TALLOC_FREE(server_info);
768
769         if (!NT_STATUS_IS_OK(nt_status)) {
770                 DEBUG(10, ("create_local_token failed: %s\n",
771                            nt_errstr(nt_status)));
772                 data_blob_free(&nt_resp);
773                 data_blob_free(&lm_resp);
774                 data_blob_clear_free(&plaintext_password);
775                 reply_nterror(req, nt_status_squash(nt_status));
776                 END_PROFILE(SMBsesssetupX);
777                 return;
778         }
779
780         data_blob_clear_free(&plaintext_password);
781
782         /* it's ok - setup a reply */
783         reply_outbuf(req, 3, 0);
784         if (get_Protocol() >= PROTOCOL_NT1) {
785                 push_signature(&req->outbuf);
786                 /* perhaps grab OS version here?? */
787         }
788
789         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
790                 SSVAL(req->outbuf,smb_vwv2,1);
791         }
792
793         /* register the name and uid as being validated, so further connections
794            to a uid can get through without a password, on the same VC */
795
796         if (lp_security() == SEC_SHARE) {
797                 sess_vuid = UID_FIELD_INVALID;
798                 TALLOC_FREE(session_info);
799         } else {
800                 /* Ignore the initial vuid. */
801                 sess_vuid = register_initial_vuid(sconn);
802                 if (sess_vuid == UID_FIELD_INVALID) {
803                         data_blob_free(&nt_resp);
804                         data_blob_free(&lm_resp);
805                         reply_nterror(req, nt_status_squash(
806                                               NT_STATUS_LOGON_FAILURE));
807                         END_PROFILE(SMBsesssetupX);
808                         return;
809                 }
810                 /* register_existing_vuid keeps the session_info */
811                 sess_vuid = register_existing_vuid(sconn, sess_vuid,
812                                         session_info,
813                                         nt_resp.data ? nt_resp : lm_resp);
814                 if (sess_vuid == UID_FIELD_INVALID) {
815                         data_blob_free(&nt_resp);
816                         data_blob_free(&lm_resp);
817                         reply_nterror(req, nt_status_squash(
818                                               NT_STATUS_LOGON_FAILURE));
819                         END_PROFILE(SMBsesssetupX);
820                         return;
821                 }
822
823                 /* current_user_info is changed on new vuid */
824                 reload_services(sconn, conn_snum_used, true);
825         }
826
827         data_blob_free(&nt_resp);
828         data_blob_free(&lm_resp);
829
830         SSVAL(req->outbuf,smb_uid,sess_vuid);
831         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
832         req->vuid = sess_vuid;
833
834         if (!sconn->smb1.sessions.done_sesssetup) {
835                 sconn->smb1.sessions.max_send =
836                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
837         }
838         sconn->smb1.sessions.done_sesssetup = true;
839
840         END_PROFILE(SMBsesssetupX);
841         chain_reply(req);
842         return;
843 }