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 Do a 'guest' logon, getting back the
77 ****************************************************************************/
79 static NTSTATUS
check_guest_password(const struct tsocket_address
*remote_address
,
80 struct auth_serversupplied_info
**server_info
)
82 struct auth_context
*auth_context
;
83 struct auth_usersupplied_info
*user_info
= NULL
;
86 static unsigned char chal
[8] = { 0, };
88 DEBUG(3,("Got anonymous request\n"));
90 nt_status
= make_auth_context_fixed(talloc_tos(), &auth_context
, chal
);
91 if (!NT_STATUS_IS_OK(nt_status
)) {
95 if (!make_user_info_guest(remote_address
, &user_info
)) {
96 TALLOC_FREE(auth_context
);
97 return NT_STATUS_NO_MEMORY
;
100 nt_status
= auth_context
->check_ntlm_password(auth_context
,
103 TALLOC_FREE(auth_context
);
104 free_user_info(&user_info
);
108 /****************************************************************************
109 Reply to a session setup command.
110 conn POINTER CAN BE NULL HERE !
111 ****************************************************************************/
113 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
117 DATA_BLOB out_blob
= data_blob_null
;
120 const char *native_os
;
121 const char *native_lanman
;
122 const char *primary_domain
;
124 uint16 data_blob_len
= SVAL(req
->vwv
+7, 0);
125 enum remote_arch_types ra_type
= get_remote_arch();
126 int vuid
= req
->vuid
;
127 user_struct
*vuser
= NULL
;
128 NTSTATUS status
= NT_STATUS_OK
;
129 struct smbd_server_connection
*sconn
= req
->sconn
;
132 DEBUG(3,("Doing spnego session setup\n"));
134 if (global_client_caps
== 0) {
135 global_client_caps
= IVAL(req
->vwv
+10, 0);
137 if (!(global_client_caps
& CAP_STATUS32
)) {
138 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
144 if (data_blob_len
== 0) {
145 /* an invalid request */
146 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
150 bufrem
= smbreq_bufrem(req
, p
);
151 /* pull the spnego blob */
152 in_blob
= data_blob_const(p
, MIN(bufrem
, data_blob_len
));
155 file_save("negotiate.dat", in_blob
.data
, in_blob
.length
);
158 p2
= (const char *)req
->buf
+ in_blob
.length
;
160 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
162 native_os
= tmp
? tmp
: "";
164 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
166 native_lanman
= tmp
? tmp
: "";
168 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
170 primary_domain
= tmp
? tmp
: "";
172 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
173 native_os
, native_lanman
, primary_domain
));
175 if ( ra_type
== RA_WIN2K
) {
176 /* Vista sets neither the OS or lanman strings */
178 if ( !strlen(native_os
) && !strlen(native_lanman
) )
179 set_remote_arch(RA_VISTA
);
181 /* Windows 2003 doesn't set the native lanman string,
182 but does set primary domain which is a bug I think */
184 if ( !strlen(native_lanman
) ) {
185 ra_lanman_string( primary_domain
);
187 ra_lanman_string( native_lanman
);
189 } else if ( ra_type
== RA_VISTA
) {
190 if ( strncmp(native_os
, "Mac OS X", 8) == 0 ) {
191 set_remote_arch(RA_OSX
);
195 vuser
= get_valid_user_struct(sconn
, vuid
);
197 reply_nterror(req
, NT_STATUS_REQUEST_NOT_ACCEPTED
);
201 /* Do we have a valid vuid now ? */
202 if (!is_partial_auth_vuid(sconn
, vuid
)) {
203 /* No, start a new authentication setup. */
204 vuid
= register_initial_vuid(sconn
);
205 if (vuid
== UID_FIELD_INVALID
) {
206 reply_nterror(req
, nt_status_squash(
207 NT_STATUS_INVALID_PARAMETER
));
212 vuser
= get_partial_auth_user_struct(sconn
, vuid
);
213 /* This MUST be valid. */
215 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
218 if (!vuser
->gensec_security
) {
219 status
= auth_generic_prepare(vuser
, sconn
->remote_address
,
220 &vuser
->gensec_security
);
221 if (!NT_STATUS_IS_OK(status
)) {
222 /* Kill the intermediate vuid */
223 invalidate_vuid(sconn
, vuid
);
224 reply_nterror(req
, nt_status_squash(status
));
228 gensec_want_feature(vuser
->gensec_security
, GENSEC_FEATURE_SESSION_KEY
);
229 gensec_want_feature(vuser
->gensec_security
, GENSEC_FEATURE_UNIX_TOKEN
);
231 status
= gensec_start_mech_by_oid(vuser
->gensec_security
, GENSEC_OID_SPNEGO
);
232 if (!NT_STATUS_IS_OK(status
)) {
233 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
234 /* Kill the intermediate vuid */
235 invalidate_vuid(sconn
, vuid
);
236 reply_nterror(req
, nt_status_squash(status
));
241 status
= gensec_update(vuser
->gensec_security
,
244 if (!NT_STATUS_IS_OK(status
) &&
245 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
246 /* Kill the intermediate vuid */
247 invalidate_vuid(sconn
, vuid
);
248 reply_nterror(req
, nt_status_squash(status
));
252 if (NT_STATUS_IS_OK(status
)) {
253 struct auth_session_info
*session_info
= NULL
;
256 status
= gensec_session_info(vuser
->gensec_security
,
259 if (!NT_STATUS_IS_OK(status
)) {
260 DEBUG(1,("Failed to generate session_info "
261 "(user and group token) for session setup: %s\n",
263 /* Kill the intermediate vuid */
264 data_blob_free(&out_blob
);
265 invalidate_vuid(sconn
, vuid
);
266 reply_nterror(req
, nt_status_squash(status
));
270 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
274 /* register_existing_vuid keeps the server info */
275 tmp_vuid
= register_existing_vuid(sconn
, vuid
,
278 if (tmp_vuid
!= vuid
) {
279 data_blob_free(&out_blob
);
280 invalidate_vuid(sconn
, vuid
);
281 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
285 /* current_user_info is changed on new vuid */
286 reload_services(sconn
, conn_snum_used
, true);
289 reply_outbuf(req
, 4, 0);
291 SSVAL(req
->outbuf
, smb_uid
, vuid
);
292 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(status
));
293 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
294 SSVAL(req
->outbuf
, smb_vwv2
, action
);
295 SSVAL(req
->outbuf
, smb_vwv3
, out_blob
.length
);
297 if (message_push_blob(&req
->outbuf
, out_blob
) == -1) {
298 data_blob_free(&out_blob
);
299 invalidate_vuid(sconn
, vuid
);
300 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
303 data_blob_free(&out_blob
);
305 if (push_signature(&req
->outbuf
) == -1) {
306 invalidate_vuid(sconn
, vuid
);
307 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
312 /****************************************************************************
313 On new VC == 0, shutdown *all* old connections and users.
314 It seems that only NT4.x does this. At W2K and above (XP etc.).
315 a new session setup with VC==0 is ignored.
316 ****************************************************************************/
318 struct shutdown_state
{
320 struct messaging_context
*msg_ctx
;
323 static int shutdown_other_smbds(const struct connections_key
*key
,
324 const struct connections_data
*crec
,
327 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
329 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
330 server_id_str(talloc_tos(), &crec
->pid
), crec
->addr
));
332 if (!process_exists(crec
->pid
)) {
333 DEBUG(10, ("process does not exist\n"));
337 if (procid_is_me(&crec
->pid
)) {
338 DEBUG(10, ("It's me\n"));
342 if (strcmp(state
->ip
, crec
->addr
) != 0) {
343 DEBUG(10, ("%s does not match %s\n", state
->ip
, crec
->addr
));
347 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
348 "(IP %s)\n", (unsigned int)procid_to_pid(&crec
->pid
),
351 messaging_send(state
->msg_ctx
, crec
->pid
, MSG_SHUTDOWN
,
356 static void setup_new_vc_session(struct smbd_server_connection
*sconn
)
358 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
359 "compatible we would close all old resources.\n"));
362 invalidate_all_vuids();
364 if (lp_reset_on_zero_vc()) {
366 struct shutdown_state state
;
368 addr
= tsocket_address_inet_addr_string(
369 sconn
->remote_address
, talloc_tos());
374 state
.msg_ctx
= sconn
->msg_ctx
;
375 connections_forall_read(shutdown_other_smbds
, &state
);
380 /****************************************************************************
381 Reply to a session setup command.
382 ****************************************************************************/
384 void reply_sesssetup_and_X(struct smb_request
*req
)
390 DATA_BLOB plaintext_password
;
393 fstring sub_user
; /* Sanitised username for substituion */
395 const char *native_os
;
396 const char *native_lanman
;
397 const char *primary_domain
;
398 struct auth_usersupplied_info
*user_info
= NULL
;
399 struct auth_serversupplied_info
*server_info
= NULL
;
400 struct auth_session_info
*session_info
= NULL
;
401 uint16 smb_flag2
= req
->flags2
;
404 struct smbd_server_connection
*sconn
= req
->sconn
;
406 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
407 bool signing_allowed
= false;
408 bool signing_mandatory
= false;
410 START_PROFILE(SMBsesssetupX
);
412 ZERO_STRUCT(lm_resp
);
413 ZERO_STRUCT(nt_resp
);
414 ZERO_STRUCT(plaintext_password
);
416 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
418 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES
) {
419 signing_allowed
= true;
421 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
) {
422 signing_mandatory
= true;
426 * We can call srv_set_signing_negotiated() each time.
427 * It finds out when it needs to turn into a noop
430 srv_set_signing_negotiated(req
->sconn
,
434 /* a SPNEGO session setup has 12 command words, whereas a normal
435 NT1 session setup has 13. See the cifs spec. */
436 if (req
->wct
== 12 &&
437 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
439 if (!sconn
->smb1
.negprot
.spnego
) {
440 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
441 "at SPNEGO session setup when it was not "
443 reply_nterror(req
, nt_status_squash(
444 NT_STATUS_LOGON_FAILURE
));
445 END_PROFILE(SMBsesssetupX
);
449 if (SVAL(req
->vwv
+4, 0) == 0) {
450 setup_new_vc_session(req
->sconn
);
453 reply_sesssetup_and_X_spnego(req
);
454 END_PROFILE(SMBsesssetupX
);
458 smb_bufsize
= SVAL(req
->vwv
+2, 0);
460 if (get_Protocol() < PROTOCOL_NT1
) {
461 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
463 /* Never do NT status codes with protocols before NT1 as we
464 * don't get client caps. */
465 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
467 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
468 reply_nterror(req
, nt_status_squash(
469 NT_STATUS_INVALID_PARAMETER
));
470 END_PROFILE(SMBsesssetupX
);
475 lm_resp
= data_blob(req
->buf
, passlen1
);
477 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
478 /* Ensure null termination */
479 plaintext_password
.data
[passlen1
] = 0;
482 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
483 req
->buf
+ passlen1
, STR_TERMINATE
);
484 user
= tmp
? tmp
: "";
489 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
490 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
491 enum remote_arch_types ra_type
= get_remote_arch();
492 const uint8_t *p
= req
->buf
;
493 const uint8_t *save_p
= req
->buf
;
497 if(global_client_caps
== 0) {
498 global_client_caps
= IVAL(req
->vwv
+11, 0);
500 if (!(global_client_caps
& CAP_STATUS32
)) {
501 remove_from_common_flags2(
502 FLAGS2_32_BIT_ERROR_CODES
);
505 /* client_caps is used as final determination if
506 * client is NT or Win95. This is needed to return
507 * the correct error codes in some circumstances.
510 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
511 ra_type
== RA_WIN95
) {
512 if(!(global_client_caps
& (CAP_NT_SMBS
|
514 set_remote_arch( RA_WIN95
);
520 /* both Win95 and WinNT stuff up the password
521 * lengths for non-encrypting systems. Uggh.
523 if passlen1==24 its a win95 system, and its setting
524 the password length incorrectly. Luckily it still
525 works with the default code because Win95 will null
526 terminate the password anyway
528 if passlen1>0 and passlen2>0 then maybe its a NT box
529 and its setting passlen2 to some random value which
530 really stuffs things up. we need to fix that one. */
532 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
538 /* check for nasty tricks */
539 if (passlen1
> MAX_PASS_LEN
540 || passlen1
> smbreq_bufrem(req
, p
)) {
541 reply_nterror(req
, nt_status_squash(
542 NT_STATUS_INVALID_PARAMETER
));
543 END_PROFILE(SMBsesssetupX
);
547 if (passlen2
> MAX_PASS_LEN
548 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
549 reply_nterror(req
, nt_status_squash(
550 NT_STATUS_INVALID_PARAMETER
));
551 END_PROFILE(SMBsesssetupX
);
555 /* Save the lanman2 password and the NT md4 password. */
557 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
562 lm_resp
= data_blob(p
, passlen1
);
563 nt_resp
= data_blob(p
+passlen1
, passlen2
);
564 } else if (lp_security() != SEC_SHARE
) {
566 * In share level we should ignore any passwords, so
567 * only read them if we're not.
570 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
572 if (unic
&& (passlen2
== 0) && passlen1
) {
573 /* Only a ascii plaintext password was sent. */
574 (void)srvstr_pull_talloc(talloc_tos(),
580 STR_TERMINATE
|STR_ASCII
);
582 (void)srvstr_pull_talloc(talloc_tos(),
587 unic
? passlen2
: passlen1
,
591 reply_nterror(req
, nt_status_squash(
592 NT_STATUS_INVALID_PARAMETER
));
593 END_PROFILE(SMBsesssetupX
);
596 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
599 p
+= passlen1
+ passlen2
;
601 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
603 user
= tmp
? tmp
: "";
605 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
607 domain
= tmp
? tmp
: "";
609 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
611 native_os
= tmp
? tmp
: "";
613 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
615 native_lanman
= tmp
? tmp
: "";
617 /* not documented or decoded by Ethereal but there is one more
618 * string in the extra bytes which is the same as the
619 * PrimaryDomain when using extended security. Windows NT 4
620 * and 2003 use this string to store the native lanman string.
621 * Windows 9x does not include a string here at all so we have
622 * to check if we have any extra bytes left */
624 byte_count
= SVAL(req
->vwv
+13, 0);
625 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
626 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
628 primary_domain
= tmp
? tmp
: "";
630 primary_domain
= talloc_strdup(talloc_tos(), "null");
633 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
634 "PrimaryDomain=[%s]\n",
635 domain
, native_os
, native_lanman
, primary_domain
));
637 if ( ra_type
== RA_WIN2K
) {
638 if ( strlen(native_lanman
) == 0 )
639 ra_lanman_string( primary_domain
);
641 ra_lanman_string( native_lanman
);
646 if (SVAL(req
->vwv
+4, 0) == 0) {
647 setup_new_vc_session(req
->sconn
);
650 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
651 domain
, user
, get_remote_machine_name()));
654 if (sconn
->smb1
.negprot
.spnego
) {
656 /* This has to be here, because this is a perfectly
657 * valid behaviour for guest logons :-( */
659 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
660 "at 'normal' session setup after "
661 "negotiating spnego.\n"));
662 reply_nterror(req
, nt_status_squash(
663 NT_STATUS_LOGON_FAILURE
));
664 END_PROFILE(SMBsesssetupX
);
667 fstrcpy(sub_user
, user
);
669 fstrcpy(sub_user
, "");
672 sub_set_smb_name(sub_user
);
674 reload_services(sconn
, conn_snum_used
, true);
676 if (lp_security() == SEC_SHARE
) {
677 char *sub_user_mapped
= NULL
;
678 /* In share level we should ignore any passwords */
680 data_blob_free(&lm_resp
);
681 data_blob_free(&nt_resp
);
682 data_blob_clear_free(&plaintext_password
);
684 (void)map_username(talloc_tos(), sub_user
, &sub_user_mapped
);
685 if (!sub_user_mapped
) {
686 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
687 END_PROFILE(SMBsesssetupX
);
690 fstrcpy(sub_user
, sub_user_mapped
);
691 add_session_user(sconn
, sub_user
);
692 add_session_workgroup(sconn
, domain
);
693 /* Then force it to null for the benfit of the code below */
699 nt_status
= check_guest_password(sconn
->remote_address
, &server_info
);
701 } else if (doencrypt
) {
702 struct auth_context
*negprot_auth_context
= NULL
;
703 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
704 if (!negprot_auth_context
) {
705 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
706 "session setup without negprot denied!\n"));
707 reply_nterror(req
, nt_status_squash(
708 NT_STATUS_LOGON_FAILURE
));
709 END_PROFILE(SMBsesssetupX
);
712 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
714 sconn
->remote_address
,
716 if (NT_STATUS_IS_OK(nt_status
)) {
717 nt_status
= negprot_auth_context
->check_ntlm_password(
718 negprot_auth_context
,
723 struct auth_context
*plaintext_auth_context
= NULL
;
725 nt_status
= make_auth_context_subsystem(
726 talloc_tos(), &plaintext_auth_context
);
728 if (NT_STATUS_IS_OK(nt_status
)) {
731 plaintext_auth_context
->get_ntlm_challenge(
732 plaintext_auth_context
, chal
);
734 if (!make_user_info_for_reply(&user_info
,
736 sconn
->remote_address
,
738 plaintext_password
)) {
739 nt_status
= NT_STATUS_NO_MEMORY
;
742 if (NT_STATUS_IS_OK(nt_status
)) {
743 nt_status
= plaintext_auth_context
->check_ntlm_password(
744 plaintext_auth_context
,
748 TALLOC_FREE(plaintext_auth_context
);
753 free_user_info(&user_info
);
755 if (!NT_STATUS_IS_OK(nt_status
)) {
756 nt_status
= do_map_to_guest_server_info(nt_status
, &server_info
,
760 if (!NT_STATUS_IS_OK(nt_status
)) {
761 data_blob_free(&nt_resp
);
762 data_blob_free(&lm_resp
);
763 data_blob_clear_free(&plaintext_password
);
764 reply_nterror(req
, nt_status_squash(nt_status
));
765 END_PROFILE(SMBsesssetupX
);
769 nt_status
= create_local_token(req
, server_info
, NULL
, sub_user
, &session_info
);
770 TALLOC_FREE(server_info
);
772 if (!NT_STATUS_IS_OK(nt_status
)) {
773 DEBUG(10, ("create_local_token failed: %s\n",
774 nt_errstr(nt_status
)));
775 data_blob_free(&nt_resp
);
776 data_blob_free(&lm_resp
);
777 data_blob_clear_free(&plaintext_password
);
778 reply_nterror(req
, nt_status_squash(nt_status
));
779 END_PROFILE(SMBsesssetupX
);
783 data_blob_clear_free(&plaintext_password
);
785 /* it's ok - setup a reply */
786 reply_outbuf(req
, 3, 0);
787 if (get_Protocol() >= PROTOCOL_NT1
) {
788 push_signature(&req
->outbuf
);
789 /* perhaps grab OS version here?? */
792 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
793 SSVAL(req
->outbuf
,smb_vwv2
,1);
796 /* register the name and uid as being validated, so further connections
797 to a uid can get through without a password, on the same VC */
799 if (lp_security() == SEC_SHARE
) {
800 sess_vuid
= UID_FIELD_INVALID
;
801 TALLOC_FREE(session_info
);
803 /* Ignore the initial vuid. */
804 sess_vuid
= register_initial_vuid(sconn
);
805 if (sess_vuid
== UID_FIELD_INVALID
) {
806 data_blob_free(&nt_resp
);
807 data_blob_free(&lm_resp
);
808 reply_nterror(req
, nt_status_squash(
809 NT_STATUS_LOGON_FAILURE
));
810 END_PROFILE(SMBsesssetupX
);
813 /* register_existing_vuid keeps the session_info */
814 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
816 nt_resp
.data
? nt_resp
: lm_resp
);
817 if (sess_vuid
== UID_FIELD_INVALID
) {
818 data_blob_free(&nt_resp
);
819 data_blob_free(&lm_resp
);
820 reply_nterror(req
, nt_status_squash(
821 NT_STATUS_LOGON_FAILURE
));
822 END_PROFILE(SMBsesssetupX
);
826 /* current_user_info is changed on new vuid */
827 reload_services(sconn
, conn_snum_used
, true);
830 data_blob_free(&nt_resp
);
831 data_blob_free(&lm_resp
);
833 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
834 SSVAL(discard_const_p(char, req
->inbuf
),smb_uid
,sess_vuid
);
835 req
->vuid
= sess_vuid
;
837 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
838 sconn
->smb1
.sessions
.max_send
=
839 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
841 sconn
->smb1
.sessions
.done_sesssetup
= true;
843 END_PROFILE(SMBsesssetupX
);