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 "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../libcli/auth/ntlmssp.h"
31 #include "ntlmssp_wrap.h"
32 #include "../librpc/gen_ndr/krb5pac.h"
33 #include "libads/kerberos_proto.h"
34 #include "../lib/util/asn1.h"
37 #include "smbprofile.h"
39 /* For split krb5 SPNEGO blobs. */
40 struct pending_auth_data {
41 struct pending_auth_data *prev, *next;
42 uint16 vuid; /* Tag for this entry. */
43 uint16 smbpid; /* Alternate tag for this entry. */
45 DATA_BLOB partial_data;
49 on a logon error possibly map the error to success if "map to guest"
52 static NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
53 struct auth_serversupplied_info **server_info,
54 const char *user, const char *domain)
56 user = user ? user : "";
57 domain = domain ? domain : "";
59 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
60 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
61 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
62 DEBUG(3,("No such user %s [%s] - using guest account\n",
64 status = make_server_info_guest(NULL, server_info);
68 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
69 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
70 DEBUG(3,("Registered username %s for guest access\n",
72 status = make_server_info_guest(NULL, server_info);
80 on a logon error possibly map the error to success if "map to guest"
83 NTSTATUS do_map_to_guest(NTSTATUS status,
84 struct auth_session_info **session_info,
85 const char *user, const char *domain)
87 user = user ? user : "";
88 domain = domain ? domain : "";
90 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
91 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
92 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
93 DEBUG(3,("No such user %s [%s] - using guest account\n",
95 status = make_session_info_guest(NULL, session_info);
99 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
100 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
101 DEBUG(3,("Registered username %s for guest access\n",
103 status = make_session_info_guest(NULL, session_info);
110 /****************************************************************************
111 Add the standard 'Samba' signature to the end of the session setup.
112 ****************************************************************************/
114 static int push_signature(uint8 **outbuf)
121 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
123 if (tmp == -1) return -1;
126 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
127 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
131 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
134 if (tmp == -1) return -1;
137 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
139 if (tmp == -1) return -1;
145 /****************************************************************************
146 Send a security blob via a session setup reply.
147 ****************************************************************************/
149 static void reply_sesssetup_blob(struct smb_request *req,
153 if (!NT_STATUS_IS_OK(nt_status) &&
154 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
155 reply_nterror(req, nt_status_squash(nt_status));
159 nt_status = nt_status_squash(nt_status);
160 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
161 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
162 SSVAL(req->outbuf, smb_vwv3, blob.length);
164 if ((message_push_blob(&req->outbuf, blob) == -1)
165 || (push_signature(&req->outbuf) == -1)) {
166 reply_nterror(req, NT_STATUS_NO_MEMORY);
170 /****************************************************************************
171 Do a 'guest' logon, getting back the
172 ****************************************************************************/
174 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
175 struct auth_serversupplied_info **server_info)
177 struct auth_context *auth_context;
178 struct auth_usersupplied_info *user_info = NULL;
181 static unsigned char chal[8] = { 0, };
183 DEBUG(3,("Got anonymous request\n"));
185 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
186 if (!NT_STATUS_IS_OK(nt_status)) {
190 if (!make_user_info_guest(remote_address, &user_info)) {
191 TALLOC_FREE(auth_context);
192 return NT_STATUS_NO_MEMORY;
195 nt_status = auth_context->check_ntlm_password(auth_context,
198 TALLOC_FREE(auth_context);
199 free_user_info(&user_info);
207 /* Experiment that failed. See "only happens with a KDC" comment below. */
208 /****************************************************************************
209 Cerate a clock skew error blob for a Windows client.
210 ****************************************************************************/
212 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
214 krb5_context context = NULL;
215 krb5_error_code kerr = 0;
217 krb5_principal host_princ = NULL;
218 char *host_princ_s = NULL;
221 *pblob_out = data_blob_null;
223 initialize_krb5_error_table();
224 kerr = krb5_init_context(&context);
228 /* Create server principal. */
229 asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
233 strlower_m(host_princ_s);
235 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
237 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
238 "for name %s: Error %s\n",
239 host_princ_s, error_message(kerr) ));
243 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
246 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
247 "failed: Error %s\n",
248 error_message(kerr) ));
252 *pblob_out = data_blob(reply.data, reply.length);
253 kerberos_free_data_contents(context,&reply);
259 SAFE_FREE(host_princ_s);
262 krb5_free_principal(context, host_princ);
264 krb5_free_context(context);
269 /****************************************************************************
270 Reply to a session setup spnego negotiate packet for kerberos.
271 ****************************************************************************/
273 static void reply_spnego_kerberos(struct smb_request *req,
277 bool *p_invalidate_vuid)
282 int sess_vuid = req->vuid;
283 NTSTATUS ret = NT_STATUS_OK;
284 DATA_BLOB ap_rep, ap_rep_wrapped, response;
285 struct auth_session_info *session_info = NULL;
286 DATA_BLOB session_key = data_blob_null;
288 DATA_BLOB nullblob = data_blob_null;
289 bool map_domainuser_to_guest = False;
290 bool username_was_mapped;
291 struct PAC_LOGON_INFO *logon_info = NULL;
292 struct smbd_server_connection *sconn = req->sconn;
300 ZERO_STRUCT(ap_rep_wrapped);
301 ZERO_STRUCT(response);
303 /* Normally we will always invalidate the intermediate vuid. */
304 *p_invalidate_vuid = True;
306 mem_ctx = talloc_init("reply_spnego_kerberos");
307 if (mem_ctx == NULL) {
308 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
312 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
313 talloc_destroy(mem_ctx);
314 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
318 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
319 &principal, &logon_info, &ap_rep,
322 data_blob_free(&ticket);
324 if (!NT_STATUS_IS_OK(ret)) {
326 /* Experiment that failed.
327 * See "only happens with a KDC" comment below. */
329 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
332 * Windows in this case returns
333 * NT_STATUS_MORE_PROCESSING_REQUIRED
334 * with a negTokenTarg blob containing an krb5_error
335 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
336 * The client then fixes its clock and continues rather
337 * than giving an error. JRA.
338 * -- Looks like this only happens with a KDC. JRA.
341 bool ok = make_krb5_skew_error(&ap_rep);
343 talloc_destroy(mem_ctx);
344 return ERROR_NT(nt_status_squash(
345 NT_STATUS_LOGON_FAILURE));
347 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
349 response = spnego_gen_auth_response(&ap_rep_wrapped,
350 ret, OID_KERBEROS5_OLD);
351 reply_sesssetup_blob(conn, inbuf, outbuf, response,
352 NT_STATUS_MORE_PROCESSING_REQUIRED);
355 * In this one case we don't invalidate the
356 * intermediate vuid as we're expecting the client
357 * to re-use it for the next sessionsetupX packet. JRA.
360 *p_invalidate_vuid = False;
362 data_blob_free(&ap_rep);
363 data_blob_free(&ap_rep_wrapped);
364 data_blob_free(&response);
365 talloc_destroy(mem_ctx);
366 return -1; /* already replied */
369 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
370 ret = NT_STATUS_LOGON_FAILURE;
373 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
375 talloc_destroy(mem_ctx);
376 reply_nterror(req, nt_status_squash(ret));
380 ret = get_user_from_kerberos_info(talloc_tos(),
381 sconn->remote_hostname,
382 principal, logon_info,
383 &username_was_mapped,
384 &map_domainuser_to_guest,
386 &real_username, &pw);
387 if (!NT_STATUS_IS_OK(ret)) {
388 data_blob_free(&ap_rep);
389 data_blob_free(&session_key);
390 talloc_destroy(mem_ctx);
391 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
395 /* save the PAC data if we have it */
397 netsamlogon_cache_store(user, &logon_info->info3);
400 /* setup the string used by %U */
401 sub_set_smb_name(real_username);
403 /* reload services so that the new %U is taken into account */
404 reload_services(sconn->msg_ctx, sconn->sock, True);
406 ret = make_session_info_krb5(mem_ctx,
407 user, domain, real_username, pw,
408 logon_info, map_domainuser_to_guest,
412 data_blob_free(&session_key);
413 if (!NT_STATUS_IS_OK(ret)) {
414 DEBUG(1, ("make_server_info_krb5 failed!\n"));
415 data_blob_free(&ap_rep);
416 TALLOC_FREE(mem_ctx);
417 reply_nterror(req, nt_status_squash(ret));
421 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
422 sess_vuid = register_initial_vuid(sconn);
425 /* register_existing_vuid keeps the server info */
426 /* register_existing_vuid takes ownership of session_key on success,
427 * no need to free after this on success. A better interface would copy
430 sess_vuid = register_existing_vuid(sconn, sess_vuid,
431 session_info, nullblob, user);
433 reply_outbuf(req, 4, 0);
434 SSVAL(req->outbuf,smb_uid,sess_vuid);
436 if (sess_vuid == UID_FIELD_INVALID ) {
437 ret = NT_STATUS_LOGON_FAILURE;
439 /* current_user_info is changed on new vuid */
440 reload_services(sconn->msg_ctx, sconn->sock, True);
442 SSVAL(req->outbuf, smb_vwv3, 0);
444 if (session_info->unix_info->guest) {
445 SSVAL(req->outbuf,smb_vwv2,1);
448 SSVAL(req->outbuf, smb_uid, sess_vuid);
450 /* Successful logon. Keep this vuid. */
451 *p_invalidate_vuid = False;
454 /* wrap that up in a nice GSS-API wrapping */
455 if (NT_STATUS_IS_OK(ret)) {
456 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
459 ap_rep_wrapped = data_blob_null;
461 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
463 reply_sesssetup_blob(req, response, ret);
465 data_blob_free(&ap_rep);
466 data_blob_free(&ap_rep_wrapped);
467 data_blob_free(&response);
468 TALLOC_FREE(mem_ctx);
473 /****************************************************************************
474 Send a session setup reply, wrapped in SPNEGO.
475 Get vuid and check first.
476 End the NTLMSSP exchange context if we are OK/complete fail
477 This should be split into two functions, one to handle each
478 leg of the NTLM auth steps.
479 ***************************************************************************/
481 static void reply_spnego_ntlmssp(struct smb_request *req,
483 struct auth_ntlmssp_state **auth_ntlmssp_state,
484 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
488 bool do_invalidate = true;
490 struct auth_session_info *session_info = NULL;
491 struct smbd_server_connection *sconn = req->sconn;
493 if (NT_STATUS_IS_OK(nt_status)) {
494 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
495 (*auth_ntlmssp_state), &session_info);
497 /* Note that this session_info won't have a session
498 * key. But for map to guest, that's exactly the right
499 * thing - we can't reasonably guess the key the
500 * client wants, as the password was wrong */
501 nt_status = do_map_to_guest(nt_status,
503 auth_ntlmssp_get_username(*auth_ntlmssp_state),
504 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
507 reply_outbuf(req, 4, 0);
509 SSVAL(req->outbuf, smb_uid, vuid);
511 if (NT_STATUS_IS_OK(nt_status)) {
512 DATA_BLOB nullblob = data_blob_null;
514 if (!is_partial_auth_vuid(sconn, vuid)) {
515 nt_status = NT_STATUS_LOGON_FAILURE;
519 /* register_existing_vuid keeps the server info */
520 if (register_existing_vuid(sconn, vuid,
521 session_info, nullblob,
522 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
524 /* The problem is, *auth_ntlmssp_state points
525 * into the vuser this will have
526 * talloc_free()'ed in
527 * register_existing_vuid() */
528 do_invalidate = false;
529 nt_status = NT_STATUS_LOGON_FAILURE;
533 /* current_user_info is changed on new vuid */
534 reload_services(sconn->msg_ctx, sconn->sock, True);
536 SSVAL(req->outbuf, smb_vwv3, 0);
538 if (session_info->unix_info->guest) {
539 SSVAL(req->outbuf,smb_vwv2,1);
546 response = spnego_gen_auth_response(talloc_tos(),
550 response = *ntlmssp_blob;
553 reply_sesssetup_blob(req, response, nt_status);
555 data_blob_free(&response);
558 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
559 and the other end, that we are not finished yet. */
561 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
562 /* NB. This is *NOT* an error case. JRA */
564 TALLOC_FREE(*auth_ntlmssp_state);
565 if (!NT_STATUS_IS_OK(nt_status)) {
566 /* Kill the intermediate vuid */
567 invalidate_vuid(sconn, vuid);
573 /****************************************************************************
574 Is this a krb5 mechanism ?
575 ****************************************************************************/
577 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
579 DATA_BLOB *pblob_out,
582 char *OIDs[ASN1_MAX_OIDS];
584 NTSTATUS ret = NT_STATUS_OK;
586 *kerb_mechOID = NULL;
588 /* parse out the OIDs and the first sec blob */
589 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
591 return NT_STATUS_LOGON_FAILURE;
594 /* only look at the first OID for determining the mechToken --
595 according to RFC2478, we should choose the one we want
596 and renegotiate, but i smell a client bug here..
598 Problem observed when connecting to a member (samba box)
599 of an AD domain as a user in a Samba domain. Samba member
600 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
601 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
602 NTLMSSP mechtoken. --jerry */
605 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
606 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
607 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
608 if (*kerb_mechOID == NULL) {
609 ret = NT_STATUS_NO_MEMORY;
614 for (i=0;OIDs[i];i++) {
615 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
616 talloc_free(OIDs[i]);
621 /****************************************************************************
622 Fall back from krb5 to NTLMSSP.
623 ****************************************************************************/
625 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
630 reply_outbuf(req, 4, 0);
631 SSVAL(req->outbuf,smb_uid,vuid);
633 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
634 "but set to downgrade to NTLMSSP\n"));
636 response = spnego_gen_auth_response(talloc_tos(), NULL,
637 NT_STATUS_MORE_PROCESSING_REQUIRED,
639 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
640 data_blob_free(&response);
643 /****************************************************************************
644 Reply to a session setup spnego negotiate packet.
645 ****************************************************************************/
647 static void reply_spnego_negotiate(struct smb_request *req,
650 struct auth_ntlmssp_state **auth_ntlmssp_state)
654 char *kerb_mech = NULL;
656 struct smbd_server_connection *sconn = req->sconn;
658 status = parse_spnego_mechanisms(talloc_tos(),
659 blob1, &secblob, &kerb_mech);
660 if (!NT_STATUS_IS_OK(status)) {
661 /* Kill the intermediate vuid */
662 invalidate_vuid(sconn, vuid);
663 reply_nterror(req, nt_status_squash(status));
667 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
668 (unsigned long)secblob.length));
671 if (kerb_mech && ((lp_security()==SEC_ADS) ||
672 USE_KERBEROS_KEYTAB) ) {
673 bool destroy_vuid = True;
674 reply_spnego_kerberos(req, &secblob, kerb_mech,
675 vuid, &destroy_vuid);
676 data_blob_free(&secblob);
678 /* Kill the intermediate vuid */
679 invalidate_vuid(sconn, vuid);
681 TALLOC_FREE(kerb_mech);
686 TALLOC_FREE(*auth_ntlmssp_state);
689 data_blob_free(&secblob);
690 /* The mechtoken is a krb5 ticket, but
691 * we need to fall back to NTLM. */
692 reply_spnego_downgrade_to_ntlmssp(req, vuid);
693 TALLOC_FREE(kerb_mech);
697 status = auth_ntlmssp_start(sconn->remote_address,
699 if (!NT_STATUS_IS_OK(status)) {
700 /* Kill the intermediate vuid */
701 invalidate_vuid(sconn, vuid);
702 reply_nterror(req, nt_status_squash(status));
706 status = auth_ntlmssp_update(*auth_ntlmssp_state,
709 data_blob_free(&secblob);
711 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
712 &chal, status, OID_NTLMSSP, true);
714 data_blob_free(&chal);
716 /* already replied */
720 /****************************************************************************
721 Reply to a session setup spnego auth packet.
722 ****************************************************************************/
724 static void reply_spnego_auth(struct smb_request *req,
727 struct auth_ntlmssp_state **auth_ntlmssp_state)
729 DATA_BLOB auth = data_blob_null;
730 DATA_BLOB auth_reply = data_blob_null;
731 DATA_BLOB secblob = data_blob_null;
732 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
733 struct smbd_server_connection *sconn = req->sconn;
735 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
737 file_save("auth.dat", blob1.data, blob1.length);
739 /* Kill the intermediate vuid */
740 invalidate_vuid(sconn, vuid);
742 reply_nterror(req, nt_status_squash(
743 NT_STATUS_LOGON_FAILURE));
747 if (auth.data[0] == ASN1_APPLICATION(0)) {
748 /* Might be a second negTokenTarg packet */
749 char *kerb_mech = NULL;
751 status = parse_spnego_mechanisms(talloc_tos(),
752 auth, &secblob, &kerb_mech);
754 if (!NT_STATUS_IS_OK(status)) {
755 /* Kill the intermediate vuid */
756 invalidate_vuid(sconn, vuid);
757 reply_nterror(req, nt_status_squash(status));
761 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
762 (unsigned long)secblob.length));
764 if (kerb_mech && ((lp_security()==SEC_ADS) ||
765 USE_KERBEROS_KEYTAB)) {
766 bool destroy_vuid = True;
767 reply_spnego_kerberos(req, &secblob, kerb_mech,
768 vuid, &destroy_vuid);
769 data_blob_free(&secblob);
770 data_blob_free(&auth);
772 /* Kill the intermediate vuid */
773 invalidate_vuid(sconn, vuid);
775 TALLOC_FREE(kerb_mech);
779 /* Can't blunder into NTLMSSP auth if we have
783 /* Kill the intermediate vuid */
784 invalidate_vuid(sconn, vuid);
785 DEBUG(3,("reply_spnego_auth: network "
786 "misconfiguration, client sent us a "
787 "krb5 ticket and kerberos security "
789 reply_nterror(req, nt_status_squash(
790 NT_STATUS_LOGON_FAILURE));
791 TALLOC_FREE(kerb_mech);
795 /* If we get here it wasn't a negTokenTarg auth packet. */
796 data_blob_free(&secblob);
798 if (!*auth_ntlmssp_state) {
799 status = auth_ntlmssp_start(sconn->remote_address,
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));
809 status = auth_ntlmssp_update(*auth_ntlmssp_state,
812 data_blob_free(&auth);
814 /* Don't send the mechid as we've already sent this (RFC4178). */
816 reply_spnego_ntlmssp(req, vuid,
818 &auth_reply, status, NULL, true);
820 data_blob_free(&auth_reply);
822 /* and tell smbd that we have already replied to this packet */
826 /****************************************************************************
827 Delete an entry on the list.
828 ****************************************************************************/
830 static void delete_partial_auth(struct smbd_server_connection *sconn,
831 struct pending_auth_data *pad)
836 DLIST_REMOVE(sconn->smb1.pd_list, pad);
837 data_blob_free(&pad->partial_data);
841 /****************************************************************************
842 Search for a partial SPNEGO auth fragment matching an smbpid.
843 ****************************************************************************/
845 static struct pending_auth_data *get_pending_auth_data(
846 struct smbd_server_connection *sconn,
849 struct pending_auth_data *pad;
851 * NOTE: using the smbpid here is completely wrong...
853 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
855 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
856 if (pad->smbpid == smbpid) {
863 /****************************************************************************
864 Check the size of an SPNEGO blob. If we need more return
865 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
866 the blob to be more than 64k.
867 ****************************************************************************/
869 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
870 uint16 smbpid, uint16 vuid,
873 struct pending_auth_data *pad = NULL;
875 size_t needed_len = 0;
877 pad = get_pending_auth_data(sconn, smbpid);
879 /* Ensure we have some data. */
880 if (pblob->length == 0) {
881 /* Caller can cope. */
882 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
883 delete_partial_auth(sconn, pad);
887 /* Were we waiting for more data ? */
890 size_t copy_len = MIN(65536, pblob->length);
892 /* Integer wrap paranoia.... */
894 if (pad->partial_data.length + copy_len <
895 pad->partial_data.length ||
896 pad->partial_data.length + copy_len < copy_len) {
898 DEBUG(2,("check_spnego_blob_complete: integer wrap "
899 "pad->partial_data.length = %u, "
901 (unsigned int)pad->partial_data.length,
902 (unsigned int)copy_len ));
904 delete_partial_auth(sconn, pad);
905 return NT_STATUS_INVALID_PARAMETER;
908 DEBUG(10,("check_spnego_blob_complete: "
909 "pad->partial_data.length = %u, "
910 "pad->needed_len = %u, "
912 "pblob->length = %u,\n",
913 (unsigned int)pad->partial_data.length,
914 (unsigned int)pad->needed_len,
915 (unsigned int)copy_len,
916 (unsigned int)pblob->length ));
918 tmp_blob = data_blob(NULL,
919 pad->partial_data.length + copy_len);
921 /* Concatenate the two (up to copy_len) bytes. */
922 memcpy(tmp_blob.data,
923 pad->partial_data.data,
924 pad->partial_data.length);
925 memcpy(tmp_blob.data + pad->partial_data.length,
929 /* Replace the partial data. */
930 data_blob_free(&pad->partial_data);
931 pad->partial_data = tmp_blob;
932 ZERO_STRUCT(tmp_blob);
935 if (pblob->length >= pad->needed_len) {
936 /* Yes, replace pblob. */
937 data_blob_free(pblob);
938 *pblob = pad->partial_data;
939 ZERO_STRUCT(pad->partial_data);
940 delete_partial_auth(sconn, pad);
944 /* Still need more data. */
945 pad->needed_len -= copy_len;
946 return NT_STATUS_MORE_PROCESSING_REQUIRED;
949 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
950 (pblob->data[0] != ASN1_CONTEXT(1))) {
951 /* Not something we can determine the
957 /* This is a new SPNEGO sessionsetup - see if
958 * the data given in this blob is enough.
961 data = asn1_init(NULL);
963 return NT_STATUS_NO_MEMORY;
966 asn1_load(data, *pblob);
967 if (asn1_start_tag(data, pblob->data[0])) {
968 /* asn1_start_tag checks if the given
969 length of the blob is enough to complete
970 the tag. If it returns true we know
971 there is nothing to do - the blob is
977 if (data->nesting == NULL) {
978 /* Incorrect tag, allocation failed,
979 or reading the tag length failed.
980 Let the caller catch. */
985 /* Here we know asn1_start_tag() has set data->has_error to true.
986 asn1_tag_remaining() will have failed due to the given blob
987 being too short. We need to work out how short. */
989 /* Integer wrap paranoia.... */
991 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
992 data->nesting->taglen + data->nesting->start < data->nesting->start) {
994 DEBUG(2,("check_spnego_blob_complete: integer wrap "
995 "data.nesting->taglen = %u, "
996 "data.nesting->start = %u\n",
997 (unsigned int)data->nesting->taglen,
998 (unsigned int)data->nesting->start ));
1001 return NT_STATUS_INVALID_PARAMETER;
1004 /* Total length of the needed asn1 is the tag length
1005 * plus the current offset. */
1007 needed_len = data->nesting->taglen + data->nesting->start;
1010 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1011 "pblob->length = %u\n",
1012 (unsigned int)needed_len,
1013 (unsigned int)pblob->length ));
1015 if (needed_len <= pblob->length) {
1016 /* Nothing to do - blob is complete. */
1017 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
1018 above should have caught this !!! */
1019 DEBUG(0,("check_spnego_blob_complete: logic "
1020 "error (needed_len = %u, "
1021 "pblob->length = %u).\n",
1022 (unsigned int)needed_len,
1023 (unsigned int)pblob->length ));
1024 return NT_STATUS_OK;
1027 /* Refuse the blob if it's bigger than 64k. */
1028 if (needed_len > 65536) {
1029 DEBUG(2,("check_spnego_blob_complete: needed_len "
1031 (unsigned int)needed_len ));
1032 return NT_STATUS_INVALID_PARAMETER;
1035 /* We must store this blob until complete. */
1036 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1037 return NT_STATUS_NO_MEMORY;
1039 pad->needed_len = needed_len - pblob->length;
1040 pad->partial_data = data_blob(pblob->data, pblob->length);
1041 if (pad->partial_data.data == NULL) {
1043 return NT_STATUS_NO_MEMORY;
1045 pad->smbpid = smbpid;
1047 DLIST_ADD(sconn->smb1.pd_list, pad);
1049 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1052 /****************************************************************************
1053 Reply to a session setup command.
1054 conn POINTER CAN BE NULL HERE !
1055 ****************************************************************************/
1057 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1063 const char *native_os;
1064 const char *native_lanman;
1065 const char *primary_domain;
1067 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1068 enum remote_arch_types ra_type = get_remote_arch();
1069 int vuid = req->vuid;
1070 user_struct *vuser = NULL;
1071 NTSTATUS status = NT_STATUS_OK;
1072 uint16 smbpid = req->smbpid;
1073 struct smbd_server_connection *sconn = req->sconn;
1075 DEBUG(3,("Doing spnego session setup\n"));
1077 if (global_client_caps == 0) {
1078 global_client_caps = IVAL(req->vwv+10, 0);
1080 if (!(global_client_caps & CAP_STATUS32)) {
1081 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1088 if (data_blob_len == 0) {
1089 /* an invalid request */
1090 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1094 bufrem = smbreq_bufrem(req, p);
1095 /* pull the spnego blob */
1096 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1099 file_save("negotiate.dat", blob1.data, blob1.length);
1102 p2 = (const char *)req->buf + blob1.length;
1104 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1106 native_os = tmp ? tmp : "";
1108 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1110 native_lanman = tmp ? tmp : "";
1112 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1114 primary_domain = tmp ? tmp : "";
1116 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1117 native_os, native_lanman, primary_domain));
1119 if ( ra_type == RA_WIN2K ) {
1120 /* Vista sets neither the OS or lanman strings */
1122 if ( !strlen(native_os) && !strlen(native_lanman) )
1123 set_remote_arch(RA_VISTA);
1125 /* Windows 2003 doesn't set the native lanman string,
1126 but does set primary domain which is a bug I think */
1128 if ( !strlen(native_lanman) ) {
1129 ra_lanman_string( primary_domain );
1131 ra_lanman_string( native_lanman );
1133 } else if ( ra_type == RA_VISTA ) {
1134 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1135 set_remote_arch(RA_OSX);
1139 /* Did we get a valid vuid ? */
1140 if (!is_partial_auth_vuid(sconn, vuid)) {
1141 /* No, then try and see if this is an intermediate sessionsetup
1142 * for a large SPNEGO packet. */
1143 struct pending_auth_data *pad;
1144 pad = get_pending_auth_data(sconn, smbpid);
1146 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1147 "pending vuid %u\n",
1148 (unsigned int)pad->vuid ));
1153 /* Do we have a valid vuid now ? */
1154 if (!is_partial_auth_vuid(sconn, vuid)) {
1155 /* No, start a new authentication setup. */
1156 vuid = register_initial_vuid(sconn);
1157 if (vuid == UID_FIELD_INVALID) {
1158 data_blob_free(&blob1);
1159 reply_nterror(req, nt_status_squash(
1160 NT_STATUS_INVALID_PARAMETER));
1165 vuser = get_partial_auth_user_struct(sconn, vuid);
1166 /* This MUST be valid. */
1168 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1171 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1172 * sessionsetup requests as the Windows limit on the security blob
1173 * field is 4k. Bug #4400. JRA.
1176 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 if (!NT_STATUS_EQUAL(status,
1179 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1180 /* Real error - kill the intermediate vuid */
1181 invalidate_vuid(sconn, vuid);
1183 data_blob_free(&blob1);
1184 reply_nterror(req, nt_status_squash(status));
1188 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1190 /* its a negTokenTarg packet */
1192 reply_spnego_negotiate(req, vuid, blob1,
1193 &vuser->auth_ntlmssp_state);
1194 data_blob_free(&blob1);
1198 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1200 /* its a auth packet */
1202 reply_spnego_auth(req, vuid, blob1,
1203 &vuser->auth_ntlmssp_state);
1204 data_blob_free(&blob1);
1208 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1211 if (!vuser->auth_ntlmssp_state) {
1212 status = auth_ntlmssp_start(sconn->remote_address,
1213 &vuser->auth_ntlmssp_state);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 /* Kill the intermediate vuid */
1216 invalidate_vuid(sconn, vuid);
1217 data_blob_free(&blob1);
1218 reply_nterror(req, nt_status_squash(status));
1223 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1226 data_blob_free(&blob1);
1228 reply_spnego_ntlmssp(req, vuid,
1229 &vuser->auth_ntlmssp_state,
1230 &chal, status, OID_NTLMSSP, false);
1231 data_blob_free(&chal);
1235 /* what sort of packet is this? */
1236 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1238 data_blob_free(&blob1);
1240 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1243 /****************************************************************************
1244 On new VC == 0, shutdown *all* old connections and users.
1245 It seems that only NT4.x does this. At W2K and above (XP etc.).
1246 a new session setup with VC==0 is ignored.
1247 ****************************************************************************/
1249 struct shutdown_state {
1251 struct messaging_context *msg_ctx;
1254 static int shutdown_other_smbds(const struct connections_key *key,
1255 const struct connections_data *crec,
1258 struct shutdown_state *state = (struct shutdown_state *)private_data;
1260 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1261 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1263 if (!process_exists(crec->pid)) {
1264 DEBUG(10, ("process does not exist\n"));
1268 if (procid_is_me(&crec->pid)) {
1269 DEBUG(10, ("It's me\n"));
1273 if (strcmp(state->ip, crec->addr) != 0) {
1274 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1278 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1279 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1282 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1287 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1289 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1290 "compatible we would close all old resources.\n"));
1293 invalidate_all_vuids();
1295 if (lp_reset_on_zero_vc()) {
1297 struct shutdown_state state;
1299 addr = tsocket_address_inet_addr_string(
1300 sconn->remote_address, talloc_tos());
1305 state.msg_ctx = sconn->msg_ctx;
1306 connections_forall_read(shutdown_other_smbds, &state);
1311 /****************************************************************************
1312 Reply to a session setup command.
1313 ****************************************************************************/
1315 void reply_sesssetup_and_X(struct smb_request *req)
1321 DATA_BLOB plaintext_password;
1324 fstring sub_user; /* Sanitised username for substituion */
1326 const char *native_os;
1327 const char *native_lanman;
1328 const char *primary_domain;
1329 struct auth_usersupplied_info *user_info = NULL;
1330 struct auth_serversupplied_info *server_info = NULL;
1331 struct auth_session_info *session_info = NULL;
1332 uint16 smb_flag2 = req->flags2;
1335 struct smbd_server_connection *sconn = req->sconn;
1337 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1339 START_PROFILE(SMBsesssetupX);
1341 ZERO_STRUCT(lm_resp);
1342 ZERO_STRUCT(nt_resp);
1343 ZERO_STRUCT(plaintext_password);
1345 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1347 /* a SPNEGO session setup has 12 command words, whereas a normal
1348 NT1 session setup has 13. See the cifs spec. */
1349 if (req->wct == 12 &&
1350 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1352 if (!sconn->smb1.negprot.spnego) {
1353 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1354 "at SPNEGO session setup when it was not "
1356 reply_nterror(req, nt_status_squash(
1357 NT_STATUS_LOGON_FAILURE));
1358 END_PROFILE(SMBsesssetupX);
1362 if (SVAL(req->vwv+4, 0) == 0) {
1363 setup_new_vc_session(req->sconn);
1366 reply_sesssetup_and_X_spnego(req);
1367 END_PROFILE(SMBsesssetupX);
1371 smb_bufsize = SVAL(req->vwv+2, 0);
1373 if (get_Protocol() < PROTOCOL_NT1) {
1374 uint16 passlen1 = SVAL(req->vwv+7, 0);
1376 /* Never do NT status codes with protocols before NT1 as we
1377 * don't get client caps. */
1378 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1380 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1381 reply_nterror(req, nt_status_squash(
1382 NT_STATUS_INVALID_PARAMETER));
1383 END_PROFILE(SMBsesssetupX);
1388 lm_resp = data_blob(req->buf, passlen1);
1390 plaintext_password = data_blob(req->buf, passlen1+1);
1391 /* Ensure null termination */
1392 plaintext_password.data[passlen1] = 0;
1395 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1396 req->buf + passlen1, STR_TERMINATE);
1397 user = tmp ? tmp : "";
1402 uint16 passlen1 = SVAL(req->vwv+7, 0);
1403 uint16 passlen2 = SVAL(req->vwv+8, 0);
1404 enum remote_arch_types ra_type = get_remote_arch();
1405 const uint8_t *p = req->buf;
1406 const uint8_t *save_p = req->buf;
1410 if(global_client_caps == 0) {
1411 global_client_caps = IVAL(req->vwv+11, 0);
1413 if (!(global_client_caps & CAP_STATUS32)) {
1414 remove_from_common_flags2(
1415 FLAGS2_32_BIT_ERROR_CODES);
1418 /* client_caps is used as final determination if
1419 * client is NT or Win95. This is needed to return
1420 * the correct error codes in some circumstances.
1423 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1424 ra_type == RA_WIN95) {
1425 if(!(global_client_caps & (CAP_NT_SMBS|
1427 set_remote_arch( RA_WIN95);
1433 /* both Win95 and WinNT stuff up the password
1434 * lengths for non-encrypting systems. Uggh.
1436 if passlen1==24 its a win95 system, and its setting
1437 the password length incorrectly. Luckily it still
1438 works with the default code because Win95 will null
1439 terminate the password anyway
1441 if passlen1>0 and passlen2>0 then maybe its a NT box
1442 and its setting passlen2 to some random value which
1443 really stuffs things up. we need to fix that one. */
1445 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1451 /* check for nasty tricks */
1452 if (passlen1 > MAX_PASS_LEN
1453 || passlen1 > smbreq_bufrem(req, p)) {
1454 reply_nterror(req, nt_status_squash(
1455 NT_STATUS_INVALID_PARAMETER));
1456 END_PROFILE(SMBsesssetupX);
1460 if (passlen2 > MAX_PASS_LEN
1461 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1462 reply_nterror(req, nt_status_squash(
1463 NT_STATUS_INVALID_PARAMETER));
1464 END_PROFILE(SMBsesssetupX);
1468 /* Save the lanman2 password and the NT md4 password. */
1470 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1475 lm_resp = data_blob(p, passlen1);
1476 nt_resp = data_blob(p+passlen1, passlen2);
1477 } else if (lp_security() != SEC_SHARE) {
1479 * In share level we should ignore any passwords, so
1480 * only read them if we're not.
1483 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1485 if (unic && (passlen2 == 0) && passlen1) {
1486 /* Only a ascii plaintext password was sent. */
1487 (void)srvstr_pull_talloc(talloc_tos(),
1493 STR_TERMINATE|STR_ASCII);
1495 (void)srvstr_pull_talloc(talloc_tos(),
1500 unic ? passlen2 : passlen1,
1504 reply_nterror(req, nt_status_squash(
1505 NT_STATUS_INVALID_PARAMETER));
1506 END_PROFILE(SMBsesssetupX);
1509 plaintext_password = data_blob(pass, strlen(pass)+1);
1512 p += passlen1 + passlen2;
1514 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1516 user = tmp ? tmp : "";
1518 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1520 domain = tmp ? tmp : "";
1522 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1524 native_os = tmp ? tmp : "";
1526 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1528 native_lanman = tmp ? tmp : "";
1530 /* not documented or decoded by Ethereal but there is one more
1531 * string in the extra bytes which is the same as the
1532 * PrimaryDomain when using extended security. Windows NT 4
1533 * and 2003 use this string to store the native lanman string.
1534 * Windows 9x does not include a string here at all so we have
1535 * to check if we have any extra bytes left */
1537 byte_count = SVAL(req->vwv+13, 0);
1538 if ( PTR_DIFF(p, save_p) < byte_count) {
1539 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1541 primary_domain = tmp ? tmp : "";
1543 primary_domain = talloc_strdup(talloc_tos(), "null");
1546 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1547 "PrimaryDomain=[%s]\n",
1548 domain, native_os, native_lanman, primary_domain));
1550 if ( ra_type == RA_WIN2K ) {
1551 if ( strlen(native_lanman) == 0 )
1552 ra_lanman_string( primary_domain );
1554 ra_lanman_string( native_lanman );
1559 if (SVAL(req->vwv+4, 0) == 0) {
1560 setup_new_vc_session(req->sconn);
1563 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1564 domain, user, get_remote_machine_name()));
1567 if (sconn->smb1.negprot.spnego) {
1569 /* This has to be here, because this is a perfectly
1570 * valid behaviour for guest logons :-( */
1572 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1573 "at 'normal' session setup after "
1574 "negotiating spnego.\n"));
1575 reply_nterror(req, nt_status_squash(
1576 NT_STATUS_LOGON_FAILURE));
1577 END_PROFILE(SMBsesssetupX);
1580 fstrcpy(sub_user, user);
1582 fstrcpy(sub_user, lp_guestaccount());
1585 sub_set_smb_name(sub_user);
1587 reload_services(sconn->msg_ctx, sconn->sock, True);
1589 if (lp_security() == SEC_SHARE) {
1590 char *sub_user_mapped = NULL;
1591 /* In share level we should ignore any passwords */
1593 data_blob_free(&lm_resp);
1594 data_blob_free(&nt_resp);
1595 data_blob_clear_free(&plaintext_password);
1597 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1598 if (!sub_user_mapped) {
1599 reply_nterror(req, NT_STATUS_NO_MEMORY);
1600 END_PROFILE(SMBsesssetupX);
1603 fstrcpy(sub_user, sub_user_mapped);
1604 add_session_user(sconn, sub_user);
1605 add_session_workgroup(sconn, domain);
1606 /* Then force it to null for the benfit of the code below */
1612 nt_status = check_guest_password(sconn->remote_address, &server_info);
1614 } else if (doencrypt) {
1615 struct auth_context *negprot_auth_context = NULL;
1616 negprot_auth_context = sconn->smb1.negprot.auth_context;
1617 if (!negprot_auth_context) {
1618 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1619 "session setup without negprot denied!\n"));
1620 reply_nterror(req, nt_status_squash(
1621 NT_STATUS_LOGON_FAILURE));
1622 END_PROFILE(SMBsesssetupX);
1625 nt_status = make_user_info_for_reply_enc(&user_info, user,
1627 sconn->remote_address,
1629 if (NT_STATUS_IS_OK(nt_status)) {
1630 nt_status = negprot_auth_context->check_ntlm_password(
1631 negprot_auth_context,
1636 struct auth_context *plaintext_auth_context = NULL;
1638 nt_status = make_auth_context_subsystem(
1639 talloc_tos(), &plaintext_auth_context);
1641 if (NT_STATUS_IS_OK(nt_status)) {
1644 plaintext_auth_context->get_ntlm_challenge(
1645 plaintext_auth_context, chal);
1647 if (!make_user_info_for_reply(&user_info,
1649 sconn->remote_address,
1651 plaintext_password)) {
1652 nt_status = NT_STATUS_NO_MEMORY;
1655 if (NT_STATUS_IS_OK(nt_status)) {
1656 nt_status = plaintext_auth_context->check_ntlm_password(
1657 plaintext_auth_context,
1661 TALLOC_FREE(plaintext_auth_context);
1666 free_user_info(&user_info);
1668 if (!NT_STATUS_IS_OK(nt_status)) {
1669 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1673 if (!NT_STATUS_IS_OK(nt_status)) {
1674 data_blob_free(&nt_resp);
1675 data_blob_free(&lm_resp);
1676 data_blob_clear_free(&plaintext_password);
1677 reply_nterror(req, nt_status_squash(nt_status));
1678 END_PROFILE(SMBsesssetupX);
1682 nt_status = create_local_token(req, server_info, NULL, &session_info);
1683 TALLOC_FREE(server_info);
1685 if (!NT_STATUS_IS_OK(nt_status)) {
1686 DEBUG(10, ("create_local_token failed: %s\n",
1687 nt_errstr(nt_status)));
1688 data_blob_free(&nt_resp);
1689 data_blob_free(&lm_resp);
1690 data_blob_clear_free(&plaintext_password);
1691 reply_nterror(req, nt_status_squash(nt_status));
1692 END_PROFILE(SMBsesssetupX);
1696 data_blob_clear_free(&plaintext_password);
1698 /* it's ok - setup a reply */
1699 reply_outbuf(req, 3, 0);
1700 if (get_Protocol() >= PROTOCOL_NT1) {
1701 push_signature(&req->outbuf);
1702 /* perhaps grab OS version here?? */
1705 if (session_info->unix_info->guest) {
1706 SSVAL(req->outbuf,smb_vwv2,1);
1709 /* register the name and uid as being validated, so further connections
1710 to a uid can get through without a password, on the same VC */
1712 if (lp_security() == SEC_SHARE) {
1713 sess_vuid = UID_FIELD_INVALID;
1714 TALLOC_FREE(session_info);
1716 /* Ignore the initial vuid. */
1717 sess_vuid = register_initial_vuid(sconn);
1718 if (sess_vuid == UID_FIELD_INVALID) {
1719 data_blob_free(&nt_resp);
1720 data_blob_free(&lm_resp);
1721 reply_nterror(req, nt_status_squash(
1722 NT_STATUS_LOGON_FAILURE));
1723 END_PROFILE(SMBsesssetupX);
1726 /* register_existing_vuid keeps the session_info */
1727 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1729 nt_resp.data ? nt_resp : lm_resp,
1731 if (sess_vuid == UID_FIELD_INVALID) {
1732 data_blob_free(&nt_resp);
1733 data_blob_free(&lm_resp);
1734 reply_nterror(req, nt_status_squash(
1735 NT_STATUS_LOGON_FAILURE));
1736 END_PROFILE(SMBsesssetupX);
1740 /* current_user_info is changed on new vuid */
1741 reload_services(sconn->msg_ctx, sconn->sock, True);
1744 data_blob_free(&nt_resp);
1745 data_blob_free(&lm_resp);
1747 SSVAL(req->outbuf,smb_uid,sess_vuid);
1748 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1749 req->vuid = sess_vuid;
1751 if (!sconn->smb1.sessions.done_sesssetup) {
1752 sconn->smb1.sessions.max_send =
1753 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1755 sconn->smb1.sessions.done_sesssetup = true;
1757 END_PROFILE(SMBsesssetupX);