2 Unix SMB/CIFS implementation.
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
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.
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.
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/>.
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"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
40 /****************************************************************************
41 Add the standard 'Samba' signature to the end of the session setup.
42 ****************************************************************************/
44 static int push_signature(uint8 **outbuf)
51 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
53 if (tmp == -1) return -1;
56 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
57 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
61 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
64 if (tmp == -1) return -1;
67 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
69 if (tmp == -1) return -1;
75 /****************************************************************************
76 Send a security blob via a session setup reply.
77 ****************************************************************************/
79 static void reply_sesssetup_blob(struct smb_request *req,
83 if (!NT_STATUS_IS_OK(nt_status) &&
84 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
85 reply_nterror(req, nt_status_squash(nt_status));
89 nt_status = nt_status_squash(nt_status);
90 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
91 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
92 SSVAL(req->outbuf, smb_vwv3, blob.length);
94 if ((message_push_blob(&req->outbuf, blob) == -1)
95 || (push_signature(&req->outbuf) == -1)) {
96 reply_nterror(req, NT_STATUS_NO_MEMORY);
100 /****************************************************************************
101 Do a 'guest' logon, getting back the
102 ****************************************************************************/
104 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
105 struct auth_serversupplied_info **server_info)
107 struct auth_context *auth_context;
108 struct auth_usersupplied_info *user_info = NULL;
111 static unsigned char chal[8] = { 0, };
113 DEBUG(3,("Got anonymous request\n"));
115 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
116 if (!NT_STATUS_IS_OK(nt_status)) {
120 if (!make_user_info_guest(remote_address, &user_info)) {
121 TALLOC_FREE(auth_context);
122 return NT_STATUS_NO_MEMORY;
125 nt_status = auth_context->check_ntlm_password(auth_context,
128 TALLOC_FREE(auth_context);
129 free_user_info(&user_info);
133 static void reply_spnego_generic(struct smb_request *req,
135 struct gensec_security **gensec_security,
136 DATA_BLOB *blob, NTSTATUS nt_status)
138 bool do_invalidate = true;
139 struct auth_session_info *session_info = NULL;
140 struct smbd_server_connection *sconn = req->sconn;
142 if (NT_STATUS_IS_OK(nt_status)) {
143 nt_status = gensec_session_info(*gensec_security,
148 reply_outbuf(req, 4, 0);
150 SSVAL(req->outbuf, smb_uid, vuid);
152 if (NT_STATUS_IS_OK(nt_status)) {
153 DATA_BLOB nullblob = data_blob_null;
155 if (!is_partial_auth_vuid(sconn, vuid)) {
156 nt_status = NT_STATUS_LOGON_FAILURE;
160 /* register_existing_vuid keeps the server info */
161 if (register_existing_vuid(sconn, vuid,
162 session_info, nullblob) !=
164 /* The problem is, *gensec_security points
165 * into the vuser this will have
166 * talloc_free()'ed in
167 * register_existing_vuid() */
168 do_invalidate = false;
169 nt_status = NT_STATUS_LOGON_FAILURE;
173 /* current_user_info is changed on new vuid */
174 reload_services(sconn, conn_snum_used, true);
176 SSVAL(req->outbuf, smb_vwv3, 0);
178 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
179 SSVAL(req->outbuf,smb_vwv2,1);
185 reply_sesssetup_blob(req, *blob, nt_status);
187 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
188 and the other end, that we are not finished yet. */
190 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
191 /* NB. This is *NOT* an error case. JRA */
193 TALLOC_FREE(*gensec_security);
194 if (!NT_STATUS_IS_OK(nt_status)) {
195 /* Kill the intermediate vuid */
196 invalidate_vuid(sconn, vuid);
202 /****************************************************************************
203 Reply to a session setup command.
204 conn POINTER CAN BE NULL HERE !
205 ****************************************************************************/
207 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
213 const char *native_os;
214 const char *native_lanman;
215 const char *primary_domain;
217 uint16 data_blob_len = SVAL(req->vwv+7, 0);
218 enum remote_arch_types ra_type = get_remote_arch();
219 int vuid = req->vuid;
220 user_struct *vuser = NULL;
221 NTSTATUS status = NT_STATUS_OK;
222 struct smbd_server_connection *sconn = req->sconn;
225 DEBUG(3,("Doing spnego session setup\n"));
227 if (global_client_caps == 0) {
228 global_client_caps = IVAL(req->vwv+10, 0);
230 if (!(global_client_caps & CAP_STATUS32)) {
231 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
238 if (data_blob_len == 0) {
239 /* an invalid request */
240 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
244 bufrem = smbreq_bufrem(req, p);
245 /* pull the spnego blob */
246 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
249 file_save("negotiate.dat", blob1.data, blob1.length);
252 p2 = (const char *)req->buf + blob1.length;
254 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
256 native_os = tmp ? tmp : "";
258 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
260 native_lanman = tmp ? tmp : "";
262 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
264 primary_domain = tmp ? tmp : "";
266 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
267 native_os, native_lanman, primary_domain));
269 if ( ra_type == RA_WIN2K ) {
270 /* Vista sets neither the OS or lanman strings */
272 if ( !strlen(native_os) && !strlen(native_lanman) )
273 set_remote_arch(RA_VISTA);
275 /* Windows 2003 doesn't set the native lanman string,
276 but does set primary domain which is a bug I think */
278 if ( !strlen(native_lanman) ) {
279 ra_lanman_string( primary_domain );
281 ra_lanman_string( native_lanman );
283 } else if ( ra_type == RA_VISTA ) {
284 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
285 set_remote_arch(RA_OSX);
289 /* Do we have a valid vuid now ? */
290 if (!is_partial_auth_vuid(sconn, vuid)) {
291 /* No, start a new authentication setup. */
292 vuid = register_initial_vuid(sconn);
293 if (vuid == UID_FIELD_INVALID) {
294 data_blob_free(&blob1);
295 reply_nterror(req, nt_status_squash(
296 NT_STATUS_INVALID_PARAMETER));
301 vuser = get_partial_auth_user_struct(sconn, vuid);
302 /* This MUST be valid. */
304 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
307 if (!vuser->gensec_security) {
308 status = auth_generic_prepare(vuser, sconn->remote_address,
309 &vuser->gensec_security);
310 if (!NT_STATUS_IS_OK(status)) {
311 /* Kill the intermediate vuid */
312 invalidate_vuid(sconn, vuid);
313 data_blob_free(&blob1);
314 reply_nterror(req, nt_status_squash(status));
318 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
319 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
321 if (sconn->use_gensec_hook) {
322 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
324 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_NTLMSSP);
326 if (!NT_STATUS_IS_OK(status)) {
327 /* Kill the intermediate vuid */
328 invalidate_vuid(sconn, vuid);
329 data_blob_free(&blob1);
330 reply_nterror(req, nt_status_squash(status));
335 status = gensec_update(vuser->gensec_security,
339 data_blob_free(&blob1);
341 reply_spnego_generic(req, vuid,
342 &vuser->gensec_security,
344 data_blob_free(&chal);
348 /****************************************************************************
349 On new VC == 0, shutdown *all* old connections and users.
350 It seems that only NT4.x does this. At W2K and above (XP etc.).
351 a new session setup with VC==0 is ignored.
352 ****************************************************************************/
354 struct shutdown_state {
356 struct messaging_context *msg_ctx;
359 static int shutdown_other_smbds(const struct connections_key *key,
360 const struct connections_data *crec,
363 struct shutdown_state *state = (struct shutdown_state *)private_data;
365 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
366 server_id_str(talloc_tos(), &crec->pid), crec->addr));
368 if (!process_exists(crec->pid)) {
369 DEBUG(10, ("process does not exist\n"));
373 if (procid_is_me(&crec->pid)) {
374 DEBUG(10, ("It's me\n"));
378 if (strcmp(state->ip, crec->addr) != 0) {
379 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
383 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
384 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
387 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
392 static void setup_new_vc_session(struct smbd_server_connection *sconn)
394 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
395 "compatible we would close all old resources.\n"));
398 invalidate_all_vuids();
400 if (lp_reset_on_zero_vc()) {
402 struct shutdown_state state;
404 addr = tsocket_address_inet_addr_string(
405 sconn->remote_address, talloc_tos());
410 state.msg_ctx = sconn->msg_ctx;
411 connections_forall_read(shutdown_other_smbds, &state);
416 /****************************************************************************
417 Reply to a session setup command.
418 ****************************************************************************/
420 void reply_sesssetup_and_X(struct smb_request *req)
426 DATA_BLOB plaintext_password;
429 fstring sub_user; /* Sanitised username for substituion */
431 const char *native_os;
432 const char *native_lanman;
433 const char *primary_domain;
434 struct auth_usersupplied_info *user_info = NULL;
435 struct auth_serversupplied_info *server_info = NULL;
436 struct auth_session_info *session_info = NULL;
437 uint16 smb_flag2 = req->flags2;
440 struct smbd_server_connection *sconn = req->sconn;
442 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
443 bool signing_allowed = false;
444 bool signing_mandatory = false;
446 START_PROFILE(SMBsesssetupX);
448 ZERO_STRUCT(lm_resp);
449 ZERO_STRUCT(nt_resp);
450 ZERO_STRUCT(plaintext_password);
452 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
454 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
455 signing_allowed = true;
457 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
458 signing_mandatory = true;
462 * We can call srv_set_signing_negotiated() each time.
463 * It finds out when it needs to turn into a noop
466 srv_set_signing_negotiated(req->sconn,
470 /* a SPNEGO session setup has 12 command words, whereas a normal
471 NT1 session setup has 13. See the cifs spec. */
472 if (req->wct == 12 &&
473 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
475 if (!sconn->smb1.negprot.spnego) {
476 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
477 "at SPNEGO session setup when it was not "
479 reply_nterror(req, nt_status_squash(
480 NT_STATUS_LOGON_FAILURE));
481 END_PROFILE(SMBsesssetupX);
485 if (SVAL(req->vwv+4, 0) == 0) {
486 setup_new_vc_session(req->sconn);
489 reply_sesssetup_and_X_spnego(req);
490 END_PROFILE(SMBsesssetupX);
494 smb_bufsize = SVAL(req->vwv+2, 0);
496 if (get_Protocol() < PROTOCOL_NT1) {
497 uint16 passlen1 = SVAL(req->vwv+7, 0);
499 /* Never do NT status codes with protocols before NT1 as we
500 * don't get client caps. */
501 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
503 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
504 reply_nterror(req, nt_status_squash(
505 NT_STATUS_INVALID_PARAMETER));
506 END_PROFILE(SMBsesssetupX);
511 lm_resp = data_blob(req->buf, passlen1);
513 plaintext_password = data_blob(req->buf, passlen1+1);
514 /* Ensure null termination */
515 plaintext_password.data[passlen1] = 0;
518 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
519 req->buf + passlen1, STR_TERMINATE);
520 user = tmp ? tmp : "";
525 uint16 passlen1 = SVAL(req->vwv+7, 0);
526 uint16 passlen2 = SVAL(req->vwv+8, 0);
527 enum remote_arch_types ra_type = get_remote_arch();
528 const uint8_t *p = req->buf;
529 const uint8_t *save_p = req->buf;
533 if(global_client_caps == 0) {
534 global_client_caps = IVAL(req->vwv+11, 0);
536 if (!(global_client_caps & CAP_STATUS32)) {
537 remove_from_common_flags2(
538 FLAGS2_32_BIT_ERROR_CODES);
541 /* client_caps is used as final determination if
542 * client is NT or Win95. This is needed to return
543 * the correct error codes in some circumstances.
546 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
547 ra_type == RA_WIN95) {
548 if(!(global_client_caps & (CAP_NT_SMBS|
550 set_remote_arch( RA_WIN95);
556 /* both Win95 and WinNT stuff up the password
557 * lengths for non-encrypting systems. Uggh.
559 if passlen1==24 its a win95 system, and its setting
560 the password length incorrectly. Luckily it still
561 works with the default code because Win95 will null
562 terminate the password anyway
564 if passlen1>0 and passlen2>0 then maybe its a NT box
565 and its setting passlen2 to some random value which
566 really stuffs things up. we need to fix that one. */
568 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
574 /* check for nasty tricks */
575 if (passlen1 > MAX_PASS_LEN
576 || passlen1 > smbreq_bufrem(req, p)) {
577 reply_nterror(req, nt_status_squash(
578 NT_STATUS_INVALID_PARAMETER));
579 END_PROFILE(SMBsesssetupX);
583 if (passlen2 > MAX_PASS_LEN
584 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
585 reply_nterror(req, nt_status_squash(
586 NT_STATUS_INVALID_PARAMETER));
587 END_PROFILE(SMBsesssetupX);
591 /* Save the lanman2 password and the NT md4 password. */
593 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
598 lm_resp = data_blob(p, passlen1);
599 nt_resp = data_blob(p+passlen1, passlen2);
600 } else if (lp_security() != SEC_SHARE) {
602 * In share level we should ignore any passwords, so
603 * only read them if we're not.
606 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
608 if (unic && (passlen2 == 0) && passlen1) {
609 /* Only a ascii plaintext password was sent. */
610 (void)srvstr_pull_talloc(talloc_tos(),
616 STR_TERMINATE|STR_ASCII);
618 (void)srvstr_pull_talloc(talloc_tos(),
623 unic ? passlen2 : passlen1,
627 reply_nterror(req, nt_status_squash(
628 NT_STATUS_INVALID_PARAMETER));
629 END_PROFILE(SMBsesssetupX);
632 plaintext_password = data_blob(pass, strlen(pass)+1);
635 p += passlen1 + passlen2;
637 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
639 user = tmp ? tmp : "";
641 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
643 domain = tmp ? tmp : "";
645 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
647 native_os = tmp ? tmp : "";
649 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
651 native_lanman = tmp ? tmp : "";
653 /* not documented or decoded by Ethereal but there is one more
654 * string in the extra bytes which is the same as the
655 * PrimaryDomain when using extended security. Windows NT 4
656 * and 2003 use this string to store the native lanman string.
657 * Windows 9x does not include a string here at all so we have
658 * to check if we have any extra bytes left */
660 byte_count = SVAL(req->vwv+13, 0);
661 if ( PTR_DIFF(p, save_p) < byte_count) {
662 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
664 primary_domain = tmp ? tmp : "";
666 primary_domain = talloc_strdup(talloc_tos(), "null");
669 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
670 "PrimaryDomain=[%s]\n",
671 domain, native_os, native_lanman, primary_domain));
673 if ( ra_type == RA_WIN2K ) {
674 if ( strlen(native_lanman) == 0 )
675 ra_lanman_string( primary_domain );
677 ra_lanman_string( native_lanman );
682 if (SVAL(req->vwv+4, 0) == 0) {
683 setup_new_vc_session(req->sconn);
686 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
687 domain, user, get_remote_machine_name()));
690 if (sconn->smb1.negprot.spnego) {
692 /* This has to be here, because this is a perfectly
693 * valid behaviour for guest logons :-( */
695 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
696 "at 'normal' session setup after "
697 "negotiating spnego.\n"));
698 reply_nterror(req, nt_status_squash(
699 NT_STATUS_LOGON_FAILURE));
700 END_PROFILE(SMBsesssetupX);
703 fstrcpy(sub_user, user);
705 fstrcpy(sub_user, "");
708 sub_set_smb_name(sub_user);
710 reload_services(sconn, conn_snum_used, true);
712 if (lp_security() == SEC_SHARE) {
713 char *sub_user_mapped = NULL;
714 /* In share level we should ignore any passwords */
716 data_blob_free(&lm_resp);
717 data_blob_free(&nt_resp);
718 data_blob_clear_free(&plaintext_password);
720 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
721 if (!sub_user_mapped) {
722 reply_nterror(req, NT_STATUS_NO_MEMORY);
723 END_PROFILE(SMBsesssetupX);
726 fstrcpy(sub_user, sub_user_mapped);
727 add_session_user(sconn, sub_user);
728 add_session_workgroup(sconn, domain);
729 /* Then force it to null for the benfit of the code below */
735 nt_status = check_guest_password(sconn->remote_address, &server_info);
737 } else if (doencrypt) {
738 struct auth_context *negprot_auth_context = NULL;
739 negprot_auth_context = sconn->smb1.negprot.auth_context;
740 if (!negprot_auth_context) {
741 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
742 "session setup without negprot denied!\n"));
743 reply_nterror(req, nt_status_squash(
744 NT_STATUS_LOGON_FAILURE));
745 END_PROFILE(SMBsesssetupX);
748 nt_status = make_user_info_for_reply_enc(&user_info, user,
750 sconn->remote_address,
752 if (NT_STATUS_IS_OK(nt_status)) {
753 nt_status = negprot_auth_context->check_ntlm_password(
754 negprot_auth_context,
759 struct auth_context *plaintext_auth_context = NULL;
761 nt_status = make_auth_context_subsystem(
762 talloc_tos(), &plaintext_auth_context);
764 if (NT_STATUS_IS_OK(nt_status)) {
767 plaintext_auth_context->get_ntlm_challenge(
768 plaintext_auth_context, chal);
770 if (!make_user_info_for_reply(&user_info,
772 sconn->remote_address,
774 plaintext_password)) {
775 nt_status = NT_STATUS_NO_MEMORY;
778 if (NT_STATUS_IS_OK(nt_status)) {
779 nt_status = plaintext_auth_context->check_ntlm_password(
780 plaintext_auth_context,
784 TALLOC_FREE(plaintext_auth_context);
789 free_user_info(&user_info);
791 if (!NT_STATUS_IS_OK(nt_status)) {
792 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
796 if (!NT_STATUS_IS_OK(nt_status)) {
797 data_blob_free(&nt_resp);
798 data_blob_free(&lm_resp);
799 data_blob_clear_free(&plaintext_password);
800 reply_nterror(req, nt_status_squash(nt_status));
801 END_PROFILE(SMBsesssetupX);
805 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
806 TALLOC_FREE(server_info);
808 if (!NT_STATUS_IS_OK(nt_status)) {
809 DEBUG(10, ("create_local_token failed: %s\n",
810 nt_errstr(nt_status)));
811 data_blob_free(&nt_resp);
812 data_blob_free(&lm_resp);
813 data_blob_clear_free(&plaintext_password);
814 reply_nterror(req, nt_status_squash(nt_status));
815 END_PROFILE(SMBsesssetupX);
819 data_blob_clear_free(&plaintext_password);
821 /* it's ok - setup a reply */
822 reply_outbuf(req, 3, 0);
823 if (get_Protocol() >= PROTOCOL_NT1) {
824 push_signature(&req->outbuf);
825 /* perhaps grab OS version here?? */
828 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
829 SSVAL(req->outbuf,smb_vwv2,1);
832 /* register the name and uid as being validated, so further connections
833 to a uid can get through without a password, on the same VC */
835 if (lp_security() == SEC_SHARE) {
836 sess_vuid = UID_FIELD_INVALID;
837 TALLOC_FREE(session_info);
839 /* Ignore the initial vuid. */
840 sess_vuid = register_initial_vuid(sconn);
841 if (sess_vuid == UID_FIELD_INVALID) {
842 data_blob_free(&nt_resp);
843 data_blob_free(&lm_resp);
844 reply_nterror(req, nt_status_squash(
845 NT_STATUS_LOGON_FAILURE));
846 END_PROFILE(SMBsesssetupX);
849 /* register_existing_vuid keeps the session_info */
850 sess_vuid = register_existing_vuid(sconn, sess_vuid,
852 nt_resp.data ? nt_resp : lm_resp);
853 if (sess_vuid == UID_FIELD_INVALID) {
854 data_blob_free(&nt_resp);
855 data_blob_free(&lm_resp);
856 reply_nterror(req, nt_status_squash(
857 NT_STATUS_LOGON_FAILURE));
858 END_PROFILE(SMBsesssetupX);
862 /* current_user_info is changed on new vuid */
863 reload_services(sconn, conn_snum_used, true);
866 data_blob_free(&nt_resp);
867 data_blob_free(&lm_resp);
869 SSVAL(req->outbuf,smb_uid,sess_vuid);
870 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
871 req->vuid = sess_vuid;
873 if (!sconn->smb1.sessions.done_sesssetup) {
874 sconn->smb1.sessions.max_send =
875 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
877 sconn->smb1.sessions.done_sesssetup = true;
879 END_PROFILE(SMBsesssetupX);