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 "smbd/globals.h"
27 #include "../libcli/auth/spnego.h"
29 #include "librpc/gen_ndr/messaging.h"
31 /* For split krb5 SPNEGO blobs. */
32 struct pending_auth_data
{
33 struct pending_auth_data
*prev
, *next
;
34 uint16 vuid
; /* Tag for this entry. */
35 uint16 smbpid
; /* Alternate tag for this entry. */
37 DATA_BLOB partial_data
;
41 on a logon error possibly map the error to success if "map to guest"
44 static NTSTATUS
do_map_to_guest(NTSTATUS status
,
45 struct auth_serversupplied_info
**server_info
,
46 const char *user
, const char *domain
)
48 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
49 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
50 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
51 DEBUG(3,("No such user %s [%s] - using guest account\n",
53 status
= make_server_info_guest(NULL
, server_info
);
57 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
58 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
59 DEBUG(3,("Registered username %s for guest access\n",
61 status
= make_server_info_guest(NULL
, server_info
);
68 /****************************************************************************
69 Add the standard 'Samba' signature to the end of the session setup.
70 ****************************************************************************/
72 static int push_signature(uint8
**outbuf
)
79 tmp
= message_push_string(outbuf
, "Unix", STR_TERMINATE
);
81 if (tmp
== -1) return -1;
84 if (asprintf(&lanman
, "Samba %s", samba_version_string()) != -1) {
85 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
89 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
92 if (tmp
== -1) return -1;
95 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
97 if (tmp
== -1) return -1;
103 /****************************************************************************
104 Send a security blob via a session setup reply.
105 ****************************************************************************/
107 static void reply_sesssetup_blob(struct smb_request
*req
,
111 if (!NT_STATUS_IS_OK(nt_status
) &&
112 !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
113 reply_nterror(req
, nt_status_squash(nt_status
));
117 nt_status
= nt_status_squash(nt_status
);
118 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
119 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
120 SSVAL(req
->outbuf
, smb_vwv3
, blob
.length
);
122 if ((message_push_blob(&req
->outbuf
, blob
) == -1)
123 || (push_signature(&req
->outbuf
) == -1)) {
124 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS
check_guest_password(struct auth_serversupplied_info
**server_info
)
134 struct auth_context
*auth_context
;
135 struct auth_usersupplied_info
*user_info
= NULL
;
138 unsigned char chal
[8];
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status
= make_auth_context_fixed(&auth_context
,
149 if (!make_user_info_guest(&user_info
)) {
150 (auth_context
->free
)(&auth_context
);
151 return NT_STATUS_NO_MEMORY
;
154 nt_status
= auth_context
->check_ntlm_password(auth_context
,
157 (auth_context
->free
)(&auth_context
);
158 free_user_info(&user_info
);
166 /* Experiment that failed. See "only happens with a KDC" comment below. */
167 /****************************************************************************
168 Cerate a clock skew error blob for a Windows client.
169 ****************************************************************************/
171 static bool make_krb5_skew_error(DATA_BLOB
*pblob_out
)
173 krb5_context context
= NULL
;
174 krb5_error_code kerr
= 0;
176 krb5_principal host_princ
= NULL
;
177 char *host_princ_s
= NULL
;
180 *pblob_out
= data_blob_null
;
182 initialize_krb5_error_table();
183 kerr
= krb5_init_context(&context
);
187 /* Create server principal. */
188 asprintf(&host_princ_s
, "%s$@%s", global_myname(), lp_realm());
192 strlower_m(host_princ_s
);
194 kerr
= smb_krb5_parse_name(context
, host_princ_s
, &host_princ
);
196 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
197 "for name %s: Error %s\n",
198 host_princ_s
, error_message(kerr
) ));
202 kerr
= smb_krb5_mk_error(context
, KRB5KRB_AP_ERR_SKEW
,
205 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
206 "failed: Error %s\n",
207 error_message(kerr
) ));
211 *pblob_out
= data_blob(reply
.data
, reply
.length
);
212 kerberos_free_data_contents(context
,&reply
);
218 SAFE_FREE(host_princ_s
);
221 krb5_free_principal(context
, host_princ
);
223 krb5_free_context(context
);
228 /****************************************************************************
229 Reply to a session setup spnego negotiate packet for kerberos.
230 ****************************************************************************/
232 static void reply_spnego_kerberos(struct smb_request
*req
,
236 bool *p_invalidate_vuid
)
240 char *client
, *p
, *domain
;
241 fstring netbios_domain_name
;
244 int sess_vuid
= req
->vuid
;
245 NTSTATUS ret
= NT_STATUS_OK
;
246 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
247 struct auth_serversupplied_info
*server_info
= NULL
;
248 DATA_BLOB session_key
= data_blob_null
;
250 DATA_BLOB nullblob
= data_blob_null
;
251 fstring real_username
;
252 bool map_domainuser_to_guest
= False
;
253 bool username_was_mapped
;
254 struct PAC_LOGON_INFO
*logon_info
= NULL
;
255 struct smbd_server_connection
*sconn
= smbd_server_conn
;
259 ZERO_STRUCT(ap_rep_wrapped
);
260 ZERO_STRUCT(response
);
262 /* Normally we will always invalidate the intermediate vuid. */
263 *p_invalidate_vuid
= True
;
265 mem_ctx
= talloc_init("reply_spnego_kerberos");
266 if (mem_ctx
== NULL
) {
267 reply_nterror(req
, nt_status_squash(NT_STATUS_NO_MEMORY
));
271 if (!spnego_parse_krb5_wrap(*secblob
, &ticket
, tok_id
)) {
272 talloc_destroy(mem_ctx
);
273 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
277 ret
= ads_verify_ticket(mem_ctx
, lp_realm(), 0, &ticket
,
278 &client
, &logon_info
, &ap_rep
,
281 data_blob_free(&ticket
);
283 if (!NT_STATUS_IS_OK(ret
)) {
285 /* Experiment that failed.
286 * See "only happens with a KDC" comment below. */
288 if (NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
291 * Windows in this case returns
292 * NT_STATUS_MORE_PROCESSING_REQUIRED
293 * with a negTokenTarg blob containing an krb5_error
294 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
295 * The client then fixes its clock and continues rather
296 * than giving an error. JRA.
297 * -- Looks like this only happens with a KDC. JRA.
300 bool ok
= make_krb5_skew_error(&ap_rep
);
302 talloc_destroy(mem_ctx
);
303 return ERROR_NT(nt_status_squash(
304 NT_STATUS_LOGON_FAILURE
));
306 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
308 response
= spnego_gen_auth_response(&ap_rep_wrapped
,
309 ret
, OID_KERBEROS5_OLD
);
310 reply_sesssetup_blob(conn
, inbuf
, outbuf
, response
,
311 NT_STATUS_MORE_PROCESSING_REQUIRED
);
314 * In this one case we don't invalidate the
315 * intermediate vuid as we're expecting the client
316 * to re-use it for the next sessionsetupX packet. JRA.
319 *p_invalidate_vuid
= False
;
321 data_blob_free(&ap_rep
);
322 data_blob_free(&ap_rep_wrapped
);
323 data_blob_free(&response
);
324 talloc_destroy(mem_ctx
);
325 return -1; /* already replied */
328 if (!NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
329 ret
= NT_STATUS_LOGON_FAILURE
;
332 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
334 talloc_destroy(mem_ctx
);
335 reply_nterror(req
, nt_status_squash(ret
));
339 DEBUG(3,("Ticket name is [%s]\n", client
));
341 p
= strchr_m(client
, '@');
343 DEBUG(3,("Doesn't look like a valid principal\n"));
344 data_blob_free(&ap_rep
);
345 data_blob_free(&session_key
);
346 talloc_destroy(mem_ctx
);
347 reply_nterror(req
,nt_status_squash(NT_STATUS_LOGON_FAILURE
));
353 /* save the PAC data if we have it */
356 netsamlogon_cache_store( client
, &logon_info
->info3
);
359 if (!strequal(p
+1, lp_realm())) {
360 DEBUG(3,("Ticket for foreign realm %s@%s\n", client
, p
+1));
361 if (!lp_allow_trusted_domains()) {
362 data_blob_free(&ap_rep
);
363 data_blob_free(&session_key
);
364 talloc_destroy(mem_ctx
);
365 reply_nterror(req
, nt_status_squash(
366 NT_STATUS_LOGON_FAILURE
));
371 /* this gives a fully qualified user name (ie. with full realm).
372 that leads to very long usernames, but what else can we do? */
376 if (logon_info
&& logon_info
->info3
.base
.domain
.string
) {
377 fstrcpy(netbios_domain_name
,
378 logon_info
->info3
.base
.domain
.string
);
379 domain
= netbios_domain_name
;
380 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain
));
384 /* If we have winbind running, we can (and must) shorten the
385 username by using the short netbios name. Otherwise we will
386 have inconsistent user names. With Kerberos, we get the
387 fully qualified realm, with ntlmssp we get the short
388 name. And even w2k3 does use ntlmssp if you for example
389 connect to an ip address. */
392 struct wbcDomainInfo
*info
= NULL
;
394 DEBUG(10, ("Mapping [%s] to short name\n", domain
));
396 wbc_status
= wbcDomainInfo(domain
, &info
);
398 if (WBC_ERROR_IS_OK(wbc_status
)) {
400 fstrcpy(netbios_domain_name
,
404 domain
= netbios_domain_name
;
405 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain
));
407 DEBUG(3, ("Could not find short name: %s\n",
408 wbcErrorString(wbc_status
)));
412 fstr_sprintf(user
, "%s%c%s", domain
, *lp_winbind_separator(), client
);
414 /* lookup the passwd struct, create a new user if necessary */
416 username_was_mapped
= map_username(sconn
, user
);
418 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
421 /* if a real user check pam account restrictions */
422 /* only really perfomed if "obey pam restriction" is true */
423 /* do this before an eventual mapping to guest occurs */
424 ret
= smb_pam_accountcheck(pw
->pw_name
);
425 if ( !NT_STATUS_IS_OK(ret
)) {
426 DEBUG(1,("PAM account restriction "
427 "prevents user login\n"));
428 data_blob_free(&ap_rep
);
429 data_blob_free(&session_key
);
430 TALLOC_FREE(mem_ctx
);
431 reply_nterror(req
, nt_status_squash(ret
));
438 /* this was originally the behavior of Samba 2.2, if a user
439 did not have a local uid but has been authenticated, then
440 map them to a guest account */
442 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID
){
443 map_domainuser_to_guest
= True
;
444 fstrcpy(user
,lp_guestaccount());
445 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
448 /* extra sanity check that the guest account is valid */
451 DEBUG(1,("Username %s is invalid on this system\n",
453 data_blob_free(&ap_rep
);
454 data_blob_free(&session_key
);
455 TALLOC_FREE(mem_ctx
);
456 reply_nterror(req
, nt_status_squash(
457 NT_STATUS_LOGON_FAILURE
));
462 /* setup the string used by %U */
464 sub_set_smb_name( real_username
);
465 reload_services(True
);
467 if ( map_domainuser_to_guest
) {
468 make_server_info_guest(NULL
, &server_info
);
469 } else if (logon_info
) {
470 /* pass the unmapped username here since map_username()
471 will be called again from inside make_server_info_info3() */
473 ret
= make_server_info_info3(mem_ctx
, client
, domain
,
474 &server_info
, &logon_info
->info3
);
475 if ( !NT_STATUS_IS_OK(ret
) ) {
476 DEBUG(1,("make_server_info_info3 failed: %s!\n",
478 data_blob_free(&ap_rep
);
479 data_blob_free(&session_key
);
480 TALLOC_FREE(mem_ctx
);
481 reply_nterror(req
, nt_status_squash(ret
));
487 * We didn't get a PAC, we have to make up the user
488 * ourselves. Try to ask the pdb backend to provide
489 * SID consistency with ntlmssp session setup
491 struct samu
*sampass
;
493 sampass
= samu_new(talloc_tos());
494 if (sampass
== NULL
) {
495 ret
= NT_STATUS_NO_MEMORY
;
496 data_blob_free(&ap_rep
);
497 data_blob_free(&session_key
);
498 TALLOC_FREE(mem_ctx
);
499 reply_nterror(req
, nt_status_squash(ret
));
503 if (pdb_getsampwnam(sampass
, real_username
)) {
504 DEBUG(10, ("found user %s in passdb, calling "
505 "make_server_info_sam\n", real_username
));
506 ret
= make_server_info_sam(&server_info
, sampass
);
507 TALLOC_FREE(sampass
);
510 * User not in passdb, make it up artificially
512 TALLOC_FREE(sampass
);
513 DEBUG(10, ("didn't find user %s in passdb, calling "
514 "make_server_info_pw\n", real_username
));
515 ret
= make_server_info_pw(&server_info
, real_username
,
519 if ( !NT_STATUS_IS_OK(ret
) ) {
520 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
522 data_blob_free(&ap_rep
);
523 data_blob_free(&session_key
);
524 TALLOC_FREE(mem_ctx
);
525 reply_nterror(req
, nt_status_squash(ret
));
529 /* make_server_info_pw does not set the domain. Without this
530 * we end up with the local netbios name in substitutions for
533 if (server_info
->info3
!= NULL
) {
534 server_info
->info3
->base
.domain
.string
=
535 talloc_strdup(server_info
->info3
, domain
);
539 server_info
->nss_token
|= username_was_mapped
;
541 /* we need to build the token for the user. make_server_info_guest()
544 if ( !server_info
->ptok
) {
545 ret
= create_local_token( server_info
);
546 if ( !NT_STATUS_IS_OK(ret
) ) {
547 DEBUG(10,("failed to create local token: %s\n",
549 data_blob_free(&ap_rep
);
550 data_blob_free(&session_key
);
551 TALLOC_FREE( mem_ctx
);
552 TALLOC_FREE( server_info
);
553 reply_nterror(req
, nt_status_squash(ret
));
558 if (!is_partial_auth_vuid(sconn
, sess_vuid
)) {
559 sess_vuid
= register_initial_vuid(sconn
);
562 data_blob_free(&server_info
->user_session_key
);
563 server_info
->user_session_key
= session_key
;
564 session_key
= data_blob_null
;
566 /* register_existing_vuid keeps the server info */
567 /* register_existing_vuid takes ownership of session_key on success,
568 * no need to free after this on success. A better interface would copy
571 sess_vuid
= register_existing_vuid(sconn
,
577 reply_outbuf(req
, 4, 0);
578 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
580 if (sess_vuid
== UID_FIELD_INVALID
) {
581 ret
= NT_STATUS_LOGON_FAILURE
;
583 /* current_user_info is changed on new vuid */
584 reload_services( True
);
586 SSVAL(req
->outbuf
, smb_vwv3
, 0);
588 if (server_info
->guest
) {
589 SSVAL(req
->outbuf
,smb_vwv2
,1);
592 SSVAL(req
->outbuf
, smb_uid
, sess_vuid
);
594 /* Successful logon. Keep this vuid. */
595 *p_invalidate_vuid
= False
;
598 /* wrap that up in a nice GSS-API wrapping */
599 if (NT_STATUS_IS_OK(ret
)) {
600 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
603 ap_rep_wrapped
= data_blob_null
;
605 response
= spnego_gen_auth_response(&ap_rep_wrapped
, ret
,
607 reply_sesssetup_blob(req
, response
, ret
);
609 data_blob_free(&ap_rep
);
610 data_blob_free(&ap_rep_wrapped
);
611 data_blob_free(&response
);
612 TALLOC_FREE(mem_ctx
);
617 /****************************************************************************
618 Send a session setup reply, wrapped in SPNEGO.
619 Get vuid and check first.
620 End the NTLMSSP exchange context if we are OK/complete fail
621 This should be split into two functions, one to handle each
622 leg of the NTLM auth steps.
623 ***************************************************************************/
625 static void reply_spnego_ntlmssp(struct smb_request
*req
,
627 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
,
628 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
,
633 struct auth_serversupplied_info
*server_info
= NULL
;
634 struct smbd_server_connection
*sconn
= smbd_server_conn
;
636 if (NT_STATUS_IS_OK(nt_status
)) {
637 server_info
= (*auth_ntlmssp_state
)->server_info
;
639 nt_status
= do_map_to_guest(nt_status
,
641 (*auth_ntlmssp_state
)->ntlmssp_state
->user
,
642 (*auth_ntlmssp_state
)->ntlmssp_state
->domain
);
645 reply_outbuf(req
, 4, 0);
647 SSVAL(req
->outbuf
, smb_uid
, vuid
);
649 if (NT_STATUS_IS_OK(nt_status
)) {
650 DATA_BLOB nullblob
= data_blob_null
;
652 if (!is_partial_auth_vuid(sconn
, vuid
)) {
653 nt_status
= NT_STATUS_LOGON_FAILURE
;
657 data_blob_free(&server_info
->user_session_key
);
658 server_info
->user_session_key
=
661 (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.data
,
662 (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.length
);
664 /* register_existing_vuid keeps the server info */
665 if (register_existing_vuid(sconn
, vuid
,
666 server_info
, nullblob
,
667 (*auth_ntlmssp_state
)->ntlmssp_state
->user
) !=
669 nt_status
= NT_STATUS_LOGON_FAILURE
;
673 (*auth_ntlmssp_state
)->server_info
= NULL
;
675 /* current_user_info is changed on new vuid */
676 reload_services( True
);
678 SSVAL(req
->outbuf
, smb_vwv3
, 0);
680 if (server_info
->guest
) {
681 SSVAL(req
->outbuf
,smb_vwv2
,1);
688 response
= spnego_gen_auth_response(ntlmssp_blob
,
691 response
= *ntlmssp_blob
;
694 reply_sesssetup_blob(req
, response
, nt_status
);
696 data_blob_free(&response
);
699 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
700 and the other end, that we are not finished yet. */
702 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
703 /* NB. This is *NOT* an error case. JRA */
704 auth_ntlmssp_end(auth_ntlmssp_state
);
705 if (!NT_STATUS_IS_OK(nt_status
)) {
706 /* Kill the intermediate vuid */
707 invalidate_vuid(sconn
, vuid
);
712 /****************************************************************************
713 Is this a krb5 mechanism ?
714 ****************************************************************************/
716 NTSTATUS
parse_spnego_mechanisms(DATA_BLOB blob_in
,
717 DATA_BLOB
*pblob_out
,
720 char *OIDs
[ASN1_MAX_OIDS
];
722 NTSTATUS ret
= NT_STATUS_OK
;
724 *kerb_mechOID
= NULL
;
726 /* parse out the OIDs and the first sec blob */
727 if (!parse_negTokenTarg(blob_in
, OIDs
, pblob_out
)) {
728 return NT_STATUS_LOGON_FAILURE
;
731 /* only look at the first OID for determining the mechToken --
732 according to RFC2478, we should choose the one we want
733 and renegotiate, but i smell a client bug here..
735 Problem observed when connecting to a member (samba box)
736 of an AD domain as a user in a Samba domain. Samba member
737 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
738 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
739 NTLMSSP mechtoken. --jerry */
742 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
743 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
744 *kerb_mechOID
= SMB_STRDUP(OIDs
[0]);
745 if (*kerb_mechOID
== NULL
) {
746 ret
= NT_STATUS_NO_MEMORY
;
751 for (i
=0;OIDs
[i
];i
++) {
752 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs
[i
]));
753 talloc_free(OIDs
[i
]);
758 /****************************************************************************
759 Fall back from krb5 to NTLMSSP.
760 ****************************************************************************/
762 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request
*req
,
767 reply_outbuf(req
, 4, 0);
768 SSVAL(req
->outbuf
,smb_uid
,vuid
);
770 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
771 "but set to downgrade to NTLMSSP\n"));
773 response
= spnego_gen_auth_response(NULL
,
774 NT_STATUS_MORE_PROCESSING_REQUIRED
,
776 reply_sesssetup_blob(req
, response
, NT_STATUS_MORE_PROCESSING_REQUIRED
);
777 data_blob_free(&response
);
780 /****************************************************************************
781 Reply to a session setup spnego negotiate packet.
782 ****************************************************************************/
784 static void reply_spnego_negotiate(struct smb_request
*req
,
787 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
)
791 char *kerb_mech
= NULL
;
793 struct smbd_server_connection
*sconn
= smbd_server_conn
;
795 status
= parse_spnego_mechanisms(blob1
, &secblob
, &kerb_mech
);
796 if (!NT_STATUS_IS_OK(status
)) {
797 /* Kill the intermediate vuid */
798 invalidate_vuid(sconn
, vuid
);
799 reply_nterror(req
, nt_status_squash(status
));
803 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
804 (unsigned long)secblob
.length
));
807 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
808 USE_KERBEROS_KEYTAB
) ) {
809 bool destroy_vuid
= True
;
810 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
811 vuid
, &destroy_vuid
);
812 data_blob_free(&secblob
);
814 /* Kill the intermediate vuid */
815 invalidate_vuid(sconn
, vuid
);
817 SAFE_FREE(kerb_mech
);
822 if (*auth_ntlmssp_state
) {
823 auth_ntlmssp_end(auth_ntlmssp_state
);
827 data_blob_free(&secblob
);
828 /* The mechtoken is a krb5 ticket, but
829 * we need to fall back to NTLM. */
830 reply_spnego_downgrade_to_ntlmssp(req
, vuid
);
831 SAFE_FREE(kerb_mech
);
835 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
836 if (!NT_STATUS_IS_OK(status
)) {
837 /* Kill the intermediate vuid */
838 invalidate_vuid(sconn
, vuid
);
839 reply_nterror(req
, nt_status_squash(status
));
843 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
846 data_blob_free(&secblob
);
848 reply_spnego_ntlmssp(req
, vuid
, auth_ntlmssp_state
,
849 &chal
, status
, OID_NTLMSSP
, true);
851 data_blob_free(&chal
);
853 /* already replied */
857 /****************************************************************************
858 Reply to a session setup spnego auth packet.
859 ****************************************************************************/
861 static void reply_spnego_auth(struct smb_request
*req
,
864 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
)
866 DATA_BLOB auth
= data_blob_null
;
867 DATA_BLOB auth_reply
= data_blob_null
;
868 DATA_BLOB secblob
= data_blob_null
;
869 NTSTATUS status
= NT_STATUS_LOGON_FAILURE
;
870 struct smbd_server_connection
*sconn
= smbd_server_conn
;
872 if (!spnego_parse_auth(blob1
, &auth
)) {
874 file_save("auth.dat", blob1
.data
, blob1
.length
);
876 /* Kill the intermediate vuid */
877 invalidate_vuid(sconn
, vuid
);
879 reply_nterror(req
, nt_status_squash(
880 NT_STATUS_LOGON_FAILURE
));
884 if (auth
.data
[0] == ASN1_APPLICATION(0)) {
885 /* Might be a second negTokenTarg packet */
886 char *kerb_mech
= NULL
;
888 status
= parse_spnego_mechanisms(auth
, &secblob
, &kerb_mech
);
890 if (!NT_STATUS_IS_OK(status
)) {
891 /* Kill the intermediate vuid */
892 invalidate_vuid(sconn
, vuid
);
893 reply_nterror(req
, nt_status_squash(status
));
897 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
898 (unsigned long)secblob
.length
));
900 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
901 USE_KERBEROS_KEYTAB
)) {
902 bool destroy_vuid
= True
;
903 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
904 vuid
, &destroy_vuid
);
905 data_blob_free(&secblob
);
906 data_blob_free(&auth
);
908 /* Kill the intermediate vuid */
909 invalidate_vuid(sconn
, vuid
);
911 SAFE_FREE(kerb_mech
);
915 /* Can't blunder into NTLMSSP auth if we have
919 /* Kill the intermediate vuid */
920 invalidate_vuid(sconn
, vuid
);
921 DEBUG(3,("reply_spnego_auth: network "
922 "misconfiguration, client sent us a "
923 "krb5 ticket and kerberos security "
925 reply_nterror(req
, nt_status_squash(
926 NT_STATUS_LOGON_FAILURE
));
927 SAFE_FREE(kerb_mech
);
931 /* If we get here it wasn't a negTokenTarg auth packet. */
932 data_blob_free(&secblob
);
934 if (!*auth_ntlmssp_state
) {
935 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
936 if (!NT_STATUS_IS_OK(status
)) {
937 /* Kill the intermediate vuid */
938 invalidate_vuid(sconn
, vuid
);
939 reply_nterror(req
, nt_status_squash(status
));
944 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
947 data_blob_free(&auth
);
949 /* Don't send the mechid as we've already sent this (RFC4178). */
951 reply_spnego_ntlmssp(req
, vuid
,
953 &auth_reply
, status
, NULL
, true);
955 data_blob_free(&auth_reply
);
957 /* and tell smbd that we have already replied to this packet */
961 /****************************************************************************
962 Delete an entry on the list.
963 ****************************************************************************/
965 static void delete_partial_auth(struct smbd_server_connection
*sconn
,
966 struct pending_auth_data
*pad
)
971 DLIST_REMOVE(sconn
->smb1
.pd_list
, pad
);
972 data_blob_free(&pad
->partial_data
);
976 /****************************************************************************
977 Search for a partial SPNEGO auth fragment matching an smbpid.
978 ****************************************************************************/
980 static struct pending_auth_data
*get_pending_auth_data(
981 struct smbd_server_connection
*sconn
,
984 struct pending_auth_data
*pad
;
986 * NOTE: using the smbpid here is completely wrong...
988 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
990 for (pad
= sconn
->smb1
.pd_list
; pad
; pad
= pad
->next
) {
991 if (pad
->smbpid
== smbpid
) {
998 /****************************************************************************
999 Check the size of an SPNEGO blob. If we need more return
1000 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1001 the blob to be more than 64k.
1002 ****************************************************************************/
1004 static NTSTATUS
check_spnego_blob_complete(struct smbd_server_connection
*sconn
,
1005 uint16 smbpid
, uint16 vuid
,
1008 struct pending_auth_data
*pad
= NULL
;
1010 size_t needed_len
= 0;
1012 pad
= get_pending_auth_data(sconn
, smbpid
);
1014 /* Ensure we have some data. */
1015 if (pblob
->length
== 0) {
1016 /* Caller can cope. */
1017 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1018 delete_partial_auth(sconn
, pad
);
1019 return NT_STATUS_OK
;
1022 /* Were we waiting for more data ? */
1025 size_t copy_len
= MIN(65536, pblob
->length
);
1027 /* Integer wrap paranoia.... */
1029 if (pad
->partial_data
.length
+ copy_len
<
1030 pad
->partial_data
.length
||
1031 pad
->partial_data
.length
+ copy_len
< copy_len
) {
1033 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1034 "pad->partial_data.length = %u, "
1036 (unsigned int)pad
->partial_data
.length
,
1037 (unsigned int)copy_len
));
1039 delete_partial_auth(sconn
, pad
);
1040 return NT_STATUS_INVALID_PARAMETER
;
1043 DEBUG(10,("check_spnego_blob_complete: "
1044 "pad->partial_data.length = %u, "
1045 "pad->needed_len = %u, "
1047 "pblob->length = %u,\n",
1048 (unsigned int)pad
->partial_data
.length
,
1049 (unsigned int)pad
->needed_len
,
1050 (unsigned int)copy_len
,
1051 (unsigned int)pblob
->length
));
1053 tmp_blob
= data_blob(NULL
,
1054 pad
->partial_data
.length
+ copy_len
);
1056 /* Concatenate the two (up to copy_len) bytes. */
1057 memcpy(tmp_blob
.data
,
1058 pad
->partial_data
.data
,
1059 pad
->partial_data
.length
);
1060 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
1064 /* Replace the partial data. */
1065 data_blob_free(&pad
->partial_data
);
1066 pad
->partial_data
= tmp_blob
;
1067 ZERO_STRUCT(tmp_blob
);
1070 if (pblob
->length
>= pad
->needed_len
) {
1071 /* Yes, replace pblob. */
1072 data_blob_free(pblob
);
1073 *pblob
= pad
->partial_data
;
1074 ZERO_STRUCT(pad
->partial_data
);
1075 delete_partial_auth(sconn
, pad
);
1076 return NT_STATUS_OK
;
1079 /* Still need more data. */
1080 pad
->needed_len
-= copy_len
;
1081 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1084 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
1085 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
1086 /* Not something we can determine the
1089 return NT_STATUS_OK
;
1092 /* This is a new SPNEGO sessionsetup - see if
1093 * the data given in this blob is enough.
1096 data
= asn1_init(NULL
);
1098 return NT_STATUS_NO_MEMORY
;
1101 asn1_load(data
, *pblob
);
1102 asn1_start_tag(data
, pblob
->data
[0]);
1103 if (data
->has_error
|| data
->nesting
== NULL
) {
1105 /* Let caller catch. */
1106 return NT_STATUS_OK
;
1109 /* Integer wrap paranoia.... */
1111 if (data
->nesting
->taglen
+ data
->nesting
->start
< data
->nesting
->taglen
||
1112 data
->nesting
->taglen
+ data
->nesting
->start
< data
->nesting
->start
) {
1114 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1115 "data.nesting->taglen = %u, "
1116 "data.nesting->start = %u\n",
1117 (unsigned int)data
->nesting
->taglen
,
1118 (unsigned int)data
->nesting
->start
));
1121 return NT_STATUS_INVALID_PARAMETER
;
1124 /* Total length of the needed asn1 is the tag length
1125 * plus the current offset. */
1127 needed_len
= data
->nesting
->taglen
+ data
->nesting
->start
;
1130 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1131 "pblob->length = %u\n",
1132 (unsigned int)needed_len
,
1133 (unsigned int)pblob
->length
));
1135 if (needed_len
<= pblob
->length
) {
1136 /* Nothing to do - blob is complete. */
1137 return NT_STATUS_OK
;
1140 /* Refuse the blob if it's bigger than 64k. */
1141 if (needed_len
> 65536) {
1142 DEBUG(2,("check_spnego_blob_complete: needed_len "
1144 (unsigned int)needed_len
));
1145 return NT_STATUS_INVALID_PARAMETER
;
1148 /* We must store this blob until complete. */
1149 if (!(pad
= SMB_MALLOC_P(struct pending_auth_data
))) {
1150 return NT_STATUS_NO_MEMORY
;
1152 pad
->needed_len
= needed_len
- pblob
->length
;
1153 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
1154 if (pad
->partial_data
.data
== NULL
) {
1156 return NT_STATUS_NO_MEMORY
;
1158 pad
->smbpid
= smbpid
;
1160 DLIST_ADD(sconn
->smb1
.pd_list
, pad
);
1162 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1165 /****************************************************************************
1166 Reply to a session setup command.
1167 conn POINTER CAN BE NULL HERE !
1168 ****************************************************************************/
1170 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
1176 const char *native_os
;
1177 const char *native_lanman
;
1178 const char *primary_domain
;
1180 uint16 data_blob_len
= SVAL(req
->vwv
+7, 0);
1181 enum remote_arch_types ra_type
= get_remote_arch();
1182 int vuid
= req
->vuid
;
1183 user_struct
*vuser
= NULL
;
1184 NTSTATUS status
= NT_STATUS_OK
;
1185 uint16 smbpid
= req
->smbpid
;
1186 struct smbd_server_connection
*sconn
= smbd_server_conn
;
1188 DEBUG(3,("Doing spnego session setup\n"));
1190 if (global_client_caps
== 0) {
1191 global_client_caps
= IVAL(req
->vwv
+10, 0);
1193 if (!(global_client_caps
& CAP_STATUS32
)) {
1194 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1201 if (data_blob_len
== 0) {
1202 /* an invalid request */
1203 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1207 bufrem
= smbreq_bufrem(req
, p
);
1208 /* pull the spnego blob */
1209 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
1212 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
1215 p2
= (char *)req
->buf
+ blob1
.length
;
1217 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1219 native_os
= tmp
? tmp
: "";
1221 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1223 native_lanman
= tmp
? tmp
: "";
1225 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1227 primary_domain
= tmp
? tmp
: "";
1229 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1230 native_os
, native_lanman
, primary_domain
));
1232 if ( ra_type
== RA_WIN2K
) {
1233 /* Vista sets neither the OS or lanman strings */
1235 if ( !strlen(native_os
) && !strlen(native_lanman
) )
1236 set_remote_arch(RA_VISTA
);
1238 /* Windows 2003 doesn't set the native lanman string,
1239 but does set primary domain which is a bug I think */
1241 if ( !strlen(native_lanman
) ) {
1242 ra_lanman_string( primary_domain
);
1244 ra_lanman_string( native_lanman
);
1248 /* Did we get a valid vuid ? */
1249 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1250 /* No, then try and see if this is an intermediate sessionsetup
1251 * for a large SPNEGO packet. */
1252 struct pending_auth_data
*pad
;
1253 pad
= get_pending_auth_data(sconn
, smbpid
);
1255 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1256 "pending vuid %u\n",
1257 (unsigned int)pad
->vuid
));
1262 /* Do we have a valid vuid now ? */
1263 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1264 /* No, start a new authentication setup. */
1265 vuid
= register_initial_vuid(sconn
);
1266 if (vuid
== UID_FIELD_INVALID
) {
1267 data_blob_free(&blob1
);
1268 reply_nterror(req
, nt_status_squash(
1269 NT_STATUS_INVALID_PARAMETER
));
1274 vuser
= get_partial_auth_user_struct(sconn
, vuid
);
1275 /* This MUST be valid. */
1277 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1280 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1281 * sessionsetup requests as the Windows limit on the security blob
1282 * field is 4k. Bug #4400. JRA.
1285 status
= check_spnego_blob_complete(sconn
, smbpid
, vuid
, &blob1
);
1286 if (!NT_STATUS_IS_OK(status
)) {
1287 if (!NT_STATUS_EQUAL(status
,
1288 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1289 /* Real error - kill the intermediate vuid */
1290 invalidate_vuid(sconn
, vuid
);
1292 data_blob_free(&blob1
);
1293 reply_nterror(req
, nt_status_squash(status
));
1297 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
1299 /* its a negTokenTarg packet */
1301 reply_spnego_negotiate(req
, vuid
, blob1
,
1302 &vuser
->auth_ntlmssp_state
);
1303 data_blob_free(&blob1
);
1307 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
1309 /* its a auth packet */
1311 reply_spnego_auth(req
, vuid
, blob1
,
1312 &vuser
->auth_ntlmssp_state
);
1313 data_blob_free(&blob1
);
1317 if (strncmp((char *)(blob1
.data
), "NTLMSSP", 7) == 0) {
1320 if (!vuser
->auth_ntlmssp_state
) {
1321 status
= auth_ntlmssp_start(&vuser
->auth_ntlmssp_state
);
1322 if (!NT_STATUS_IS_OK(status
)) {
1323 /* Kill the intermediate vuid */
1324 invalidate_vuid(sconn
, vuid
);
1325 data_blob_free(&blob1
);
1326 reply_nterror(req
, nt_status_squash(status
));
1331 status
= auth_ntlmssp_update(vuser
->auth_ntlmssp_state
,
1334 data_blob_free(&blob1
);
1336 reply_spnego_ntlmssp(req
, vuid
,
1337 &vuser
->auth_ntlmssp_state
,
1338 &chal
, status
, OID_NTLMSSP
, false);
1339 data_blob_free(&chal
);
1343 /* what sort of packet is this? */
1344 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1346 data_blob_free(&blob1
);
1348 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1351 /****************************************************************************
1352 On new VC == 0, shutdown *all* old connections and users.
1353 It seems that only NT4.x does this. At W2K and above (XP etc.).
1354 a new session setup with VC==0 is ignored.
1355 ****************************************************************************/
1357 static int shutdown_other_smbds(const struct connections_key
*key
,
1358 const struct connections_data
*crec
,
1361 const char *ip
= (const char *)private_data
;
1363 if (!process_exists(crec
->pid
)) {
1367 if (procid_is_me(&crec
->pid
)) {
1371 if (strcmp(ip
, crec
->addr
) != 0) {
1375 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1376 "(IP %s)\n", (unsigned int)procid_to_pid(&crec
->pid
), ip
));
1378 messaging_send(smbd_messaging_context(), crec
->pid
, MSG_SHUTDOWN
,
1383 static void setup_new_vc_session(void)
1385 char addr
[INET6_ADDRSTRLEN
];
1387 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1388 "compatible we would close all old resources.\n"));
1391 invalidate_all_vuids();
1393 if (lp_reset_on_zero_vc()) {
1394 connections_forall_read(shutdown_other_smbds
,
1395 CONST_DISCARD(void *,
1396 client_addr(get_client_fd(),addr
,sizeof(addr
))));
1400 /****************************************************************************
1401 Reply to a session setup command.
1402 ****************************************************************************/
1404 void reply_sesssetup_and_X(struct smb_request
*req
)
1410 DATA_BLOB plaintext_password
;
1413 fstring sub_user
; /* Sainitised username for substituion */
1415 const char *native_os
;
1416 const char *native_lanman
;
1417 const char *primary_domain
;
1418 struct auth_usersupplied_info
*user_info
= NULL
;
1419 struct auth_serversupplied_info
*server_info
= NULL
;
1420 uint16 smb_flag2
= req
->flags2
;
1423 struct smbd_server_connection
*sconn
= smbd_server_conn
;
1425 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
1427 START_PROFILE(SMBsesssetupX
);
1429 ZERO_STRUCT(lm_resp
);
1430 ZERO_STRUCT(nt_resp
);
1431 ZERO_STRUCT(plaintext_password
);
1433 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
1435 /* a SPNEGO session setup has 12 command words, whereas a normal
1436 NT1 session setup has 13. See the cifs spec. */
1437 if (req
->wct
== 12 &&
1438 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
1440 if (!sconn
->smb1
.negprot
.spnego
) {
1441 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1442 "at SPNEGO session setup when it was not "
1444 reply_nterror(req
, nt_status_squash(
1445 NT_STATUS_LOGON_FAILURE
));
1446 END_PROFILE(SMBsesssetupX
);
1450 if (SVAL(req
->vwv
+4, 0) == 0) {
1451 setup_new_vc_session();
1454 reply_sesssetup_and_X_spnego(req
);
1455 END_PROFILE(SMBsesssetupX
);
1459 smb_bufsize
= SVAL(req
->vwv
+2, 0);
1461 if (get_Protocol() < PROTOCOL_NT1
) {
1462 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1464 /* Never do NT status codes with protocols before NT1 as we
1465 * don't get client caps. */
1466 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1468 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
1469 reply_nterror(req
, nt_status_squash(
1470 NT_STATUS_INVALID_PARAMETER
));
1471 END_PROFILE(SMBsesssetupX
);
1476 lm_resp
= data_blob(req
->buf
, passlen1
);
1478 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
1479 /* Ensure null termination */
1480 plaintext_password
.data
[passlen1
] = 0;
1483 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
1484 req
->buf
+ passlen1
, STR_TERMINATE
);
1485 user
= tmp
? tmp
: "";
1490 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1491 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
1492 enum remote_arch_types ra_type
= get_remote_arch();
1493 const uint8_t *p
= req
->buf
;
1494 const uint8_t *save_p
= req
->buf
;
1498 if(global_client_caps
== 0) {
1499 global_client_caps
= IVAL(req
->vwv
+11, 0);
1501 if (!(global_client_caps
& CAP_STATUS32
)) {
1502 remove_from_common_flags2(
1503 FLAGS2_32_BIT_ERROR_CODES
);
1506 /* client_caps is used as final determination if
1507 * client is NT or Win95. This is needed to return
1508 * the correct error codes in some circumstances.
1511 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
1512 ra_type
== RA_WIN95
) {
1513 if(!(global_client_caps
& (CAP_NT_SMBS
|
1515 set_remote_arch( RA_WIN95
);
1521 /* both Win95 and WinNT stuff up the password
1522 * lengths for non-encrypting systems. Uggh.
1524 if passlen1==24 its a win95 system, and its setting
1525 the password length incorrectly. Luckily it still
1526 works with the default code because Win95 will null
1527 terminate the password anyway
1529 if passlen1>0 and passlen2>0 then maybe its a NT box
1530 and its setting passlen2 to some random value which
1531 really stuffs things up. we need to fix that one. */
1533 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
1539 /* check for nasty tricks */
1540 if (passlen1
> MAX_PASS_LEN
1541 || passlen1
> smbreq_bufrem(req
, p
)) {
1542 reply_nterror(req
, nt_status_squash(
1543 NT_STATUS_INVALID_PARAMETER
));
1544 END_PROFILE(SMBsesssetupX
);
1548 if (passlen2
> MAX_PASS_LEN
1549 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
1550 reply_nterror(req
, nt_status_squash(
1551 NT_STATUS_INVALID_PARAMETER
));
1552 END_PROFILE(SMBsesssetupX
);
1556 /* Save the lanman2 password and the NT md4 password. */
1558 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1563 lm_resp
= data_blob(p
, passlen1
);
1564 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1565 } else if (lp_security() != SEC_SHARE
) {
1567 * In share level we should ignore any passwords, so
1568 * only read them if we're not.
1571 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
1573 if (unic
&& (passlen2
== 0) && passlen1
) {
1574 /* Only a ascii plaintext password was sent. */
1575 (void)srvstr_pull_talloc(talloc_tos(),
1581 STR_TERMINATE
|STR_ASCII
);
1583 (void)srvstr_pull_talloc(talloc_tos(),
1588 unic
? passlen2
: passlen1
,
1592 reply_nterror(req
, nt_status_squash(
1593 NT_STATUS_INVALID_PARAMETER
));
1594 END_PROFILE(SMBsesssetupX
);
1597 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1600 p
+= passlen1
+ passlen2
;
1602 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1604 user
= tmp
? tmp
: "";
1606 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1608 domain
= tmp
? tmp
: "";
1610 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1612 native_os
= tmp
? tmp
: "";
1614 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1616 native_lanman
= tmp
? tmp
: "";
1618 /* not documented or decoded by Ethereal but there is one more
1619 * string in the extra bytes which is the same as the
1620 * PrimaryDomain when using extended security. Windows NT 4
1621 * and 2003 use this string to store the native lanman string.
1622 * Windows 9x does not include a string here at all so we have
1623 * to check if we have any extra bytes left */
1625 byte_count
= SVAL(req
->vwv
+13, 0);
1626 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
1627 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1629 primary_domain
= tmp
? tmp
: "";
1631 primary_domain
= talloc_strdup(talloc_tos(), "null");
1634 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1635 "PrimaryDomain=[%s]\n",
1636 domain
, native_os
, native_lanman
, primary_domain
));
1638 if ( ra_type
== RA_WIN2K
) {
1639 if ( strlen(native_lanman
) == 0 )
1640 ra_lanman_string( primary_domain
);
1642 ra_lanman_string( native_lanman
);
1647 if (SVAL(req
->vwv
+4, 0) == 0) {
1648 setup_new_vc_session();
1651 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1652 domain
, user
, get_remote_machine_name()));
1655 if (sconn
->smb1
.negprot
.spnego
) {
1657 /* This has to be here, because this is a perfectly
1658 * valid behaviour for guest logons :-( */
1660 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1661 "at 'normal' session setup after "
1662 "negotiating spnego.\n"));
1663 reply_nterror(req
, nt_status_squash(
1664 NT_STATUS_LOGON_FAILURE
));
1665 END_PROFILE(SMBsesssetupX
);
1668 fstrcpy(sub_user
, user
);
1670 fstrcpy(sub_user
, lp_guestaccount());
1673 sub_set_smb_name(sub_user
);
1675 reload_services(True
);
1677 if (lp_security() == SEC_SHARE
) {
1678 /* In share level we should ignore any passwords */
1680 data_blob_free(&lm_resp
);
1681 data_blob_free(&nt_resp
);
1682 data_blob_clear_free(&plaintext_password
);
1684 map_username(sconn
, sub_user
);
1685 add_session_user(sconn
, sub_user
);
1686 add_session_workgroup(sconn
, domain
);
1687 /* Then force it to null for the benfit of the code below */
1693 nt_status
= check_guest_password(&server_info
);
1695 } else if (doencrypt
) {
1696 struct auth_context
*negprot_auth_context
= NULL
;
1697 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
1698 if (!negprot_auth_context
) {
1699 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1700 "session setup without negprot denied!\n"));
1701 reply_nterror(req
, nt_status_squash(
1702 NT_STATUS_LOGON_FAILURE
));
1703 END_PROFILE(SMBsesssetupX
);
1706 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
1709 if (NT_STATUS_IS_OK(nt_status
)) {
1710 nt_status
= negprot_auth_context
->check_ntlm_password(
1711 negprot_auth_context
,
1716 struct auth_context
*plaintext_auth_context
= NULL
;
1718 nt_status
= make_auth_context_subsystem(
1719 &plaintext_auth_context
);
1721 if (NT_STATUS_IS_OK(nt_status
)) {
1724 plaintext_auth_context
->get_ntlm_challenge(
1725 plaintext_auth_context
, chal
);
1727 if (!make_user_info_for_reply(&user_info
,
1729 plaintext_password
)) {
1730 nt_status
= NT_STATUS_NO_MEMORY
;
1733 if (NT_STATUS_IS_OK(nt_status
)) {
1734 nt_status
= plaintext_auth_context
->check_ntlm_password(
1735 plaintext_auth_context
,
1739 (plaintext_auth_context
->free
)(
1740 &plaintext_auth_context
);
1745 free_user_info(&user_info
);
1747 if (!NT_STATUS_IS_OK(nt_status
)) {
1748 nt_status
= do_map_to_guest(nt_status
, &server_info
,
1752 if (!NT_STATUS_IS_OK(nt_status
)) {
1753 data_blob_free(&nt_resp
);
1754 data_blob_free(&lm_resp
);
1755 data_blob_clear_free(&plaintext_password
);
1756 reply_nterror(req
, nt_status_squash(nt_status
));
1757 END_PROFILE(SMBsesssetupX
);
1761 /* Ensure we can't possible take a code path leading to a
1764 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1765 END_PROFILE(SMBsesssetupX
);
1769 if (!server_info
->ptok
) {
1770 nt_status
= create_local_token(server_info
);
1772 if (!NT_STATUS_IS_OK(nt_status
)) {
1773 DEBUG(10, ("create_local_token failed: %s\n",
1774 nt_errstr(nt_status
)));
1775 data_blob_free(&nt_resp
);
1776 data_blob_free(&lm_resp
);
1777 data_blob_clear_free(&plaintext_password
);
1778 reply_nterror(req
, nt_status_squash(nt_status
));
1779 END_PROFILE(SMBsesssetupX
);
1784 data_blob_clear_free(&plaintext_password
);
1786 /* it's ok - setup a reply */
1787 reply_outbuf(req
, 3, 0);
1788 if (get_Protocol() >= PROTOCOL_NT1
) {
1789 push_signature(&req
->outbuf
);
1790 /* perhaps grab OS version here?? */
1793 if (server_info
->guest
) {
1794 SSVAL(req
->outbuf
,smb_vwv2
,1);
1797 /* register the name and uid as being validated, so further connections
1798 to a uid can get through without a password, on the same VC */
1800 if (lp_security() == SEC_SHARE
) {
1801 sess_vuid
= UID_FIELD_INVALID
;
1802 TALLOC_FREE(server_info
);
1804 /* Ignore the initial vuid. */
1805 sess_vuid
= register_initial_vuid(sconn
);
1806 if (sess_vuid
== UID_FIELD_INVALID
) {
1807 data_blob_free(&nt_resp
);
1808 data_blob_free(&lm_resp
);
1809 reply_nterror(req
, nt_status_squash(
1810 NT_STATUS_LOGON_FAILURE
));
1811 END_PROFILE(SMBsesssetupX
);
1814 /* register_existing_vuid keeps the server info */
1815 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
1817 nt_resp
.data
? nt_resp
: lm_resp
,
1819 if (sess_vuid
== UID_FIELD_INVALID
) {
1820 data_blob_free(&nt_resp
);
1821 data_blob_free(&lm_resp
);
1822 reply_nterror(req
, nt_status_squash(
1823 NT_STATUS_LOGON_FAILURE
));
1824 END_PROFILE(SMBsesssetupX
);
1828 /* current_user_info is changed on new vuid */
1829 reload_services( True
);
1832 data_blob_free(&nt_resp
);
1833 data_blob_free(&lm_resp
);
1835 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1836 SSVAL(req
->inbuf
,smb_uid
,sess_vuid
);
1837 req
->vuid
= sess_vuid
;
1839 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
1840 sconn
->smb1
.sessions
.max_send
=
1841 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
1843 sconn
->smb1
.sessions
.done_sesssetup
= true;
1845 END_PROFILE(SMBsesssetupX
);