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)
1168 const char *native_os;
1169 const char *native_lanman;
1170 const char *primary_domain;
1172 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1173 enum remote_arch_types ra_type = get_remote_arch();
1174 int vuid = req->vuid;
1175 user_struct *vuser = NULL;
1176 NTSTATUS status = NT_STATUS_OK;
1177 uint16 smbpid = req->smbpid;
1179 DEBUG(3,("Doing spnego session setup\n"));
1181 if (global_client_caps == 0) {
1182 global_client_caps = IVAL(req->vwv+10, 0);
1184 if (!(global_client_caps & CAP_STATUS32)) {
1185 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1192 if (data_blob_len == 0) {
1193 /* an invalid request */
1194 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1198 bufrem = smbreq_bufrem(req, p);
1199 /* pull the spnego blob */
1200 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1203 file_save("negotiate.dat", blob1.data, blob1.length);
1206 p2 = (char *)req->buf + data_blob_len;
1208 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1210 native_os = tmp ? tmp : "";
1212 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1214 native_lanman = tmp ? tmp : "";
1216 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1218 primary_domain = tmp ? tmp : "";
1220 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1221 native_os, native_lanman, primary_domain));
1223 if ( ra_type == RA_WIN2K ) {
1224 /* Vista sets neither the OS or lanman strings */
1226 if ( !strlen(native_os) && !strlen(native_lanman) )
1227 set_remote_arch(RA_VISTA);
1229 /* Windows 2003 doesn't set the native lanman string,
1230 but does set primary domain which is a bug I think */
1232 if ( !strlen(native_lanman) ) {
1233 ra_lanman_string( primary_domain );
1235 ra_lanman_string( native_lanman );
1239 /* Did we get a valid vuid ? */
1240 if (!is_partial_auth_vuid(vuid)) {
1241 /* No, then try and see if this is an intermediate sessionsetup
1242 * for a large SPNEGO packet. */
1243 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1245 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1246 "pending vuid %u\n",
1247 (unsigned int)pad->vuid ));
1252 /* Do we have a valid vuid now ? */
1253 if (!is_partial_auth_vuid(vuid)) {
1254 /* No, start a new authentication setup. */
1255 vuid = register_initial_vuid();
1256 if (vuid == UID_FIELD_INVALID) {
1257 data_blob_free(&blob1);
1258 reply_nterror(req, nt_status_squash(
1259 NT_STATUS_INVALID_PARAMETER));
1264 vuser = get_partial_auth_user_struct(vuid);
1265 /* This MUST be valid. */
1267 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1270 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1271 * sessionsetup requests as the Windows limit on the security blob
1272 * field is 4k. Bug #4400. JRA.
1275 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1276 if (!NT_STATUS_IS_OK(status)) {
1277 if (!NT_STATUS_EQUAL(status,
1278 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1279 /* Real error - kill the intermediate vuid */
1280 invalidate_vuid(vuid);
1282 data_blob_free(&blob1);
1283 reply_nterror(req, nt_status_squash(status));
1287 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1289 /* its a negTokenTarg packet */
1291 reply_spnego_negotiate(req, vuid, blob1,
1292 &vuser->auth_ntlmssp_state);
1293 data_blob_free(&blob1);
1297 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1299 /* its a auth packet */
1301 reply_spnego_auth(req, vuid, blob1,
1302 &vuser->auth_ntlmssp_state);
1303 data_blob_free(&blob1);
1307 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1310 if (!vuser->auth_ntlmssp_state) {
1311 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1312 if (!NT_STATUS_IS_OK(status)) {
1313 /* Kill the intermediate vuid */
1314 invalidate_vuid(vuid);
1315 data_blob_free(&blob1);
1316 reply_nterror(req, nt_status_squash(status));
1321 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1324 data_blob_free(&blob1);
1326 reply_spnego_ntlmssp(req, vuid,
1327 &vuser->auth_ntlmssp_state,
1328 &chal, status, OID_NTLMSSP, false);
1329 data_blob_free(&chal);
1333 /* what sort of packet is this? */
1334 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1336 data_blob_free(&blob1);
1338 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1341 /****************************************************************************
1342 On new VC == 0, shutdown *all* old connections and users.
1343 It seems that only NT4.x does this. At W2K and above (XP etc.).
1344 a new session setup with VC==0 is ignored.
1345 ****************************************************************************/
1347 static int shutdown_other_smbds(struct db_record *rec,
1348 const struct connections_key *key,
1349 const struct connections_data *crec,
1352 const char *ip = (const char *)private_data;
1354 if (!process_exists(crec->pid)) {
1358 if (procid_is_me(&crec->pid)) {
1362 if (strcmp(ip, crec->addr) != 0) {
1366 DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
1367 "(IP %s)\n", procid_to_pid(&crec->pid), ip));
1369 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1374 static void setup_new_vc_session(void)
1376 char addr[INET6_ADDRSTRLEN];
1378 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1379 "compatible we would close all old resources.\n"));
1382 invalidate_all_vuids();
1384 if (lp_reset_on_zero_vc()) {
1385 connections_forall(shutdown_other_smbds,
1386 CONST_DISCARD(void *,
1387 client_addr(get_client_fd(),addr,sizeof(addr))));
1391 /****************************************************************************
1392 Reply to a session setup command.
1393 ****************************************************************************/
1395 void reply_sesssetup_and_X(struct smb_request *req)
1401 DATA_BLOB plaintext_password;
1404 fstring sub_user; /* Sainitised username for substituion */
1406 const char *native_os;
1407 const char *native_lanman;
1408 const char *primary_domain;
1409 static bool done_sesssetup = False;
1410 auth_usersupplied_info *user_info = NULL;
1411 auth_serversupplied_info *server_info = NULL;
1412 uint16 smb_flag2 = req->flags2;
1416 bool doencrypt = global_encrypted_passwords_negotiated;
1418 START_PROFILE(SMBsesssetupX);
1420 ZERO_STRUCT(lm_resp);
1421 ZERO_STRUCT(nt_resp);
1422 ZERO_STRUCT(plaintext_password);
1424 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1426 /* a SPNEGO session setup has 12 command words, whereas a normal
1427 NT1 session setup has 13. See the cifs spec. */
1428 if (req->wct == 12 &&
1429 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1431 if (!global_spnego_negotiated) {
1432 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1433 "at SPNEGO session setup when it was not "
1435 reply_nterror(req, nt_status_squash(
1436 NT_STATUS_LOGON_FAILURE));
1437 END_PROFILE(SMBsesssetupX);
1441 if (SVAL(req->vwv+4, 0) == 0) {
1442 setup_new_vc_session();
1445 reply_sesssetup_and_X_spnego(req);
1446 END_PROFILE(SMBsesssetupX);
1450 smb_bufsize = SVAL(req->vwv+2, 0);
1452 if (Protocol < PROTOCOL_NT1) {
1453 uint16 passlen1 = SVAL(req->vwv+7, 0);
1455 /* Never do NT status codes with protocols before NT1 as we
1456 * don't get client caps. */
1457 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1459 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1460 reply_nterror(req, nt_status_squash(
1461 NT_STATUS_INVALID_PARAMETER));
1462 END_PROFILE(SMBsesssetupX);
1467 lm_resp = data_blob(req->buf, passlen1);
1469 plaintext_password = data_blob(req->buf, passlen1+1);
1470 /* Ensure null termination */
1471 plaintext_password.data[passlen1] = 0;
1474 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1475 req->buf + passlen1, STR_TERMINATE);
1476 user = tmp ? tmp : "";
1481 uint16 passlen1 = SVAL(req->vwv+7, 0);
1482 uint16 passlen2 = SVAL(req->vwv+8, 0);
1483 enum remote_arch_types ra_type = get_remote_arch();
1484 const uint8_t *p = req->buf;
1485 const uint8_t *save_p = req->buf;
1489 if(global_client_caps == 0) {
1490 global_client_caps = IVAL(req->vwv+11, 0);
1492 if (!(global_client_caps & CAP_STATUS32)) {
1493 remove_from_common_flags2(
1494 FLAGS2_32_BIT_ERROR_CODES);
1497 /* client_caps is used as final determination if
1498 * client is NT or Win95. This is needed to return
1499 * the correct error codes in some circumstances.
1502 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1503 ra_type == RA_WIN95) {
1504 if(!(global_client_caps & (CAP_NT_SMBS|
1506 set_remote_arch( RA_WIN95);
1512 /* both Win95 and WinNT stuff up the password
1513 * lengths for non-encrypting systems. Uggh.
1515 if passlen1==24 its a win95 system, and its setting
1516 the password length incorrectly. Luckily it still
1517 works with the default code because Win95 will null
1518 terminate the password anyway
1520 if passlen1>0 and passlen2>0 then maybe its a NT box
1521 and its setting passlen2 to some random value which
1522 really stuffs things up. we need to fix that one. */
1524 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1530 /* check for nasty tricks */
1531 if (passlen1 > MAX_PASS_LEN
1532 || passlen1 > smbreq_bufrem(req, p)) {
1533 reply_nterror(req, nt_status_squash(
1534 NT_STATUS_INVALID_PARAMETER));
1535 END_PROFILE(SMBsesssetupX);
1539 if (passlen2 > MAX_PASS_LEN
1540 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1541 reply_nterror(req, nt_status_squash(
1542 NT_STATUS_INVALID_PARAMETER));
1543 END_PROFILE(SMBsesssetupX);
1547 /* Save the lanman2 password and the NT md4 password. */
1549 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1554 lm_resp = data_blob(p, passlen1);
1555 nt_resp = data_blob(p+passlen1, passlen2);
1556 } else if (lp_security() != SEC_SHARE) {
1558 * In share level we should ignore any passwords, so
1559 * only read them if we're not.
1562 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1564 if (unic && (passlen2 == 0) && passlen1) {
1565 /* Only a ascii plaintext password was sent. */
1566 (void)srvstr_pull_talloc(talloc_tos(),
1572 STR_TERMINATE|STR_ASCII);
1574 (void)srvstr_pull_talloc(talloc_tos(),
1579 unic ? passlen2 : passlen1,
1583 reply_nterror(req, nt_status_squash(
1584 NT_STATUS_INVALID_PARAMETER));
1585 END_PROFILE(SMBsesssetupX);
1588 plaintext_password = data_blob(pass, strlen(pass)+1);
1591 p += passlen1 + passlen2;
1593 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1595 user = tmp ? tmp : "";
1597 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1599 domain = tmp ? tmp : "";
1601 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1603 native_os = tmp ? tmp : "";
1605 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1607 native_lanman = tmp ? tmp : "";
1609 /* not documented or decoded by Ethereal but there is one more
1610 * string in the extra bytes which is the same as the
1611 * PrimaryDomain when using extended security. Windows NT 4
1612 * and 2003 use this string to store the native lanman string.
1613 * Windows 9x does not include a string here at all so we have
1614 * to check if we have any extra bytes left */
1616 byte_count = SVAL(req->vwv+13, 0);
1617 if ( PTR_DIFF(p, save_p) < byte_count) {
1618 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1620 primary_domain = tmp ? tmp : "";
1622 primary_domain = talloc_strdup(talloc_tos(), "null");
1625 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1626 "PrimaryDomain=[%s]\n",
1627 domain, native_os, native_lanman, primary_domain));
1629 if ( ra_type == RA_WIN2K ) {
1630 if ( strlen(native_lanman) == 0 )
1631 ra_lanman_string( primary_domain );
1633 ra_lanman_string( native_lanman );
1638 if (SVAL(req->vwv+4, 0) == 0) {
1639 setup_new_vc_session();
1642 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1643 domain, user, get_remote_machine_name()));
1646 if (global_spnego_negotiated) {
1648 /* This has to be here, because this is a perfectly
1649 * valid behaviour for guest logons :-( */
1651 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1652 "at 'normal' session setup after "
1653 "negotiating spnego.\n"));
1654 reply_nterror(req, nt_status_squash(
1655 NT_STATUS_LOGON_FAILURE));
1656 END_PROFILE(SMBsesssetupX);
1659 fstrcpy(sub_user, user);
1661 fstrcpy(sub_user, lp_guestaccount());
1664 sub_set_smb_name(sub_user);
1666 reload_services(True);
1668 if (lp_security() == SEC_SHARE) {
1669 /* In share level we should ignore any passwords */
1671 data_blob_free(&lm_resp);
1672 data_blob_free(&nt_resp);
1673 data_blob_clear_free(&plaintext_password);
1675 map_username(sub_user);
1676 add_session_user(sub_user);
1677 add_session_workgroup(domain);
1678 /* Then force it to null for the benfit of the code below */
1684 nt_status = check_guest_password(&server_info);
1686 } else if (doencrypt) {
1687 if (!negprot_global_auth_context) {
1688 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1689 "session setup without negprot denied!\n"));
1690 reply_nterror(req, nt_status_squash(
1691 NT_STATUS_LOGON_FAILURE));
1692 END_PROFILE(SMBsesssetupX);
1695 nt_status = make_user_info_for_reply_enc(&user_info, user,
1698 if (NT_STATUS_IS_OK(nt_status)) {
1699 nt_status = negprot_global_auth_context->check_ntlm_password(
1700 negprot_global_auth_context,
1705 struct auth_context *plaintext_auth_context = NULL;
1708 nt_status = make_auth_context_subsystem(
1709 &plaintext_auth_context);
1711 if (NT_STATUS_IS_OK(nt_status)) {
1712 chal = plaintext_auth_context->get_ntlm_challenge(
1713 plaintext_auth_context);
1715 if (!make_user_info_for_reply(&user_info,
1717 plaintext_password)) {
1718 nt_status = NT_STATUS_NO_MEMORY;
1721 if (NT_STATUS_IS_OK(nt_status)) {
1722 nt_status = plaintext_auth_context->check_ntlm_password(
1723 plaintext_auth_context,
1727 (plaintext_auth_context->free)(
1728 &plaintext_auth_context);
1733 free_user_info(&user_info);
1735 if (!NT_STATUS_IS_OK(nt_status)) {
1736 nt_status = do_map_to_guest(nt_status, &server_info,
1740 if (!NT_STATUS_IS_OK(nt_status)) {
1741 data_blob_free(&nt_resp);
1742 data_blob_free(&lm_resp);
1743 data_blob_clear_free(&plaintext_password);
1744 reply_nterror(req, nt_status_squash(nt_status));
1745 END_PROFILE(SMBsesssetupX);
1749 /* Ensure we can't possible take a code path leading to a
1752 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1753 END_PROFILE(SMBsesssetupX);
1757 if (!server_info->ptok) {
1758 nt_status = create_local_token(server_info);
1760 if (!NT_STATUS_IS_OK(nt_status)) {
1761 DEBUG(10, ("create_local_token failed: %s\n",
1762 nt_errstr(nt_status)));
1763 data_blob_free(&nt_resp);
1764 data_blob_free(&lm_resp);
1765 data_blob_clear_free(&plaintext_password);
1766 reply_nterror(req, nt_status_squash(nt_status));
1767 END_PROFILE(SMBsesssetupX);
1772 data_blob_clear_free(&plaintext_password);
1774 /* it's ok - setup a reply */
1775 reply_outbuf(req, 3, 0);
1776 if (Protocol >= PROTOCOL_NT1) {
1777 push_signature(&req->outbuf);
1778 /* perhaps grab OS version here?? */
1781 if (server_info->guest) {
1782 SSVAL(req->outbuf,smb_vwv2,1);
1785 /* register the name and uid as being validated, so further connections
1786 to a uid can get through without a password, on the same VC */
1788 if (lp_security() == SEC_SHARE) {
1789 sess_vuid = UID_FIELD_INVALID;
1790 TALLOC_FREE(server_info);
1792 /* Ignore the initial vuid. */
1793 sess_vuid = register_initial_vuid();
1794 if (sess_vuid == UID_FIELD_INVALID) {
1795 data_blob_free(&nt_resp);
1796 data_blob_free(&lm_resp);
1797 reply_nterror(req, nt_status_squash(
1798 NT_STATUS_LOGON_FAILURE));
1799 END_PROFILE(SMBsesssetupX);
1802 /* register_existing_vuid keeps the server info */
1803 sess_vuid = register_existing_vuid(sess_vuid,
1805 nt_resp.data ? nt_resp : lm_resp,
1807 if (sess_vuid == UID_FIELD_INVALID) {
1808 data_blob_free(&nt_resp);
1809 data_blob_free(&lm_resp);
1810 reply_nterror(req, nt_status_squash(
1811 NT_STATUS_LOGON_FAILURE));
1812 END_PROFILE(SMBsesssetupX);
1816 /* current_user_info is changed on new vuid */
1817 reload_services( True );
1819 sessionsetup_start_signing_engine(server_info, req->inbuf);
1822 data_blob_free(&nt_resp);
1823 data_blob_free(&lm_resp);
1825 SSVAL(req->outbuf,smb_uid,sess_vuid);
1826 SSVAL(req->inbuf,smb_uid,sess_vuid);
1828 if (!done_sesssetup)
1829 max_send = MIN(max_send,smb_bufsize);
1831 done_sesssetup = True;
1833 END_PROFILE(SMBsesssetupX);