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
)
53 fstr_sprintf(native_os
, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION
,
54 SAMBA_MINOR_NBT_ANNOUNCE_VERSION
);
56 tmp
= message_push_string(outbuf
, native_os
, STR_TERMINATE
);
58 if (tmp
== -1) return -1;
61 if (asprintf(&lanman
, "Samba %s", samba_version_string()) != -1) {
62 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
66 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
69 if (tmp
== -1) return -1;
72 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
74 if (tmp
== -1) return -1;
80 /****************************************************************************
81 Do a 'guest' logon, getting back the
82 ****************************************************************************/
84 static NTSTATUS
check_guest_password(const struct tsocket_address
*remote_address
,
86 struct auth_session_info
**session_info
)
88 struct auth4_context
*auth_context
;
89 struct auth_usersupplied_info
*user_info
= NULL
;
93 DEBUG(3,("Got anonymous request\n"));
95 nt_status
= make_auth4_context(talloc_tos(), &auth_context
);
96 if (!NT_STATUS_IS_OK(nt_status
)) {
100 auth_context
->get_ntlm_challenge(auth_context
,
103 if (!make_user_info_guest(remote_address
, &user_info
)) {
104 TALLOC_FREE(auth_context
);
105 return NT_STATUS_NO_MEMORY
;
108 nt_status
= auth_check_password_session_info(auth_context
,
109 mem_ctx
, user_info
, session_info
);
110 free_user_info(&user_info
);
111 TALLOC_FREE(auth_context
);
115 /****************************************************************************
116 Reply to a session setup command.
117 conn POINTER CAN BE NULL HERE !
118 ****************************************************************************/
120 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
124 DATA_BLOB out_blob
= data_blob_null
;
127 const char *native_os
;
128 const char *native_lanman
;
129 const char *primary_domain
;
131 uint16 data_blob_len
= SVAL(req
->vwv
+7, 0);
132 enum remote_arch_types ra_type
= get_remote_arch();
133 uint64_t vuid
= req
->vuid
;
134 NTSTATUS status
= NT_STATUS_OK
;
135 struct smbd_server_connection
*sconn
= req
->sconn
;
137 NTTIME now
= timeval_to_nttime(&req
->request_time
);
138 struct smbXsrv_session
*session
= NULL
;
139 uint16_t smb_bufsize
= SVAL(req
->vwv
+2, 0);
140 uint32_t client_caps
= IVAL(req
->vwv
+10, 0);
142 DEBUG(3,("Doing spnego session setup\n"));
144 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
145 global_client_caps
= client_caps
;
147 if (!(global_client_caps
& CAP_STATUS32
)) {
148 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
154 if (data_blob_len
== 0) {
155 /* an invalid request */
156 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
160 bufrem
= smbreq_bufrem(req
, p
);
161 /* pull the spnego blob */
162 in_blob
= data_blob_const(p
, MIN(bufrem
, data_blob_len
));
165 file_save("negotiate.dat", in_blob
.data
, in_blob
.length
);
168 p2
= (const char *)req
->buf
+ in_blob
.length
;
170 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
172 native_os
= tmp
? tmp
: "";
174 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
176 native_lanman
= tmp
? tmp
: "";
178 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
180 primary_domain
= tmp
? tmp
: "";
182 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
183 native_os
, native_lanman
, primary_domain
));
185 if ( ra_type
== RA_WIN2K
) {
186 /* Vista sets neither the OS or lanman strings */
188 if ( !strlen(native_os
) && !strlen(native_lanman
) )
189 set_remote_arch(RA_VISTA
);
191 /* Windows 2003 doesn't set the native lanman string,
192 but does set primary domain which is a bug I think */
194 if ( !strlen(native_lanman
) ) {
195 ra_lanman_string( primary_domain
);
197 ra_lanman_string( native_lanman
);
199 } else if ( ra_type
== RA_VISTA
) {
200 if ( strncmp(native_os
, "Mac OS X", 8) == 0 ) {
201 set_remote_arch(RA_OSX
);
206 status
= smb1srv_session_lookup(sconn
->conn
,
209 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
210 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
213 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
214 status
= NT_STATUS_OK
;
216 if (NT_STATUS_IS_OK(status
)) {
217 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
218 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
219 TALLOC_FREE(session
->gensec
);
221 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
222 reply_nterror(req
, nt_status_squash(status
));
227 if (session
== NULL
) {
228 /* create a new session */
229 status
= smbXsrv_session_create(sconn
->conn
,
231 if (!NT_STATUS_IS_OK(status
)) {
232 reply_nterror(req
, nt_status_squash(status
));
237 if (!session
->gensec
) {
238 status
= auth_generic_prepare(session
, sconn
->remote_address
,
240 if (!NT_STATUS_IS_OK(status
)) {
241 TALLOC_FREE(session
);
242 reply_nterror(req
, nt_status_squash(status
));
246 gensec_want_feature(session
->gensec
, GENSEC_FEATURE_SESSION_KEY
);
247 gensec_want_feature(session
->gensec
, GENSEC_FEATURE_UNIX_TOKEN
);
249 status
= gensec_start_mech_by_oid(session
->gensec
,
251 if (!NT_STATUS_IS_OK(status
)) {
252 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
253 TALLOC_FREE(session
);;
254 reply_nterror(req
, nt_status_squash(status
));
260 status
= gensec_update(session
->gensec
,
264 if (!NT_STATUS_IS_OK(status
) &&
265 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
266 TALLOC_FREE(session
);
267 reply_nterror(req
, nt_status_squash(status
));
271 if (NT_STATUS_IS_OK(status
) && session
->global
->auth_session_info
== NULL
) {
272 struct auth_session_info
*session_info
= NULL
;
274 status
= gensec_session_info(session
->gensec
,
277 if (!NT_STATUS_IS_OK(status
)) {
278 DEBUG(1,("Failed to generate session_info "
279 "(user and group token) for session setup: %s\n",
281 data_blob_free(&out_blob
);
282 TALLOC_FREE(session
);
283 reply_nterror(req
, nt_status_squash(status
));
287 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
291 if (session_info
->session_key
.length
> 0) {
292 struct smbXsrv_session
*x
= session
;
295 * Note: the SMB1 signing key is not truncated to 16 byte!
297 x
->global
->signing_key
=
298 data_blob_dup_talloc(x
->global
,
299 session_info
->session_key
);
300 if (x
->global
->signing_key
.data
== NULL
) {
301 data_blob_free(&out_blob
);
302 TALLOC_FREE(session
);
303 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
308 * clear the session key
309 * the first tcon will add setup the application key
311 data_blob_clear_free(&session_info
->session_key
);
314 session
->compat
= talloc_zero(session
, struct user_struct
);
315 if (session
->compat
== NULL
) {
316 data_blob_free(&out_blob
);
317 TALLOC_FREE(session
);
318 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
321 session
->compat
->session
= session
;
322 session
->compat
->homes_snum
= -1;
323 session
->compat
->session_info
= session_info
;
324 session
->compat
->session_keystr
= NULL
;
325 session
->compat
->vuid
= session
->global
->session_wire_id
;
326 DLIST_ADD(sconn
->users
, session
->compat
);
329 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
330 session
->compat
->homes_snum
=
331 register_homes_share(session_info
->unix_info
->unix_name
);
334 if (srv_is_signing_negotiated(sconn
) &&
336 session
->global
->signing_key
.length
> 0)
339 * Try and turn on server signing on the first non-guest
342 srv_set_signing(sconn
,
343 session
->global
->signing_key
,
347 set_current_user_info(session_info
->unix_info
->sanitized_username
,
348 session_info
->unix_info
->unix_name
,
349 session_info
->info
->domain_name
);
351 session
->status
= NT_STATUS_OK
;
352 session
->global
->auth_session_info
= talloc_move(session
->global
,
354 session
->global
->auth_session_info_seqnum
+= 1;
355 session
->global
->channels
[0].auth_session_info_seqnum
=
356 session
->global
->auth_session_info_seqnum
;
357 if (client_caps
& CAP_DYNAMIC_REAUTH
) {
358 session
->global
->expiration_time
=
359 gensec_expire_time(session
->gensec
);
361 session
->global
->expiration_time
=
362 GENSEC_EXPIRE_TIME_INFINITY
;
365 if (!session_claim(session
)) {
366 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
367 (unsigned long long)session
->compat
->vuid
));
368 data_blob_free(&out_blob
);
369 TALLOC_FREE(session
);
370 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
374 status
= smbXsrv_session_update(session
);
375 if (!NT_STATUS_IS_OK(status
)) {
376 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
377 (unsigned long long)session
->compat
->vuid
,
379 data_blob_free(&out_blob
);
380 TALLOC_FREE(session
);
381 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
385 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
386 sconn
->smb1
.sessions
.max_send
=
387 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
389 sconn
->smb1
.sessions
.done_sesssetup
= true;
391 /* current_user_info is changed on new vuid */
392 reload_services(sconn
, conn_snum_used
, true);
393 } else if (NT_STATUS_IS_OK(status
)) {
394 struct auth_session_info
*session_info
= NULL
;
396 status
= gensec_session_info(session
->gensec
,
399 if (!NT_STATUS_IS_OK(status
)) {
400 DEBUG(1,("Failed to generate session_info "
401 "(user and group token) for session setup: %s\n",
403 data_blob_free(&out_blob
);
404 TALLOC_FREE(session
);
405 reply_nterror(req
, nt_status_squash(status
));
409 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
414 * Keep the application key
416 data_blob_clear_free(&session_info
->session_key
);
417 session_info
->session_key
=
418 session
->global
->auth_session_info
->session_key
;
419 talloc_steal(session_info
, session_info
->session_key
.data
);
420 TALLOC_FREE(session
->global
->auth_session_info
);
422 session
->compat
->session_info
= session_info
;
424 session
->compat
->vuid
= session
->global
->session_wire_id
;
426 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
427 session
->compat
->homes_snum
=
428 register_homes_share(session_info
->unix_info
->unix_name
);
431 set_current_user_info(session_info
->unix_info
->sanitized_username
,
432 session_info
->unix_info
->unix_name
,
433 session_info
->info
->domain_name
);
435 session
->status
= NT_STATUS_OK
;
436 session
->global
->auth_session_info
= talloc_move(session
->global
,
438 session
->global
->auth_session_info_seqnum
+= 1;
439 session
->global
->channels
[0].auth_session_info_seqnum
=
440 session
->global
->auth_session_info_seqnum
;
441 if (client_caps
& CAP_DYNAMIC_REAUTH
) {
442 session
->global
->expiration_time
=
443 gensec_expire_time(session
->gensec
);
445 session
->global
->expiration_time
=
446 GENSEC_EXPIRE_TIME_INFINITY
;
449 status
= smbXsrv_session_update(session
);
450 if (!NT_STATUS_IS_OK(status
)) {
451 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
452 (unsigned long long)session
->compat
->vuid
,
454 data_blob_free(&out_blob
);
455 TALLOC_FREE(session
);
456 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
460 conn_clear_vuid_caches(sconn
, session
->compat
->vuid
);
462 /* current_user_info is changed on new vuid */
463 reload_services(sconn
, conn_snum_used
, true);
466 vuid
= session
->global
->session_wire_id
;
468 reply_outbuf(req
, 4, 0);
470 SSVAL(req
->outbuf
, smb_uid
, vuid
);
471 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(status
));
472 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
473 SSVAL(req
->outbuf
, smb_vwv2
, action
);
474 SSVAL(req
->outbuf
, smb_vwv3
, out_blob
.length
);
476 if (message_push_blob(&req
->outbuf
, out_blob
) == -1) {
477 data_blob_free(&out_blob
);
478 TALLOC_FREE(session
);
479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
482 data_blob_free(&out_blob
);
484 if (push_signature(&req
->outbuf
) == -1) {
485 TALLOC_FREE(session
);
486 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
491 /****************************************************************************
492 On new VC == 0, shutdown *all* old connections and users.
493 It seems that only NT4.x does this. At W2K and above (XP etc.).
494 a new session setup with VC==0 is ignored.
495 ****************************************************************************/
497 struct shutdown_state
{
499 struct messaging_context
*msg_ctx
;
502 static int shutdown_other_smbds(struct smbXsrv_session_global0
*session
,
505 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
506 struct server_id self_pid
= messaging_server_id(state
->msg_ctx
);
507 struct server_id pid
= session
->channels
[0].server_id
;
508 const char *addr
= session
->channels
[0].remote_address
;
510 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
511 server_id_str(talloc_tos(), &pid
), addr
));
513 if (!process_exists(pid
)) {
514 DEBUG(10, ("process does not exist\n"));
518 if (serverid_equal(&pid
, &self_pid
)) {
519 DEBUG(10, ("It's me\n"));
524 * here we use strstr() because 'addr'
525 * (session->channels[0].remote_address)
526 * contains a string like:
527 * 'ipv4:127.0.0.1:48163'
529 if (strstr(addr
, state
->ip
) == NULL
) {
530 DEBUG(10, ("%s does not match %s\n", state
->ip
, addr
));
534 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
535 "(IP %s)\n", (unsigned int)procid_to_pid(&pid
),
538 messaging_send(state
->msg_ctx
, pid
, MSG_SHUTDOWN
,
543 static void setup_new_vc_session(struct smbd_server_connection
*sconn
)
545 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
546 "compatible we would close all old resources.\n"));
549 invalidate_all_vuids();
551 if (lp_reset_on_zero_vc()) {
553 struct shutdown_state state
;
555 addr
= tsocket_address_inet_addr_string(
556 sconn
->remote_address
, talloc_tos());
561 state
.msg_ctx
= sconn
->msg_ctx
;
562 smbXsrv_session_global_traverse(shutdown_other_smbds
, &state
);
567 /****************************************************************************
568 Reply to a session setup command.
569 ****************************************************************************/
571 void reply_sesssetup_and_X(struct smb_request
*req
)
574 uint16_t smb_bufsize
;
577 DATA_BLOB plaintext_password
;
580 fstring sub_user
; /* Sanitised username for substituion */
582 const char *native_os
;
583 const char *native_lanman
;
584 const char *primary_domain
;
585 struct auth_usersupplied_info
*user_info
= NULL
;
586 struct auth_session_info
*session_info
= NULL
;
587 uint16 smb_flag2
= req
->flags2
;
589 NTTIME now
= timeval_to_nttime(&req
->request_time
);
590 struct smbXsrv_session
*session
= NULL
;
593 struct smbd_server_connection
*sconn
= req
->sconn
;
595 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
596 bool signing_allowed
= false;
597 bool signing_mandatory
= false;
599 START_PROFILE(SMBsesssetupX
);
601 ZERO_STRUCT(lm_resp
);
602 ZERO_STRUCT(nt_resp
);
603 ZERO_STRUCT(plaintext_password
);
605 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
607 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES
) {
608 signing_allowed
= true;
610 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
) {
611 signing_mandatory
= true;
615 * We can call srv_set_signing_negotiated() each time.
616 * It finds out when it needs to turn into a noop
619 srv_set_signing_negotiated(req
->sconn
,
623 /* a SPNEGO session setup has 12 command words, whereas a normal
624 NT1 session setup has 13. See the cifs spec. */
625 if (req
->wct
== 12 &&
626 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
628 if (!sconn
->smb1
.negprot
.spnego
) {
629 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
630 "at SPNEGO session setup when it was not "
632 reply_nterror(req
, nt_status_squash(
633 NT_STATUS_LOGON_FAILURE
));
634 END_PROFILE(SMBsesssetupX
);
638 if (SVAL(req
->vwv
+4, 0) == 0) {
639 setup_new_vc_session(req
->sconn
);
642 reply_sesssetup_and_X_spnego(req
);
643 END_PROFILE(SMBsesssetupX
);
647 smb_bufsize
= SVAL(req
->vwv
+2, 0);
649 if (get_Protocol() < PROTOCOL_NT1
) {
650 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
652 /* Never do NT status codes with protocols before NT1 as we
653 * don't get client caps. */
654 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
656 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
657 reply_nterror(req
, nt_status_squash(
658 NT_STATUS_INVALID_PARAMETER
));
659 END_PROFILE(SMBsesssetupX
);
664 lm_resp
= data_blob(req
->buf
, passlen1
);
666 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
667 /* Ensure null termination */
668 plaintext_password
.data
[passlen1
] = 0;
671 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
672 req
->buf
+ passlen1
, STR_TERMINATE
);
673 user
= tmp
? tmp
: "";
678 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
679 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
680 enum remote_arch_types ra_type
= get_remote_arch();
681 const uint8_t *p
= req
->buf
;
682 const uint8_t *save_p
= req
->buf
;
685 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
686 global_client_caps
= IVAL(req
->vwv
+11, 0);
688 if (!(global_client_caps
& CAP_STATUS32
)) {
689 remove_from_common_flags2(
690 FLAGS2_32_BIT_ERROR_CODES
);
693 /* client_caps is used as final determination if
694 * client is NT or Win95. This is needed to return
695 * the correct error codes in some circumstances.
698 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
699 ra_type
== RA_WIN95
) {
700 if(!(global_client_caps
& (CAP_NT_SMBS
|
702 set_remote_arch( RA_WIN95
);
708 /* both Win95 and WinNT stuff up the password
709 * lengths for non-encrypting systems. Uggh.
711 if passlen1==24 its a win95 system, and its setting
712 the password length incorrectly. Luckily it still
713 works with the default code because Win95 will null
714 terminate the password anyway
716 if passlen1>0 and passlen2>0 then maybe its a NT box
717 and its setting passlen2 to some random value which
718 really stuffs things up. we need to fix that one. */
720 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
726 /* check for nasty tricks */
727 if (passlen1
> MAX_PASS_LEN
728 || passlen1
> smbreq_bufrem(req
, p
)) {
729 reply_nterror(req
, nt_status_squash(
730 NT_STATUS_INVALID_PARAMETER
));
731 END_PROFILE(SMBsesssetupX
);
735 if (passlen2
> MAX_PASS_LEN
736 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
737 reply_nterror(req
, nt_status_squash(
738 NT_STATUS_INVALID_PARAMETER
));
739 END_PROFILE(SMBsesssetupX
);
743 /* Save the lanman2 password and the NT md4 password. */
745 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
750 lm_resp
= data_blob(p
, passlen1
);
751 nt_resp
= data_blob(p
+passlen1
, passlen2
);
754 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
756 if (unic
&& (passlen2
== 0) && passlen1
) {
757 /* Only a ascii plaintext password was sent. */
758 (void)srvstr_pull_talloc(talloc_tos(),
764 STR_TERMINATE
|STR_ASCII
);
766 (void)srvstr_pull_talloc(talloc_tos(),
771 unic
? passlen2
: passlen1
,
775 reply_nterror(req
, nt_status_squash(
776 NT_STATUS_INVALID_PARAMETER
));
777 END_PROFILE(SMBsesssetupX
);
780 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
783 p
+= passlen1
+ passlen2
;
785 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
787 user
= tmp
? tmp
: "";
789 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
791 domain
= tmp
? tmp
: "";
793 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
795 native_os
= tmp
? tmp
: "";
797 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
799 native_lanman
= tmp
? tmp
: "";
801 /* not documented or decoded by Ethereal but there is one more
802 * string in the extra bytes which is the same as the
803 * PrimaryDomain when using extended security. Windows NT 4
804 * and 2003 use this string to store the native lanman string.
805 * Windows 9x does not include a string here at all so we have
806 * to check if we have any extra bytes left */
808 byte_count
= SVAL(req
->vwv
+13, 0);
809 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
810 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
812 primary_domain
= tmp
? tmp
: "";
814 primary_domain
= talloc_strdup(talloc_tos(), "null");
817 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
818 "PrimaryDomain=[%s]\n",
819 domain
, native_os
, native_lanman
, primary_domain
));
821 if ( ra_type
== RA_WIN2K
) {
822 if ( strlen(native_lanman
) == 0 )
823 ra_lanman_string( primary_domain
);
825 ra_lanman_string( native_lanman
);
830 if (SVAL(req
->vwv
+4, 0) == 0) {
831 setup_new_vc_session(req
->sconn
);
834 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
835 domain
, user
, get_remote_machine_name()));
838 if (sconn
->smb1
.negprot
.spnego
) {
840 /* This has to be here, because this is a perfectly
841 * valid behaviour for guest logons :-( */
843 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
844 "at 'normal' session setup after "
845 "negotiating spnego.\n"));
846 reply_nterror(req
, nt_status_squash(
847 NT_STATUS_LOGON_FAILURE
));
848 END_PROFILE(SMBsesssetupX
);
851 fstrcpy(sub_user
, user
);
853 fstrcpy(sub_user
, "");
856 sub_set_smb_name(sub_user
);
858 reload_services(sconn
, conn_snum_used
, true);
862 nt_status
= check_guest_password(sconn
->remote_address
, req
, &session_info
);
864 } else if (doencrypt
) {
865 struct auth4_context
*negprot_auth_context
= NULL
;
866 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
867 if (!negprot_auth_context
) {
868 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
869 "session setup without negprot denied!\n"));
870 reply_nterror(req
, nt_status_squash(
871 NT_STATUS_LOGON_FAILURE
));
872 END_PROFILE(SMBsesssetupX
);
875 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
877 sconn
->remote_address
,
879 if (NT_STATUS_IS_OK(nt_status
)) {
880 nt_status
= auth_check_password_session_info(negprot_auth_context
,
881 req
, user_info
, &session_info
);
884 struct auth4_context
*plaintext_auth_context
= NULL
;
886 nt_status
= make_auth4_context(
887 talloc_tos(), &plaintext_auth_context
);
889 if (NT_STATUS_IS_OK(nt_status
)) {
892 plaintext_auth_context
->get_ntlm_challenge(
893 plaintext_auth_context
, chal
);
895 if (!make_user_info_for_reply(&user_info
,
897 sconn
->remote_address
,
899 plaintext_password
)) {
900 nt_status
= NT_STATUS_NO_MEMORY
;
903 if (NT_STATUS_IS_OK(nt_status
)) {
904 nt_status
= auth_check_password_session_info(plaintext_auth_context
,
905 req
, user_info
, &session_info
);
907 TALLOC_FREE(plaintext_auth_context
);
911 free_user_info(&user_info
);
913 if (!NT_STATUS_IS_OK(nt_status
)) {
914 data_blob_free(&nt_resp
);
915 data_blob_free(&lm_resp
);
916 data_blob_clear_free(&plaintext_password
);
917 reply_nterror(req
, nt_status_squash(nt_status
));
918 END_PROFILE(SMBsesssetupX
);
922 data_blob_clear_free(&plaintext_password
);
924 /* it's ok - setup a reply */
925 reply_outbuf(req
, 3, 0);
926 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
927 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
929 if (get_Protocol() >= PROTOCOL_NT1
) {
930 push_signature(&req
->outbuf
);
931 /* perhaps grab OS version here?? */
934 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
938 /* register the name and uid as being validated, so further connections
939 to a uid can get through without a password, on the same VC */
941 nt_status
= smbXsrv_session_create(sconn
->conn
,
943 if (!NT_STATUS_IS_OK(nt_status
)) {
944 data_blob_free(&nt_resp
);
945 data_blob_free(&lm_resp
);
946 reply_nterror(req
, nt_status_squash(nt_status
));
947 END_PROFILE(SMBsesssetupX
);
951 if (session_info
->session_key
.length
> 0) {
952 uint8_t session_key
[16];
955 * Note: the SMB1 signing key is not truncated to 16 byte!
957 session
->global
->signing_key
=
958 data_blob_dup_talloc(session
->global
,
959 session_info
->session_key
);
960 if (session
->global
->signing_key
.data
== NULL
) {
961 data_blob_free(&nt_resp
);
962 data_blob_free(&lm_resp
);
963 TALLOC_FREE(session
);
964 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
965 END_PROFILE(SMBsesssetupX
);
970 * The application key is truncated/padded to 16 bytes
972 ZERO_STRUCT(session_key
);
973 memcpy(session_key
, session
->global
->signing_key
.data
,
974 MIN(session
->global
->signing_key
.length
,
975 sizeof(session_key
)));
976 session
->global
->application_key
=
977 data_blob_talloc(session
->global
,
979 sizeof(session_key
));
980 ZERO_STRUCT(session_key
);
981 if (session
->global
->application_key
.data
== NULL
) {
982 data_blob_free(&nt_resp
);
983 data_blob_free(&lm_resp
);
984 TALLOC_FREE(session
);
985 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
986 END_PROFILE(SMBsesssetupX
);
991 * Place the application key into the session_info
993 data_blob_clear_free(&session_info
->session_key
);
994 session_info
->session_key
= data_blob_dup_talloc(session_info
,
995 session
->global
->application_key
);
996 if (session_info
->session_key
.data
== NULL
) {
997 data_blob_free(&nt_resp
);
998 data_blob_free(&lm_resp
);
999 TALLOC_FREE(session
);
1000 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1001 END_PROFILE(SMBsesssetupX
);
1006 session
->compat
= talloc_zero(session
, struct user_struct
);
1007 if (session
->compat
== NULL
) {
1008 data_blob_free(&nt_resp
);
1009 data_blob_free(&lm_resp
);
1010 TALLOC_FREE(session
);
1011 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1012 END_PROFILE(SMBsesssetupX
);
1015 session
->compat
->session
= session
;
1016 session
->compat
->homes_snum
= -1;
1017 session
->compat
->session_info
= session_info
;
1018 session
->compat
->session_keystr
= NULL
;
1019 session
->compat
->vuid
= session
->global
->session_wire_id
;
1020 DLIST_ADD(sconn
->users
, session
->compat
);
1023 if (security_session_user_level(session_info
, NULL
) >= SECURITY_USER
) {
1024 session
->compat
->homes_snum
=
1025 register_homes_share(session_info
->unix_info
->unix_name
);
1028 if (srv_is_signing_negotiated(sconn
) &&
1030 session
->global
->signing_key
.length
> 0)
1033 * Try and turn on server signing on the first non-guest
1036 srv_set_signing(sconn
,
1037 session
->global
->signing_key
,
1038 nt_resp
.data
? nt_resp
: lm_resp
);
1041 set_current_user_info(session_info
->unix_info
->sanitized_username
,
1042 session_info
->unix_info
->unix_name
,
1043 session_info
->info
->domain_name
);
1045 session
->status
= NT_STATUS_OK
;
1046 session
->global
->auth_session_info
= talloc_move(session
->global
,
1048 session
->global
->auth_session_info_seqnum
+= 1;
1049 session
->global
->channels
[0].auth_session_info_seqnum
=
1050 session
->global
->auth_session_info_seqnum
;
1051 session
->global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1053 nt_status
= smbXsrv_session_update(session
);
1054 if (!NT_STATUS_IS_OK(nt_status
)) {
1055 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1056 (unsigned long long)session
->compat
->vuid
,
1057 nt_errstr(nt_status
)));
1058 data_blob_free(&nt_resp
);
1059 data_blob_free(&lm_resp
);
1060 TALLOC_FREE(session
);
1061 reply_nterror(req
, nt_status_squash(nt_status
));
1062 END_PROFILE(SMBsesssetupX
);
1066 if (!session_claim(session
)) {
1067 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1068 (unsigned long long)session
->compat
->vuid
));
1069 data_blob_free(&nt_resp
);
1070 data_blob_free(&lm_resp
);
1071 TALLOC_FREE(session
);
1072 reply_nterror(req
, NT_STATUS_LOGON_FAILURE
);
1073 END_PROFILE(SMBsesssetupX
);
1077 /* current_user_info is changed on new vuid */
1078 reload_services(sconn
, conn_snum_used
, true);
1080 sess_vuid
= session
->global
->session_wire_id
;
1082 data_blob_free(&nt_resp
);
1083 data_blob_free(&lm_resp
);
1085 SSVAL(req
->outbuf
,smb_vwv2
,action
);
1086 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1087 SSVAL(discard_const_p(char, req
->inbuf
),smb_uid
,sess_vuid
);
1088 req
->vuid
= sess_vuid
;
1090 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
1091 sconn
->smb1
.sessions
.max_send
=
1092 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
1094 sconn
->smb1
.sessions
.done_sesssetup
= true;
1096 END_PROFILE(SMBsesssetupX
);