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 data = asn1_init(NULL);
1090 return NT_STATUS_NO_MEMORY;
1093 asn1_load(data, *pblob);
1094 asn1_start_tag(data, pblob->data[0]);
1095 if (data->has_error || data->nesting == NULL) {
1097 /* Let caller catch. */
1098 return NT_STATUS_OK;
1101 /* Integer wrap paranoia.... */
1103 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1104 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1106 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1107 "data.nesting->taglen = %u, "
1108 "data.nesting->start = %u\n",
1109 (unsigned int)data->nesting->taglen,
1110 (unsigned int)data->nesting->start ));
1113 return NT_STATUS_INVALID_PARAMETER;
1116 /* Total length of the needed asn1 is the tag length
1117 * plus the current offset. */
1119 needed_len = data->nesting->taglen + data->nesting->start;
1122 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1123 "pblob->length = %u\n",
1124 (unsigned int)needed_len,
1125 (unsigned int)pblob->length ));
1127 if (needed_len <= pblob->length) {
1128 /* Nothing to do - blob is complete. */
1129 return NT_STATUS_OK;
1132 /* Refuse the blob if it's bigger than 64k. */
1133 if (needed_len > 65536) {
1134 DEBUG(2,("check_spnego_blob_complete: needed_len "
1136 (unsigned int)needed_len ));
1137 return NT_STATUS_INVALID_PARAMETER;
1140 /* We must store this blob until complete. */
1141 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1142 return NT_STATUS_NO_MEMORY;
1144 pad->needed_len = needed_len - pblob->length;
1145 pad->partial_data = data_blob(pblob->data, pblob->length);
1146 if (pad->partial_data.data == NULL) {
1148 return NT_STATUS_NO_MEMORY;
1150 pad->smbpid = smbpid;
1152 DLIST_ADD(pd_list, pad);
1154 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1157 /****************************************************************************
1158 Reply to a session setup command.
1159 conn POINTER CAN BE NULL HERE !
1160 ****************************************************************************/
1162 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1167 fstring native_os, native_lanman, primary_domain;
1169 uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1170 enum remote_arch_types ra_type = get_remote_arch();
1171 int vuid = SVAL(req->inbuf,smb_uid);
1172 user_struct *vuser = NULL;
1173 NTSTATUS status = NT_STATUS_OK;
1174 uint16 smbpid = req->smbpid;
1175 uint16 smb_flag2 = req->flags2;
1177 DEBUG(3,("Doing spnego session setup\n"));
1179 if (global_client_caps == 0) {
1180 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1182 if (!(global_client_caps & CAP_STATUS32)) {
1183 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1188 p = (uint8 *)smb_buf(req->inbuf);
1190 if (data_blob_len == 0) {
1191 /* an invalid request */
1192 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1196 bufrem = smb_bufrem(req->inbuf, p);
1197 /* pull the spnego blob */
1198 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1201 file_save("negotiate.dat", blob1.data, blob1.length);
1204 p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1205 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1206 sizeof(native_os), STR_TERMINATE);
1207 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1208 sizeof(native_lanman), STR_TERMINATE);
1209 p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1210 sizeof(primary_domain), STR_TERMINATE);
1211 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1212 native_os, native_lanman, primary_domain));
1214 if ( ra_type == RA_WIN2K ) {
1215 /* Vista sets neither the OS or lanman strings */
1217 if ( !strlen(native_os) && !strlen(native_lanman) )
1218 set_remote_arch(RA_VISTA);
1220 /* Windows 2003 doesn't set the native lanman string,
1221 but does set primary domain which is a bug I think */
1223 if ( !strlen(native_lanman) ) {
1224 ra_lanman_string( primary_domain );
1226 ra_lanman_string( native_lanman );
1230 /* Did we get a valid vuid ? */
1231 if (!is_partial_auth_vuid(vuid)) {
1232 /* No, then try and see if this is an intermediate sessionsetup
1233 * for a large SPNEGO packet. */
1234 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1236 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1237 "pending vuid %u\n",
1238 (unsigned int)pad->vuid ));
1243 /* Do we have a valid vuid now ? */
1244 if (!is_partial_auth_vuid(vuid)) {
1245 /* No, start a new authentication setup. */
1246 vuid = register_initial_vuid();
1247 if (vuid == UID_FIELD_INVALID) {
1248 data_blob_free(&blob1);
1249 reply_nterror(req, nt_status_squash(
1250 NT_STATUS_INVALID_PARAMETER));
1255 vuser = get_partial_auth_user_struct(vuid);
1256 /* This MUST be valid. */
1258 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1261 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1262 * sessionsetup requests as the Windows limit on the security blob
1263 * field is 4k. Bug #4400. JRA.
1266 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 if (!NT_STATUS_EQUAL(status,
1269 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1270 /* Real error - kill the intermediate vuid */
1271 invalidate_vuid(vuid);
1273 data_blob_free(&blob1);
1274 reply_nterror(req, nt_status_squash(status));
1278 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1280 /* its a negTokenTarg packet */
1282 reply_spnego_negotiate(req, vuid, blob1,
1283 &vuser->auth_ntlmssp_state);
1284 data_blob_free(&blob1);
1288 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1290 /* its a auth packet */
1292 reply_spnego_auth(req, vuid, blob1,
1293 &vuser->auth_ntlmssp_state);
1294 data_blob_free(&blob1);
1298 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1301 if (!vuser->auth_ntlmssp_state) {
1302 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 /* Kill the intermediate vuid */
1305 invalidate_vuid(vuid);
1306 data_blob_free(&blob1);
1307 reply_nterror(req, nt_status_squash(status));
1312 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1315 data_blob_free(&blob1);
1317 reply_spnego_ntlmssp(req, vuid,
1318 &vuser->auth_ntlmssp_state,
1319 &chal, status, OID_NTLMSSP, false);
1320 data_blob_free(&chal);
1324 /* what sort of packet is this? */
1325 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1327 data_blob_free(&blob1);
1329 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1332 /****************************************************************************
1333 On new VC == 0, shutdown *all* old connections and users.
1334 It seems that only NT4.x does this. At W2K and above (XP etc.).
1335 a new session setup with VC==0 is ignored.
1336 ****************************************************************************/
1338 static int shutdown_other_smbds(struct db_record *rec,
1339 const struct connections_key *key,
1340 const struct connections_data *crec,
1343 const char *ip = (const char *)private_data;
1345 if (!process_exists(crec->pid)) {
1349 if (procid_is_me(&crec->pid)) {
1353 if (strcmp(ip, crec->addr) != 0) {
1357 DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
1358 "(IP %s)\n", procid_to_pid(&crec->pid), ip));
1360 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1365 static void setup_new_vc_session(void)
1367 char addr[INET6_ADDRSTRLEN];
1369 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1370 "compatible we would close all old resources.\n"));
1373 invalidate_all_vuids();
1375 if (lp_reset_on_zero_vc()) {
1376 connections_forall(shutdown_other_smbds,
1377 CONST_DISCARD(void *,
1378 client_addr(get_client_fd(),addr,sizeof(addr))));
1382 /****************************************************************************
1383 Reply to a session setup command.
1384 ****************************************************************************/
1386 void reply_sesssetup_and_X(struct smb_request *req)
1392 DATA_BLOB plaintext_password;
1394 fstring sub_user; /* Sainitised username for substituion */
1397 fstring native_lanman;
1398 fstring primary_domain;
1399 static bool done_sesssetup = False;
1400 auth_usersupplied_info *user_info = NULL;
1401 auth_serversupplied_info *server_info = NULL;
1402 uint16 smb_flag2 = req->flags2;
1406 bool doencrypt = global_encrypted_passwords_negotiated;
1408 START_PROFILE(SMBsesssetupX);
1410 ZERO_STRUCT(lm_resp);
1411 ZERO_STRUCT(nt_resp);
1412 ZERO_STRUCT(plaintext_password);
1414 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1416 /* a SPNEGO session setup has 12 command words, whereas a normal
1417 NT1 session setup has 13. See the cifs spec. */
1418 if (req->wct == 12 &&
1419 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1421 if (!global_spnego_negotiated) {
1422 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1423 "at SPNEGO session setup when it was not "
1425 reply_nterror(req, nt_status_squash(
1426 NT_STATUS_LOGON_FAILURE));
1427 END_PROFILE(SMBsesssetupX);
1431 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1432 setup_new_vc_session();
1435 reply_sesssetup_and_X_spnego(req);
1436 END_PROFILE(SMBsesssetupX);
1440 smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1442 if (Protocol < PROTOCOL_NT1) {
1443 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1445 /* Never do NT status codes with protocols before NT1 as we
1446 * don't get client caps. */
1447 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1449 if ((passlen1 > MAX_PASS_LEN)
1450 || (passlen1 > smb_buflen(req->inbuf))) {
1451 reply_nterror(req, nt_status_squash(
1452 NT_STATUS_INVALID_PARAMETER));
1453 END_PROFILE(SMBsesssetupX);
1458 lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1460 plaintext_password = data_blob(smb_buf(req->inbuf),
1462 /* Ensure null termination */
1463 plaintext_password.data[passlen1] = 0;
1466 srvstr_pull_buf(req->inbuf, req->flags2, user,
1467 smb_buf(req->inbuf)+passlen1, sizeof(user),
1472 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1473 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1474 enum remote_arch_types ra_type = get_remote_arch();
1475 char *p = smb_buf(req->inbuf);
1476 char *save_p = smb_buf(req->inbuf);
1480 if(global_client_caps == 0) {
1481 global_client_caps = IVAL(req->inbuf,smb_vwv11);
1483 if (!(global_client_caps & CAP_STATUS32)) {
1484 remove_from_common_flags2(
1485 FLAGS2_32_BIT_ERROR_CODES);
1488 /* client_caps is used as final determination if
1489 * client is NT or Win95. This is needed to return
1490 * the correct error codes in some circumstances.
1493 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1494 ra_type == RA_WIN95) {
1495 if(!(global_client_caps & (CAP_NT_SMBS|
1497 set_remote_arch( RA_WIN95);
1503 /* both Win95 and WinNT stuff up the password
1504 * lengths for non-encrypting systems. Uggh.
1506 if passlen1==24 its a win95 system, and its setting
1507 the password length incorrectly. Luckily it still
1508 works with the default code because Win95 will null
1509 terminate the password anyway
1511 if passlen1>0 and passlen2>0 then maybe its a NT box
1512 and its setting passlen2 to some random value which
1513 really stuffs things up. we need to fix that one. */
1515 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1521 /* check for nasty tricks */
1522 if (passlen1 > MAX_PASS_LEN
1523 || passlen1 > smb_bufrem(req->inbuf, p)) {
1524 reply_nterror(req, nt_status_squash(
1525 NT_STATUS_INVALID_PARAMETER));
1526 END_PROFILE(SMBsesssetupX);
1530 if (passlen2 > MAX_PASS_LEN
1531 || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1532 reply_nterror(req, nt_status_squash(
1533 NT_STATUS_INVALID_PARAMETER));
1534 END_PROFILE(SMBsesssetupX);
1538 /* Save the lanman2 password and the NT md4 password. */
1540 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1545 lm_resp = data_blob(p, passlen1);
1546 nt_resp = data_blob(p+passlen1, passlen2);
1547 } else if (lp_security() != SEC_SHARE) {
1549 * In share level we should ignore any passwords, so
1550 * only read them if we're not.
1553 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1555 if (unic && (passlen2 == 0) && passlen1) {
1556 /* Only a ascii plaintext password was sent. */
1557 (void)srvstr_pull_talloc(talloc_tos(),
1561 smb_buf(req->inbuf),
1563 STR_TERMINATE|STR_ASCII);
1565 (void)srvstr_pull_talloc(talloc_tos(),
1569 smb_buf(req->inbuf),
1570 unic ? passlen2 : passlen1,
1574 reply_nterror(req, nt_status_squash(
1575 NT_STATUS_INVALID_PARAMETER));
1576 END_PROFILE(SMBsesssetupX);
1579 plaintext_password = data_blob(pass, strlen(pass)+1);
1582 p += passlen1 + passlen2;
1583 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1584 sizeof(user), STR_TERMINATE);
1585 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1586 sizeof(domain), STR_TERMINATE);
1587 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1588 p, sizeof(native_os), STR_TERMINATE);
1589 p += srvstr_pull_buf(req->inbuf, req->flags2,
1590 native_lanman, p, sizeof(native_lanman),
1593 /* not documented or decoded by Ethereal but there is one more
1594 * string in the extra bytes which is the same as the
1595 * PrimaryDomain when using extended security. Windows NT 4
1596 * and 2003 use this string to store the native lanman string.
1597 * Windows 9x does not include a string here at all so we have
1598 * to check if we have any extra bytes left */
1600 byte_count = SVAL(req->inbuf, smb_vwv13);
1601 if ( PTR_DIFF(p, save_p) < byte_count) {
1602 p += srvstr_pull_buf(req->inbuf, req->flags2,
1604 sizeof(primary_domain),
1607 fstrcpy( primary_domain, "null" );
1610 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1611 "PrimaryDomain=[%s]\n",
1612 domain, native_os, native_lanman, primary_domain));
1614 if ( ra_type == RA_WIN2K ) {
1615 if ( strlen(native_lanman) == 0 )
1616 ra_lanman_string( primary_domain );
1618 ra_lanman_string( native_lanman );
1623 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1624 setup_new_vc_session();
1627 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1628 domain, user, get_remote_machine_name()));
1631 if (global_spnego_negotiated) {
1633 /* This has to be here, because this is a perfectly
1634 * valid behaviour for guest logons :-( */
1636 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1637 "at 'normal' session setup after "
1638 "negotiating spnego.\n"));
1639 reply_nterror(req, nt_status_squash(
1640 NT_STATUS_LOGON_FAILURE));
1641 END_PROFILE(SMBsesssetupX);
1644 fstrcpy(sub_user, user);
1646 fstrcpy(sub_user, lp_guestaccount());
1649 sub_set_smb_name(sub_user);
1651 reload_services(True);
1653 if (lp_security() == SEC_SHARE) {
1654 /* In share level we should ignore any passwords */
1656 data_blob_free(&lm_resp);
1657 data_blob_free(&nt_resp);
1658 data_blob_clear_free(&plaintext_password);
1660 map_username(sub_user);
1661 add_session_user(sub_user);
1662 add_session_workgroup(domain);
1663 /* Then force it to null for the benfit of the code below */
1669 nt_status = check_guest_password(&server_info);
1671 } else if (doencrypt) {
1672 if (!negprot_global_auth_context) {
1673 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1674 "session setup without negprot denied!\n"));
1675 reply_nterror(req, nt_status_squash(
1676 NT_STATUS_LOGON_FAILURE));
1677 END_PROFILE(SMBsesssetupX);
1680 nt_status = make_user_info_for_reply_enc(&user_info, user,
1683 if (NT_STATUS_IS_OK(nt_status)) {
1684 nt_status = negprot_global_auth_context->check_ntlm_password(
1685 negprot_global_auth_context,
1690 struct auth_context *plaintext_auth_context = NULL;
1693 nt_status = make_auth_context_subsystem(
1694 &plaintext_auth_context);
1696 if (NT_STATUS_IS_OK(nt_status)) {
1697 chal = plaintext_auth_context->get_ntlm_challenge(
1698 plaintext_auth_context);
1700 if (!make_user_info_for_reply(&user_info,
1702 plaintext_password)) {
1703 nt_status = NT_STATUS_NO_MEMORY;
1706 if (NT_STATUS_IS_OK(nt_status)) {
1707 nt_status = plaintext_auth_context->check_ntlm_password(
1708 plaintext_auth_context,
1712 (plaintext_auth_context->free)(
1713 &plaintext_auth_context);
1718 free_user_info(&user_info);
1720 if (!NT_STATUS_IS_OK(nt_status)) {
1721 nt_status = do_map_to_guest(nt_status, &server_info,
1725 if (!NT_STATUS_IS_OK(nt_status)) {
1726 data_blob_free(&nt_resp);
1727 data_blob_free(&lm_resp);
1728 data_blob_clear_free(&plaintext_password);
1729 reply_nterror(req, nt_status_squash(nt_status));
1730 END_PROFILE(SMBsesssetupX);
1734 /* Ensure we can't possible take a code path leading to a
1737 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1738 END_PROFILE(SMBsesssetupX);
1742 if (!server_info->ptok) {
1743 nt_status = create_local_token(server_info);
1745 if (!NT_STATUS_IS_OK(nt_status)) {
1746 DEBUG(10, ("create_local_token failed: %s\n",
1747 nt_errstr(nt_status)));
1748 data_blob_free(&nt_resp);
1749 data_blob_free(&lm_resp);
1750 data_blob_clear_free(&plaintext_password);
1751 reply_nterror(req, nt_status_squash(nt_status));
1752 END_PROFILE(SMBsesssetupX);
1757 data_blob_clear_free(&plaintext_password);
1759 /* it's ok - setup a reply */
1760 reply_outbuf(req, 3, 0);
1761 if (Protocol >= PROTOCOL_NT1) {
1762 push_signature(&req->outbuf);
1763 /* perhaps grab OS version here?? */
1766 if (server_info->guest) {
1767 SSVAL(req->outbuf,smb_vwv2,1);
1770 /* register the name and uid as being validated, so further connections
1771 to a uid can get through without a password, on the same VC */
1773 if (lp_security() == SEC_SHARE) {
1774 sess_vuid = UID_FIELD_INVALID;
1775 TALLOC_FREE(server_info);
1777 /* Ignore the initial vuid. */
1778 sess_vuid = register_initial_vuid();
1779 if (sess_vuid == UID_FIELD_INVALID) {
1780 data_blob_free(&nt_resp);
1781 data_blob_free(&lm_resp);
1782 reply_nterror(req, nt_status_squash(
1783 NT_STATUS_LOGON_FAILURE));
1784 END_PROFILE(SMBsesssetupX);
1787 /* register_existing_vuid keeps the server info */
1788 sess_vuid = register_existing_vuid(sess_vuid,
1790 nt_resp.data ? nt_resp : lm_resp,
1792 if (sess_vuid == UID_FIELD_INVALID) {
1793 data_blob_free(&nt_resp);
1794 data_blob_free(&lm_resp);
1795 reply_nterror(req, nt_status_squash(
1796 NT_STATUS_LOGON_FAILURE));
1797 END_PROFILE(SMBsesssetupX);
1801 /* current_user_info is changed on new vuid */
1802 reload_services( True );
1804 sessionsetup_start_signing_engine(server_info, req->inbuf);
1807 data_blob_free(&nt_resp);
1808 data_blob_free(&lm_resp);
1810 SSVAL(req->outbuf,smb_uid,sess_vuid);
1811 SSVAL(req->inbuf,smb_uid,sess_vuid);
1813 if (!done_sesssetup)
1814 max_send = MIN(max_send,smb_bufsize);
1816 done_sesssetup = True;
1818 END_PROFILE(SMBsesssetupX);