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