987b626d6bcc2d7e96cfeab08f5a6b436f7b27c4
[vlendec/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                                      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                         DEBUG(1,("Failed to generate session_info "
261                                  "(user and group token) for session setup: %s\n",
262                                  nt_errstr(status)));
263                         /* Kill the intermediate vuid */
264                         data_blob_free(&out_blob);
265                         invalidate_vuid(sconn, vuid);
266                         reply_nterror(req, nt_status_squash(status));
267                         return;
268                 }
269
270                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
271                         action = 1;
272                 }
273
274                 /* register_existing_vuid keeps the server info */
275                 tmp_vuid = register_existing_vuid(sconn, vuid,
276                                                   session_info,
277                                                   data_blob_null);
278                 if (tmp_vuid != vuid) {
279                         data_blob_free(&out_blob);
280                         invalidate_vuid(sconn, vuid);
281                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
282                         return;
283                 }
284
285                 /* current_user_info is changed on new vuid */
286                 reload_services(sconn, conn_snum_used, true);
287         }
288
289         reply_outbuf(req, 4, 0);
290
291         SSVAL(req->outbuf, smb_uid, vuid);
292         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
293         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
294         SSVAL(req->outbuf, smb_vwv2, action);
295         SSVAL(req->outbuf, smb_vwv3, out_blob.length);
296
297         if (message_push_blob(&req->outbuf, out_blob) == -1) {
298                 data_blob_free(&out_blob);
299                 invalidate_vuid(sconn, vuid);
300                 reply_nterror(req, NT_STATUS_NO_MEMORY);
301                 return;
302         }
303         data_blob_free(&out_blob);
304
305         if (push_signature(&req->outbuf) == -1) {
306                 invalidate_vuid(sconn, vuid);
307                 reply_nterror(req, NT_STATUS_NO_MEMORY);
308                 return;
309         }
310 }
311
312 /****************************************************************************
313  On new VC == 0, shutdown *all* old connections and users.
314  It seems that only NT4.x does this. At W2K and above (XP etc.).
315  a new session setup with VC==0 is ignored.
316 ****************************************************************************/
317
318 struct shutdown_state {
319         const char *ip;
320         struct messaging_context *msg_ctx;
321 };
322
323 static int shutdown_other_smbds(const struct connections_key *key,
324                                 const struct connections_data *crec,
325                                 void *private_data)
326 {
327         struct shutdown_state *state = (struct shutdown_state *)private_data;
328
329         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
330                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
331
332         if (!process_exists(crec->pid)) {
333                 DEBUG(10, ("process does not exist\n"));
334                 return 0;
335         }
336
337         if (procid_is_me(&crec->pid)) {
338                 DEBUG(10, ("It's me\n"));
339                 return 0;
340         }
341
342         if (strcmp(state->ip, crec->addr) != 0) {
343                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
344                 return 0;
345         }
346
347         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
348                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
349                   state->ip));
350
351         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
352                        &data_blob_null);
353         return 0;
354 }
355
356 static void setup_new_vc_session(struct smbd_server_connection *sconn)
357 {
358         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
359                 "compatible we would close all old resources.\n"));
360 #if 0
361         conn_close_all();
362         invalidate_all_vuids();
363 #endif
364         if (lp_reset_on_zero_vc()) {
365                 char *addr;
366                 struct shutdown_state state;
367
368                 addr = tsocket_address_inet_addr_string(
369                         sconn->remote_address, talloc_tos());
370                 if (addr == NULL) {
371                         return;
372                 }
373                 state.ip = addr;
374                 state.msg_ctx = sconn->msg_ctx;
375                 connections_forall_read(shutdown_other_smbds, &state);
376                 TALLOC_FREE(addr);
377         }
378 }
379
380 /****************************************************************************
381  Reply to a session setup command.
382 ****************************************************************************/
383
384 void reply_sesssetup_and_X(struct smb_request *req)
385 {
386         int sess_vuid;
387         int smb_bufsize;
388         DATA_BLOB lm_resp;
389         DATA_BLOB nt_resp;
390         DATA_BLOB plaintext_password;
391         char *tmp;
392         const char *user;
393         fstring sub_user; /* Sanitised username for substituion */
394         const char *domain;
395         const char *native_os;
396         const char *native_lanman;
397         const char *primary_domain;
398         struct auth_usersupplied_info *user_info = NULL;
399         struct auth_serversupplied_info *server_info = NULL;
400         struct auth_session_info *session_info = NULL;
401         uint16 smb_flag2 = req->flags2;
402
403         NTSTATUS nt_status;
404         struct smbd_server_connection *sconn = req->sconn;
405
406         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
407         bool signing_allowed = false;
408         bool signing_mandatory = false;
409
410         START_PROFILE(SMBsesssetupX);
411
412         ZERO_STRUCT(lm_resp);
413         ZERO_STRUCT(nt_resp);
414         ZERO_STRUCT(plaintext_password);
415
416         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
417
418         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
419                 signing_allowed = true;
420         }
421         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
422                 signing_mandatory = true;
423         }
424
425         /*
426          * We can call srv_set_signing_negotiated() each time.
427          * It finds out when it needs to turn into a noop
428          * itself.
429          */
430         srv_set_signing_negotiated(req->sconn,
431                                    signing_allowed,
432                                    signing_mandatory);
433
434         /* a SPNEGO session setup has 12 command words, whereas a normal
435            NT1 session setup has 13. See the cifs spec. */
436         if (req->wct == 12 &&
437             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
438
439                 if (!sconn->smb1.negprot.spnego) {
440                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
441                                  "at SPNEGO session setup when it was not "
442                                  "negotiated.\n"));
443                         reply_nterror(req, nt_status_squash(
444                                               NT_STATUS_LOGON_FAILURE));
445                         END_PROFILE(SMBsesssetupX);
446                         return;
447                 }
448
449                 if (SVAL(req->vwv+4, 0) == 0) {
450                         setup_new_vc_session(req->sconn);
451                 }
452
453                 reply_sesssetup_and_X_spnego(req);
454                 END_PROFILE(SMBsesssetupX);
455                 return;
456         }
457
458         smb_bufsize = SVAL(req->vwv+2, 0);
459
460         if (get_Protocol() < PROTOCOL_NT1) {
461                 uint16 passlen1 = SVAL(req->vwv+7, 0);
462
463                 /* Never do NT status codes with protocols before NT1 as we
464                  * don't get client caps. */
465                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
466
467                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
468                         reply_nterror(req, nt_status_squash(
469                                               NT_STATUS_INVALID_PARAMETER));
470                         END_PROFILE(SMBsesssetupX);
471                         return;
472                 }
473
474                 if (doencrypt) {
475                         lm_resp = data_blob(req->buf, passlen1);
476                 } else {
477                         plaintext_password = data_blob(req->buf, passlen1+1);
478                         /* Ensure null termination */
479                         plaintext_password.data[passlen1] = 0;
480                 }
481
482                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
483                                        req->buf + passlen1, STR_TERMINATE);
484                 user = tmp ? tmp : "";
485
486                 domain = "";
487
488         } else {
489                 uint16 passlen1 = SVAL(req->vwv+7, 0);
490                 uint16 passlen2 = SVAL(req->vwv+8, 0);
491                 enum remote_arch_types ra_type = get_remote_arch();
492                 const uint8_t *p = req->buf;
493                 const uint8_t *save_p = req->buf;
494                 uint16 byte_count;
495
496
497                 if(global_client_caps == 0) {
498                         global_client_caps = IVAL(req->vwv+11, 0);
499
500                         if (!(global_client_caps & CAP_STATUS32)) {
501                                 remove_from_common_flags2(
502                                                 FLAGS2_32_BIT_ERROR_CODES);
503                         }
504
505                         /* client_caps is used as final determination if
506                          * client is NT or Win95. This is needed to return
507                          * the correct error codes in some circumstances.
508                         */
509
510                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
511                                         ra_type == RA_WIN95) {
512                                 if(!(global_client_caps & (CAP_NT_SMBS|
513                                                         CAP_STATUS32))) {
514                                         set_remote_arch( RA_WIN95);
515                                 }
516                         }
517                 }
518
519                 if (!doencrypt) {
520                         /* both Win95 and WinNT stuff up the password
521                          * lengths for non-encrypting systems. Uggh.
522
523                            if passlen1==24 its a win95 system, and its setting
524                            the password length incorrectly. Luckily it still
525                            works with the default code because Win95 will null
526                            terminate the password anyway
527
528                            if passlen1>0 and passlen2>0 then maybe its a NT box
529                            and its setting passlen2 to some random value which
530                            really stuffs things up. we need to fix that one.  */
531
532                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
533                                         passlen2 != 1) {
534                                 passlen2 = 0;
535                         }
536                 }
537
538                 /* check for nasty tricks */
539                 if (passlen1 > MAX_PASS_LEN
540                     || passlen1 > smbreq_bufrem(req, p)) {
541                         reply_nterror(req, nt_status_squash(
542                                               NT_STATUS_INVALID_PARAMETER));
543                         END_PROFILE(SMBsesssetupX);
544                         return;
545                 }
546
547                 if (passlen2 > MAX_PASS_LEN
548                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
549                         reply_nterror(req, nt_status_squash(
550                                               NT_STATUS_INVALID_PARAMETER));
551                         END_PROFILE(SMBsesssetupX);
552                         return;
553                 }
554
555                 /* Save the lanman2 password and the NT md4 password. */
556
557                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
558                         doencrypt = False;
559                 }
560
561                 if (doencrypt) {
562                         lm_resp = data_blob(p, passlen1);
563                         nt_resp = data_blob(p+passlen1, passlen2);
564                 } else if (lp_security() != SEC_SHARE) {
565                         /*
566                          * In share level we should ignore any passwords, so
567                          * only read them if we're not.
568                          */
569                         char *pass = NULL;
570                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
571
572                         if (unic && (passlen2 == 0) && passlen1) {
573                                 /* Only a ascii plaintext password was sent. */
574                                 (void)srvstr_pull_talloc(talloc_tos(),
575                                                         req->inbuf,
576                                                         req->flags2,
577                                                         &pass,
578                                                         req->buf,
579                                                         passlen1,
580                                                         STR_TERMINATE|STR_ASCII);
581                         } else {
582                                 (void)srvstr_pull_talloc(talloc_tos(),
583                                                         req->inbuf,
584                                                         req->flags2,
585                                                         &pass,
586                                                         req->buf,
587                                                         unic ? passlen2 : passlen1,
588                                                         STR_TERMINATE);
589                         }
590                         if (!pass) {
591                                 reply_nterror(req, nt_status_squash(
592                                               NT_STATUS_INVALID_PARAMETER));
593                                 END_PROFILE(SMBsesssetupX);
594                                 return;
595                         }
596                         plaintext_password = data_blob(pass, strlen(pass)+1);
597                 }
598
599                 p += passlen1 + passlen2;
600
601                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
602                                             STR_TERMINATE);
603                 user = tmp ? tmp : "";
604
605                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
606                                             STR_TERMINATE);
607                 domain = tmp ? tmp : "";
608
609                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
610                                             STR_TERMINATE);
611                 native_os = tmp ? tmp : "";
612
613                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
614                                             STR_TERMINATE);
615                 native_lanman = tmp ? tmp : "";
616
617                 /* not documented or decoded by Ethereal but there is one more
618                  * string in the extra bytes which is the same as the
619                  * PrimaryDomain when using extended security.  Windows NT 4
620                  * and 2003 use this string to store the native lanman string.
621                  * Windows 9x does not include a string here at all so we have
622                  * to check if we have any extra bytes left */
623
624                 byte_count = SVAL(req->vwv+13, 0);
625                 if ( PTR_DIFF(p, save_p) < byte_count) {
626                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
627                                                     STR_TERMINATE);
628                         primary_domain = tmp ? tmp : "";
629                 } else {
630                         primary_domain = talloc_strdup(talloc_tos(), "null");
631                 }
632
633                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
634                         "PrimaryDomain=[%s]\n",
635                         domain, native_os, native_lanman, primary_domain));
636
637                 if ( ra_type == RA_WIN2K ) {
638                         if ( strlen(native_lanman) == 0 )
639                                 ra_lanman_string( primary_domain );
640                         else
641                                 ra_lanman_string( native_lanman );
642                 }
643
644         }
645
646         if (SVAL(req->vwv+4, 0) == 0) {
647                 setup_new_vc_session(req->sconn);
648         }
649
650         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
651                                 domain, user, get_remote_machine_name()));
652
653         if (*user) {
654                 if (sconn->smb1.negprot.spnego) {
655
656                         /* This has to be here, because this is a perfectly
657                          * valid behaviour for guest logons :-( */
658
659                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
660                                 "at 'normal' session setup after "
661                                 "negotiating spnego.\n"));
662                         reply_nterror(req, nt_status_squash(
663                                               NT_STATUS_LOGON_FAILURE));
664                         END_PROFILE(SMBsesssetupX);
665                         return;
666                 }
667                 fstrcpy(sub_user, user);
668         } else {
669                 fstrcpy(sub_user, "");
670         }
671
672         sub_set_smb_name(sub_user);
673
674         reload_services(sconn, conn_snum_used, true);
675
676         if (lp_security() == SEC_SHARE) {
677                 char *sub_user_mapped = NULL;
678                 /* In share level we should ignore any passwords */
679
680                 data_blob_free(&lm_resp);
681                 data_blob_free(&nt_resp);
682                 data_blob_clear_free(&plaintext_password);
683
684                 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
685                 if (!sub_user_mapped) {
686                         reply_nterror(req, NT_STATUS_NO_MEMORY);
687                         END_PROFILE(SMBsesssetupX);
688                         return;
689                 }
690                 fstrcpy(sub_user, sub_user_mapped);
691                 add_session_user(sconn, sub_user);
692                 add_session_workgroup(sconn, domain);
693                 /* Then force it to null for the benfit of the code below */
694                 user = "";
695         }
696
697         if (!*user) {
698
699                 nt_status = check_guest_password(sconn->remote_address, &server_info);
700
701         } else if (doencrypt) {
702                 struct auth_context *negprot_auth_context = NULL;
703                 negprot_auth_context = sconn->smb1.negprot.auth_context;
704                 if (!negprot_auth_context) {
705                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
706                                 "session setup without negprot denied!\n"));
707                         reply_nterror(req, nt_status_squash(
708                                               NT_STATUS_LOGON_FAILURE));
709                         END_PROFILE(SMBsesssetupX);
710                         return;
711                 }
712                 nt_status = make_user_info_for_reply_enc(&user_info, user,
713                                                 domain,
714                                                 sconn->remote_address,
715                                                 lm_resp, nt_resp);
716                 if (NT_STATUS_IS_OK(nt_status)) {
717                         nt_status = negprot_auth_context->check_ntlm_password(
718                                         negprot_auth_context,
719                                         user_info,
720                                         &server_info);
721                 }
722         } else {
723                 struct auth_context *plaintext_auth_context = NULL;
724
725                 nt_status = make_auth_context_subsystem(
726                         talloc_tos(), &plaintext_auth_context);
727
728                 if (NT_STATUS_IS_OK(nt_status)) {
729                         uint8_t chal[8];
730
731                         plaintext_auth_context->get_ntlm_challenge(
732                                         plaintext_auth_context, chal);
733
734                         if (!make_user_info_for_reply(&user_info,
735                                                       user, domain,
736                                                       sconn->remote_address,
737                                                       chal,
738                                                       plaintext_password)) {
739                                 nt_status = NT_STATUS_NO_MEMORY;
740                         }
741
742                         if (NT_STATUS_IS_OK(nt_status)) {
743                                 nt_status = plaintext_auth_context->check_ntlm_password(
744                                                 plaintext_auth_context,
745                                                 user_info,
746                                                 &server_info);
747
748                                 TALLOC_FREE(plaintext_auth_context);
749                         }
750                 }
751         }
752
753         free_user_info(&user_info);
754
755         if (!NT_STATUS_IS_OK(nt_status)) {
756                 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
757                                                         user, domain);
758         }
759
760         if (!NT_STATUS_IS_OK(nt_status)) {
761                 data_blob_free(&nt_resp);
762                 data_blob_free(&lm_resp);
763                 data_blob_clear_free(&plaintext_password);
764                 reply_nterror(req, nt_status_squash(nt_status));
765                 END_PROFILE(SMBsesssetupX);
766                 return;
767         }
768
769         nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
770         TALLOC_FREE(server_info);
771
772         if (!NT_STATUS_IS_OK(nt_status)) {
773                 DEBUG(10, ("create_local_token failed: %s\n",
774                            nt_errstr(nt_status)));
775                 data_blob_free(&nt_resp);
776                 data_blob_free(&lm_resp);
777                 data_blob_clear_free(&plaintext_password);
778                 reply_nterror(req, nt_status_squash(nt_status));
779                 END_PROFILE(SMBsesssetupX);
780                 return;
781         }
782
783         data_blob_clear_free(&plaintext_password);
784
785         /* it's ok - setup a reply */
786         reply_outbuf(req, 3, 0);
787         if (get_Protocol() >= PROTOCOL_NT1) {
788                 push_signature(&req->outbuf);
789                 /* perhaps grab OS version here?? */
790         }
791
792         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
793                 SSVAL(req->outbuf,smb_vwv2,1);
794         }
795
796         /* register the name and uid as being validated, so further connections
797            to a uid can get through without a password, on the same VC */
798
799         if (lp_security() == SEC_SHARE) {
800                 sess_vuid = UID_FIELD_INVALID;
801                 TALLOC_FREE(session_info);
802         } else {
803                 /* Ignore the initial vuid. */
804                 sess_vuid = register_initial_vuid(sconn);
805                 if (sess_vuid == UID_FIELD_INVALID) {
806                         data_blob_free(&nt_resp);
807                         data_blob_free(&lm_resp);
808                         reply_nterror(req, nt_status_squash(
809                                               NT_STATUS_LOGON_FAILURE));
810                         END_PROFILE(SMBsesssetupX);
811                         return;
812                 }
813                 /* register_existing_vuid keeps the session_info */
814                 sess_vuid = register_existing_vuid(sconn, sess_vuid,
815                                         session_info,
816                                         nt_resp.data ? nt_resp : lm_resp);
817                 if (sess_vuid == UID_FIELD_INVALID) {
818                         data_blob_free(&nt_resp);
819                         data_blob_free(&lm_resp);
820                         reply_nterror(req, nt_status_squash(
821                                               NT_STATUS_LOGON_FAILURE));
822                         END_PROFILE(SMBsesssetupX);
823                         return;
824                 }
825
826                 /* current_user_info is changed on new vuid */
827                 reload_services(sconn, conn_snum_used, true);
828         }
829
830         data_blob_free(&nt_resp);
831         data_blob_free(&lm_resp);
832
833         SSVAL(req->outbuf,smb_uid,sess_vuid);
834         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
835         req->vuid = sess_vuid;
836
837         if (!sconn->smb1.sessions.done_sesssetup) {
838                 sconn->smb1.sessions.max_send =
839                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
840         }
841         sconn->smb1.sessions.done_sesssetup = true;
842
843         END_PROFILE(SMBsesssetupX);
844         chain_reply(req);
845         return;
846 }