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 static NTSTATUS do_map_to_guest(NTSTATUS status,
45 struct auth_serversupplied_info **server_info,
46 const char *user, const char *domain)
48 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
49 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
50 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
51 DEBUG(3,("No such user %s [%s] - using guest account\n",
53 status = make_server_info_guest(NULL, server_info);
57 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
58 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
59 DEBUG(3,("Registered username %s for guest access\n",
61 status = make_server_info_guest(NULL, server_info);
68 /****************************************************************************
69 Add the standard 'Samba' signature to the end of the session setup.
70 ****************************************************************************/
72 static int push_signature(uint8 **outbuf)
79 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
81 if (tmp == -1) return -1;
84 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
85 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
89 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
92 if (tmp == -1) return -1;
95 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
97 if (tmp == -1) return -1;
103 /****************************************************************************
104 Send a security blob via a session setup reply.
105 ****************************************************************************/
107 static void reply_sesssetup_blob(struct smb_request *req,
111 if (!NT_STATUS_IS_OK(nt_status) &&
112 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
113 reply_nterror(req, nt_status_squash(nt_status));
117 nt_status = nt_status_squash(nt_status);
118 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
119 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
120 SSVAL(req->outbuf, smb_vwv3, blob.length);
122 if ((message_push_blob(&req->outbuf, blob) == -1)
123 || (push_signature(&req->outbuf) == -1)) {
124 reply_nterror(req, NT_STATUS_NO_MEMORY);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
134 struct auth_context *auth_context;
135 struct auth_usersupplied_info *user_info = NULL;
138 unsigned char chal[8];
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
149 if (!make_user_info_guest(&user_info)) {
150 (auth_context->free)(&auth_context);
151 return NT_STATUS_NO_MEMORY;
154 nt_status = auth_context->check_ntlm_password(auth_context,
157 (auth_context->free)(&auth_context);
158 free_user_info(&user_info);
166 /* Experiment that failed. See "only happens with a KDC" comment below. */
167 /****************************************************************************
168 Cerate a clock skew error blob for a Windows client.
169 ****************************************************************************/
171 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
173 krb5_context context = NULL;
174 krb5_error_code kerr = 0;
176 krb5_principal host_princ = NULL;
177 char *host_princ_s = NULL;
180 *pblob_out = data_blob_null;
182 initialize_krb5_error_table();
183 kerr = krb5_init_context(&context);
187 /* Create server principal. */
188 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
192 strlower_m(host_princ_s);
194 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
196 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
197 "for name %s: Error %s\n",
198 host_princ_s, error_message(kerr) ));
202 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
205 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
206 "failed: Error %s\n",
207 error_message(kerr) ));
211 *pblob_out = data_blob(reply.data, reply.length);
212 kerberos_free_data_contents(context,&reply);
218 SAFE_FREE(host_princ_s);
221 krb5_free_principal(context, host_princ);
223 krb5_free_context(context);
228 /****************************************************************************
229 Reply to a session setup spnego negotiate packet for kerberos.
230 ****************************************************************************/
232 static void reply_spnego_kerberos(struct smb_request *req,
236 bool *p_invalidate_vuid)
240 char *client, *p, *domain;
241 fstring netbios_domain_name;
244 int sess_vuid = req->vuid;
245 NTSTATUS ret = NT_STATUS_OK;
246 DATA_BLOB ap_rep, ap_rep_wrapped, response;
247 struct auth_serversupplied_info *server_info = NULL;
248 DATA_BLOB session_key = data_blob_null;
250 DATA_BLOB nullblob = data_blob_null;
251 fstring real_username;
252 bool map_domainuser_to_guest = False;
253 bool username_was_mapped;
254 struct PAC_LOGON_INFO *logon_info = NULL;
255 struct smbd_server_connection *sconn = smbd_server_conn;
259 ZERO_STRUCT(ap_rep_wrapped);
260 ZERO_STRUCT(response);
262 /* Normally we will always invalidate the intermediate vuid. */
263 *p_invalidate_vuid = True;
265 mem_ctx = talloc_init("reply_spnego_kerberos");
266 if (mem_ctx == NULL) {
267 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
271 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
272 talloc_destroy(mem_ctx);
273 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
277 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
278 &client, &logon_info, &ap_rep,
281 data_blob_free(&ticket);
283 if (!NT_STATUS_IS_OK(ret)) {
285 /* Experiment that failed.
286 * See "only happens with a KDC" comment below. */
288 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
291 * Windows in this case returns
292 * NT_STATUS_MORE_PROCESSING_REQUIRED
293 * with a negTokenTarg blob containing an krb5_error
294 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
295 * The client then fixes its clock and continues rather
296 * than giving an error. JRA.
297 * -- Looks like this only happens with a KDC. JRA.
300 bool ok = make_krb5_skew_error(&ap_rep);
302 talloc_destroy(mem_ctx);
303 return ERROR_NT(nt_status_squash(
304 NT_STATUS_LOGON_FAILURE));
306 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
308 response = spnego_gen_auth_response(&ap_rep_wrapped,
309 ret, OID_KERBEROS5_OLD);
310 reply_sesssetup_blob(conn, inbuf, outbuf, response,
311 NT_STATUS_MORE_PROCESSING_REQUIRED);
314 * In this one case we don't invalidate the
315 * intermediate vuid as we're expecting the client
316 * to re-use it for the next sessionsetupX packet. JRA.
319 *p_invalidate_vuid = False;
321 data_blob_free(&ap_rep);
322 data_blob_free(&ap_rep_wrapped);
323 data_blob_free(&response);
324 talloc_destroy(mem_ctx);
325 return -1; /* already replied */
328 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
329 ret = NT_STATUS_LOGON_FAILURE;
332 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
334 talloc_destroy(mem_ctx);
335 reply_nterror(req, nt_status_squash(ret));
339 DEBUG(3,("Ticket name is [%s]\n", client));
341 p = strchr_m(client, '@');
343 DEBUG(3,("Doesn't look like a valid principal\n"));
344 data_blob_free(&ap_rep);
345 data_blob_free(&session_key);
346 talloc_destroy(mem_ctx);
347 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
353 /* save the PAC data if we have it */
356 netsamlogon_cache_store( client, &logon_info->info3 );
359 if (!strequal(p+1, lp_realm())) {
360 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
361 if (!lp_allow_trusted_domains()) {
362 data_blob_free(&ap_rep);
363 data_blob_free(&session_key);
364 talloc_destroy(mem_ctx);
365 reply_nterror(req, nt_status_squash(
366 NT_STATUS_LOGON_FAILURE));
371 /* this gives a fully qualified user name (ie. with full realm).
372 that leads to very long usernames, but what else can we do? */
376 if (logon_info && logon_info->info3.base.domain.string) {
377 fstrcpy(netbios_domain_name,
378 logon_info->info3.base.domain.string);
379 domain = netbios_domain_name;
380 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
384 /* If we have winbind running, we can (and must) shorten the
385 username by using the short netbios name. Otherwise we will
386 have inconsistent user names. With Kerberos, we get the
387 fully qualified realm, with ntlmssp we get the short
388 name. And even w2k3 does use ntlmssp if you for example
389 connect to an ip address. */
392 struct wbcDomainInfo *info = NULL;
394 DEBUG(10, ("Mapping [%s] to short name\n", domain));
396 wbc_status = wbcDomainInfo(domain, &info);
398 if (WBC_ERROR_IS_OK(wbc_status)) {
400 fstrcpy(netbios_domain_name,
404 domain = netbios_domain_name;
405 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
407 DEBUG(3, ("Could not find short name: %s\n",
408 wbcErrorString(wbc_status)));
412 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
414 /* lookup the passwd struct, create a new user if necessary */
416 username_was_mapped = map_username(user);
418 pw = smb_getpwnam( mem_ctx, user, real_username, True );
421 /* if a real user check pam account restrictions */
422 /* only really perfomed if "obey pam restriction" is true */
423 /* do this before an eventual mapping to guest occurs */
424 ret = smb_pam_accountcheck(pw->pw_name);
425 if ( !NT_STATUS_IS_OK(ret)) {
426 DEBUG(1,("PAM account restriction "
427 "prevents user login\n"));
428 data_blob_free(&ap_rep);
429 data_blob_free(&session_key);
430 TALLOC_FREE(mem_ctx);
431 reply_nterror(req, nt_status_squash(ret));
438 /* this was originally the behavior of Samba 2.2, if a user
439 did not have a local uid but has been authenticated, then
440 map them to a guest account */
442 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
443 map_domainuser_to_guest = True;
444 fstrcpy(user,lp_guestaccount());
445 pw = smb_getpwnam( mem_ctx, user, real_username, True );
448 /* extra sanity check that the guest account is valid */
451 DEBUG(1,("Username %s is invalid on this system\n",
453 data_blob_free(&ap_rep);
454 data_blob_free(&session_key);
455 TALLOC_FREE(mem_ctx);
456 reply_nterror(req, nt_status_squash(
457 NT_STATUS_LOGON_FAILURE));
462 /* setup the string used by %U */
464 sub_set_smb_name( real_username );
465 reload_services(True);
467 if ( map_domainuser_to_guest ) {
468 make_server_info_guest(NULL, &server_info);
469 } else if (logon_info) {
470 /* pass the unmapped username here since map_username()
471 will be called again from inside make_server_info_info3() */
473 ret = make_server_info_info3(mem_ctx, client, domain,
474 &server_info, &logon_info->info3);
475 if ( !NT_STATUS_IS_OK(ret) ) {
476 DEBUG(1,("make_server_info_info3 failed: %s!\n",
478 data_blob_free(&ap_rep);
479 data_blob_free(&session_key);
480 TALLOC_FREE(mem_ctx);
481 reply_nterror(req, nt_status_squash(ret));
487 * We didn't get a PAC, we have to make up the user
488 * ourselves. Try to ask the pdb backend to provide
489 * SID consistency with ntlmssp session setup
491 struct samu *sampass;
493 sampass = samu_new(talloc_tos());
494 if (sampass == NULL) {
495 ret = NT_STATUS_NO_MEMORY;
496 data_blob_free(&ap_rep);
497 data_blob_free(&session_key);
498 TALLOC_FREE(mem_ctx);
499 reply_nterror(req, nt_status_squash(ret));
503 if (pdb_getsampwnam(sampass, real_username)) {
504 DEBUG(10, ("found user %s in passdb, calling "
505 "make_server_info_sam\n", real_username));
506 ret = make_server_info_sam(&server_info, sampass);
507 TALLOC_FREE(sampass);
510 * User not in passdb, make it up artificially
512 TALLOC_FREE(sampass);
513 DEBUG(10, ("didn't find user %s in passdb, calling "
514 "make_server_info_pw\n", real_username));
515 ret = make_server_info_pw(&server_info, real_username,
519 if ( !NT_STATUS_IS_OK(ret) ) {
520 DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
522 data_blob_free(&ap_rep);
523 data_blob_free(&session_key);
524 TALLOC_FREE(mem_ctx);
525 reply_nterror(req, nt_status_squash(ret));
529 /* make_server_info_pw does not set the domain. Without this
530 * we end up with the local netbios name in substitutions for
533 if (server_info->info3 != NULL) {
534 server_info->info3->base.domain.string =
535 talloc_strdup(server_info->info3, domain);
539 server_info->nss_token |= username_was_mapped;
541 /* we need to build the token for the user. make_server_info_guest()
544 if ( !server_info->ptok ) {
545 ret = create_local_token( server_info );
546 if ( !NT_STATUS_IS_OK(ret) ) {
547 DEBUG(10,("failed to create local token: %s\n",
549 data_blob_free(&ap_rep);
550 data_blob_free(&session_key);
551 TALLOC_FREE( mem_ctx );
552 TALLOC_FREE( server_info );
553 reply_nterror(req, nt_status_squash(ret));
558 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
559 sess_vuid = register_initial_vuid(sconn);
562 data_blob_free(&server_info->user_session_key);
563 server_info->user_session_key = session_key;
564 talloc_steal(server_info, session_key.data);
566 session_key = data_blob_null;
568 /* register_existing_vuid keeps the server info */
569 /* register_existing_vuid takes ownership of session_key on success,
570 * no need to free after this on success. A better interface would copy
573 sess_vuid = register_existing_vuid(sconn,
579 reply_outbuf(req, 4, 0);
580 SSVAL(req->outbuf,smb_uid,sess_vuid);
582 if (sess_vuid == UID_FIELD_INVALID ) {
583 ret = NT_STATUS_LOGON_FAILURE;
585 /* current_user_info is changed on new vuid */
586 reload_services( True );
588 SSVAL(req->outbuf, smb_vwv3, 0);
590 if (server_info->guest) {
591 SSVAL(req->outbuf,smb_vwv2,1);
594 SSVAL(req->outbuf, smb_uid, sess_vuid);
596 /* Successful logon. Keep this vuid. */
597 *p_invalidate_vuid = False;
600 /* wrap that up in a nice GSS-API wrapping */
601 if (NT_STATUS_IS_OK(ret)) {
602 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
605 ap_rep_wrapped = data_blob_null;
607 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
609 reply_sesssetup_blob(req, response, ret);
611 data_blob_free(&ap_rep);
612 data_blob_free(&ap_rep_wrapped);
613 data_blob_free(&response);
614 TALLOC_FREE(mem_ctx);
619 /****************************************************************************
620 Send a session setup reply, wrapped in SPNEGO.
621 Get vuid and check first.
622 End the NTLMSSP exchange context if we are OK/complete fail
623 This should be split into two functions, one to handle each
624 leg of the NTLM auth steps.
625 ***************************************************************************/
627 static void reply_spnego_ntlmssp(struct smb_request *req,
629 struct auth_ntlmssp_state **auth_ntlmssp_state,
630 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
634 bool do_invalidate = true;
636 struct auth_serversupplied_info *server_info = NULL;
637 struct smbd_server_connection *sconn = smbd_server_conn;
639 if (NT_STATUS_IS_OK(nt_status)) {
640 nt_status = auth_ntlmssp_server_info(talloc_tos(), (*auth_ntlmssp_state), &server_info);
642 /* Note that this server_info won't have a session
643 * key. But for map to guest, that's exactly the right
644 * thing - we can't reasonably guess the key the
645 * client wants, as the password was wrong */
646 nt_status = do_map_to_guest(nt_status,
648 auth_ntlmssp_get_username(*auth_ntlmssp_state),
649 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
652 reply_outbuf(req, 4, 0);
654 SSVAL(req->outbuf, smb_uid, vuid);
656 if (NT_STATUS_IS_OK(nt_status)) {
657 DATA_BLOB nullblob = data_blob_null;
659 if (!is_partial_auth_vuid(sconn, vuid)) {
660 nt_status = NT_STATUS_LOGON_FAILURE;
664 /* register_existing_vuid keeps the server info */
665 if (register_existing_vuid(sconn, vuid,
666 server_info, nullblob,
667 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
669 /* The problem is, *auth_ntlmssp_state points
670 * into the vuser this will have
671 * talloc_free()'ed in
672 * register_existing_vuid() */
673 do_invalidate = false;
674 nt_status = NT_STATUS_LOGON_FAILURE;
678 /* current_user_info is changed on new vuid */
679 reload_services( True );
681 SSVAL(req->outbuf, smb_vwv3, 0);
683 if (server_info->guest) {
684 SSVAL(req->outbuf,smb_vwv2,1);
691 response = spnego_gen_auth_response(ntlmssp_blob,
694 response = *ntlmssp_blob;
697 reply_sesssetup_blob(req, response, nt_status);
699 data_blob_free(&response);
702 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
703 and the other end, that we are not finished yet. */
705 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
706 /* NB. This is *NOT* an error case. JRA */
708 auth_ntlmssp_end(auth_ntlmssp_state);
709 if (!NT_STATUS_IS_OK(nt_status)) {
710 /* Kill the intermediate vuid */
711 invalidate_vuid(sconn, vuid);
717 /****************************************************************************
718 Is this a krb5 mechanism ?
719 ****************************************************************************/
721 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
722 DATA_BLOB *pblob_out,
725 char *OIDs[ASN1_MAX_OIDS];
727 NTSTATUS ret = NT_STATUS_OK;
729 *kerb_mechOID = NULL;
731 /* parse out the OIDs and the first sec blob */
732 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
733 return NT_STATUS_LOGON_FAILURE;
736 /* only look at the first OID for determining the mechToken --
737 according to RFC2478, we should choose the one we want
738 and renegotiate, but i smell a client bug here..
740 Problem observed when connecting to a member (samba box)
741 of an AD domain as a user in a Samba domain. Samba member
742 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
743 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
744 NTLMSSP mechtoken. --jerry */
747 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
748 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
749 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
750 if (*kerb_mechOID == NULL) {
751 ret = NT_STATUS_NO_MEMORY;
756 for (i=0;OIDs[i];i++) {
757 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
758 talloc_free(OIDs[i]);
763 /****************************************************************************
764 Fall back from krb5 to NTLMSSP.
765 ****************************************************************************/
767 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
772 reply_outbuf(req, 4, 0);
773 SSVAL(req->outbuf,smb_uid,vuid);
775 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
776 "but set to downgrade to NTLMSSP\n"));
778 response = spnego_gen_auth_response(NULL,
779 NT_STATUS_MORE_PROCESSING_REQUIRED,
781 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
782 data_blob_free(&response);
785 /****************************************************************************
786 Reply to a session setup spnego negotiate packet.
787 ****************************************************************************/
789 static void reply_spnego_negotiate(struct smb_request *req,
792 struct auth_ntlmssp_state **auth_ntlmssp_state)
796 char *kerb_mech = NULL;
798 struct smbd_server_connection *sconn = smbd_server_conn;
800 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
801 if (!NT_STATUS_IS_OK(status)) {
802 /* Kill the intermediate vuid */
803 invalidate_vuid(sconn, vuid);
804 reply_nterror(req, nt_status_squash(status));
808 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
809 (unsigned long)secblob.length));
812 if (kerb_mech && ((lp_security()==SEC_ADS) ||
813 USE_KERBEROS_KEYTAB) ) {
814 bool destroy_vuid = True;
815 reply_spnego_kerberos(req, &secblob, kerb_mech,
816 vuid, &destroy_vuid);
817 data_blob_free(&secblob);
819 /* Kill the intermediate vuid */
820 invalidate_vuid(sconn, vuid);
822 SAFE_FREE(kerb_mech);
827 if (*auth_ntlmssp_state) {
828 auth_ntlmssp_end(auth_ntlmssp_state);
832 data_blob_free(&secblob);
833 /* The mechtoken is a krb5 ticket, but
834 * we need to fall back to NTLM. */
835 reply_spnego_downgrade_to_ntlmssp(req, vuid);
836 SAFE_FREE(kerb_mech);
840 status = auth_ntlmssp_start(auth_ntlmssp_state);
841 if (!NT_STATUS_IS_OK(status)) {
842 /* Kill the intermediate vuid */
843 invalidate_vuid(sconn, vuid);
844 reply_nterror(req, nt_status_squash(status));
848 status = auth_ntlmssp_update(*auth_ntlmssp_state,
851 data_blob_free(&secblob);
853 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
854 &chal, status, OID_NTLMSSP, true);
856 data_blob_free(&chal);
858 /* already replied */
862 /****************************************************************************
863 Reply to a session setup spnego auth packet.
864 ****************************************************************************/
866 static void reply_spnego_auth(struct smb_request *req,
869 struct auth_ntlmssp_state **auth_ntlmssp_state)
871 DATA_BLOB auth = data_blob_null;
872 DATA_BLOB auth_reply = data_blob_null;
873 DATA_BLOB secblob = data_blob_null;
874 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
875 struct smbd_server_connection *sconn = smbd_server_conn;
877 if (!spnego_parse_auth(blob1, &auth)) {
879 file_save("auth.dat", blob1.data, blob1.length);
881 /* Kill the intermediate vuid */
882 invalidate_vuid(sconn, vuid);
884 reply_nterror(req, nt_status_squash(
885 NT_STATUS_LOGON_FAILURE));
889 if (auth.data[0] == ASN1_APPLICATION(0)) {
890 /* Might be a second negTokenTarg packet */
891 char *kerb_mech = NULL;
893 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
895 if (!NT_STATUS_IS_OK(status)) {
896 /* Kill the intermediate vuid */
897 invalidate_vuid(sconn, vuid);
898 reply_nterror(req, nt_status_squash(status));
902 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
903 (unsigned long)secblob.length));
905 if (kerb_mech && ((lp_security()==SEC_ADS) ||
906 USE_KERBEROS_KEYTAB)) {
907 bool destroy_vuid = True;
908 reply_spnego_kerberos(req, &secblob, kerb_mech,
909 vuid, &destroy_vuid);
910 data_blob_free(&secblob);
911 data_blob_free(&auth);
913 /* Kill the intermediate vuid */
914 invalidate_vuid(sconn, vuid);
916 SAFE_FREE(kerb_mech);
920 /* Can't blunder into NTLMSSP auth if we have
924 /* Kill the intermediate vuid */
925 invalidate_vuid(sconn, vuid);
926 DEBUG(3,("reply_spnego_auth: network "
927 "misconfiguration, client sent us a "
928 "krb5 ticket and kerberos security "
930 reply_nterror(req, nt_status_squash(
931 NT_STATUS_LOGON_FAILURE));
932 SAFE_FREE(kerb_mech);
936 /* If we get here it wasn't a negTokenTarg auth packet. */
937 data_blob_free(&secblob);
939 if (!*auth_ntlmssp_state) {
940 status = auth_ntlmssp_start(auth_ntlmssp_state);
941 if (!NT_STATUS_IS_OK(status)) {
942 /* Kill the intermediate vuid */
943 invalidate_vuid(sconn, vuid);
944 reply_nterror(req, nt_status_squash(status));
949 status = auth_ntlmssp_update(*auth_ntlmssp_state,
952 data_blob_free(&auth);
954 /* Don't send the mechid as we've already sent this (RFC4178). */
956 reply_spnego_ntlmssp(req, vuid,
958 &auth_reply, status, NULL, true);
960 data_blob_free(&auth_reply);
962 /* and tell smbd that we have already replied to this packet */
966 /****************************************************************************
967 Delete an entry on the list.
968 ****************************************************************************/
970 static void delete_partial_auth(struct smbd_server_connection *sconn,
971 struct pending_auth_data *pad)
976 DLIST_REMOVE(sconn->smb1.pd_list, pad);
977 data_blob_free(&pad->partial_data);
981 /****************************************************************************
982 Search for a partial SPNEGO auth fragment matching an smbpid.
983 ****************************************************************************/
985 static struct pending_auth_data *get_pending_auth_data(
986 struct smbd_server_connection *sconn,
989 struct pending_auth_data *pad;
991 * NOTE: using the smbpid here is completely wrong...
993 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
995 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
996 if (pad->smbpid == smbpid) {
1003 /****************************************************************************
1004 Check the size of an SPNEGO blob. If we need more return
1005 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
1006 the blob to be more than 64k.
1007 ****************************************************************************/
1009 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
1010 uint16 smbpid, uint16 vuid,
1013 struct pending_auth_data *pad = NULL;
1015 size_t needed_len = 0;
1017 pad = get_pending_auth_data(sconn, smbpid);
1019 /* Ensure we have some data. */
1020 if (pblob->length == 0) {
1021 /* Caller can cope. */
1022 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1023 delete_partial_auth(sconn, pad);
1024 return NT_STATUS_OK;
1027 /* Were we waiting for more data ? */
1030 size_t copy_len = MIN(65536, pblob->length);
1032 /* Integer wrap paranoia.... */
1034 if (pad->partial_data.length + copy_len <
1035 pad->partial_data.length ||
1036 pad->partial_data.length + copy_len < copy_len) {
1038 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1039 "pad->partial_data.length = %u, "
1041 (unsigned int)pad->partial_data.length,
1042 (unsigned int)copy_len ));
1044 delete_partial_auth(sconn, pad);
1045 return NT_STATUS_INVALID_PARAMETER;
1048 DEBUG(10,("check_spnego_blob_complete: "
1049 "pad->partial_data.length = %u, "
1050 "pad->needed_len = %u, "
1052 "pblob->length = %u,\n",
1053 (unsigned int)pad->partial_data.length,
1054 (unsigned int)pad->needed_len,
1055 (unsigned int)copy_len,
1056 (unsigned int)pblob->length ));
1058 tmp_blob = data_blob(NULL,
1059 pad->partial_data.length + copy_len);
1061 /* Concatenate the two (up to copy_len) bytes. */
1062 memcpy(tmp_blob.data,
1063 pad->partial_data.data,
1064 pad->partial_data.length);
1065 memcpy(tmp_blob.data + pad->partial_data.length,
1069 /* Replace the partial data. */
1070 data_blob_free(&pad->partial_data);
1071 pad->partial_data = tmp_blob;
1072 ZERO_STRUCT(tmp_blob);
1075 if (pblob->length >= pad->needed_len) {
1076 /* Yes, replace pblob. */
1077 data_blob_free(pblob);
1078 *pblob = pad->partial_data;
1079 ZERO_STRUCT(pad->partial_data);
1080 delete_partial_auth(sconn, pad);
1081 return NT_STATUS_OK;
1084 /* Still need more data. */
1085 pad->needed_len -= copy_len;
1086 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1089 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1090 (pblob->data[0] != ASN1_CONTEXT(1))) {
1091 /* Not something we can determine the
1094 return NT_STATUS_OK;
1097 /* This is a new SPNEGO sessionsetup - see if
1098 * the data given in this blob is enough.
1101 data = asn1_init(NULL);
1103 return NT_STATUS_NO_MEMORY;
1106 asn1_load(data, *pblob);
1107 asn1_start_tag(data, pblob->data[0]);
1108 if (data->has_error || data->nesting == NULL) {
1110 /* Let caller catch. */
1111 return NT_STATUS_OK;
1114 /* Integer wrap paranoia.... */
1116 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1117 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1119 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1120 "data.nesting->taglen = %u, "
1121 "data.nesting->start = %u\n",
1122 (unsigned int)data->nesting->taglen,
1123 (unsigned int)data->nesting->start ));
1126 return NT_STATUS_INVALID_PARAMETER;
1129 /* Total length of the needed asn1 is the tag length
1130 * plus the current offset. */
1132 needed_len = data->nesting->taglen + data->nesting->start;
1135 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1136 "pblob->length = %u\n",
1137 (unsigned int)needed_len,
1138 (unsigned int)pblob->length ));
1140 if (needed_len <= pblob->length) {
1141 /* Nothing to do - blob is complete. */
1142 return NT_STATUS_OK;
1145 /* Refuse the blob if it's bigger than 64k. */
1146 if (needed_len > 65536) {
1147 DEBUG(2,("check_spnego_blob_complete: needed_len "
1149 (unsigned int)needed_len ));
1150 return NT_STATUS_INVALID_PARAMETER;
1153 /* We must store this blob until complete. */
1154 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1155 return NT_STATUS_NO_MEMORY;
1157 pad->needed_len = needed_len - pblob->length;
1158 pad->partial_data = data_blob(pblob->data, pblob->length);
1159 if (pad->partial_data.data == NULL) {
1161 return NT_STATUS_NO_MEMORY;
1163 pad->smbpid = smbpid;
1165 DLIST_ADD(sconn->smb1.pd_list, pad);
1167 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1170 /****************************************************************************
1171 Reply to a session setup command.
1172 conn POINTER CAN BE NULL HERE !
1173 ****************************************************************************/
1175 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1181 const char *native_os;
1182 const char *native_lanman;
1183 const char *primary_domain;
1185 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1186 enum remote_arch_types ra_type = get_remote_arch();
1187 int vuid = req->vuid;
1188 user_struct *vuser = NULL;
1189 NTSTATUS status = NT_STATUS_OK;
1190 uint16 smbpid = req->smbpid;
1191 struct smbd_server_connection *sconn = smbd_server_conn;
1193 DEBUG(3,("Doing spnego session setup\n"));
1195 if (global_client_caps == 0) {
1196 global_client_caps = IVAL(req->vwv+10, 0);
1198 if (!(global_client_caps & CAP_STATUS32)) {
1199 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1206 if (data_blob_len == 0) {
1207 /* an invalid request */
1208 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1212 bufrem = smbreq_bufrem(req, p);
1213 /* pull the spnego blob */
1214 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1217 file_save("negotiate.dat", blob1.data, blob1.length);
1220 p2 = (char *)req->buf + blob1.length;
1222 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1224 native_os = tmp ? tmp : "";
1226 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1228 native_lanman = tmp ? tmp : "";
1230 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1232 primary_domain = tmp ? tmp : "";
1234 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1235 native_os, native_lanman, primary_domain));
1237 if ( ra_type == RA_WIN2K ) {
1238 /* Vista sets neither the OS or lanman strings */
1240 if ( !strlen(native_os) && !strlen(native_lanman) )
1241 set_remote_arch(RA_VISTA);
1243 /* Windows 2003 doesn't set the native lanman string,
1244 but does set primary domain which is a bug I think */
1246 if ( !strlen(native_lanman) ) {
1247 ra_lanman_string( primary_domain );
1249 ra_lanman_string( native_lanman );
1253 /* Did we get a valid vuid ? */
1254 if (!is_partial_auth_vuid(sconn, vuid)) {
1255 /* No, then try and see if this is an intermediate sessionsetup
1256 * for a large SPNEGO packet. */
1257 struct pending_auth_data *pad;
1258 pad = get_pending_auth_data(sconn, smbpid);
1260 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1261 "pending vuid %u\n",
1262 (unsigned int)pad->vuid ));
1267 /* Do we have a valid vuid now ? */
1268 if (!is_partial_auth_vuid(sconn, vuid)) {
1269 /* No, start a new authentication setup. */
1270 vuid = register_initial_vuid(sconn);
1271 if (vuid == UID_FIELD_INVALID) {
1272 data_blob_free(&blob1);
1273 reply_nterror(req, nt_status_squash(
1274 NT_STATUS_INVALID_PARAMETER));
1279 vuser = get_partial_auth_user_struct(sconn, vuid);
1280 /* This MUST be valid. */
1282 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1285 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1286 * sessionsetup requests as the Windows limit on the security blob
1287 * field is 4k. Bug #4400. JRA.
1290 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1291 if (!NT_STATUS_IS_OK(status)) {
1292 if (!NT_STATUS_EQUAL(status,
1293 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1294 /* Real error - kill the intermediate vuid */
1295 invalidate_vuid(sconn, vuid);
1297 data_blob_free(&blob1);
1298 reply_nterror(req, nt_status_squash(status));
1302 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1304 /* its a negTokenTarg packet */
1306 reply_spnego_negotiate(req, vuid, blob1,
1307 &vuser->auth_ntlmssp_state);
1308 data_blob_free(&blob1);
1312 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1314 /* its a auth packet */
1316 reply_spnego_auth(req, vuid, blob1,
1317 &vuser->auth_ntlmssp_state);
1318 data_blob_free(&blob1);
1322 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1325 if (!vuser->auth_ntlmssp_state) {
1326 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 /* Kill the intermediate vuid */
1329 invalidate_vuid(sconn, vuid);
1330 data_blob_free(&blob1);
1331 reply_nterror(req, nt_status_squash(status));
1336 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1339 data_blob_free(&blob1);
1341 reply_spnego_ntlmssp(req, vuid,
1342 &vuser->auth_ntlmssp_state,
1343 &chal, status, OID_NTLMSSP, false);
1344 data_blob_free(&chal);
1348 /* what sort of packet is this? */
1349 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1351 data_blob_free(&blob1);
1353 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1356 /****************************************************************************
1357 On new VC == 0, shutdown *all* old connections and users.
1358 It seems that only NT4.x does this. At W2K and above (XP etc.).
1359 a new session setup with VC==0 is ignored.
1360 ****************************************************************************/
1362 static int shutdown_other_smbds(const struct connections_key *key,
1363 const struct connections_data *crec,
1366 const char *ip = (const char *)private_data;
1368 if (!process_exists(crec->pid)) {
1372 if (procid_is_me(&crec->pid)) {
1376 if (strcmp(ip, crec->addr) != 0) {
1380 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1381 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1383 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1388 static void setup_new_vc_session(void)
1390 char addr[INET6_ADDRSTRLEN];
1392 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1393 "compatible we would close all old resources.\n"));
1396 invalidate_all_vuids();
1398 if (lp_reset_on_zero_vc()) {
1399 connections_forall_read(shutdown_other_smbds,
1400 CONST_DISCARD(void *,
1401 client_addr(get_client_fd(),addr,sizeof(addr))));
1405 /****************************************************************************
1406 Reply to a session setup command.
1407 ****************************************************************************/
1409 void reply_sesssetup_and_X(struct smb_request *req)
1415 DATA_BLOB plaintext_password;
1418 fstring sub_user; /* Sainitised username for substituion */
1420 const char *native_os;
1421 const char *native_lanman;
1422 const char *primary_domain;
1423 struct auth_usersupplied_info *user_info = NULL;
1424 struct auth_serversupplied_info *server_info = NULL;
1425 uint16 smb_flag2 = req->flags2;
1428 struct smbd_server_connection *sconn = smbd_server_conn;
1430 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1432 START_PROFILE(SMBsesssetupX);
1434 ZERO_STRUCT(lm_resp);
1435 ZERO_STRUCT(nt_resp);
1436 ZERO_STRUCT(plaintext_password);
1438 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1440 /* a SPNEGO session setup has 12 command words, whereas a normal
1441 NT1 session setup has 13. See the cifs spec. */
1442 if (req->wct == 12 &&
1443 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1445 if (!sconn->smb1.negprot.spnego) {
1446 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1447 "at SPNEGO session setup when it was not "
1449 reply_nterror(req, nt_status_squash(
1450 NT_STATUS_LOGON_FAILURE));
1451 END_PROFILE(SMBsesssetupX);
1455 if (SVAL(req->vwv+4, 0) == 0) {
1456 setup_new_vc_session();
1459 reply_sesssetup_and_X_spnego(req);
1460 END_PROFILE(SMBsesssetupX);
1464 smb_bufsize = SVAL(req->vwv+2, 0);
1466 if (get_Protocol() < PROTOCOL_NT1) {
1467 uint16 passlen1 = SVAL(req->vwv+7, 0);
1469 /* Never do NT status codes with protocols before NT1 as we
1470 * don't get client caps. */
1471 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1473 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1474 reply_nterror(req, nt_status_squash(
1475 NT_STATUS_INVALID_PARAMETER));
1476 END_PROFILE(SMBsesssetupX);
1481 lm_resp = data_blob(req->buf, passlen1);
1483 plaintext_password = data_blob(req->buf, passlen1+1);
1484 /* Ensure null termination */
1485 plaintext_password.data[passlen1] = 0;
1488 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1489 req->buf + passlen1, STR_TERMINATE);
1490 user = tmp ? tmp : "";
1495 uint16 passlen1 = SVAL(req->vwv+7, 0);
1496 uint16 passlen2 = SVAL(req->vwv+8, 0);
1497 enum remote_arch_types ra_type = get_remote_arch();
1498 const uint8_t *p = req->buf;
1499 const uint8_t *save_p = req->buf;
1503 if(global_client_caps == 0) {
1504 global_client_caps = IVAL(req->vwv+11, 0);
1506 if (!(global_client_caps & CAP_STATUS32)) {
1507 remove_from_common_flags2(
1508 FLAGS2_32_BIT_ERROR_CODES);
1511 /* client_caps is used as final determination if
1512 * client is NT or Win95. This is needed to return
1513 * the correct error codes in some circumstances.
1516 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1517 ra_type == RA_WIN95) {
1518 if(!(global_client_caps & (CAP_NT_SMBS|
1520 set_remote_arch( RA_WIN95);
1526 /* both Win95 and WinNT stuff up the password
1527 * lengths for non-encrypting systems. Uggh.
1529 if passlen1==24 its a win95 system, and its setting
1530 the password length incorrectly. Luckily it still
1531 works with the default code because Win95 will null
1532 terminate the password anyway
1534 if passlen1>0 and passlen2>0 then maybe its a NT box
1535 and its setting passlen2 to some random value which
1536 really stuffs things up. we need to fix that one. */
1538 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1544 /* check for nasty tricks */
1545 if (passlen1 > MAX_PASS_LEN
1546 || passlen1 > smbreq_bufrem(req, p)) {
1547 reply_nterror(req, nt_status_squash(
1548 NT_STATUS_INVALID_PARAMETER));
1549 END_PROFILE(SMBsesssetupX);
1553 if (passlen2 > MAX_PASS_LEN
1554 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1555 reply_nterror(req, nt_status_squash(
1556 NT_STATUS_INVALID_PARAMETER));
1557 END_PROFILE(SMBsesssetupX);
1561 /* Save the lanman2 password and the NT md4 password. */
1563 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1568 lm_resp = data_blob(p, passlen1);
1569 nt_resp = data_blob(p+passlen1, passlen2);
1570 } else if (lp_security() != SEC_SHARE) {
1572 * In share level we should ignore any passwords, so
1573 * only read them if we're not.
1576 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1578 if (unic && (passlen2 == 0) && passlen1) {
1579 /* Only a ascii plaintext password was sent. */
1580 (void)srvstr_pull_talloc(talloc_tos(),
1586 STR_TERMINATE|STR_ASCII);
1588 (void)srvstr_pull_talloc(talloc_tos(),
1593 unic ? passlen2 : passlen1,
1597 reply_nterror(req, nt_status_squash(
1598 NT_STATUS_INVALID_PARAMETER));
1599 END_PROFILE(SMBsesssetupX);
1602 plaintext_password = data_blob(pass, strlen(pass)+1);
1605 p += passlen1 + passlen2;
1607 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1609 user = tmp ? tmp : "";
1611 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1613 domain = tmp ? tmp : "";
1615 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1617 native_os = tmp ? tmp : "";
1619 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1621 native_lanman = tmp ? tmp : "";
1623 /* not documented or decoded by Ethereal but there is one more
1624 * string in the extra bytes which is the same as the
1625 * PrimaryDomain when using extended security. Windows NT 4
1626 * and 2003 use this string to store the native lanman string.
1627 * Windows 9x does not include a string here at all so we have
1628 * to check if we have any extra bytes left */
1630 byte_count = SVAL(req->vwv+13, 0);
1631 if ( PTR_DIFF(p, save_p) < byte_count) {
1632 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1634 primary_domain = tmp ? tmp : "";
1636 primary_domain = talloc_strdup(talloc_tos(), "null");
1639 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1640 "PrimaryDomain=[%s]\n",
1641 domain, native_os, native_lanman, primary_domain));
1643 if ( ra_type == RA_WIN2K ) {
1644 if ( strlen(native_lanman) == 0 )
1645 ra_lanman_string( primary_domain );
1647 ra_lanman_string( native_lanman );
1652 if (SVAL(req->vwv+4, 0) == 0) {
1653 setup_new_vc_session();
1656 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1657 domain, user, get_remote_machine_name()));
1660 if (sconn->smb1.negprot.spnego) {
1662 /* This has to be here, because this is a perfectly
1663 * valid behaviour for guest logons :-( */
1665 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1666 "at 'normal' session setup after "
1667 "negotiating spnego.\n"));
1668 reply_nterror(req, nt_status_squash(
1669 NT_STATUS_LOGON_FAILURE));
1670 END_PROFILE(SMBsesssetupX);
1673 fstrcpy(sub_user, user);
1675 fstrcpy(sub_user, lp_guestaccount());
1678 sub_set_smb_name(sub_user);
1680 reload_services(True);
1682 if (lp_security() == SEC_SHARE) {
1683 /* In share level we should ignore any passwords */
1685 data_blob_free(&lm_resp);
1686 data_blob_free(&nt_resp);
1687 data_blob_clear_free(&plaintext_password);
1689 map_username(sub_user);
1690 add_session_user(sconn, sub_user);
1691 add_session_workgroup(sconn, domain);
1692 /* Then force it to null for the benfit of the code below */
1698 nt_status = check_guest_password(&server_info);
1700 } else if (doencrypt) {
1701 struct auth_context *negprot_auth_context = NULL;
1702 negprot_auth_context = sconn->smb1.negprot.auth_context;
1703 if (!negprot_auth_context) {
1704 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1705 "session setup without negprot denied!\n"));
1706 reply_nterror(req, nt_status_squash(
1707 NT_STATUS_LOGON_FAILURE));
1708 END_PROFILE(SMBsesssetupX);
1711 nt_status = make_user_info_for_reply_enc(&user_info, user,
1714 if (NT_STATUS_IS_OK(nt_status)) {
1715 nt_status = negprot_auth_context->check_ntlm_password(
1716 negprot_auth_context,
1721 struct auth_context *plaintext_auth_context = NULL;
1723 nt_status = make_auth_context_subsystem(
1724 &plaintext_auth_context);
1726 if (NT_STATUS_IS_OK(nt_status)) {
1729 plaintext_auth_context->get_ntlm_challenge(
1730 plaintext_auth_context, chal);
1732 if (!make_user_info_for_reply(&user_info,
1734 plaintext_password)) {
1735 nt_status = NT_STATUS_NO_MEMORY;
1738 if (NT_STATUS_IS_OK(nt_status)) {
1739 nt_status = plaintext_auth_context->check_ntlm_password(
1740 plaintext_auth_context,
1744 (plaintext_auth_context->free)(
1745 &plaintext_auth_context);
1750 free_user_info(&user_info);
1752 if (!NT_STATUS_IS_OK(nt_status)) {
1753 nt_status = do_map_to_guest(nt_status, &server_info,
1757 if (!NT_STATUS_IS_OK(nt_status)) {
1758 data_blob_free(&nt_resp);
1759 data_blob_free(&lm_resp);
1760 data_blob_clear_free(&plaintext_password);
1761 reply_nterror(req, nt_status_squash(nt_status));
1762 END_PROFILE(SMBsesssetupX);
1766 /* Ensure we can't possible take a code path leading to a
1769 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1770 END_PROFILE(SMBsesssetupX);
1774 if (!server_info->ptok) {
1775 nt_status = create_local_token(server_info);
1777 if (!NT_STATUS_IS_OK(nt_status)) {
1778 DEBUG(10, ("create_local_token failed: %s\n",
1779 nt_errstr(nt_status)));
1780 data_blob_free(&nt_resp);
1781 data_blob_free(&lm_resp);
1782 data_blob_clear_free(&plaintext_password);
1783 reply_nterror(req, nt_status_squash(nt_status));
1784 END_PROFILE(SMBsesssetupX);
1789 data_blob_clear_free(&plaintext_password);
1791 /* it's ok - setup a reply */
1792 reply_outbuf(req, 3, 0);
1793 if (get_Protocol() >= PROTOCOL_NT1) {
1794 push_signature(&req->outbuf);
1795 /* perhaps grab OS version here?? */
1798 if (server_info->guest) {
1799 SSVAL(req->outbuf,smb_vwv2,1);
1802 /* register the name and uid as being validated, so further connections
1803 to a uid can get through without a password, on the same VC */
1805 if (lp_security() == SEC_SHARE) {
1806 sess_vuid = UID_FIELD_INVALID;
1807 TALLOC_FREE(server_info);
1809 /* Ignore the initial vuid. */
1810 sess_vuid = register_initial_vuid(sconn);
1811 if (sess_vuid == UID_FIELD_INVALID) {
1812 data_blob_free(&nt_resp);
1813 data_blob_free(&lm_resp);
1814 reply_nterror(req, nt_status_squash(
1815 NT_STATUS_LOGON_FAILURE));
1816 END_PROFILE(SMBsesssetupX);
1819 /* register_existing_vuid keeps the server info */
1820 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1822 nt_resp.data ? nt_resp : lm_resp,
1824 if (sess_vuid == UID_FIELD_INVALID) {
1825 data_blob_free(&nt_resp);
1826 data_blob_free(&lm_resp);
1827 reply_nterror(req, nt_status_squash(
1828 NT_STATUS_LOGON_FAILURE));
1829 END_PROFILE(SMBsesssetupX);
1833 /* current_user_info is changed on new vuid */
1834 reload_services( True );
1837 data_blob_free(&nt_resp);
1838 data_blob_free(&lm_resp);
1840 SSVAL(req->outbuf,smb_uid,sess_vuid);
1841 SSVAL(req->inbuf,smb_uid,sess_vuid);
1842 req->vuid = sess_vuid;
1844 if (!sconn->smb1.sessions.done_sesssetup) {
1845 sconn->smb1.sessions.max_send =
1846 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1848 sconn->smb1.sessions.done_sesssetup = true;
1850 END_PROFILE(SMBsesssetupX);