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;
31 on a logon error possibly map the error to success if "map to guest"
34 static NTSTATUS do_map_to_guest(NTSTATUS status,
35 auth_serversupplied_info **server_info,
36 const char *user, const char *domain)
38 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
39 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
40 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
41 DEBUG(3,("No such user %s [%s] - using guest account\n",
43 status = make_server_info_guest(NULL, server_info);
47 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
48 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
49 DEBUG(3,("Registered username %s for guest access\n",
51 status = make_server_info_guest(NULL, server_info);
58 /****************************************************************************
59 Add the standard 'Samba' signature to the end of the session setup.
60 ****************************************************************************/
62 static int push_signature(uint8 **outbuf)
69 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
71 if (tmp == -1) return -1;
74 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
75 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
79 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
82 if (tmp == -1) return -1;
85 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
87 if (tmp == -1) return -1;
93 /****************************************************************************
94 Send a security blob via a session setup reply.
95 ****************************************************************************/
97 static void reply_sesssetup_blob(struct smb_request *req,
101 if (!NT_STATUS_IS_OK(nt_status) &&
102 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
103 reply_nterror(req, nt_status_squash(nt_status));
107 nt_status = nt_status_squash(nt_status);
108 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
109 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
110 SSVAL(req->outbuf, smb_vwv3, blob.length);
112 if ((message_push_blob(&req->outbuf, blob) == -1)
113 || (push_signature(&req->outbuf) == -1)) {
114 reply_nterror(req, NT_STATUS_NO_MEMORY);
118 /****************************************************************************
119 Do a 'guest' logon, getting back the
120 ****************************************************************************/
122 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
124 struct auth_context *auth_context;
125 auth_usersupplied_info *user_info = NULL;
128 unsigned char chal[8];
132 DEBUG(3,("Got anonymous request\n"));
134 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
139 if (!make_user_info_guest(&user_info)) {
140 (auth_context->free)(&auth_context);
141 return NT_STATUS_NO_MEMORY;
144 nt_status = auth_context->check_ntlm_password(auth_context,
147 (auth_context->free)(&auth_context);
148 free_user_info(&user_info);
156 /* Experiment that failed. See "only happens with a KDC" comment below. */
157 /****************************************************************************
158 Cerate a clock skew error blob for a Windows client.
159 ****************************************************************************/
161 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
163 krb5_context context = NULL;
164 krb5_error_code kerr = 0;
166 krb5_principal host_princ = NULL;
167 char *host_princ_s = NULL;
170 *pblob_out = data_blob_null;
172 initialize_krb5_error_table();
173 kerr = krb5_init_context(&context);
177 /* Create server principal. */
178 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
182 strlower_m(host_princ_s);
184 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
186 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
187 "for name %s: Error %s\n",
188 host_princ_s, error_message(kerr) ));
192 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
195 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
196 "failed: Error %s\n",
197 error_message(kerr) ));
201 *pblob_out = data_blob(reply.data, reply.length);
202 kerberos_free_data_contents(context,&reply);
208 SAFE_FREE(host_princ_s);
211 krb5_free_principal(context, host_princ);
213 krb5_free_context(context);
218 /****************************************************************************
219 Reply to a session setup spnego negotiate packet for kerberos.
220 ****************************************************************************/
222 static void reply_spnego_kerberos(struct smb_request *req,
226 bool *p_invalidate_vuid)
230 char *client, *p, *domain;
231 fstring netbios_domain_name;
234 int sess_vuid = req->vuid;
235 NTSTATUS ret = NT_STATUS_OK;
236 struct PAC_DATA *pac_data = NULL;
237 DATA_BLOB ap_rep, ap_rep_wrapped, response;
238 auth_serversupplied_info *server_info = NULL;
239 DATA_BLOB session_key = data_blob_null;
241 DATA_BLOB nullblob = data_blob_null;
242 fstring real_username;
243 bool map_domainuser_to_guest = False;
244 bool username_was_mapped;
245 struct PAC_LOGON_INFO *logon_info = NULL;
249 ZERO_STRUCT(ap_rep_wrapped);
250 ZERO_STRUCT(response);
252 /* Normally we will always invalidate the intermediate vuid. */
253 *p_invalidate_vuid = True;
255 mem_ctx = talloc_init("reply_spnego_kerberos");
256 if (mem_ctx == NULL) {
257 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
261 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
262 talloc_destroy(mem_ctx);
263 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
267 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
268 &client, &pac_data, &ap_rep,
271 data_blob_free(&ticket);
273 if (!NT_STATUS_IS_OK(ret)) {
275 /* Experiment that failed.
276 * 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
282 * NT_STATUS_MORE_PROCESSING_REQUIRED
283 * with a negTokenTarg blob containing an krb5_error
284 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
285 * The client then fixes its clock and continues rather
286 * than giving an error. JRA.
287 * -- Looks like this only happens with a KDC. JRA.
290 bool ok = make_krb5_skew_error(&ap_rep);
292 talloc_destroy(mem_ctx);
293 return ERROR_NT(nt_status_squash(
294 NT_STATUS_LOGON_FAILURE));
296 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
298 response = spnego_gen_auth_response(&ap_rep_wrapped,
299 ret, OID_KERBEROS5_OLD);
300 reply_sesssetup_blob(conn, inbuf, outbuf, response,
301 NT_STATUS_MORE_PROCESSING_REQUIRED);
304 * In this one case we don't invalidate the
305 * intermediate vuid as we're expecting the client
306 * to re-use it for the next sessionsetupX packet. JRA.
309 *p_invalidate_vuid = False;
311 data_blob_free(&ap_rep);
312 data_blob_free(&ap_rep_wrapped);
313 data_blob_free(&response);
314 talloc_destroy(mem_ctx);
315 return -1; /* already replied */
318 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
319 ret = NT_STATUS_LOGON_FAILURE;
322 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
324 talloc_destroy(mem_ctx);
325 reply_nterror(req, nt_status_squash(ret));
329 DEBUG(3,("Ticket name is [%s]\n", client));
331 p = strchr_m(client, '@');
333 DEBUG(3,("Doesn't look like a valid principal\n"));
334 data_blob_free(&ap_rep);
335 data_blob_free(&session_key);
336 talloc_destroy(mem_ctx);
337 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
343 /* save the PAC data if we have it */
346 logon_info = get_logon_info_from_pac(pac_data);
348 netsamlogon_cache_store( client, &logon_info->info3 );
352 if (!strequal(p+1, lp_realm())) {
353 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
354 if (!lp_allow_trusted_domains()) {
355 data_blob_free(&ap_rep);
356 data_blob_free(&session_key);
357 talloc_destroy(mem_ctx);
358 reply_nterror(req, nt_status_squash(
359 NT_STATUS_LOGON_FAILURE));
364 /* this gives a fully qualified user name (ie. with full realm).
365 that leads to very long usernames, but what else can we do? */
369 if (logon_info && logon_info->info3.base.domain.string) {
370 fstrcpy(netbios_domain_name,
371 logon_info->info3.base.domain.string);
372 domain = netbios_domain_name;
373 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
377 /* If we have winbind running, we can (and must) shorten the
378 username by using the short netbios name. Otherwise we will
379 have inconsistent user names. With Kerberos, we get the
380 fully qualified realm, with ntlmssp we get the short
381 name. And even w2k3 does use ntlmssp if you for example
382 connect to an ip address. */
385 struct wbcDomainInfo *info = NULL;
387 DEBUG(10, ("Mapping [%s] to short name\n", domain));
389 wbc_status = wbcDomainInfo(domain, &info);
391 if (WBC_ERROR_IS_OK(wbc_status)) {
393 fstrcpy(netbios_domain_name,
397 domain = netbios_domain_name;
398 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
400 DEBUG(3, ("Could not find short name: %s\n",
401 wbcErrorString(wbc_status)));
405 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
407 /* lookup the passwd struct, create a new user if necessary */
409 username_was_mapped = map_username( user );
411 pw = smb_getpwnam( mem_ctx, user, real_username, True );
414 /* if a real user check pam account restrictions */
415 /* only really perfomed if "obey pam restriction" is true */
416 /* do this before an eventual mapping to guest occurs */
417 ret = smb_pam_accountcheck(pw->pw_name);
418 if ( !NT_STATUS_IS_OK(ret)) {
419 DEBUG(1,("PAM account restriction "
420 "prevents user login\n"));
421 data_blob_free(&ap_rep);
422 data_blob_free(&session_key);
423 TALLOC_FREE(mem_ctx);
424 reply_nterror(req, nt_status_squash(ret));
431 /* this was originally the behavior of Samba 2.2, if a user
432 did not have a local uid but has been authenticated, then
433 map them to a guest account */
435 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
436 map_domainuser_to_guest = True;
437 fstrcpy(user,lp_guestaccount());
438 pw = smb_getpwnam( mem_ctx, user, real_username, True );
441 /* extra sanity check that the guest account is valid */
444 DEBUG(1,("Username %s is invalid on this system\n",
446 data_blob_free(&ap_rep);
447 data_blob_free(&session_key);
448 TALLOC_FREE(mem_ctx);
449 reply_nterror(req, nt_status_squash(
450 NT_STATUS_LOGON_FAILURE));
455 /* setup the string used by %U */
457 sub_set_smb_name( real_username );
458 reload_services(True);
460 if ( map_domainuser_to_guest ) {
461 make_server_info_guest(NULL, &server_info);
462 } else if (logon_info) {
463 /* pass the unmapped username here since map_username()
464 will be called again from inside make_server_info_info3() */
466 ret = make_server_info_info3(mem_ctx, client, domain,
467 &server_info, &logon_info->info3);
468 if ( !NT_STATUS_IS_OK(ret) ) {
469 DEBUG(1,("make_server_info_info3 failed: %s!\n",
471 data_blob_free(&ap_rep);
472 data_blob_free(&session_key);
473 TALLOC_FREE(mem_ctx);
474 reply_nterror(req, nt_status_squash(ret));
479 ret = make_server_info_pw(&server_info, real_username, pw);
481 if ( !NT_STATUS_IS_OK(ret) ) {
482 DEBUG(1,("make_server_info_pw failed: %s!\n",
484 data_blob_free(&ap_rep);
485 data_blob_free(&session_key);
486 TALLOC_FREE(mem_ctx);
487 reply_nterror(req, nt_status_squash(ret));
491 /* make_server_info_pw does not set the domain. Without this
492 * we end up with the local netbios name in substitutions for
495 if (server_info->sam_account != NULL) {
496 pdb_set_domain(server_info->sam_account,
501 server_info->nss_token |= username_was_mapped;
503 /* we need to build the token for the user. make_server_info_guest()
506 if ( !server_info->ptok ) {
507 ret = create_local_token( server_info );
508 if ( !NT_STATUS_IS_OK(ret) ) {
509 DEBUG(10,("failed to create local token: %s\n",
511 data_blob_free(&ap_rep);
512 data_blob_free(&session_key);
513 TALLOC_FREE( mem_ctx );
514 TALLOC_FREE( server_info );
515 reply_nterror(req, nt_status_squash(ret));
520 if (!is_partial_auth_vuid(sess_vuid)) {
521 sess_vuid = register_initial_vuid();
524 data_blob_free(&server_info->user_session_key);
525 server_info->user_session_key = session_key;
526 session_key = data_blob_null;
528 /* register_existing_vuid keeps the server info */
529 /* register_existing_vuid takes ownership of session_key on success,
530 * no need to free after this on success. A better interface would copy
533 sess_vuid = register_existing_vuid(sess_vuid,
538 reply_outbuf(req, 4, 0);
539 SSVAL(req->outbuf,smb_uid,sess_vuid);
541 if (sess_vuid == UID_FIELD_INVALID ) {
542 ret = NT_STATUS_LOGON_FAILURE;
544 /* current_user_info is changed on new vuid */
545 reload_services( True );
547 SSVAL(req->outbuf, smb_vwv3, 0);
549 if (server_info->guest) {
550 SSVAL(req->outbuf,smb_vwv2,1);
553 SSVAL(req->outbuf, smb_uid, sess_vuid);
555 /* Successful logon. Keep this vuid. */
556 *p_invalidate_vuid = False;
559 /* wrap that up in a nice GSS-API wrapping */
560 if (NT_STATUS_IS_OK(ret)) {
561 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
564 ap_rep_wrapped = data_blob_null;
566 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
568 reply_sesssetup_blob(req, response, ret);
570 data_blob_free(&ap_rep);
571 data_blob_free(&ap_rep_wrapped);
572 data_blob_free(&response);
573 TALLOC_FREE(mem_ctx);
578 /****************************************************************************
579 Send a session setup reply, wrapped in SPNEGO.
580 Get vuid and check first.
581 End the NTLMSSP exchange context if we are OK/complete fail
582 This should be split into two functions, one to handle each
583 leg of the NTLM auth steps.
584 ***************************************************************************/
586 static void reply_spnego_ntlmssp(struct smb_request *req,
588 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
589 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
594 struct auth_serversupplied_info *server_info = NULL;
596 if (NT_STATUS_IS_OK(nt_status)) {
597 server_info = (*auth_ntlmssp_state)->server_info;
599 nt_status = do_map_to_guest(nt_status,
601 (*auth_ntlmssp_state)->ntlmssp_state->user,
602 (*auth_ntlmssp_state)->ntlmssp_state->domain);
605 reply_outbuf(req, 4, 0);
607 SSVAL(req->outbuf, smb_uid, vuid);
609 if (NT_STATUS_IS_OK(nt_status)) {
610 DATA_BLOB nullblob = data_blob_null;
612 if (!is_partial_auth_vuid(vuid)) {
613 nt_status = NT_STATUS_LOGON_FAILURE;
617 data_blob_free(&server_info->user_session_key);
618 server_info->user_session_key =
621 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
622 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
624 /* register_existing_vuid keeps the server info */
625 if (register_existing_vuid(vuid,
626 server_info, nullblob,
627 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
629 nt_status = NT_STATUS_LOGON_FAILURE;
633 (*auth_ntlmssp_state)->server_info = NULL;
635 /* current_user_info is changed on new vuid */
636 reload_services( True );
638 SSVAL(req->outbuf, smb_vwv3, 0);
640 if (server_info->guest) {
641 SSVAL(req->outbuf,smb_vwv2,1);
648 response = spnego_gen_auth_response(ntlmssp_blob,
651 response = *ntlmssp_blob;
654 reply_sesssetup_blob(req, response, nt_status);
656 data_blob_free(&response);
659 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
660 and the other end, that we are not finished yet. */
662 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
663 /* NB. This is *NOT* an error case. JRA */
664 auth_ntlmssp_end(auth_ntlmssp_state);
665 if (!NT_STATUS_IS_OK(nt_status)) {
666 /* Kill the intermediate vuid */
667 invalidate_vuid(vuid);
672 /****************************************************************************
673 Is this a krb5 mechanism ?
674 ****************************************************************************/
676 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
677 DATA_BLOB *pblob_out,
680 char *OIDs[ASN1_MAX_OIDS];
682 NTSTATUS ret = NT_STATUS_OK;
684 *kerb_mechOID = NULL;
686 /* parse out the OIDs and the first sec blob */
687 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
688 return NT_STATUS_LOGON_FAILURE;
691 /* only look at the first OID for determining the mechToken --
692 according to RFC2478, we should choose the one we want
693 and renegotiate, but i smell a client bug here..
695 Problem observed when connecting to a member (samba box)
696 of an AD domain as a user in a Samba domain. Samba member
697 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
698 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
699 NTLMSSP mechtoken. --jerry */
702 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
703 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
704 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
705 if (*kerb_mechOID == NULL) {
706 ret = NT_STATUS_NO_MEMORY;
711 for (i=0;OIDs[i];i++) {
712 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
713 talloc_free(OIDs[i]);
718 /****************************************************************************
719 Fall back from krb5 to NTLMSSP.
720 ****************************************************************************/
722 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
727 reply_outbuf(req, 4, 0);
728 SSVAL(req->outbuf,smb_uid,vuid);
730 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
731 "but set to downgrade to NTLMSSP\n"));
733 response = spnego_gen_auth_response(NULL,
734 NT_STATUS_MORE_PROCESSING_REQUIRED,
736 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
737 data_blob_free(&response);
740 /****************************************************************************
741 Reply to a session setup spnego negotiate packet.
742 ****************************************************************************/
744 static void reply_spnego_negotiate(struct smb_request *req,
747 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
751 char *kerb_mech = NULL;
754 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
755 if (!NT_STATUS_IS_OK(status)) {
756 /* Kill the intermediate vuid */
757 invalidate_vuid(vuid);
758 reply_nterror(req, nt_status_squash(status));
762 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
763 (unsigned long)secblob.length));
766 if (kerb_mech && ((lp_security()==SEC_ADS) ||
767 USE_KERBEROS_KEYTAB) ) {
768 bool destroy_vuid = True;
769 reply_spnego_kerberos(req, &secblob, kerb_mech,
770 vuid, &destroy_vuid);
771 data_blob_free(&secblob);
773 /* Kill the intermediate vuid */
774 invalidate_vuid(vuid);
776 SAFE_FREE(kerb_mech);
781 if (*auth_ntlmssp_state) {
782 auth_ntlmssp_end(auth_ntlmssp_state);
786 data_blob_free(&secblob);
787 /* The mechtoken is a krb5 ticket, but
788 * we need to fall back to NTLM. */
789 reply_spnego_downgrade_to_ntlmssp(req, vuid);
790 SAFE_FREE(kerb_mech);
794 status = auth_ntlmssp_start(auth_ntlmssp_state);
795 if (!NT_STATUS_IS_OK(status)) {
796 /* Kill the intermediate vuid */
797 invalidate_vuid(vuid);
798 reply_nterror(req, nt_status_squash(status));
802 status = auth_ntlmssp_update(*auth_ntlmssp_state,
805 data_blob_free(&secblob);
807 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
808 &chal, status, OID_NTLMSSP, true);
810 data_blob_free(&chal);
812 /* already replied */
816 /****************************************************************************
817 Reply to a session setup spnego auth packet.
818 ****************************************************************************/
820 static void reply_spnego_auth(struct smb_request *req,
823 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
825 DATA_BLOB auth = data_blob_null;
826 DATA_BLOB auth_reply = data_blob_null;
827 DATA_BLOB secblob = data_blob_null;
828 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
830 if (!spnego_parse_auth(blob1, &auth)) {
832 file_save("auth.dat", blob1.data, blob1.length);
834 /* Kill the intermediate vuid */
835 invalidate_vuid(vuid);
837 reply_nterror(req, nt_status_squash(
838 NT_STATUS_LOGON_FAILURE));
842 if (auth.data[0] == ASN1_APPLICATION(0)) {
843 /* Might be a second negTokenTarg packet */
844 char *kerb_mech = NULL;
846 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
848 if (!NT_STATUS_IS_OK(status)) {
849 /* Kill the intermediate vuid */
850 invalidate_vuid(vuid);
851 reply_nterror(req, nt_status_squash(status));
855 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
856 (unsigned long)secblob.length));
858 if (kerb_mech && ((lp_security()==SEC_ADS) ||
859 USE_KERBEROS_KEYTAB)) {
860 bool destroy_vuid = True;
861 reply_spnego_kerberos(req, &secblob, kerb_mech,
862 vuid, &destroy_vuid);
863 data_blob_free(&secblob);
864 data_blob_free(&auth);
866 /* Kill the intermediate vuid */
867 invalidate_vuid(vuid);
869 SAFE_FREE(kerb_mech);
873 /* Can't blunder into NTLMSSP auth if we have
877 /* Kill the intermediate vuid */
878 invalidate_vuid(vuid);
879 DEBUG(3,("reply_spnego_auth: network "
880 "misconfiguration, client sent us a "
881 "krb5 ticket and kerberos security "
883 reply_nterror(req, nt_status_squash(
884 NT_STATUS_LOGON_FAILURE));
885 SAFE_FREE(kerb_mech);
889 /* If we get here it wasn't a negTokenTarg auth packet. */
890 data_blob_free(&secblob);
892 if (!*auth_ntlmssp_state) {
893 status = auth_ntlmssp_start(auth_ntlmssp_state);
894 if (!NT_STATUS_IS_OK(status)) {
895 /* Kill the intermediate vuid */
896 invalidate_vuid(vuid);
897 reply_nterror(req, nt_status_squash(status));
902 status = auth_ntlmssp_update(*auth_ntlmssp_state,
905 data_blob_free(&auth);
907 /* Don't send the mechid as we've already sent this (RFC4178). */
909 reply_spnego_ntlmssp(req, vuid,
911 &auth_reply, status, NULL, true);
913 data_blob_free(&auth_reply);
915 /* and tell smbd that we have already replied to this packet */
919 /****************************************************************************
920 Delete an entry on the list.
921 ****************************************************************************/
923 static void delete_partial_auth(struct pending_auth_data *pad)
928 DLIST_REMOVE(pd_list, pad);
929 data_blob_free(&pad->partial_data);
933 /****************************************************************************
934 Search for a partial SPNEGO auth fragment matching an smbpid.
935 ****************************************************************************/
937 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
939 struct pending_auth_data *pad;
941 for (pad = pd_list; pad; pad = pad->next) {
942 if (pad->smbpid == smbpid) {
949 /****************************************************************************
950 Check the size of an SPNEGO blob. If we need more return
951 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
952 the blob to be more than 64k.
953 ****************************************************************************/
955 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
958 struct pending_auth_data *pad = NULL;
960 size_t needed_len = 0;
962 pad = get_pending_auth_data(smbpid);
964 /* Ensure we have some data. */
965 if (pblob->length == 0) {
966 /* Caller can cope. */
967 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
968 delete_partial_auth(pad);
972 /* Were we waiting for more data ? */
975 size_t copy_len = MIN(65536, pblob->length);
977 /* Integer wrap paranoia.... */
979 if (pad->partial_data.length + copy_len <
980 pad->partial_data.length ||
981 pad->partial_data.length + copy_len < copy_len) {
983 DEBUG(2,("check_spnego_blob_complete: integer wrap "
984 "pad->partial_data.length = %u, "
986 (unsigned int)pad->partial_data.length,
987 (unsigned int)copy_len ));
989 delete_partial_auth(pad);
990 return NT_STATUS_INVALID_PARAMETER;
993 DEBUG(10,("check_spnego_blob_complete: "
994 "pad->partial_data.length = %u, "
995 "pad->needed_len = %u, "
997 "pblob->length = %u,\n",
998 (unsigned int)pad->partial_data.length,
999 (unsigned int)pad->needed_len,
1000 (unsigned int)copy_len,
1001 (unsigned int)pblob->length ));
1003 tmp_blob = data_blob(NULL,
1004 pad->partial_data.length + copy_len);
1006 /* Concatenate the two (up to copy_len) bytes. */
1007 memcpy(tmp_blob.data,
1008 pad->partial_data.data,
1009 pad->partial_data.length);
1010 memcpy(tmp_blob.data + pad->partial_data.length,
1014 /* Replace the partial data. */
1015 data_blob_free(&pad->partial_data);
1016 pad->partial_data = tmp_blob;
1017 ZERO_STRUCT(tmp_blob);
1020 if (pblob->length >= pad->needed_len) {
1021 /* Yes, replace pblob. */
1022 data_blob_free(pblob);
1023 *pblob = pad->partial_data;
1024 ZERO_STRUCT(pad->partial_data);
1025 delete_partial_auth(pad);
1026 return NT_STATUS_OK;
1029 /* Still need more data. */
1030 pad->needed_len -= copy_len;
1031 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1034 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1035 (pblob->data[0] != ASN1_CONTEXT(1))) {
1036 /* Not something we can determine the
1039 return NT_STATUS_OK;
1042 /* This is a new SPNEGO sessionsetup - see if
1043 * the data given in this blob is enough.
1046 data = asn1_init(NULL);
1048 return NT_STATUS_NO_MEMORY;
1051 asn1_load(data, *pblob);
1052 asn1_start_tag(data, pblob->data[0]);
1053 if (data->has_error || data->nesting == NULL) {
1055 /* Let caller catch. */
1056 return NT_STATUS_OK;
1059 /* Integer wrap paranoia.... */
1061 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1062 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1064 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1065 "data.nesting->taglen = %u, "
1066 "data.nesting->start = %u\n",
1067 (unsigned int)data->nesting->taglen,
1068 (unsigned int)data->nesting->start ));
1071 return NT_STATUS_INVALID_PARAMETER;
1074 /* Total length of the needed asn1 is the tag length
1075 * plus the current offset. */
1077 needed_len = data->nesting->taglen + data->nesting->start;
1080 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1081 "pblob->length = %u\n",
1082 (unsigned int)needed_len,
1083 (unsigned int)pblob->length ));
1085 if (needed_len <= pblob->length) {
1086 /* Nothing to do - blob is complete. */
1087 return NT_STATUS_OK;
1090 /* Refuse the blob if it's bigger than 64k. */
1091 if (needed_len > 65536) {
1092 DEBUG(2,("check_spnego_blob_complete: needed_len "
1094 (unsigned int)needed_len ));
1095 return NT_STATUS_INVALID_PARAMETER;
1098 /* We must store this blob until complete. */
1099 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1100 return NT_STATUS_NO_MEMORY;
1102 pad->needed_len = needed_len - pblob->length;
1103 pad->partial_data = data_blob(pblob->data, pblob->length);
1104 if (pad->partial_data.data == NULL) {
1106 return NT_STATUS_NO_MEMORY;
1108 pad->smbpid = smbpid;
1110 DLIST_ADD(pd_list, pad);
1112 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1115 /****************************************************************************
1116 Reply to a session setup command.
1117 conn POINTER CAN BE NULL HERE !
1118 ****************************************************************************/
1120 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1126 const char *native_os;
1127 const char *native_lanman;
1128 const char *primary_domain;
1130 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1131 enum remote_arch_types ra_type = get_remote_arch();
1132 int vuid = req->vuid;
1133 user_struct *vuser = NULL;
1134 NTSTATUS status = NT_STATUS_OK;
1135 uint16 smbpid = req->smbpid;
1137 DEBUG(3,("Doing spnego session setup\n"));
1139 if (global_client_caps == 0) {
1140 global_client_caps = IVAL(req->vwv+10, 0);
1142 if (!(global_client_caps & CAP_STATUS32)) {
1143 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1150 if (data_blob_len == 0) {
1151 /* an invalid request */
1152 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1156 bufrem = smbreq_bufrem(req, p);
1157 /* pull the spnego blob */
1158 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1161 file_save("negotiate.dat", blob1.data, blob1.length);
1164 p2 = (char *)req->buf + data_blob_len;
1166 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1168 native_os = tmp ? tmp : "";
1170 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1172 native_lanman = tmp ? tmp : "";
1174 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1176 primary_domain = tmp ? tmp : "";
1178 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1179 native_os, native_lanman, primary_domain));
1181 if ( ra_type == RA_WIN2K ) {
1182 /* Vista sets neither the OS or lanman strings */
1184 if ( !strlen(native_os) && !strlen(native_lanman) )
1185 set_remote_arch(RA_VISTA);
1187 /* Windows 2003 doesn't set the native lanman string,
1188 but does set primary domain which is a bug I think */
1190 if ( !strlen(native_lanman) ) {
1191 ra_lanman_string( primary_domain );
1193 ra_lanman_string( native_lanman );
1197 /* Did we get a valid vuid ? */
1198 if (!is_partial_auth_vuid(vuid)) {
1199 /* No, then try and see if this is an intermediate sessionsetup
1200 * for a large SPNEGO packet. */
1201 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1203 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1204 "pending vuid %u\n",
1205 (unsigned int)pad->vuid ));
1210 /* Do we have a valid vuid now ? */
1211 if (!is_partial_auth_vuid(vuid)) {
1212 /* No, start a new authentication setup. */
1213 vuid = register_initial_vuid();
1214 if (vuid == UID_FIELD_INVALID) {
1215 data_blob_free(&blob1);
1216 reply_nterror(req, nt_status_squash(
1217 NT_STATUS_INVALID_PARAMETER));
1222 vuser = get_partial_auth_user_struct(vuid);
1223 /* This MUST be valid. */
1225 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1228 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1229 * sessionsetup requests as the Windows limit on the security blob
1230 * field is 4k. Bug #4400. JRA.
1233 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 if (!NT_STATUS_EQUAL(status,
1236 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1237 /* Real error - kill the intermediate vuid */
1238 invalidate_vuid(vuid);
1240 data_blob_free(&blob1);
1241 reply_nterror(req, nt_status_squash(status));
1245 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1247 /* its a negTokenTarg packet */
1249 reply_spnego_negotiate(req, vuid, blob1,
1250 &vuser->auth_ntlmssp_state);
1251 data_blob_free(&blob1);
1255 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1257 /* its a auth packet */
1259 reply_spnego_auth(req, vuid, blob1,
1260 &vuser->auth_ntlmssp_state);
1261 data_blob_free(&blob1);
1265 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1268 if (!vuser->auth_ntlmssp_state) {
1269 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 /* Kill the intermediate vuid */
1272 invalidate_vuid(vuid);
1273 data_blob_free(&blob1);
1274 reply_nterror(req, nt_status_squash(status));
1279 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1282 data_blob_free(&blob1);
1284 reply_spnego_ntlmssp(req, vuid,
1285 &vuser->auth_ntlmssp_state,
1286 &chal, status, OID_NTLMSSP, false);
1287 data_blob_free(&chal);
1291 /* what sort of packet is this? */
1292 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1294 data_blob_free(&blob1);
1296 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1299 /****************************************************************************
1300 On new VC == 0, shutdown *all* old connections and users.
1301 It seems that only NT4.x does this. At W2K and above (XP etc.).
1302 a new session setup with VC==0 is ignored.
1303 ****************************************************************************/
1305 static int shutdown_other_smbds(struct db_record *rec,
1306 const struct connections_key *key,
1307 const struct connections_data *crec,
1310 const char *ip = (const char *)private_data;
1312 if (!process_exists(crec->pid)) {
1316 if (procid_is_me(&crec->pid)) {
1320 if (strcmp(ip, crec->addr) != 0) {
1324 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1325 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1327 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1332 static void setup_new_vc_session(void)
1334 char addr[INET6_ADDRSTRLEN];
1336 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1337 "compatible we would close all old resources.\n"));
1340 invalidate_all_vuids();
1342 if (lp_reset_on_zero_vc()) {
1343 connections_forall(shutdown_other_smbds,
1344 CONST_DISCARD(void *,
1345 client_addr(get_client_fd(),addr,sizeof(addr))));
1349 /****************************************************************************
1350 Reply to a session setup command.
1351 ****************************************************************************/
1353 void reply_sesssetup_and_X(struct smb_request *req)
1359 DATA_BLOB plaintext_password;
1362 fstring sub_user; /* Sainitised username for substituion */
1364 const char *native_os;
1365 const char *native_lanman;
1366 const char *primary_domain;
1367 auth_usersupplied_info *user_info = NULL;
1368 auth_serversupplied_info *server_info = NULL;
1369 uint16 smb_flag2 = req->flags2;
1373 bool doencrypt = global_encrypted_passwords_negotiated;
1375 START_PROFILE(SMBsesssetupX);
1377 ZERO_STRUCT(lm_resp);
1378 ZERO_STRUCT(nt_resp);
1379 ZERO_STRUCT(plaintext_password);
1381 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1383 /* a SPNEGO session setup has 12 command words, whereas a normal
1384 NT1 session setup has 13. See the cifs spec. */
1385 if (req->wct == 12 &&
1386 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1388 if (!global_spnego_negotiated) {
1389 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1390 "at SPNEGO session setup when it was not "
1392 reply_nterror(req, nt_status_squash(
1393 NT_STATUS_LOGON_FAILURE));
1394 END_PROFILE(SMBsesssetupX);
1398 if (SVAL(req->vwv+4, 0) == 0) {
1399 setup_new_vc_session();
1402 reply_sesssetup_and_X_spnego(req);
1403 END_PROFILE(SMBsesssetupX);
1407 smb_bufsize = SVAL(req->vwv+2, 0);
1409 if (Protocol < PROTOCOL_NT1) {
1410 uint16 passlen1 = SVAL(req->vwv+7, 0);
1412 /* Never do NT status codes with protocols before NT1 as we
1413 * don't get client caps. */
1414 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1416 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1417 reply_nterror(req, nt_status_squash(
1418 NT_STATUS_INVALID_PARAMETER));
1419 END_PROFILE(SMBsesssetupX);
1424 lm_resp = data_blob(req->buf, passlen1);
1426 plaintext_password = data_blob(req->buf, passlen1+1);
1427 /* Ensure null termination */
1428 plaintext_password.data[passlen1] = 0;
1431 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1432 req->buf + passlen1, STR_TERMINATE);
1433 user = tmp ? tmp : "";
1438 uint16 passlen1 = SVAL(req->vwv+7, 0);
1439 uint16 passlen2 = SVAL(req->vwv+8, 0);
1440 enum remote_arch_types ra_type = get_remote_arch();
1441 const uint8_t *p = req->buf;
1442 const uint8_t *save_p = req->buf;
1446 if(global_client_caps == 0) {
1447 global_client_caps = IVAL(req->vwv+11, 0);
1449 if (!(global_client_caps & CAP_STATUS32)) {
1450 remove_from_common_flags2(
1451 FLAGS2_32_BIT_ERROR_CODES);
1454 /* client_caps is used as final determination if
1455 * client is NT or Win95. This is needed to return
1456 * the correct error codes in some circumstances.
1459 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1460 ra_type == RA_WIN95) {
1461 if(!(global_client_caps & (CAP_NT_SMBS|
1463 set_remote_arch( RA_WIN95);
1469 /* both Win95 and WinNT stuff up the password
1470 * lengths for non-encrypting systems. Uggh.
1472 if passlen1==24 its a win95 system, and its setting
1473 the password length incorrectly. Luckily it still
1474 works with the default code because Win95 will null
1475 terminate the password anyway
1477 if passlen1>0 and passlen2>0 then maybe its a NT box
1478 and its setting passlen2 to some random value which
1479 really stuffs things up. we need to fix that one. */
1481 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1487 /* check for nasty tricks */
1488 if (passlen1 > MAX_PASS_LEN
1489 || passlen1 > smbreq_bufrem(req, p)) {
1490 reply_nterror(req, nt_status_squash(
1491 NT_STATUS_INVALID_PARAMETER));
1492 END_PROFILE(SMBsesssetupX);
1496 if (passlen2 > MAX_PASS_LEN
1497 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1498 reply_nterror(req, nt_status_squash(
1499 NT_STATUS_INVALID_PARAMETER));
1500 END_PROFILE(SMBsesssetupX);
1504 /* Save the lanman2 password and the NT md4 password. */
1506 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1511 lm_resp = data_blob(p, passlen1);
1512 nt_resp = data_blob(p+passlen1, passlen2);
1513 } else if (lp_security() != SEC_SHARE) {
1515 * In share level we should ignore any passwords, so
1516 * only read them if we're not.
1519 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1521 if (unic && (passlen2 == 0) && passlen1) {
1522 /* Only a ascii plaintext password was sent. */
1523 (void)srvstr_pull_talloc(talloc_tos(),
1529 STR_TERMINATE|STR_ASCII);
1531 (void)srvstr_pull_talloc(talloc_tos(),
1536 unic ? passlen2 : passlen1,
1540 reply_nterror(req, nt_status_squash(
1541 NT_STATUS_INVALID_PARAMETER));
1542 END_PROFILE(SMBsesssetupX);
1545 plaintext_password = data_blob(pass, strlen(pass)+1);
1548 p += passlen1 + passlen2;
1550 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1552 user = tmp ? tmp : "";
1554 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1556 domain = tmp ? tmp : "";
1558 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1560 native_os = tmp ? tmp : "";
1562 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1564 native_lanman = tmp ? tmp : "";
1566 /* not documented or decoded by Ethereal but there is one more
1567 * string in the extra bytes which is the same as the
1568 * PrimaryDomain when using extended security. Windows NT 4
1569 * and 2003 use this string to store the native lanman string.
1570 * Windows 9x does not include a string here at all so we have
1571 * to check if we have any extra bytes left */
1573 byte_count = SVAL(req->vwv+13, 0);
1574 if ( PTR_DIFF(p, save_p) < byte_count) {
1575 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1577 primary_domain = tmp ? tmp : "";
1579 primary_domain = talloc_strdup(talloc_tos(), "null");
1582 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1583 "PrimaryDomain=[%s]\n",
1584 domain, native_os, native_lanman, primary_domain));
1586 if ( ra_type == RA_WIN2K ) {
1587 if ( strlen(native_lanman) == 0 )
1588 ra_lanman_string( primary_domain );
1590 ra_lanman_string( native_lanman );
1595 if (SVAL(req->vwv+4, 0) == 0) {
1596 setup_new_vc_session();
1599 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1600 domain, user, get_remote_machine_name()));
1603 if (global_spnego_negotiated) {
1605 /* This has to be here, because this is a perfectly
1606 * valid behaviour for guest logons :-( */
1608 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1609 "at 'normal' session setup after "
1610 "negotiating spnego.\n"));
1611 reply_nterror(req, nt_status_squash(
1612 NT_STATUS_LOGON_FAILURE));
1613 END_PROFILE(SMBsesssetupX);
1616 fstrcpy(sub_user, user);
1618 fstrcpy(sub_user, lp_guestaccount());
1621 sub_set_smb_name(sub_user);
1623 reload_services(True);
1625 if (lp_security() == SEC_SHARE) {
1626 /* In share level we should ignore any passwords */
1628 data_blob_free(&lm_resp);
1629 data_blob_free(&nt_resp);
1630 data_blob_clear_free(&plaintext_password);
1632 map_username(sub_user);
1633 add_session_user(sub_user);
1634 add_session_workgroup(domain);
1635 /* Then force it to null for the benfit of the code below */
1641 nt_status = check_guest_password(&server_info);
1643 } else if (doencrypt) {
1644 if (!negprot_global_auth_context) {
1645 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1646 "session setup without negprot denied!\n"));
1647 reply_nterror(req, nt_status_squash(
1648 NT_STATUS_LOGON_FAILURE));
1649 END_PROFILE(SMBsesssetupX);
1652 nt_status = make_user_info_for_reply_enc(&user_info, user,
1655 if (NT_STATUS_IS_OK(nt_status)) {
1656 nt_status = negprot_global_auth_context->check_ntlm_password(
1657 negprot_global_auth_context,
1662 struct auth_context *plaintext_auth_context = NULL;
1664 nt_status = make_auth_context_subsystem(
1665 &plaintext_auth_context);
1667 if (NT_STATUS_IS_OK(nt_status)) {
1670 plaintext_auth_context->get_ntlm_challenge(
1671 plaintext_auth_context, chal);
1673 if (!make_user_info_for_reply(&user_info,
1675 plaintext_password)) {
1676 nt_status = NT_STATUS_NO_MEMORY;
1679 if (NT_STATUS_IS_OK(nt_status)) {
1680 nt_status = plaintext_auth_context->check_ntlm_password(
1681 plaintext_auth_context,
1685 (plaintext_auth_context->free)(
1686 &plaintext_auth_context);
1691 free_user_info(&user_info);
1693 if (!NT_STATUS_IS_OK(nt_status)) {
1694 nt_status = do_map_to_guest(nt_status, &server_info,
1698 if (!NT_STATUS_IS_OK(nt_status)) {
1699 data_blob_free(&nt_resp);
1700 data_blob_free(&lm_resp);
1701 data_blob_clear_free(&plaintext_password);
1702 reply_nterror(req, nt_status_squash(nt_status));
1703 END_PROFILE(SMBsesssetupX);
1707 /* Ensure we can't possible take a code path leading to a
1710 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1711 END_PROFILE(SMBsesssetupX);
1715 if (!server_info->ptok) {
1716 nt_status = create_local_token(server_info);
1718 if (!NT_STATUS_IS_OK(nt_status)) {
1719 DEBUG(10, ("create_local_token failed: %s\n",
1720 nt_errstr(nt_status)));
1721 data_blob_free(&nt_resp);
1722 data_blob_free(&lm_resp);
1723 data_blob_clear_free(&plaintext_password);
1724 reply_nterror(req, nt_status_squash(nt_status));
1725 END_PROFILE(SMBsesssetupX);
1730 data_blob_clear_free(&plaintext_password);
1732 /* it's ok - setup a reply */
1733 reply_outbuf(req, 3, 0);
1734 if (Protocol >= PROTOCOL_NT1) {
1735 push_signature(&req->outbuf);
1736 /* perhaps grab OS version here?? */
1739 if (server_info->guest) {
1740 SSVAL(req->outbuf,smb_vwv2,1);
1743 /* register the name and uid as being validated, so further connections
1744 to a uid can get through without a password, on the same VC */
1746 if (lp_security() == SEC_SHARE) {
1747 sess_vuid = UID_FIELD_INVALID;
1748 TALLOC_FREE(server_info);
1750 /* Ignore the initial vuid. */
1751 sess_vuid = register_initial_vuid();
1752 if (sess_vuid == UID_FIELD_INVALID) {
1753 data_blob_free(&nt_resp);
1754 data_blob_free(&lm_resp);
1755 reply_nterror(req, nt_status_squash(
1756 NT_STATUS_LOGON_FAILURE));
1757 END_PROFILE(SMBsesssetupX);
1760 /* register_existing_vuid keeps the server info */
1761 sess_vuid = register_existing_vuid(sess_vuid,
1763 nt_resp.data ? nt_resp : lm_resp,
1765 if (sess_vuid == UID_FIELD_INVALID) {
1766 data_blob_free(&nt_resp);
1767 data_blob_free(&lm_resp);
1768 reply_nterror(req, nt_status_squash(
1769 NT_STATUS_LOGON_FAILURE));
1770 END_PROFILE(SMBsesssetupX);
1774 /* current_user_info is changed on new vuid */
1775 reload_services( True );
1778 data_blob_free(&nt_resp);
1779 data_blob_free(&lm_resp);
1781 SSVAL(req->outbuf,smb_uid,sess_vuid);
1782 SSVAL(req->inbuf,smb_uid,sess_vuid);
1784 if (!done_sesssetup)
1785 max_send = MIN(max_send,smb_bufsize);
1787 done_sesssetup = True;
1789 END_PROFILE(SMBsesssetupX);