2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 extern struct auth_context *negprot_global_auth_context;
28 extern bool global_encrypted_passwords_negotiated;
29 extern bool global_spnego_negotiated;
30 extern enum protocol_types Protocol;
33 uint32 global_client_caps = 0;
36 on a logon error possibly map the error to success if "map to guest"
39 static NTSTATUS do_map_to_guest(NTSTATUS status,
40 auth_serversupplied_info **server_info,
41 const char *user, const char *domain)
43 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
44 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
45 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
46 DEBUG(3,("No such user %s [%s] - using guest account\n",
48 status = make_server_info_guest(NULL, server_info);
52 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
53 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
54 DEBUG(3,("Registered username %s for guest access\n",
56 status = make_server_info_guest(NULL, server_info);
63 /****************************************************************************
64 Add the standard 'Samba' signature to the end of the session setup.
65 ****************************************************************************/
67 static int push_signature(uint8 **outbuf)
74 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
76 if (tmp == -1) return -1;
79 if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
80 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
84 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
87 if (tmp == -1) return -1;
90 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
92 if (tmp == -1) return -1;
98 /****************************************************************************
99 Start the signing engine if needed. Don't fail signing here.
100 ****************************************************************************/
102 static void sessionsetup_start_signing_engine(
103 const auth_serversupplied_info *server_info,
106 if (!server_info->guest && !srv_signing_started()) {
107 /* We need to start the signing engine
108 * here but a W2K client sends the old
109 * "BSRSPYL " signature instead of the
110 * correct one. Subsequent packets will
113 srv_check_sign_mac((char *)inbuf, False);
117 /****************************************************************************
118 Send a security blob via a session setup reply.
119 ****************************************************************************/
121 static void reply_sesssetup_blob(struct smb_request *req,
125 if (!NT_STATUS_IS_OK(nt_status) &&
126 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
127 reply_nterror(req, nt_status_squash(nt_status));
131 nt_status = nt_status_squash(nt_status);
132 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
133 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
134 SSVAL(req->outbuf, smb_vwv3, blob.length);
136 if ((message_push_blob(&req->outbuf, blob) == -1)
137 || (push_signature(&req->outbuf) == -1)) {
138 reply_nterror(req, NT_STATUS_NO_MEMORY);
142 /****************************************************************************
143 Do a 'guest' logon, getting back the
144 ****************************************************************************/
146 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
148 struct auth_context *auth_context;
149 auth_usersupplied_info *user_info = NULL;
152 unsigned char chal[8];
156 DEBUG(3,("Got anonymous request\n"));
158 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
163 if (!make_user_info_guest(&user_info)) {
164 (auth_context->free)(&auth_context);
165 return NT_STATUS_NO_MEMORY;
168 nt_status = auth_context->check_ntlm_password(auth_context,
171 (auth_context->free)(&auth_context);
172 free_user_info(&user_info);
180 /* Experiment that failed. See "only happens with a KDC" comment below. */
181 /****************************************************************************
182 Cerate a clock skew error blob for a Windows client.
183 ****************************************************************************/
185 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
187 krb5_context context = NULL;
188 krb5_error_code kerr = 0;
190 krb5_principal host_princ = NULL;
191 char *host_princ_s = NULL;
194 *pblob_out = data_blob_null;
196 initialize_krb5_error_table();
197 kerr = krb5_init_context(&context);
201 /* Create server principal. */
202 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
206 strlower_m(host_princ_s);
208 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
210 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
211 "for name %s: Error %s\n",
212 host_princ_s, error_message(kerr) ));
216 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
219 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
220 "failed: Error %s\n",
221 error_message(kerr) ));
225 *pblob_out = data_blob(reply.data, reply.length);
226 kerberos_free_data_contents(context,&reply);
232 SAFE_FREE(host_princ_s);
235 krb5_free_principal(context, host_princ);
237 krb5_free_context(context);
242 /****************************************************************************
243 Reply to a session setup spnego negotiate packet for kerberos.
244 ****************************************************************************/
246 static void reply_spnego_kerberos(struct smb_request *req,
250 bool *p_invalidate_vuid)
254 char *client, *p, *domain;
255 fstring netbios_domain_name;
258 int sess_vuid = req->vuid;
259 NTSTATUS ret = NT_STATUS_OK;
260 struct PAC_DATA *pac_data = NULL;
261 DATA_BLOB ap_rep, ap_rep_wrapped, response;
262 auth_serversupplied_info *server_info = NULL;
263 DATA_BLOB session_key = data_blob_null;
265 DATA_BLOB nullblob = data_blob_null;
266 fstring real_username;
267 bool map_domainuser_to_guest = False;
268 bool username_was_mapped;
269 struct PAC_LOGON_INFO *logon_info = NULL;
273 ZERO_STRUCT(ap_rep_wrapped);
274 ZERO_STRUCT(response);
276 /* Normally we will always invalidate the intermediate vuid. */
277 *p_invalidate_vuid = True;
279 mem_ctx = talloc_init("reply_spnego_kerberos");
280 if (mem_ctx == NULL) {
281 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
285 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
286 talloc_destroy(mem_ctx);
287 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
291 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
292 &client, &pac_data, &ap_rep,
295 data_blob_free(&ticket);
297 if (!NT_STATUS_IS_OK(ret)) {
299 /* Experiment that failed.
300 * See "only happens with a KDC" comment below. */
302 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
305 * Windows in this case returns
306 * NT_STATUS_MORE_PROCESSING_REQUIRED
307 * with a negTokenTarg blob containing an krb5_error
308 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
309 * The client then fixes its clock and continues rather
310 * than giving an error. JRA.
311 * -- Looks like this only happens with a KDC. JRA.
314 bool ok = make_krb5_skew_error(&ap_rep);
316 talloc_destroy(mem_ctx);
317 return ERROR_NT(nt_status_squash(
318 NT_STATUS_LOGON_FAILURE));
320 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
322 response = spnego_gen_auth_response(&ap_rep_wrapped,
323 ret, OID_KERBEROS5_OLD);
324 reply_sesssetup_blob(conn, inbuf, outbuf, response,
325 NT_STATUS_MORE_PROCESSING_REQUIRED);
328 * In this one case we don't invalidate the
329 * intermediate vuid as we're expecting the client
330 * to re-use it for the next sessionsetupX packet. JRA.
333 *p_invalidate_vuid = False;
335 data_blob_free(&ap_rep);
336 data_blob_free(&ap_rep_wrapped);
337 data_blob_free(&response);
338 talloc_destroy(mem_ctx);
339 return -1; /* already replied */
342 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
343 ret = NT_STATUS_LOGON_FAILURE;
346 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
348 talloc_destroy(mem_ctx);
349 reply_nterror(req, nt_status_squash(ret));
353 DEBUG(3,("Ticket name is [%s]\n", client));
355 p = strchr_m(client, '@');
357 DEBUG(3,("Doesn't look like a valid principal\n"));
358 data_blob_free(&ap_rep);
359 data_blob_free(&session_key);
361 talloc_destroy(mem_ctx);
362 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
368 /* save the PAC data if we have it */
371 logon_info = get_logon_info_from_pac(pac_data);
373 netsamlogon_cache_store( client, &logon_info->info3 );
377 if (!strequal(p+1, lp_realm())) {
378 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
379 if (!lp_allow_trusted_domains()) {
380 data_blob_free(&ap_rep);
381 data_blob_free(&session_key);
383 talloc_destroy(mem_ctx);
384 reply_nterror(req, nt_status_squash(
385 NT_STATUS_LOGON_FAILURE));
390 /* this gives a fully qualified user name (ie. with full realm).
391 that leads to very long usernames, but what else can we do? */
395 if (logon_info && logon_info->info3.base.domain.string) {
396 fstrcpy(netbios_domain_name,
397 logon_info->info3.base.domain.string);
398 domain = netbios_domain_name;
399 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
403 /* If we have winbind running, we can (and must) shorten the
404 username by using the short netbios name. Otherwise we will
405 have inconsistent user names. With Kerberos, we get the
406 fully qualified realm, with ntlmssp we get the short
407 name. And even w2k3 does use ntlmssp if you for example
408 connect to an ip address. */
411 struct wbcDomainInfo *info = NULL;
413 DEBUG(10, ("Mapping [%s] to short name\n", domain));
415 wbc_status = wbcDomainInfo(domain, &info);
417 if (WBC_ERROR_IS_OK(wbc_status)) {
419 fstrcpy(netbios_domain_name,
423 domain = netbios_domain_name;
424 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
426 DEBUG(3, ("Could not find short name: %s\n",
427 wbcErrorString(wbc_status)));
431 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
433 /* lookup the passwd struct, create a new user if necessary */
435 username_was_mapped = map_username( user );
437 pw = smb_getpwnam( mem_ctx, user, real_username, True );
440 /* if a real user check pam account restrictions */
441 /* only really perfomed if "obey pam restriction" is true */
442 /* do this before an eventual mapping to guest occurs */
443 ret = smb_pam_accountcheck(pw->pw_name);
444 if ( !NT_STATUS_IS_OK(ret)) {
445 DEBUG(1,("PAM account restriction "
446 "prevents user login\n"));
447 data_blob_free(&ap_rep);
448 data_blob_free(&session_key);
449 TALLOC_FREE(mem_ctx);
450 reply_nterror(req, nt_status_squash(ret));
457 /* this was originally the behavior of Samba 2.2, if a user
458 did not have a local uid but has been authenticated, then
459 map them to a guest account */
461 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
462 map_domainuser_to_guest = True;
463 fstrcpy(user,lp_guestaccount());
464 pw = smb_getpwnam( mem_ctx, user, real_username, True );
467 /* extra sanity check that the guest account is valid */
470 DEBUG(1,("Username %s is invalid on this system\n",
473 data_blob_free(&ap_rep);
474 data_blob_free(&session_key);
475 TALLOC_FREE(mem_ctx);
476 reply_nterror(req, nt_status_squash(
477 NT_STATUS_LOGON_FAILURE));
482 /* setup the string used by %U */
484 sub_set_smb_name( real_username );
485 reload_services(True);
487 if ( map_domainuser_to_guest ) {
488 make_server_info_guest(NULL, &server_info);
489 } else if (logon_info) {
490 /* pass the unmapped username here since map_username()
491 will be called again from inside make_server_info_info3() */
493 ret = make_server_info_info3(mem_ctx, client, domain,
494 &server_info, &logon_info->info3);
495 if ( !NT_STATUS_IS_OK(ret) ) {
496 DEBUG(1,("make_server_info_info3 failed: %s!\n",
499 data_blob_free(&ap_rep);
500 data_blob_free(&session_key);
501 TALLOC_FREE(mem_ctx);
502 reply_nterror(req, nt_status_squash(ret));
507 ret = make_server_info_pw(&server_info, real_username, pw);
509 if ( !NT_STATUS_IS_OK(ret) ) {
510 DEBUG(1,("make_server_info_pw failed: %s!\n",
513 data_blob_free(&ap_rep);
514 data_blob_free(&session_key);
515 TALLOC_FREE(mem_ctx);
516 reply_nterror(req, nt_status_squash(ret));
520 /* make_server_info_pw does not set the domain. Without this
521 * we end up with the local netbios name in substitutions for
524 if (server_info->sam_account != NULL) {
525 pdb_set_domain(server_info->sam_account,
530 server_info->nss_token |= username_was_mapped;
532 /* we need to build the token for the user. make_server_info_guest()
535 if ( !server_info->ptok ) {
536 ret = create_local_token( server_info );
537 if ( !NT_STATUS_IS_OK(ret) ) {
538 DEBUG(10,("failed to create local token: %s\n",
541 data_blob_free(&ap_rep);
542 data_blob_free(&session_key);
543 TALLOC_FREE( mem_ctx );
544 TALLOC_FREE( server_info );
545 reply_nterror(req, nt_status_squash(ret));
550 /* register_existing_vuid keeps the server info */
551 /* register_existing_vuid takes ownership of session_key on success,
552 * no need to free after this on success. A better interface would copy
555 if (!is_partial_auth_vuid(sess_vuid)) {
556 sess_vuid = register_initial_vuid();
559 data_blob_free(&server_info->user_session_key);
560 server_info->user_session_key = session_key;
561 session_key = data_blob_null;
563 sess_vuid = register_existing_vuid(sess_vuid,
570 reply_outbuf(req, 4, 0);
571 SSVAL(req->outbuf,smb_uid,sess_vuid);
573 if (sess_vuid == UID_FIELD_INVALID ) {
574 ret = NT_STATUS_LOGON_FAILURE;
576 /* current_user_info is changed on new vuid */
577 reload_services( True );
579 SSVAL(req->outbuf, smb_vwv3, 0);
581 if (server_info->guest) {
582 SSVAL(req->outbuf,smb_vwv2,1);
585 SSVAL(req->outbuf, smb_uid, sess_vuid);
587 sessionsetup_start_signing_engine(server_info, req->inbuf);
588 /* Successful logon. Keep this vuid. */
589 *p_invalidate_vuid = False;
592 /* wrap that up in a nice GSS-API wrapping */
593 if (NT_STATUS_IS_OK(ret)) {
594 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
597 ap_rep_wrapped = data_blob_null;
599 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
601 reply_sesssetup_blob(req, response, ret);
603 data_blob_free(&ap_rep);
604 data_blob_free(&ap_rep_wrapped);
605 data_blob_free(&response);
606 TALLOC_FREE(mem_ctx);
611 /****************************************************************************
612 Send a session setup reply, wrapped in SPNEGO.
613 Get vuid and check first.
614 End the NTLMSSP exchange context if we are OK/complete fail
615 This should be split into two functions, one to handle each
616 leg of the NTLM auth steps.
617 ***************************************************************************/
619 static void reply_spnego_ntlmssp(struct smb_request *req,
621 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
622 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
627 struct auth_serversupplied_info *server_info = NULL;
629 if (NT_STATUS_IS_OK(nt_status)) {
630 server_info = (*auth_ntlmssp_state)->server_info;
632 nt_status = do_map_to_guest(nt_status,
634 (*auth_ntlmssp_state)->ntlmssp_state->user,
635 (*auth_ntlmssp_state)->ntlmssp_state->domain);
638 reply_outbuf(req, 4, 0);
640 SSVAL(req->outbuf, smb_uid, vuid);
642 if (NT_STATUS_IS_OK(nt_status)) {
643 DATA_BLOB nullblob = data_blob_null;
645 if (!is_partial_auth_vuid(vuid)) {
646 nt_status = NT_STATUS_LOGON_FAILURE;
650 data_blob_free(&server_info->user_session_key);
651 server_info->user_session_key =
654 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
655 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
657 /* register_existing_vuid keeps the server info */
658 if (register_existing_vuid(vuid,
659 server_info, nullblob,
660 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
662 nt_status = NT_STATUS_LOGON_FAILURE;
666 (*auth_ntlmssp_state)->server_info = NULL;
668 /* current_user_info is changed on new vuid */
669 reload_services( True );
671 SSVAL(req->outbuf, smb_vwv3, 0);
673 if (server_info->guest) {
674 SSVAL(req->outbuf,smb_vwv2,1);
677 sessionsetup_start_signing_engine(server_info,
678 (uint8 *)req->inbuf);
684 response = spnego_gen_auth_response(ntlmssp_blob,
687 response = *ntlmssp_blob;
690 reply_sesssetup_blob(req, response, nt_status);
692 data_blob_free(&response);
695 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
696 and the other end, that we are not finished yet. */
698 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
699 /* NB. This is *NOT* an error case. JRA */
700 auth_ntlmssp_end(auth_ntlmssp_state);
701 if (!NT_STATUS_IS_OK(nt_status)) {
702 /* Kill the intermediate vuid */
703 invalidate_vuid(vuid);
708 /****************************************************************************
709 Is this a krb5 mechanism ?
710 ****************************************************************************/
712 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
713 DATA_BLOB *pblob_out,
716 char *OIDs[ASN1_MAX_OIDS];
718 NTSTATUS ret = NT_STATUS_OK;
720 *kerb_mechOID = NULL;
722 /* parse out the OIDs and the first sec blob */
723 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
724 return NT_STATUS_LOGON_FAILURE;
727 /* only look at the first OID for determining the mechToken --
728 according to RFC2478, we should choose the one we want
729 and renegotiate, but i smell a client bug here..
731 Problem observed when connecting to a member (samba box)
732 of an AD domain as a user in a Samba domain. Samba member
733 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
734 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
735 NTLMSSP mechtoken. --jerry */
738 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
739 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
740 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
741 if (*kerb_mechOID == NULL) {
742 ret = NT_STATUS_NO_MEMORY;
747 for (i=0;OIDs[i];i++) {
748 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
749 talloc_free(OIDs[i]);
754 /****************************************************************************
755 Fall back from krb5 to NTLMSSP.
756 ****************************************************************************/
758 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
763 reply_outbuf(req, 4, 0);
764 SSVAL(req->outbuf,smb_uid,vuid);
766 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
767 "but set to downgrade to NTLMSSP\n"));
769 response = spnego_gen_auth_response(NULL,
770 NT_STATUS_MORE_PROCESSING_REQUIRED,
772 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
773 data_blob_free(&response);
776 /****************************************************************************
777 Reply to a session setup spnego negotiate packet.
778 ****************************************************************************/
780 static void reply_spnego_negotiate(struct smb_request *req,
783 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
787 char *kerb_mech = NULL;
790 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
791 if (!NT_STATUS_IS_OK(status)) {
792 /* Kill the intermediate vuid */
793 invalidate_vuid(vuid);
794 reply_nterror(req, nt_status_squash(status));
798 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
799 (unsigned long)secblob.length));
802 if (kerb_mech && ((lp_security()==SEC_ADS) ||
803 lp_use_kerberos_keytab()) ) {
804 bool destroy_vuid = True;
805 reply_spnego_kerberos(req, &secblob, kerb_mech,
806 vuid, &destroy_vuid);
807 data_blob_free(&secblob);
809 /* Kill the intermediate vuid */
810 invalidate_vuid(vuid);
812 SAFE_FREE(kerb_mech);
817 if (*auth_ntlmssp_state) {
818 auth_ntlmssp_end(auth_ntlmssp_state);
822 data_blob_free(&secblob);
823 /* The mechtoken is a krb5 ticket, but
824 * we need to fall back to NTLM. */
825 reply_spnego_downgrade_to_ntlmssp(req, vuid);
826 SAFE_FREE(kerb_mech);
830 status = auth_ntlmssp_start(auth_ntlmssp_state);
831 if (!NT_STATUS_IS_OK(status)) {
832 /* Kill the intermediate vuid */
833 invalidate_vuid(vuid);
834 reply_nterror(req, nt_status_squash(status));
838 status = auth_ntlmssp_update(*auth_ntlmssp_state,
841 data_blob_free(&secblob);
843 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
844 &chal, status, OID_NTLMSSP, true);
846 data_blob_free(&chal);
848 /* already replied */
852 /****************************************************************************
853 Reply to a session setup spnego auth packet.
854 ****************************************************************************/
856 static void reply_spnego_auth(struct smb_request *req,
859 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
861 DATA_BLOB auth = data_blob_null;
862 DATA_BLOB auth_reply = data_blob_null;
863 DATA_BLOB secblob = data_blob_null;
864 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
866 if (!spnego_parse_auth(blob1, &auth)) {
868 file_save("auth.dat", blob1.data, blob1.length);
870 /* Kill the intermediate vuid */
871 invalidate_vuid(vuid);
873 reply_nterror(req, nt_status_squash(
874 NT_STATUS_LOGON_FAILURE));
878 if (auth.data[0] == ASN1_APPLICATION(0)) {
879 /* Might be a second negTokenTarg packet */
880 char *kerb_mech = NULL;
882 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
884 if (!NT_STATUS_IS_OK(status)) {
885 /* Kill the intermediate vuid */
886 invalidate_vuid(vuid);
887 reply_nterror(req, nt_status_squash(status));
891 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
892 (unsigned long)secblob.length));
894 if (kerb_mech && ((lp_security()==SEC_ADS) ||
895 lp_use_kerberos_keytab()) ) {
896 bool destroy_vuid = True;
897 reply_spnego_kerberos(req, &secblob, kerb_mech,
898 vuid, &destroy_vuid);
899 data_blob_free(&secblob);
900 data_blob_free(&auth);
902 /* Kill the intermediate vuid */
903 invalidate_vuid(vuid);
905 SAFE_FREE(kerb_mech);
909 /* Can't blunder into NTLMSSP auth if we have
913 /* Kill the intermediate vuid */
914 invalidate_vuid(vuid);
915 DEBUG(3,("reply_spnego_auth: network "
916 "misconfiguration, client sent us a "
917 "krb5 ticket and kerberos security "
919 reply_nterror(req, nt_status_squash(
920 NT_STATUS_LOGON_FAILURE));
921 SAFE_FREE(kerb_mech);
925 /* If we get here it wasn't a negTokenTarg auth packet. */
926 data_blob_free(&secblob);
928 if (!*auth_ntlmssp_state) {
929 status = auth_ntlmssp_start(auth_ntlmssp_state);
930 if (!NT_STATUS_IS_OK(status)) {
931 /* Kill the intermediate vuid */
932 invalidate_vuid(vuid);
933 reply_nterror(req, nt_status_squash(status));
938 status = auth_ntlmssp_update(*auth_ntlmssp_state,
941 data_blob_free(&auth);
943 /* Don't send the mechid as we've already sent this (RFC4178). */
945 reply_spnego_ntlmssp(req, vuid,
947 &auth_reply, status, NULL, true);
949 data_blob_free(&auth_reply);
951 /* and tell smbd that we have already replied to this packet */
955 /****************************************************************************
956 List to store partial SPNEGO auth fragments.
957 ****************************************************************************/
959 static struct pending_auth_data *pd_list;
961 /****************************************************************************
962 Delete an entry on the list.
963 ****************************************************************************/
965 static void delete_partial_auth(struct pending_auth_data *pad)
970 DLIST_REMOVE(pd_list, pad);
971 data_blob_free(&pad->partial_data);
975 /****************************************************************************
976 Search for a partial SPNEGO auth fragment matching an smbpid.
977 ****************************************************************************/
979 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
981 struct pending_auth_data *pad;
983 for (pad = pd_list; pad; pad = pad->next) {
984 if (pad->smbpid == smbpid) {
991 /****************************************************************************
992 Check the size of an SPNEGO blob. If we need more return
993 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
994 the blob to be more than 64k.
995 ****************************************************************************/
997 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
1000 struct pending_auth_data *pad = NULL;
1002 size_t needed_len = 0;
1004 pad = get_pending_auth_data(smbpid);
1006 /* Ensure we have some data. */
1007 if (pblob->length == 0) {
1008 /* Caller can cope. */
1009 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1010 delete_partial_auth(pad);
1011 return NT_STATUS_OK;
1014 /* Were we waiting for more data ? */
1017 size_t copy_len = MIN(65536, pblob->length);
1019 /* Integer wrap paranoia.... */
1021 if (pad->partial_data.length + copy_len <
1022 pad->partial_data.length ||
1023 pad->partial_data.length + copy_len < copy_len) {
1025 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1026 "pad->partial_data.length = %u, "
1028 (unsigned int)pad->partial_data.length,
1029 (unsigned int)copy_len ));
1031 delete_partial_auth(pad);
1032 return NT_STATUS_INVALID_PARAMETER;
1035 DEBUG(10,("check_spnego_blob_complete: "
1036 "pad->partial_data.length = %u, "
1037 "pad->needed_len = %u, "
1039 "pblob->length = %u,\n",
1040 (unsigned int)pad->partial_data.length,
1041 (unsigned int)pad->needed_len,
1042 (unsigned int)copy_len,
1043 (unsigned int)pblob->length ));
1045 tmp_blob = data_blob(NULL,
1046 pad->partial_data.length + copy_len);
1048 /* Concatenate the two (up to copy_len) bytes. */
1049 memcpy(tmp_blob.data,
1050 pad->partial_data.data,
1051 pad->partial_data.length);
1052 memcpy(tmp_blob.data + pad->partial_data.length,
1056 /* Replace the partial data. */
1057 data_blob_free(&pad->partial_data);
1058 pad->partial_data = tmp_blob;
1059 ZERO_STRUCT(tmp_blob);
1062 if (pblob->length >= pad->needed_len) {
1063 /* Yes, replace pblob. */
1064 data_blob_free(pblob);
1065 *pblob = pad->partial_data;
1066 ZERO_STRUCT(pad->partial_data);
1067 delete_partial_auth(pad);
1068 return NT_STATUS_OK;
1071 /* Still need more data. */
1072 pad->needed_len -= copy_len;
1073 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1076 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1077 (pblob->data[0] != ASN1_CONTEXT(1))) {
1078 /* Not something we can determine the
1081 return NT_STATUS_OK;
1084 /* This is a new SPNEGO sessionsetup - see if
1085 * the data given in this blob is enough.
1088 asn1_load(&data, *pblob);
1089 asn1_start_tag(&data, pblob->data[0]);
1090 if (data.has_error || data.nesting == NULL) {
1092 /* Let caller catch. */
1093 return NT_STATUS_OK;
1096 /* Integer wrap paranoia.... */
1098 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1099 data.nesting->taglen + data.nesting->start < data.nesting->start) {
1101 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1102 "data.nesting->taglen = %u, "
1103 "data.nesting->start = %u\n",
1104 (unsigned int)data.nesting->taglen,
1105 (unsigned int)data.nesting->start ));
1108 return NT_STATUS_INVALID_PARAMETER;
1111 /* Total length of the needed asn1 is the tag length
1112 * plus the current offset. */
1114 needed_len = data.nesting->taglen + data.nesting->start;
1117 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1118 "pblob->length = %u\n",
1119 (unsigned int)needed_len,
1120 (unsigned int)pblob->length ));
1122 if (needed_len <= pblob->length) {
1123 /* Nothing to do - blob is complete. */
1124 return NT_STATUS_OK;
1127 /* Refuse the blob if it's bigger than 64k. */
1128 if (needed_len > 65536) {
1129 DEBUG(2,("check_spnego_blob_complete: needed_len "
1131 (unsigned int)needed_len ));
1132 return NT_STATUS_INVALID_PARAMETER;
1135 /* We must store this blob until complete. */
1136 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1137 return NT_STATUS_NO_MEMORY;
1139 pad->needed_len = needed_len - pblob->length;
1140 pad->partial_data = data_blob(pblob->data, pblob->length);
1141 if (pad->partial_data.data == NULL) {
1143 return NT_STATUS_NO_MEMORY;
1145 pad->smbpid = smbpid;
1147 DLIST_ADD(pd_list, pad);
1149 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1152 /****************************************************************************
1153 Reply to a session setup command.
1154 conn POINTER CAN BE NULL HERE !
1155 ****************************************************************************/
1157 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1162 fstring native_os, native_lanman, primary_domain;
1164 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1165 enum remote_arch_types ra_type = get_remote_arch();
1166 int vuid = SVAL(req->inbuf,smb_uid);
1167 user_struct *vuser = NULL;
1168 NTSTATUS status = NT_STATUS_OK;
1169 uint16 smbpid = req->smbpid;
1170 uint16 smb_flag2 = req->flags2;
1172 DEBUG(3,("Doing spnego session setup\n"));
1174 if (global_client_caps == 0) {
1175 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1177 if (!(global_client_caps & CAP_STATUS32)) {
1178 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1183 p = (uint8 *)smb_buf(req->inbuf);
1185 if (data_blob_len == 0) {
1186 /* an invalid request */
1187 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1191 bufrem = smb_bufrem(req->inbuf, p);
1192 /* pull the spnego blob */
1193 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1196 file_save("negotiate.dat", blob1.data, blob1.length);
1199 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1200 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1201 sizeof(native_os), STR_TERMINATE);
1202 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1203 sizeof(native_lanman), STR_TERMINATE);
1204 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1205 sizeof(primary_domain), STR_TERMINATE);
1206 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1207 native_os, native_lanman, primary_domain));
1209 if ( ra_type == RA_WIN2K ) {
1210 /* Vista sets neither the OS or lanman strings */
1212 if ( !strlen(native_os) && !strlen(native_lanman) )
1213 set_remote_arch(RA_VISTA);
1215 /* Windows 2003 doesn't set the native lanman string,
1216 but does set primary domain which is a bug I think */
1218 if ( !strlen(native_lanman) ) {
1219 ra_lanman_string( primary_domain );
1221 ra_lanman_string( native_lanman );
1225 /* Did we get a valid vuid ? */
1226 if (!is_partial_auth_vuid(vuid)) {
1227 /* No, then try and see if this is an intermediate sessionsetup
1228 * for a large SPNEGO packet. */
1229 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1231 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1232 "pending vuid %u\n",
1233 (unsigned int)pad->vuid ));
1238 /* Do we have a valid vuid now ? */
1239 if (!is_partial_auth_vuid(vuid)) {
1240 /* No, start a new authentication setup. */
1241 vuid = register_initial_vuid();
1242 if (vuid == UID_FIELD_INVALID) {
1243 data_blob_free(&blob1);
1244 reply_nterror(req, nt_status_squash(
1245 NT_STATUS_INVALID_PARAMETER));
1250 vuser = get_partial_auth_user_struct(vuid);
1251 /* This MUST be valid. */
1253 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1256 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1257 * sessionsetup requests as the Windows limit on the security blob
1258 * field is 4k. Bug #4400. JRA.
1261 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1262 if (!NT_STATUS_IS_OK(status)) {
1263 if (!NT_STATUS_EQUAL(status,
1264 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1265 /* Real error - kill the intermediate vuid */
1266 invalidate_vuid(vuid);
1268 data_blob_free(&blob1);
1269 reply_nterror(req, nt_status_squash(status));
1273 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1275 /* its a negTokenTarg packet */
1277 reply_spnego_negotiate(req, vuid, blob1,
1278 &vuser->auth_ntlmssp_state);
1279 data_blob_free(&blob1);
1283 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1285 /* its a auth packet */
1287 reply_spnego_auth(req, vuid, blob1,
1288 &vuser->auth_ntlmssp_state);
1289 data_blob_free(&blob1);
1293 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1296 if (!vuser->auth_ntlmssp_state) {
1297 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1298 if (!NT_STATUS_IS_OK(status)) {
1299 /* Kill the intermediate vuid */
1300 invalidate_vuid(vuid);
1301 data_blob_free(&blob1);
1302 reply_nterror(req, nt_status_squash(status));
1307 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1310 data_blob_free(&blob1);
1312 reply_spnego_ntlmssp(req, vuid,
1313 &vuser->auth_ntlmssp_state,
1314 &chal, status, OID_NTLMSSP, false);
1315 data_blob_free(&chal);
1319 /* what sort of packet is this? */
1320 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1322 data_blob_free(&blob1);
1324 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1327 /****************************************************************************
1328 On new VC == 0, shutdown *all* old connections and users.
1329 It seems that only NT4.x does this. At W2K and above (XP etc.).
1330 a new session setup with VC==0 is ignored.
1331 ****************************************************************************/
1333 static int shutdown_other_smbds(struct db_record *rec,
1334 const struct connections_key *key,
1335 const struct connections_data *crec,
1338 const char *ip = (const char *)private_data;
1340 if (!process_exists(crec->pid)) {
1344 if (procid_is_me(&crec->pid)) {
1348 if (strcmp(ip, crec->addr) != 0) {
1352 DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
1353 "(IP %s)\n", procid_to_pid(&crec->pid), ip));
1355 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1360 static void setup_new_vc_session(void)
1362 char addr[INET6_ADDRSTRLEN];
1364 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1365 "compatible we would close all old resources.\n"));
1368 invalidate_all_vuids();
1370 if (lp_reset_on_zero_vc()) {
1371 connections_forall(shutdown_other_smbds,
1372 CONST_DISCARD(void *,
1373 client_addr(get_client_fd(),addr,sizeof(addr))));
1377 /****************************************************************************
1378 Reply to a session setup command.
1379 ****************************************************************************/
1381 void reply_sesssetup_and_X(struct smb_request *req)
1387 DATA_BLOB plaintext_password;
1389 fstring sub_user; /* Sainitised username for substituion */
1392 fstring native_lanman;
1393 fstring primary_domain;
1394 static bool done_sesssetup = False;
1395 auth_usersupplied_info *user_info = NULL;
1396 auth_serversupplied_info *server_info = NULL;
1397 uint16 smb_flag2 = req->flags2;
1401 bool doencrypt = global_encrypted_passwords_negotiated;
1403 START_PROFILE(SMBsesssetupX);
1405 ZERO_STRUCT(lm_resp);
1406 ZERO_STRUCT(nt_resp);
1407 ZERO_STRUCT(plaintext_password);
1409 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1411 /* a SPNEGO session setup has 12 command words, whereas a normal
1412 NT1 session setup has 13. See the cifs spec. */
1413 if (req->wct == 12 &&
1414 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1416 if (!global_spnego_negotiated) {
1417 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1418 "at SPNEGO session setup when it was not "
1420 reply_nterror(req, nt_status_squash(
1421 NT_STATUS_LOGON_FAILURE));
1422 END_PROFILE(SMBsesssetupX);
1426 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1427 setup_new_vc_session();
1430 reply_sesssetup_and_X_spnego(req);
1431 END_PROFILE(SMBsesssetupX);
1435 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1437 if (Protocol < PROTOCOL_NT1) {
1438 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1440 /* Never do NT status codes with protocols before NT1 as we
1441 * don't get client caps. */
1442 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1444 if ((passlen1 > MAX_PASS_LEN)
1445 || (passlen1 > smb_bufrem(req->inbuf,
1446 smb_buf(req->inbuf)))) {
1447 reply_nterror(req, nt_status_squash(
1448 NT_STATUS_INVALID_PARAMETER));
1449 END_PROFILE(SMBsesssetupX);
1454 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1456 plaintext_password = data_blob(smb_buf(req->inbuf),
1458 /* Ensure null termination */
1459 plaintext_password.data[passlen1] = 0;
1462 srvstr_pull_buf(req->inbuf, req->flags2, user,
1463 smb_buf(req->inbuf)+passlen1, sizeof(user),
1468 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1469 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1470 enum remote_arch_types ra_type = get_remote_arch();
1471 char *p = smb_buf(req->inbuf);
1472 char *save_p = smb_buf(req->inbuf);
1476 if(global_client_caps == 0) {
1477 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1479 if (!(global_client_caps & CAP_STATUS32)) {
1480 remove_from_common_flags2(
1481 FLAGS2_32_BIT_ERROR_CODES);
1484 /* client_caps is used as final determination if
1485 * client is NT or Win95. This is needed to return
1486 * the correct error codes in some circumstances.
1489 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1490 ra_type == RA_WIN95) {
1491 if(!(global_client_caps & (CAP_NT_SMBS|
1493 set_remote_arch( RA_WIN95);
1499 /* both Win95 and WinNT stuff up the password
1500 * lengths for non-encrypting systems. Uggh.
1502 if passlen1==24 its a win95 system, and its setting
1503 the password length incorrectly. Luckily it still
1504 works with the default code because Win95 will null
1505 terminate the password anyway
1507 if passlen1>0 and passlen2>0 then maybe its a NT box
1508 and its setting passlen2 to some random value which
1509 really stuffs things up. we need to fix that one. */
1511 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1517 /* check for nasty tricks */
1518 if (passlen1 > MAX_PASS_LEN
1519 || passlen1 > smb_bufrem(req->inbuf, p)) {
1520 reply_nterror(req, nt_status_squash(
1521 NT_STATUS_INVALID_PARAMETER));
1522 END_PROFILE(SMBsesssetupX);
1526 if (passlen2 > MAX_PASS_LEN
1527 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1528 reply_nterror(req, nt_status_squash(
1529 NT_STATUS_INVALID_PARAMETER));
1530 END_PROFILE(SMBsesssetupX);
1534 /* Save the lanman2 password and the NT md4 password. */
1536 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1541 lm_resp = data_blob(p, passlen1);
1542 nt_resp = data_blob(p+passlen1, passlen2);
1543 } else if (lp_security() != SEC_SHARE) {
1545 * In share level we should ignore any passwords, so
1546 * only read them if we're not.
1549 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1551 if (unic && (passlen2 == 0) && passlen1) {
1552 /* Only a ascii plaintext password was sent. */
1553 (void)srvstr_pull_talloc(talloc_tos(),
1557 smb_buf(req->inbuf),
1559 STR_TERMINATE|STR_ASCII);
1561 (void)srvstr_pull_talloc(talloc_tos(),
1565 smb_buf(req->inbuf),
1566 unic ? passlen2 : passlen1,
1570 reply_nterror(req, nt_status_squash(
1571 NT_STATUS_INVALID_PARAMETER));
1572 END_PROFILE(SMBsesssetupX);
1575 plaintext_password = data_blob(pass, strlen(pass)+1);
1578 p += passlen1 + passlen2;
1579 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1580 sizeof(user), STR_TERMINATE);
1581 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1582 sizeof(domain), STR_TERMINATE);
1583 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1584 p, sizeof(native_os), STR_TERMINATE);
1585 p += srvstr_pull_buf(req->inbuf, req->flags2,
1586 native_lanman, p, sizeof(native_lanman),
1589 /* not documented or decoded by Ethereal but there is one more
1590 * string in the extra bytes which is the same as the
1591 * PrimaryDomain when using extended security. Windows NT 4
1592 * and 2003 use this string to store the native lanman string.
1593 * Windows 9x does not include a string here at all so we have
1594 * to check if we have any extra bytes left */
1596 byte_count = SVAL(req->inbuf, smb_vwv13);
1597 if ( PTR_DIFF(p, save_p) < byte_count) {
1598 p += srvstr_pull_buf(req->inbuf, req->flags2,
1600 sizeof(primary_domain),
1603 fstrcpy( primary_domain, "null" );
1606 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1607 "PrimaryDomain=[%s]\n",
1608 domain, native_os, native_lanman, primary_domain));
1610 if ( ra_type == RA_WIN2K ) {
1611 if ( strlen(native_lanman) == 0 )
1612 ra_lanman_string( primary_domain );
1614 ra_lanman_string( native_lanman );
1619 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1620 setup_new_vc_session();
1623 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1624 domain, user, get_remote_machine_name()));
1627 if (global_spnego_negotiated) {
1629 /* This has to be here, because this is a perfectly
1630 * valid behaviour for guest logons :-( */
1632 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1633 "at 'normal' session setup after "
1634 "negotiating spnego.\n"));
1635 reply_nterror(req, nt_status_squash(
1636 NT_STATUS_LOGON_FAILURE));
1637 END_PROFILE(SMBsesssetupX);
1640 fstrcpy(sub_user, user);
1642 fstrcpy(sub_user, lp_guestaccount());
1645 sub_set_smb_name(sub_user);
1647 reload_services(True);
1649 if (lp_security() == SEC_SHARE) {
1650 /* In share level we should ignore any passwords */
1652 data_blob_free(&lm_resp);
1653 data_blob_free(&nt_resp);
1654 data_blob_clear_free(&plaintext_password);
1656 map_username(sub_user);
1657 add_session_user(sub_user);
1658 add_session_workgroup(domain);
1659 /* Then force it to null for the benfit of the code below */
1665 nt_status = check_guest_password(&server_info);
1667 } else if (doencrypt) {
1668 if (!negprot_global_auth_context) {
1669 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1670 "session setup without negprot denied!\n"));
1671 reply_nterror(req, nt_status_squash(
1672 NT_STATUS_LOGON_FAILURE));
1673 END_PROFILE(SMBsesssetupX);
1676 nt_status = make_user_info_for_reply_enc(&user_info, user,
1679 if (NT_STATUS_IS_OK(nt_status)) {
1680 nt_status = negprot_global_auth_context->check_ntlm_password(
1681 negprot_global_auth_context,
1686 struct auth_context *plaintext_auth_context = NULL;
1689 nt_status = make_auth_context_subsystem(
1690 &plaintext_auth_context);
1692 if (NT_STATUS_IS_OK(nt_status)) {
1693 chal = plaintext_auth_context->get_ntlm_challenge(
1694 plaintext_auth_context);
1696 if (!make_user_info_for_reply(&user_info,
1698 plaintext_password)) {
1699 nt_status = NT_STATUS_NO_MEMORY;
1702 if (NT_STATUS_IS_OK(nt_status)) {
1703 nt_status = plaintext_auth_context->check_ntlm_password(
1704 plaintext_auth_context,
1708 (plaintext_auth_context->free)(
1709 &plaintext_auth_context);
1714 free_user_info(&user_info);
1716 if (!NT_STATUS_IS_OK(nt_status)) {
1717 nt_status = do_map_to_guest(nt_status, &server_info,
1721 if (!NT_STATUS_IS_OK(nt_status)) {
1722 data_blob_free(&nt_resp);
1723 data_blob_free(&lm_resp);
1724 data_blob_clear_free(&plaintext_password);
1725 reply_nterror(req, nt_status_squash(nt_status));
1726 END_PROFILE(SMBsesssetupX);
1730 /* Ensure we can't possible take a code path leading to a
1733 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1734 END_PROFILE(SMBsesssetupX);
1738 if (!server_info->ptok) {
1739 nt_status = create_local_token(server_info);
1741 if (!NT_STATUS_IS_OK(nt_status)) {
1742 DEBUG(10, ("create_local_token failed: %s\n",
1743 nt_errstr(nt_status)));
1744 data_blob_free(&nt_resp);
1745 data_blob_free(&lm_resp);
1746 data_blob_clear_free(&plaintext_password);
1747 reply_nterror(req, nt_status_squash(nt_status));
1748 END_PROFILE(SMBsesssetupX);
1753 data_blob_clear_free(&plaintext_password);
1755 /* it's ok - setup a reply */
1756 reply_outbuf(req, 3, 0);
1757 if (Protocol >= PROTOCOL_NT1) {
1758 push_signature(&req->outbuf);
1759 /* perhaps grab OS version here?? */
1762 if (server_info->guest) {
1763 SSVAL(req->outbuf,smb_vwv2,1);
1766 /* register the name and uid as being validated, so further connections
1767 to a uid can get through without a password, on the same VC */
1769 if (lp_security() == SEC_SHARE) {
1770 sess_vuid = UID_FIELD_INVALID;
1771 TALLOC_FREE(server_info);
1773 /* Ignore the initial vuid. */
1774 sess_vuid = register_initial_vuid();
1775 if (sess_vuid == UID_FIELD_INVALID) {
1776 data_blob_free(&nt_resp);
1777 data_blob_free(&lm_resp);
1778 reply_nterror(req, nt_status_squash(
1779 NT_STATUS_LOGON_FAILURE));
1780 END_PROFILE(SMBsesssetupX);
1783 /* register_existing_vuid keeps the server info */
1784 sess_vuid = register_existing_vuid(sess_vuid,
1786 nt_resp.data ? nt_resp : lm_resp,
1788 if (sess_vuid == UID_FIELD_INVALID) {
1789 data_blob_free(&nt_resp);
1790 data_blob_free(&lm_resp);
1791 reply_nterror(req, nt_status_squash(
1792 NT_STATUS_LOGON_FAILURE));
1793 END_PROFILE(SMBsesssetupX);
1797 /* current_user_info is changed on new vuid */
1798 reload_services( True );
1800 sessionsetup_start_signing_engine(server_info, req->inbuf);
1803 data_blob_free(&nt_resp);
1804 data_blob_free(&lm_resp);
1806 SSVAL(req->outbuf,smb_uid,sess_vuid);
1807 SSVAL(req->inbuf,smb_uid,sess_vuid);
1809 if (!done_sesssetup)
1810 max_send = MIN(max_send,smb_bufsize);
1812 done_sesssetup = True;
1814 END_PROFILE(SMBsesssetupX);