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 = req->sconn;
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 = req->sconn;
639 if (NT_STATUS_IS_OK(nt_status)) {
640 server_info = auth_ntlmssp_server_info(talloc_tos(), (*auth_ntlmssp_state));
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 = req->sconn;
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 = req->sconn;
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 = req->sconn;
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 struct shutdown_state {
1364 struct messaging_context *msg_ctx;
1367 static int shutdown_other_smbds(const struct connections_key *key,
1368 const struct connections_data *crec,
1371 struct shutdown_state *state = (struct shutdown_state *)private_data;
1373 if (!process_exists(crec->pid)) {
1377 if (procid_is_me(&crec->pid)) {
1381 if (strcmp(state->ip, crec->addr) != 0) {
1385 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1386 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1389 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1394 static void setup_new_vc_session(struct messaging_context *msg_ctx)
1396 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1397 "compatible we would close all old resources.\n"));
1400 invalidate_all_vuids();
1402 if (lp_reset_on_zero_vc()) {
1403 char addr[INET6_ADDRSTRLEN];
1404 struct shutdown_state state;
1406 state.ip = client_addr(get_client_fd(),addr,sizeof(addr));
1407 state.msg_ctx = msg_ctx;
1408 connections_forall_read(shutdown_other_smbds, &state);
1412 /****************************************************************************
1413 Reply to a session setup command.
1414 ****************************************************************************/
1416 void reply_sesssetup_and_X(struct smb_request *req)
1422 DATA_BLOB plaintext_password;
1425 fstring sub_user; /* Sanitised username for substituion */
1427 const char *native_os;
1428 const char *native_lanman;
1429 const char *primary_domain;
1430 struct auth_usersupplied_info *user_info = NULL;
1431 struct auth_serversupplied_info *server_info = NULL;
1432 uint16 smb_flag2 = req->flags2;
1435 struct smbd_server_connection *sconn = req->sconn;
1437 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1439 START_PROFILE(SMBsesssetupX);
1441 ZERO_STRUCT(lm_resp);
1442 ZERO_STRUCT(nt_resp);
1443 ZERO_STRUCT(plaintext_password);
1445 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1447 /* a SPNEGO session setup has 12 command words, whereas a normal
1448 NT1 session setup has 13. See the cifs spec. */
1449 if (req->wct == 12 &&
1450 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1452 if (!sconn->smb1.negprot.spnego) {
1453 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1454 "at SPNEGO session setup when it was not "
1456 reply_nterror(req, nt_status_squash(
1457 NT_STATUS_LOGON_FAILURE));
1458 END_PROFILE(SMBsesssetupX);
1462 if (SVAL(req->vwv+4, 0) == 0) {
1463 setup_new_vc_session(req->sconn->msg_ctx);
1466 reply_sesssetup_and_X_spnego(req);
1467 END_PROFILE(SMBsesssetupX);
1471 smb_bufsize = SVAL(req->vwv+2, 0);
1473 if (get_Protocol() < PROTOCOL_NT1) {
1474 uint16 passlen1 = SVAL(req->vwv+7, 0);
1476 /* Never do NT status codes with protocols before NT1 as we
1477 * don't get client caps. */
1478 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1480 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1481 reply_nterror(req, nt_status_squash(
1482 NT_STATUS_INVALID_PARAMETER));
1483 END_PROFILE(SMBsesssetupX);
1488 lm_resp = data_blob(req->buf, passlen1);
1490 plaintext_password = data_blob(req->buf, passlen1+1);
1491 /* Ensure null termination */
1492 plaintext_password.data[passlen1] = 0;
1495 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1496 req->buf + passlen1, STR_TERMINATE);
1497 user = tmp ? tmp : "";
1502 uint16 passlen1 = SVAL(req->vwv+7, 0);
1503 uint16 passlen2 = SVAL(req->vwv+8, 0);
1504 enum remote_arch_types ra_type = get_remote_arch();
1505 const uint8_t *p = req->buf;
1506 const uint8_t *save_p = req->buf;
1510 if(global_client_caps == 0) {
1511 global_client_caps = IVAL(req->vwv+11, 0);
1513 if (!(global_client_caps & CAP_STATUS32)) {
1514 remove_from_common_flags2(
1515 FLAGS2_32_BIT_ERROR_CODES);
1518 /* client_caps is used as final determination if
1519 * client is NT or Win95. This is needed to return
1520 * the correct error codes in some circumstances.
1523 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1524 ra_type == RA_WIN95) {
1525 if(!(global_client_caps & (CAP_NT_SMBS|
1527 set_remote_arch( RA_WIN95);
1533 /* both Win95 and WinNT stuff up the password
1534 * lengths for non-encrypting systems. Uggh.
1536 if passlen1==24 its a win95 system, and its setting
1537 the password length incorrectly. Luckily it still
1538 works with the default code because Win95 will null
1539 terminate the password anyway
1541 if passlen1>0 and passlen2>0 then maybe its a NT box
1542 and its setting passlen2 to some random value which
1543 really stuffs things up. we need to fix that one. */
1545 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1551 /* check for nasty tricks */
1552 if (passlen1 > MAX_PASS_LEN
1553 || passlen1 > smbreq_bufrem(req, p)) {
1554 reply_nterror(req, nt_status_squash(
1555 NT_STATUS_INVALID_PARAMETER));
1556 END_PROFILE(SMBsesssetupX);
1560 if (passlen2 > MAX_PASS_LEN
1561 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1562 reply_nterror(req, nt_status_squash(
1563 NT_STATUS_INVALID_PARAMETER));
1564 END_PROFILE(SMBsesssetupX);
1568 /* Save the lanman2 password and the NT md4 password. */
1570 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1575 lm_resp = data_blob(p, passlen1);
1576 nt_resp = data_blob(p+passlen1, passlen2);
1577 } else if (lp_security() != SEC_SHARE) {
1579 * In share level we should ignore any passwords, so
1580 * only read them if we're not.
1583 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1585 if (unic && (passlen2 == 0) && passlen1) {
1586 /* Only a ascii plaintext password was sent. */
1587 (void)srvstr_pull_talloc(talloc_tos(),
1593 STR_TERMINATE|STR_ASCII);
1595 (void)srvstr_pull_talloc(talloc_tos(),
1600 unic ? passlen2 : passlen1,
1604 reply_nterror(req, nt_status_squash(
1605 NT_STATUS_INVALID_PARAMETER));
1606 END_PROFILE(SMBsesssetupX);
1609 plaintext_password = data_blob(pass, strlen(pass)+1);
1612 p += passlen1 + passlen2;
1614 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1616 user = tmp ? tmp : "";
1618 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1620 domain = tmp ? tmp : "";
1622 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1624 native_os = tmp ? tmp : "";
1626 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1628 native_lanman = tmp ? tmp : "";
1630 /* not documented or decoded by Ethereal but there is one more
1631 * string in the extra bytes which is the same as the
1632 * PrimaryDomain when using extended security. Windows NT 4
1633 * and 2003 use this string to store the native lanman string.
1634 * Windows 9x does not include a string here at all so we have
1635 * to check if we have any extra bytes left */
1637 byte_count = SVAL(req->vwv+13, 0);
1638 if ( PTR_DIFF(p, save_p) < byte_count) {
1639 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1641 primary_domain = tmp ? tmp : "";
1643 primary_domain = talloc_strdup(talloc_tos(), "null");
1646 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1647 "PrimaryDomain=[%s]\n",
1648 domain, native_os, native_lanman, primary_domain));
1650 if ( ra_type == RA_WIN2K ) {
1651 if ( strlen(native_lanman) == 0 )
1652 ra_lanman_string( primary_domain );
1654 ra_lanman_string( native_lanman );
1659 if (SVAL(req->vwv+4, 0) == 0) {
1660 setup_new_vc_session(req->sconn->msg_ctx);
1663 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1664 domain, user, get_remote_machine_name()));
1667 if (sconn->smb1.negprot.spnego) {
1669 /* This has to be here, because this is a perfectly
1670 * valid behaviour for guest logons :-( */
1672 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1673 "at 'normal' session setup after "
1674 "negotiating spnego.\n"));
1675 reply_nterror(req, nt_status_squash(
1676 NT_STATUS_LOGON_FAILURE));
1677 END_PROFILE(SMBsesssetupX);
1680 fstrcpy(sub_user, user);
1682 fstrcpy(sub_user, lp_guestaccount());
1685 sub_set_smb_name(sub_user);
1687 reload_services(True);
1689 if (lp_security() == SEC_SHARE) {
1690 /* In share level we should ignore any passwords */
1692 data_blob_free(&lm_resp);
1693 data_blob_free(&nt_resp);
1694 data_blob_clear_free(&plaintext_password);
1696 map_username(sub_user);
1697 add_session_user(sconn, sub_user);
1698 add_session_workgroup(sconn, domain);
1699 /* Then force it to null for the benfit of the code below */
1705 nt_status = check_guest_password(&server_info);
1707 } else if (doencrypt) {
1708 struct auth_context *negprot_auth_context = NULL;
1709 negprot_auth_context = sconn->smb1.negprot.auth_context;
1710 if (!negprot_auth_context) {
1711 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1712 "session setup without negprot denied!\n"));
1713 reply_nterror(req, nt_status_squash(
1714 NT_STATUS_LOGON_FAILURE));
1715 END_PROFILE(SMBsesssetupX);
1718 nt_status = make_user_info_for_reply_enc(&user_info, user,
1721 if (NT_STATUS_IS_OK(nt_status)) {
1722 nt_status = negprot_auth_context->check_ntlm_password(
1723 negprot_auth_context,
1728 struct auth_context *plaintext_auth_context = NULL;
1730 nt_status = make_auth_context_subsystem(
1731 &plaintext_auth_context);
1733 if (NT_STATUS_IS_OK(nt_status)) {
1736 plaintext_auth_context->get_ntlm_challenge(
1737 plaintext_auth_context, chal);
1739 if (!make_user_info_for_reply(&user_info,
1741 plaintext_password)) {
1742 nt_status = NT_STATUS_NO_MEMORY;
1745 if (NT_STATUS_IS_OK(nt_status)) {
1746 nt_status = plaintext_auth_context->check_ntlm_password(
1747 plaintext_auth_context,
1751 (plaintext_auth_context->free)(
1752 &plaintext_auth_context);
1757 free_user_info(&user_info);
1759 if (!NT_STATUS_IS_OK(nt_status)) {
1760 nt_status = do_map_to_guest(nt_status, &server_info,
1764 if (!NT_STATUS_IS_OK(nt_status)) {
1765 data_blob_free(&nt_resp);
1766 data_blob_free(&lm_resp);
1767 data_blob_clear_free(&plaintext_password);
1768 reply_nterror(req, nt_status_squash(nt_status));
1769 END_PROFILE(SMBsesssetupX);
1773 /* Ensure we can't possible take a code path leading to a
1776 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1777 END_PROFILE(SMBsesssetupX);
1781 if (!server_info->ptok) {
1782 nt_status = create_local_token(server_info);
1784 if (!NT_STATUS_IS_OK(nt_status)) {
1785 DEBUG(10, ("create_local_token failed: %s\n",
1786 nt_errstr(nt_status)));
1787 data_blob_free(&nt_resp);
1788 data_blob_free(&lm_resp);
1789 data_blob_clear_free(&plaintext_password);
1790 reply_nterror(req, nt_status_squash(nt_status));
1791 END_PROFILE(SMBsesssetupX);
1796 data_blob_clear_free(&plaintext_password);
1798 /* it's ok - setup a reply */
1799 reply_outbuf(req, 3, 0);
1800 if (get_Protocol() >= PROTOCOL_NT1) {
1801 push_signature(&req->outbuf);
1802 /* perhaps grab OS version here?? */
1805 if (server_info->guest) {
1806 SSVAL(req->outbuf,smb_vwv2,1);
1809 /* register the name and uid as being validated, so further connections
1810 to a uid can get through without a password, on the same VC */
1812 if (lp_security() == SEC_SHARE) {
1813 sess_vuid = UID_FIELD_INVALID;
1814 TALLOC_FREE(server_info);
1816 /* Ignore the initial vuid. */
1817 sess_vuid = register_initial_vuid(sconn);
1818 if (sess_vuid == UID_FIELD_INVALID) {
1819 data_blob_free(&nt_resp);
1820 data_blob_free(&lm_resp);
1821 reply_nterror(req, nt_status_squash(
1822 NT_STATUS_LOGON_FAILURE));
1823 END_PROFILE(SMBsesssetupX);
1826 /* register_existing_vuid keeps the server info */
1827 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1829 nt_resp.data ? nt_resp : lm_resp,
1831 if (sess_vuid == UID_FIELD_INVALID) {
1832 data_blob_free(&nt_resp);
1833 data_blob_free(&lm_resp);
1834 reply_nterror(req, nt_status_squash(
1835 NT_STATUS_LOGON_FAILURE));
1836 END_PROFILE(SMBsesssetupX);
1840 /* current_user_info is changed on new vuid */
1841 reload_services( True );
1844 data_blob_free(&nt_resp);
1845 data_blob_free(&lm_resp);
1847 SSVAL(req->outbuf,smb_uid,sess_vuid);
1848 SSVAL(req->inbuf,smb_uid,sess_vuid);
1849 req->vuid = sess_vuid;
1851 if (!sconn->smb1.sessions.done_sesssetup) {
1852 sconn->smb1.sessions.max_send =
1853 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1855 sconn->smb1.sessions.done_sesssetup = true;
1857 END_PROFILE(SMBsesssetupX);