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"
28 extern enum protocol_types Protocol;
30 /* For split krb5 SPNEGO blobs. */
31 struct pending_auth_data {
32 struct pending_auth_data *prev, *next;
33 uint16 vuid; /* Tag for this entry. */
34 uint16 smbpid; /* Alternate tag for this entry. */
36 DATA_BLOB partial_data;
40 on a logon error possibly map the error to success if "map to guest"
43 static NTSTATUS do_map_to_guest(NTSTATUS status,
44 auth_serversupplied_info **server_info,
45 const char *user, const char *domain)
47 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
48 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
49 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
50 DEBUG(3,("No such user %s [%s] - using guest account\n",
52 status = make_server_info_guest(NULL, server_info);
56 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
57 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
58 DEBUG(3,("Registered username %s for guest access\n",
60 status = make_server_info_guest(NULL, server_info);
67 /****************************************************************************
68 Add the standard 'Samba' signature to the end of the session setup.
69 ****************************************************************************/
71 static int push_signature(uint8 **outbuf)
78 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
80 if (tmp == -1) return -1;
83 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
84 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
88 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
91 if (tmp == -1) return -1;
94 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
96 if (tmp == -1) return -1;
102 /****************************************************************************
103 Send a security blob via a session setup reply.
104 ****************************************************************************/
106 static void reply_sesssetup_blob(struct smb_request *req,
110 if (!NT_STATUS_IS_OK(nt_status) &&
111 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
112 reply_nterror(req, nt_status_squash(nt_status));
116 nt_status = nt_status_squash(nt_status);
117 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
118 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
119 SSVAL(req->outbuf, smb_vwv3, blob.length);
121 if ((message_push_blob(&req->outbuf, blob) == -1)
122 || (push_signature(&req->outbuf) == -1)) {
123 reply_nterror(req, NT_STATUS_NO_MEMORY);
127 /****************************************************************************
128 Do a 'guest' logon, getting back the
129 ****************************************************************************/
131 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
133 struct auth_context *auth_context;
134 auth_usersupplied_info *user_info = NULL;
137 unsigned char chal[8];
141 DEBUG(3,("Got anonymous request\n"));
143 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
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,
156 (auth_context->free)(&auth_context);
157 free_user_info(&user_info);
165 /* Experiment that failed. See "only happens with a KDC" comment below. */
166 /****************************************************************************
167 Cerate a clock skew error blob for a Windows client.
168 ****************************************************************************/
170 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
172 krb5_context context = NULL;
173 krb5_error_code kerr = 0;
175 krb5_principal host_princ = NULL;
176 char *host_princ_s = NULL;
179 *pblob_out = data_blob_null;
181 initialize_krb5_error_table();
182 kerr = krb5_init_context(&context);
186 /* Create server principal. */
187 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
191 strlower_m(host_princ_s);
193 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
195 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
196 "for name %s: Error %s\n",
197 host_princ_s, error_message(kerr) ));
201 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
204 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
205 "failed: Error %s\n",
206 error_message(kerr) ));
210 *pblob_out = data_blob(reply.data, reply.length);
211 kerberos_free_data_contents(context,&reply);
217 SAFE_FREE(host_princ_s);
220 krb5_free_principal(context, host_princ);
222 krb5_free_context(context);
227 /****************************************************************************
228 Reply to a session setup spnego negotiate packet for kerberos.
229 ****************************************************************************/
231 static void reply_spnego_kerberos(struct smb_request *req,
235 bool *p_invalidate_vuid)
239 char *client, *p, *domain;
240 fstring netbios_domain_name;
243 int sess_vuid = req->vuid;
244 NTSTATUS ret = NT_STATUS_OK;
245 struct PAC_DATA *pac_data = NULL;
246 DATA_BLOB ap_rep, ap_rep_wrapped, response;
247 auth_serversupplied_info *server_info = NULL;
248 DATA_BLOB session_key = data_blob_null;
250 DATA_BLOB nullblob = data_blob_null;
251 fstring real_username;
252 bool map_domainuser_to_guest = False;
253 bool username_was_mapped;
254 struct PAC_LOGON_INFO *logon_info = NULL;
258 ZERO_STRUCT(ap_rep_wrapped);
259 ZERO_STRUCT(response);
261 /* Normally we will always invalidate the intermediate vuid. */
262 *p_invalidate_vuid = True;
264 mem_ctx = talloc_init("reply_spnego_kerberos");
265 if (mem_ctx == NULL) {
266 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
270 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
271 talloc_destroy(mem_ctx);
272 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
276 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
277 &client, &pac_data, &ap_rep,
280 data_blob_free(&ticket);
282 if (!NT_STATUS_IS_OK(ret)) {
284 /* Experiment that failed.
285 * See "only happens with a KDC" comment below. */
287 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
290 * Windows in this case returns
291 * NT_STATUS_MORE_PROCESSING_REQUIRED
292 * with a negTokenTarg blob containing an krb5_error
293 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
294 * The client then fixes its clock and continues rather
295 * than giving an error. JRA.
296 * -- Looks like this only happens with a KDC. JRA.
299 bool ok = make_krb5_skew_error(&ap_rep);
301 talloc_destroy(mem_ctx);
302 return ERROR_NT(nt_status_squash(
303 NT_STATUS_LOGON_FAILURE));
305 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
307 response = spnego_gen_auth_response(&ap_rep_wrapped,
308 ret, OID_KERBEROS5_OLD);
309 reply_sesssetup_blob(conn, inbuf, outbuf, response,
310 NT_STATUS_MORE_PROCESSING_REQUIRED);
313 * In this one case we don't invalidate the
314 * intermediate vuid as we're expecting the client
315 * to re-use it for the next sessionsetupX packet. JRA.
318 *p_invalidate_vuid = False;
320 data_blob_free(&ap_rep);
321 data_blob_free(&ap_rep_wrapped);
322 data_blob_free(&response);
323 talloc_destroy(mem_ctx);
324 return -1; /* already replied */
327 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
328 ret = NT_STATUS_LOGON_FAILURE;
331 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
333 talloc_destroy(mem_ctx);
334 reply_nterror(req, nt_status_squash(ret));
338 DEBUG(3,("Ticket name is [%s]\n", client));
340 p = strchr_m(client, '@');
342 DEBUG(3,("Doesn't look like a valid principal\n"));
343 data_blob_free(&ap_rep);
344 data_blob_free(&session_key);
345 talloc_destroy(mem_ctx);
346 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
352 /* save the PAC data if we have it */
355 logon_info = get_logon_info_from_pac(pac_data);
357 netsamlogon_cache_store( client, &logon_info->info3 );
361 if (!strequal(p+1, lp_realm())) {
362 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
363 if (!lp_allow_trusted_domains()) {
364 data_blob_free(&ap_rep);
365 data_blob_free(&session_key);
366 talloc_destroy(mem_ctx);
367 reply_nterror(req, nt_status_squash(
368 NT_STATUS_LOGON_FAILURE));
373 /* this gives a fully qualified user name (ie. with full realm).
374 that leads to very long usernames, but what else can we do? */
378 if (logon_info && logon_info->info3.base.domain.string) {
379 fstrcpy(netbios_domain_name,
380 logon_info->info3.base.domain.string);
381 domain = netbios_domain_name;
382 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
386 /* If we have winbind running, we can (and must) shorten the
387 username by using the short netbios name. Otherwise we will
388 have inconsistent user names. With Kerberos, we get the
389 fully qualified realm, with ntlmssp we get the short
390 name. And even w2k3 does use ntlmssp if you for example
391 connect to an ip address. */
394 struct wbcDomainInfo *info = NULL;
396 DEBUG(10, ("Mapping [%s] to short name\n", domain));
398 wbc_status = wbcDomainInfo(domain, &info);
400 if (WBC_ERROR_IS_OK(wbc_status)) {
402 fstrcpy(netbios_domain_name,
406 domain = netbios_domain_name;
407 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
409 DEBUG(3, ("Could not find short name: %s\n",
410 wbcErrorString(wbc_status)));
414 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
416 /* lookup the passwd struct, create a new user if necessary */
418 username_was_mapped = map_username( user );
420 pw = smb_getpwnam( mem_ctx, user, real_username, True );
423 /* if a real user check pam account restrictions */
424 /* only really perfomed if "obey pam restriction" is true */
425 /* do this before an eventual mapping to guest occurs */
426 ret = smb_pam_accountcheck(pw->pw_name);
427 if ( !NT_STATUS_IS_OK(ret)) {
428 DEBUG(1,("PAM account restriction "
429 "prevents user login\n"));
430 data_blob_free(&ap_rep);
431 data_blob_free(&session_key);
432 TALLOC_FREE(mem_ctx);
433 reply_nterror(req, nt_status_squash(ret));
440 /* this was originally the behavior of Samba 2.2, if a user
441 did not have a local uid but has been authenticated, then
442 map them to a guest account */
444 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
445 map_domainuser_to_guest = True;
446 fstrcpy(user,lp_guestaccount());
447 pw = smb_getpwnam( mem_ctx, user, real_username, True );
450 /* extra sanity check that the guest account is valid */
453 DEBUG(1,("Username %s is invalid on this system\n",
455 data_blob_free(&ap_rep);
456 data_blob_free(&session_key);
457 TALLOC_FREE(mem_ctx);
458 reply_nterror(req, nt_status_squash(
459 NT_STATUS_LOGON_FAILURE));
464 /* setup the string used by %U */
466 sub_set_smb_name( real_username );
467 reload_services(True);
469 if ( map_domainuser_to_guest ) {
470 make_server_info_guest(NULL, &server_info);
471 } else if (logon_info) {
472 /* pass the unmapped username here since map_username()
473 will be called again from inside make_server_info_info3() */
475 ret = make_server_info_info3(mem_ctx, client, domain,
476 &server_info, &logon_info->info3);
477 if ( !NT_STATUS_IS_OK(ret) ) {
478 DEBUG(1,("make_server_info_info3 failed: %s!\n",
480 data_blob_free(&ap_rep);
481 data_blob_free(&session_key);
482 TALLOC_FREE(mem_ctx);
483 reply_nterror(req, nt_status_squash(ret));
488 ret = make_server_info_pw(&server_info, real_username, pw);
490 if ( !NT_STATUS_IS_OK(ret) ) {
491 DEBUG(1,("make_server_info_pw failed: %s!\n",
493 data_blob_free(&ap_rep);
494 data_blob_free(&session_key);
495 TALLOC_FREE(mem_ctx);
496 reply_nterror(req, nt_status_squash(ret));
500 /* make_server_info_pw does not set the domain. Without this
501 * we end up with the local netbios name in substitutions for
504 if (server_info->sam_account != NULL) {
505 pdb_set_domain(server_info->sam_account,
510 server_info->nss_token |= username_was_mapped;
512 /* we need to build the token for the user. make_server_info_guest()
515 if ( !server_info->ptok ) {
516 ret = create_local_token( server_info );
517 if ( !NT_STATUS_IS_OK(ret) ) {
518 DEBUG(10,("failed to create local token: %s\n",
520 data_blob_free(&ap_rep);
521 data_blob_free(&session_key);
522 TALLOC_FREE( mem_ctx );
523 TALLOC_FREE( server_info );
524 reply_nterror(req, nt_status_squash(ret));
529 if (!is_partial_auth_vuid(sess_vuid)) {
530 sess_vuid = register_initial_vuid();
533 data_blob_free(&server_info->user_session_key);
534 server_info->user_session_key = session_key;
535 session_key = data_blob_null;
537 /* register_existing_vuid keeps the server info */
538 /* register_existing_vuid takes ownership of session_key on success,
539 * no need to free after this on success. A better interface would copy
542 sess_vuid = register_existing_vuid(sess_vuid,
547 reply_outbuf(req, 4, 0);
548 SSVAL(req->outbuf,smb_uid,sess_vuid);
550 if (sess_vuid == UID_FIELD_INVALID ) {
551 ret = NT_STATUS_LOGON_FAILURE;
553 /* current_user_info is changed on new vuid */
554 reload_services( True );
556 SSVAL(req->outbuf, smb_vwv3, 0);
558 if (server_info->guest) {
559 SSVAL(req->outbuf,smb_vwv2,1);
562 SSVAL(req->outbuf, smb_uid, sess_vuid);
564 /* Successful logon. Keep this vuid. */
565 *p_invalidate_vuid = False;
568 /* wrap that up in a nice GSS-API wrapping */
569 if (NT_STATUS_IS_OK(ret)) {
570 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
573 ap_rep_wrapped = data_blob_null;
575 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
577 reply_sesssetup_blob(req, response, ret);
579 data_blob_free(&ap_rep);
580 data_blob_free(&ap_rep_wrapped);
581 data_blob_free(&response);
582 TALLOC_FREE(mem_ctx);
587 /****************************************************************************
588 Send a session setup reply, wrapped in SPNEGO.
589 Get vuid and check first.
590 End the NTLMSSP exchange context if we are OK/complete fail
591 This should be split into two functions, one to handle each
592 leg of the NTLM auth steps.
593 ***************************************************************************/
595 static void reply_spnego_ntlmssp(struct smb_request *req,
597 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
598 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
603 struct auth_serversupplied_info *server_info = NULL;
605 if (NT_STATUS_IS_OK(nt_status)) {
606 server_info = (*auth_ntlmssp_state)->server_info;
608 nt_status = do_map_to_guest(nt_status,
610 (*auth_ntlmssp_state)->ntlmssp_state->user,
611 (*auth_ntlmssp_state)->ntlmssp_state->domain);
614 reply_outbuf(req, 4, 0);
616 SSVAL(req->outbuf, smb_uid, vuid);
618 if (NT_STATUS_IS_OK(nt_status)) {
619 DATA_BLOB nullblob = data_blob_null;
621 if (!is_partial_auth_vuid(vuid)) {
622 nt_status = NT_STATUS_LOGON_FAILURE;
626 data_blob_free(&server_info->user_session_key);
627 server_info->user_session_key =
630 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
631 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
633 /* register_existing_vuid keeps the server info */
634 if (register_existing_vuid(vuid,
635 server_info, nullblob,
636 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
638 nt_status = NT_STATUS_LOGON_FAILURE;
642 (*auth_ntlmssp_state)->server_info = NULL;
644 /* current_user_info is changed on new vuid */
645 reload_services( True );
647 SSVAL(req->outbuf, smb_vwv3, 0);
649 if (server_info->guest) {
650 SSVAL(req->outbuf,smb_vwv2,1);
657 response = spnego_gen_auth_response(ntlmssp_blob,
660 response = *ntlmssp_blob;
663 reply_sesssetup_blob(req, response, nt_status);
665 data_blob_free(&response);
668 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
669 and the other end, that we are not finished yet. */
671 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
672 /* NB. This is *NOT* an error case. JRA */
673 auth_ntlmssp_end(auth_ntlmssp_state);
674 if (!NT_STATUS_IS_OK(nt_status)) {
675 /* Kill the intermediate vuid */
676 invalidate_vuid(vuid);
681 /****************************************************************************
682 Is this a krb5 mechanism ?
683 ****************************************************************************/
685 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
686 DATA_BLOB *pblob_out,
689 char *OIDs[ASN1_MAX_OIDS];
691 NTSTATUS ret = NT_STATUS_OK;
693 *kerb_mechOID = NULL;
695 /* parse out the OIDs and the first sec blob */
696 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
697 return NT_STATUS_LOGON_FAILURE;
700 /* only look at the first OID for determining the mechToken --
701 according to RFC2478, we should choose the one we want
702 and renegotiate, but i smell a client bug here..
704 Problem observed when connecting to a member (samba box)
705 of an AD domain as a user in a Samba domain. Samba member
706 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
707 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
708 NTLMSSP mechtoken. --jerry */
711 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
712 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
713 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
714 if (*kerb_mechOID == NULL) {
715 ret = NT_STATUS_NO_MEMORY;
720 for (i=0;OIDs[i];i++) {
721 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
722 talloc_free(OIDs[i]);
727 /****************************************************************************
728 Fall back from krb5 to NTLMSSP.
729 ****************************************************************************/
731 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
736 reply_outbuf(req, 4, 0);
737 SSVAL(req->outbuf,smb_uid,vuid);
739 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
740 "but set to downgrade to NTLMSSP\n"));
742 response = spnego_gen_auth_response(NULL,
743 NT_STATUS_MORE_PROCESSING_REQUIRED,
745 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
746 data_blob_free(&response);
749 /****************************************************************************
750 Reply to a session setup spnego negotiate packet.
751 ****************************************************************************/
753 static void reply_spnego_negotiate(struct smb_request *req,
756 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
760 char *kerb_mech = NULL;
763 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
764 if (!NT_STATUS_IS_OK(status)) {
765 /* Kill the intermediate vuid */
766 invalidate_vuid(vuid);
767 reply_nterror(req, nt_status_squash(status));
771 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
772 (unsigned long)secblob.length));
775 if (kerb_mech && ((lp_security()==SEC_ADS) ||
776 USE_KERBEROS_KEYTAB) ) {
777 bool destroy_vuid = True;
778 reply_spnego_kerberos(req, &secblob, kerb_mech,
779 vuid, &destroy_vuid);
780 data_blob_free(&secblob);
782 /* Kill the intermediate vuid */
783 invalidate_vuid(vuid);
785 SAFE_FREE(kerb_mech);
790 if (*auth_ntlmssp_state) {
791 auth_ntlmssp_end(auth_ntlmssp_state);
795 data_blob_free(&secblob);
796 /* The mechtoken is a krb5 ticket, but
797 * we need to fall back to NTLM. */
798 reply_spnego_downgrade_to_ntlmssp(req, vuid);
799 SAFE_FREE(kerb_mech);
803 status = auth_ntlmssp_start(auth_ntlmssp_state);
804 if (!NT_STATUS_IS_OK(status)) {
805 /* Kill the intermediate vuid */
806 invalidate_vuid(vuid);
807 reply_nterror(req, nt_status_squash(status));
811 status = auth_ntlmssp_update(*auth_ntlmssp_state,
814 data_blob_free(&secblob);
816 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
817 &chal, status, OID_NTLMSSP, true);
819 data_blob_free(&chal);
821 /* already replied */
825 /****************************************************************************
826 Reply to a session setup spnego auth packet.
827 ****************************************************************************/
829 static void reply_spnego_auth(struct smb_request *req,
832 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
834 DATA_BLOB auth = data_blob_null;
835 DATA_BLOB auth_reply = data_blob_null;
836 DATA_BLOB secblob = data_blob_null;
837 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
839 if (!spnego_parse_auth(blob1, &auth)) {
841 file_save("auth.dat", blob1.data, blob1.length);
843 /* Kill the intermediate vuid */
844 invalidate_vuid(vuid);
846 reply_nterror(req, nt_status_squash(
847 NT_STATUS_LOGON_FAILURE));
851 if (auth.data[0] == ASN1_APPLICATION(0)) {
852 /* Might be a second negTokenTarg packet */
853 char *kerb_mech = NULL;
855 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
857 if (!NT_STATUS_IS_OK(status)) {
858 /* Kill the intermediate vuid */
859 invalidate_vuid(vuid);
860 reply_nterror(req, nt_status_squash(status));
864 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
865 (unsigned long)secblob.length));
867 if (kerb_mech && ((lp_security()==SEC_ADS) ||
868 USE_KERBEROS_KEYTAB)) {
869 bool destroy_vuid = True;
870 reply_spnego_kerberos(req, &secblob, kerb_mech,
871 vuid, &destroy_vuid);
872 data_blob_free(&secblob);
873 data_blob_free(&auth);
875 /* Kill the intermediate vuid */
876 invalidate_vuid(vuid);
878 SAFE_FREE(kerb_mech);
882 /* Can't blunder into NTLMSSP auth if we have
886 /* Kill the intermediate vuid */
887 invalidate_vuid(vuid);
888 DEBUG(3,("reply_spnego_auth: network "
889 "misconfiguration, client sent us a "
890 "krb5 ticket and kerberos security "
892 reply_nterror(req, nt_status_squash(
893 NT_STATUS_LOGON_FAILURE));
894 SAFE_FREE(kerb_mech);
898 /* If we get here it wasn't a negTokenTarg auth packet. */
899 data_blob_free(&secblob);
901 if (!*auth_ntlmssp_state) {
902 status = auth_ntlmssp_start(auth_ntlmssp_state);
903 if (!NT_STATUS_IS_OK(status)) {
904 /* Kill the intermediate vuid */
905 invalidate_vuid(vuid);
906 reply_nterror(req, nt_status_squash(status));
911 status = auth_ntlmssp_update(*auth_ntlmssp_state,
914 data_blob_free(&auth);
916 /* Don't send the mechid as we've already sent this (RFC4178). */
918 reply_spnego_ntlmssp(req, vuid,
920 &auth_reply, status, NULL, true);
922 data_blob_free(&auth_reply);
924 /* and tell smbd that we have already replied to this packet */
928 /****************************************************************************
929 Delete an entry on the list.
930 ****************************************************************************/
932 static void delete_partial_auth(struct smbd_server_connection *sconn,
933 struct pending_auth_data *pad)
938 DLIST_REMOVE(sconn->smb1.pd_list, pad);
939 data_blob_free(&pad->partial_data);
943 /****************************************************************************
944 Search for a partial SPNEGO auth fragment matching an smbpid.
945 ****************************************************************************/
947 static struct pending_auth_data *get_pending_auth_data(
948 struct smbd_server_connection *sconn,
951 struct pending_auth_data *pad;
953 * NOTE: using the smbpid here is completely wrong...
955 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
957 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
958 if (pad->smbpid == smbpid) {
965 /****************************************************************************
966 Check the size of an SPNEGO blob. If we need more return
967 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
968 the blob to be more than 64k.
969 ****************************************************************************/
971 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
972 uint16 smbpid, uint16 vuid,
975 struct pending_auth_data *pad = NULL;
977 size_t needed_len = 0;
979 pad = get_pending_auth_data(sconn, smbpid);
981 /* Ensure we have some data. */
982 if (pblob->length == 0) {
983 /* Caller can cope. */
984 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
985 delete_partial_auth(sconn, pad);
989 /* Were we waiting for more data ? */
992 size_t copy_len = MIN(65536, pblob->length);
994 /* Integer wrap paranoia.... */
996 if (pad->partial_data.length + copy_len <
997 pad->partial_data.length ||
998 pad->partial_data.length + copy_len < copy_len) {
1000 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1001 "pad->partial_data.length = %u, "
1003 (unsigned int)pad->partial_data.length,
1004 (unsigned int)copy_len ));
1006 delete_partial_auth(sconn, pad);
1007 return NT_STATUS_INVALID_PARAMETER;
1010 DEBUG(10,("check_spnego_blob_complete: "
1011 "pad->partial_data.length = %u, "
1012 "pad->needed_len = %u, "
1014 "pblob->length = %u,\n",
1015 (unsigned int)pad->partial_data.length,
1016 (unsigned int)pad->needed_len,
1017 (unsigned int)copy_len,
1018 (unsigned int)pblob->length ));
1020 tmp_blob = data_blob(NULL,
1021 pad->partial_data.length + copy_len);
1023 /* Concatenate the two (up to copy_len) bytes. */
1024 memcpy(tmp_blob.data,
1025 pad->partial_data.data,
1026 pad->partial_data.length);
1027 memcpy(tmp_blob.data + pad->partial_data.length,
1031 /* Replace the partial data. */
1032 data_blob_free(&pad->partial_data);
1033 pad->partial_data = tmp_blob;
1034 ZERO_STRUCT(tmp_blob);
1037 if (pblob->length >= pad->needed_len) {
1038 /* Yes, replace pblob. */
1039 data_blob_free(pblob);
1040 *pblob = pad->partial_data;
1041 ZERO_STRUCT(pad->partial_data);
1042 delete_partial_auth(sconn, pad);
1043 return NT_STATUS_OK;
1046 /* Still need more data. */
1047 pad->needed_len -= copy_len;
1048 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1051 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1052 (pblob->data[0] != ASN1_CONTEXT(1))) {
1053 /* Not something we can determine the
1056 return NT_STATUS_OK;
1059 /* This is a new SPNEGO sessionsetup - see if
1060 * the data given in this blob is enough.
1063 data = asn1_init(NULL);
1065 return NT_STATUS_NO_MEMORY;
1068 asn1_load(data, *pblob);
1069 asn1_start_tag(data, pblob->data[0]);
1070 if (data->has_error || data->nesting == NULL) {
1072 /* Let caller catch. */
1073 return NT_STATUS_OK;
1076 /* Integer wrap paranoia.... */
1078 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1079 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1081 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1082 "data.nesting->taglen = %u, "
1083 "data.nesting->start = %u\n",
1084 (unsigned int)data->nesting->taglen,
1085 (unsigned int)data->nesting->start ));
1088 return NT_STATUS_INVALID_PARAMETER;
1091 /* Total length of the needed asn1 is the tag length
1092 * plus the current offset. */
1094 needed_len = data->nesting->taglen + data->nesting->start;
1097 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1098 "pblob->length = %u\n",
1099 (unsigned int)needed_len,
1100 (unsigned int)pblob->length ));
1102 if (needed_len <= pblob->length) {
1103 /* Nothing to do - blob is complete. */
1104 return NT_STATUS_OK;
1107 /* Refuse the blob if it's bigger than 64k. */
1108 if (needed_len > 65536) {
1109 DEBUG(2,("check_spnego_blob_complete: needed_len "
1111 (unsigned int)needed_len ));
1112 return NT_STATUS_INVALID_PARAMETER;
1115 /* We must store this blob until complete. */
1116 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1117 return NT_STATUS_NO_MEMORY;
1119 pad->needed_len = needed_len - pblob->length;
1120 pad->partial_data = data_blob(pblob->data, pblob->length);
1121 if (pad->partial_data.data == NULL) {
1123 return NT_STATUS_NO_MEMORY;
1125 pad->smbpid = smbpid;
1127 DLIST_ADD(sconn->smb1.pd_list, pad);
1129 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1132 /****************************************************************************
1133 Reply to a session setup command.
1134 conn POINTER CAN BE NULL HERE !
1135 ****************************************************************************/
1137 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1143 const char *native_os;
1144 const char *native_lanman;
1145 const char *primary_domain;
1147 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1148 enum remote_arch_types ra_type = get_remote_arch();
1149 int vuid = req->vuid;
1150 user_struct *vuser = NULL;
1151 NTSTATUS status = NT_STATUS_OK;
1152 uint16 smbpid = req->smbpid;
1153 struct smbd_server_connection *sconn = smbd_server_conn;
1155 DEBUG(3,("Doing spnego session setup\n"));
1157 if (global_client_caps == 0) {
1158 global_client_caps = IVAL(req->vwv+10, 0);
1160 if (!(global_client_caps & CAP_STATUS32)) {
1161 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1168 if (data_blob_len == 0) {
1169 /* an invalid request */
1170 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1174 bufrem = smbreq_bufrem(req, p);
1175 /* pull the spnego blob */
1176 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1179 file_save("negotiate.dat", blob1.data, blob1.length);
1182 p2 = (char *)req->buf + data_blob_len;
1184 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1186 native_os = tmp ? tmp : "";
1188 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1190 native_lanman = tmp ? tmp : "";
1192 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1194 primary_domain = tmp ? tmp : "";
1196 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1197 native_os, native_lanman, primary_domain));
1199 if ( ra_type == RA_WIN2K ) {
1200 /* Vista sets neither the OS or lanman strings */
1202 if ( !strlen(native_os) && !strlen(native_lanman) )
1203 set_remote_arch(RA_VISTA);
1205 /* Windows 2003 doesn't set the native lanman string,
1206 but does set primary domain which is a bug I think */
1208 if ( !strlen(native_lanman) ) {
1209 ra_lanman_string( primary_domain );
1211 ra_lanman_string( native_lanman );
1215 /* Did we get a valid vuid ? */
1216 if (!is_partial_auth_vuid(vuid)) {
1217 /* No, then try and see if this is an intermediate sessionsetup
1218 * for a large SPNEGO packet. */
1219 struct pending_auth_data *pad;
1220 pad = get_pending_auth_data(sconn, smbpid);
1222 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1223 "pending vuid %u\n",
1224 (unsigned int)pad->vuid ));
1229 /* Do we have a valid vuid now ? */
1230 if (!is_partial_auth_vuid(vuid)) {
1231 /* No, start a new authentication setup. */
1232 vuid = register_initial_vuid();
1233 if (vuid == UID_FIELD_INVALID) {
1234 data_blob_free(&blob1);
1235 reply_nterror(req, nt_status_squash(
1236 NT_STATUS_INVALID_PARAMETER));
1241 vuser = get_partial_auth_user_struct(vuid);
1242 /* This MUST be valid. */
1244 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1247 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1248 * sessionsetup requests as the Windows limit on the security blob
1249 * field is 4k. Bug #4400. JRA.
1252 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 if (!NT_STATUS_EQUAL(status,
1255 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1256 /* Real error - kill the intermediate vuid */
1257 invalidate_vuid(vuid);
1259 data_blob_free(&blob1);
1260 reply_nterror(req, nt_status_squash(status));
1264 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1266 /* its a negTokenTarg packet */
1268 reply_spnego_negotiate(req, vuid, blob1,
1269 &vuser->auth_ntlmssp_state);
1270 data_blob_free(&blob1);
1274 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1276 /* its a auth packet */
1278 reply_spnego_auth(req, vuid, blob1,
1279 &vuser->auth_ntlmssp_state);
1280 data_blob_free(&blob1);
1284 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1287 if (!vuser->auth_ntlmssp_state) {
1288 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 /* Kill the intermediate vuid */
1291 invalidate_vuid(vuid);
1292 data_blob_free(&blob1);
1293 reply_nterror(req, nt_status_squash(status));
1298 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1301 data_blob_free(&blob1);
1303 reply_spnego_ntlmssp(req, vuid,
1304 &vuser->auth_ntlmssp_state,
1305 &chal, status, OID_NTLMSSP, false);
1306 data_blob_free(&chal);
1310 /* what sort of packet is this? */
1311 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1313 data_blob_free(&blob1);
1315 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1318 /****************************************************************************
1319 On new VC == 0, shutdown *all* old connections and users.
1320 It seems that only NT4.x does this. At W2K and above (XP etc.).
1321 a new session setup with VC==0 is ignored.
1322 ****************************************************************************/
1324 static int shutdown_other_smbds(struct db_record *rec,
1325 const struct connections_key *key,
1326 const struct connections_data *crec,
1329 const char *ip = (const char *)private_data;
1331 if (!process_exists(crec->pid)) {
1335 if (procid_is_me(&crec->pid)) {
1339 if (strcmp(ip, crec->addr) != 0) {
1343 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1344 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1346 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1351 static void setup_new_vc_session(void)
1353 char addr[INET6_ADDRSTRLEN];
1355 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1356 "compatible we would close all old resources.\n"));
1359 invalidate_all_vuids();
1361 if (lp_reset_on_zero_vc()) {
1362 connections_forall(shutdown_other_smbds,
1363 CONST_DISCARD(void *,
1364 client_addr(get_client_fd(),addr,sizeof(addr))));
1368 /****************************************************************************
1369 Reply to a session setup command.
1370 ****************************************************************************/
1372 void reply_sesssetup_and_X(struct smb_request *req)
1378 DATA_BLOB plaintext_password;
1381 fstring sub_user; /* Sainitised username for substituion */
1383 const char *native_os;
1384 const char *native_lanman;
1385 const char *primary_domain;
1386 auth_usersupplied_info *user_info = NULL;
1387 auth_serversupplied_info *server_info = NULL;
1388 uint16 smb_flag2 = req->flags2;
1392 bool doencrypt = global_encrypted_passwords_negotiated;
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->vwv+4, 0) == 0) {
1418 setup_new_vc_session();
1421 reply_sesssetup_and_X_spnego(req);
1422 END_PROFILE(SMBsesssetupX);
1426 smb_bufsize = SVAL(req->vwv+2, 0);
1428 if (Protocol < PROTOCOL_NT1) {
1429 uint16 passlen1 = SVAL(req->vwv+7, 0);
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) || (passlen1 > req->buflen)) {
1436 reply_nterror(req, nt_status_squash(
1437 NT_STATUS_INVALID_PARAMETER));
1438 END_PROFILE(SMBsesssetupX);
1443 lm_resp = data_blob(req->buf, passlen1);
1445 plaintext_password = data_blob(req->buf, passlen1+1);
1446 /* Ensure null termination */
1447 plaintext_password.data[passlen1] = 0;
1450 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1451 req->buf + passlen1, STR_TERMINATE);
1452 user = tmp ? tmp : "";
1457 uint16 passlen1 = SVAL(req->vwv+7, 0);
1458 uint16 passlen2 = SVAL(req->vwv+8, 0);
1459 enum remote_arch_types ra_type = get_remote_arch();
1460 const uint8_t *p = req->buf;
1461 const uint8_t *save_p = req->buf;
1465 if(global_client_caps == 0) {
1466 global_client_caps = IVAL(req->vwv+11, 0);
1468 if (!(global_client_caps & CAP_STATUS32)) {
1469 remove_from_common_flags2(
1470 FLAGS2_32_BIT_ERROR_CODES);
1473 /* client_caps is used as final determination if
1474 * client is NT or Win95. This is needed to return
1475 * the correct error codes in some circumstances.
1478 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1479 ra_type == RA_WIN95) {
1480 if(!(global_client_caps & (CAP_NT_SMBS|
1482 set_remote_arch( RA_WIN95);
1488 /* both Win95 and WinNT stuff up the password
1489 * lengths for non-encrypting systems. Uggh.
1491 if passlen1==24 its a win95 system, and its setting
1492 the password length incorrectly. Luckily it still
1493 works with the default code because Win95 will null
1494 terminate the password anyway
1496 if passlen1>0 and passlen2>0 then maybe its a NT box
1497 and its setting passlen2 to some random value which
1498 really stuffs things up. we need to fix that one. */
1500 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1506 /* check for nasty tricks */
1507 if (passlen1 > MAX_PASS_LEN
1508 || passlen1 > smbreq_bufrem(req, p)) {
1509 reply_nterror(req, nt_status_squash(
1510 NT_STATUS_INVALID_PARAMETER));
1511 END_PROFILE(SMBsesssetupX);
1515 if (passlen2 > MAX_PASS_LEN
1516 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1517 reply_nterror(req, nt_status_squash(
1518 NT_STATUS_INVALID_PARAMETER));
1519 END_PROFILE(SMBsesssetupX);
1523 /* Save the lanman2 password and the NT md4 password. */
1525 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1530 lm_resp = data_blob(p, passlen1);
1531 nt_resp = data_blob(p+passlen1, passlen2);
1532 } else if (lp_security() != SEC_SHARE) {
1534 * In share level we should ignore any passwords, so
1535 * only read them if we're not.
1538 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1540 if (unic && (passlen2 == 0) && passlen1) {
1541 /* Only a ascii plaintext password was sent. */
1542 (void)srvstr_pull_talloc(talloc_tos(),
1548 STR_TERMINATE|STR_ASCII);
1550 (void)srvstr_pull_talloc(talloc_tos(),
1555 unic ? passlen2 : passlen1,
1559 reply_nterror(req, nt_status_squash(
1560 NT_STATUS_INVALID_PARAMETER));
1561 END_PROFILE(SMBsesssetupX);
1564 plaintext_password = data_blob(pass, strlen(pass)+1);
1567 p += passlen1 + passlen2;
1569 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1571 user = tmp ? tmp : "";
1573 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1575 domain = tmp ? tmp : "";
1577 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1579 native_os = tmp ? tmp : "";
1581 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1583 native_lanman = tmp ? tmp : "";
1585 /* not documented or decoded by Ethereal but there is one more
1586 * string in the extra bytes which is the same as the
1587 * PrimaryDomain when using extended security. Windows NT 4
1588 * and 2003 use this string to store the native lanman string.
1589 * Windows 9x does not include a string here at all so we have
1590 * to check if we have any extra bytes left */
1592 byte_count = SVAL(req->vwv+13, 0);
1593 if ( PTR_DIFF(p, save_p) < byte_count) {
1594 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1596 primary_domain = tmp ? tmp : "";
1598 primary_domain = talloc_strdup(talloc_tos(), "null");
1601 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1602 "PrimaryDomain=[%s]\n",
1603 domain, native_os, native_lanman, primary_domain));
1605 if ( ra_type == RA_WIN2K ) {
1606 if ( strlen(native_lanman) == 0 )
1607 ra_lanman_string( primary_domain );
1609 ra_lanman_string( native_lanman );
1614 if (SVAL(req->vwv+4, 0) == 0) {
1615 setup_new_vc_session();
1618 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1619 domain, user, get_remote_machine_name()));
1622 if (global_spnego_negotiated) {
1624 /* This has to be here, because this is a perfectly
1625 * valid behaviour for guest logons :-( */
1627 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1628 "at 'normal' session setup after "
1629 "negotiating spnego.\n"));
1630 reply_nterror(req, nt_status_squash(
1631 NT_STATUS_LOGON_FAILURE));
1632 END_PROFILE(SMBsesssetupX);
1635 fstrcpy(sub_user, user);
1637 fstrcpy(sub_user, lp_guestaccount());
1640 sub_set_smb_name(sub_user);
1642 reload_services(True);
1644 if (lp_security() == SEC_SHARE) {
1645 /* In share level we should ignore any passwords */
1647 data_blob_free(&lm_resp);
1648 data_blob_free(&nt_resp);
1649 data_blob_clear_free(&plaintext_password);
1651 map_username(sub_user);
1652 add_session_user(sub_user);
1653 add_session_workgroup(domain);
1654 /* Then force it to null for the benfit of the code below */
1660 nt_status = check_guest_password(&server_info);
1662 } else if (doencrypt) {
1663 if (!negprot_global_auth_context) {
1664 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1665 "session setup without negprot denied!\n"));
1666 reply_nterror(req, nt_status_squash(
1667 NT_STATUS_LOGON_FAILURE));
1668 END_PROFILE(SMBsesssetupX);
1671 nt_status = make_user_info_for_reply_enc(&user_info, user,
1674 if (NT_STATUS_IS_OK(nt_status)) {
1675 nt_status = negprot_global_auth_context->check_ntlm_password(
1676 negprot_global_auth_context,
1681 struct auth_context *plaintext_auth_context = NULL;
1683 nt_status = make_auth_context_subsystem(
1684 &plaintext_auth_context);
1686 if (NT_STATUS_IS_OK(nt_status)) {
1689 plaintext_auth_context->get_ntlm_challenge(
1690 plaintext_auth_context, chal);
1692 if (!make_user_info_for_reply(&user_info,
1694 plaintext_password)) {
1695 nt_status = NT_STATUS_NO_MEMORY;
1698 if (NT_STATUS_IS_OK(nt_status)) {
1699 nt_status = plaintext_auth_context->check_ntlm_password(
1700 plaintext_auth_context,
1704 (plaintext_auth_context->free)(
1705 &plaintext_auth_context);
1710 free_user_info(&user_info);
1712 if (!NT_STATUS_IS_OK(nt_status)) {
1713 nt_status = do_map_to_guest(nt_status, &server_info,
1717 if (!NT_STATUS_IS_OK(nt_status)) {
1718 data_blob_free(&nt_resp);
1719 data_blob_free(&lm_resp);
1720 data_blob_clear_free(&plaintext_password);
1721 reply_nterror(req, nt_status_squash(nt_status));
1722 END_PROFILE(SMBsesssetupX);
1726 /* Ensure we can't possible take a code path leading to a
1729 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1730 END_PROFILE(SMBsesssetupX);
1734 if (!server_info->ptok) {
1735 nt_status = create_local_token(server_info);
1737 if (!NT_STATUS_IS_OK(nt_status)) {
1738 DEBUG(10, ("create_local_token failed: %s\n",
1739 nt_errstr(nt_status)));
1740 data_blob_free(&nt_resp);
1741 data_blob_free(&lm_resp);
1742 data_blob_clear_free(&plaintext_password);
1743 reply_nterror(req, nt_status_squash(nt_status));
1744 END_PROFILE(SMBsesssetupX);
1749 data_blob_clear_free(&plaintext_password);
1751 /* it's ok - setup a reply */
1752 reply_outbuf(req, 3, 0);
1753 if (Protocol >= PROTOCOL_NT1) {
1754 push_signature(&req->outbuf);
1755 /* perhaps grab OS version here?? */
1758 if (server_info->guest) {
1759 SSVAL(req->outbuf,smb_vwv2,1);
1762 /* register the name and uid as being validated, so further connections
1763 to a uid can get through without a password, on the same VC */
1765 if (lp_security() == SEC_SHARE) {
1766 sess_vuid = UID_FIELD_INVALID;
1767 TALLOC_FREE(server_info);
1769 /* Ignore the initial vuid. */
1770 sess_vuid = register_initial_vuid();
1771 if (sess_vuid == UID_FIELD_INVALID) {
1772 data_blob_free(&nt_resp);
1773 data_blob_free(&lm_resp);
1774 reply_nterror(req, nt_status_squash(
1775 NT_STATUS_LOGON_FAILURE));
1776 END_PROFILE(SMBsesssetupX);
1779 /* register_existing_vuid keeps the server info */
1780 sess_vuid = register_existing_vuid(sess_vuid,
1782 nt_resp.data ? nt_resp : lm_resp,
1784 if (sess_vuid == UID_FIELD_INVALID) {
1785 data_blob_free(&nt_resp);
1786 data_blob_free(&lm_resp);
1787 reply_nterror(req, nt_status_squash(
1788 NT_STATUS_LOGON_FAILURE));
1789 END_PROFILE(SMBsesssetupX);
1793 /* current_user_info is changed on new vuid */
1794 reload_services( True );
1797 data_blob_free(&nt_resp);
1798 data_blob_free(&lm_resp);
1800 SSVAL(req->outbuf,smb_uid,sess_vuid);
1801 SSVAL(req->inbuf,smb_uid,sess_vuid);
1803 if (!done_sesssetup)
1804 max_send = MIN(max_send,smb_bufsize);
1806 done_sesssetup = True;
1808 END_PROFILE(SMBsesssetupX);