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"
39 #include "lib/conn_tdb.h"
41 /****************************************************************************
42 Add the standard 'Samba' signature to the end of the session setup.
43 ****************************************************************************/
45 static int push_signature(uint8
**outbuf
)
52 tmp
= message_push_string(outbuf
, "Unix", STR_TERMINATE
);
54 if (tmp
== -1) return -1;
57 if (asprintf(&lanman
, "Samba %s", samba_version_string()) != -1) {
58 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
62 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
65 if (tmp
== -1) return -1;
68 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
70 if (tmp
== -1) return -1;
76 /****************************************************************************
77 Do a 'guest' logon, getting back the
78 ****************************************************************************/
80 static NTSTATUS
check_guest_password(const struct tsocket_address
*remote_address
,
82 struct auth_session_info
**session_info
)
84 struct auth4_context
*auth_context
;
85 struct auth_usersupplied_info
*user_info
= NULL
;
89 DEBUG(3,("Got anonymous request\n"));
91 nt_status
= make_auth4_context(talloc_tos(), &auth_context
);
92 if (!NT_STATUS_IS_OK(nt_status
)) {
96 auth_context
->get_ntlm_challenge(auth_context
,
99 if (!make_user_info_guest(remote_address
, &user_info
)) {
100 TALLOC_FREE(auth_context
);
101 return NT_STATUS_NO_MEMORY
;
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
);
111 /****************************************************************************
112 Reply to a session setup command.
113 conn POINTER CAN BE NULL HERE !
114 ****************************************************************************/
116 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
120 DATA_BLOB out_blob
= data_blob_null
;
123 const char *native_os
;
124 const char *native_lanman
;
125 const char *primary_domain
;
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 NTSTATUS status
= NT_STATUS_OK
;
131 struct smbd_server_connection
*sconn
= req
->sconn
;
133 NTTIME now
= timeval_to_nttime(&req
->request_time
);
134 struct smbXsrv_session
*session
= NULL
;
135 uint32_t client_caps
= IVAL(req
->vwv
+10, 0);
137 DEBUG(3,("Doing spnego session setup\n"));
139 if (global_client_caps
== 0) {
140 global_client_caps
= client_caps
;
142 if (!(global_client_caps
& CAP_STATUS32
)) {
143 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
149 if (data_blob_len
== 0) {
150 /* an invalid request */
151 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
155 bufrem
= smbreq_bufrem(req
, p
);
156 /* pull the spnego blob */
157 in_blob
= data_blob_const(p
, MIN(bufrem
, data_blob_len
));
160 file_save("negotiate.dat", in_blob
.data
, in_blob
.length
);
163 p2
= (const char *)req
->buf
+ in_blob
.length
;
165 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
167 native_os
= tmp
? tmp
: "";
169 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
171 native_lanman
= tmp
? tmp
: "";
173 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
175 primary_domain
= tmp
? tmp
: "";
177 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
178 native_os
, native_lanman
, primary_domain
));
180 if ( ra_type
== RA_WIN2K
) {
181 /* Vista sets neither the OS or lanman strings */
183 if ( !strlen(native_os
) && !strlen(native_lanman
) )
184 set_remote_arch(RA_VISTA
);
186 /* Windows 2003 doesn't set the native lanman string,
187 but does set primary domain which is a bug I think */
189 if ( !strlen(native_lanman
) ) {
190 ra_lanman_string( primary_domain
);
192 ra_lanman_string( native_lanman
);
194 } else if ( ra_type
== RA_VISTA
) {
195 if ( strncmp(native_os
, "Mac OS X", 8) == 0 ) {
196 set_remote_arch(RA_OSX
);
201 status
= smb1srv_session_lookup(sconn
->conn
,
204 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
205 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
208 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
209 status
= NT_STATUS_OK
;
211 if (NT_STATUS_IS_OK(status
)) {
212 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
213 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
214 TALLOC_FREE(session
->gensec
);
216 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
217 reply_nterror(req
, nt_status_squash(status
));
222 if (session
== NULL
) {
223 /* create a new session */
224 status
= smbXsrv_session_create(sconn
->conn
,
226 if (!NT_STATUS_IS_OK(status
)) {
227 reply_nterror(req
, nt_status_squash(status
));
232 if (!session
->gensec
) {
233 status
= auth_generic_prepare(session
, sconn
->remote_address
,
235 if (!NT_STATUS_IS_OK(status
)) {
236 TALLOC_FREE(session
);
237 reply_nterror(req
, nt_status_squash(status
));
241 gensec_want_feature(session
->gensec
, GENSEC_FEATURE_SESSION_KEY
);
242 gensec_want_feature(session
->gensec
, GENSEC_FEATURE_UNIX_TOKEN
);
244 status
= gensec_start_mech_by_oid(session
->gensec
,
246 if (!NT_STATUS_IS_OK(status
)) {
247 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
248 TALLOC_FREE(session
);;
249 reply_nterror(req
, nt_status_squash(status
));
255 status
= gensec_update(session
->gensec
,
259 if (!NT_STATUS_IS_OK(status
) &&
260 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
261 TALLOC_FREE(session
);
262 reply_nterror(req
, nt_status_squash(status
));
266 if (NT_STATUS_IS_OK(status
) && session
->global
->auth_session_info
== NULL
) {
267 struct auth_session_info
*session_info
= NULL
;
269 status
= gensec_session_info(session
->gensec
,
272 if (!NT_STATUS_IS_OK(status
)) {
273 DEBUG(1,("Failed to generate session_info "
274 "(user and group token) for session setup: %s\n",
276 data_blob_free(&out_blob
);
277 TALLOC_FREE(session
);
278 reply_nterror(req
, nt_status_squash(status
));
282 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
286 if (session_info
->session_key
.length
> 0) {
287 struct smbXsrv_session
*x
= session
;
290 * Note: the SMB1 signing key is not truncated to 16 byte!
292 x
->global
->signing_key
=
293 data_blob_dup_talloc(x
->global
,
294 session_info
->session_key
);
295 if (x
->global
->signing_key
.data
== NULL
) {
296 data_blob_free(&out_blob
);
297 TALLOC_FREE(session
);
298 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
303 * clear the session key
304 * the first tcon will add setup the application key
306 data_blob_clear_free(&session_info
->session_key
);
309 session
->compat
= talloc_zero(session
, struct user_struct
);
310 if (session
->compat
== NULL
) {
311 data_blob_free(&out_blob
);
312 TALLOC_FREE(session
);
313 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
316 session
->compat
->session
= session
;
317 session
->compat
->homes_snum
= -1;
318 session
->compat
->session_info
= session_info
;
319 session
->compat
->session_keystr
= NULL
;
320 session
->compat
->vuid
= session
->global
->session_wire_id
;
321 DLIST_ADD(sconn
->users
, session
->compat
);
324 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
325 session
->compat
->homes_snum
=
326 register_homes_share(session_info
->unix_info
->unix_name
);
329 if (srv_is_signing_negotiated(sconn
) &&
331 session
->global
->signing_key
.length
> 0)
334 * Try and turn on server signing on the first non-guest
337 srv_set_signing(sconn
,
338 session
->global
->signing_key
,
342 set_current_user_info(session_info
->unix_info
->sanitized_username
,
343 session_info
->unix_info
->unix_name
,
344 session_info
->info
->domain_name
);
346 session
->status
= NT_STATUS_OK
;
347 session
->global
->auth_session_info
= talloc_move(session
->global
,
349 session
->global
->auth_session_info_seqnum
+= 1;
350 session
->global
->channels
[0].auth_session_info_seqnum
=
351 session
->global
->auth_session_info_seqnum
;
352 if (client_caps
& CAP_DYNAMIC_REAUTH
) {
353 session
->global
->expiration_time
=
354 gensec_expire_time(session
->gensec
);
356 session
->global
->expiration_time
=
357 GENSEC_EXPIRE_TIME_INFINITY
;
360 if (!session_claim(session
)) {
361 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
362 (unsigned long long)session
->compat
->vuid
));
363 data_blob_free(&out_blob
);
364 TALLOC_FREE(session
);
365 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
369 status
= smbXsrv_session_update(session
);
370 if (!NT_STATUS_IS_OK(status
)) {
371 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
372 (unsigned long long)session
->compat
->vuid
,
374 data_blob_free(&out_blob
);
375 TALLOC_FREE(session
);
376 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
380 /* current_user_info is changed on new vuid */
381 reload_services(sconn
, conn_snum_used
, true);
382 } else if (NT_STATUS_IS_OK(status
)) {
383 struct auth_session_info
*session_info
= NULL
;
385 status
= gensec_session_info(session
->gensec
,
388 if (!NT_STATUS_IS_OK(status
)) {
389 DEBUG(1,("Failed to generate session_info "
390 "(user and group token) for session setup: %s\n",
392 data_blob_free(&out_blob
);
393 TALLOC_FREE(session
);
394 reply_nterror(req
, nt_status_squash(status
));
398 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
403 * Keep the application key
405 data_blob_clear_free(&session_info
->session_key
);
406 session_info
->session_key
=
407 session
->global
->auth_session_info
->session_key
;
408 talloc_steal(session_info
, session_info
->session_key
.data
);
409 TALLOC_FREE(session
->global
->auth_session_info
);
411 session
->compat
->session_info
= session_info
;
413 session
->compat
->vuid
= session
->global
->session_wire_id
;
415 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
416 session
->compat
->homes_snum
=
417 register_homes_share(session_info
->unix_info
->unix_name
);
420 set_current_user_info(session_info
->unix_info
->sanitized_username
,
421 session_info
->unix_info
->unix_name
,
422 session_info
->info
->domain_name
);
424 session
->status
= NT_STATUS_OK
;
425 session
->global
->auth_session_info
= talloc_move(session
->global
,
427 session
->global
->auth_session_info_seqnum
+= 1;
428 session
->global
->channels
[0].auth_session_info_seqnum
=
429 session
->global
->auth_session_info_seqnum
;
430 if (client_caps
& CAP_DYNAMIC_REAUTH
) {
431 session
->global
->expiration_time
=
432 gensec_expire_time(session
->gensec
);
434 session
->global
->expiration_time
=
435 GENSEC_EXPIRE_TIME_INFINITY
;
438 status
= smbXsrv_session_update(session
);
439 if (!NT_STATUS_IS_OK(status
)) {
440 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
441 (unsigned long long)session
->compat
->vuid
,
443 data_blob_free(&out_blob
);
444 TALLOC_FREE(session
);
445 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
449 conn_clear_vuid_caches(sconn
, session
->compat
->vuid
);
451 /* current_user_info is changed on new vuid */
452 reload_services(sconn
, conn_snum_used
, true);
455 vuid
= session
->global
->session_wire_id
;
457 reply_outbuf(req
, 4, 0);
459 SSVAL(req
->outbuf
, smb_uid
, vuid
);
460 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(status
));
461 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
462 SSVAL(req
->outbuf
, smb_vwv2
, action
);
463 SSVAL(req
->outbuf
, smb_vwv3
, out_blob
.length
);
465 if (message_push_blob(&req
->outbuf
, out_blob
) == -1) {
466 data_blob_free(&out_blob
);
467 TALLOC_FREE(session
);
468 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
471 data_blob_free(&out_blob
);
473 if (push_signature(&req
->outbuf
) == -1) {
474 TALLOC_FREE(session
);
475 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
480 /****************************************************************************
481 On new VC == 0, shutdown *all* old connections and users.
482 It seems that only NT4.x does this. At W2K and above (XP etc.).
483 a new session setup with VC==0 is ignored.
484 ****************************************************************************/
486 struct shutdown_state
{
488 struct messaging_context
*msg_ctx
;
491 static int shutdown_other_smbds(struct smbXsrv_session_global0
*session
,
494 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
495 struct server_id self_pid
= messaging_server_id(state
->msg_ctx
);
496 struct server_id pid
= session
->channels
[0].server_id
;
497 const char *addr
= session
->channels
[0].remote_address
;
499 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
500 server_id_str(talloc_tos(), &pid
), addr
));
502 if (!process_exists(pid
)) {
503 DEBUG(10, ("process does not exist\n"));
507 if (serverid_equal(&pid
, &self_pid
)) {
508 DEBUG(10, ("It's me\n"));
513 * here we use strstr() because 'addr'
514 * (session->channels[0].remote_address)
515 * contains a string like:
516 * 'ipv4:127.0.0.1:48163'
518 if (strstr(addr
, state
->ip
) == NULL
) {
519 DEBUG(10, ("%s does not match %s\n", state
->ip
, addr
));
523 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
524 "(IP %s)\n", (unsigned int)procid_to_pid(&pid
),
527 messaging_send(state
->msg_ctx
, pid
, MSG_SHUTDOWN
,
532 static void setup_new_vc_session(struct smbd_server_connection
*sconn
)
534 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
535 "compatible we would close all old resources.\n"));
538 invalidate_all_vuids();
540 if (lp_reset_on_zero_vc()) {
542 struct shutdown_state state
;
544 addr
= tsocket_address_inet_addr_string(
545 sconn
->remote_address
, talloc_tos());
550 state
.msg_ctx
= sconn
->msg_ctx
;
551 smbXsrv_session_global_traverse(shutdown_other_smbds
, &state
);
556 /****************************************************************************
557 Reply to a session setup command.
558 ****************************************************************************/
560 void reply_sesssetup_and_X(struct smb_request
*req
)
566 DATA_BLOB plaintext_password
;
569 fstring sub_user
; /* Sanitised username for substituion */
571 const char *native_os
;
572 const char *native_lanman
;
573 const char *primary_domain
;
574 struct auth_usersupplied_info
*user_info
= NULL
;
575 struct auth_session_info
*session_info
= NULL
;
576 uint16 smb_flag2
= req
->flags2
;
578 NTTIME now
= timeval_to_nttime(&req
->request_time
);
579 struct smbXsrv_session
*session
= NULL
;
582 struct smbd_server_connection
*sconn
= req
->sconn
;
584 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
585 bool signing_allowed
= false;
586 bool signing_mandatory
= false;
588 START_PROFILE(SMBsesssetupX
);
590 ZERO_STRUCT(lm_resp
);
591 ZERO_STRUCT(nt_resp
);
592 ZERO_STRUCT(plaintext_password
);
594 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
596 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES
) {
597 signing_allowed
= true;
599 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
) {
600 signing_mandatory
= true;
604 * We can call srv_set_signing_negotiated() each time.
605 * It finds out when it needs to turn into a noop
608 srv_set_signing_negotiated(req
->sconn
,
612 /* a SPNEGO session setup has 12 command words, whereas a normal
613 NT1 session setup has 13. See the cifs spec. */
614 if (req
->wct
== 12 &&
615 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
617 if (!sconn
->smb1
.negprot
.spnego
) {
618 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
619 "at SPNEGO session setup when it was not "
621 reply_nterror(req
, nt_status_squash(
622 NT_STATUS_LOGON_FAILURE
));
623 END_PROFILE(SMBsesssetupX
);
627 if (SVAL(req
->vwv
+4, 0) == 0) {
628 setup_new_vc_session(req
->sconn
);
631 reply_sesssetup_and_X_spnego(req
);
632 END_PROFILE(SMBsesssetupX
);
636 smb_bufsize
= SVAL(req
->vwv
+2, 0);
638 if (get_Protocol() < PROTOCOL_NT1
) {
639 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
641 /* Never do NT status codes with protocols before NT1 as we
642 * don't get client caps. */
643 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
645 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
646 reply_nterror(req
, nt_status_squash(
647 NT_STATUS_INVALID_PARAMETER
));
648 END_PROFILE(SMBsesssetupX
);
653 lm_resp
= data_blob(req
->buf
, passlen1
);
655 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
656 /* Ensure null termination */
657 plaintext_password
.data
[passlen1
] = 0;
660 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
661 req
->buf
+ passlen1
, STR_TERMINATE
);
662 user
= tmp
? tmp
: "";
667 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
668 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
669 enum remote_arch_types ra_type
= get_remote_arch();
670 const uint8_t *p
= req
->buf
;
671 const uint8_t *save_p
= req
->buf
;
675 if(global_client_caps
== 0) {
676 global_client_caps
= IVAL(req
->vwv
+11, 0);
678 if (!(global_client_caps
& CAP_STATUS32
)) {
679 remove_from_common_flags2(
680 FLAGS2_32_BIT_ERROR_CODES
);
683 /* client_caps is used as final determination if
684 * client is NT or Win95. This is needed to return
685 * the correct error codes in some circumstances.
688 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
689 ra_type
== RA_WIN95
) {
690 if(!(global_client_caps
& (CAP_NT_SMBS
|
692 set_remote_arch( RA_WIN95
);
698 /* both Win95 and WinNT stuff up the password
699 * lengths for non-encrypting systems. Uggh.
701 if passlen1==24 its a win95 system, and its setting
702 the password length incorrectly. Luckily it still
703 works with the default code because Win95 will null
704 terminate the password anyway
706 if passlen1>0 and passlen2>0 then maybe its a NT box
707 and its setting passlen2 to some random value which
708 really stuffs things up. we need to fix that one. */
710 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
716 /* check for nasty tricks */
717 if (passlen1
> MAX_PASS_LEN
718 || passlen1
> smbreq_bufrem(req
, p
)) {
719 reply_nterror(req
, nt_status_squash(
720 NT_STATUS_INVALID_PARAMETER
));
721 END_PROFILE(SMBsesssetupX
);
725 if (passlen2
> MAX_PASS_LEN
726 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
727 reply_nterror(req
, nt_status_squash(
728 NT_STATUS_INVALID_PARAMETER
));
729 END_PROFILE(SMBsesssetupX
);
733 /* Save the lanman2 password and the NT md4 password. */
735 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
740 lm_resp
= data_blob(p
, passlen1
);
741 nt_resp
= data_blob(p
+passlen1
, passlen2
);
744 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
746 if (unic
&& (passlen2
== 0) && passlen1
) {
747 /* Only a ascii plaintext password was sent. */
748 (void)srvstr_pull_talloc(talloc_tos(),
754 STR_TERMINATE
|STR_ASCII
);
756 (void)srvstr_pull_talloc(talloc_tos(),
761 unic
? passlen2
: passlen1
,
765 reply_nterror(req
, nt_status_squash(
766 NT_STATUS_INVALID_PARAMETER
));
767 END_PROFILE(SMBsesssetupX
);
770 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
773 p
+= passlen1
+ passlen2
;
775 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
777 user
= tmp
? tmp
: "";
779 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
781 domain
= tmp
? tmp
: "";
783 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
785 native_os
= tmp
? tmp
: "";
787 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
789 native_lanman
= tmp
? tmp
: "";
791 /* not documented or decoded by Ethereal but there is one more
792 * string in the extra bytes which is the same as the
793 * PrimaryDomain when using extended security. Windows NT 4
794 * and 2003 use this string to store the native lanman string.
795 * Windows 9x does not include a string here at all so we have
796 * to check if we have any extra bytes left */
798 byte_count
= SVAL(req
->vwv
+13, 0);
799 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
800 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
802 primary_domain
= tmp
? tmp
: "";
804 primary_domain
= talloc_strdup(talloc_tos(), "null");
807 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
808 "PrimaryDomain=[%s]\n",
809 domain
, native_os
, native_lanman
, primary_domain
));
811 if ( ra_type
== RA_WIN2K
) {
812 if ( strlen(native_lanman
) == 0 )
813 ra_lanman_string( primary_domain
);
815 ra_lanman_string( native_lanman
);
820 if (SVAL(req
->vwv
+4, 0) == 0) {
821 setup_new_vc_session(req
->sconn
);
824 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
825 domain
, user
, get_remote_machine_name()));
828 if (sconn
->smb1
.negprot
.spnego
) {
830 /* This has to be here, because this is a perfectly
831 * valid behaviour for guest logons :-( */
833 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
834 "at 'normal' session setup after "
835 "negotiating spnego.\n"));
836 reply_nterror(req
, nt_status_squash(
837 NT_STATUS_LOGON_FAILURE
));
838 END_PROFILE(SMBsesssetupX
);
841 fstrcpy(sub_user
, user
);
843 fstrcpy(sub_user
, "");
846 sub_set_smb_name(sub_user
);
848 reload_services(sconn
, conn_snum_used
, true);
852 nt_status
= check_guest_password(sconn
->remote_address
, req
, &session_info
);
854 } else if (doencrypt
) {
855 struct auth4_context
*negprot_auth_context
= NULL
;
856 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
857 if (!negprot_auth_context
) {
858 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
859 "session setup without negprot denied!\n"));
860 reply_nterror(req
, nt_status_squash(
861 NT_STATUS_LOGON_FAILURE
));
862 END_PROFILE(SMBsesssetupX
);
865 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
867 sconn
->remote_address
,
869 if (NT_STATUS_IS_OK(nt_status
)) {
870 nt_status
= auth_check_password_session_info(negprot_auth_context
,
871 req
, user_info
, &session_info
);
874 struct auth4_context
*plaintext_auth_context
= NULL
;
876 nt_status
= make_auth4_context(
877 talloc_tos(), &plaintext_auth_context
);
879 if (NT_STATUS_IS_OK(nt_status
)) {
882 plaintext_auth_context
->get_ntlm_challenge(
883 plaintext_auth_context
, chal
);
885 if (!make_user_info_for_reply(&user_info
,
887 sconn
->remote_address
,
889 plaintext_password
)) {
890 nt_status
= NT_STATUS_NO_MEMORY
;
893 if (NT_STATUS_IS_OK(nt_status
)) {
894 nt_status
= auth_check_password_session_info(plaintext_auth_context
,
895 req
, user_info
, &session_info
);
897 TALLOC_FREE(plaintext_auth_context
);
901 free_user_info(&user_info
);
903 if (!NT_STATUS_IS_OK(nt_status
)) {
904 data_blob_free(&nt_resp
);
905 data_blob_free(&lm_resp
);
906 data_blob_clear_free(&plaintext_password
);
907 reply_nterror(req
, nt_status_squash(nt_status
));
908 END_PROFILE(SMBsesssetupX
);
912 data_blob_clear_free(&plaintext_password
);
914 /* it's ok - setup a reply */
915 reply_outbuf(req
, 3, 0);
916 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
917 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
919 if (get_Protocol() >= PROTOCOL_NT1
) {
920 push_signature(&req
->outbuf
);
921 /* perhaps grab OS version here?? */
924 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
928 /* register the name and uid as being validated, so further connections
929 to a uid can get through without a password, on the same VC */
931 nt_status
= smbXsrv_session_create(sconn
->conn
,
933 if (!NT_STATUS_IS_OK(nt_status
)) {
934 data_blob_free(&nt_resp
);
935 data_blob_free(&lm_resp
);
936 reply_nterror(req
, nt_status_squash(nt_status
));
937 END_PROFILE(SMBsesssetupX
);
941 if (session_info
->session_key
.length
> 0) {
942 uint8_t session_key
[16];
945 * Note: the SMB1 signing key is not truncated to 16 byte!
947 session
->global
->signing_key
=
948 data_blob_dup_talloc(session
->global
,
949 session_info
->session_key
);
950 if (session
->global
->signing_key
.data
== NULL
) {
951 data_blob_free(&nt_resp
);
952 data_blob_free(&lm_resp
);
953 TALLOC_FREE(session
);
954 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
955 END_PROFILE(SMBsesssetupX
);
960 * The application key is truncated/padded to 16 bytes
962 ZERO_STRUCT(session_key
);
963 memcpy(session_key
, session
->global
->signing_key
.data
,
964 MIN(session
->global
->signing_key
.length
,
965 sizeof(session_key
)));
966 session
->global
->application_key
=
967 data_blob_talloc(session
->global
,
969 sizeof(session_key
));
970 ZERO_STRUCT(session_key
);
971 if (session
->global
->application_key
.data
== NULL
) {
972 data_blob_free(&nt_resp
);
973 data_blob_free(&lm_resp
);
974 TALLOC_FREE(session
);
975 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
976 END_PROFILE(SMBsesssetupX
);
981 * Place the application key into the session_info
983 data_blob_clear_free(&session_info
->session_key
);
984 session_info
->session_key
= data_blob_dup_talloc(session_info
,
985 session
->global
->application_key
);
986 if (session_info
->session_key
.data
== NULL
) {
987 data_blob_free(&nt_resp
);
988 data_blob_free(&lm_resp
);
989 TALLOC_FREE(session
);
990 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
991 END_PROFILE(SMBsesssetupX
);
996 session
->compat
= talloc_zero(session
, struct user_struct
);
997 if (session
->compat
== NULL
) {
998 data_blob_free(&nt_resp
);
999 data_blob_free(&lm_resp
);
1000 TALLOC_FREE(session
);
1001 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1002 END_PROFILE(SMBsesssetupX
);
1005 session
->compat
->session
= session
;
1006 session
->compat
->homes_snum
= -1;
1007 session
->compat
->session_info
= session_info
;
1008 session
->compat
->session_keystr
= NULL
;
1009 session
->compat
->vuid
= session
->global
->session_wire_id
;
1010 DLIST_ADD(sconn
->users
, session
->compat
);
1013 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
1014 session
->compat
->homes_snum
=
1015 register_homes_share(session_info
->unix_info
->unix_name
);
1018 if (srv_is_signing_negotiated(sconn
) &&
1020 session
->global
->signing_key
.length
> 0)
1023 * Try and turn on server signing on the first non-guest
1026 srv_set_signing(sconn
,
1027 session
->global
->signing_key
,
1028 nt_resp
.data
? nt_resp
: lm_resp
);
1031 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1032 session_info
->unix_info
->unix_name
,
1033 session_info
->info
->domain_name
);
1035 session
->status
= NT_STATUS_OK
;
1036 session
->global
->auth_session_info
= talloc_move(session
->global
,
1038 session
->global
->auth_session_info_seqnum
+= 1;
1039 session
->global
->channels
[0].auth_session_info_seqnum
=
1040 session
->global
->auth_session_info_seqnum
;
1041 session
->global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1043 nt_status
= smbXsrv_session_update(session
);
1044 if (!NT_STATUS_IS_OK(nt_status
)) {
1045 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1046 (unsigned long long)session
->compat
->vuid
,
1047 nt_errstr(nt_status
)));
1048 data_blob_free(&nt_resp
);
1049 data_blob_free(&lm_resp
);
1050 TALLOC_FREE(session
);
1051 reply_nterror(req
, nt_status_squash(nt_status
));
1052 END_PROFILE(SMBsesssetupX
);
1056 if (!session_claim(session
)) {
1057 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1058 (unsigned long long)session
->compat
->vuid
));
1059 data_blob_free(&nt_resp
);
1060 data_blob_free(&lm_resp
);
1061 TALLOC_FREE(session
);
1062 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
1063 END_PROFILE(SMBsesssetupX
);
1067 /* current_user_info is changed on new vuid */
1068 reload_services(sconn
, conn_snum_used
, true);
1070 sess_vuid
= session
->global
->session_wire_id
;
1072 data_blob_free(&nt_resp
);
1073 data_blob_free(&lm_resp
);
1075 SSVAL(req
->outbuf
,smb_vwv2
,action
);
1076 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1077 SSVAL(discard_const_p(char, req
->inbuf
),smb_uid
,sess_vuid
);
1078 req
->vuid
= sess_vuid
;
1080 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
1081 sconn
->smb1
.sessions
.max_send
=
1082 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
1084 sconn
->smb1
.sessions
.done_sesssetup
= true;
1086 END_PROFILE(SMBsesssetupX
);