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/>.
27 extern struct auth_context
*negprot_global_auth_context
;
28 extern bool global_encrypted_passwords_negotiated
;
29 extern bool global_spnego_negotiated
;
30 extern enum protocol_types Protocol
;
33 uint32 global_client_caps
= 0;
36 on a logon error possibly map the error to success if "map to guest"
39 static NTSTATUS
do_map_to_guest(NTSTATUS status
,
40 auth_serversupplied_info
**server_info
,
41 const char *user
, const char *domain
)
43 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
44 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
45 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
46 DEBUG(3,("No such user %s [%s] - using guest account\n",
48 status
= make_server_info_guest(server_info
);
52 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
53 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
54 DEBUG(3,("Registered username %s for guest access\n",
56 status
= make_server_info_guest(server_info
);
63 /****************************************************************************
64 Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
67 static int push_signature(uint8
**outbuf
)
74 tmp
= message_push_string(outbuf
, "Unix", STR_TERMINATE
);
76 if (tmp
== -1) return -1;
79 if (asprintf(&lanman
, "Samba %s", SAMBA_VERSION_STRING
) != -1) {
80 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
84 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
87 if (tmp
== -1) return -1;
90 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
92 if (tmp
== -1) return -1;
98 /****************************************************************************
99 Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
102 static void sessionsetup_start_signing_engine(
103 const auth_serversupplied_info
*server_info
,
106 if (!server_info
->guest
&& !srv_signing_started()) {
107 /* We need to start the signing engine
108 * here but a W2K client sends the old
109 * "BSRSPYL " signature instead of the
110 * correct one. Subsequent packets will
113 srv_check_sign_mac((char *)inbuf
, False
);
117 /****************************************************************************
118 Send a security blob via a session setup reply.
119 ****************************************************************************/
121 static void reply_sesssetup_blob(struct smb_request
*req
,
125 if (!NT_STATUS_IS_OK(nt_status
) &&
126 !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
127 reply_nterror(req
, nt_status_squash(nt_status
));
129 nt_status
= nt_status_squash(nt_status
);
130 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
131 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
132 SSVAL(req
->outbuf
, smb_vwv3
, blob
.length
);
134 if ((message_push_blob(&req
->outbuf
, blob
) == -1)
135 || (push_signature(&req
->outbuf
) == -1)) {
136 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
140 show_msg((char *)req
->outbuf
);
141 srv_send_smb(smbd_server_fd(),(char *)req
->outbuf
,req
->encrypted
);
142 TALLOC_FREE(req
->outbuf
);
145 /****************************************************************************
146 Do a 'guest' logon, getting back the
147 ****************************************************************************/
149 static NTSTATUS
check_guest_password(auth_serversupplied_info
**server_info
)
151 struct auth_context
*auth_context
;
152 auth_usersupplied_info
*user_info
= NULL
;
155 unsigned char chal
[8];
159 DEBUG(3,("Got anonymous request\n"));
161 if (!NT_STATUS_IS_OK(nt_status
= make_auth_context_fixed(&auth_context
,
166 if (!make_user_info_guest(&user_info
)) {
167 (auth_context
->free
)(&auth_context
);
168 return NT_STATUS_NO_MEMORY
;
171 nt_status
= auth_context
->check_ntlm_password(auth_context
,
174 (auth_context
->free
)(&auth_context
);
175 free_user_info(&user_info
);
183 /* Experiment that failed. See "only happens with a KDC" comment below. */
184 /****************************************************************************
185 Cerate a clock skew error blob for a Windows client.
186 ****************************************************************************/
188 static bool make_krb5_skew_error(DATA_BLOB
*pblob_out
)
190 krb5_context context
= NULL
;
191 krb5_error_code kerr
= 0;
193 krb5_principal host_princ
= NULL
;
194 char *host_princ_s
= NULL
;
197 *pblob_out
= data_blob_null
;
199 initialize_krb5_error_table();
200 kerr
= krb5_init_context(&context
);
204 /* Create server principal. */
205 asprintf(&host_princ_s
, "%s$@%s", global_myname(), lp_realm());
209 strlower_m(host_princ_s
);
211 kerr
= smb_krb5_parse_name(context
, host_princ_s
, &host_princ
);
213 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
214 "for name %s: Error %s\n",
215 host_princ_s
, error_message(kerr
) ));
219 kerr
= smb_krb5_mk_error(context
, KRB5KRB_AP_ERR_SKEW
,
222 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
223 "failed: Error %s\n",
224 error_message(kerr
) ));
228 *pblob_out
= data_blob(reply
.data
, reply
.length
);
229 kerberos_free_data_contents(context
,&reply
);
235 SAFE_FREE(host_princ_s
);
238 krb5_free_principal(context
, host_princ
);
240 krb5_free_context(context
);
245 /****************************************************************************
246 Reply to a session setup spnego negotiate packet for kerberos.
247 ****************************************************************************/
249 static void reply_spnego_kerberos(struct smb_request
*req
,
252 bool *p_invalidate_vuid
)
256 char *client
, *p
, *domain
;
257 fstring netbios_domain_name
;
260 int sess_vuid
= req
->vuid
;
261 NTSTATUS ret
= NT_STATUS_OK
;
262 struct PAC_DATA
*pac_data
= NULL
;
263 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
264 auth_serversupplied_info
*server_info
= NULL
;
265 DATA_BLOB session_key
= data_blob_null
;
267 DATA_BLOB nullblob
= data_blob_null
;
268 fstring real_username
;
269 bool map_domainuser_to_guest
= False
;
270 bool username_was_mapped
;
271 struct PAC_LOGON_INFO
*logon_info
= NULL
;
275 ZERO_STRUCT(ap_rep_wrapped
);
276 ZERO_STRUCT(response
);
278 /* Normally we will always invalidate the intermediate vuid. */
279 *p_invalidate_vuid
= True
;
281 mem_ctx
= talloc_init("reply_spnego_kerberos");
282 if (mem_ctx
== NULL
) {
283 reply_nterror(req
, nt_status_squash(NT_STATUS_NO_MEMORY
));
287 if (!spnego_parse_krb5_wrap(*secblob
, &ticket
, tok_id
)) {
288 talloc_destroy(mem_ctx
);
289 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
293 ret
= ads_verify_ticket(mem_ctx
, lp_realm(), 0, &ticket
,
294 &client
, &pac_data
, &ap_rep
,
297 data_blob_free(&ticket
);
299 if (!NT_STATUS_IS_OK(ret
)) {
301 /* Experiment that failed.
302 * See "only happens with a KDC" comment below. */
304 if (NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
307 * Windows in this case returns
308 * NT_STATUS_MORE_PROCESSING_REQUIRED
309 * with a negTokenTarg blob containing an krb5_error
310 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
311 * The client then fixes its clock and continues rather
312 * than giving an error. JRA.
313 * -- Looks like this only happens with a KDC. JRA.
316 bool ok
= make_krb5_skew_error(&ap_rep
);
318 talloc_destroy(mem_ctx
);
319 return ERROR_NT(nt_status_squash(
320 NT_STATUS_LOGON_FAILURE
));
322 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
324 response
= spnego_gen_auth_response(&ap_rep_wrapped
,
325 ret
, OID_KERBEROS5_OLD
);
326 reply_sesssetup_blob(conn
, inbuf
, outbuf
, response
,
327 NT_STATUS_MORE_PROCESSING_REQUIRED
);
330 * In this one case we don't invalidate the
331 * intermediate vuid as we're expecting the client
332 * to re-use it for the next sessionsetupX packet. JRA.
335 *p_invalidate_vuid
= False
;
337 data_blob_free(&ap_rep
);
338 data_blob_free(&ap_rep_wrapped
);
339 data_blob_free(&response
);
340 talloc_destroy(mem_ctx
);
341 return -1; /* already replied */
344 if (!NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
345 ret
= NT_STATUS_LOGON_FAILURE
;
348 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
350 talloc_destroy(mem_ctx
);
351 reply_nterror(req
, nt_status_squash(ret
));
355 DEBUG(3,("Ticket name is [%s]\n", client
));
357 p
= strchr_m(client
, '@');
359 DEBUG(3,("Doesn't look like a valid principal\n"));
360 data_blob_free(&ap_rep
);
361 data_blob_free(&session_key
);
363 talloc_destroy(mem_ctx
);
364 reply_nterror(req
,nt_status_squash(NT_STATUS_LOGON_FAILURE
));
370 /* save the PAC data if we have it */
373 logon_info
= get_logon_info_from_pac(pac_data
);
375 netsamlogon_cache_store( client
, &logon_info
->info3
);
379 if (!strequal(p
+1, lp_realm())) {
380 DEBUG(3,("Ticket for foreign realm %s@%s\n", client
, p
+1));
381 if (!lp_allow_trusted_domains()) {
382 data_blob_free(&ap_rep
);
383 data_blob_free(&session_key
);
385 talloc_destroy(mem_ctx
);
386 reply_nterror(req
, nt_status_squash(
387 NT_STATUS_LOGON_FAILURE
));
392 /* this gives a fully qualified user name (ie. with full realm).
393 that leads to very long usernames, but what else can we do? */
397 if (logon_info
&& logon_info
->info3
.base
.domain
.string
) {
398 fstrcpy(netbios_domain_name
,
399 logon_info
->info3
.base
.domain
.string
);
400 domain
= netbios_domain_name
;
401 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain
));
405 /* If we have winbind running, we can (and must) shorten the
406 username by using the short netbios name. Otherwise we will
407 have inconsistent user names. With Kerberos, we get the
408 fully qualified realm, with ntlmssp we get the short
409 name. And even w2k3 does use ntlmssp if you for example
410 connect to an ip address. */
413 struct wbcDomainInfo
*info
= NULL
;
415 DEBUG(10, ("Mapping [%s] to short name\n", domain
));
417 wbc_status
= wbcDomainInfo(domain
, &info
);
419 if (WBC_ERROR_IS_OK(wbc_status
)) {
421 fstrcpy(netbios_domain_name
,
425 domain
= netbios_domain_name
;
426 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain
));
428 DEBUG(3, ("Could not find short name: %s\n",
429 wbcErrorString(wbc_status
)));
433 fstr_sprintf(user
, "%s%c%s", domain
, *lp_winbind_separator(), client
);
435 /* lookup the passwd struct, create a new user if necessary */
437 username_was_mapped
= map_username( user
);
439 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
442 /* if a real user check pam account restrictions */
443 /* only really perfomed if "obey pam restriction" is true */
444 /* do this before an eventual mappign to guest occurs */
445 ret
= smb_pam_accountcheck(pw
->pw_name
);
446 if ( !NT_STATUS_IS_OK(ret
)) {
447 DEBUG(1,("PAM account restriction "
448 "prevents user login\n"));
449 data_blob_free(&ap_rep
);
450 data_blob_free(&session_key
);
451 TALLOC_FREE(mem_ctx
);
452 reply_nterror(req
, nt_status_squash(ret
));
459 /* this was originally the behavior of Samba 2.2, if a user
460 did not have a local uid but has been authenticated, then
461 map them to a guest account */
463 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID
){
464 map_domainuser_to_guest
= True
;
465 fstrcpy(user
,lp_guestaccount());
466 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
469 /* extra sanity check that the guest account is valid */
472 DEBUG(1,("Username %s is invalid on this system\n",
475 data_blob_free(&ap_rep
);
476 data_blob_free(&session_key
);
477 TALLOC_FREE(mem_ctx
);
478 reply_nterror(req
, nt_status_squash(
479 NT_STATUS_LOGON_FAILURE
));
484 /* setup the string used by %U */
486 sub_set_smb_name( real_username
);
487 reload_services(True
);
489 if ( map_domainuser_to_guest
) {
490 make_server_info_guest(&server_info
);
491 } else if (logon_info
) {
492 /* pass the unmapped username here since map_username()
493 will be called again from inside make_server_info_info3() */
495 ret
= make_server_info_info3(mem_ctx
, client
, domain
,
496 &server_info
, &logon_info
->info3
);
497 if ( !NT_STATUS_IS_OK(ret
) ) {
498 DEBUG(1,("make_server_info_info3 failed: %s!\n",
501 data_blob_free(&ap_rep
);
502 data_blob_free(&session_key
);
503 TALLOC_FREE(mem_ctx
);
504 reply_nterror(req
, nt_status_squash(ret
));
509 ret
= make_server_info_pw(&server_info
, real_username
, pw
);
511 if ( !NT_STATUS_IS_OK(ret
) ) {
512 DEBUG(1,("make_server_info_pw failed: %s!\n",
515 data_blob_free(&ap_rep
);
516 data_blob_free(&session_key
);
517 TALLOC_FREE(mem_ctx
);
518 reply_nterror(req
, nt_status_squash(ret
));
522 /* make_server_info_pw does not set the domain. Without this
523 * we end up with the local netbios name in substitutions for
526 if (server_info
->sam_account
!= NULL
) {
527 pdb_set_domain(server_info
->sam_account
,
532 if (username_was_mapped
) {
533 server_info
->was_mapped
= username_was_mapped
;
536 /* we need to build the token for the user. make_server_info_guest()
539 if ( !server_info
->ptok
) {
540 ret
= create_local_token( server_info
);
541 if ( !NT_STATUS_IS_OK(ret
) ) {
543 data_blob_free(&ap_rep
);
544 data_blob_free(&session_key
);
545 TALLOC_FREE( mem_ctx
);
546 TALLOC_FREE( server_info
);
547 reply_nterror(req
, nt_status_squash(ret
));
552 /* register_existing_vuid keeps the server info */
553 /* register_existing_vuid takes ownership of session_key on success,
554 * no need to free after this on success. A better interface would copy
557 if (!is_partial_auth_vuid(sess_vuid
)) {
558 sess_vuid
= register_initial_vuid();
560 sess_vuid
= register_existing_vuid(sess_vuid
,
568 reply_outbuf(req
, 4, 0);
569 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
571 if (sess_vuid
== UID_FIELD_INVALID
) {
572 ret
= NT_STATUS_LOGON_FAILURE
;
573 data_blob_free(&session_key
);
575 /* current_user_info is changed on new vuid */
576 reload_services( True
);
578 SSVAL(req
->outbuf
, smb_vwv3
, 0);
580 if (server_info
->guest
) {
581 SSVAL(req
->outbuf
,smb_vwv2
,1);
584 SSVAL(req
->outbuf
, smb_uid
, sess_vuid
);
586 sessionsetup_start_signing_engine(server_info
, req
->inbuf
);
587 /* Successful logon. Keep this vuid. */
588 *p_invalidate_vuid
= False
;
591 /* wrap that up in a nice GSS-API wrapping */
592 if (NT_STATUS_IS_OK(ret
)) {
593 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
596 ap_rep_wrapped
= data_blob_null
;
598 response
= spnego_gen_auth_response(&ap_rep_wrapped
, ret
,
600 reply_sesssetup_blob(req
, response
, ret
);
602 data_blob_free(&ap_rep
);
603 data_blob_free(&ap_rep_wrapped
);
604 data_blob_free(&response
);
605 TALLOC_FREE(mem_ctx
);
610 /****************************************************************************
611 Send a session setup reply, wrapped in SPNEGO.
612 Get vuid and check first.
613 End the NTLMSSP exchange context if we are OK/complete fail
614 This should be split into two functions, one to handle each
615 leg of the NTLM auth steps.
616 ***************************************************************************/
618 static void reply_spnego_ntlmssp(struct smb_request
*req
,
620 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
,
621 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
,
626 struct auth_serversupplied_info
*server_info
= NULL
;
628 if (NT_STATUS_IS_OK(nt_status
)) {
629 server_info
= (*auth_ntlmssp_state
)->server_info
;
631 nt_status
= do_map_to_guest(nt_status
,
633 (*auth_ntlmssp_state
)->ntlmssp_state
->user
,
634 (*auth_ntlmssp_state
)->ntlmssp_state
->domain
);
637 reply_outbuf(req
, 4, 0);
639 SSVAL(req
->outbuf
, smb_uid
, vuid
);
641 if (NT_STATUS_IS_OK(nt_status
)) {
642 DATA_BLOB nullblob
= data_blob_null
;
643 DATA_BLOB session_key
=
645 (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.data
,
646 (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.length
);
648 if (!is_partial_auth_vuid(vuid
)) {
649 data_blob_free(&session_key
);
650 nt_status
= NT_STATUS_LOGON_FAILURE
;
653 /* register_existing_vuid keeps the server info */
654 if (register_existing_vuid(vuid
,
656 session_key
, nullblob
,
657 (*auth_ntlmssp_state
)->ntlmssp_state
->user
) !=
659 data_blob_free(&session_key
);
660 nt_status
= NT_STATUS_LOGON_FAILURE
;
664 (*auth_ntlmssp_state
)->server_info
= NULL
;
666 /* current_user_info is changed on new vuid */
667 reload_services( True
);
669 SSVAL(req
->outbuf
, smb_vwv3
, 0);
671 if (server_info
->guest
) {
672 SSVAL(req
->outbuf
,smb_vwv2
,1);
675 sessionsetup_start_signing_engine(server_info
,
676 (uint8
*)req
->inbuf
);
682 response
= spnego_gen_auth_response(ntlmssp_blob
,
685 response
= *ntlmssp_blob
;
688 reply_sesssetup_blob(req
, response
, nt_status
);
690 data_blob_free(&response
);
693 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
694 and the other end, that we are not finished yet. */
696 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
697 /* NB. This is *NOT* an error case. JRA */
698 auth_ntlmssp_end(auth_ntlmssp_state
);
699 if (!NT_STATUS_IS_OK(nt_status
)) {
700 /* Kill the intermediate vuid */
701 invalidate_vuid(vuid
);
706 /****************************************************************************
707 Is this a krb5 mechanism ?
708 ****************************************************************************/
710 NTSTATUS
parse_spnego_mechanisms(DATA_BLOB blob_in
, DATA_BLOB
*pblob_out
,
713 char *OIDs
[ASN1_MAX_OIDS
];
718 /* parse out the OIDs and the first sec blob */
719 if (!parse_negTokenTarg(blob_in
, OIDs
, pblob_out
)) {
720 return NT_STATUS_LOGON_FAILURE
;
723 /* only look at the first OID for determining the mechToken --
724 according to RFC2478, we should choose the one we want
725 and renegotiate, but i smell a client bug here..
727 Problem observed when connecting to a member (samba box)
728 of an AD domain as a user in a Samba domain. Samba member
729 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
730 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
731 NTLMSSP mechtoken. --jerry */
734 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
735 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
740 for (i
=0;OIDs
[i
];i
++) {
741 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs
[i
]));
747 /****************************************************************************
748 Fall back from krb5 to NTLMSSP.
749 ****************************************************************************/
751 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request
*req
,
756 reply_outbuf(req
, 4, 0);
757 SSVAL(req
->outbuf
,smb_uid
,vuid
);
759 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
760 "but set to downgrade to NTLMSSP\n"));
762 response
= spnego_gen_auth_response(NULL
,
763 NT_STATUS_MORE_PROCESSING_REQUIRED
,
765 reply_sesssetup_blob(req
, response
, NT_STATUS_MORE_PROCESSING_REQUIRED
);
766 data_blob_free(&response
);
769 /****************************************************************************
770 Reply to a session setup spnego negotiate packet.
771 ****************************************************************************/
773 static void reply_spnego_negotiate(struct smb_request
*req
,
776 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
)
780 bool got_kerberos_mechanism
= False
;
783 status
= parse_spnego_mechanisms(blob1
, &secblob
,
784 &got_kerberos_mechanism
);
785 if (!NT_STATUS_IS_OK(status
)) {
786 /* Kill the intermediate vuid */
787 invalidate_vuid(vuid
);
788 reply_nterror(req
, nt_status_squash(status
));
792 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
793 (unsigned long)secblob
.length
));
796 if ( got_kerberos_mechanism
&& ((lp_security()==SEC_ADS
) ||
797 lp_use_kerberos_keytab()) ) {
798 bool destroy_vuid
= True
;
799 reply_spnego_kerberos(req
, &secblob
, vuid
,
801 data_blob_free(&secblob
);
803 /* Kill the intermediate vuid */
804 invalidate_vuid(vuid
);
810 if (*auth_ntlmssp_state
) {
811 auth_ntlmssp_end(auth_ntlmssp_state
);
814 if (got_kerberos_mechanism
) {
815 data_blob_free(&secblob
);
816 /* The mechtoken is a krb5 ticket, but
817 * we need to fall back to NTLM. */
818 reply_spnego_downgrade_to_ntlmssp(req
,
823 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
824 if (!NT_STATUS_IS_OK(status
)) {
825 /* Kill the intermediate vuid */
826 invalidate_vuid(vuid
);
827 reply_nterror(req
, nt_status_squash(status
));
831 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
834 data_blob_free(&secblob
);
836 reply_spnego_ntlmssp(req
, vuid
, auth_ntlmssp_state
,
837 &chal
, status
, OID_NTLMSSP
, true);
839 data_blob_free(&chal
);
841 /* already replied */
845 /****************************************************************************
846 Reply to a session setup spnego auth packet.
847 ****************************************************************************/
849 static void reply_spnego_auth(struct smb_request
*req
,
852 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
)
854 DATA_BLOB auth
= data_blob_null
;
855 DATA_BLOB auth_reply
= data_blob_null
;
856 DATA_BLOB secblob
= data_blob_null
;
857 NTSTATUS status
= NT_STATUS_LOGON_FAILURE
;
859 if (!spnego_parse_auth(blob1
, &auth
)) {
861 file_save("auth.dat", blob1
.data
, blob1
.length
);
863 /* Kill the intermediate vuid */
864 invalidate_vuid(vuid
);
866 reply_nterror(req
, nt_status_squash(
867 NT_STATUS_LOGON_FAILURE
));
871 if (auth
.data
[0] == ASN1_APPLICATION(0)) {
872 /* Might be a second negTokenTarg packet */
874 bool got_krb5_mechanism
= False
;
875 status
= parse_spnego_mechanisms(auth
, &secblob
,
876 &got_krb5_mechanism
);
878 if (!NT_STATUS_IS_OK(status
)) {
879 /* Kill the intermediate vuid */
880 invalidate_vuid(vuid
);
881 reply_nterror(req
, nt_status_squash(status
));
885 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
886 (unsigned long)secblob
.length
));
888 if ( got_krb5_mechanism
&& ((lp_security()==SEC_ADS
) ||
889 lp_use_kerberos_keytab()) ) {
890 bool destroy_vuid
= True
;
891 reply_spnego_kerberos(req
, &secblob
,
892 vuid
, &destroy_vuid
);
893 data_blob_free(&secblob
);
894 data_blob_free(&auth
);
896 /* Kill the intermediate vuid */
897 invalidate_vuid(vuid
);
902 /* Can't blunder into NTLMSSP auth if we have
905 if (got_krb5_mechanism
) {
906 /* Kill the intermediate vuid */
907 invalidate_vuid(vuid
);
908 DEBUG(3,("reply_spnego_auth: network "
909 "misconfiguration, client sent us a "
910 "krb5 ticket and kerberos security "
912 reply_nterror(req
, nt_status_squash(
913 NT_STATUS_LOGON_FAILURE
));
917 /* If we get here it wasn't a negTokenTarg auth packet. */
918 data_blob_free(&secblob
);
920 if (!*auth_ntlmssp_state
) {
921 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
922 if (!NT_STATUS_IS_OK(status
)) {
923 /* Kill the intermediate vuid */
924 invalidate_vuid(vuid
);
925 reply_nterror(req
, nt_status_squash(status
));
930 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
933 data_blob_free(&auth
);
935 /* Don't send the mechid as we've already sent this (RFC4178). */
937 reply_spnego_ntlmssp(req
, vuid
,
939 &auth_reply
, status
, NULL
, true);
941 data_blob_free(&auth_reply
);
943 /* and tell smbd that we have already replied to this packet */
947 /****************************************************************************
948 List to store partial SPNEGO auth fragments.
949 ****************************************************************************/
951 static struct pending_auth_data
*pd_list
;
953 /****************************************************************************
954 Delete an entry on the list.
955 ****************************************************************************/
957 static void delete_partial_auth(struct pending_auth_data
*pad
)
962 DLIST_REMOVE(pd_list
, pad
);
963 data_blob_free(&pad
->partial_data
);
967 /****************************************************************************
968 Search for a partial SPNEGO auth fragment matching an smbpid.
969 ****************************************************************************/
971 static struct pending_auth_data
*get_pending_auth_data(uint16 smbpid
)
973 struct pending_auth_data
*pad
;
975 for (pad
= pd_list
; pad
; pad
= pad
->next
) {
976 if (pad
->smbpid
== smbpid
) {
983 /****************************************************************************
984 Check the size of an SPNEGO blob. If we need more return
985 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
986 the blob to be more than 64k.
987 ****************************************************************************/
989 static NTSTATUS
check_spnego_blob_complete(uint16 smbpid
, uint16 vuid
,
992 struct pending_auth_data
*pad
= NULL
;
994 size_t needed_len
= 0;
996 pad
= get_pending_auth_data(smbpid
);
998 /* Ensure we have some data. */
999 if (pblob
->length
== 0) {
1000 /* Caller can cope. */
1001 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1002 delete_partial_auth(pad
);
1003 return NT_STATUS_OK
;
1006 /* Were we waiting for more data ? */
1009 size_t copy_len
= MIN(65536, pblob
->length
);
1011 /* Integer wrap paranoia.... */
1013 if (pad
->partial_data
.length
+ copy_len
<
1014 pad
->partial_data
.length
||
1015 pad
->partial_data
.length
+ copy_len
< copy_len
) {
1017 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1018 "pad->partial_data.length = %u, "
1020 (unsigned int)pad
->partial_data
.length
,
1021 (unsigned int)copy_len
));
1023 delete_partial_auth(pad
);
1024 return NT_STATUS_INVALID_PARAMETER
;
1027 DEBUG(10,("check_spnego_blob_complete: "
1028 "pad->partial_data.length = %u, "
1029 "pad->needed_len = %u, "
1031 "pblob->length = %u,\n",
1032 (unsigned int)pad
->partial_data
.length
,
1033 (unsigned int)pad
->needed_len
,
1034 (unsigned int)copy_len
,
1035 (unsigned int)pblob
->length
));
1037 tmp_blob
= data_blob(NULL
,
1038 pad
->partial_data
.length
+ copy_len
);
1040 /* Concatenate the two (up to copy_len) bytes. */
1041 memcpy(tmp_blob
.data
,
1042 pad
->partial_data
.data
,
1043 pad
->partial_data
.length
);
1044 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
1048 /* Replace the partial data. */
1049 data_blob_free(&pad
->partial_data
);
1050 pad
->partial_data
= tmp_blob
;
1051 ZERO_STRUCT(tmp_blob
);
1054 if (pblob
->length
>= pad
->needed_len
) {
1055 /* Yes, replace pblob. */
1056 data_blob_free(pblob
);
1057 *pblob
= pad
->partial_data
;
1058 ZERO_STRUCT(pad
->partial_data
);
1059 delete_partial_auth(pad
);
1060 return NT_STATUS_OK
;
1063 /* Still need more data. */
1064 pad
->needed_len
-= copy_len
;
1065 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1068 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
1069 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
1070 /* Not something we can determine the
1073 return NT_STATUS_OK
;
1076 /* This is a new SPNEGO sessionsetup - see if
1077 * the data given in this blob is enough.
1080 asn1_load(&data
, *pblob
);
1081 asn1_start_tag(&data
, pblob
->data
[0]);
1082 if (data
.has_error
|| data
.nesting
== NULL
) {
1084 /* Let caller catch. */
1085 return NT_STATUS_OK
;
1088 /* Integer wrap paranoia.... */
1090 if (data
.nesting
->taglen
+ data
.nesting
->start
< data
.nesting
->taglen
||
1091 data
.nesting
->taglen
+ data
.nesting
->start
< data
.nesting
->start
) {
1093 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1094 "data.nesting->taglen = %u, "
1095 "data.nesting->start = %u\n",
1096 (unsigned int)data
.nesting
->taglen
,
1097 (unsigned int)data
.nesting
->start
));
1100 return NT_STATUS_INVALID_PARAMETER
;
1103 /* Total length of the needed asn1 is the tag length
1104 * plus the current offset. */
1106 needed_len
= data
.nesting
->taglen
+ data
.nesting
->start
;
1109 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1110 "pblob->length = %u\n",
1111 (unsigned int)needed_len
,
1112 (unsigned int)pblob
->length
));
1114 if (needed_len
<= pblob
->length
) {
1115 /* Nothing to do - blob is complete. */
1116 return NT_STATUS_OK
;
1119 /* Refuse the blob if it's bigger than 64k. */
1120 if (needed_len
> 65536) {
1121 DEBUG(2,("check_spnego_blob_complete: needed_len "
1123 (unsigned int)needed_len
));
1124 return NT_STATUS_INVALID_PARAMETER
;
1127 /* We must store this blob until complete. */
1128 if (!(pad
= SMB_MALLOC_P(struct pending_auth_data
))) {
1129 return NT_STATUS_NO_MEMORY
;
1131 pad
->needed_len
= needed_len
- pblob
->length
;
1132 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
1133 if (pad
->partial_data
.data
== NULL
) {
1135 return NT_STATUS_NO_MEMORY
;
1137 pad
->smbpid
= smbpid
;
1139 DLIST_ADD(pd_list
, pad
);
1141 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1144 /****************************************************************************
1145 Reply to a session setup command.
1146 conn POINTER CAN BE NULL HERE !
1147 ****************************************************************************/
1149 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
1154 fstring native_os
, native_lanman
, primary_domain
;
1156 uint16 data_blob_len
= SVAL(req
->inbuf
, smb_vwv7
);
1157 enum remote_arch_types ra_type
= get_remote_arch();
1158 int vuid
= SVAL(req
->inbuf
,smb_uid
);
1159 user_struct
*vuser
= NULL
;
1160 NTSTATUS status
= NT_STATUS_OK
;
1161 uint16 smbpid
= req
->smbpid
;
1162 uint16 smb_flag2
= req
->flags2
;
1164 DEBUG(3,("Doing spnego session setup\n"));
1166 if (global_client_caps
== 0) {
1167 global_client_caps
= IVAL(req
->inbuf
,smb_vwv10
);
1169 if (!(global_client_caps
& CAP_STATUS32
)) {
1170 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1175 p
= (uint8
*)smb_buf(req
->inbuf
);
1177 if (data_blob_len
== 0) {
1178 /* an invalid request */
1179 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1183 bufrem
= smb_bufrem(req
->inbuf
, p
);
1184 /* pull the spnego blob */
1185 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
1188 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
1191 p2
= (char *)req
->inbuf
+ smb_vwv13
+ data_blob_len
;
1192 p2
+= srvstr_pull_buf(req
->inbuf
, smb_flag2
, native_os
, p2
,
1193 sizeof(native_os
), STR_TERMINATE
);
1194 p2
+= srvstr_pull_buf(req
->inbuf
, smb_flag2
, native_lanman
, p2
,
1195 sizeof(native_lanman
), STR_TERMINATE
);
1196 p2
+= srvstr_pull_buf(req
->inbuf
, smb_flag2
, primary_domain
, p2
,
1197 sizeof(primary_domain
), STR_TERMINATE
);
1198 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1199 native_os
, native_lanman
, primary_domain
));
1201 if ( ra_type
== RA_WIN2K
) {
1202 /* Vista sets neither the OS or lanman strings */
1204 if ( !strlen(native_os
) && !strlen(native_lanman
) )
1205 set_remote_arch(RA_VISTA
);
1207 /* Windows 2003 doesn't set the native lanman string,
1208 but does set primary domain which is a bug I think */
1210 if ( !strlen(native_lanman
) ) {
1211 ra_lanman_string( primary_domain
);
1213 ra_lanman_string( native_lanman
);
1217 /* Did we get a valid vuid ? */
1218 if (!is_partial_auth_vuid(vuid
)) {
1219 /* No, then try and see if this is an intermediate sessionsetup
1220 * for a large SPNEGO packet. */
1221 struct pending_auth_data
*pad
= get_pending_auth_data(smbpid
);
1223 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1224 "pending vuid %u\n",
1225 (unsigned int)pad
->vuid
));
1230 /* Do we have a valid vuid now ? */
1231 if (!is_partial_auth_vuid(vuid
)) {
1232 /* No, start a new authentication setup. */
1233 vuid
= register_initial_vuid();
1234 if (vuid
== UID_FIELD_INVALID
) {
1235 data_blob_free(&blob1
);
1236 reply_nterror(req
, nt_status_squash(
1237 NT_STATUS_INVALID_PARAMETER
));
1242 vuser
= get_partial_auth_user_struct(vuid
);
1243 /* This MUST be valid. */
1245 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1248 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1249 * sessionsetup requests as the Windows limit on the security blob
1250 * field is 4k. Bug #4400. JRA.
1253 status
= check_spnego_blob_complete(smbpid
, vuid
, &blob1
);
1254 if (!NT_STATUS_IS_OK(status
)) {
1255 if (!NT_STATUS_EQUAL(status
,
1256 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1257 /* Real error - kill the intermediate vuid */
1258 invalidate_vuid(vuid
);
1260 data_blob_free(&blob1
);
1261 reply_nterror(req
, nt_status_squash(status
));
1265 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
1267 /* its a negTokenTarg packet */
1269 reply_spnego_negotiate(req
, vuid
, blob1
,
1270 &vuser
->auth_ntlmssp_state
);
1271 data_blob_free(&blob1
);
1275 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
1277 /* its a auth packet */
1279 reply_spnego_auth(req
, vuid
, blob1
,
1280 &vuser
->auth_ntlmssp_state
);
1281 data_blob_free(&blob1
);
1285 if (strncmp((char *)(blob1
.data
), "NTLMSSP", 7) == 0) {
1288 if (!vuser
->auth_ntlmssp_state
) {
1289 status
= auth_ntlmssp_start(&vuser
->auth_ntlmssp_state
);
1290 if (!NT_STATUS_IS_OK(status
)) {
1291 /* Kill the intermediate vuid */
1292 invalidate_vuid(vuid
);
1293 data_blob_free(&blob1
);
1294 reply_nterror(req
, nt_status_squash(status
));
1299 status
= auth_ntlmssp_update(vuser
->auth_ntlmssp_state
,
1302 data_blob_free(&blob1
);
1304 reply_spnego_ntlmssp(req
, vuid
,
1305 &vuser
->auth_ntlmssp_state
,
1306 &chal
, status
, OID_NTLMSSP
, false);
1307 data_blob_free(&chal
);
1311 /* what sort of packet is this? */
1312 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1314 data_blob_free(&blob1
);
1316 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1319 /****************************************************************************
1320 On new VC == 0, shutdown *all* old connections and users.
1321 It seems that only NT4.x does this. At W2K and above (XP etc.).
1322 a new session setup with VC==0 is ignored.
1323 ****************************************************************************/
1325 static int shutdown_other_smbds(struct db_record
*rec
,
1326 const struct connections_key
*key
,
1327 const struct connections_data
*crec
,
1330 const char *ip
= (const char *)private_data
;
1332 if (!process_exists(crec
->pid
)) {
1336 if (procid_is_me(&crec
->pid
)) {
1340 if (strcmp(ip
, crec
->addr
) != 0) {
1344 messaging_send(smbd_messaging_context(), crec
->pid
, MSG_SHUTDOWN
,
1349 static void setup_new_vc_session(void)
1351 char addr
[INET6_ADDRSTRLEN
];
1353 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1354 "compatible we would close all old resources.\n"));
1357 invalidate_all_vuids();
1359 if (lp_reset_on_zero_vc()) {
1360 connections_forall(shutdown_other_smbds
,
1361 CONST_DISCARD(void *,
1362 client_addr(get_client_fd(),addr
,sizeof(addr
))));
1366 /****************************************************************************
1367 Reply to a session setup command.
1368 ****************************************************************************/
1370 void reply_sesssetup_and_X(struct smb_request
*req
)
1376 DATA_BLOB plaintext_password
;
1378 fstring sub_user
; /* Sainitised username for substituion */
1381 fstring native_lanman
;
1382 fstring primary_domain
;
1383 static bool done_sesssetup
= False
;
1384 auth_usersupplied_info
*user_info
= NULL
;
1385 auth_serversupplied_info
*server_info
= NULL
;
1386 uint16 smb_flag2
= req
->flags2
;
1390 bool doencrypt
= global_encrypted_passwords_negotiated
;
1392 DATA_BLOB session_key
;
1394 START_PROFILE(SMBsesssetupX
);
1396 ZERO_STRUCT(lm_resp
);
1397 ZERO_STRUCT(nt_resp
);
1398 ZERO_STRUCT(plaintext_password
);
1400 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
1402 /* a SPNEGO session setup has 12 command words, whereas a normal
1403 NT1 session setup has 13. See the cifs spec. */
1404 if (req
->wct
== 12 &&
1405 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
1407 if (!global_spnego_negotiated
) {
1408 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1409 "at SPNEGO session setup when it was not "
1411 reply_nterror(req
, nt_status_squash(
1412 NT_STATUS_LOGON_FAILURE
));
1413 END_PROFILE(SMBsesssetupX
);
1417 if (SVAL(req
->inbuf
,smb_vwv4
) == 0) {
1418 setup_new_vc_session();
1421 reply_sesssetup_and_X_spnego(req
);
1422 END_PROFILE(SMBsesssetupX
);
1426 smb_bufsize
= SVAL(req
->inbuf
,smb_vwv2
);
1428 if (Protocol
< PROTOCOL_NT1
) {
1429 uint16 passlen1
= SVAL(req
->inbuf
,smb_vwv7
);
1431 /* Never do NT status codes with protocols before NT1 as we
1432 * don't get client caps. */
1433 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1435 if ((passlen1
> MAX_PASS_LEN
)
1436 || (passlen1
> smb_bufrem(req
->inbuf
,
1437 smb_buf(req
->inbuf
)))) {
1438 reply_nterror(req
, nt_status_squash(
1439 NT_STATUS_INVALID_PARAMETER
));
1440 END_PROFILE(SMBsesssetupX
);
1445 lm_resp
= data_blob(smb_buf(req
->inbuf
), passlen1
);
1447 plaintext_password
= data_blob(smb_buf(req
->inbuf
),
1449 /* Ensure null termination */
1450 plaintext_password
.data
[passlen1
] = 0;
1453 srvstr_pull_buf(req
->inbuf
, req
->flags2
, user
,
1454 smb_buf(req
->inbuf
)+passlen1
, sizeof(user
),
1459 uint16 passlen1
= SVAL(req
->inbuf
,smb_vwv7
);
1460 uint16 passlen2
= SVAL(req
->inbuf
,smb_vwv8
);
1461 enum remote_arch_types ra_type
= get_remote_arch();
1462 char *p
= smb_buf(req
->inbuf
);
1463 char *save_p
= smb_buf(req
->inbuf
);
1467 if(global_client_caps
== 0) {
1468 global_client_caps
= IVAL(req
->inbuf
,smb_vwv11
);
1470 if (!(global_client_caps
& CAP_STATUS32
)) {
1471 remove_from_common_flags2(
1472 FLAGS2_32_BIT_ERROR_CODES
);
1475 /* client_caps is used as final determination if
1476 * client is NT or Win95. This is needed to return
1477 * the correct error codes in some circumstances.
1480 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
1481 ra_type
== RA_WIN95
) {
1482 if(!(global_client_caps
& (CAP_NT_SMBS
|
1484 set_remote_arch( RA_WIN95
);
1490 /* both Win95 and WinNT stuff up the password
1491 * lengths for non-encrypting systems. Uggh.
1493 if passlen1==24 its a win95 system, and its setting
1494 the password length incorrectly. Luckily it still
1495 works with the default code because Win95 will null
1496 terminate the password anyway
1498 if passlen1>0 and passlen2>0 then maybe its a NT box
1499 and its setting passlen2 to some random value which
1500 really stuffs things up. we need to fix that one. */
1502 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
1508 /* check for nasty tricks */
1509 if (passlen1
> MAX_PASS_LEN
1510 || passlen1
> smb_bufrem(req
->inbuf
, p
)) {
1511 reply_nterror(req
, nt_status_squash(
1512 NT_STATUS_INVALID_PARAMETER
));
1513 END_PROFILE(SMBsesssetupX
);
1517 if (passlen2
> MAX_PASS_LEN
1518 || passlen2
> smb_bufrem(req
->inbuf
, p
+passlen1
)) {
1519 reply_nterror(req
, nt_status_squash(
1520 NT_STATUS_INVALID_PARAMETER
));
1521 END_PROFILE(SMBsesssetupX
);
1525 /* Save the lanman2 password and the NT md4 password. */
1527 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1532 lm_resp
= data_blob(p
, passlen1
);
1533 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1536 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
1538 if (unic
&& (passlen2
== 0) && passlen1
) {
1539 /* Only a ascii plaintext password was sent. */
1540 (void)srvstr_pull_talloc(talloc_tos(),
1544 smb_buf(req
->inbuf
),
1546 STR_TERMINATE
|STR_ASCII
);
1548 (void)srvstr_pull_talloc(talloc_tos(),
1552 smb_buf(req
->inbuf
),
1553 unic
? passlen2
: passlen1
,
1557 reply_nterror(req
, nt_status_squash(
1558 NT_STATUS_INVALID_PARAMETER
));
1559 END_PROFILE(SMBsesssetupX
);
1562 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1565 p
+= passlen1
+ passlen2
;
1566 p
+= srvstr_pull_buf(req
->inbuf
, req
->flags2
, user
, p
,
1567 sizeof(user
), STR_TERMINATE
);
1568 p
+= srvstr_pull_buf(req
->inbuf
, req
->flags2
, domain
, p
,
1569 sizeof(domain
), STR_TERMINATE
);
1570 p
+= srvstr_pull_buf(req
->inbuf
, req
->flags2
, native_os
,
1571 p
, sizeof(native_os
), STR_TERMINATE
);
1572 p
+= srvstr_pull_buf(req
->inbuf
, req
->flags2
,
1573 native_lanman
, p
, sizeof(native_lanman
),
1576 /* not documented or decoded by Ethereal but there is one more
1577 * string in the extra bytes which is the same as the
1578 * PrimaryDomain when using extended security. Windows NT 4
1579 * and 2003 use this string to store the native lanman string.
1580 * Windows 9x does not include a string here at all so we have
1581 * to check if we have any extra bytes left */
1583 byte_count
= SVAL(req
->inbuf
, smb_vwv13
);
1584 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
1585 p
+= srvstr_pull_buf(req
->inbuf
, req
->flags2
,
1587 sizeof(primary_domain
),
1590 fstrcpy( primary_domain
, "null" );
1593 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1594 "PrimaryDomain=[%s]\n",
1595 domain
, native_os
, native_lanman
, primary_domain
));
1597 if ( ra_type
== RA_WIN2K
) {
1598 if ( strlen(native_lanman
) == 0 )
1599 ra_lanman_string( primary_domain
);
1601 ra_lanman_string( native_lanman
);
1606 if (SVAL(req
->inbuf
,smb_vwv4
) == 0) {
1607 setup_new_vc_session();
1610 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1611 domain
, user
, get_remote_machine_name()));
1614 if (global_spnego_negotiated
) {
1616 /* This has to be here, because this is a perfectly
1617 * valid behaviour for guest logons :-( */
1619 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1620 "at 'normal' session setup after "
1621 "negotiating spnego.\n"));
1622 reply_nterror(req
, nt_status_squash(
1623 NT_STATUS_LOGON_FAILURE
));
1624 END_PROFILE(SMBsesssetupX
);
1627 fstrcpy(sub_user
, user
);
1629 fstrcpy(sub_user
, lp_guestaccount());
1632 sub_set_smb_name(sub_user
);
1634 reload_services(True
);
1636 if (lp_security() == SEC_SHARE
) {
1637 /* in share level we should ignore any passwords */
1639 data_blob_free(&lm_resp
);
1640 data_blob_free(&nt_resp
);
1641 data_blob_clear_free(&plaintext_password
);
1643 map_username(sub_user
);
1644 add_session_user(sub_user
);
1645 add_session_workgroup(domain
);
1646 /* Then force it to null for the benfit of the code below */
1652 nt_status
= check_guest_password(&server_info
);
1654 } else if (doencrypt
) {
1655 if (!negprot_global_auth_context
) {
1656 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1657 "session setup without negprot denied!\n"));
1658 reply_nterror(req
, nt_status_squash(
1659 NT_STATUS_LOGON_FAILURE
));
1660 END_PROFILE(SMBsesssetupX
);
1663 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
1666 if (NT_STATUS_IS_OK(nt_status
)) {
1667 nt_status
= negprot_global_auth_context
->check_ntlm_password(
1668 negprot_global_auth_context
,
1673 struct auth_context
*plaintext_auth_context
= NULL
;
1676 nt_status
= make_auth_context_subsystem(
1677 &plaintext_auth_context
);
1679 if (NT_STATUS_IS_OK(nt_status
)) {
1680 chal
= plaintext_auth_context
->get_ntlm_challenge(
1681 plaintext_auth_context
);
1683 if (!make_user_info_for_reply(&user_info
,
1685 plaintext_password
)) {
1686 nt_status
= NT_STATUS_NO_MEMORY
;
1689 if (NT_STATUS_IS_OK(nt_status
)) {
1690 nt_status
= plaintext_auth_context
->check_ntlm_password(
1691 plaintext_auth_context
,
1695 (plaintext_auth_context
->free
)(
1696 &plaintext_auth_context
);
1701 free_user_info(&user_info
);
1703 if (!NT_STATUS_IS_OK(nt_status
)) {
1704 nt_status
= do_map_to_guest(nt_status
, &server_info
,
1708 if (!NT_STATUS_IS_OK(nt_status
)) {
1709 data_blob_free(&nt_resp
);
1710 data_blob_free(&lm_resp
);
1711 data_blob_clear_free(&plaintext_password
);
1712 reply_nterror(req
, nt_status_squash(nt_status
));
1713 END_PROFILE(SMBsesssetupX
);
1717 /* Ensure we can't possible take a code path leading to a
1720 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1721 END_PROFILE(SMBsesssetupX
);
1725 nt_status
= create_local_token(server_info
);
1726 if (!NT_STATUS_IS_OK(nt_status
)) {
1727 DEBUG(10, ("create_local_token failed: %s\n",
1728 nt_errstr(nt_status
)));
1729 data_blob_free(&nt_resp
);
1730 data_blob_free(&lm_resp
);
1731 data_blob_clear_free(&plaintext_password
);
1732 reply_nterror(req
, nt_status_squash(nt_status
));
1733 END_PROFILE(SMBsesssetupX
);
1737 if (server_info
->user_session_key
.data
) {
1738 session_key
= data_blob(server_info
->user_session_key
.data
,
1739 server_info
->user_session_key
.length
);
1741 session_key
= data_blob_null
;
1744 data_blob_clear_free(&plaintext_password
);
1746 /* it's ok - setup a reply */
1747 reply_outbuf(req
, 3, 0);
1748 if (Protocol
>= PROTOCOL_NT1
) {
1749 push_signature(&req
->outbuf
);
1750 /* perhaps grab OS version here?? */
1753 if (server_info
->guest
) {
1754 SSVAL(req
->outbuf
,smb_vwv2
,1);
1757 /* register the name and uid as being validated, so further connections
1758 to a uid can get through without a password, on the same VC */
1760 if (lp_security() == SEC_SHARE
) {
1761 sess_vuid
= UID_FIELD_INVALID
;
1762 data_blob_free(&session_key
);
1763 TALLOC_FREE(server_info
);
1765 /* Ignore the initial vuid. */
1766 sess_vuid
= register_initial_vuid();
1767 if (sess_vuid
== UID_FIELD_INVALID
) {
1768 data_blob_free(&nt_resp
);
1769 data_blob_free(&lm_resp
);
1770 data_blob_free(&session_key
);
1771 reply_nterror(req
, nt_status_squash(
1772 NT_STATUS_LOGON_FAILURE
));
1773 END_PROFILE(SMBsesssetupX
);
1776 /* register_existing_vuid keeps the server info */
1777 sess_vuid
= register_existing_vuid(sess_vuid
,
1780 nt_resp
.data
? nt_resp
: lm_resp
,
1782 if (sess_vuid
== UID_FIELD_INVALID
) {
1783 data_blob_free(&nt_resp
);
1784 data_blob_free(&lm_resp
);
1785 data_blob_free(&session_key
);
1786 reply_nterror(req
, nt_status_squash(
1787 NT_STATUS_LOGON_FAILURE
));
1788 END_PROFILE(SMBsesssetupX
);
1792 /* current_user_info is changed on new vuid */
1793 reload_services( True
);
1795 sessionsetup_start_signing_engine(server_info
, req
->inbuf
);
1798 data_blob_free(&nt_resp
);
1799 data_blob_free(&lm_resp
);
1801 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1802 SSVAL(req
->inbuf
,smb_uid
,sess_vuid
);
1804 if (!done_sesssetup
)
1805 max_send
= MIN(max_send
,smb_bufsize
);
1807 done_sesssetup
= True
;
1809 END_PROFILE(SMBsesssetupX
);