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 in_blob
= data_blob_const(p
, MIN(bufrem
, data_blob_len
));
249 file_save("negotiate.dat", in_blob
.data
, in_blob
.length
);
252 p2
= (const char *)req
->buf
+ in_blob
.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 reply_nterror(req
, nt_status_squash(
295 NT_STATUS_INVALID_PARAMETER
));
300 vuser
= get_partial_auth_user_struct(sconn
, vuid
);
301 /* This MUST be valid. */
303 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
306 if (!vuser
->gensec_security
) {
307 status
= auth_generic_prepare(vuser
, sconn
->remote_address
,
308 &vuser
->gensec_security
);
309 if (!NT_STATUS_IS_OK(status
)) {
310 /* Kill the intermediate vuid */
311 invalidate_vuid(sconn
, vuid
);
312 reply_nterror(req
, nt_status_squash(status
));
316 gensec_want_feature(vuser
->gensec_security
, GENSEC_FEATURE_SESSION_KEY
);
317 gensec_want_feature(vuser
->gensec_security
, GENSEC_FEATURE_UNIX_TOKEN
);
319 if (sconn
->use_gensec_hook
) {
320 status
= gensec_start_mech_by_oid(vuser
->gensec_security
, GENSEC_OID_SPNEGO
);
322 status
= gensec_start_mech_by_oid(vuser
->gensec_security
, GENSEC_OID_NTLMSSP
);
324 if (!NT_STATUS_IS_OK(status
)) {
325 /* Kill the intermediate vuid */
326 invalidate_vuid(sconn
, vuid
);
327 reply_nterror(req
, nt_status_squash(status
));
332 status
= gensec_update(vuser
->gensec_security
,
336 reply_spnego_generic(req
, vuid
,
337 &vuser
->gensec_security
,
339 data_blob_free(&chal
);
343 /****************************************************************************
344 On new VC == 0, shutdown *all* old connections and users.
345 It seems that only NT4.x does this. At W2K and above (XP etc.).
346 a new session setup with VC==0 is ignored.
347 ****************************************************************************/
349 struct shutdown_state
{
351 struct messaging_context
*msg_ctx
;
354 static int shutdown_other_smbds(const struct connections_key
*key
,
355 const struct connections_data
*crec
,
358 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
360 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
361 server_id_str(talloc_tos(), &crec
->pid
), crec
->addr
));
363 if (!process_exists(crec
->pid
)) {
364 DEBUG(10, ("process does not exist\n"));
368 if (procid_is_me(&crec
->pid
)) {
369 DEBUG(10, ("It's me\n"));
373 if (strcmp(state
->ip
, crec
->addr
) != 0) {
374 DEBUG(10, ("%s does not match %s\n", state
->ip
, crec
->addr
));
378 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
379 "(IP %s)\n", (unsigned int)procid_to_pid(&crec
->pid
),
382 messaging_send(state
->msg_ctx
, crec
->pid
, MSG_SHUTDOWN
,
387 static void setup_new_vc_session(struct smbd_server_connection
*sconn
)
389 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
390 "compatible we would close all old resources.\n"));
393 invalidate_all_vuids();
395 if (lp_reset_on_zero_vc()) {
397 struct shutdown_state state
;
399 addr
= tsocket_address_inet_addr_string(
400 sconn
->remote_address
, talloc_tos());
405 state
.msg_ctx
= sconn
->msg_ctx
;
406 connections_forall_read(shutdown_other_smbds
, &state
);
411 /****************************************************************************
412 Reply to a session setup command.
413 ****************************************************************************/
415 void reply_sesssetup_and_X(struct smb_request
*req
)
421 DATA_BLOB plaintext_password
;
424 fstring sub_user
; /* Sanitised username for substituion */
426 const char *native_os
;
427 const char *native_lanman
;
428 const char *primary_domain
;
429 struct auth_usersupplied_info
*user_info
= NULL
;
430 struct auth_serversupplied_info
*server_info
= NULL
;
431 struct auth_session_info
*session_info
= NULL
;
432 uint16 smb_flag2
= req
->flags2
;
435 struct smbd_server_connection
*sconn
= req
->sconn
;
437 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
438 bool signing_allowed
= false;
439 bool signing_mandatory
= false;
441 START_PROFILE(SMBsesssetupX
);
443 ZERO_STRUCT(lm_resp
);
444 ZERO_STRUCT(nt_resp
);
445 ZERO_STRUCT(plaintext_password
);
447 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
449 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES
) {
450 signing_allowed
= true;
452 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
) {
453 signing_mandatory
= true;
457 * We can call srv_set_signing_negotiated() each time.
458 * It finds out when it needs to turn into a noop
461 srv_set_signing_negotiated(req
->sconn
,
465 /* a SPNEGO session setup has 12 command words, whereas a normal
466 NT1 session setup has 13. See the cifs spec. */
467 if (req
->wct
== 12 &&
468 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
470 if (!sconn
->smb1
.negprot
.spnego
) {
471 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
472 "at SPNEGO session setup when it was not "
474 reply_nterror(req
, nt_status_squash(
475 NT_STATUS_LOGON_FAILURE
));
476 END_PROFILE(SMBsesssetupX
);
480 if (SVAL(req
->vwv
+4, 0) == 0) {
481 setup_new_vc_session(req
->sconn
);
484 reply_sesssetup_and_X_spnego(req
);
485 END_PROFILE(SMBsesssetupX
);
489 smb_bufsize
= SVAL(req
->vwv
+2, 0);
491 if (get_Protocol() < PROTOCOL_NT1
) {
492 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
494 /* Never do NT status codes with protocols before NT1 as we
495 * don't get client caps. */
496 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
498 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
499 reply_nterror(req
, nt_status_squash(
500 NT_STATUS_INVALID_PARAMETER
));
501 END_PROFILE(SMBsesssetupX
);
506 lm_resp
= data_blob(req
->buf
, passlen1
);
508 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
509 /* Ensure null termination */
510 plaintext_password
.data
[passlen1
] = 0;
513 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
514 req
->buf
+ passlen1
, STR_TERMINATE
);
515 user
= tmp
? tmp
: "";
520 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
521 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
522 enum remote_arch_types ra_type
= get_remote_arch();
523 const uint8_t *p
= req
->buf
;
524 const uint8_t *save_p
= req
->buf
;
528 if(global_client_caps
== 0) {
529 global_client_caps
= IVAL(req
->vwv
+11, 0);
531 if (!(global_client_caps
& CAP_STATUS32
)) {
532 remove_from_common_flags2(
533 FLAGS2_32_BIT_ERROR_CODES
);
536 /* client_caps is used as final determination if
537 * client is NT or Win95. This is needed to return
538 * the correct error codes in some circumstances.
541 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
542 ra_type
== RA_WIN95
) {
543 if(!(global_client_caps
& (CAP_NT_SMBS
|
545 set_remote_arch( RA_WIN95
);
551 /* both Win95 and WinNT stuff up the password
552 * lengths for non-encrypting systems. Uggh.
554 if passlen1==24 its a win95 system, and its setting
555 the password length incorrectly. Luckily it still
556 works with the default code because Win95 will null
557 terminate the password anyway
559 if passlen1>0 and passlen2>0 then maybe its a NT box
560 and its setting passlen2 to some random value which
561 really stuffs things up. we need to fix that one. */
563 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
569 /* check for nasty tricks */
570 if (passlen1
> MAX_PASS_LEN
571 || passlen1
> smbreq_bufrem(req
, p
)) {
572 reply_nterror(req
, nt_status_squash(
573 NT_STATUS_INVALID_PARAMETER
));
574 END_PROFILE(SMBsesssetupX
);
578 if (passlen2
> MAX_PASS_LEN
579 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
580 reply_nterror(req
, nt_status_squash(
581 NT_STATUS_INVALID_PARAMETER
));
582 END_PROFILE(SMBsesssetupX
);
586 /* Save the lanman2 password and the NT md4 password. */
588 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
593 lm_resp
= data_blob(p
, passlen1
);
594 nt_resp
= data_blob(p
+passlen1
, passlen2
);
595 } else if (lp_security() != SEC_SHARE
) {
597 * In share level we should ignore any passwords, so
598 * only read them if we're not.
601 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
603 if (unic
&& (passlen2
== 0) && passlen1
) {
604 /* Only a ascii plaintext password was sent. */
605 (void)srvstr_pull_talloc(talloc_tos(),
611 STR_TERMINATE
|STR_ASCII
);
613 (void)srvstr_pull_talloc(talloc_tos(),
618 unic
? passlen2
: passlen1
,
622 reply_nterror(req
, nt_status_squash(
623 NT_STATUS_INVALID_PARAMETER
));
624 END_PROFILE(SMBsesssetupX
);
627 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
630 p
+= passlen1
+ passlen2
;
632 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
634 user
= tmp
? tmp
: "";
636 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
638 domain
= tmp
? tmp
: "";
640 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
642 native_os
= tmp
? tmp
: "";
644 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
646 native_lanman
= tmp
? tmp
: "";
648 /* not documented or decoded by Ethereal but there is one more
649 * string in the extra bytes which is the same as the
650 * PrimaryDomain when using extended security. Windows NT 4
651 * and 2003 use this string to store the native lanman string.
652 * Windows 9x does not include a string here at all so we have
653 * to check if we have any extra bytes left */
655 byte_count
= SVAL(req
->vwv
+13, 0);
656 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
657 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
659 primary_domain
= tmp
? tmp
: "";
661 primary_domain
= talloc_strdup(talloc_tos(), "null");
664 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
665 "PrimaryDomain=[%s]\n",
666 domain
, native_os
, native_lanman
, primary_domain
));
668 if ( ra_type
== RA_WIN2K
) {
669 if ( strlen(native_lanman
) == 0 )
670 ra_lanman_string( primary_domain
);
672 ra_lanman_string( native_lanman
);
677 if (SVAL(req
->vwv
+4, 0) == 0) {
678 setup_new_vc_session(req
->sconn
);
681 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
682 domain
, user
, get_remote_machine_name()));
685 if (sconn
->smb1
.negprot
.spnego
) {
687 /* This has to be here, because this is a perfectly
688 * valid behaviour for guest logons :-( */
690 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
691 "at 'normal' session setup after "
692 "negotiating spnego.\n"));
693 reply_nterror(req
, nt_status_squash(
694 NT_STATUS_LOGON_FAILURE
));
695 END_PROFILE(SMBsesssetupX
);
698 fstrcpy(sub_user
, user
);
700 fstrcpy(sub_user
, "");
703 sub_set_smb_name(sub_user
);
705 reload_services(sconn
, conn_snum_used
, true);
707 if (lp_security() == SEC_SHARE
) {
708 char *sub_user_mapped
= NULL
;
709 /* In share level we should ignore any passwords */
711 data_blob_free(&lm_resp
);
712 data_blob_free(&nt_resp
);
713 data_blob_clear_free(&plaintext_password
);
715 (void)map_username(talloc_tos(), sub_user
, &sub_user_mapped
);
716 if (!sub_user_mapped
) {
717 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
718 END_PROFILE(SMBsesssetupX
);
721 fstrcpy(sub_user
, sub_user_mapped
);
722 add_session_user(sconn
, sub_user
);
723 add_session_workgroup(sconn
, domain
);
724 /* Then force it to null for the benfit of the code below */
730 nt_status
= check_guest_password(sconn
->remote_address
, &server_info
);
732 } else if (doencrypt
) {
733 struct auth_context
*negprot_auth_context
= NULL
;
734 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
735 if (!negprot_auth_context
) {
736 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
737 "session setup without negprot denied!\n"));
738 reply_nterror(req
, nt_status_squash(
739 NT_STATUS_LOGON_FAILURE
));
740 END_PROFILE(SMBsesssetupX
);
743 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
745 sconn
->remote_address
,
747 if (NT_STATUS_IS_OK(nt_status
)) {
748 nt_status
= negprot_auth_context
->check_ntlm_password(
749 negprot_auth_context
,
754 struct auth_context
*plaintext_auth_context
= NULL
;
756 nt_status
= make_auth_context_subsystem(
757 talloc_tos(), &plaintext_auth_context
);
759 if (NT_STATUS_IS_OK(nt_status
)) {
762 plaintext_auth_context
->get_ntlm_challenge(
763 plaintext_auth_context
, chal
);
765 if (!make_user_info_for_reply(&user_info
,
767 sconn
->remote_address
,
769 plaintext_password
)) {
770 nt_status
= NT_STATUS_NO_MEMORY
;
773 if (NT_STATUS_IS_OK(nt_status
)) {
774 nt_status
= plaintext_auth_context
->check_ntlm_password(
775 plaintext_auth_context
,
779 TALLOC_FREE(plaintext_auth_context
);
784 free_user_info(&user_info
);
786 if (!NT_STATUS_IS_OK(nt_status
)) {
787 nt_status
= do_map_to_guest_server_info(nt_status
, &server_info
,
791 if (!NT_STATUS_IS_OK(nt_status
)) {
792 data_blob_free(&nt_resp
);
793 data_blob_free(&lm_resp
);
794 data_blob_clear_free(&plaintext_password
);
795 reply_nterror(req
, nt_status_squash(nt_status
));
796 END_PROFILE(SMBsesssetupX
);
800 nt_status
= create_local_token(req
, server_info
, NULL
, sub_user
, &session_info
);
801 TALLOC_FREE(server_info
);
803 if (!NT_STATUS_IS_OK(nt_status
)) {
804 DEBUG(10, ("create_local_token failed: %s\n",
805 nt_errstr(nt_status
)));
806 data_blob_free(&nt_resp
);
807 data_blob_free(&lm_resp
);
808 data_blob_clear_free(&plaintext_password
);
809 reply_nterror(req
, nt_status_squash(nt_status
));
810 END_PROFILE(SMBsesssetupX
);
814 data_blob_clear_free(&plaintext_password
);
816 /* it's ok - setup a reply */
817 reply_outbuf(req
, 3, 0);
818 if (get_Protocol() >= PROTOCOL_NT1
) {
819 push_signature(&req
->outbuf
);
820 /* perhaps grab OS version here?? */
823 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
824 SSVAL(req
->outbuf
,smb_vwv2
,1);
827 /* register the name and uid as being validated, so further connections
828 to a uid can get through without a password, on the same VC */
830 if (lp_security() == SEC_SHARE
) {
831 sess_vuid
= UID_FIELD_INVALID
;
832 TALLOC_FREE(session_info
);
834 /* Ignore the initial vuid. */
835 sess_vuid
= register_initial_vuid(sconn
);
836 if (sess_vuid
== UID_FIELD_INVALID
) {
837 data_blob_free(&nt_resp
);
838 data_blob_free(&lm_resp
);
839 reply_nterror(req
, nt_status_squash(
840 NT_STATUS_LOGON_FAILURE
));
841 END_PROFILE(SMBsesssetupX
);
844 /* register_existing_vuid keeps the session_info */
845 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
847 nt_resp
.data
? nt_resp
: lm_resp
);
848 if (sess_vuid
== UID_FIELD_INVALID
) {
849 data_blob_free(&nt_resp
);
850 data_blob_free(&lm_resp
);
851 reply_nterror(req
, nt_status_squash(
852 NT_STATUS_LOGON_FAILURE
));
853 END_PROFILE(SMBsesssetupX
);
857 /* current_user_info is changed on new vuid */
858 reload_services(sconn
, conn_snum_used
, true);
861 data_blob_free(&nt_resp
);
862 data_blob_free(&lm_resp
);
864 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
865 SSVAL(discard_const_p(char, req
->inbuf
),smb_uid
,sess_vuid
);
866 req
->vuid
= sess_vuid
;
868 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
869 sconn
->smb1
.sessions
.max_send
=
870 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
872 sconn
->smb1
.sessions
.done_sesssetup
= true;
874 END_PROFILE(SMBsesssetupX
);