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