2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "smbd/globals.h"
27 #include "../libcli/auth/spnego.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "librpc/gen_ndr/messaging.h"
31 #include "libads/kerberos_proto.h"
33 /* For split krb5 SPNEGO blobs. */
34 struct pending_auth_data {
35 struct pending_auth_data *prev, *next;
36 uint16 vuid; /* Tag for this entry. */
37 uint16 smbpid; /* Alternate tag for this entry. */
39 DATA_BLOB partial_data;
43 on a logon error possibly map the error to success if "map to guest"
46 NTSTATUS do_map_to_guest(NTSTATUS status,
47 struct auth_serversupplied_info **server_info,
48 const char *user, const char *domain)
50 user = user ? user : "";
51 domain = domain ? domain : "";
53 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
54 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
55 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
56 DEBUG(3,("No such user %s [%s] - using guest account\n",
58 status = make_server_info_guest(NULL, server_info);
62 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
63 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
64 DEBUG(3,("Registered username %s for guest access\n",
66 status = make_server_info_guest(NULL, server_info);
73 /****************************************************************************
74 Add the standard 'Samba' signature to the end of the session setup.
75 ****************************************************************************/
77 static int push_signature(uint8 **outbuf)
84 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
86 if (tmp == -1) return -1;
89 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
90 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
94 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
97 if (tmp == -1) return -1;
100 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
102 if (tmp == -1) return -1;
108 /****************************************************************************
109 Send a security blob via a session setup reply.
110 ****************************************************************************/
112 static void reply_sesssetup_blob(struct smb_request *req,
116 if (!NT_STATUS_IS_OK(nt_status) &&
117 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
118 reply_nterror(req, nt_status_squash(nt_status));
122 nt_status = nt_status_squash(nt_status);
123 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
124 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
125 SSVAL(req->outbuf, smb_vwv3, blob.length);
127 if ((message_push_blob(&req->outbuf, blob) == -1)
128 || (push_signature(&req->outbuf) == -1)) {
129 reply_nterror(req, NT_STATUS_NO_MEMORY);
133 /****************************************************************************
134 Do a 'guest' logon, getting back the
135 ****************************************************************************/
137 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
139 struct auth_context *auth_context;
140 struct auth_usersupplied_info *user_info = NULL;
143 unsigned char chal[8];
147 DEBUG(3,("Got anonymous request\n"));
149 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
154 if (!make_user_info_guest(&user_info)) {
155 TALLOC_FREE(auth_context);
156 return NT_STATUS_NO_MEMORY;
159 nt_status = auth_context->check_ntlm_password(auth_context,
162 TALLOC_FREE(auth_context);
163 free_user_info(&user_info);
171 /* Experiment that failed. See "only happens with a KDC" comment below. */
172 /****************************************************************************
173 Cerate a clock skew error blob for a Windows client.
174 ****************************************************************************/
176 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
178 krb5_context context = NULL;
179 krb5_error_code kerr = 0;
181 krb5_principal host_princ = NULL;
182 char *host_princ_s = NULL;
185 *pblob_out = data_blob_null;
187 initialize_krb5_error_table();
188 kerr = krb5_init_context(&context);
192 /* Create server principal. */
193 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
197 strlower_m(host_princ_s);
199 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
201 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
202 "for name %s: Error %s\n",
203 host_princ_s, error_message(kerr) ));
207 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
210 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
211 "failed: Error %s\n",
212 error_message(kerr) ));
216 *pblob_out = data_blob(reply.data, reply.length);
217 kerberos_free_data_contents(context,&reply);
223 SAFE_FREE(host_princ_s);
226 krb5_free_principal(context, host_princ);
228 krb5_free_context(context);
233 /****************************************************************************
234 Reply to a session setup spnego negotiate packet for kerberos.
235 ****************************************************************************/
237 static void reply_spnego_kerberos(struct smb_request *req,
241 bool *p_invalidate_vuid)
245 char *client, *p, *domain;
246 fstring netbios_domain_name;
249 int sess_vuid = req->vuid;
250 NTSTATUS ret = NT_STATUS_OK;
251 DATA_BLOB ap_rep, ap_rep_wrapped, response;
252 struct auth_serversupplied_info *server_info = NULL;
253 DATA_BLOB session_key = data_blob_null;
255 DATA_BLOB nullblob = data_blob_null;
256 fstring real_username;
257 bool map_domainuser_to_guest = False;
258 bool username_was_mapped;
259 struct PAC_LOGON_INFO *logon_info = NULL;
260 struct smbd_server_connection *sconn = req->sconn;
264 ZERO_STRUCT(ap_rep_wrapped);
265 ZERO_STRUCT(response);
267 /* Normally we will always invalidate the intermediate vuid. */
268 *p_invalidate_vuid = True;
270 mem_ctx = talloc_init("reply_spnego_kerberos");
271 if (mem_ctx == NULL) {
272 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
276 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
277 talloc_destroy(mem_ctx);
278 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
282 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
283 &client, &logon_info, &ap_rep,
286 data_blob_free(&ticket);
288 if (!NT_STATUS_IS_OK(ret)) {
290 /* Experiment that failed.
291 * See "only happens with a KDC" comment below. */
293 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
296 * Windows in this case returns
297 * NT_STATUS_MORE_PROCESSING_REQUIRED
298 * with a negTokenTarg blob containing an krb5_error
299 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
300 * The client then fixes its clock and continues rather
301 * than giving an error. JRA.
302 * -- Looks like this only happens with a KDC. JRA.
305 bool ok = make_krb5_skew_error(&ap_rep);
307 talloc_destroy(mem_ctx);
308 return ERROR_NT(nt_status_squash(
309 NT_STATUS_LOGON_FAILURE));
311 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
313 response = spnego_gen_auth_response(&ap_rep_wrapped,
314 ret, OID_KERBEROS5_OLD);
315 reply_sesssetup_blob(conn, inbuf, outbuf, response,
316 NT_STATUS_MORE_PROCESSING_REQUIRED);
319 * In this one case we don't invalidate the
320 * intermediate vuid as we're expecting the client
321 * to re-use it for the next sessionsetupX packet. JRA.
324 *p_invalidate_vuid = False;
326 data_blob_free(&ap_rep);
327 data_blob_free(&ap_rep_wrapped);
328 data_blob_free(&response);
329 talloc_destroy(mem_ctx);
330 return -1; /* already replied */
333 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
334 ret = NT_STATUS_LOGON_FAILURE;
337 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
339 talloc_destroy(mem_ctx);
340 reply_nterror(req, nt_status_squash(ret));
344 DEBUG(3,("Ticket name is [%s]\n", client));
346 p = strchr_m(client, '@');
348 DEBUG(3,("Doesn't look like a valid principal\n"));
349 data_blob_free(&ap_rep);
350 data_blob_free(&session_key);
351 talloc_destroy(mem_ctx);
352 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
358 /* save the PAC data if we have it */
361 netsamlogon_cache_store( client, &logon_info->info3 );
364 if (!strequal(p+1, lp_realm())) {
365 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
366 if (!lp_allow_trusted_domains()) {
367 data_blob_free(&ap_rep);
368 data_blob_free(&session_key);
369 talloc_destroy(mem_ctx);
370 reply_nterror(req, nt_status_squash(
371 NT_STATUS_LOGON_FAILURE));
376 /* this gives a fully qualified user name (ie. with full realm).
377 that leads to very long usernames, but what else can we do? */
381 if (logon_info && logon_info->info3.base.domain.string) {
382 fstrcpy(netbios_domain_name,
383 logon_info->info3.base.domain.string);
384 domain = netbios_domain_name;
385 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
389 /* If we have winbind running, we can (and must) shorten the
390 username by using the short netbios name. Otherwise we will
391 have inconsistent user names. With Kerberos, we get the
392 fully qualified realm, with ntlmssp we get the short
393 name. And even w2k3 does use ntlmssp if you for example
394 connect to an ip address. */
397 struct wbcDomainInfo *info = NULL;
399 DEBUG(10, ("Mapping [%s] to short name\n", domain));
401 wbc_status = wbcDomainInfo(domain, &info);
403 if (WBC_ERROR_IS_OK(wbc_status)) {
405 fstrcpy(netbios_domain_name,
409 domain = netbios_domain_name;
410 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
412 DEBUG(3, ("Could not find short name: %s\n",
413 wbcErrorString(wbc_status)));
417 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
419 /* lookup the passwd struct, create a new user if necessary */
421 username_was_mapped = map_username(user);
423 pw = smb_getpwnam( mem_ctx, user, real_username, True );
426 /* if a real user check pam account restrictions */
427 /* only really perfomed if "obey pam restriction" is true */
428 /* do this before an eventual mapping to guest occurs */
429 ret = smb_pam_accountcheck(pw->pw_name);
430 if ( !NT_STATUS_IS_OK(ret)) {
431 DEBUG(1,("PAM account restriction "
432 "prevents user login\n"));
433 data_blob_free(&ap_rep);
434 data_blob_free(&session_key);
435 TALLOC_FREE(mem_ctx);
436 reply_nterror(req, nt_status_squash(ret));
443 /* this was originally the behavior of Samba 2.2, if a user
444 did not have a local uid but has been authenticated, then
445 map them to a guest account */
447 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
448 map_domainuser_to_guest = True;
449 fstrcpy(user,lp_guestaccount());
450 pw = smb_getpwnam( mem_ctx, user, real_username, True );
453 /* extra sanity check that the guest account is valid */
456 DEBUG(1,("Username %s is invalid on this system\n",
458 data_blob_free(&ap_rep);
459 data_blob_free(&session_key);
460 TALLOC_FREE(mem_ctx);
461 reply_nterror(req, nt_status_squash(
462 NT_STATUS_LOGON_FAILURE));
467 /* setup the string used by %U */
469 sub_set_smb_name( real_username );
470 reload_services(True);
472 if ( map_domainuser_to_guest ) {
473 make_server_info_guest(NULL, &server_info);
474 } else if (logon_info) {
475 /* pass the unmapped username here since map_username()
476 will be called again from inside make_server_info_info3() */
478 ret = make_server_info_info3(mem_ctx, client, domain,
479 &server_info, &logon_info->info3);
480 if ( !NT_STATUS_IS_OK(ret) ) {
481 DEBUG(1,("make_server_info_info3 failed: %s!\n",
483 data_blob_free(&ap_rep);
484 data_blob_free(&session_key);
485 TALLOC_FREE(mem_ctx);
486 reply_nterror(req, nt_status_squash(ret));
492 * We didn't get a PAC, we have to make up the user
493 * ourselves. Try to ask the pdb backend to provide
494 * SID consistency with ntlmssp session setup
496 struct samu *sampass;
498 sampass = samu_new(talloc_tos());
499 if (sampass == NULL) {
500 ret = NT_STATUS_NO_MEMORY;
501 data_blob_free(&ap_rep);
502 data_blob_free(&session_key);
503 TALLOC_FREE(mem_ctx);
504 reply_nterror(req, nt_status_squash(ret));
508 if (pdb_getsampwnam(sampass, real_username)) {
509 DEBUG(10, ("found user %s in passdb, calling "
510 "make_server_info_sam\n", real_username));
511 ret = make_server_info_sam(&server_info, sampass);
512 TALLOC_FREE(sampass);
515 * User not in passdb, make it up artificially
517 TALLOC_FREE(sampass);
518 DEBUG(10, ("didn't find user %s in passdb, calling "
519 "make_server_info_pw\n", real_username));
520 ret = make_server_info_pw(&server_info, real_username,
524 if ( !NT_STATUS_IS_OK(ret) ) {
525 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
527 data_blob_free(&ap_rep);
528 data_blob_free(&session_key);
529 TALLOC_FREE(mem_ctx);
530 reply_nterror(req, nt_status_squash(ret));
534 /* make_server_info_pw does not set the domain. Without this
535 * we end up with the local netbios name in substitutions for
538 if (server_info->info3 != NULL) {
539 server_info->info3->base.domain.string =
540 talloc_strdup(server_info->info3, domain);
544 server_info->nss_token |= username_was_mapped;
546 /* we need to build the token for the user. make_server_info_guest()
549 if ( !server_info->ptok ) {
550 ret = create_local_token( server_info );
551 if ( !NT_STATUS_IS_OK(ret) ) {
552 DEBUG(10,("failed to create local token: %s\n",
554 data_blob_free(&ap_rep);
555 data_blob_free(&session_key);
556 TALLOC_FREE( mem_ctx );
557 TALLOC_FREE( server_info );
558 reply_nterror(req, nt_status_squash(ret));
563 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
564 sess_vuid = register_initial_vuid(sconn);
567 data_blob_free(&server_info->user_session_key);
568 server_info->user_session_key = session_key;
569 talloc_steal(server_info, session_key.data);
571 session_key = data_blob_null;
573 /* register_existing_vuid keeps the server info */
574 /* register_existing_vuid takes ownership of session_key on success,
575 * no need to free after this on success. A better interface would copy
578 sess_vuid = register_existing_vuid(sconn,
584 reply_outbuf(req, 4, 0);
585 SSVAL(req->outbuf,smb_uid,sess_vuid);
587 if (sess_vuid == UID_FIELD_INVALID ) {
588 ret = NT_STATUS_LOGON_FAILURE;
590 /* current_user_info is changed on new vuid */
591 reload_services( True );
593 SSVAL(req->outbuf, smb_vwv3, 0);
595 if (server_info->guest) {
596 SSVAL(req->outbuf,smb_vwv2,1);
599 SSVAL(req->outbuf, smb_uid, sess_vuid);
601 /* Successful logon. Keep this vuid. */
602 *p_invalidate_vuid = False;
605 /* wrap that up in a nice GSS-API wrapping */
606 if (NT_STATUS_IS_OK(ret)) {
607 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
610 ap_rep_wrapped = data_blob_null;
612 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
614 reply_sesssetup_blob(req, response, ret);
616 data_blob_free(&ap_rep);
617 data_blob_free(&ap_rep_wrapped);
618 data_blob_free(&response);
619 TALLOC_FREE(mem_ctx);
624 /****************************************************************************
625 Send a session setup reply, wrapped in SPNEGO.
626 Get vuid and check first.
627 End the NTLMSSP exchange context if we are OK/complete fail
628 This should be split into two functions, one to handle each
629 leg of the NTLM auth steps.
630 ***************************************************************************/
632 static void reply_spnego_ntlmssp(struct smb_request *req,
634 struct auth_ntlmssp_state **auth_ntlmssp_state,
635 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
639 bool do_invalidate = true;
641 struct auth_serversupplied_info *server_info = NULL;
642 struct smbd_server_connection *sconn = req->sconn;
644 if (NT_STATUS_IS_OK(nt_status)) {
645 nt_status = auth_ntlmssp_steal_server_info(talloc_tos(),
646 (*auth_ntlmssp_state), &server_info);
648 /* Note that this server_info won't have a session
649 * key. But for map to guest, that's exactly the right
650 * thing - we can't reasonably guess the key the
651 * client wants, as the password was wrong */
652 nt_status = do_map_to_guest(nt_status,
654 auth_ntlmssp_get_username(*auth_ntlmssp_state),
655 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
658 reply_outbuf(req, 4, 0);
660 SSVAL(req->outbuf, smb_uid, vuid);
662 if (NT_STATUS_IS_OK(nt_status)) {
663 DATA_BLOB nullblob = data_blob_null;
665 if (!is_partial_auth_vuid(sconn, vuid)) {
666 nt_status = NT_STATUS_LOGON_FAILURE;
670 /* register_existing_vuid keeps the server info */
671 if (register_existing_vuid(sconn, vuid,
672 server_info, nullblob,
673 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
675 /* The problem is, *auth_ntlmssp_state points
676 * into the vuser this will have
677 * talloc_free()'ed in
678 * register_existing_vuid() */
679 do_invalidate = false;
680 nt_status = NT_STATUS_LOGON_FAILURE;
684 /* current_user_info is changed on new vuid */
685 reload_services( True );
687 SSVAL(req->outbuf, smb_vwv3, 0);
689 if (server_info->guest) {
690 SSVAL(req->outbuf,smb_vwv2,1);
697 response = spnego_gen_auth_response(talloc_tos(),
701 response = *ntlmssp_blob;
704 reply_sesssetup_blob(req, response, nt_status);
706 data_blob_free(&response);
709 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
710 and the other end, that we are not finished yet. */
712 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
713 /* NB. This is *NOT* an error case. JRA */
715 TALLOC_FREE(*auth_ntlmssp_state);
716 if (!NT_STATUS_IS_OK(nt_status)) {
717 /* Kill the intermediate vuid */
718 invalidate_vuid(sconn, vuid);
724 /****************************************************************************
725 Is this a krb5 mechanism ?
726 ****************************************************************************/
728 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
730 DATA_BLOB *pblob_out,
733 char *OIDs[ASN1_MAX_OIDS];
735 NTSTATUS ret = NT_STATUS_OK;
737 *kerb_mechOID = NULL;
739 /* parse out the OIDs and the first sec blob */
740 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out)) {
741 return NT_STATUS_LOGON_FAILURE;
744 /* only look at the first OID for determining the mechToken --
745 according to RFC2478, we should choose the one we want
746 and renegotiate, but i smell a client bug here..
748 Problem observed when connecting to a member (samba box)
749 of an AD domain as a user in a Samba domain. Samba member
750 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
751 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
752 NTLMSSP mechtoken. --jerry */
755 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
756 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
757 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
758 if (*kerb_mechOID == NULL) {
759 ret = NT_STATUS_NO_MEMORY;
764 for (i=0;OIDs[i];i++) {
765 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
766 talloc_free(OIDs[i]);
771 /****************************************************************************
772 Fall back from krb5 to NTLMSSP.
773 ****************************************************************************/
775 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
780 reply_outbuf(req, 4, 0);
781 SSVAL(req->outbuf,smb_uid,vuid);
783 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
784 "but set to downgrade to NTLMSSP\n"));
786 response = spnego_gen_auth_response(talloc_tos(), NULL,
787 NT_STATUS_MORE_PROCESSING_REQUIRED,
789 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
790 data_blob_free(&response);
793 /****************************************************************************
794 Reply to a session setup spnego negotiate packet.
795 ****************************************************************************/
797 static void reply_spnego_negotiate(struct smb_request *req,
800 struct auth_ntlmssp_state **auth_ntlmssp_state)
804 char *kerb_mech = NULL;
806 struct smbd_server_connection *sconn = req->sconn;
808 status = parse_spnego_mechanisms(talloc_tos(),
809 blob1, &secblob, &kerb_mech);
810 if (!NT_STATUS_IS_OK(status)) {
811 /* Kill the intermediate vuid */
812 invalidate_vuid(sconn, vuid);
813 reply_nterror(req, nt_status_squash(status));
817 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
818 (unsigned long)secblob.length));
821 if (kerb_mech && ((lp_security()==SEC_ADS) ||
822 USE_KERBEROS_KEYTAB) ) {
823 bool destroy_vuid = True;
824 reply_spnego_kerberos(req, &secblob, kerb_mech,
825 vuid, &destroy_vuid);
826 data_blob_free(&secblob);
828 /* Kill the intermediate vuid */
829 invalidate_vuid(sconn, vuid);
831 TALLOC_FREE(kerb_mech);
836 if (*auth_ntlmssp_state) {
837 TALLOC_FREE(*auth_ntlmssp_state);
841 data_blob_free(&secblob);
842 /* The mechtoken is a krb5 ticket, but
843 * we need to fall back to NTLM. */
844 reply_spnego_downgrade_to_ntlmssp(req, vuid);
845 TALLOC_FREE(kerb_mech);
849 status = auth_ntlmssp_start(auth_ntlmssp_state);
850 if (!NT_STATUS_IS_OK(status)) {
851 /* Kill the intermediate vuid */
852 invalidate_vuid(sconn, vuid);
853 reply_nterror(req, nt_status_squash(status));
857 status = auth_ntlmssp_update(*auth_ntlmssp_state,
860 data_blob_free(&secblob);
862 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
863 &chal, status, OID_NTLMSSP, true);
865 data_blob_free(&chal);
867 /* already replied */
871 /****************************************************************************
872 Reply to a session setup spnego auth packet.
873 ****************************************************************************/
875 static void reply_spnego_auth(struct smb_request *req,
878 struct auth_ntlmssp_state **auth_ntlmssp_state)
880 DATA_BLOB auth = data_blob_null;
881 DATA_BLOB auth_reply = data_blob_null;
882 DATA_BLOB secblob = data_blob_null;
883 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
884 struct smbd_server_connection *sconn = req->sconn;
886 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
888 file_save("auth.dat", blob1.data, blob1.length);
890 /* Kill the intermediate vuid */
891 invalidate_vuid(sconn, vuid);
893 reply_nterror(req, nt_status_squash(
894 NT_STATUS_LOGON_FAILURE));
898 if (auth.data[0] == ASN1_APPLICATION(0)) {
899 /* Might be a second negTokenTarg packet */
900 char *kerb_mech = NULL;
902 status = parse_spnego_mechanisms(talloc_tos(),
903 auth, &secblob, &kerb_mech);
905 if (!NT_STATUS_IS_OK(status)) {
906 /* Kill the intermediate vuid */
907 invalidate_vuid(sconn, vuid);
908 reply_nterror(req, nt_status_squash(status));
912 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
913 (unsigned long)secblob.length));
915 if (kerb_mech && ((lp_security()==SEC_ADS) ||
916 USE_KERBEROS_KEYTAB)) {
917 bool destroy_vuid = True;
918 reply_spnego_kerberos(req, &secblob, kerb_mech,
919 vuid, &destroy_vuid);
920 data_blob_free(&secblob);
921 data_blob_free(&auth);
923 /* Kill the intermediate vuid */
924 invalidate_vuid(sconn, vuid);
926 TALLOC_FREE(kerb_mech);
930 /* Can't blunder into NTLMSSP auth if we have
934 /* Kill the intermediate vuid */
935 invalidate_vuid(sconn, vuid);
936 DEBUG(3,("reply_spnego_auth: network "
937 "misconfiguration, client sent us a "
938 "krb5 ticket and kerberos security "
940 reply_nterror(req, nt_status_squash(
941 NT_STATUS_LOGON_FAILURE));
942 TALLOC_FREE(kerb_mech);
946 /* If we get here it wasn't a negTokenTarg auth packet. */
947 data_blob_free(&secblob);
949 if (!*auth_ntlmssp_state) {
950 status = auth_ntlmssp_start(auth_ntlmssp_state);
951 if (!NT_STATUS_IS_OK(status)) {
952 /* Kill the intermediate vuid */
953 invalidate_vuid(sconn, vuid);
954 reply_nterror(req, nt_status_squash(status));
959 status = auth_ntlmssp_update(*auth_ntlmssp_state,
962 data_blob_free(&auth);
964 /* Don't send the mechid as we've already sent this (RFC4178). */
966 reply_spnego_ntlmssp(req, vuid,
968 &auth_reply, status, NULL, true);
970 data_blob_free(&auth_reply);
972 /* and tell smbd that we have already replied to this packet */
976 /****************************************************************************
977 Delete an entry on the list.
978 ****************************************************************************/
980 static void delete_partial_auth(struct smbd_server_connection *sconn,
981 struct pending_auth_data *pad)
986 DLIST_REMOVE(sconn->smb1.pd_list, pad);
987 data_blob_free(&pad->partial_data);
991 /****************************************************************************
992 Search for a partial SPNEGO auth fragment matching an smbpid.
993 ****************************************************************************/
995 static struct pending_auth_data *get_pending_auth_data(
996 struct smbd_server_connection *sconn,
999 struct pending_auth_data *pad;
1001 * NOTE: using the smbpid here is completely wrong...
1003 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
1005 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
1006 if (pad->smbpid == smbpid) {
1013 /****************************************************************************
1014 Check the size of an SPNEGO blob. If we need more return
1015 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1016 the blob to be more than 64k.
1017 ****************************************************************************/
1019 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1020 uint16 smbpid, uint16 vuid,
1023 struct pending_auth_data *pad = NULL;
1025 size_t needed_len = 0;
1027 pad = get_pending_auth_data(sconn, smbpid);
1029 /* Ensure we have some data. */
1030 if (pblob->length == 0) {
1031 /* Caller can cope. */
1032 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1033 delete_partial_auth(sconn, pad);
1034 return NT_STATUS_OK;
1037 /* Were we waiting for more data ? */
1040 size_t copy_len = MIN(65536, pblob->length);
1042 /* Integer wrap paranoia.... */
1044 if (pad->partial_data.length + copy_len <
1045 pad->partial_data.length ||
1046 pad->partial_data.length + copy_len < copy_len) {
1048 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1049 "pad->partial_data.length = %u, "
1051 (unsigned int)pad->partial_data.length,
1052 (unsigned int)copy_len ));
1054 delete_partial_auth(sconn, pad);
1055 return NT_STATUS_INVALID_PARAMETER;
1058 DEBUG(10,("check_spnego_blob_complete: "
1059 "pad->partial_data.length = %u, "
1060 "pad->needed_len = %u, "
1062 "pblob->length = %u,\n",
1063 (unsigned int)pad->partial_data.length,
1064 (unsigned int)pad->needed_len,
1065 (unsigned int)copy_len,
1066 (unsigned int)pblob->length ));
1068 tmp_blob = data_blob(NULL,
1069 pad->partial_data.length + copy_len);
1071 /* Concatenate the two (up to copy_len) bytes. */
1072 memcpy(tmp_blob.data,
1073 pad->partial_data.data,
1074 pad->partial_data.length);
1075 memcpy(tmp_blob.data + pad->partial_data.length,
1079 /* Replace the partial data. */
1080 data_blob_free(&pad->partial_data);
1081 pad->partial_data = tmp_blob;
1082 ZERO_STRUCT(tmp_blob);
1085 if (pblob->length >= pad->needed_len) {
1086 /* Yes, replace pblob. */
1087 data_blob_free(pblob);
1088 *pblob = pad->partial_data;
1089 ZERO_STRUCT(pad->partial_data);
1090 delete_partial_auth(sconn, pad);
1091 return NT_STATUS_OK;
1094 /* Still need more data. */
1095 pad->needed_len -= copy_len;
1096 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1099 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1100 (pblob->data[0] != ASN1_CONTEXT(1))) {
1101 /* Not something we can determine the
1104 return NT_STATUS_OK;
1107 /* This is a new SPNEGO sessionsetup - see if
1108 * the data given in this blob is enough.
1111 data = asn1_init(NULL);
1113 return NT_STATUS_NO_MEMORY;
1116 asn1_load(data, *pblob);
1117 asn1_start_tag(data, pblob->data[0]);
1118 if (data->has_error || data->nesting == NULL) {
1120 /* Let caller catch. */
1121 return NT_STATUS_OK;
1124 /* Integer wrap paranoia.... */
1126 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1127 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1129 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1130 "data.nesting->taglen = %u, "
1131 "data.nesting->start = %u\n",
1132 (unsigned int)data->nesting->taglen,
1133 (unsigned int)data->nesting->start ));
1136 return NT_STATUS_INVALID_PARAMETER;
1139 /* Total length of the needed asn1 is the tag length
1140 * plus the current offset. */
1142 needed_len = data->nesting->taglen + data->nesting->start;
1145 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1146 "pblob->length = %u\n",
1147 (unsigned int)needed_len,
1148 (unsigned int)pblob->length ));
1150 if (needed_len <= pblob->length) {
1151 /* Nothing to do - blob is complete. */
1152 return NT_STATUS_OK;
1155 /* Refuse the blob if it's bigger than 64k. */
1156 if (needed_len > 65536) {
1157 DEBUG(2,("check_spnego_blob_complete: needed_len "
1159 (unsigned int)needed_len ));
1160 return NT_STATUS_INVALID_PARAMETER;
1163 /* We must store this blob until complete. */
1164 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1165 return NT_STATUS_NO_MEMORY;
1167 pad->needed_len = needed_len - pblob->length;
1168 pad->partial_data = data_blob(pblob->data, pblob->length);
1169 if (pad->partial_data.data == NULL) {
1171 return NT_STATUS_NO_MEMORY;
1173 pad->smbpid = smbpid;
1175 DLIST_ADD(sconn->smb1.pd_list, pad);
1177 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1180 /****************************************************************************
1181 Reply to a session setup command.
1182 conn POINTER CAN BE NULL HERE !
1183 ****************************************************************************/
1185 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1191 const char *native_os;
1192 const char *native_lanman;
1193 const char *primary_domain;
1195 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1196 enum remote_arch_types ra_type = get_remote_arch();
1197 int vuid = req->vuid;
1198 user_struct *vuser = NULL;
1199 NTSTATUS status = NT_STATUS_OK;
1200 uint16 smbpid = req->smbpid;
1201 struct smbd_server_connection *sconn = req->sconn;
1203 DEBUG(3,("Doing spnego session setup\n"));
1205 if (global_client_caps == 0) {
1206 global_client_caps = IVAL(req->vwv+10, 0);
1208 if (!(global_client_caps & CAP_STATUS32)) {
1209 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1216 if (data_blob_len == 0) {
1217 /* an invalid request */
1218 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1222 bufrem = smbreq_bufrem(req, p);
1223 /* pull the spnego blob */
1224 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1227 file_save("negotiate.dat", blob1.data, blob1.length);
1230 p2 = (char *)req->buf + blob1.length;
1232 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1234 native_os = tmp ? tmp : "";
1236 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1238 native_lanman = tmp ? tmp : "";
1240 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1242 primary_domain = tmp ? tmp : "";
1244 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1245 native_os, native_lanman, primary_domain));
1247 if ( ra_type == RA_WIN2K ) {
1248 /* Vista sets neither the OS or lanman strings */
1250 if ( !strlen(native_os) && !strlen(native_lanman) )
1251 set_remote_arch(RA_VISTA);
1253 /* Windows 2003 doesn't set the native lanman string,
1254 but does set primary domain which is a bug I think */
1256 if ( !strlen(native_lanman) ) {
1257 ra_lanman_string( primary_domain );
1259 ra_lanman_string( native_lanman );
1263 /* Did we get a valid vuid ? */
1264 if (!is_partial_auth_vuid(sconn, vuid)) {
1265 /* No, then try and see if this is an intermediate sessionsetup
1266 * for a large SPNEGO packet. */
1267 struct pending_auth_data *pad;
1268 pad = get_pending_auth_data(sconn, smbpid);
1270 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1271 "pending vuid %u\n",
1272 (unsigned int)pad->vuid ));
1277 /* Do we have a valid vuid now ? */
1278 if (!is_partial_auth_vuid(sconn, vuid)) {
1279 /* No, start a new authentication setup. */
1280 vuid = register_initial_vuid(sconn);
1281 if (vuid == UID_FIELD_INVALID) {
1282 data_blob_free(&blob1);
1283 reply_nterror(req, nt_status_squash(
1284 NT_STATUS_INVALID_PARAMETER));
1289 vuser = get_partial_auth_user_struct(sconn, vuid);
1290 /* This MUST be valid. */
1292 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1295 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1296 * sessionsetup requests as the Windows limit on the security blob
1297 * field is 4k. Bug #4400. JRA.
1300 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 if (!NT_STATUS_EQUAL(status,
1303 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1304 /* Real error - kill the intermediate vuid */
1305 invalidate_vuid(sconn, vuid);
1307 data_blob_free(&blob1);
1308 reply_nterror(req, nt_status_squash(status));
1312 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1314 /* its a negTokenTarg packet */
1316 reply_spnego_negotiate(req, vuid, blob1,
1317 &vuser->auth_ntlmssp_state);
1318 data_blob_free(&blob1);
1322 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1324 /* its a auth packet */
1326 reply_spnego_auth(req, vuid, blob1,
1327 &vuser->auth_ntlmssp_state);
1328 data_blob_free(&blob1);
1332 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1335 if (!vuser->auth_ntlmssp_state) {
1336 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1337 if (!NT_STATUS_IS_OK(status)) {
1338 /* Kill the intermediate vuid */
1339 invalidate_vuid(sconn, vuid);
1340 data_blob_free(&blob1);
1341 reply_nterror(req, nt_status_squash(status));
1346 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1349 data_blob_free(&blob1);
1351 reply_spnego_ntlmssp(req, vuid,
1352 &vuser->auth_ntlmssp_state,
1353 &chal, status, OID_NTLMSSP, false);
1354 data_blob_free(&chal);
1358 /* what sort of packet is this? */
1359 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1361 data_blob_free(&blob1);
1363 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1366 /****************************************************************************
1367 On new VC == 0, shutdown *all* old connections and users.
1368 It seems that only NT4.x does this. At W2K and above (XP etc.).
1369 a new session setup with VC==0 is ignored.
1370 ****************************************************************************/
1372 struct shutdown_state {
1374 struct messaging_context *msg_ctx;
1377 static int shutdown_other_smbds(const struct connections_key *key,
1378 const struct connections_data *crec,
1381 struct shutdown_state *state = (struct shutdown_state *)private_data;
1383 if (!process_exists(crec->pid)) {
1387 if (procid_is_me(&crec->pid)) {
1391 if (strcmp(state->ip, crec->addr) != 0) {
1395 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1396 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1399 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1404 static void setup_new_vc_session(struct messaging_context *msg_ctx)
1406 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1407 "compatible we would close all old resources.\n"));
1410 invalidate_all_vuids();
1412 if (lp_reset_on_zero_vc()) {
1413 char addr[INET6_ADDRSTRLEN];
1414 struct shutdown_state state;
1416 state.ip = client_addr(get_client_fd(),addr,sizeof(addr));
1417 state.msg_ctx = msg_ctx;
1418 connections_forall_read(shutdown_other_smbds, &state);
1422 /****************************************************************************
1423 Reply to a session setup command.
1424 ****************************************************************************/
1426 void reply_sesssetup_and_X(struct smb_request *req)
1432 DATA_BLOB plaintext_password;
1435 fstring sub_user; /* Sanitised username for substituion */
1437 const char *native_os;
1438 const char *native_lanman;
1439 const char *primary_domain;
1440 struct auth_usersupplied_info *user_info = NULL;
1441 struct auth_serversupplied_info *server_info = NULL;
1442 uint16 smb_flag2 = req->flags2;
1445 struct smbd_server_connection *sconn = req->sconn;
1447 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1449 START_PROFILE(SMBsesssetupX);
1451 ZERO_STRUCT(lm_resp);
1452 ZERO_STRUCT(nt_resp);
1453 ZERO_STRUCT(plaintext_password);
1455 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1457 /* a SPNEGO session setup has 12 command words, whereas a normal
1458 NT1 session setup has 13. See the cifs spec. */
1459 if (req->wct == 12 &&
1460 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1462 if (!sconn->smb1.negprot.spnego) {
1463 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1464 "at SPNEGO session setup when it was not "
1466 reply_nterror(req, nt_status_squash(
1467 NT_STATUS_LOGON_FAILURE));
1468 END_PROFILE(SMBsesssetupX);
1472 if (SVAL(req->vwv+4, 0) == 0) {
1473 setup_new_vc_session(req->sconn->msg_ctx);
1476 reply_sesssetup_and_X_spnego(req);
1477 END_PROFILE(SMBsesssetupX);
1481 smb_bufsize = SVAL(req->vwv+2, 0);
1483 if (get_Protocol() < PROTOCOL_NT1) {
1484 uint16 passlen1 = SVAL(req->vwv+7, 0);
1486 /* Never do NT status codes with protocols before NT1 as we
1487 * don't get client caps. */
1488 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1490 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1491 reply_nterror(req, nt_status_squash(
1492 NT_STATUS_INVALID_PARAMETER));
1493 END_PROFILE(SMBsesssetupX);
1498 lm_resp = data_blob(req->buf, passlen1);
1500 plaintext_password = data_blob(req->buf, passlen1+1);
1501 /* Ensure null termination */
1502 plaintext_password.data[passlen1] = 0;
1505 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1506 req->buf + passlen1, STR_TERMINATE);
1507 user = tmp ? tmp : "";
1512 uint16 passlen1 = SVAL(req->vwv+7, 0);
1513 uint16 passlen2 = SVAL(req->vwv+8, 0);
1514 enum remote_arch_types ra_type = get_remote_arch();
1515 const uint8_t *p = req->buf;
1516 const uint8_t *save_p = req->buf;
1520 if(global_client_caps == 0) {
1521 global_client_caps = IVAL(req->vwv+11, 0);
1523 if (!(global_client_caps & CAP_STATUS32)) {
1524 remove_from_common_flags2(
1525 FLAGS2_32_BIT_ERROR_CODES);
1528 /* client_caps is used as final determination if
1529 * client is NT or Win95. This is needed to return
1530 * the correct error codes in some circumstances.
1533 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1534 ra_type == RA_WIN95) {
1535 if(!(global_client_caps & (CAP_NT_SMBS|
1537 set_remote_arch( RA_WIN95);
1543 /* both Win95 and WinNT stuff up the password
1544 * lengths for non-encrypting systems. Uggh.
1546 if passlen1==24 its a win95 system, and its setting
1547 the password length incorrectly. Luckily it still
1548 works with the default code because Win95 will null
1549 terminate the password anyway
1551 if passlen1>0 and passlen2>0 then maybe its a NT box
1552 and its setting passlen2 to some random value which
1553 really stuffs things up. we need to fix that one. */
1555 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1561 /* check for nasty tricks */
1562 if (passlen1 > MAX_PASS_LEN
1563 || passlen1 > smbreq_bufrem(req, p)) {
1564 reply_nterror(req, nt_status_squash(
1565 NT_STATUS_INVALID_PARAMETER));
1566 END_PROFILE(SMBsesssetupX);
1570 if (passlen2 > MAX_PASS_LEN
1571 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1572 reply_nterror(req, nt_status_squash(
1573 NT_STATUS_INVALID_PARAMETER));
1574 END_PROFILE(SMBsesssetupX);
1578 /* Save the lanman2 password and the NT md4 password. */
1580 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1585 lm_resp = data_blob(p, passlen1);
1586 nt_resp = data_blob(p+passlen1, passlen2);
1587 } else if (lp_security() != SEC_SHARE) {
1589 * In share level we should ignore any passwords, so
1590 * only read them if we're not.
1593 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1595 if (unic && (passlen2 == 0) && passlen1) {
1596 /* Only a ascii plaintext password was sent. */
1597 (void)srvstr_pull_talloc(talloc_tos(),
1603 STR_TERMINATE|STR_ASCII);
1605 (void)srvstr_pull_talloc(talloc_tos(),
1610 unic ? passlen2 : passlen1,
1614 reply_nterror(req, nt_status_squash(
1615 NT_STATUS_INVALID_PARAMETER));
1616 END_PROFILE(SMBsesssetupX);
1619 plaintext_password = data_blob(pass, strlen(pass)+1);
1622 p += passlen1 + passlen2;
1624 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1626 user = tmp ? tmp : "";
1628 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1630 domain = tmp ? tmp : "";
1632 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1634 native_os = tmp ? tmp : "";
1636 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1638 native_lanman = tmp ? tmp : "";
1640 /* not documented or decoded by Ethereal but there is one more
1641 * string in the extra bytes which is the same as the
1642 * PrimaryDomain when using extended security. Windows NT 4
1643 * and 2003 use this string to store the native lanman string.
1644 * Windows 9x does not include a string here at all so we have
1645 * to check if we have any extra bytes left */
1647 byte_count = SVAL(req->vwv+13, 0);
1648 if ( PTR_DIFF(p, save_p) < byte_count) {
1649 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1651 primary_domain = tmp ? tmp : "";
1653 primary_domain = talloc_strdup(talloc_tos(), "null");
1656 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1657 "PrimaryDomain=[%s]\n",
1658 domain, native_os, native_lanman, primary_domain));
1660 if ( ra_type == RA_WIN2K ) {
1661 if ( strlen(native_lanman) == 0 )
1662 ra_lanman_string( primary_domain );
1664 ra_lanman_string( native_lanman );
1669 if (SVAL(req->vwv+4, 0) == 0) {
1670 setup_new_vc_session(req->sconn->msg_ctx);
1673 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1674 domain, user, get_remote_machine_name()));
1677 if (sconn->smb1.negprot.spnego) {
1679 /* This has to be here, because this is a perfectly
1680 * valid behaviour for guest logons :-( */
1682 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1683 "at 'normal' session setup after "
1684 "negotiating spnego.\n"));
1685 reply_nterror(req, nt_status_squash(
1686 NT_STATUS_LOGON_FAILURE));
1687 END_PROFILE(SMBsesssetupX);
1690 fstrcpy(sub_user, user);
1692 fstrcpy(sub_user, lp_guestaccount());
1695 sub_set_smb_name(sub_user);
1697 reload_services(True);
1699 if (lp_security() == SEC_SHARE) {
1700 /* In share level we should ignore any passwords */
1702 data_blob_free(&lm_resp);
1703 data_blob_free(&nt_resp);
1704 data_blob_clear_free(&plaintext_password);
1706 map_username(sub_user);
1707 add_session_user(sconn, sub_user);
1708 add_session_workgroup(sconn, domain);
1709 /* Then force it to null for the benfit of the code below */
1715 nt_status = check_guest_password(&server_info);
1717 } else if (doencrypt) {
1718 struct auth_context *negprot_auth_context = NULL;
1719 negprot_auth_context = sconn->smb1.negprot.auth_context;
1720 if (!negprot_auth_context) {
1721 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1722 "session setup without negprot denied!\n"));
1723 reply_nterror(req, nt_status_squash(
1724 NT_STATUS_LOGON_FAILURE));
1725 END_PROFILE(SMBsesssetupX);
1728 nt_status = make_user_info_for_reply_enc(&user_info, user,
1731 if (NT_STATUS_IS_OK(nt_status)) {
1732 nt_status = negprot_auth_context->check_ntlm_password(
1733 negprot_auth_context,
1738 struct auth_context *plaintext_auth_context = NULL;
1740 nt_status = make_auth_context_subsystem(
1741 &plaintext_auth_context);
1743 if (NT_STATUS_IS_OK(nt_status)) {
1746 plaintext_auth_context->get_ntlm_challenge(
1747 plaintext_auth_context, chal);
1749 if (!make_user_info_for_reply(&user_info,
1751 plaintext_password)) {
1752 nt_status = NT_STATUS_NO_MEMORY;
1755 if (NT_STATUS_IS_OK(nt_status)) {
1756 nt_status = plaintext_auth_context->check_ntlm_password(
1757 plaintext_auth_context,
1761 TALLOC_FREE(plaintext_auth_context);
1766 free_user_info(&user_info);
1768 if (!NT_STATUS_IS_OK(nt_status)) {
1769 nt_status = do_map_to_guest(nt_status, &server_info,
1773 if (!NT_STATUS_IS_OK(nt_status)) {
1774 data_blob_free(&nt_resp);
1775 data_blob_free(&lm_resp);
1776 data_blob_clear_free(&plaintext_password);
1777 reply_nterror(req, nt_status_squash(nt_status));
1778 END_PROFILE(SMBsesssetupX);
1782 /* Ensure we can't possible take a code path leading to a
1785 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1786 END_PROFILE(SMBsesssetupX);
1790 if (!server_info->ptok) {
1791 nt_status = create_local_token(server_info);
1793 if (!NT_STATUS_IS_OK(nt_status)) {
1794 DEBUG(10, ("create_local_token failed: %s\n",
1795 nt_errstr(nt_status)));
1796 data_blob_free(&nt_resp);
1797 data_blob_free(&lm_resp);
1798 data_blob_clear_free(&plaintext_password);
1799 reply_nterror(req, nt_status_squash(nt_status));
1800 END_PROFILE(SMBsesssetupX);
1805 data_blob_clear_free(&plaintext_password);
1807 /* it's ok - setup a reply */
1808 reply_outbuf(req, 3, 0);
1809 if (get_Protocol() >= PROTOCOL_NT1) {
1810 push_signature(&req->outbuf);
1811 /* perhaps grab OS version here?? */
1814 if (server_info->guest) {
1815 SSVAL(req->outbuf,smb_vwv2,1);
1818 /* register the name and uid as being validated, so further connections
1819 to a uid can get through without a password, on the same VC */
1821 if (lp_security() == SEC_SHARE) {
1822 sess_vuid = UID_FIELD_INVALID;
1823 TALLOC_FREE(server_info);
1825 /* Ignore the initial vuid. */
1826 sess_vuid = register_initial_vuid(sconn);
1827 if (sess_vuid == UID_FIELD_INVALID) {
1828 data_blob_free(&nt_resp);
1829 data_blob_free(&lm_resp);
1830 reply_nterror(req, nt_status_squash(
1831 NT_STATUS_LOGON_FAILURE));
1832 END_PROFILE(SMBsesssetupX);
1835 /* register_existing_vuid keeps the server info */
1836 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1838 nt_resp.data ? nt_resp : lm_resp,
1840 if (sess_vuid == UID_FIELD_INVALID) {
1841 data_blob_free(&nt_resp);
1842 data_blob_free(&lm_resp);
1843 reply_nterror(req, nt_status_squash(
1844 NT_STATUS_LOGON_FAILURE));
1845 END_PROFILE(SMBsesssetupX);
1849 /* current_user_info is changed on new vuid */
1850 reload_services( True );
1853 data_blob_free(&nt_resp);
1854 data_blob_free(&lm_resp);
1856 SSVAL(req->outbuf,smb_uid,sess_vuid);
1857 SSVAL(req->inbuf,smb_uid,sess_vuid);
1858 req->vuid = sess_vuid;
1860 if (!sconn->smb1.sessions.done_sesssetup) {
1861 sconn->smb1.sessions.max_send =
1862 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1864 sconn->smb1.sessions.done_sesssetup = true;
1866 END_PROFILE(SMBsesssetupX);