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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern struct auth_context
*negprot_global_auth_context
;
27 extern BOOL global_encrypted_passwords_negotiated
;
28 extern BOOL global_spnego_negotiated
;
29 extern enum protocol_types Protocol
;
32 uint32 global_client_caps
= 0;
35 on a logon error possibly map the error to success if "map to guest"
38 static NTSTATUS
do_map_to_guest(NTSTATUS status
, auth_serversupplied_info
**server_info
,
39 const char *user
, const char *domain
)
41 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
42 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
43 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
44 DEBUG(3,("No such user %s [%s] - using guest account\n",
46 status
= make_server_info_guest(server_info
);
50 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
51 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
52 DEBUG(3,("Registered username %s for guest access\n",user
));
53 status
= make_server_info_guest(server_info
);
60 /****************************************************************************
61 Add the standard 'Samba' signature to the end of the session setup.
62 ****************************************************************************/
64 static int add_signature(char *outbuf
, char *p
)
69 fstr_sprintf( lanman
, "Samba %s", SAMBA_VERSION_STRING
);
71 p
+= srvstr_push(outbuf
, p
, "Unix", BUFFER_SIZE
- (p
- outbuf
), STR_TERMINATE
);
72 p
+= srvstr_push(outbuf
, p
, lanman
, BUFFER_SIZE
- (p
- outbuf
), STR_TERMINATE
);
73 p
+= srvstr_push(outbuf
, p
, lp_workgroup(), BUFFER_SIZE
- (p
- outbuf
), STR_TERMINATE
);
75 return PTR_DIFF(p
, start
);
78 /****************************************************************************
79 Start the signing engine if needed. Don't fail signing here.
80 ****************************************************************************/
82 static void sessionsetup_start_signing_engine(const auth_serversupplied_info
*server_info
, char *inbuf
)
84 if (!server_info
->guest
&& !srv_signing_started()) {
85 /* We need to start the signing engine
86 * here but a W2K client sends the old
87 * "BSRSPYL " signature instead of the
88 * correct one. Subsequent packets will
91 srv_check_sign_mac(inbuf
, False
);
95 /****************************************************************************
96 Send a security blob via a session setup reply.
97 We must already have called set_message(outbuf,4,0,True)
98 before calling this function.
99 ****************************************************************************/
101 static BOOL
reply_sesssetup_blob(connection_struct
*conn
, char *outbuf
,
102 DATA_BLOB blob
, NTSTATUS nt_status
)
106 if (!NT_STATUS_IS_OK(nt_status
) && !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
107 ERROR_NT(nt_status_squash(nt_status
));
109 nt_status
= nt_status_squash(nt_status
);
110 SIVAL(outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
111 SSVAL(outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
112 SSVAL(outbuf
, smb_vwv3
, blob
.length
);
115 /* should we cap this? */
116 memcpy(p
, blob
.data
, blob
.length
);
119 p
+= add_signature( outbuf
, p
);
121 set_message_end(outbuf
,p
);
125 return send_smb(smbd_server_fd(),outbuf
);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS
check_guest_password(auth_serversupplied_info
**server_info
)
134 struct auth_context
*auth_context
;
135 auth_usersupplied_info
*user_info
= NULL
;
138 unsigned char chal
[8];
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status
= make_auth_context_fixed(&auth_context
, chal
))) {
148 if (!make_user_info_guest(&user_info
)) {
149 (auth_context
->free
)(&auth_context
);
150 return NT_STATUS_NO_MEMORY
;
153 nt_status
= auth_context
->check_ntlm_password(auth_context
, user_info
, server_info
);
154 (auth_context
->free
)(&auth_context
);
155 free_user_info(&user_info
);
163 /* Experiment that failed. See "only happens with a KDC" comment below. */
164 /****************************************************************************
165 Cerate a clock skew error blob for a Windows client.
166 ****************************************************************************/
168 static BOOL
make_krb5_skew_error(DATA_BLOB
*pblob_out
)
170 krb5_context context
= NULL
;
171 krb5_error_code kerr
= 0;
173 krb5_principal host_princ
= NULL
;
174 char *host_princ_s
= NULL
;
177 *pblob_out
= data_blob(NULL
,0);
179 initialize_krb5_error_table();
180 kerr
= krb5_init_context(&context
);
184 /* Create server principal. */
185 asprintf(&host_princ_s
, "%s$@%s", global_myname(), lp_realm());
189 strlower_m(host_princ_s
);
191 kerr
= smb_krb5_parse_name(context
, host_princ_s
, &host_princ
);
193 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
194 host_princ_s
, error_message(kerr
) ));
198 kerr
= smb_krb5_mk_error(context
, KRB5KRB_AP_ERR_SKEW
, host_princ
, &reply
);
200 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
201 error_message(kerr
) ));
205 *pblob_out
= data_blob(reply
.data
, reply
.length
);
206 kerberos_free_data_contents(context
,&reply
);
212 SAFE_FREE(host_princ_s
);
215 krb5_free_principal(context
, host_princ
);
217 krb5_free_context(context
);
222 /****************************************************************************
223 Reply to a session setup spnego negotiate packet for kerberos.
224 ****************************************************************************/
226 static int reply_spnego_kerberos(connection_struct
*conn
,
227 char *inbuf
, char *outbuf
,
228 int length
, int bufsize
,
230 BOOL
*p_invalidate_vuid
)
234 char *client
, *p
, *domain
;
235 fstring netbios_domain_name
;
241 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
242 auth_serversupplied_info
*server_info
= NULL
;
243 DATA_BLOB session_key
= data_blob(NULL
, 0);
245 DATA_BLOB nullblob
= data_blob(NULL
, 0);
246 fstring real_username
;
247 BOOL map_domainuser_to_guest
= False
;
248 BOOL username_was_mapped
;
249 PAC_LOGON_INFO
*logon_info
= NULL
;
252 ZERO_STRUCT(pac_data
);
254 ZERO_STRUCT(ap_rep_wrapped
);
255 ZERO_STRUCT(response
);
257 /* Normally we will always invalidate the intermediate vuid. */
258 *p_invalidate_vuid
= True
;
260 mem_ctx
= talloc_init("reply_spnego_kerberos");
261 if (mem_ctx
== NULL
) {
262 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY
));
265 if (!spnego_parse_krb5_wrap(*secblob
, &ticket
, tok_id
)) {
266 talloc_destroy(mem_ctx
);
267 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
270 ret
= ads_verify_ticket(mem_ctx
, lp_realm(), 0, &ticket
, &client
, &pac_data
, &ap_rep
, &session_key
);
272 data_blob_free(&ticket
);
274 if (!NT_STATUS_IS_OK(ret
)) {
276 /* Experiment that failed. See "only happens with a KDC" comment below. */
278 if (NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
281 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
282 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
283 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
284 * clock and continues rather than giving an error. JRA.
285 * -- Looks like this only happens with a KDC. JRA.
288 BOOL ok
= make_krb5_skew_error(&ap_rep
);
290 talloc_destroy(mem_ctx
);
291 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
293 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
, TOK_ID_KRB_ERROR
);
294 response
= spnego_gen_auth_response(&ap_rep_wrapped
, ret
, OID_KERBEROS5_OLD
);
295 reply_sesssetup_blob(conn
, outbuf
, response
, NT_STATUS_MORE_PROCESSING_REQUIRED
);
298 * In this one case we don't invalidate the intermediate vuid.
299 * as we're expecting the client to re-use it for the next
300 * sessionsetupX packet. JRA.
303 *p_invalidate_vuid
= False
;
305 data_blob_free(&ap_rep
);
306 data_blob_free(&ap_rep_wrapped
);
307 data_blob_free(&response
);
308 talloc_destroy(mem_ctx
);
309 return -1; /* already replied */
312 if (!NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
313 ret
= NT_STATUS_LOGON_FAILURE
;
316 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret
)));
317 talloc_destroy(mem_ctx
);
318 return ERROR_NT(nt_status_squash(ret
));
321 DEBUG(3,("Ticket name is [%s]\n", client
));
323 p
= strchr_m(client
, '@');
325 DEBUG(3,("Doesn't look like a valid principal\n"));
326 data_blob_free(&ap_rep
);
327 data_blob_free(&session_key
);
329 talloc_destroy(mem_ctx
);
330 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
335 /* save the PAC data if we have it */
338 logon_info
= get_logon_info_from_pac(pac_data
);
340 netsamlogon_cache_store( client
, &logon_info
->info3
);
344 if (!strequal(p
+1, lp_realm())) {
345 DEBUG(3,("Ticket for foreign realm %s@%s\n", client
, p
+1));
346 if (!lp_allow_trusted_domains()) {
347 data_blob_free(&ap_rep
);
348 data_blob_free(&session_key
);
350 talloc_destroy(mem_ctx
);
351 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
355 /* this gives a fully qualified user name (ie. with full realm).
356 that leads to very long usernames, but what else can we do? */
360 if (logon_info
&& logon_info
->info3
.hdr_logon_dom
.uni_str_len
) {
362 unistr2_to_ascii(netbios_domain_name
, &logon_info
->info3
.uni_logon_dom
, -1);
363 domain
= netbios_domain_name
;
364 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain
));
368 /* If we have winbind running, we can (and must) shorten the
369 username by using the short netbios name. Otherwise we will
370 have inconsistent user names. With Kerberos, we get the
371 fully qualified realm, with ntlmssp we get the short
372 name. And even w2k3 does use ntlmssp if you for example
373 connect to an ip address. */
375 struct winbindd_request wb_request
;
376 struct winbindd_response wb_response
;
377 NSS_STATUS wb_result
;
379 ZERO_STRUCT(wb_request
);
380 ZERO_STRUCT(wb_response
);
382 DEBUG(10, ("Mapping [%s] to short name\n", domain
));
384 fstrcpy(wb_request
.domain_name
, domain
);
386 wb_result
= winbindd_request_response(WINBINDD_DOMAIN_INFO
,
387 &wb_request
, &wb_response
);
389 if (wb_result
== NSS_STATUS_SUCCESS
) {
391 fstrcpy(netbios_domain_name
,
392 wb_response
.data
.domain_info
.name
);
393 domain
= netbios_domain_name
;
395 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain
));
397 DEBUG(3, ("Could not find short name -- winbind "
402 fstr_sprintf(user
, "%s%c%s", domain
, *lp_winbind_separator(), client
);
404 /* lookup the passwd struct, create a new user if necessary */
406 username_was_mapped
= map_username( user
);
408 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
411 /* if a real user check pam account restrictions */
412 /* only really perfomed if "obey pam restriction" is true */
413 /* do this before an eventual mappign to guest occurs */
414 ret
= smb_pam_accountcheck(pw
->pw_name
);
415 if ( !NT_STATUS_IS_OK(ret
)) {
416 DEBUG(1, ("PAM account restriction prevents user login\n"));
417 data_blob_free(&ap_rep
);
418 data_blob_free(&session_key
);
419 TALLOC_FREE(mem_ctx
);
420 return ERROR_NT(nt_status_squash(ret
));
426 /* this was originally the behavior of Samba 2.2, if a user
427 did not have a local uid but has been authenticated, then
428 map them to a guest account */
430 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID
){
431 map_domainuser_to_guest
= True
;
432 fstrcpy(user
,lp_guestaccount());
433 pw
= smb_getpwnam( mem_ctx
, user
, real_username
, True
);
436 /* extra sanity check that the guest account is valid */
439 DEBUG(1,("Username %s is invalid on this system\n", user
));
441 data_blob_free(&ap_rep
);
442 data_blob_free(&session_key
);
443 TALLOC_FREE(mem_ctx
);
444 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
448 /* setup the string used by %U */
450 sub_set_smb_name( real_username
);
451 reload_services(True
);
453 if ( map_domainuser_to_guest
) {
454 make_server_info_guest(&server_info
);
455 } else if (logon_info
) {
456 /* pass the unmapped username here since map_username()
457 will be called again from inside make_server_info_info3() */
459 ret
= make_server_info_info3(mem_ctx
, client
, domain
,
460 &server_info
, &logon_info
->info3
);
461 if ( !NT_STATUS_IS_OK(ret
) ) {
462 DEBUG(1,("make_server_info_info3 failed: %s!\n",
465 data_blob_free(&ap_rep
);
466 data_blob_free(&session_key
);
467 TALLOC_FREE(mem_ctx
);
468 return ERROR_NT(nt_status_squash(ret
));
472 ret
= make_server_info_pw(&server_info
, real_username
, pw
);
474 if ( !NT_STATUS_IS_OK(ret
) ) {
475 DEBUG(1,("make_server_info_pw failed: %s!\n",
478 data_blob_free(&ap_rep
);
479 data_blob_free(&session_key
);
480 TALLOC_FREE(mem_ctx
);
481 return ERROR_NT(nt_status_squash(ret
));
484 /* make_server_info_pw does not set the domain. Without this
485 * we end up with the local netbios name in substitutions for
488 if (server_info
->sam_account
!= NULL
) {
489 pdb_set_domain(server_info
->sam_account
, domain
, PDB_SET
);
493 server_info
->was_mapped
|= username_was_mapped
;
495 /* we need to build the token for the user. make_server_info_guest()
498 if ( !server_info
->ptok
) {
499 ret
= create_local_token( server_info
);
500 if ( !NT_STATUS_IS_OK(ret
) ) {
502 data_blob_free(&ap_rep
);
503 data_blob_free(&session_key
);
504 TALLOC_FREE( mem_ctx
);
505 TALLOC_FREE( server_info
);
506 return ERROR_NT(nt_status_squash(ret
));
510 /* register_vuid keeps the server info */
511 /* register_vuid takes ownership of session_key, no need to free after this.
512 A better interface would copy it.... */
513 sess_vuid
= register_vuid(server_info
, session_key
, nullblob
, client
);
517 set_message(outbuf
,4,0,True
);
519 if (sess_vuid
== UID_FIELD_INVALID
) {
520 ret
= NT_STATUS_LOGON_FAILURE
;
522 /* current_user_info is changed on new vuid */
523 reload_services( True
);
525 SSVAL(outbuf
, smb_vwv3
, 0);
527 if (server_info
->guest
) {
528 SSVAL(outbuf
,smb_vwv2
,1);
531 SSVAL(outbuf
, smb_uid
, sess_vuid
);
533 sessionsetup_start_signing_engine(server_info
, inbuf
);
536 /* wrap that up in a nice GSS-API wrapping */
537 if (NT_STATUS_IS_OK(ret
)) {
538 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
, TOK_ID_KRB_AP_REP
);
540 ap_rep_wrapped
= data_blob(NULL
, 0);
542 response
= spnego_gen_auth_response(&ap_rep_wrapped
, ret
, OID_KERBEROS5_OLD
);
543 reply_sesssetup_blob(conn
, outbuf
, response
, ret
);
545 data_blob_free(&ap_rep
);
546 data_blob_free(&ap_rep_wrapped
);
547 data_blob_free(&response
);
548 TALLOC_FREE(mem_ctx
);
550 return -1; /* already replied */
554 /****************************************************************************
555 Send a session setup reply, wrapped in SPNEGO.
556 Get vuid and check first.
557 End the NTLMSSP exchange context if we are OK/complete fail
558 This should be split into two functions, one to handle each
559 leg of the NTLM auth steps.
560 ***************************************************************************/
562 static BOOL
reply_spnego_ntlmssp(connection_struct
*conn
, char *inbuf
, char *outbuf
,
564 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
,
565 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
,
570 struct auth_serversupplied_info
*server_info
= NULL
;
572 if (NT_STATUS_IS_OK(nt_status
)) {
573 server_info
= (*auth_ntlmssp_state
)->server_info
;
575 nt_status
= do_map_to_guest(nt_status
,
577 (*auth_ntlmssp_state
)->ntlmssp_state
->user
,
578 (*auth_ntlmssp_state
)->ntlmssp_state
->domain
);
581 set_message(outbuf
,4,0,True
);
583 if (NT_STATUS_IS_OK(nt_status
)) {
585 DATA_BLOB nullblob
= data_blob(NULL
, 0);
586 DATA_BLOB session_key
= data_blob((*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.data
, (*auth_ntlmssp_state
)->ntlmssp_state
->session_key
.length
);
588 /* register_vuid keeps the server info */
589 sess_vuid
= register_vuid(server_info
, session_key
, nullblob
, (*auth_ntlmssp_state
)->ntlmssp_state
->user
);
590 (*auth_ntlmssp_state
)->server_info
= NULL
;
592 if (sess_vuid
== UID_FIELD_INVALID
) {
593 nt_status
= NT_STATUS_LOGON_FAILURE
;
596 /* current_user_info is changed on new vuid */
597 reload_services( True
);
599 SSVAL(outbuf
, smb_vwv3
, 0);
601 if (server_info
->guest
) {
602 SSVAL(outbuf
,smb_vwv2
,1);
605 SSVAL(outbuf
,smb_uid
,sess_vuid
);
607 sessionsetup_start_signing_engine(server_info
, inbuf
);
612 response
= spnego_gen_auth_response(ntlmssp_blob
, nt_status
, OID_NTLMSSP
);
614 response
= *ntlmssp_blob
;
617 ret
= reply_sesssetup_blob(conn
, outbuf
, response
, nt_status
);
619 data_blob_free(&response
);
622 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
623 and the other end, that we are not finished yet. */
625 if (!ret
|| !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
626 /* NB. This is *NOT* an error case. JRA */
627 auth_ntlmssp_end(auth_ntlmssp_state
);
628 /* Kill the intermediate vuid */
629 invalidate_intermediate_vuid(vuid
);
635 /****************************************************************************
636 Is this a krb5 mechanism ?
637 ****************************************************************************/
639 static NTSTATUS
parse_spnego_mechanisms(DATA_BLOB blob_in
, DATA_BLOB
*pblob_out
, BOOL
*p_is_krb5
)
641 char *OIDs
[ASN1_MAX_OIDS
];
646 /* parse out the OIDs and the first sec blob */
647 if (!parse_negTokenTarg(blob_in
, OIDs
, pblob_out
)) {
648 return NT_STATUS_LOGON_FAILURE
;
651 /* only look at the first OID for determining the mechToken --
652 accoirding to RFC2478, we should choose the one we want
653 and renegotiate, but i smell a client bug here..
655 Problem observed when connecting to a member (samba box)
656 of an AD domain as a user in a Samba domain. Samba member
657 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
658 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
659 NTLMSSP mechtoken. --jerry */
662 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
663 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
668 for (i
=0;OIDs
[i
];i
++) {
669 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs
[i
]));
675 /****************************************************************************
676 Reply to a session setup spnego negotiate packet.
677 ****************************************************************************/
679 static int reply_spnego_negotiate(connection_struct
*conn
,
683 int length
, int bufsize
,
685 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
)
689 BOOL got_kerberos_mechanism
= False
;
692 status
= parse_spnego_mechanisms(blob1
, &secblob
, &got_kerberos_mechanism
);
693 if (!NT_STATUS_IS_OK(status
)) {
694 /* Kill the intermediate vuid */
695 invalidate_intermediate_vuid(vuid
);
696 return ERROR_NT(nt_status_squash(status
));
699 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob
.length
));
702 if ( got_kerberos_mechanism
&& ((lp_security()==SEC_ADS
) || lp_use_kerberos_keytab()) ) {
703 BOOL destroy_vuid
= True
;
704 int ret
= reply_spnego_kerberos(conn
, inbuf
, outbuf
,
705 length
, bufsize
, &secblob
, &destroy_vuid
);
706 data_blob_free(&secblob
);
708 /* Kill the intermediate vuid */
709 invalidate_intermediate_vuid(vuid
);
715 if (got_kerberos_mechanism
) {
716 invalidate_intermediate_vuid(vuid
);
717 DEBUG(3,("reply_spnego_negotiate: network "
718 "misconfiguration, client sent us a "
719 "krb5 ticket and kerberos security "
721 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
724 if (*auth_ntlmssp_state
) {
725 auth_ntlmssp_end(auth_ntlmssp_state
);
728 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
729 if (!NT_STATUS_IS_OK(status
)) {
730 /* Kill the intermediate vuid */
731 invalidate_intermediate_vuid(vuid
);
732 return ERROR_NT(nt_status_squash(status
));
735 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
738 data_blob_free(&secblob
);
740 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, vuid
, auth_ntlmssp_state
,
741 &chal
, status
, True
);
743 data_blob_free(&chal
);
745 /* already replied */
749 /****************************************************************************
750 Reply to a session setup spnego auth packet.
751 ****************************************************************************/
753 static int reply_spnego_auth(connection_struct
*conn
, char *inbuf
, char *outbuf
,
755 int length
, int bufsize
,
757 AUTH_NTLMSSP_STATE
**auth_ntlmssp_state
)
759 DATA_BLOB auth
= data_blob(NULL
,0);
760 DATA_BLOB auth_reply
= data_blob(NULL
,0);
761 DATA_BLOB secblob
= data_blob(NULL
,0);
762 NTSTATUS status
= NT_STATUS_INVALID_PARAMETER
;
764 if (!spnego_parse_auth(blob1
, &auth
)) {
766 file_save("auth.dat", blob1
.data
, blob1
.length
);
768 /* Kill the intermediate vuid */
769 invalidate_intermediate_vuid(vuid
);
771 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
774 if (auth
.data
[0] == ASN1_APPLICATION(0)) {
775 /* Might be a second negTokenTarg packet */
777 BOOL got_krb5_mechanism
= False
;
778 status
= parse_spnego_mechanisms(auth
, &secblob
, &got_krb5_mechanism
);
779 if (NT_STATUS_IS_OK(status
)) {
780 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob
.length
));
782 if ( got_krb5_mechanism
&& ((lp_security()==SEC_ADS
) || lp_use_kerberos_keytab()) ) {
783 BOOL destroy_vuid
= True
;
784 int ret
= reply_spnego_kerberos(conn
, inbuf
, outbuf
,
785 length
, bufsize
, &secblob
, &destroy_vuid
);
786 data_blob_free(&secblob
);
787 data_blob_free(&auth
);
789 /* Kill the intermediate vuid */
790 invalidate_intermediate_vuid(vuid
);
798 /* If we get here it wasn't a negTokenTarg auth packet. */
799 data_blob_free(&secblob
);
801 if (!*auth_ntlmssp_state
) {
802 /* Kill the intermediate vuid */
803 invalidate_intermediate_vuid(vuid
);
805 /* auth before negotiatiate? */
806 return ERROR_NT(NT_STATUS_LOGON_FAILURE
);
809 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
812 data_blob_free(&auth
);
814 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, vuid
,
816 &auth_reply
, status
, True
);
818 data_blob_free(&auth_reply
);
820 /* and tell smbd that we have already replied to this packet */
824 /****************************************************************************
825 List to store partial SPNEGO auth fragments.
826 ****************************************************************************/
828 static struct pending_auth_data
*pd_list
;
830 /****************************************************************************
831 Delete an entry on the list.
832 ****************************************************************************/
834 static void delete_partial_auth(struct pending_auth_data
*pad
)
839 DLIST_REMOVE(pd_list
, pad
);
840 data_blob_free(&pad
->partial_data
);
844 /****************************************************************************
845 Search for a partial SPNEGO auth fragment matching an smbpid.
846 ****************************************************************************/
848 static struct pending_auth_data
*get_pending_auth_data(uint16 smbpid
)
850 struct pending_auth_data
*pad
;
852 for (pad
= pd_list
; pad
; pad
= pad
->next
) {
853 if (pad
->smbpid
== smbpid
) {
860 /****************************************************************************
861 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
862 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
863 ****************************************************************************/
865 static NTSTATUS
check_spnego_blob_complete(uint16 smbpid
, uint16 vuid
, DATA_BLOB
*pblob
)
867 struct pending_auth_data
*pad
= NULL
;
869 size_t needed_len
= 0;
871 pad
= get_pending_auth_data(smbpid
);
873 /* Ensure we have some data. */
874 if (pblob
->length
== 0) {
875 /* Caller can cope. */
876 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
877 delete_partial_auth(pad
);
881 /* Were we waiting for more data ? */
884 size_t copy_len
= MIN(65536, pblob
->length
);
886 /* Integer wrap paranoia.... */
888 if (pad
->partial_data
.length
+ copy_len
< pad
->partial_data
.length
||
889 pad
->partial_data
.length
+ copy_len
< copy_len
) {
891 DEBUG(2,("check_spnego_blob_complete: integer wrap "
892 "pad->partial_data.length = %u, "
894 (unsigned int)pad
->partial_data
.length
,
895 (unsigned int)copy_len
));
897 delete_partial_auth(pad
);
898 return NT_STATUS_INVALID_PARAMETER
;
901 DEBUG(10,("check_spnego_blob_complete: "
902 "pad->partial_data.length = %u, "
903 "pad->needed_len = %u, "
905 "pblob->length = %u,\n",
906 (unsigned int)pad
->partial_data
.length
,
907 (unsigned int)pad
->needed_len
,
908 (unsigned int)copy_len
,
909 (unsigned int)pblob
->length
));
911 tmp_blob
= data_blob(NULL
,
912 pad
->partial_data
.length
+ copy_len
);
914 /* Concatenate the two (up to copy_len) bytes. */
915 memcpy(tmp_blob
.data
,
916 pad
->partial_data
.data
,
917 pad
->partial_data
.length
);
918 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
922 /* Replace the partial data. */
923 data_blob_free(&pad
->partial_data
);
924 pad
->partial_data
= tmp_blob
;
925 ZERO_STRUCT(tmp_blob
);
928 if (pblob
->length
>= pad
->needed_len
) {
929 /* Yes, replace pblob. */
930 data_blob_free(pblob
);
931 *pblob
= pad
->partial_data
;
932 ZERO_STRUCT(pad
->partial_data
);
933 delete_partial_auth(pad
);
937 /* Still need more data. */
938 pad
->needed_len
-= copy_len
;
939 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
942 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
943 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
944 /* Not something we can determine the
950 /* This is a new SPNEGO sessionsetup - see if
951 * the data given in this blob is enough.
954 asn1_load(&data
, *pblob
);
955 asn1_start_tag(&data
, pblob
->data
[0]);
956 if (data
.has_error
|| data
.nesting
== NULL
) {
958 /* Let caller catch. */
962 /* Integer wrap paranoia.... */
964 if (data
.nesting
->taglen
+ data
.nesting
->start
< data
.nesting
->taglen
||
965 data
.nesting
->taglen
+ data
.nesting
->start
< data
.nesting
->start
) {
967 DEBUG(2,("check_spnego_blob_complete: integer wrap "
968 "data.nesting->taglen = %u, "
969 "data.nesting->start = %u\n",
970 (unsigned int)data
.nesting
->taglen
,
971 (unsigned int)data
.nesting
->start
));
974 return NT_STATUS_INVALID_PARAMETER
;
977 /* Total length of the needed asn1 is the tag length
978 * plus the current offset. */
980 needed_len
= data
.nesting
->taglen
+ data
.nesting
->start
;
983 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
984 "pblob->length = %u\n",
985 (unsigned int)needed_len
,
986 (unsigned int)pblob
->length
));
988 if (needed_len
<= pblob
->length
) {
989 /* Nothing to do - blob is complete. */
993 /* Refuse the blob if it's bigger than 64k. */
994 if (needed_len
> 65536) {
995 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
996 (unsigned int)needed_len
));
997 return NT_STATUS_INVALID_PARAMETER
;
1000 /* We must store this blob until complete. */
1001 pad
= SMB_MALLOC(sizeof(struct pending_auth_data
));
1003 return NT_STATUS_NO_MEMORY
;
1005 pad
->needed_len
= needed_len
- pblob
->length
;
1006 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
1007 if (pad
->partial_data
.data
== NULL
) {
1009 return NT_STATUS_NO_MEMORY
;
1011 pad
->smbpid
= smbpid
;
1013 DLIST_ADD(pd_list
, pad
);
1015 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1018 /****************************************************************************
1019 Reply to a session setup command.
1020 conn POINTER CAN BE NULL HERE !
1021 ****************************************************************************/
1023 static int reply_sesssetup_and_X_spnego(connection_struct
*conn
, char *inbuf
,
1025 int length
,int bufsize
)
1031 fstring native_os
, native_lanman
, primary_domain
;
1033 uint16 data_blob_len
= SVAL(inbuf
, smb_vwv7
);
1034 enum remote_arch_types ra_type
= get_remote_arch();
1035 int vuid
= SVAL(inbuf
,smb_uid
);
1036 user_struct
*vuser
= NULL
;
1037 NTSTATUS status
= NT_STATUS_OK
;
1038 uint16 smbpid
= SVAL(inbuf
,smb_pid
);
1040 DEBUG(3,("Doing spnego session setup\n"));
1042 if (global_client_caps
== 0) {
1043 global_client_caps
= IVAL(inbuf
,smb_vwv10
);
1045 if (!(global_client_caps
& CAP_STATUS32
)) {
1046 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1051 p
= (uint8
*)smb_buf(inbuf
);
1053 if (data_blob_len
== 0) {
1054 /* an invalid request */
1055 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1058 bufrem
= smb_bufrem(inbuf
, p
);
1059 /* pull the spnego blob */
1060 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
1063 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
1066 p2
= inbuf
+ smb_vwv13
+ data_blob_len
;
1067 p2
+= srvstr_pull_buf(inbuf
, native_os
, p2
, sizeof(native_os
), STR_TERMINATE
);
1068 p2
+= srvstr_pull_buf(inbuf
, native_lanman
, p2
, sizeof(native_lanman
), STR_TERMINATE
);
1069 p2
+= srvstr_pull_buf(inbuf
, primary_domain
, p2
, sizeof(primary_domain
), STR_TERMINATE
);
1070 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1071 native_os
, native_lanman
, primary_domain
));
1073 if ( ra_type
== RA_WIN2K
) {
1074 /* Vista sets neither the OS or lanman strings */
1076 if ( !strlen(native_os
) && !strlen(native_lanman
) )
1077 set_remote_arch(RA_VISTA
);
1079 /* Windows 2003 doesn't set the native lanman string,
1080 but does set primary domain which is a bug I think */
1082 if ( !strlen(native_lanman
) ) {
1083 ra_lanman_string( primary_domain
);
1085 ra_lanman_string( native_lanman
);
1089 vuser
= get_partial_auth_user_struct(vuid
);
1091 struct pending_auth_data
*pad
= get_pending_auth_data(smbpid
);
1093 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1094 (unsigned int)pad
->vuid
));
1096 vuser
= get_partial_auth_user_struct(vuid
);
1101 vuid
= register_vuid(NULL
, data_blob(NULL
, 0), data_blob(NULL
, 0), NULL
);
1102 if (vuid
== UID_FIELD_INVALID
) {
1103 data_blob_free(&blob1
);
1104 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1107 vuser
= get_partial_auth_user_struct(vuid
);
1111 data_blob_free(&blob1
);
1112 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1115 SSVAL(outbuf
,smb_uid
,vuid
);
1117 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1118 * sessionsetup requests as the Windows limit on the security blob
1119 * field is 4k. Bug #4400. JRA.
1122 status
= check_spnego_blob_complete(smbpid
, vuid
, &blob1
);
1123 if (!NT_STATUS_IS_OK(status
)) {
1124 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1125 /* Real error - kill the intermediate vuid */
1126 invalidate_intermediate_vuid(vuid
);
1128 data_blob_free(&blob1
);
1129 return ERROR_NT(nt_status_squash(status
));
1132 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
1133 /* its a negTokenTarg packet */
1134 ret
= reply_spnego_negotiate(conn
, inbuf
, outbuf
, vuid
, length
, bufsize
, blob1
,
1135 &vuser
->auth_ntlmssp_state
);
1136 data_blob_free(&blob1
);
1140 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
1141 /* its a auth packet */
1142 ret
= reply_spnego_auth(conn
, inbuf
, outbuf
, vuid
, length
, bufsize
, blob1
,
1143 &vuser
->auth_ntlmssp_state
);
1144 data_blob_free(&blob1
);
1148 if (strncmp((char *)(blob1
.data
), "NTLMSSP", 7) == 0) {
1150 if (!vuser
->auth_ntlmssp_state
) {
1151 status
= auth_ntlmssp_start(&vuser
->auth_ntlmssp_state
);
1152 if (!NT_STATUS_IS_OK(status
)) {
1153 /* Kill the intermediate vuid */
1154 invalidate_intermediate_vuid(vuid
);
1155 data_blob_free(&blob1
);
1156 return ERROR_NT(nt_status_squash(status
));
1160 status
= auth_ntlmssp_update(vuser
->auth_ntlmssp_state
,
1163 data_blob_free(&blob1
);
1165 reply_spnego_ntlmssp(conn
, inbuf
, outbuf
, vuid
,
1166 &vuser
->auth_ntlmssp_state
,
1167 &chal
, status
, False
);
1168 data_blob_free(&chal
);
1172 /* what sort of packet is this? */
1173 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1175 data_blob_free(&blob1
);
1177 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1180 /****************************************************************************
1181 On new VC == 0, shutdown *all* old connections and users.
1182 It seems that only NT4.x does this. At W2K and above (XP etc.).
1183 a new session setup with VC==0 is ignored.
1184 ****************************************************************************/
1186 static int shutdown_other_smbds(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
1189 struct sessionid sessionid
;
1190 const char *ip
= (const char *)p
;
1192 SMB_ASSERT(dbuf
.dsize
== sizeof(sessionid
));
1193 memcpy(&sessionid
, dbuf
.dptr
, sizeof(sessionid
));
1195 if (!process_exists(pid_to_procid(sessionid
.pid
))) {
1199 if (sessionid
.pid
== sys_getpid()) {
1203 if (strcmp(ip
, sessionid
.ip_addr
) != 0) {
1207 message_send_pid(pid_to_procid(sessionid
.pid
), MSG_SHUTDOWN
,
1212 static void setup_new_vc_session(void)
1214 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1217 invalidate_all_vuids();
1219 if (lp_reset_on_zero_vc()) {
1220 session_traverse(shutdown_other_smbds
, client_addr());
1224 /****************************************************************************
1225 Reply to a session setup command.
1226 ****************************************************************************/
1228 int reply_sesssetup_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,
1229 int length
,int bufsize
)
1235 DATA_BLOB plaintext_password
;
1237 fstring sub_user
; /* Sainitised username for substituion */
1240 fstring native_lanman
;
1241 fstring primary_domain
;
1242 static BOOL done_sesssetup
= False
;
1243 auth_usersupplied_info
*user_info
= NULL
;
1244 auth_serversupplied_info
*server_info
= NULL
;
1248 BOOL doencrypt
= global_encrypted_passwords_negotiated
;
1250 DATA_BLOB session_key
;
1252 START_PROFILE(SMBsesssetupX
);
1254 ZERO_STRUCT(lm_resp
);
1255 ZERO_STRUCT(nt_resp
);
1256 ZERO_STRUCT(plaintext_password
);
1258 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf
, smb_wct
), SVAL(inbuf
, smb_flg2
)));
1260 /* a SPNEGO session setup has 12 command words, whereas a normal
1261 NT1 session setup has 13. See the cifs spec. */
1262 if (CVAL(inbuf
, smb_wct
) == 12 &&
1263 (SVAL(inbuf
, smb_flg2
) & FLAGS2_EXTENDED_SECURITY
)) {
1264 if (!global_spnego_negotiated
) {
1265 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1266 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1269 if (SVAL(inbuf
,smb_vwv4
) == 0) {
1270 setup_new_vc_session();
1272 return reply_sesssetup_and_X_spnego(conn
, inbuf
, outbuf
, length
, bufsize
);
1275 smb_bufsize
= SVAL(inbuf
,smb_vwv2
);
1277 if (Protocol
< PROTOCOL_NT1
) {
1278 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
1280 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1281 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1283 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> smb_bufrem(inbuf
, smb_buf(inbuf
)))) {
1284 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1288 lm_resp
= data_blob(smb_buf(inbuf
), passlen1
);
1290 plaintext_password
= data_blob(smb_buf(inbuf
), passlen1
+1);
1291 /* Ensure null termination */
1292 plaintext_password
.data
[passlen1
] = 0;
1295 srvstr_pull_buf(inbuf
, user
, smb_buf(inbuf
)+passlen1
, sizeof(user
), STR_TERMINATE
);
1299 uint16 passlen1
= SVAL(inbuf
,smb_vwv7
);
1300 uint16 passlen2
= SVAL(inbuf
,smb_vwv8
);
1301 enum remote_arch_types ra_type
= get_remote_arch();
1302 char *p
= smb_buf(inbuf
);
1303 char *save_p
= smb_buf(inbuf
);
1307 if(global_client_caps
== 0) {
1308 global_client_caps
= IVAL(inbuf
,smb_vwv11
);
1310 if (!(global_client_caps
& CAP_STATUS32
)) {
1311 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1314 /* client_caps is used as final determination if client is NT or Win95.
1315 This is needed to return the correct error codes in some
1319 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
|| ra_type
== RA_WIN95
) {
1320 if(!(global_client_caps
& (CAP_NT_SMBS
| CAP_STATUS32
))) {
1321 set_remote_arch( RA_WIN95
);
1327 /* both Win95 and WinNT stuff up the password lengths for
1328 non-encrypting systems. Uggh.
1330 if passlen1==24 its a win95 system, and its setting the
1331 password length incorrectly. Luckily it still works with the
1332 default code because Win95 will null terminate the password
1335 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1336 setting passlen2 to some random value which really stuffs
1337 things up. we need to fix that one. */
1339 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 && passlen2
!= 1)
1343 /* check for nasty tricks */
1344 if (passlen1
> MAX_PASS_LEN
|| passlen1
> smb_bufrem(inbuf
, p
)) {
1345 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1348 if (passlen2
> MAX_PASS_LEN
|| passlen2
> smb_bufrem(inbuf
, p
+passlen1
)) {
1349 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER
));
1352 /* Save the lanman2 password and the NT md4 password. */
1354 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1359 lm_resp
= data_blob(p
, passlen1
);
1360 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1363 BOOL unic
=SVAL(inbuf
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
;
1366 /* This was the previous fix. Not sure if it's still valid. JRA. */
1367 if ((ra_type
== RA_WINNT
) && (passlen2
== 0) && unic
&& passlen1
) {
1368 /* NT4.0 stuffs up plaintext unicode password lengths... */
1369 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
) + 1,
1370 sizeof(pass
), passlen1
, STR_TERMINATE
);
1373 if (unic
&& (passlen2
== 0) && passlen1
) {
1374 /* Only a ascii plaintext password was sent. */
1375 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
), sizeof(pass
),
1376 passlen1
, STR_TERMINATE
|STR_ASCII
);
1378 srvstr_pull(inbuf
, pass
, smb_buf(inbuf
),
1379 sizeof(pass
), unic
? passlen2
: passlen1
,
1382 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1385 p
+= passlen1
+ passlen2
;
1386 p
+= srvstr_pull_buf(inbuf
, user
, p
, sizeof(user
), STR_TERMINATE
);
1387 p
+= srvstr_pull_buf(inbuf
, domain
, p
, sizeof(domain
), STR_TERMINATE
);
1388 p
+= srvstr_pull_buf(inbuf
, native_os
, p
, sizeof(native_os
), STR_TERMINATE
);
1389 p
+= srvstr_pull_buf(inbuf
, native_lanman
, p
, sizeof(native_lanman
), STR_TERMINATE
);
1391 /* not documented or decoded by Ethereal but there is one more string
1392 in the extra bytes which is the same as the PrimaryDomain when using
1393 extended security. Windows NT 4 and 2003 use this string to store
1394 the native lanman string. Windows 9x does not include a string here
1395 at all so we have to check if we have any extra bytes left */
1397 byte_count
= SVAL(inbuf
, smb_vwv13
);
1398 if ( PTR_DIFF(p
, save_p
) < byte_count
)
1399 p
+= srvstr_pull_buf(inbuf
, primary_domain
, p
, sizeof(primary_domain
), STR_TERMINATE
);
1401 fstrcpy( primary_domain
, "null" );
1403 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1404 domain
, native_os
, native_lanman
, primary_domain
));
1406 if ( ra_type
== RA_WIN2K
) {
1407 if ( strlen(native_lanman
) == 0 )
1408 ra_lanman_string( primary_domain
);
1410 ra_lanman_string( native_lanman
);
1415 if (SVAL(inbuf
,smb_vwv4
) == 0) {
1416 setup_new_vc_session();
1419 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain
, user
, get_remote_machine_name()));
1422 if (global_spnego_negotiated
) {
1424 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1426 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1427 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1429 fstrcpy(sub_user
, user
);
1431 fstrcpy(sub_user
, lp_guestaccount());
1434 sub_set_smb_name(sub_user
);
1436 reload_services(True
);
1438 if (lp_security() == SEC_SHARE
) {
1439 /* in share level we should ignore any passwords */
1441 data_blob_free(&lm_resp
);
1442 data_blob_free(&nt_resp
);
1443 data_blob_clear_free(&plaintext_password
);
1445 map_username(sub_user
);
1446 add_session_user(sub_user
);
1447 add_session_workgroup(domain
);
1448 /* Then force it to null for the benfit of the code below */
1454 nt_status
= check_guest_password(&server_info
);
1456 } else if (doencrypt
) {
1457 if (!negprot_global_auth_context
) {
1458 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1459 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1461 nt_status
= make_user_info_for_reply_enc(&user_info
, user
, domain
,
1463 if (NT_STATUS_IS_OK(nt_status
)) {
1464 nt_status
= negprot_global_auth_context
->check_ntlm_password(negprot_global_auth_context
,
1469 struct auth_context
*plaintext_auth_context
= NULL
;
1472 nt_status
= make_auth_context_subsystem(&plaintext_auth_context
);
1474 if (NT_STATUS_IS_OK(nt_status
)) {
1475 chal
= plaintext_auth_context
->get_ntlm_challenge(plaintext_auth_context
);
1477 if (!make_user_info_for_reply(&user_info
,
1479 plaintext_password
)) {
1480 nt_status
= NT_STATUS_NO_MEMORY
;
1483 if (NT_STATUS_IS_OK(nt_status
)) {
1484 nt_status
= plaintext_auth_context
->check_ntlm_password(plaintext_auth_context
,
1488 (plaintext_auth_context
->free
)(&plaintext_auth_context
);
1493 free_user_info(&user_info
);
1495 if (!NT_STATUS_IS_OK(nt_status
)) {
1496 nt_status
= do_map_to_guest(nt_status
, &server_info
, user
, domain
);
1499 if (!NT_STATUS_IS_OK(nt_status
)) {
1500 data_blob_free(&nt_resp
);
1501 data_blob_free(&lm_resp
);
1502 data_blob_clear_free(&plaintext_password
);
1503 return ERROR_NT(nt_status_squash(nt_status
));
1506 /* Ensure we can't possible take a code path leading to a null defref. */
1508 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1511 if (!server_info
->ptok
) {
1512 nt_status
= create_local_token(server_info
);
1513 if (!NT_STATUS_IS_OK(nt_status
)) {
1514 DEBUG(10, ("create_local_token failed: %s\n",
1515 nt_errstr(nt_status
)));
1516 data_blob_free(&nt_resp
);
1517 data_blob_free(&lm_resp
);
1518 data_blob_clear_free(&plaintext_password
);
1519 return ERROR_NT(nt_status_squash(nt_status
));
1523 if (server_info
->user_session_key
.data
) {
1524 session_key
= data_blob(server_info
->user_session_key
.data
, server_info
->user_session_key
.length
);
1526 session_key
= data_blob(NULL
, 0);
1529 data_blob_clear_free(&plaintext_password
);
1531 /* it's ok - setup a reply */
1532 set_message(outbuf
,3,0,True
);
1533 if (Protocol
>= PROTOCOL_NT1
) {
1534 char *p
= smb_buf( outbuf
);
1535 p
+= add_signature( outbuf
, p
);
1536 set_message_end( outbuf
, p
);
1537 /* perhaps grab OS version here?? */
1540 if (server_info
->guest
) {
1541 SSVAL(outbuf
,smb_vwv2
,1);
1544 /* register the name and uid as being validated, so further connections
1545 to a uid can get through without a password, on the same VC */
1547 if (lp_security() == SEC_SHARE
) {
1548 sess_vuid
= UID_FIELD_INVALID
;
1549 data_blob_free(&session_key
);
1550 TALLOC_FREE(server_info
);
1552 /* register_vuid keeps the server info */
1553 sess_vuid
= register_vuid(server_info
, session_key
,
1554 nt_resp
.data
? nt_resp
: lm_resp
,
1556 if (sess_vuid
== UID_FIELD_INVALID
) {
1557 data_blob_free(&nt_resp
);
1558 data_blob_free(&lm_resp
);
1559 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1562 /* current_user_info is changed on new vuid */
1563 reload_services( True
);
1565 sessionsetup_start_signing_engine(server_info
, inbuf
);
1568 data_blob_free(&nt_resp
);
1569 data_blob_free(&lm_resp
);
1571 SSVAL(outbuf
,smb_uid
,sess_vuid
);
1572 SSVAL(inbuf
,smb_uid
,sess_vuid
);
1574 if (!done_sesssetup
)
1575 max_send
= MIN(max_send
,smb_bufsize
);
1577 done_sesssetup
= True
;
1579 END_PROFILE(SMBsesssetupX
);
1580 return chain_reply(inbuf
,outbuf
,length
,bufsize
);