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 "librpc/gen_ndr/messaging.h"
31 /* For split krb5 SPNEGO blobs. */
32 struct pending_auth_data {
33 struct pending_auth_data *prev, *next;
34 uint16 vuid; /* Tag for this entry. */
35 uint16 smbpid; /* Alternate tag for this entry. */
37 DATA_BLOB partial_data;
41 on a logon error possibly map the error to success if "map to guest"
44 NTSTATUS do_map_to_guest(NTSTATUS status,
45 struct auth_serversupplied_info **server_info,
46 const char *user, const char *domain)
48 user = user ? user : "";
49 domain = domain ? domain : "";
51 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
52 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
53 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
54 DEBUG(3,("No such user %s [%s] - using guest account\n",
56 status = make_server_info_guest(NULL, server_info);
60 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
61 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
62 DEBUG(3,("Registered username %s for guest access\n",
64 status = make_server_info_guest(NULL, server_info);
71 /****************************************************************************
72 Add the standard 'Samba' signature to the end of the session setup.
73 ****************************************************************************/
75 static int push_signature(uint8 **outbuf)
82 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
84 if (tmp == -1) return -1;
87 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
88 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
92 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
95 if (tmp == -1) return -1;
98 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
100 if (tmp == -1) return -1;
106 /****************************************************************************
107 Send a security blob via a session setup reply.
108 ****************************************************************************/
110 static void reply_sesssetup_blob(struct smb_request *req,
114 if (!NT_STATUS_IS_OK(nt_status) &&
115 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
116 reply_nterror(req, nt_status_squash(nt_status));
120 nt_status = nt_status_squash(nt_status);
121 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
122 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
123 SSVAL(req->outbuf, smb_vwv3, blob.length);
125 if ((message_push_blob(&req->outbuf, blob) == -1)
126 || (push_signature(&req->outbuf) == -1)) {
127 reply_nterror(req, NT_STATUS_NO_MEMORY);
131 /****************************************************************************
132 Do a 'guest' logon, getting back the
133 ****************************************************************************/
135 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
137 struct auth_context *auth_context;
138 struct auth_usersupplied_info *user_info = NULL;
141 unsigned char chal[8];
145 DEBUG(3,("Got anonymous request\n"));
147 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
152 if (!make_user_info_guest(&user_info)) {
153 TALLOC_FREE(auth_context);
154 return NT_STATUS_NO_MEMORY;
157 nt_status = auth_context->check_ntlm_password(auth_context,
160 TALLOC_FREE(auth_context);
161 free_user_info(&user_info);
169 /* Experiment that failed. See "only happens with a KDC" comment below. */
170 /****************************************************************************
171 Cerate a clock skew error blob for a Windows client.
172 ****************************************************************************/
174 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
176 krb5_context context = NULL;
177 krb5_error_code kerr = 0;
179 krb5_principal host_princ = NULL;
180 char *host_princ_s = NULL;
183 *pblob_out = data_blob_null;
185 initialize_krb5_error_table();
186 kerr = krb5_init_context(&context);
190 /* Create server principal. */
191 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
195 strlower_m(host_princ_s);
197 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
199 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
200 "for name %s: Error %s\n",
201 host_princ_s, error_message(kerr) ));
205 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
208 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
209 "failed: Error %s\n",
210 error_message(kerr) ));
214 *pblob_out = data_blob(reply.data, reply.length);
215 kerberos_free_data_contents(context,&reply);
221 SAFE_FREE(host_princ_s);
224 krb5_free_principal(context, host_princ);
226 krb5_free_context(context);
231 /****************************************************************************
232 Reply to a session setup spnego negotiate packet for kerberos.
233 ****************************************************************************/
235 static void reply_spnego_kerberos(struct smb_request *req,
239 bool *p_invalidate_vuid)
243 char *client, *p, *domain;
244 fstring netbios_domain_name;
247 int sess_vuid = req->vuid;
248 NTSTATUS ret = NT_STATUS_OK;
249 DATA_BLOB ap_rep, ap_rep_wrapped, response;
250 struct auth_serversupplied_info *server_info = NULL;
251 DATA_BLOB session_key = data_blob_null;
253 DATA_BLOB nullblob = data_blob_null;
254 fstring real_username;
255 bool map_domainuser_to_guest = False;
256 bool username_was_mapped;
257 struct PAC_LOGON_INFO *logon_info = NULL;
258 struct smbd_server_connection *sconn = req->sconn;
262 ZERO_STRUCT(ap_rep_wrapped);
263 ZERO_STRUCT(response);
265 /* Normally we will always invalidate the intermediate vuid. */
266 *p_invalidate_vuid = True;
268 mem_ctx = talloc_init("reply_spnego_kerberos");
269 if (mem_ctx == NULL) {
270 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
274 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
275 talloc_destroy(mem_ctx);
276 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
280 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
281 &client, &logon_info, &ap_rep,
284 data_blob_free(&ticket);
286 if (!NT_STATUS_IS_OK(ret)) {
288 /* Experiment that failed.
289 * See "only happens with a KDC" comment below. */
291 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
294 * Windows in this case returns
295 * NT_STATUS_MORE_PROCESSING_REQUIRED
296 * with a negTokenTarg blob containing an krb5_error
297 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
298 * The client then fixes its clock and continues rather
299 * than giving an error. JRA.
300 * -- Looks like this only happens with a KDC. JRA.
303 bool ok = make_krb5_skew_error(&ap_rep);
305 talloc_destroy(mem_ctx);
306 return ERROR_NT(nt_status_squash(
307 NT_STATUS_LOGON_FAILURE));
309 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
311 response = spnego_gen_auth_response(&ap_rep_wrapped,
312 ret, OID_KERBEROS5_OLD);
313 reply_sesssetup_blob(conn, inbuf, outbuf, response,
314 NT_STATUS_MORE_PROCESSING_REQUIRED);
317 * In this one case we don't invalidate the
318 * intermediate vuid as we're expecting the client
319 * to re-use it for the next sessionsetupX packet. JRA.
322 *p_invalidate_vuid = False;
324 data_blob_free(&ap_rep);
325 data_blob_free(&ap_rep_wrapped);
326 data_blob_free(&response);
327 talloc_destroy(mem_ctx);
328 return -1; /* already replied */
331 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
332 ret = NT_STATUS_LOGON_FAILURE;
335 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
337 talloc_destroy(mem_ctx);
338 reply_nterror(req, nt_status_squash(ret));
342 DEBUG(3,("Ticket name is [%s]\n", client));
344 p = strchr_m(client, '@');
346 DEBUG(3,("Doesn't look like a valid principal\n"));
347 data_blob_free(&ap_rep);
348 data_blob_free(&session_key);
349 talloc_destroy(mem_ctx);
350 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
356 /* save the PAC data if we have it */
359 netsamlogon_cache_store( client, &logon_info->info3 );
362 if (!strequal(p+1, lp_realm())) {
363 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
364 if (!lp_allow_trusted_domains()) {
365 data_blob_free(&ap_rep);
366 data_blob_free(&session_key);
367 talloc_destroy(mem_ctx);
368 reply_nterror(req, nt_status_squash(
369 NT_STATUS_LOGON_FAILURE));
374 /* this gives a fully qualified user name (ie. with full realm).
375 that leads to very long usernames, but what else can we do? */
379 if (logon_info && logon_info->info3.base.domain.string) {
380 fstrcpy(netbios_domain_name,
381 logon_info->info3.base.domain.string);
382 domain = netbios_domain_name;
383 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
387 /* If we have winbind running, we can (and must) shorten the
388 username by using the short netbios name. Otherwise we will
389 have inconsistent user names. With Kerberos, we get the
390 fully qualified realm, with ntlmssp we get the short
391 name. And even w2k3 does use ntlmssp if you for example
392 connect to an ip address. */
395 struct wbcDomainInfo *info = NULL;
397 DEBUG(10, ("Mapping [%s] to short name\n", domain));
399 wbc_status = wbcDomainInfo(domain, &info);
401 if (WBC_ERROR_IS_OK(wbc_status)) {
403 fstrcpy(netbios_domain_name,
407 domain = netbios_domain_name;
408 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
410 DEBUG(3, ("Could not find short name: %s\n",
411 wbcErrorString(wbc_status)));
415 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
417 /* lookup the passwd struct, create a new user if necessary */
419 username_was_mapped = map_username(user);
421 pw = smb_getpwnam( mem_ctx, user, real_username, True );
424 /* if a real user check pam account restrictions */
425 /* only really perfomed if "obey pam restriction" is true */
426 /* do this before an eventual mapping to guest occurs */
427 ret = smb_pam_accountcheck(pw->pw_name);
428 if ( !NT_STATUS_IS_OK(ret)) {
429 DEBUG(1,("PAM account restriction "
430 "prevents user login\n"));
431 data_blob_free(&ap_rep);
432 data_blob_free(&session_key);
433 TALLOC_FREE(mem_ctx);
434 reply_nterror(req, nt_status_squash(ret));
441 /* this was originally the behavior of Samba 2.2, if a user
442 did not have a local uid but has been authenticated, then
443 map them to a guest account */
445 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
446 map_domainuser_to_guest = True;
447 fstrcpy(user,lp_guestaccount());
448 pw = smb_getpwnam( mem_ctx, user, real_username, True );
451 /* extra sanity check that the guest account is valid */
454 DEBUG(1,("Username %s is invalid on this system\n",
456 data_blob_free(&ap_rep);
457 data_blob_free(&session_key);
458 TALLOC_FREE(mem_ctx);
459 reply_nterror(req, nt_status_squash(
460 NT_STATUS_LOGON_FAILURE));
465 /* setup the string used by %U */
467 sub_set_smb_name( real_username );
468 reload_services(True);
470 if ( map_domainuser_to_guest ) {
471 make_server_info_guest(NULL, &server_info);
472 } else if (logon_info) {
473 /* pass the unmapped username here since map_username()
474 will be called again from inside make_server_info_info3() */
476 ret = make_server_info_info3(mem_ctx, client, domain,
477 &server_info, &logon_info->info3);
478 if ( !NT_STATUS_IS_OK(ret) ) {
479 DEBUG(1,("make_server_info_info3 failed: %s!\n",
481 data_blob_free(&ap_rep);
482 data_blob_free(&session_key);
483 TALLOC_FREE(mem_ctx);
484 reply_nterror(req, nt_status_squash(ret));
490 * We didn't get a PAC, we have to make up the user
491 * ourselves. Try to ask the pdb backend to provide
492 * SID consistency with ntlmssp session setup
494 struct samu *sampass;
496 sampass = samu_new(talloc_tos());
497 if (sampass == NULL) {
498 ret = NT_STATUS_NO_MEMORY;
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));
506 if (pdb_getsampwnam(sampass, real_username)) {
507 DEBUG(10, ("found user %s in passdb, calling "
508 "make_server_info_sam\n", real_username));
509 ret = make_server_info_sam(&server_info, sampass);
510 TALLOC_FREE(sampass);
513 * User not in passdb, make it up artificially
515 TALLOC_FREE(sampass);
516 DEBUG(10, ("didn't find user %s in passdb, calling "
517 "make_server_info_pw\n", real_username));
518 ret = make_server_info_pw(&server_info, real_username,
522 if ( !NT_STATUS_IS_OK(ret) ) {
523 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
525 data_blob_free(&ap_rep);
526 data_blob_free(&session_key);
527 TALLOC_FREE(mem_ctx);
528 reply_nterror(req, nt_status_squash(ret));
532 /* make_server_info_pw does not set the domain. Without this
533 * we end up with the local netbios name in substitutions for
536 if (server_info->info3 != NULL) {
537 server_info->info3->base.domain.string =
538 talloc_strdup(server_info->info3, domain);
542 server_info->nss_token |= username_was_mapped;
544 /* we need to build the token for the user. make_server_info_guest()
547 if ( !server_info->ptok ) {
548 ret = create_local_token( server_info );
549 if ( !NT_STATUS_IS_OK(ret) ) {
550 DEBUG(10,("failed to create local token: %s\n",
552 data_blob_free(&ap_rep);
553 data_blob_free(&session_key);
554 TALLOC_FREE( mem_ctx );
555 TALLOC_FREE( server_info );
556 reply_nterror(req, nt_status_squash(ret));
561 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
562 sess_vuid = register_initial_vuid(sconn);
565 data_blob_free(&server_info->user_session_key);
566 server_info->user_session_key = session_key;
567 talloc_steal(server_info, session_key.data);
569 session_key = data_blob_null;
571 /* register_existing_vuid keeps the server info */
572 /* register_existing_vuid takes ownership of session_key on success,
573 * no need to free after this on success. A better interface would copy
576 sess_vuid = register_existing_vuid(sconn,
582 reply_outbuf(req, 4, 0);
583 SSVAL(req->outbuf,smb_uid,sess_vuid);
585 if (sess_vuid == UID_FIELD_INVALID ) {
586 ret = NT_STATUS_LOGON_FAILURE;
588 /* current_user_info is changed on new vuid */
589 reload_services( True );
591 SSVAL(req->outbuf, smb_vwv3, 0);
593 if (server_info->guest) {
594 SSVAL(req->outbuf,smb_vwv2,1);
597 SSVAL(req->outbuf, smb_uid, sess_vuid);
599 /* Successful logon. Keep this vuid. */
600 *p_invalidate_vuid = False;
603 /* wrap that up in a nice GSS-API wrapping */
604 if (NT_STATUS_IS_OK(ret)) {
605 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
608 ap_rep_wrapped = data_blob_null;
610 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
612 reply_sesssetup_blob(req, response, ret);
614 data_blob_free(&ap_rep);
615 data_blob_free(&ap_rep_wrapped);
616 data_blob_free(&response);
617 TALLOC_FREE(mem_ctx);
622 /****************************************************************************
623 Send a session setup reply, wrapped in SPNEGO.
624 Get vuid and check first.
625 End the NTLMSSP exchange context if we are OK/complete fail
626 This should be split into two functions, one to handle each
627 leg of the NTLM auth steps.
628 ***************************************************************************/
630 static void reply_spnego_ntlmssp(struct smb_request *req,
632 struct auth_ntlmssp_state **auth_ntlmssp_state,
633 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
637 bool do_invalidate = true;
639 struct auth_serversupplied_info *server_info = NULL;
640 struct smbd_server_connection *sconn = req->sconn;
642 if (NT_STATUS_IS_OK(nt_status)) {
643 nt_status = auth_ntlmssp_server_info(talloc_tos(), (*auth_ntlmssp_state), &server_info);
645 /* Note that this server_info won't have a session
646 * key. But for map to guest, that's exactly the right
647 * thing - we can't reasonably guess the key the
648 * client wants, as the password was wrong */
649 nt_status = do_map_to_guest(nt_status,
651 auth_ntlmssp_get_username(*auth_ntlmssp_state),
652 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
655 reply_outbuf(req, 4, 0);
657 SSVAL(req->outbuf, smb_uid, vuid);
659 if (NT_STATUS_IS_OK(nt_status)) {
660 DATA_BLOB nullblob = data_blob_null;
662 if (!is_partial_auth_vuid(sconn, vuid)) {
663 nt_status = NT_STATUS_LOGON_FAILURE;
667 /* register_existing_vuid keeps the server info */
668 if (register_existing_vuid(sconn, vuid,
669 server_info, nullblob,
670 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
672 /* The problem is, *auth_ntlmssp_state points
673 * into the vuser this will have
674 * talloc_free()'ed in
675 * register_existing_vuid() */
676 do_invalidate = false;
677 nt_status = NT_STATUS_LOGON_FAILURE;
681 /* current_user_info is changed on new vuid */
682 reload_services( True );
684 SSVAL(req->outbuf, smb_vwv3, 0);
686 if (server_info->guest) {
687 SSVAL(req->outbuf,smb_vwv2,1);
694 response = spnego_gen_auth_response(ntlmssp_blob,
697 response = *ntlmssp_blob;
700 reply_sesssetup_blob(req, response, nt_status);
702 data_blob_free(&response);
705 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
706 and the other end, that we are not finished yet. */
708 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
709 /* NB. This is *NOT* an error case. JRA */
711 TALLOC_FREE(*auth_ntlmssp_state);
712 if (!NT_STATUS_IS_OK(nt_status)) {
713 /* Kill the intermediate vuid */
714 invalidate_vuid(sconn, vuid);
720 /****************************************************************************
721 Is this a krb5 mechanism ?
722 ****************************************************************************/
724 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
725 DATA_BLOB *pblob_out,
728 char *OIDs[ASN1_MAX_OIDS];
730 NTSTATUS ret = NT_STATUS_OK;
732 *kerb_mechOID = NULL;
734 /* parse out the OIDs and the first sec blob */
735 if (!spnego_parse_negTokenInit(blob_in, OIDs, NULL, pblob_out)) {
736 return NT_STATUS_LOGON_FAILURE;
739 /* only look at the first OID for determining the mechToken --
740 according to RFC2478, we should choose the one we want
741 and renegotiate, but i smell a client bug here..
743 Problem observed when connecting to a member (samba box)
744 of an AD domain as a user in a Samba domain. Samba member
745 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
746 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
747 NTLMSSP mechtoken. --jerry */
750 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
751 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
752 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
753 if (*kerb_mechOID == NULL) {
754 ret = NT_STATUS_NO_MEMORY;
759 for (i=0;OIDs[i];i++) {
760 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
761 talloc_free(OIDs[i]);
766 /****************************************************************************
767 Fall back from krb5 to NTLMSSP.
768 ****************************************************************************/
770 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
775 reply_outbuf(req, 4, 0);
776 SSVAL(req->outbuf,smb_uid,vuid);
778 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
779 "but set to downgrade to NTLMSSP\n"));
781 response = spnego_gen_auth_response(NULL,
782 NT_STATUS_MORE_PROCESSING_REQUIRED,
784 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
785 data_blob_free(&response);
788 /****************************************************************************
789 Reply to a session setup spnego negotiate packet.
790 ****************************************************************************/
792 static void reply_spnego_negotiate(struct smb_request *req,
795 struct auth_ntlmssp_state **auth_ntlmssp_state)
799 char *kerb_mech = NULL;
801 struct smbd_server_connection *sconn = req->sconn;
803 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
804 if (!NT_STATUS_IS_OK(status)) {
805 /* Kill the intermediate vuid */
806 invalidate_vuid(sconn, vuid);
807 reply_nterror(req, nt_status_squash(status));
811 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
812 (unsigned long)secblob.length));
815 if (kerb_mech && ((lp_security()==SEC_ADS) ||
816 USE_KERBEROS_KEYTAB) ) {
817 bool destroy_vuid = True;
818 reply_spnego_kerberos(req, &secblob, kerb_mech,
819 vuid, &destroy_vuid);
820 data_blob_free(&secblob);
822 /* Kill the intermediate vuid */
823 invalidate_vuid(sconn, vuid);
825 SAFE_FREE(kerb_mech);
830 if (*auth_ntlmssp_state) {
831 TALLOC_FREE(*auth_ntlmssp_state);
835 data_blob_free(&secblob);
836 /* The mechtoken is a krb5 ticket, but
837 * we need to fall back to NTLM. */
838 reply_spnego_downgrade_to_ntlmssp(req, vuid);
839 SAFE_FREE(kerb_mech);
843 status = auth_ntlmssp_start(auth_ntlmssp_state);
844 if (!NT_STATUS_IS_OK(status)) {
845 /* Kill the intermediate vuid */
846 invalidate_vuid(sconn, vuid);
847 reply_nterror(req, nt_status_squash(status));
851 status = auth_ntlmssp_update(*auth_ntlmssp_state,
854 data_blob_free(&secblob);
856 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
857 &chal, status, OID_NTLMSSP, true);
859 data_blob_free(&chal);
861 /* already replied */
865 /****************************************************************************
866 Reply to a session setup spnego auth packet.
867 ****************************************************************************/
869 static void reply_spnego_auth(struct smb_request *req,
872 struct auth_ntlmssp_state **auth_ntlmssp_state)
874 DATA_BLOB auth = data_blob_null;
875 DATA_BLOB auth_reply = data_blob_null;
876 DATA_BLOB secblob = data_blob_null;
877 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
878 struct smbd_server_connection *sconn = req->sconn;
880 if (!spnego_parse_auth(blob1, &auth)) {
882 file_save("auth.dat", blob1.data, blob1.length);
884 /* Kill the intermediate vuid */
885 invalidate_vuid(sconn, vuid);
887 reply_nterror(req, nt_status_squash(
888 NT_STATUS_LOGON_FAILURE));
892 if (auth.data[0] == ASN1_APPLICATION(0)) {
893 /* Might be a second negTokenTarg packet */
894 char *kerb_mech = NULL;
896 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
898 if (!NT_STATUS_IS_OK(status)) {
899 /* Kill the intermediate vuid */
900 invalidate_vuid(sconn, vuid);
901 reply_nterror(req, nt_status_squash(status));
905 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
906 (unsigned long)secblob.length));
908 if (kerb_mech && ((lp_security()==SEC_ADS) ||
909 USE_KERBEROS_KEYTAB)) {
910 bool destroy_vuid = True;
911 reply_spnego_kerberos(req, &secblob, kerb_mech,
912 vuid, &destroy_vuid);
913 data_blob_free(&secblob);
914 data_blob_free(&auth);
916 /* Kill the intermediate vuid */
917 invalidate_vuid(sconn, vuid);
919 SAFE_FREE(kerb_mech);
923 /* Can't blunder into NTLMSSP auth if we have
927 /* Kill the intermediate vuid */
928 invalidate_vuid(sconn, vuid);
929 DEBUG(3,("reply_spnego_auth: network "
930 "misconfiguration, client sent us a "
931 "krb5 ticket and kerberos security "
933 reply_nterror(req, nt_status_squash(
934 NT_STATUS_LOGON_FAILURE));
935 SAFE_FREE(kerb_mech);
939 /* If we get here it wasn't a negTokenTarg auth packet. */
940 data_blob_free(&secblob);
942 if (!*auth_ntlmssp_state) {
943 status = auth_ntlmssp_start(auth_ntlmssp_state);
944 if (!NT_STATUS_IS_OK(status)) {
945 /* Kill the intermediate vuid */
946 invalidate_vuid(sconn, vuid);
947 reply_nterror(req, nt_status_squash(status));
952 status = auth_ntlmssp_update(*auth_ntlmssp_state,
955 data_blob_free(&auth);
957 /* Don't send the mechid as we've already sent this (RFC4178). */
959 reply_spnego_ntlmssp(req, vuid,
961 &auth_reply, status, NULL, true);
963 data_blob_free(&auth_reply);
965 /* and tell smbd that we have already replied to this packet */
969 /****************************************************************************
970 Delete an entry on the list.
971 ****************************************************************************/
973 static void delete_partial_auth(struct smbd_server_connection *sconn,
974 struct pending_auth_data *pad)
979 DLIST_REMOVE(sconn->smb1.pd_list, pad);
980 data_blob_free(&pad->partial_data);
984 /****************************************************************************
985 Search for a partial SPNEGO auth fragment matching an smbpid.
986 ****************************************************************************/
988 static struct pending_auth_data *get_pending_auth_data(
989 struct smbd_server_connection *sconn,
992 struct pending_auth_data *pad;
994 * NOTE: using the smbpid here is completely wrong...
996 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
998 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
999 if (pad->smbpid == smbpid) {
1006 /****************************************************************************
1007 Check the size of an SPNEGO blob. If we need more return
1008 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1009 the blob to be more than 64k.
1010 ****************************************************************************/
1012 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1013 uint16 smbpid, uint16 vuid,
1016 struct pending_auth_data *pad = NULL;
1018 size_t needed_len = 0;
1020 pad = get_pending_auth_data(sconn, smbpid);
1022 /* Ensure we have some data. */
1023 if (pblob->length == 0) {
1024 /* Caller can cope. */
1025 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1026 delete_partial_auth(sconn, pad);
1027 return NT_STATUS_OK;
1030 /* Were we waiting for more data ? */
1033 size_t copy_len = MIN(65536, pblob->length);
1035 /* Integer wrap paranoia.... */
1037 if (pad->partial_data.length + copy_len <
1038 pad->partial_data.length ||
1039 pad->partial_data.length + copy_len < copy_len) {
1041 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1042 "pad->partial_data.length = %u, "
1044 (unsigned int)pad->partial_data.length,
1045 (unsigned int)copy_len ));
1047 delete_partial_auth(sconn, pad);
1048 return NT_STATUS_INVALID_PARAMETER;
1051 DEBUG(10,("check_spnego_blob_complete: "
1052 "pad->partial_data.length = %u, "
1053 "pad->needed_len = %u, "
1055 "pblob->length = %u,\n",
1056 (unsigned int)pad->partial_data.length,
1057 (unsigned int)pad->needed_len,
1058 (unsigned int)copy_len,
1059 (unsigned int)pblob->length ));
1061 tmp_blob = data_blob(NULL,
1062 pad->partial_data.length + copy_len);
1064 /* Concatenate the two (up to copy_len) bytes. */
1065 memcpy(tmp_blob.data,
1066 pad->partial_data.data,
1067 pad->partial_data.length);
1068 memcpy(tmp_blob.data + pad->partial_data.length,
1072 /* Replace the partial data. */
1073 data_blob_free(&pad->partial_data);
1074 pad->partial_data = tmp_blob;
1075 ZERO_STRUCT(tmp_blob);
1078 if (pblob->length >= pad->needed_len) {
1079 /* Yes, replace pblob. */
1080 data_blob_free(pblob);
1081 *pblob = pad->partial_data;
1082 ZERO_STRUCT(pad->partial_data);
1083 delete_partial_auth(sconn, pad);
1084 return NT_STATUS_OK;
1087 /* Still need more data. */
1088 pad->needed_len -= copy_len;
1089 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1092 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1093 (pblob->data[0] != ASN1_CONTEXT(1))) {
1094 /* Not something we can determine the
1097 return NT_STATUS_OK;
1100 /* This is a new SPNEGO sessionsetup - see if
1101 * the data given in this blob is enough.
1104 data = asn1_init(NULL);
1106 return NT_STATUS_NO_MEMORY;
1109 asn1_load(data, *pblob);
1110 asn1_start_tag(data, pblob->data[0]);
1111 if (data->has_error || data->nesting == NULL) {
1113 /* Let caller catch. */
1114 return NT_STATUS_OK;
1117 /* Integer wrap paranoia.... */
1119 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1120 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1122 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1123 "data.nesting->taglen = %u, "
1124 "data.nesting->start = %u\n",
1125 (unsigned int)data->nesting->taglen,
1126 (unsigned int)data->nesting->start ));
1129 return NT_STATUS_INVALID_PARAMETER;
1132 /* Total length of the needed asn1 is the tag length
1133 * plus the current offset. */
1135 needed_len = data->nesting->taglen + data->nesting->start;
1138 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1139 "pblob->length = %u\n",
1140 (unsigned int)needed_len,
1141 (unsigned int)pblob->length ));
1143 if (needed_len <= pblob->length) {
1144 /* Nothing to do - blob is complete. */
1145 return NT_STATUS_OK;
1148 /* Refuse the blob if it's bigger than 64k. */
1149 if (needed_len > 65536) {
1150 DEBUG(2,("check_spnego_blob_complete: needed_len "
1152 (unsigned int)needed_len ));
1153 return NT_STATUS_INVALID_PARAMETER;
1156 /* We must store this blob until complete. */
1157 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1158 return NT_STATUS_NO_MEMORY;
1160 pad->needed_len = needed_len - pblob->length;
1161 pad->partial_data = data_blob(pblob->data, pblob->length);
1162 if (pad->partial_data.data == NULL) {
1164 return NT_STATUS_NO_MEMORY;
1166 pad->smbpid = smbpid;
1168 DLIST_ADD(sconn->smb1.pd_list, pad);
1170 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1173 /****************************************************************************
1174 Reply to a session setup command.
1175 conn POINTER CAN BE NULL HERE !
1176 ****************************************************************************/
1178 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1184 const char *native_os;
1185 const char *native_lanman;
1186 const char *primary_domain;
1188 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1189 enum remote_arch_types ra_type = get_remote_arch();
1190 int vuid = req->vuid;
1191 user_struct *vuser = NULL;
1192 NTSTATUS status = NT_STATUS_OK;
1193 uint16 smbpid = req->smbpid;
1194 struct smbd_server_connection *sconn = req->sconn;
1196 DEBUG(3,("Doing spnego session setup\n"));
1198 if (global_client_caps == 0) {
1199 global_client_caps = IVAL(req->vwv+10, 0);
1201 if (!(global_client_caps & CAP_STATUS32)) {
1202 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1209 if (data_blob_len == 0) {
1210 /* an invalid request */
1211 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1215 bufrem = smbreq_bufrem(req, p);
1216 /* pull the spnego blob */
1217 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1220 file_save("negotiate.dat", blob1.data, blob1.length);
1223 p2 = (char *)req->buf + blob1.length;
1225 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1227 native_os = tmp ? tmp : "";
1229 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1231 native_lanman = tmp ? tmp : "";
1233 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1235 primary_domain = tmp ? tmp : "";
1237 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1238 native_os, native_lanman, primary_domain));
1240 if ( ra_type == RA_WIN2K ) {
1241 /* Vista sets neither the OS or lanman strings */
1243 if ( !strlen(native_os) && !strlen(native_lanman) )
1244 set_remote_arch(RA_VISTA);
1246 /* Windows 2003 doesn't set the native lanman string,
1247 but does set primary domain which is a bug I think */
1249 if ( !strlen(native_lanman) ) {
1250 ra_lanman_string( primary_domain );
1252 ra_lanman_string( native_lanman );
1256 /* Did we get a valid vuid ? */
1257 if (!is_partial_auth_vuid(sconn, vuid)) {
1258 /* No, then try and see if this is an intermediate sessionsetup
1259 * for a large SPNEGO packet. */
1260 struct pending_auth_data *pad;
1261 pad = get_pending_auth_data(sconn, smbpid);
1263 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1264 "pending vuid %u\n",
1265 (unsigned int)pad->vuid ));
1270 /* Do we have a valid vuid now ? */
1271 if (!is_partial_auth_vuid(sconn, vuid)) {
1272 /* No, start a new authentication setup. */
1273 vuid = register_initial_vuid(sconn);
1274 if (vuid == UID_FIELD_INVALID) {
1275 data_blob_free(&blob1);
1276 reply_nterror(req, nt_status_squash(
1277 NT_STATUS_INVALID_PARAMETER));
1282 vuser = get_partial_auth_user_struct(sconn, vuid);
1283 /* This MUST be valid. */
1285 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1288 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1289 * sessionsetup requests as the Windows limit on the security blob
1290 * field is 4k. Bug #4400. JRA.
1293 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 if (!NT_STATUS_EQUAL(status,
1296 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1297 /* Real error - kill the intermediate vuid */
1298 invalidate_vuid(sconn, vuid);
1300 data_blob_free(&blob1);
1301 reply_nterror(req, nt_status_squash(status));
1305 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1307 /* its a negTokenTarg packet */
1309 reply_spnego_negotiate(req, vuid, blob1,
1310 &vuser->auth_ntlmssp_state);
1311 data_blob_free(&blob1);
1315 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1317 /* its a auth packet */
1319 reply_spnego_auth(req, vuid, blob1,
1320 &vuser->auth_ntlmssp_state);
1321 data_blob_free(&blob1);
1325 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1328 if (!vuser->auth_ntlmssp_state) {
1329 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1330 if (!NT_STATUS_IS_OK(status)) {
1331 /* Kill the intermediate vuid */
1332 invalidate_vuid(sconn, vuid);
1333 data_blob_free(&blob1);
1334 reply_nterror(req, nt_status_squash(status));
1339 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1342 data_blob_free(&blob1);
1344 reply_spnego_ntlmssp(req, vuid,
1345 &vuser->auth_ntlmssp_state,
1346 &chal, status, OID_NTLMSSP, false);
1347 data_blob_free(&chal);
1351 /* what sort of packet is this? */
1352 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1354 data_blob_free(&blob1);
1356 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1359 /****************************************************************************
1360 On new VC == 0, shutdown *all* old connections and users.
1361 It seems that only NT4.x does this. At W2K and above (XP etc.).
1362 a new session setup with VC==0 is ignored.
1363 ****************************************************************************/
1365 struct shutdown_state {
1367 struct messaging_context *msg_ctx;
1370 static int shutdown_other_smbds(const struct connections_key *key,
1371 const struct connections_data *crec,
1374 struct shutdown_state *state = (struct shutdown_state *)private_data;
1376 if (!process_exists(crec->pid)) {
1380 if (procid_is_me(&crec->pid)) {
1384 if (strcmp(state->ip, crec->addr) != 0) {
1388 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1389 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1392 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1397 static void setup_new_vc_session(struct messaging_context *msg_ctx)
1399 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1400 "compatible we would close all old resources.\n"));
1403 invalidate_all_vuids();
1405 if (lp_reset_on_zero_vc()) {
1406 char addr[INET6_ADDRSTRLEN];
1407 struct shutdown_state state;
1409 state.ip = client_addr(get_client_fd(),addr,sizeof(addr));
1410 state.msg_ctx = msg_ctx;
1411 connections_forall_read(shutdown_other_smbds, &state);
1415 /****************************************************************************
1416 Reply to a session setup command.
1417 ****************************************************************************/
1419 void reply_sesssetup_and_X(struct smb_request *req)
1425 DATA_BLOB plaintext_password;
1428 fstring sub_user; /* Sanitised username for substituion */
1430 const char *native_os;
1431 const char *native_lanman;
1432 const char *primary_domain;
1433 struct auth_usersupplied_info *user_info = NULL;
1434 struct auth_serversupplied_info *server_info = NULL;
1435 uint16 smb_flag2 = req->flags2;
1438 struct smbd_server_connection *sconn = req->sconn;
1440 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1442 START_PROFILE(SMBsesssetupX);
1444 ZERO_STRUCT(lm_resp);
1445 ZERO_STRUCT(nt_resp);
1446 ZERO_STRUCT(plaintext_password);
1448 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1450 /* a SPNEGO session setup has 12 command words, whereas a normal
1451 NT1 session setup has 13. See the cifs spec. */
1452 if (req->wct == 12 &&
1453 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1455 if (!sconn->smb1.negprot.spnego) {
1456 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1457 "at SPNEGO session setup when it was not "
1459 reply_nterror(req, nt_status_squash(
1460 NT_STATUS_LOGON_FAILURE));
1461 END_PROFILE(SMBsesssetupX);
1465 if (SVAL(req->vwv+4, 0) == 0) {
1466 setup_new_vc_session(req->sconn->msg_ctx);
1469 reply_sesssetup_and_X_spnego(req);
1470 END_PROFILE(SMBsesssetupX);
1474 smb_bufsize = SVAL(req->vwv+2, 0);
1476 if (get_Protocol() < PROTOCOL_NT1) {
1477 uint16 passlen1 = SVAL(req->vwv+7, 0);
1479 /* Never do NT status codes with protocols before NT1 as we
1480 * don't get client caps. */
1481 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1483 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1484 reply_nterror(req, nt_status_squash(
1485 NT_STATUS_INVALID_PARAMETER));
1486 END_PROFILE(SMBsesssetupX);
1491 lm_resp = data_blob(req->buf, passlen1);
1493 plaintext_password = data_blob(req->buf, passlen1+1);
1494 /* Ensure null termination */
1495 plaintext_password.data[passlen1] = 0;
1498 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1499 req->buf + passlen1, STR_TERMINATE);
1500 user = tmp ? tmp : "";
1505 uint16 passlen1 = SVAL(req->vwv+7, 0);
1506 uint16 passlen2 = SVAL(req->vwv+8, 0);
1507 enum remote_arch_types ra_type = get_remote_arch();
1508 const uint8_t *p = req->buf;
1509 const uint8_t *save_p = req->buf;
1513 if(global_client_caps == 0) {
1514 global_client_caps = IVAL(req->vwv+11, 0);
1516 if (!(global_client_caps & CAP_STATUS32)) {
1517 remove_from_common_flags2(
1518 FLAGS2_32_BIT_ERROR_CODES);
1521 /* client_caps is used as final determination if
1522 * client is NT or Win95. This is needed to return
1523 * the correct error codes in some circumstances.
1526 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1527 ra_type == RA_WIN95) {
1528 if(!(global_client_caps & (CAP_NT_SMBS|
1530 set_remote_arch( RA_WIN95);
1536 /* both Win95 and WinNT stuff up the password
1537 * lengths for non-encrypting systems. Uggh.
1539 if passlen1==24 its a win95 system, and its setting
1540 the password length incorrectly. Luckily it still
1541 works with the default code because Win95 will null
1542 terminate the password anyway
1544 if passlen1>0 and passlen2>0 then maybe its a NT box
1545 and its setting passlen2 to some random value which
1546 really stuffs things up. we need to fix that one. */
1548 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1554 /* check for nasty tricks */
1555 if (passlen1 > MAX_PASS_LEN
1556 || passlen1 > smbreq_bufrem(req, p)) {
1557 reply_nterror(req, nt_status_squash(
1558 NT_STATUS_INVALID_PARAMETER));
1559 END_PROFILE(SMBsesssetupX);
1563 if (passlen2 > MAX_PASS_LEN
1564 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1565 reply_nterror(req, nt_status_squash(
1566 NT_STATUS_INVALID_PARAMETER));
1567 END_PROFILE(SMBsesssetupX);
1571 /* Save the lanman2 password and the NT md4 password. */
1573 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1578 lm_resp = data_blob(p, passlen1);
1579 nt_resp = data_blob(p+passlen1, passlen2);
1580 } else if (lp_security() != SEC_SHARE) {
1582 * In share level we should ignore any passwords, so
1583 * only read them if we're not.
1586 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1588 if (unic && (passlen2 == 0) && passlen1) {
1589 /* Only a ascii plaintext password was sent. */
1590 (void)srvstr_pull_talloc(talloc_tos(),
1596 STR_TERMINATE|STR_ASCII);
1598 (void)srvstr_pull_talloc(talloc_tos(),
1603 unic ? passlen2 : passlen1,
1607 reply_nterror(req, nt_status_squash(
1608 NT_STATUS_INVALID_PARAMETER));
1609 END_PROFILE(SMBsesssetupX);
1612 plaintext_password = data_blob(pass, strlen(pass)+1);
1615 p += passlen1 + passlen2;
1617 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1619 user = tmp ? tmp : "";
1621 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1623 domain = tmp ? tmp : "";
1625 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1627 native_os = tmp ? tmp : "";
1629 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1631 native_lanman = tmp ? tmp : "";
1633 /* not documented or decoded by Ethereal but there is one more
1634 * string in the extra bytes which is the same as the
1635 * PrimaryDomain when using extended security. Windows NT 4
1636 * and 2003 use this string to store the native lanman string.
1637 * Windows 9x does not include a string here at all so we have
1638 * to check if we have any extra bytes left */
1640 byte_count = SVAL(req->vwv+13, 0);
1641 if ( PTR_DIFF(p, save_p) < byte_count) {
1642 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1644 primary_domain = tmp ? tmp : "";
1646 primary_domain = talloc_strdup(talloc_tos(), "null");
1649 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1650 "PrimaryDomain=[%s]\n",
1651 domain, native_os, native_lanman, primary_domain));
1653 if ( ra_type == RA_WIN2K ) {
1654 if ( strlen(native_lanman) == 0 )
1655 ra_lanman_string( primary_domain );
1657 ra_lanman_string( native_lanman );
1662 if (SVAL(req->vwv+4, 0) == 0) {
1663 setup_new_vc_session(req->sconn->msg_ctx);
1666 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1667 domain, user, get_remote_machine_name()));
1670 if (sconn->smb1.negprot.spnego) {
1672 /* This has to be here, because this is a perfectly
1673 * valid behaviour for guest logons :-( */
1675 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1676 "at 'normal' session setup after "
1677 "negotiating spnego.\n"));
1678 reply_nterror(req, nt_status_squash(
1679 NT_STATUS_LOGON_FAILURE));
1680 END_PROFILE(SMBsesssetupX);
1683 fstrcpy(sub_user, user);
1685 fstrcpy(sub_user, lp_guestaccount());
1688 sub_set_smb_name(sub_user);
1690 reload_services(True);
1692 if (lp_security() == SEC_SHARE) {
1693 /* In share level we should ignore any passwords */
1695 data_blob_free(&lm_resp);
1696 data_blob_free(&nt_resp);
1697 data_blob_clear_free(&plaintext_password);
1699 map_username(sub_user);
1700 add_session_user(sconn, sub_user);
1701 add_session_workgroup(sconn, domain);
1702 /* Then force it to null for the benfit of the code below */
1708 nt_status = check_guest_password(&server_info);
1710 } else if (doencrypt) {
1711 struct auth_context *negprot_auth_context = NULL;
1712 negprot_auth_context = sconn->smb1.negprot.auth_context;
1713 if (!negprot_auth_context) {
1714 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1715 "session setup without negprot denied!\n"));
1716 reply_nterror(req, nt_status_squash(
1717 NT_STATUS_LOGON_FAILURE));
1718 END_PROFILE(SMBsesssetupX);
1721 nt_status = make_user_info_for_reply_enc(&user_info, user,
1724 if (NT_STATUS_IS_OK(nt_status)) {
1725 nt_status = negprot_auth_context->check_ntlm_password(
1726 negprot_auth_context,
1731 struct auth_context *plaintext_auth_context = NULL;
1733 nt_status = make_auth_context_subsystem(
1734 &plaintext_auth_context);
1736 if (NT_STATUS_IS_OK(nt_status)) {
1739 plaintext_auth_context->get_ntlm_challenge(
1740 plaintext_auth_context, chal);
1742 if (!make_user_info_for_reply(&user_info,
1744 plaintext_password)) {
1745 nt_status = NT_STATUS_NO_MEMORY;
1748 if (NT_STATUS_IS_OK(nt_status)) {
1749 nt_status = plaintext_auth_context->check_ntlm_password(
1750 plaintext_auth_context,
1754 TALLOC_FREE(plaintext_auth_context);
1759 free_user_info(&user_info);
1761 if (!NT_STATUS_IS_OK(nt_status)) {
1762 nt_status = do_map_to_guest(nt_status, &server_info,
1766 if (!NT_STATUS_IS_OK(nt_status)) {
1767 data_blob_free(&nt_resp);
1768 data_blob_free(&lm_resp);
1769 data_blob_clear_free(&plaintext_password);
1770 reply_nterror(req, nt_status_squash(nt_status));
1771 END_PROFILE(SMBsesssetupX);
1775 /* Ensure we can't possible take a code path leading to a
1778 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1779 END_PROFILE(SMBsesssetupX);
1783 if (!server_info->ptok) {
1784 nt_status = create_local_token(server_info);
1786 if (!NT_STATUS_IS_OK(nt_status)) {
1787 DEBUG(10, ("create_local_token failed: %s\n",
1788 nt_errstr(nt_status)));
1789 data_blob_free(&nt_resp);
1790 data_blob_free(&lm_resp);
1791 data_blob_clear_free(&plaintext_password);
1792 reply_nterror(req, nt_status_squash(nt_status));
1793 END_PROFILE(SMBsesssetupX);
1798 data_blob_clear_free(&plaintext_password);
1800 /* it's ok - setup a reply */
1801 reply_outbuf(req, 3, 0);
1802 if (get_Protocol() >= PROTOCOL_NT1) {
1803 push_signature(&req->outbuf);
1804 /* perhaps grab OS version here?? */
1807 if (server_info->guest) {
1808 SSVAL(req->outbuf,smb_vwv2,1);
1811 /* register the name and uid as being validated, so further connections
1812 to a uid can get through without a password, on the same VC */
1814 if (lp_security() == SEC_SHARE) {
1815 sess_vuid = UID_FIELD_INVALID;
1816 TALLOC_FREE(server_info);
1818 /* Ignore the initial vuid. */
1819 sess_vuid = register_initial_vuid(sconn);
1820 if (sess_vuid == UID_FIELD_INVALID) {
1821 data_blob_free(&nt_resp);
1822 data_blob_free(&lm_resp);
1823 reply_nterror(req, nt_status_squash(
1824 NT_STATUS_LOGON_FAILURE));
1825 END_PROFILE(SMBsesssetupX);
1828 /* register_existing_vuid keeps the server info */
1829 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1831 nt_resp.data ? nt_resp : lm_resp,
1833 if (sess_vuid == UID_FIELD_INVALID) {
1834 data_blob_free(&nt_resp);
1835 data_blob_free(&lm_resp);
1836 reply_nterror(req, nt_status_squash(
1837 NT_STATUS_LOGON_FAILURE));
1838 END_PROFILE(SMBsesssetupX);
1842 /* current_user_info is changed on new vuid */
1843 reload_services( True );
1846 data_blob_free(&nt_resp);
1847 data_blob_free(&lm_resp);
1849 SSVAL(req->outbuf,smb_uid,sess_vuid);
1850 SSVAL(req->inbuf,smb_uid,sess_vuid);
1851 req->vuid = sess_vuid;
1853 if (!sconn->smb1.sessions.done_sesssetup) {
1854 sconn->smb1.sessions.max_send =
1855 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1857 sconn->smb1.sessions.done_sesssetup = true;
1859 END_PROFILE(SMBsesssetupX);