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"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "librpc/gen_ndr/messaging.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
34 /* For split krb5 SPNEGO blobs. */
35 struct pending_auth_data
{
36 struct pending_auth_data
*prev
, *next
;
37 uint16 vuid
; /* Tag for this entry. */
38 uint16 smbpid
; /* Alternate tag for this entry. */
40 DATA_BLOB partial_data
;
44 on a logon error possibly map the error to success if "map to guest"
47 NTSTATUS
do_map_to_guest(NTSTATUS status
,
48 struct auth_serversupplied_info
**server_info
,
49 const char *user
, const char *domain
)
51 user
= user
? user
: "";
52 domain
= domain
? domain
: "";
54 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
55 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
56 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
57 DEBUG(3,("No such user %s [%s] - using guest account\n",
59 status
= make_server_info_guest(NULL
, server_info
);
63 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
64 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
65 DEBUG(3,("Registered username %s for guest access\n",
67 status
= make_server_info_guest(NULL
, server_info
);
74 /****************************************************************************
75 Add the standard 'Samba' signature to the end of the session setup.
76 ****************************************************************************/
78 static int push_signature(uint8
**outbuf
)
85 tmp
= message_push_string(outbuf
, "Unix", STR_TERMINATE
);
87 if (tmp
== -1) return -1;
90 if (asprintf(&lanman
, "Samba %s", samba_version_string()) != -1) {
91 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
95 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
98 if (tmp
== -1) return -1;
101 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
103 if (tmp
== -1) return -1;
109 /****************************************************************************
110 Send a security blob via a session setup reply.
111 ****************************************************************************/
113 static void reply_sesssetup_blob(struct smb_request
*req
,
117 if (!NT_STATUS_IS_OK(nt_status
) &&
118 !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
119 reply_nterror(req
, nt_status_squash(nt_status
));
123 nt_status
= nt_status_squash(nt_status
);
124 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
125 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
126 SSVAL(req
->outbuf
, smb_vwv3
, blob
.length
);
128 if ((message_push_blob(&req
->outbuf
, blob
) == -1)
129 || (push_signature(&req
->outbuf
) == -1)) {
130 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
134 /****************************************************************************
135 Do a 'guest' logon, getting back the
136 ****************************************************************************/
138 static NTSTATUS
check_guest_password(struct auth_serversupplied_info
**server_info
)
140 struct auth_context
*auth_context
;
141 struct auth_usersupplied_info
*user_info
= NULL
;
144 unsigned char chal
[8];
148 DEBUG(3,("Got anonymous request\n"));
150 if (!NT_STATUS_IS_OK(nt_status
= make_auth_context_fixed(&auth_context
,
155 if (!make_user_info_guest(&user_info
)) {
156 TALLOC_FREE(auth_context
);
157 return NT_STATUS_NO_MEMORY
;
160 nt_status
= auth_context
->check_ntlm_password(auth_context
,
163 TALLOC_FREE(auth_context
);
164 free_user_info(&user_info
);
172 /* Experiment that failed. See "only happens with a KDC" comment below. */
173 /****************************************************************************
174 Cerate a clock skew error blob for a Windows client.
175 ****************************************************************************/
177 static bool make_krb5_skew_error(DATA_BLOB
*pblob_out
)
179 krb5_context context
= NULL
;
180 krb5_error_code kerr
= 0;
182 krb5_principal host_princ
= NULL
;
183 char *host_princ_s
= NULL
;
186 *pblob_out
= data_blob_null
;
188 initialize_krb5_error_table();
189 kerr
= krb5_init_context(&context
);
193 /* Create server principal. */
194 asprintf(&host_princ_s
, "%s$@%s", global_myname(), lp_realm());
198 strlower_m(host_princ_s
);
200 kerr
= smb_krb5_parse_name(context
, host_princ_s
, &host_princ
);
202 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
203 "for name %s: Error %s\n",
204 host_princ_s
, error_message(kerr
) ));
208 kerr
= smb_krb5_mk_error(context
, KRB5KRB_AP_ERR_SKEW
,
211 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
212 "failed: Error %s\n",
213 error_message(kerr
) ));
217 *pblob_out
= data_blob(reply
.data
, reply
.length
);
218 kerberos_free_data_contents(context
,&reply
);
224 SAFE_FREE(host_princ_s
);
227 krb5_free_principal(context
, host_princ
);
229 krb5_free_context(context
);
234 /****************************************************************************
235 Reply to a session setup spnego negotiate packet for kerberos.
236 ****************************************************************************/
238 static void reply_spnego_kerberos(struct smb_request
*req
,
242 bool *p_invalidate_vuid
)
246 char *client
, *p
, *domain
;
247 fstring netbios_domain_name
;
250 int sess_vuid
= req
->vuid
;
251 NTSTATUS ret
= NT_STATUS_OK
;
252 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
253 struct auth_serversupplied_info
*server_info
= NULL
;
254 DATA_BLOB session_key
= data_blob_null
;
256 DATA_BLOB nullblob
= data_blob_null
;
257 fstring real_username
;
258 bool map_domainuser_to_guest
= False
;
259 bool username_was_mapped
;
260 struct PAC_LOGON_INFO
*logon_info
= NULL
;
261 struct smbd_server_connection
*sconn
= req
->sconn
;
265 ZERO_STRUCT(ap_rep_wrapped
);
266 ZERO_STRUCT(response
);
268 /* Normally we will always invalidate the intermediate vuid. */
269 *p_invalidate_vuid
= True
;
271 mem_ctx
= talloc_init("reply_spnego_kerberos");
272 if (mem_ctx
== NULL
) {
273 reply_nterror(req
, nt_status_squash(NT_STATUS_NO_MEMORY
));
277 if (!spnego_parse_krb5_wrap(mem_ctx
, *secblob
, &ticket
, tok_id
)) {
278 talloc_destroy(mem_ctx
);
279 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
283 ret
= ads_verify_ticket(mem_ctx
, lp_realm(), 0, &ticket
,
284 &client
, &logon_info
, &ap_rep
,
287 data_blob_free(&ticket
);
289 if (!NT_STATUS_IS_OK(ret
)) {
291 /* Experiment that failed.
292 * See "only happens with a KDC" comment below. */
294 if (NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
297 * Windows in this case returns
298 * NT_STATUS_MORE_PROCESSING_REQUIRED
299 * with a negTokenTarg blob containing an krb5_error
300 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
301 * The client then fixes its clock and continues rather
302 * than giving an error. JRA.
303 * -- Looks like this only happens with a KDC. JRA.
306 bool ok
= make_krb5_skew_error(&ap_rep
);
308 talloc_destroy(mem_ctx
);
309 return ERROR_NT(nt_status_squash(
310 NT_STATUS_LOGON_FAILURE
));
312 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
314 response
= spnego_gen_auth_response(&ap_rep_wrapped
,
315 ret
, OID_KERBEROS5_OLD
);
316 reply_sesssetup_blob(conn
, inbuf
, outbuf
, response
,
317 NT_STATUS_MORE_PROCESSING_REQUIRED
);
320 * In this one case we don't invalidate the
321 * intermediate vuid as we're expecting the client
322 * to re-use it for the next sessionsetupX packet. JRA.
325 *p_invalidate_vuid
= False
;
327 data_blob_free(&ap_rep
);
328 data_blob_free(&ap_rep_wrapped
);
329 data_blob_free(&response
);
330 talloc_destroy(mem_ctx
);
331 return -1; /* already replied */
334 if (!NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
335 ret
= NT_STATUS_LOGON_FAILURE
;
338 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
340 talloc_destroy(mem_ctx
);
341 reply_nterror(req
, nt_status_squash(ret
));
345 DEBUG(3,("Ticket name is [%s]\n", client
));
347 p
= strchr_m(client
, '@');
349 DEBUG(3,("Doesn't look like a valid principal\n"));
350 data_blob_free(&ap_rep
);
351 data_blob_free(&session_key
);
352 talloc_destroy(mem_ctx
);
353 reply_nterror(req
,nt_status_squash(NT_STATUS_LOGON_FAILURE
));
359 /* save the PAC data if we have it */
362 netsamlogon_cache_store( client
, &logon_info
->info3
);
365 if (!strequal(p
+1, lp_realm())) {
366 DEBUG(3,("Ticket for foreign realm %s@%s\n", client
, p
+1));
367 if (!lp_allow_trusted_domains()) {
368 data_blob_free(&ap_rep
);
369 data_blob_free(&session_key
);
370 talloc_destroy(mem_ctx
);
371 reply_nterror(req
, nt_status_squash(
372 NT_STATUS_LOGON_FAILURE
));
377 /* this gives a fully qualified user name (ie. with full realm).
378 that leads to very long usernames, but what else can we do? */
382 if (logon_info
&& logon_info
->info3
.base
.domain
.string
) {
383 fstrcpy(netbios_domain_name
,
384 logon_info
->info3
.base
.domain
.string
);
385 domain
= netbios_domain_name
;
386 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain
));
390 /* If we have winbind running, we can (and must) shorten the
391 username by using the short netbios name. Otherwise we will
392 have inconsistent user names. With Kerberos, we get the
393 fully qualified realm, with ntlmssp we get the short
394 name. And even w2k3 does use ntlmssp if you for example
395 connect to an ip address. */
398 struct wbcDomainInfo
*info
= NULL
;
400 DEBUG(10, ("Mapping [%s] to short name\n", domain
));
402 wbc_status
= wbcDomainInfo(domain
, &info
);
404 if (WBC_ERROR_IS_OK(wbc_status
)) {
406 fstrcpy(netbios_domain_name
,
410 domain
= netbios_domain_name
;
411 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain
));
413 DEBUG(3, ("Could not find short name: %s\n",
414 wbcErrorString(wbc_status
)));
418 fstr_sprintf(user
, "%s%c%s", domain
, *lp_winbind_separator(), client
);
420 /* lookup the passwd struct, create a new user if necessary */
422 username_was_mapped
= map_username(user
);
424 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
427 /* if a real user check pam account restrictions */
428 /* only really perfomed if "obey pam restriction" is true */
429 /* do this before an eventual mapping to guest occurs */
430 ret
= smb_pam_accountcheck(pw
->pw_name
);
431 if ( !NT_STATUS_IS_OK(ret
)) {
432 DEBUG(1,("PAM account restriction "
433 "prevents user login\n"));
434 data_blob_free(&ap_rep
);
435 data_blob_free(&session_key
);
436 TALLOC_FREE(mem_ctx
);
437 reply_nterror(req
, nt_status_squash(ret
));
444 /* this was originally the behavior of Samba 2.2, if a user
445 did not have a local uid but has been authenticated, then
446 map them to a guest account */
448 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID
){
449 map_domainuser_to_guest
= True
;
450 fstrcpy(user
,lp_guestaccount());
451 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
454 /* extra sanity check that the guest account is valid */
457 DEBUG(1,("Username %s is invalid on this system\n",
459 data_blob_free(&ap_rep
);
460 data_blob_free(&session_key
);
461 TALLOC_FREE(mem_ctx
);
462 reply_nterror(req
, nt_status_squash(
463 NT_STATUS_LOGON_FAILURE
));
468 /* setup the string used by %U */
470 sub_set_smb_name( real_username
);
471 reload_services(sconn
->msg_ctx
, True
);
473 if ( map_domainuser_to_guest
) {
474 make_server_info_guest(NULL
, &server_info
);
475 } else if (logon_info
) {
476 /* pass the unmapped username here since map_username()
477 will be called again from inside make_server_info_info3() */
479 ret
= make_server_info_info3(mem_ctx
, client
, domain
,
480 &server_info
, &logon_info
->info3
);
481 if ( !NT_STATUS_IS_OK(ret
) ) {
482 DEBUG(1,("make_server_info_info3 failed: %s!\n",
484 data_blob_free(&ap_rep
);
485 data_blob_free(&session_key
);
486 TALLOC_FREE(mem_ctx
);
487 reply_nterror(req
, nt_status_squash(ret
));
493 * We didn't get a PAC, we have to make up the user
494 * ourselves. Try to ask the pdb backend to provide
495 * SID consistency with ntlmssp session setup
497 struct samu
*sampass
;
499 sampass
= samu_new(talloc_tos());
500 if (sampass
== NULL
) {
501 ret
= NT_STATUS_NO_MEMORY
;
502 data_blob_free(&ap_rep
);
503 data_blob_free(&session_key
);
504 TALLOC_FREE(mem_ctx
);
505 reply_nterror(req
, nt_status_squash(ret
));
509 if (pdb_getsampwnam(sampass
, real_username
)) {
510 DEBUG(10, ("found user %s in passdb, calling "
511 "make_server_info_sam\n", real_username
));
512 ret
= make_server_info_sam(&server_info
, sampass
);
513 TALLOC_FREE(sampass
);
516 * User not in passdb, make it up artificially
518 TALLOC_FREE(sampass
);
519 DEBUG(10, ("didn't find user %s in passdb, calling "
520 "make_server_info_pw\n", real_username
));
521 ret
= make_server_info_pw(&server_info
, real_username
,
525 if ( !NT_STATUS_IS_OK(ret
) ) {
526 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
528 data_blob_free(&ap_rep
);
529 data_blob_free(&session_key
);
530 TALLOC_FREE(mem_ctx
);
531 reply_nterror(req
, nt_status_squash(ret
));
535 /* make_server_info_pw does not set the domain. Without this
536 * we end up with the local netbios name in substitutions for
539 if (server_info
->info3
!= NULL
) {
540 server_info
->info3
->base
.domain
.string
=
541 talloc_strdup(server_info
->info3
, domain
);
545 server_info
->nss_token
|= username_was_mapped
;
547 /* we need to build the token for the user. make_server_info_guest()
550 if ( !server_info
->ptok
) {
551 ret
= create_local_token( server_info
);
552 if ( !NT_STATUS_IS_OK(ret
) ) {
553 DEBUG(10,("failed to create local token: %s\n",
555 data_blob_free(&ap_rep
);
556 data_blob_free(&session_key
);
557 TALLOC_FREE( mem_ctx
);
558 TALLOC_FREE( server_info
);
559 reply_nterror(req
, nt_status_squash(ret
));
564 if (!is_partial_auth_vuid(sconn
, sess_vuid
)) {
565 sess_vuid
= register_initial_vuid(sconn
);
568 data_blob_free(&server_info
->user_session_key
);
569 server_info
->user_session_key
= session_key
;
570 talloc_steal(server_info
, session_key
.data
);
572 session_key
= data_blob_null
;
574 /* register_existing_vuid keeps the server info */
575 /* register_existing_vuid takes ownership of session_key on success,
576 * no need to free after this on success. A better interface would copy
579 sess_vuid
= register_existing_vuid(sconn
,
585 reply_outbuf(req
, 4, 0);
586 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
588 if (sess_vuid
== UID_FIELD_INVALID
) {
589 ret
= NT_STATUS_LOGON_FAILURE
;
591 /* current_user_info is changed on new vuid */
592 reload_services(sconn
->msg_ctx
, True
);
594 SSVAL(req
->outbuf
, smb_vwv3
, 0);
596 if (server_info
->guest
) {
597 SSVAL(req
->outbuf
,smb_vwv2
,1);
600 SSVAL(req
->outbuf
, smb_uid
, sess_vuid
);
602 /* Successful logon. Keep this vuid. */
603 *p_invalidate_vuid
= False
;
606 /* wrap that up in a nice GSS-API wrapping */
607 if (NT_STATUS_IS_OK(ret
)) {
608 ap_rep_wrapped
= spnego_gen_krb5_wrap(talloc_tos(), ap_rep
,
611 ap_rep_wrapped
= data_blob_null
;
613 response
= spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped
, ret
,
615 reply_sesssetup_blob(req
, response
, ret
);
617 data_blob_free(&ap_rep
);
618 data_blob_free(&ap_rep_wrapped
);
619 data_blob_free(&response
);
620 TALLOC_FREE(mem_ctx
);
625 /****************************************************************************
626 Send a session setup reply, wrapped in SPNEGO.
627 Get vuid and check first.
628 End the NTLMSSP exchange context if we are OK/complete fail
629 This should be split into two functions, one to handle each
630 leg of the NTLM auth steps.
631 ***************************************************************************/
633 static void reply_spnego_ntlmssp(struct smb_request
*req
,
635 struct auth_ntlmssp_state
**auth_ntlmssp_state
,
636 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
,
640 bool do_invalidate
= true;
642 struct auth_serversupplied_info
*server_info
= NULL
;
643 struct smbd_server_connection
*sconn
= req
->sconn
;
645 if (NT_STATUS_IS_OK(nt_status
)) {
646 nt_status
= auth_ntlmssp_steal_server_info(talloc_tos(),
647 (*auth_ntlmssp_state
), &server_info
);
649 /* Note that this server_info won't have a session
650 * key. But for map to guest, that's exactly the right
651 * thing - we can't reasonably guess the key the
652 * client wants, as the password was wrong */
653 nt_status
= do_map_to_guest(nt_status
,
655 auth_ntlmssp_get_username(*auth_ntlmssp_state
),
656 auth_ntlmssp_get_domain(*auth_ntlmssp_state
));
659 reply_outbuf(req
, 4, 0);
661 SSVAL(req
->outbuf
, smb_uid
, vuid
);
663 if (NT_STATUS_IS_OK(nt_status
)) {
664 DATA_BLOB nullblob
= data_blob_null
;
666 if (!is_partial_auth_vuid(sconn
, vuid
)) {
667 nt_status
= NT_STATUS_LOGON_FAILURE
;
671 /* register_existing_vuid keeps the server info */
672 if (register_existing_vuid(sconn
, vuid
,
673 server_info
, nullblob
,
674 auth_ntlmssp_get_username(*auth_ntlmssp_state
)) !=
676 /* The problem is, *auth_ntlmssp_state points
677 * into the vuser this will have
678 * talloc_free()'ed in
679 * register_existing_vuid() */
680 do_invalidate
= false;
681 nt_status
= NT_STATUS_LOGON_FAILURE
;
685 /* current_user_info is changed on new vuid */
686 reload_services(sconn
->msg_ctx
, True
);
688 SSVAL(req
->outbuf
, smb_vwv3
, 0);
690 if (server_info
->guest
) {
691 SSVAL(req
->outbuf
,smb_vwv2
,1);
698 response
= spnego_gen_auth_response(talloc_tos(),
702 response
= *ntlmssp_blob
;
705 reply_sesssetup_blob(req
, response
, nt_status
);
707 data_blob_free(&response
);
710 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
711 and the other end, that we are not finished yet. */
713 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
714 /* NB. This is *NOT* an error case. JRA */
716 TALLOC_FREE(*auth_ntlmssp_state
);
717 if (!NT_STATUS_IS_OK(nt_status
)) {
718 /* Kill the intermediate vuid */
719 invalidate_vuid(sconn
, vuid
);
725 /****************************************************************************
726 Is this a krb5 mechanism ?
727 ****************************************************************************/
729 NTSTATUS
parse_spnego_mechanisms(TALLOC_CTX
*ctx
,
731 DATA_BLOB
*pblob_out
,
734 char *OIDs
[ASN1_MAX_OIDS
];
736 NTSTATUS ret
= NT_STATUS_OK
;
738 *kerb_mechOID
= NULL
;
740 /* parse out the OIDs and the first sec blob */
741 if (!spnego_parse_negTokenInit(ctx
, blob_in
, OIDs
, NULL
, pblob_out
)) {
742 return NT_STATUS_LOGON_FAILURE
;
745 /* only look at the first OID for determining the mechToken --
746 according to RFC2478, we should choose the one we want
747 and renegotiate, but i smell a client bug here..
749 Problem observed when connecting to a member (samba box)
750 of an AD domain as a user in a Samba domain. Samba member
751 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
752 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
753 NTLMSSP mechtoken. --jerry */
756 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
757 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
758 *kerb_mechOID
= talloc_strdup(ctx
, OIDs
[0]);
759 if (*kerb_mechOID
== NULL
) {
760 ret
= NT_STATUS_NO_MEMORY
;
765 for (i
=0;OIDs
[i
];i
++) {
766 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs
[i
]));
767 talloc_free(OIDs
[i
]);
772 /****************************************************************************
773 Fall back from krb5 to NTLMSSP.
774 ****************************************************************************/
776 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request
*req
,
781 reply_outbuf(req
, 4, 0);
782 SSVAL(req
->outbuf
,smb_uid
,vuid
);
784 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
785 "but set to downgrade to NTLMSSP\n"));
787 response
= spnego_gen_auth_response(talloc_tos(), NULL
,
788 NT_STATUS_MORE_PROCESSING_REQUIRED
,
790 reply_sesssetup_blob(req
, response
, NT_STATUS_MORE_PROCESSING_REQUIRED
);
791 data_blob_free(&response
);
794 /****************************************************************************
795 Reply to a session setup spnego negotiate packet.
796 ****************************************************************************/
798 static void reply_spnego_negotiate(struct smb_request
*req
,
801 struct auth_ntlmssp_state
**auth_ntlmssp_state
)
805 char *kerb_mech
= NULL
;
807 struct smbd_server_connection
*sconn
= req
->sconn
;
809 status
= parse_spnego_mechanisms(talloc_tos(),
810 blob1
, &secblob
, &kerb_mech
);
811 if (!NT_STATUS_IS_OK(status
)) {
812 /* Kill the intermediate vuid */
813 invalidate_vuid(sconn
, vuid
);
814 reply_nterror(req
, nt_status_squash(status
));
818 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
819 (unsigned long)secblob
.length
));
822 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
823 USE_KERBEROS_KEYTAB
) ) {
824 bool destroy_vuid
= True
;
825 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
826 vuid
, &destroy_vuid
);
827 data_blob_free(&secblob
);
829 /* Kill the intermediate vuid */
830 invalidate_vuid(sconn
, vuid
);
832 TALLOC_FREE(kerb_mech
);
837 if (*auth_ntlmssp_state
) {
838 TALLOC_FREE(*auth_ntlmssp_state
);
842 data_blob_free(&secblob
);
843 /* The mechtoken is a krb5 ticket, but
844 * we need to fall back to NTLM. */
845 reply_spnego_downgrade_to_ntlmssp(req
, vuid
);
846 TALLOC_FREE(kerb_mech
);
850 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
851 if (!NT_STATUS_IS_OK(status
)) {
852 /* Kill the intermediate vuid */
853 invalidate_vuid(sconn
, vuid
);
854 reply_nterror(req
, nt_status_squash(status
));
858 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
861 data_blob_free(&secblob
);
863 reply_spnego_ntlmssp(req
, vuid
, auth_ntlmssp_state
,
864 &chal
, status
, OID_NTLMSSP
, true);
866 data_blob_free(&chal
);
868 /* already replied */
872 /****************************************************************************
873 Reply to a session setup spnego auth packet.
874 ****************************************************************************/
876 static void reply_spnego_auth(struct smb_request
*req
,
879 struct auth_ntlmssp_state
**auth_ntlmssp_state
)
881 DATA_BLOB auth
= data_blob_null
;
882 DATA_BLOB auth_reply
= data_blob_null
;
883 DATA_BLOB secblob
= data_blob_null
;
884 NTSTATUS status
= NT_STATUS_LOGON_FAILURE
;
885 struct smbd_server_connection
*sconn
= req
->sconn
;
887 if (!spnego_parse_auth(talloc_tos(), blob1
, &auth
)) {
889 file_save("auth.dat", blob1
.data
, blob1
.length
);
891 /* Kill the intermediate vuid */
892 invalidate_vuid(sconn
, vuid
);
894 reply_nterror(req
, nt_status_squash(
895 NT_STATUS_LOGON_FAILURE
));
899 if (auth
.data
[0] == ASN1_APPLICATION(0)) {
900 /* Might be a second negTokenTarg packet */
901 char *kerb_mech
= NULL
;
903 status
= parse_spnego_mechanisms(talloc_tos(),
904 auth
, &secblob
, &kerb_mech
);
906 if (!NT_STATUS_IS_OK(status
)) {
907 /* Kill the intermediate vuid */
908 invalidate_vuid(sconn
, vuid
);
909 reply_nterror(req
, nt_status_squash(status
));
913 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
914 (unsigned long)secblob
.length
));
916 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
917 USE_KERBEROS_KEYTAB
)) {
918 bool destroy_vuid
= True
;
919 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
920 vuid
, &destroy_vuid
);
921 data_blob_free(&secblob
);
922 data_blob_free(&auth
);
924 /* Kill the intermediate vuid */
925 invalidate_vuid(sconn
, vuid
);
927 TALLOC_FREE(kerb_mech
);
931 /* Can't blunder into NTLMSSP auth if we have
935 /* Kill the intermediate vuid */
936 invalidate_vuid(sconn
, vuid
);
937 DEBUG(3,("reply_spnego_auth: network "
938 "misconfiguration, client sent us a "
939 "krb5 ticket and kerberos security "
941 reply_nterror(req
, nt_status_squash(
942 NT_STATUS_LOGON_FAILURE
));
943 TALLOC_FREE(kerb_mech
);
947 /* If we get here it wasn't a negTokenTarg auth packet. */
948 data_blob_free(&secblob
);
950 if (!*auth_ntlmssp_state
) {
951 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
952 if (!NT_STATUS_IS_OK(status
)) {
953 /* Kill the intermediate vuid */
954 invalidate_vuid(sconn
, vuid
);
955 reply_nterror(req
, nt_status_squash(status
));
960 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
963 data_blob_free(&auth
);
965 /* Don't send the mechid as we've already sent this (RFC4178). */
967 reply_spnego_ntlmssp(req
, vuid
,
969 &auth_reply
, status
, NULL
, true);
971 data_blob_free(&auth_reply
);
973 /* and tell smbd that we have already replied to this packet */
977 /****************************************************************************
978 Delete an entry on the list.
979 ****************************************************************************/
981 static void delete_partial_auth(struct smbd_server_connection
*sconn
,
982 struct pending_auth_data
*pad
)
987 DLIST_REMOVE(sconn
->smb1
.pd_list
, pad
);
988 data_blob_free(&pad
->partial_data
);
992 /****************************************************************************
993 Search for a partial SPNEGO auth fragment matching an smbpid.
994 ****************************************************************************/
996 static struct pending_auth_data
*get_pending_auth_data(
997 struct smbd_server_connection
*sconn
,
1000 struct pending_auth_data
*pad
;
1002 * NOTE: using the smbpid here is completely wrong...
1004 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
1006 for (pad
= sconn
->smb1
.pd_list
; pad
; pad
= pad
->next
) {
1007 if (pad
->smbpid
== smbpid
) {
1014 /****************************************************************************
1015 Check the size of an SPNEGO blob. If we need more return
1016 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1017 the blob to be more than 64k.
1018 ****************************************************************************/
1020 static NTSTATUS
check_spnego_blob_complete(struct smbd_server_connection
*sconn
,
1021 uint16 smbpid
, uint16 vuid
,
1024 struct pending_auth_data
*pad
= NULL
;
1026 size_t needed_len
= 0;
1028 pad
= get_pending_auth_data(sconn
, smbpid
);
1030 /* Ensure we have some data. */
1031 if (pblob
->length
== 0) {
1032 /* Caller can cope. */
1033 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1034 delete_partial_auth(sconn
, pad
);
1035 return NT_STATUS_OK
;
1038 /* Were we waiting for more data ? */
1041 size_t copy_len
= MIN(65536, pblob
->length
);
1043 /* Integer wrap paranoia.... */
1045 if (pad
->partial_data
.length
+ copy_len
<
1046 pad
->partial_data
.length
||
1047 pad
->partial_data
.length
+ copy_len
< copy_len
) {
1049 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1050 "pad->partial_data.length = %u, "
1052 (unsigned int)pad
->partial_data
.length
,
1053 (unsigned int)copy_len
));
1055 delete_partial_auth(sconn
, pad
);
1056 return NT_STATUS_INVALID_PARAMETER
;
1059 DEBUG(10,("check_spnego_blob_complete: "
1060 "pad->partial_data.length = %u, "
1061 "pad->needed_len = %u, "
1063 "pblob->length = %u,\n",
1064 (unsigned int)pad
->partial_data
.length
,
1065 (unsigned int)pad
->needed_len
,
1066 (unsigned int)copy_len
,
1067 (unsigned int)pblob
->length
));
1069 tmp_blob
= data_blob(NULL
,
1070 pad
->partial_data
.length
+ copy_len
);
1072 /* Concatenate the two (up to copy_len) bytes. */
1073 memcpy(tmp_blob
.data
,
1074 pad
->partial_data
.data
,
1075 pad
->partial_data
.length
);
1076 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
1080 /* Replace the partial data. */
1081 data_blob_free(&pad
->partial_data
);
1082 pad
->partial_data
= tmp_blob
;
1083 ZERO_STRUCT(tmp_blob
);
1086 if (pblob
->length
>= pad
->needed_len
) {
1087 /* Yes, replace pblob. */
1088 data_blob_free(pblob
);
1089 *pblob
= pad
->partial_data
;
1090 ZERO_STRUCT(pad
->partial_data
);
1091 delete_partial_auth(sconn
, pad
);
1092 return NT_STATUS_OK
;
1095 /* Still need more data. */
1096 pad
->needed_len
-= copy_len
;
1097 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1100 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
1101 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
1102 /* Not something we can determine the
1105 return NT_STATUS_OK
;
1108 /* This is a new SPNEGO sessionsetup - see if
1109 * the data given in this blob is enough.
1112 data
= asn1_init(NULL
);
1114 return NT_STATUS_NO_MEMORY
;
1117 asn1_load(data
, *pblob
);
1118 asn1_start_tag(data
, pblob
->data
[0]);
1119 if (data
->has_error
|| data
->nesting
== NULL
) {
1121 /* Let caller catch. */
1122 return NT_STATUS_OK
;
1125 /* Integer wrap paranoia.... */
1127 if (data
->nesting
->taglen
+ data
->nesting
->start
< data
->nesting
->taglen
||
1128 data
->nesting
->taglen
+ data
->nesting
->start
< data
->nesting
->start
) {
1130 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1131 "data.nesting->taglen = %u, "
1132 "data.nesting->start = %u\n",
1133 (unsigned int)data
->nesting
->taglen
,
1134 (unsigned int)data
->nesting
->start
));
1137 return NT_STATUS_INVALID_PARAMETER
;
1140 /* Total length of the needed asn1 is the tag length
1141 * plus the current offset. */
1143 needed_len
= data
->nesting
->taglen
+ data
->nesting
->start
;
1146 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1147 "pblob->length = %u\n",
1148 (unsigned int)needed_len
,
1149 (unsigned int)pblob
->length
));
1151 if (needed_len
<= pblob
->length
) {
1152 /* Nothing to do - blob is complete. */
1153 return NT_STATUS_OK
;
1156 /* Refuse the blob if it's bigger than 64k. */
1157 if (needed_len
> 65536) {
1158 DEBUG(2,("check_spnego_blob_complete: needed_len "
1160 (unsigned int)needed_len
));
1161 return NT_STATUS_INVALID_PARAMETER
;
1164 /* We must store this blob until complete. */
1165 if (!(pad
= SMB_MALLOC_P(struct pending_auth_data
))) {
1166 return NT_STATUS_NO_MEMORY
;
1168 pad
->needed_len
= needed_len
- pblob
->length
;
1169 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
1170 if (pad
->partial_data
.data
== NULL
) {
1172 return NT_STATUS_NO_MEMORY
;
1174 pad
->smbpid
= smbpid
;
1176 DLIST_ADD(sconn
->smb1
.pd_list
, pad
);
1178 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1181 /****************************************************************************
1182 Reply to a session setup command.
1183 conn POINTER CAN BE NULL HERE !
1184 ****************************************************************************/
1186 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
1192 const char *native_os
;
1193 const char *native_lanman
;
1194 const char *primary_domain
;
1196 uint16 data_blob_len
= SVAL(req
->vwv
+7, 0);
1197 enum remote_arch_types ra_type
= get_remote_arch();
1198 int vuid
= req
->vuid
;
1199 user_struct
*vuser
= NULL
;
1200 NTSTATUS status
= NT_STATUS_OK
;
1201 uint16 smbpid
= req
->smbpid
;
1202 struct smbd_server_connection
*sconn
= req
->sconn
;
1204 DEBUG(3,("Doing spnego session setup\n"));
1206 if (global_client_caps
== 0) {
1207 global_client_caps
= IVAL(req
->vwv
+10, 0);
1209 if (!(global_client_caps
& CAP_STATUS32
)) {
1210 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1217 if (data_blob_len
== 0) {
1218 /* an invalid request */
1219 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1223 bufrem
= smbreq_bufrem(req
, p
);
1224 /* pull the spnego blob */
1225 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
1228 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
1231 p2
= (char *)req
->buf
+ blob1
.length
;
1233 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1235 native_os
= tmp
? tmp
: "";
1237 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1239 native_lanman
= tmp
? tmp
: "";
1241 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1243 primary_domain
= tmp
? tmp
: "";
1245 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1246 native_os
, native_lanman
, primary_domain
));
1248 if ( ra_type
== RA_WIN2K
) {
1249 /* Vista sets neither the OS or lanman strings */
1251 if ( !strlen(native_os
) && !strlen(native_lanman
) )
1252 set_remote_arch(RA_VISTA
);
1254 /* Windows 2003 doesn't set the native lanman string,
1255 but does set primary domain which is a bug I think */
1257 if ( !strlen(native_lanman
) ) {
1258 ra_lanman_string( primary_domain
);
1260 ra_lanman_string( native_lanman
);
1264 /* Did we get a valid vuid ? */
1265 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1266 /* No, then try and see if this is an intermediate sessionsetup
1267 * for a large SPNEGO packet. */
1268 struct pending_auth_data
*pad
;
1269 pad
= get_pending_auth_data(sconn
, smbpid
);
1271 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1272 "pending vuid %u\n",
1273 (unsigned int)pad
->vuid
));
1278 /* Do we have a valid vuid now ? */
1279 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1280 /* No, start a new authentication setup. */
1281 vuid
= register_initial_vuid(sconn
);
1282 if (vuid
== UID_FIELD_INVALID
) {
1283 data_blob_free(&blob1
);
1284 reply_nterror(req
, nt_status_squash(
1285 NT_STATUS_INVALID_PARAMETER
));
1290 vuser
= get_partial_auth_user_struct(sconn
, vuid
);
1291 /* This MUST be valid. */
1293 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1296 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1297 * sessionsetup requests as the Windows limit on the security blob
1298 * field is 4k. Bug #4400. JRA.
1301 status
= check_spnego_blob_complete(sconn
, smbpid
, vuid
, &blob1
);
1302 if (!NT_STATUS_IS_OK(status
)) {
1303 if (!NT_STATUS_EQUAL(status
,
1304 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1305 /* Real error - kill the intermediate vuid */
1306 invalidate_vuid(sconn
, vuid
);
1308 data_blob_free(&blob1
);
1309 reply_nterror(req
, nt_status_squash(status
));
1313 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
1315 /* its a negTokenTarg packet */
1317 reply_spnego_negotiate(req
, vuid
, blob1
,
1318 &vuser
->auth_ntlmssp_state
);
1319 data_blob_free(&blob1
);
1323 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
1325 /* its a auth packet */
1327 reply_spnego_auth(req
, vuid
, blob1
,
1328 &vuser
->auth_ntlmssp_state
);
1329 data_blob_free(&blob1
);
1333 if (strncmp((char *)(blob1
.data
), "NTLMSSP", 7) == 0) {
1336 if (!vuser
->auth_ntlmssp_state
) {
1337 status
= auth_ntlmssp_start(&vuser
->auth_ntlmssp_state
);
1338 if (!NT_STATUS_IS_OK(status
)) {
1339 /* Kill the intermediate vuid */
1340 invalidate_vuid(sconn
, vuid
);
1341 data_blob_free(&blob1
);
1342 reply_nterror(req
, nt_status_squash(status
));
1347 status
= auth_ntlmssp_update(vuser
->auth_ntlmssp_state
,
1350 data_blob_free(&blob1
);
1352 reply_spnego_ntlmssp(req
, vuid
,
1353 &vuser
->auth_ntlmssp_state
,
1354 &chal
, status
, OID_NTLMSSP
, false);
1355 data_blob_free(&chal
);
1359 /* what sort of packet is this? */
1360 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1362 data_blob_free(&blob1
);
1364 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1367 /****************************************************************************
1368 On new VC == 0, shutdown *all* old connections and users.
1369 It seems that only NT4.x does this. At W2K and above (XP etc.).
1370 a new session setup with VC==0 is ignored.
1371 ****************************************************************************/
1373 struct shutdown_state
{
1375 struct messaging_context
*msg_ctx
;
1378 static int shutdown_other_smbds(const struct connections_key
*key
,
1379 const struct connections_data
*crec
,
1382 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
1384 if (!process_exists(crec
->pid
)) {
1388 if (procid_is_me(&crec
->pid
)) {
1392 if (strcmp(state
->ip
, crec
->addr
) != 0) {
1396 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1397 "(IP %s)\n", (unsigned int)procid_to_pid(&crec
->pid
),
1400 messaging_send(state
->msg_ctx
, crec
->pid
, MSG_SHUTDOWN
,
1405 static void setup_new_vc_session(struct messaging_context
*msg_ctx
)
1407 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1408 "compatible we would close all old resources.\n"));
1411 invalidate_all_vuids();
1413 if (lp_reset_on_zero_vc()) {
1414 char addr
[INET6_ADDRSTRLEN
];
1415 struct shutdown_state state
;
1417 state
.ip
= client_addr(get_client_fd(),addr
,sizeof(addr
));
1418 state
.msg_ctx
= msg_ctx
;
1419 connections_forall_read(shutdown_other_smbds
, &state
);
1423 /****************************************************************************
1424 Reply to a session setup command.
1425 ****************************************************************************/
1427 void reply_sesssetup_and_X(struct smb_request
*req
)
1433 DATA_BLOB plaintext_password
;
1436 fstring sub_user
; /* Sanitised username for substituion */
1438 const char *native_os
;
1439 const char *native_lanman
;
1440 const char *primary_domain
;
1441 struct auth_usersupplied_info
*user_info
= NULL
;
1442 struct auth_serversupplied_info
*server_info
= NULL
;
1443 uint16 smb_flag2
= req
->flags2
;
1446 struct smbd_server_connection
*sconn
= req
->sconn
;
1448 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
1450 START_PROFILE(SMBsesssetupX
);
1452 ZERO_STRUCT(lm_resp
);
1453 ZERO_STRUCT(nt_resp
);
1454 ZERO_STRUCT(plaintext_password
);
1456 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
1458 /* a SPNEGO session setup has 12 command words, whereas a normal
1459 NT1 session setup has 13. See the cifs spec. */
1460 if (req
->wct
== 12 &&
1461 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
1463 if (!sconn
->smb1
.negprot
.spnego
) {
1464 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1465 "at SPNEGO session setup when it was not "
1467 reply_nterror(req
, nt_status_squash(
1468 NT_STATUS_LOGON_FAILURE
));
1469 END_PROFILE(SMBsesssetupX
);
1473 if (SVAL(req
->vwv
+4, 0) == 0) {
1474 setup_new_vc_session(req
->sconn
->msg_ctx
);
1477 reply_sesssetup_and_X_spnego(req
);
1478 END_PROFILE(SMBsesssetupX
);
1482 smb_bufsize
= SVAL(req
->vwv
+2, 0);
1484 if (get_Protocol() < PROTOCOL_NT1
) {
1485 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1487 /* Never do NT status codes with protocols before NT1 as we
1488 * don't get client caps. */
1489 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1491 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
1492 reply_nterror(req
, nt_status_squash(
1493 NT_STATUS_INVALID_PARAMETER
));
1494 END_PROFILE(SMBsesssetupX
);
1499 lm_resp
= data_blob(req
->buf
, passlen1
);
1501 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
1502 /* Ensure null termination */
1503 plaintext_password
.data
[passlen1
] = 0;
1506 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
1507 req
->buf
+ passlen1
, STR_TERMINATE
);
1508 user
= tmp
? tmp
: "";
1513 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1514 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
1515 enum remote_arch_types ra_type
= get_remote_arch();
1516 const uint8_t *p
= req
->buf
;
1517 const uint8_t *save_p
= req
->buf
;
1521 if(global_client_caps
== 0) {
1522 global_client_caps
= IVAL(req
->vwv
+11, 0);
1524 if (!(global_client_caps
& CAP_STATUS32
)) {
1525 remove_from_common_flags2(
1526 FLAGS2_32_BIT_ERROR_CODES
);
1529 /* client_caps is used as final determination if
1530 * client is NT or Win95. This is needed to return
1531 * the correct error codes in some circumstances.
1534 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
1535 ra_type
== RA_WIN95
) {
1536 if(!(global_client_caps
& (CAP_NT_SMBS
|
1538 set_remote_arch( RA_WIN95
);
1544 /* both Win95 and WinNT stuff up the password
1545 * lengths for non-encrypting systems. Uggh.
1547 if passlen1==24 its a win95 system, and its setting
1548 the password length incorrectly. Luckily it still
1549 works with the default code because Win95 will null
1550 terminate the password anyway
1552 if passlen1>0 and passlen2>0 then maybe its a NT box
1553 and its setting passlen2 to some random value which
1554 really stuffs things up. we need to fix that one. */
1556 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
1562 /* check for nasty tricks */
1563 if (passlen1
> MAX_PASS_LEN
1564 || passlen1
> smbreq_bufrem(req
, p
)) {
1565 reply_nterror(req
, nt_status_squash(
1566 NT_STATUS_INVALID_PARAMETER
));
1567 END_PROFILE(SMBsesssetupX
);
1571 if (passlen2
> MAX_PASS_LEN
1572 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
1573 reply_nterror(req
, nt_status_squash(
1574 NT_STATUS_INVALID_PARAMETER
));
1575 END_PROFILE(SMBsesssetupX
);
1579 /* Save the lanman2 password and the NT md4 password. */
1581 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1586 lm_resp
= data_blob(p
, passlen1
);
1587 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1588 } else if (lp_security() != SEC_SHARE
) {
1590 * In share level we should ignore any passwords, so
1591 * only read them if we're not.
1594 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
1596 if (unic
&& (passlen2
== 0) && passlen1
) {
1597 /* Only a ascii plaintext password was sent. */
1598 (void)srvstr_pull_talloc(talloc_tos(),
1604 STR_TERMINATE
|STR_ASCII
);
1606 (void)srvstr_pull_talloc(talloc_tos(),
1611 unic
? passlen2
: passlen1
,
1615 reply_nterror(req
, nt_status_squash(
1616 NT_STATUS_INVALID_PARAMETER
));
1617 END_PROFILE(SMBsesssetupX
);
1620 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1623 p
+= passlen1
+ passlen2
;
1625 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1627 user
= tmp
? tmp
: "";
1629 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1631 domain
= tmp
? tmp
: "";
1633 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1635 native_os
= tmp
? tmp
: "";
1637 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1639 native_lanman
= tmp
? tmp
: "";
1641 /* not documented or decoded by Ethereal but there is one more
1642 * string in the extra bytes which is the same as the
1643 * PrimaryDomain when using extended security. Windows NT 4
1644 * and 2003 use this string to store the native lanman string.
1645 * Windows 9x does not include a string here at all so we have
1646 * to check if we have any extra bytes left */
1648 byte_count
= SVAL(req
->vwv
+13, 0);
1649 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
1650 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1652 primary_domain
= tmp
? tmp
: "";
1654 primary_domain
= talloc_strdup(talloc_tos(), "null");
1657 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1658 "PrimaryDomain=[%s]\n",
1659 domain
, native_os
, native_lanman
, primary_domain
));
1661 if ( ra_type
== RA_WIN2K
) {
1662 if ( strlen(native_lanman
) == 0 )
1663 ra_lanman_string( primary_domain
);
1665 ra_lanman_string( native_lanman
);
1670 if (SVAL(req
->vwv
+4, 0) == 0) {
1671 setup_new_vc_session(req
->sconn
->msg_ctx
);
1674 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1675 domain
, user
, get_remote_machine_name()));
1678 if (sconn
->smb1
.negprot
.spnego
) {
1680 /* This has to be here, because this is a perfectly
1681 * valid behaviour for guest logons :-( */
1683 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1684 "at 'normal' session setup after "
1685 "negotiating spnego.\n"));
1686 reply_nterror(req
, nt_status_squash(
1687 NT_STATUS_LOGON_FAILURE
));
1688 END_PROFILE(SMBsesssetupX
);
1691 fstrcpy(sub_user
, user
);
1693 fstrcpy(sub_user
, lp_guestaccount());
1696 sub_set_smb_name(sub_user
);
1698 reload_services(sconn
->msg_ctx
, True
);
1700 if (lp_security() == SEC_SHARE
) {
1701 /* In share level we should ignore any passwords */
1703 data_blob_free(&lm_resp
);
1704 data_blob_free(&nt_resp
);
1705 data_blob_clear_free(&plaintext_password
);
1707 map_username(sub_user
);
1708 add_session_user(sconn
, sub_user
);
1709 add_session_workgroup(sconn
, domain
);
1710 /* Then force it to null for the benfit of the code below */
1716 nt_status
= check_guest_password(&server_info
);
1718 } else if (doencrypt
) {
1719 struct auth_context
*negprot_auth_context
= NULL
;
1720 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
1721 if (!negprot_auth_context
) {
1722 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1723 "session setup without negprot denied!\n"));
1724 reply_nterror(req
, nt_status_squash(
1725 NT_STATUS_LOGON_FAILURE
));
1726 END_PROFILE(SMBsesssetupX
);
1729 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
1732 if (NT_STATUS_IS_OK(nt_status
)) {
1733 nt_status
= negprot_auth_context
->check_ntlm_password(
1734 negprot_auth_context
,
1739 struct auth_context
*plaintext_auth_context
= NULL
;
1741 nt_status
= make_auth_context_subsystem(
1742 &plaintext_auth_context
);
1744 if (NT_STATUS_IS_OK(nt_status
)) {
1747 plaintext_auth_context
->get_ntlm_challenge(
1748 plaintext_auth_context
, chal
);
1750 if (!make_user_info_for_reply(&user_info
,
1752 plaintext_password
)) {
1753 nt_status
= NT_STATUS_NO_MEMORY
;
1756 if (NT_STATUS_IS_OK(nt_status
)) {
1757 nt_status
= plaintext_auth_context
->check_ntlm_password(
1758 plaintext_auth_context
,
1762 TALLOC_FREE(plaintext_auth_context
);
1767 free_user_info(&user_info
);
1769 if (!NT_STATUS_IS_OK(nt_status
)) {
1770 nt_status
= do_map_to_guest(nt_status
, &server_info
,
1774 if (!NT_STATUS_IS_OK(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
);
1783 /* Ensure we can't possible take a code path leading to a
1786 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1787 END_PROFILE(SMBsesssetupX
);
1791 if (!server_info
->ptok
) {
1792 nt_status
= create_local_token(server_info
);
1794 if (!NT_STATUS_IS_OK(nt_status
)) {
1795 DEBUG(10, ("create_local_token failed: %s\n",
1796 nt_errstr(nt_status
)));
1797 data_blob_free(&nt_resp
);
1798 data_blob_free(&lm_resp
);
1799 data_blob_clear_free(&plaintext_password
);
1800 reply_nterror(req
, nt_status_squash(nt_status
));
1801 END_PROFILE(SMBsesssetupX
);
1806 data_blob_clear_free(&plaintext_password
);
1808 /* it's ok - setup a reply */
1809 reply_outbuf(req
, 3, 0);
1810 if (get_Protocol() >= PROTOCOL_NT1
) {
1811 push_signature(&req
->outbuf
);
1812 /* perhaps grab OS version here?? */
1815 if (server_info
->guest
) {
1816 SSVAL(req
->outbuf
,smb_vwv2
,1);
1819 /* register the name and uid as being validated, so further connections
1820 to a uid can get through without a password, on the same VC */
1822 if (lp_security() == SEC_SHARE
) {
1823 sess_vuid
= UID_FIELD_INVALID
;
1824 TALLOC_FREE(server_info
);
1826 /* Ignore the initial vuid. */
1827 sess_vuid
= register_initial_vuid(sconn
);
1828 if (sess_vuid
== UID_FIELD_INVALID
) {
1829 data_blob_free(&nt_resp
);
1830 data_blob_free(&lm_resp
);
1831 reply_nterror(req
, nt_status_squash(
1832 NT_STATUS_LOGON_FAILURE
));
1833 END_PROFILE(SMBsesssetupX
);
1836 /* register_existing_vuid keeps the server info */
1837 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
1839 nt_resp
.data
? nt_resp
: lm_resp
,
1841 if (sess_vuid
== UID_FIELD_INVALID
) {
1842 data_blob_free(&nt_resp
);
1843 data_blob_free(&lm_resp
);
1844 reply_nterror(req
, nt_status_squash(
1845 NT_STATUS_LOGON_FAILURE
));
1846 END_PROFILE(SMBsesssetupX
);
1850 /* current_user_info is changed on new vuid */
1851 reload_services(sconn
->msg_ctx
, True
);
1854 data_blob_free(&nt_resp
);
1855 data_blob_free(&lm_resp
);
1857 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1858 SSVAL(req
->inbuf
,smb_uid
,sess_vuid
);
1859 req
->vuid
= sess_vuid
;
1861 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
1862 sconn
->smb1
.sessions
.max_send
=
1863 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
1865 sconn
->smb1
.sessions
.done_sesssetup
= true;
1867 END_PROFILE(SMBsesssetupX
);