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/smbd.h"
27 #include "smbd/globals.h"
28 #include "../libcli/auth/spnego.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "ntlmssp_wrap.h"
31 #include "librpc/gen_ndr/messaging.h"
32 #include "../librpc/gen_ndr/krb5pac.h"
33 #include "libads/kerberos_proto.h"
34 #include "../lib/util/asn1.h"
37 /* For split krb5 SPNEGO blobs. */
38 struct pending_auth_data {
39 struct pending_auth_data *prev, *next;
40 uint16 vuid; /* Tag for this entry. */
41 uint16 smbpid; /* Alternate tag for this entry. */
43 DATA_BLOB partial_data;
47 on a logon error possibly map the error to success if "map to guest"
50 NTSTATUS do_map_to_guest(NTSTATUS status,
51 struct auth_serversupplied_info **server_info,
52 const char *user, const char *domain)
54 user = user ? user : "";
55 domain = domain ? domain : "";
57 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
58 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
59 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
60 DEBUG(3,("No such user %s [%s] - using guest account\n",
62 status = make_server_info_guest(NULL, server_info);
66 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
67 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
68 DEBUG(3,("Registered username %s for guest access\n",
70 status = make_server_info_guest(NULL, server_info);
77 /****************************************************************************
78 Add the standard 'Samba' signature to the end of the session setup.
79 ****************************************************************************/
81 static int push_signature(uint8 **outbuf)
88 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
90 if (tmp == -1) return -1;
93 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
94 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
98 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
101 if (tmp == -1) return -1;
104 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
106 if (tmp == -1) return -1;
112 /****************************************************************************
113 Send a security blob via a session setup reply.
114 ****************************************************************************/
116 static void reply_sesssetup_blob(struct smb_request *req,
120 if (!NT_STATUS_IS_OK(nt_status) &&
121 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
122 reply_nterror(req, nt_status_squash(nt_status));
126 nt_status = nt_status_squash(nt_status);
127 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
128 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
129 SSVAL(req->outbuf, smb_vwv3, blob.length);
131 if ((message_push_blob(&req->outbuf, blob) == -1)
132 || (push_signature(&req->outbuf) == -1)) {
133 reply_nterror(req, NT_STATUS_NO_MEMORY);
137 /****************************************************************************
138 Do a 'guest' logon, getting back the
139 ****************************************************************************/
141 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
143 struct auth_context *auth_context;
144 struct auth_usersupplied_info *user_info = NULL;
147 static unsigned char chal[8] = { 0, };
149 DEBUG(3,("Got anonymous request\n"));
151 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
152 if (!NT_STATUS_IS_OK(nt_status)) {
156 if (!make_user_info_guest(&user_info)) {
157 TALLOC_FREE(auth_context);
158 return NT_STATUS_NO_MEMORY;
161 nt_status = auth_context->check_ntlm_password(auth_context,
164 TALLOC_FREE(auth_context);
165 free_user_info(&user_info);
173 /* Experiment that failed. See "only happens with a KDC" comment below. */
174 /****************************************************************************
175 Cerate a clock skew error blob for a Windows client.
176 ****************************************************************************/
178 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
180 krb5_context context = NULL;
181 krb5_error_code kerr = 0;
183 krb5_principal host_princ = NULL;
184 char *host_princ_s = NULL;
187 *pblob_out = data_blob_null;
189 initialize_krb5_error_table();
190 kerr = krb5_init_context(&context);
194 /* Create server principal. */
195 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
199 strlower_m(host_princ_s);
201 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
203 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
204 "for name %s: Error %s\n",
205 host_princ_s, error_message(kerr) ));
209 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
212 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
213 "failed: Error %s\n",
214 error_message(kerr) ));
218 *pblob_out = data_blob(reply.data, reply.length);
219 kerberos_free_data_contents(context,&reply);
225 SAFE_FREE(host_princ_s);
228 krb5_free_principal(context, host_princ);
230 krb5_free_context(context);
235 /****************************************************************************
236 Reply to a session setup spnego negotiate packet for kerberos.
237 ****************************************************************************/
239 static void reply_spnego_kerberos(struct smb_request *req,
243 bool *p_invalidate_vuid)
248 int sess_vuid = req->vuid;
249 NTSTATUS ret = NT_STATUS_OK;
250 DATA_BLOB ap_rep, ap_rep_wrapped, response;
251 struct auth_serversupplied_info *server_info = NULL;
252 DATA_BLOB session_key = data_blob_null;
254 DATA_BLOB nullblob = data_blob_null;
255 bool map_domainuser_to_guest = False;
256 bool username_was_mapped;
257 struct PAC_LOGON_INFO *logon_info = NULL;
258 struct smbd_server_connection *sconn = req->sconn;
266 ZERO_STRUCT(ap_rep_wrapped);
267 ZERO_STRUCT(response);
269 /* Normally we will always invalidate the intermediate vuid. */
270 *p_invalidate_vuid = True;
272 mem_ctx = talloc_init("reply_spnego_kerberos");
273 if (mem_ctx == NULL) {
274 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
278 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
279 talloc_destroy(mem_ctx);
280 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
284 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
285 &principal, &logon_info, &ap_rep,
288 data_blob_free(&ticket);
290 if (!NT_STATUS_IS_OK(ret)) {
292 /* Experiment that failed.
293 * See "only happens with a KDC" comment below. */
295 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
298 * Windows in this case returns
299 * NT_STATUS_MORE_PROCESSING_REQUIRED
300 * with a negTokenTarg blob containing an krb5_error
301 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
302 * The client then fixes its clock and continues rather
303 * than giving an error. JRA.
304 * -- Looks like this only happens with a KDC. JRA.
307 bool ok = make_krb5_skew_error(&ap_rep);
309 talloc_destroy(mem_ctx);
310 return ERROR_NT(nt_status_squash(
311 NT_STATUS_LOGON_FAILURE));
313 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
315 response = spnego_gen_auth_response(&ap_rep_wrapped,
316 ret, OID_KERBEROS5_OLD);
317 reply_sesssetup_blob(conn, inbuf, outbuf, response,
318 NT_STATUS_MORE_PROCESSING_REQUIRED);
321 * In this one case we don't invalidate the
322 * intermediate vuid as we're expecting the client
323 * to re-use it for the next sessionsetupX packet. JRA.
326 *p_invalidate_vuid = False;
328 data_blob_free(&ap_rep);
329 data_blob_free(&ap_rep_wrapped);
330 data_blob_free(&response);
331 talloc_destroy(mem_ctx);
332 return -1; /* already replied */
335 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
336 ret = NT_STATUS_LOGON_FAILURE;
339 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
341 talloc_destroy(mem_ctx);
342 reply_nterror(req, nt_status_squash(ret));
346 ret = get_user_from_kerberos_info(talloc_tos(),
347 sconn->client_id.name,
348 principal, logon_info,
349 &username_was_mapped,
350 &map_domainuser_to_guest,
352 &real_username, &pw);
353 if (!NT_STATUS_IS_OK(ret)) {
354 data_blob_free(&ap_rep);
355 data_blob_free(&session_key);
356 talloc_destroy(mem_ctx);
357 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
361 /* save the PAC data if we have it */
363 netsamlogon_cache_store(user, &logon_info->info3);
366 /* setup the string used by %U */
367 sub_set_smb_name(real_username);
369 /* reload services so that the new %U is taken into account */
370 reload_services(sconn->msg_ctx, sconn->sock, True);
372 ret = make_server_info_krb5(mem_ctx,
373 user, domain, real_username, pw,
374 logon_info, map_domainuser_to_guest,
376 if (!NT_STATUS_IS_OK(ret)) {
377 DEBUG(1, ("make_server_info_krb5 failed!\n"));
378 data_blob_free(&ap_rep);
379 data_blob_free(&session_key);
380 TALLOC_FREE(mem_ctx);
381 reply_nterror(req, nt_status_squash(ret));
385 server_info->nss_token |= username_was_mapped;
387 /* we need to build the token for the user. make_server_info_guest()
390 if ( !server_info->security_token ) {
391 ret = create_local_token( server_info );
392 if ( !NT_STATUS_IS_OK(ret) ) {
393 DEBUG(10,("failed to create local token: %s\n",
395 data_blob_free(&ap_rep);
396 data_blob_free(&session_key);
397 TALLOC_FREE( mem_ctx );
398 TALLOC_FREE( server_info );
399 reply_nterror(req, nt_status_squash(ret));
404 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
405 sess_vuid = register_initial_vuid(sconn);
408 data_blob_free(&server_info->user_session_key);
409 /* Set the kerberos-derived session key onto the server_info */
410 server_info->user_session_key = session_key;
411 talloc_steal(server_info, session_key.data);
413 session_key = data_blob_null;
415 /* register_existing_vuid keeps the server info */
416 /* register_existing_vuid takes ownership of session_key on success,
417 * no need to free after this on success. A better interface would copy
420 sess_vuid = register_existing_vuid(sconn, sess_vuid,
421 server_info, nullblob, user);
423 reply_outbuf(req, 4, 0);
424 SSVAL(req->outbuf,smb_uid,sess_vuid);
426 if (sess_vuid == UID_FIELD_INVALID ) {
427 ret = NT_STATUS_LOGON_FAILURE;
429 /* current_user_info is changed on new vuid */
430 reload_services(sconn->msg_ctx, sconn->sock, True);
432 SSVAL(req->outbuf, smb_vwv3, 0);
434 if (server_info->guest) {
435 SSVAL(req->outbuf,smb_vwv2,1);
438 SSVAL(req->outbuf, smb_uid, sess_vuid);
440 /* Successful logon. Keep this vuid. */
441 *p_invalidate_vuid = False;
444 /* wrap that up in a nice GSS-API wrapping */
445 if (NT_STATUS_IS_OK(ret)) {
446 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
449 ap_rep_wrapped = data_blob_null;
451 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
453 reply_sesssetup_blob(req, response, ret);
455 data_blob_free(&ap_rep);
456 data_blob_free(&ap_rep_wrapped);
457 data_blob_free(&response);
458 TALLOC_FREE(mem_ctx);
463 /****************************************************************************
464 Send a session setup reply, wrapped in SPNEGO.
465 Get vuid and check first.
466 End the NTLMSSP exchange context if we are OK/complete fail
467 This should be split into two functions, one to handle each
468 leg of the NTLM auth steps.
469 ***************************************************************************/
471 static void reply_spnego_ntlmssp(struct smb_request *req,
473 struct auth_ntlmssp_state **auth_ntlmssp_state,
474 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
478 bool do_invalidate = true;
480 struct auth_serversupplied_info *session_info = NULL;
481 struct smbd_server_connection *sconn = req->sconn;
483 if (NT_STATUS_IS_OK(nt_status)) {
484 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
485 (*auth_ntlmssp_state), &session_info);
487 /* Note that this session_info won't have a session
488 * key. But for map to guest, that's exactly the right
489 * thing - we can't reasonably guess the key the
490 * client wants, as the password was wrong */
491 nt_status = do_map_to_guest(nt_status,
493 auth_ntlmssp_get_username(*auth_ntlmssp_state),
494 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
497 reply_outbuf(req, 4, 0);
499 SSVAL(req->outbuf, smb_uid, vuid);
501 if (NT_STATUS_IS_OK(nt_status)) {
502 DATA_BLOB nullblob = data_blob_null;
504 if (!is_partial_auth_vuid(sconn, vuid)) {
505 nt_status = NT_STATUS_LOGON_FAILURE;
509 /* register_existing_vuid keeps the server info */
510 if (register_existing_vuid(sconn, vuid,
511 session_info, nullblob,
512 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
514 /* The problem is, *auth_ntlmssp_state points
515 * into the vuser this will have
516 * talloc_free()'ed in
517 * register_existing_vuid() */
518 do_invalidate = false;
519 nt_status = NT_STATUS_LOGON_FAILURE;
523 /* current_user_info is changed on new vuid */
524 reload_services(sconn->msg_ctx, sconn->sock, True);
526 SSVAL(req->outbuf, smb_vwv3, 0);
528 if (session_info->guest) {
529 SSVAL(req->outbuf,smb_vwv2,1);
536 response = spnego_gen_auth_response(talloc_tos(),
540 response = *ntlmssp_blob;
543 reply_sesssetup_blob(req, response, nt_status);
545 data_blob_free(&response);
548 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
549 and the other end, that we are not finished yet. */
551 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
552 /* NB. This is *NOT* an error case. JRA */
554 TALLOC_FREE(*auth_ntlmssp_state);
555 if (!NT_STATUS_IS_OK(nt_status)) {
556 /* Kill the intermediate vuid */
557 invalidate_vuid(sconn, vuid);
563 /****************************************************************************
564 Is this a krb5 mechanism ?
565 ****************************************************************************/
567 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
569 DATA_BLOB *pblob_out,
572 char *OIDs[ASN1_MAX_OIDS];
574 NTSTATUS ret = NT_STATUS_OK;
576 *kerb_mechOID = NULL;
578 /* parse out the OIDs and the first sec blob */
579 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
581 return NT_STATUS_LOGON_FAILURE;
584 /* only look at the first OID for determining the mechToken --
585 according to RFC2478, we should choose the one we want
586 and renegotiate, but i smell a client bug here..
588 Problem observed when connecting to a member (samba box)
589 of an AD domain as a user in a Samba domain. Samba member
590 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
591 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
592 NTLMSSP mechtoken. --jerry */
595 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
596 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
597 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
598 if (*kerb_mechOID == NULL) {
599 ret = NT_STATUS_NO_MEMORY;
604 for (i=0;OIDs[i];i++) {
605 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
606 talloc_free(OIDs[i]);
611 /****************************************************************************
612 Fall back from krb5 to NTLMSSP.
613 ****************************************************************************/
615 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
620 reply_outbuf(req, 4, 0);
621 SSVAL(req->outbuf,smb_uid,vuid);
623 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
624 "but set to downgrade to NTLMSSP\n"));
626 response = spnego_gen_auth_response(talloc_tos(), NULL,
627 NT_STATUS_MORE_PROCESSING_REQUIRED,
629 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
630 data_blob_free(&response);
633 /****************************************************************************
634 Reply to a session setup spnego negotiate packet.
635 ****************************************************************************/
637 static void reply_spnego_negotiate(struct smb_request *req,
640 struct auth_ntlmssp_state **auth_ntlmssp_state)
644 char *kerb_mech = NULL;
646 struct smbd_server_connection *sconn = req->sconn;
648 status = parse_spnego_mechanisms(talloc_tos(),
649 blob1, &secblob, &kerb_mech);
650 if (!NT_STATUS_IS_OK(status)) {
651 /* Kill the intermediate vuid */
652 invalidate_vuid(sconn, vuid);
653 reply_nterror(req, nt_status_squash(status));
657 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
658 (unsigned long)secblob.length));
661 if (kerb_mech && ((lp_security()==SEC_ADS) ||
662 USE_KERBEROS_KEYTAB) ) {
663 bool destroy_vuid = True;
664 reply_spnego_kerberos(req, &secblob, kerb_mech,
665 vuid, &destroy_vuid);
666 data_blob_free(&secblob);
668 /* Kill the intermediate vuid */
669 invalidate_vuid(sconn, vuid);
671 TALLOC_FREE(kerb_mech);
676 if (*auth_ntlmssp_state) {
677 TALLOC_FREE(*auth_ntlmssp_state);
681 data_blob_free(&secblob);
682 /* The mechtoken is a krb5 ticket, but
683 * we need to fall back to NTLM. */
684 reply_spnego_downgrade_to_ntlmssp(req, vuid);
685 TALLOC_FREE(kerb_mech);
689 status = auth_ntlmssp_start(auth_ntlmssp_state);
690 if (!NT_STATUS_IS_OK(status)) {
691 /* Kill the intermediate vuid */
692 invalidate_vuid(sconn, vuid);
693 reply_nterror(req, nt_status_squash(status));
697 status = auth_ntlmssp_update(*auth_ntlmssp_state,
700 data_blob_free(&secblob);
702 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
703 &chal, status, OID_NTLMSSP, true);
705 data_blob_free(&chal);
707 /* already replied */
711 /****************************************************************************
712 Reply to a session setup spnego auth packet.
713 ****************************************************************************/
715 static void reply_spnego_auth(struct smb_request *req,
718 struct auth_ntlmssp_state **auth_ntlmssp_state)
720 DATA_BLOB auth = data_blob_null;
721 DATA_BLOB auth_reply = data_blob_null;
722 DATA_BLOB secblob = data_blob_null;
723 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
724 struct smbd_server_connection *sconn = req->sconn;
726 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
728 file_save("auth.dat", blob1.data, blob1.length);
730 /* Kill the intermediate vuid */
731 invalidate_vuid(sconn, vuid);
733 reply_nterror(req, nt_status_squash(
734 NT_STATUS_LOGON_FAILURE));
738 if (auth.data[0] == ASN1_APPLICATION(0)) {
739 /* Might be a second negTokenTarg packet */
740 char *kerb_mech = NULL;
742 status = parse_spnego_mechanisms(talloc_tos(),
743 auth, &secblob, &kerb_mech);
745 if (!NT_STATUS_IS_OK(status)) {
746 /* Kill the intermediate vuid */
747 invalidate_vuid(sconn, vuid);
748 reply_nterror(req, nt_status_squash(status));
752 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
753 (unsigned long)secblob.length));
755 if (kerb_mech && ((lp_security()==SEC_ADS) ||
756 USE_KERBEROS_KEYTAB)) {
757 bool destroy_vuid = True;
758 reply_spnego_kerberos(req, &secblob, kerb_mech,
759 vuid, &destroy_vuid);
760 data_blob_free(&secblob);
761 data_blob_free(&auth);
763 /* Kill the intermediate vuid */
764 invalidate_vuid(sconn, vuid);
766 TALLOC_FREE(kerb_mech);
770 /* Can't blunder into NTLMSSP auth if we have
774 /* Kill the intermediate vuid */
775 invalidate_vuid(sconn, vuid);
776 DEBUG(3,("reply_spnego_auth: network "
777 "misconfiguration, client sent us a "
778 "krb5 ticket and kerberos security "
780 reply_nterror(req, nt_status_squash(
781 NT_STATUS_LOGON_FAILURE));
782 TALLOC_FREE(kerb_mech);
786 /* If we get here it wasn't a negTokenTarg auth packet. */
787 data_blob_free(&secblob);
789 if (!*auth_ntlmssp_state) {
790 status = auth_ntlmssp_start(auth_ntlmssp_state);
791 if (!NT_STATUS_IS_OK(status)) {
792 /* Kill the intermediate vuid */
793 invalidate_vuid(sconn, vuid);
794 reply_nterror(req, nt_status_squash(status));
799 status = auth_ntlmssp_update(*auth_ntlmssp_state,
802 data_blob_free(&auth);
804 /* Don't send the mechid as we've already sent this (RFC4178). */
806 reply_spnego_ntlmssp(req, vuid,
808 &auth_reply, status, NULL, true);
810 data_blob_free(&auth_reply);
812 /* and tell smbd that we have already replied to this packet */
816 /****************************************************************************
817 Delete an entry on the list.
818 ****************************************************************************/
820 static void delete_partial_auth(struct smbd_server_connection *sconn,
821 struct pending_auth_data *pad)
826 DLIST_REMOVE(sconn->smb1.pd_list, pad);
827 data_blob_free(&pad->partial_data);
831 /****************************************************************************
832 Search for a partial SPNEGO auth fragment matching an smbpid.
833 ****************************************************************************/
835 static struct pending_auth_data *get_pending_auth_data(
836 struct smbd_server_connection *sconn,
839 struct pending_auth_data *pad;
841 * NOTE: using the smbpid here is completely wrong...
843 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
845 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
846 if (pad->smbpid == smbpid) {
853 /****************************************************************************
854 Check the size of an SPNEGO blob. If we need more return
855 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
856 the blob to be more than 64k.
857 ****************************************************************************/
859 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
860 uint16 smbpid, uint16 vuid,
863 struct pending_auth_data *pad = NULL;
865 size_t needed_len = 0;
867 pad = get_pending_auth_data(sconn, smbpid);
869 /* Ensure we have some data. */
870 if (pblob->length == 0) {
871 /* Caller can cope. */
872 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
873 delete_partial_auth(sconn, pad);
877 /* Were we waiting for more data ? */
880 size_t copy_len = MIN(65536, pblob->length);
882 /* Integer wrap paranoia.... */
884 if (pad->partial_data.length + copy_len <
885 pad->partial_data.length ||
886 pad->partial_data.length + copy_len < copy_len) {
888 DEBUG(2,("check_spnego_blob_complete: integer wrap "
889 "pad->partial_data.length = %u, "
891 (unsigned int)pad->partial_data.length,
892 (unsigned int)copy_len ));
894 delete_partial_auth(sconn, pad);
895 return NT_STATUS_INVALID_PARAMETER;
898 DEBUG(10,("check_spnego_blob_complete: "
899 "pad->partial_data.length = %u, "
900 "pad->needed_len = %u, "
902 "pblob->length = %u,\n",
903 (unsigned int)pad->partial_data.length,
904 (unsigned int)pad->needed_len,
905 (unsigned int)copy_len,
906 (unsigned int)pblob->length ));
908 tmp_blob = data_blob(NULL,
909 pad->partial_data.length + copy_len);
911 /* Concatenate the two (up to copy_len) bytes. */
912 memcpy(tmp_blob.data,
913 pad->partial_data.data,
914 pad->partial_data.length);
915 memcpy(tmp_blob.data + pad->partial_data.length,
919 /* Replace the partial data. */
920 data_blob_free(&pad->partial_data);
921 pad->partial_data = tmp_blob;
922 ZERO_STRUCT(tmp_blob);
925 if (pblob->length >= pad->needed_len) {
926 /* Yes, replace pblob. */
927 data_blob_free(pblob);
928 *pblob = pad->partial_data;
929 ZERO_STRUCT(pad->partial_data);
930 delete_partial_auth(sconn, pad);
934 /* Still need more data. */
935 pad->needed_len -= copy_len;
936 return NT_STATUS_MORE_PROCESSING_REQUIRED;
939 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
940 (pblob->data[0] != ASN1_CONTEXT(1))) {
941 /* Not something we can determine the
947 /* This is a new SPNEGO sessionsetup - see if
948 * the data given in this blob is enough.
951 data = asn1_init(NULL);
953 return NT_STATUS_NO_MEMORY;
956 asn1_load(data, *pblob);
957 asn1_start_tag(data, pblob->data[0]);
958 if (data->has_error || data->nesting == NULL) {
960 /* Let caller catch. */
964 /* Integer wrap paranoia.... */
966 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
967 data->nesting->taglen + data->nesting->start < data->nesting->start) {
969 DEBUG(2,("check_spnego_blob_complete: integer wrap "
970 "data.nesting->taglen = %u, "
971 "data.nesting->start = %u\n",
972 (unsigned int)data->nesting->taglen,
973 (unsigned int)data->nesting->start ));
976 return NT_STATUS_INVALID_PARAMETER;
979 /* Total length of the needed asn1 is the tag length
980 * plus the current offset. */
982 needed_len = data->nesting->taglen + data->nesting->start;
985 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
986 "pblob->length = %u\n",
987 (unsigned int)needed_len,
988 (unsigned int)pblob->length ));
990 if (needed_len <= pblob->length) {
991 /* Nothing to do - blob is complete. */
995 /* Refuse the blob if it's bigger than 64k. */
996 if (needed_len > 65536) {
997 DEBUG(2,("check_spnego_blob_complete: needed_len "
999 (unsigned int)needed_len ));
1000 return NT_STATUS_INVALID_PARAMETER;
1003 /* We must store this blob until complete. */
1004 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1005 return NT_STATUS_NO_MEMORY;
1007 pad->needed_len = needed_len - pblob->length;
1008 pad->partial_data = data_blob(pblob->data, pblob->length);
1009 if (pad->partial_data.data == NULL) {
1011 return NT_STATUS_NO_MEMORY;
1013 pad->smbpid = smbpid;
1015 DLIST_ADD(sconn->smb1.pd_list, pad);
1017 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1020 /****************************************************************************
1021 Reply to a session setup command.
1022 conn POINTER CAN BE NULL HERE !
1023 ****************************************************************************/
1025 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1031 const char *native_os;
1032 const char *native_lanman;
1033 const char *primary_domain;
1035 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1036 enum remote_arch_types ra_type = get_remote_arch();
1037 int vuid = req->vuid;
1038 user_struct *vuser = NULL;
1039 NTSTATUS status = NT_STATUS_OK;
1040 uint16 smbpid = req->smbpid;
1041 struct smbd_server_connection *sconn = req->sconn;
1043 DEBUG(3,("Doing spnego session setup\n"));
1045 if (global_client_caps == 0) {
1046 global_client_caps = IVAL(req->vwv+10, 0);
1048 if (!(global_client_caps & CAP_STATUS32)) {
1049 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1056 if (data_blob_len == 0) {
1057 /* an invalid request */
1058 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1062 bufrem = smbreq_bufrem(req, p);
1063 /* pull the spnego blob */
1064 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1067 file_save("negotiate.dat", blob1.data, blob1.length);
1070 p2 = (char *)req->buf + blob1.length;
1072 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1074 native_os = tmp ? tmp : "";
1076 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1078 native_lanman = tmp ? tmp : "";
1080 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1082 primary_domain = tmp ? tmp : "";
1084 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1085 native_os, native_lanman, primary_domain));
1087 if ( ra_type == RA_WIN2K ) {
1088 /* Vista sets neither the OS or lanman strings */
1090 if ( !strlen(native_os) && !strlen(native_lanman) )
1091 set_remote_arch(RA_VISTA);
1093 /* Windows 2003 doesn't set the native lanman string,
1094 but does set primary domain which is a bug I think */
1096 if ( !strlen(native_lanman) ) {
1097 ra_lanman_string( primary_domain );
1099 ra_lanman_string( native_lanman );
1101 } else if ( ra_type == RA_VISTA ) {
1102 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1103 set_remote_arch(RA_OSX);
1107 /* Did we get a valid vuid ? */
1108 if (!is_partial_auth_vuid(sconn, vuid)) {
1109 /* No, then try and see if this is an intermediate sessionsetup
1110 * for a large SPNEGO packet. */
1111 struct pending_auth_data *pad;
1112 pad = get_pending_auth_data(sconn, smbpid);
1114 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1115 "pending vuid %u\n",
1116 (unsigned int)pad->vuid ));
1121 /* Do we have a valid vuid now ? */
1122 if (!is_partial_auth_vuid(sconn, vuid)) {
1123 /* No, start a new authentication setup. */
1124 vuid = register_initial_vuid(sconn);
1125 if (vuid == UID_FIELD_INVALID) {
1126 data_blob_free(&blob1);
1127 reply_nterror(req, nt_status_squash(
1128 NT_STATUS_INVALID_PARAMETER));
1133 vuser = get_partial_auth_user_struct(sconn, vuid);
1134 /* This MUST be valid. */
1136 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1139 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1140 * sessionsetup requests as the Windows limit on the security blob
1141 * field is 4k. Bug #4400. JRA.
1144 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 if (!NT_STATUS_EQUAL(status,
1147 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1148 /* Real error - kill the intermediate vuid */
1149 invalidate_vuid(sconn, vuid);
1151 data_blob_free(&blob1);
1152 reply_nterror(req, nt_status_squash(status));
1156 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1158 /* its a negTokenTarg packet */
1160 reply_spnego_negotiate(req, vuid, blob1,
1161 &vuser->auth_ntlmssp_state);
1162 data_blob_free(&blob1);
1166 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1168 /* its a auth packet */
1170 reply_spnego_auth(req, vuid, blob1,
1171 &vuser->auth_ntlmssp_state);
1172 data_blob_free(&blob1);
1176 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1179 if (!vuser->auth_ntlmssp_state) {
1180 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1181 if (!NT_STATUS_IS_OK(status)) {
1182 /* Kill the intermediate vuid */
1183 invalidate_vuid(sconn, vuid);
1184 data_blob_free(&blob1);
1185 reply_nterror(req, nt_status_squash(status));
1190 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1193 data_blob_free(&blob1);
1195 reply_spnego_ntlmssp(req, vuid,
1196 &vuser->auth_ntlmssp_state,
1197 &chal, status, OID_NTLMSSP, false);
1198 data_blob_free(&chal);
1202 /* what sort of packet is this? */
1203 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1205 data_blob_free(&blob1);
1207 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1210 /****************************************************************************
1211 On new VC == 0, shutdown *all* old connections and users.
1212 It seems that only NT4.x does this. At W2K and above (XP etc.).
1213 a new session setup with VC==0 is ignored.
1214 ****************************************************************************/
1216 struct shutdown_state {
1218 struct messaging_context *msg_ctx;
1221 static int shutdown_other_smbds(const struct connections_key *key,
1222 const struct connections_data *crec,
1225 struct shutdown_state *state = (struct shutdown_state *)private_data;
1227 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1228 procid_str(talloc_tos(), &crec->pid), crec->addr));
1230 if (!process_exists(crec->pid)) {
1231 DEBUG(10, ("process does not exist\n"));
1235 if (procid_is_me(&crec->pid)) {
1236 DEBUG(10, ("It's me\n"));
1240 if (strcmp(state->ip, crec->addr) != 0) {
1241 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1245 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1246 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1249 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1254 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1256 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1257 "compatible we would close all old resources.\n"));
1260 invalidate_all_vuids();
1262 if (lp_reset_on_zero_vc()) {
1264 struct shutdown_state state;
1266 addr = tsocket_address_inet_addr_string(
1267 sconn->remote_address, talloc_tos());
1272 state.msg_ctx = sconn->msg_ctx;
1273 connections_forall_read(shutdown_other_smbds, &state);
1278 /****************************************************************************
1279 Reply to a session setup command.
1280 ****************************************************************************/
1282 void reply_sesssetup_and_X(struct smb_request *req)
1288 DATA_BLOB plaintext_password;
1291 fstring sub_user; /* Sanitised username for substituion */
1293 const char *native_os;
1294 const char *native_lanman;
1295 const char *primary_domain;
1296 struct auth_usersupplied_info *user_info = NULL;
1297 struct auth_serversupplied_info *server_info = NULL;
1298 uint16 smb_flag2 = req->flags2;
1301 struct smbd_server_connection *sconn = req->sconn;
1303 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1305 START_PROFILE(SMBsesssetupX);
1307 ZERO_STRUCT(lm_resp);
1308 ZERO_STRUCT(nt_resp);
1309 ZERO_STRUCT(plaintext_password);
1311 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1313 /* a SPNEGO session setup has 12 command words, whereas a normal
1314 NT1 session setup has 13. See the cifs spec. */
1315 if (req->wct == 12 &&
1316 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1318 if (!sconn->smb1.negprot.spnego) {
1319 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1320 "at SPNEGO session setup when it was not "
1322 reply_nterror(req, nt_status_squash(
1323 NT_STATUS_LOGON_FAILURE));
1324 END_PROFILE(SMBsesssetupX);
1328 if (SVAL(req->vwv+4, 0) == 0) {
1329 setup_new_vc_session(req->sconn);
1332 reply_sesssetup_and_X_spnego(req);
1333 END_PROFILE(SMBsesssetupX);
1337 smb_bufsize = SVAL(req->vwv+2, 0);
1339 if (get_Protocol() < PROTOCOL_NT1) {
1340 uint16 passlen1 = SVAL(req->vwv+7, 0);
1342 /* Never do NT status codes with protocols before NT1 as we
1343 * don't get client caps. */
1344 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1346 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1347 reply_nterror(req, nt_status_squash(
1348 NT_STATUS_INVALID_PARAMETER));
1349 END_PROFILE(SMBsesssetupX);
1354 lm_resp = data_blob(req->buf, passlen1);
1356 plaintext_password = data_blob(req->buf, passlen1+1);
1357 /* Ensure null termination */
1358 plaintext_password.data[passlen1] = 0;
1361 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1362 req->buf + passlen1, STR_TERMINATE);
1363 user = tmp ? tmp : "";
1368 uint16 passlen1 = SVAL(req->vwv+7, 0);
1369 uint16 passlen2 = SVAL(req->vwv+8, 0);
1370 enum remote_arch_types ra_type = get_remote_arch();
1371 const uint8_t *p = req->buf;
1372 const uint8_t *save_p = req->buf;
1376 if(global_client_caps == 0) {
1377 global_client_caps = IVAL(req->vwv+11, 0);
1379 if (!(global_client_caps & CAP_STATUS32)) {
1380 remove_from_common_flags2(
1381 FLAGS2_32_BIT_ERROR_CODES);
1384 /* client_caps is used as final determination if
1385 * client is NT or Win95. This is needed to return
1386 * the correct error codes in some circumstances.
1389 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1390 ra_type == RA_WIN95) {
1391 if(!(global_client_caps & (CAP_NT_SMBS|
1393 set_remote_arch( RA_WIN95);
1399 /* both Win95 and WinNT stuff up the password
1400 * lengths for non-encrypting systems. Uggh.
1402 if passlen1==24 its a win95 system, and its setting
1403 the password length incorrectly. Luckily it still
1404 works with the default code because Win95 will null
1405 terminate the password anyway
1407 if passlen1>0 and passlen2>0 then maybe its a NT box
1408 and its setting passlen2 to some random value which
1409 really stuffs things up. we need to fix that one. */
1411 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1417 /* check for nasty tricks */
1418 if (passlen1 > MAX_PASS_LEN
1419 || passlen1 > smbreq_bufrem(req, p)) {
1420 reply_nterror(req, nt_status_squash(
1421 NT_STATUS_INVALID_PARAMETER));
1422 END_PROFILE(SMBsesssetupX);
1426 if (passlen2 > MAX_PASS_LEN
1427 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1428 reply_nterror(req, nt_status_squash(
1429 NT_STATUS_INVALID_PARAMETER));
1430 END_PROFILE(SMBsesssetupX);
1434 /* Save the lanman2 password and the NT md4 password. */
1436 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1441 lm_resp = data_blob(p, passlen1);
1442 nt_resp = data_blob(p+passlen1, passlen2);
1443 } else if (lp_security() != SEC_SHARE) {
1445 * In share level we should ignore any passwords, so
1446 * only read them if we're not.
1449 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1451 if (unic && (passlen2 == 0) && passlen1) {
1452 /* Only a ascii plaintext password was sent. */
1453 (void)srvstr_pull_talloc(talloc_tos(),
1459 STR_TERMINATE|STR_ASCII);
1461 (void)srvstr_pull_talloc(talloc_tos(),
1466 unic ? passlen2 : passlen1,
1470 reply_nterror(req, nt_status_squash(
1471 NT_STATUS_INVALID_PARAMETER));
1472 END_PROFILE(SMBsesssetupX);
1475 plaintext_password = data_blob(pass, strlen(pass)+1);
1478 p += passlen1 + passlen2;
1480 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1482 user = tmp ? tmp : "";
1484 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1486 domain = tmp ? tmp : "";
1488 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1490 native_os = tmp ? tmp : "";
1492 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1494 native_lanman = tmp ? tmp : "";
1496 /* not documented or decoded by Ethereal but there is one more
1497 * string in the extra bytes which is the same as the
1498 * PrimaryDomain when using extended security. Windows NT 4
1499 * and 2003 use this string to store the native lanman string.
1500 * Windows 9x does not include a string here at all so we have
1501 * to check if we have any extra bytes left */
1503 byte_count = SVAL(req->vwv+13, 0);
1504 if ( PTR_DIFF(p, save_p) < byte_count) {
1505 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1507 primary_domain = tmp ? tmp : "";
1509 primary_domain = talloc_strdup(talloc_tos(), "null");
1512 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1513 "PrimaryDomain=[%s]\n",
1514 domain, native_os, native_lanman, primary_domain));
1516 if ( ra_type == RA_WIN2K ) {
1517 if ( strlen(native_lanman) == 0 )
1518 ra_lanman_string( primary_domain );
1520 ra_lanman_string( native_lanman );
1525 if (SVAL(req->vwv+4, 0) == 0) {
1526 setup_new_vc_session(req->sconn);
1529 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1530 domain, user, get_remote_machine_name()));
1533 if (sconn->smb1.negprot.spnego) {
1535 /* This has to be here, because this is a perfectly
1536 * valid behaviour for guest logons :-( */
1538 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1539 "at 'normal' session setup after "
1540 "negotiating spnego.\n"));
1541 reply_nterror(req, nt_status_squash(
1542 NT_STATUS_LOGON_FAILURE));
1543 END_PROFILE(SMBsesssetupX);
1546 fstrcpy(sub_user, user);
1548 fstrcpy(sub_user, lp_guestaccount());
1551 sub_set_smb_name(sub_user);
1553 reload_services(sconn->msg_ctx, sconn->sock, True);
1555 if (lp_security() == SEC_SHARE) {
1556 char *sub_user_mapped = NULL;
1557 /* In share level we should ignore any passwords */
1559 data_blob_free(&lm_resp);
1560 data_blob_free(&nt_resp);
1561 data_blob_clear_free(&plaintext_password);
1563 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1564 if (!sub_user_mapped) {
1565 reply_nterror(req, NT_STATUS_NO_MEMORY);
1566 END_PROFILE(SMBsesssetupX);
1569 fstrcpy(sub_user, sub_user_mapped);
1570 add_session_user(sconn, sub_user);
1571 add_session_workgroup(sconn, domain);
1572 /* Then force it to null for the benfit of the code below */
1578 nt_status = check_guest_password(&server_info);
1580 } else if (doencrypt) {
1581 struct auth_context *negprot_auth_context = NULL;
1582 negprot_auth_context = sconn->smb1.negprot.auth_context;
1583 if (!negprot_auth_context) {
1584 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1585 "session setup without negprot denied!\n"));
1586 reply_nterror(req, nt_status_squash(
1587 NT_STATUS_LOGON_FAILURE));
1588 END_PROFILE(SMBsesssetupX);
1591 nt_status = make_user_info_for_reply_enc(&user_info, user,
1594 if (NT_STATUS_IS_OK(nt_status)) {
1595 nt_status = negprot_auth_context->check_ntlm_password(
1596 negprot_auth_context,
1601 struct auth_context *plaintext_auth_context = NULL;
1603 nt_status = make_auth_context_subsystem(
1604 talloc_tos(), &plaintext_auth_context);
1606 if (NT_STATUS_IS_OK(nt_status)) {
1609 plaintext_auth_context->get_ntlm_challenge(
1610 plaintext_auth_context, chal);
1612 if (!make_user_info_for_reply(&user_info,
1614 plaintext_password)) {
1615 nt_status = NT_STATUS_NO_MEMORY;
1618 if (NT_STATUS_IS_OK(nt_status)) {
1619 nt_status = plaintext_auth_context->check_ntlm_password(
1620 plaintext_auth_context,
1624 TALLOC_FREE(plaintext_auth_context);
1629 free_user_info(&user_info);
1631 if (!NT_STATUS_IS_OK(nt_status)) {
1632 nt_status = do_map_to_guest(nt_status, &server_info,
1636 if (!NT_STATUS_IS_OK(nt_status)) {
1637 data_blob_free(&nt_resp);
1638 data_blob_free(&lm_resp);
1639 data_blob_clear_free(&plaintext_password);
1640 reply_nterror(req, nt_status_squash(nt_status));
1641 END_PROFILE(SMBsesssetupX);
1645 /* Ensure we can't possible take a code path leading to a
1648 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1649 END_PROFILE(SMBsesssetupX);
1653 if (!server_info->security_token) {
1654 nt_status = create_local_token(server_info);
1656 if (!NT_STATUS_IS_OK(nt_status)) {
1657 DEBUG(10, ("create_local_token failed: %s\n",
1658 nt_errstr(nt_status)));
1659 data_blob_free(&nt_resp);
1660 data_blob_free(&lm_resp);
1661 data_blob_clear_free(&plaintext_password);
1662 reply_nterror(req, nt_status_squash(nt_status));
1663 END_PROFILE(SMBsesssetupX);
1668 data_blob_clear_free(&plaintext_password);
1670 /* it's ok - setup a reply */
1671 reply_outbuf(req, 3, 0);
1672 if (get_Protocol() >= PROTOCOL_NT1) {
1673 push_signature(&req->outbuf);
1674 /* perhaps grab OS version here?? */
1677 if (server_info->guest) {
1678 SSVAL(req->outbuf,smb_vwv2,1);
1681 /* register the name and uid as being validated, so further connections
1682 to a uid can get through without a password, on the same VC */
1684 if (lp_security() == SEC_SHARE) {
1685 sess_vuid = UID_FIELD_INVALID;
1686 TALLOC_FREE(server_info);
1688 /* Ignore the initial vuid. */
1689 sess_vuid = register_initial_vuid(sconn);
1690 if (sess_vuid == UID_FIELD_INVALID) {
1691 data_blob_free(&nt_resp);
1692 data_blob_free(&lm_resp);
1693 reply_nterror(req, nt_status_squash(
1694 NT_STATUS_LOGON_FAILURE));
1695 END_PROFILE(SMBsesssetupX);
1698 /* register_existing_vuid keeps the server info */
1699 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1701 nt_resp.data ? nt_resp : lm_resp,
1703 if (sess_vuid == UID_FIELD_INVALID) {
1704 data_blob_free(&nt_resp);
1705 data_blob_free(&lm_resp);
1706 reply_nterror(req, nt_status_squash(
1707 NT_STATUS_LOGON_FAILURE));
1708 END_PROFILE(SMBsesssetupX);
1712 /* current_user_info is changed on new vuid */
1713 reload_services(sconn->msg_ctx, sconn->sock, True);
1716 data_blob_free(&nt_resp);
1717 data_blob_free(&lm_resp);
1719 SSVAL(req->outbuf,smb_uid,sess_vuid);
1720 SSVAL(req->inbuf,smb_uid,sess_vuid);
1721 req->vuid = sess_vuid;
1723 if (!sconn->smb1.sessions.done_sesssetup) {
1724 sconn->smb1.sessions.max_send =
1725 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1727 sconn->smb1.sessions.done_sesssetup = true;
1729 END_PROFILE(SMBsesssetupX);