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