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"
38 #include "../libcli/security/security.h"
40 /* For split krb5 SPNEGO blobs. */
41 struct pending_auth_data {
42 struct pending_auth_data *prev, *next;
43 uint16 vuid; /* Tag for this entry. */
44 uint16 smbpid; /* Alternate tag for this entry. */
46 DATA_BLOB partial_data;
49 /****************************************************************************
50 Add the standard 'Samba' signature to the end of the session setup.
51 ****************************************************************************/
53 static int push_signature(uint8 **outbuf)
60 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
62 if (tmp == -1) return -1;
65 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
66 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
70 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
73 if (tmp == -1) return -1;
76 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
78 if (tmp == -1) return -1;
84 /****************************************************************************
85 Send a security blob via a session setup reply.
86 ****************************************************************************/
88 static void reply_sesssetup_blob(struct smb_request *req,
92 if (!NT_STATUS_IS_OK(nt_status) &&
93 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
94 reply_nterror(req, nt_status_squash(nt_status));
98 nt_status = nt_status_squash(nt_status);
99 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
100 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
101 SSVAL(req->outbuf, smb_vwv3, blob.length);
103 if ((message_push_blob(&req->outbuf, blob) == -1)
104 || (push_signature(&req->outbuf) == -1)) {
105 reply_nterror(req, NT_STATUS_NO_MEMORY);
109 /****************************************************************************
110 Do a 'guest' logon, getting back the
111 ****************************************************************************/
113 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
114 struct auth_serversupplied_info **server_info)
116 struct auth_context *auth_context;
117 struct auth_usersupplied_info *user_info = NULL;
120 static unsigned char chal[8] = { 0, };
122 DEBUG(3,("Got anonymous request\n"));
124 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
125 if (!NT_STATUS_IS_OK(nt_status)) {
129 if (!make_user_info_guest(remote_address, &user_info)) {
130 TALLOC_FREE(auth_context);
131 return NT_STATUS_NO_MEMORY;
134 nt_status = auth_context->check_ntlm_password(auth_context,
137 TALLOC_FREE(auth_context);
138 free_user_info(&user_info);
146 /* Experiment that failed. See "only happens with a KDC" comment below. */
147 /****************************************************************************
148 Cerate a clock skew error blob for a Windows client.
149 ****************************************************************************/
151 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
153 krb5_context context = NULL;
154 krb5_error_code kerr = 0;
156 krb5_principal host_princ = NULL;
157 char *host_princ_s = NULL;
160 *pblob_out = data_blob_null;
162 initialize_krb5_error_table();
163 kerr = krb5_init_context(&context);
167 /* Create server principal. */
168 asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
172 strlower_m(host_princ_s);
174 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
176 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
177 "for name %s: Error %s\n",
178 host_princ_s, error_message(kerr) ));
182 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
185 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
186 "failed: Error %s\n",
187 error_message(kerr) ));
191 *pblob_out = data_blob(reply.data, reply.length);
192 kerberos_free_data_contents(context,&reply);
198 SAFE_FREE(host_princ_s);
201 krb5_free_principal(context, host_princ);
203 krb5_free_context(context);
208 /****************************************************************************
209 Reply to a session setup spnego negotiate packet for kerberos.
210 ****************************************************************************/
212 static void reply_spnego_kerberos(struct smb_request *req,
216 bool *p_invalidate_vuid)
221 int sess_vuid = req->vuid;
222 NTSTATUS ret = NT_STATUS_OK;
223 DATA_BLOB ap_rep, ap_rep_wrapped, response;
224 struct auth_session_info *session_info = NULL;
225 DATA_BLOB session_key = data_blob_null;
227 DATA_BLOB nullblob = data_blob_null;
228 bool map_domainuser_to_guest = False;
229 bool username_was_mapped;
230 struct PAC_LOGON_INFO *logon_info = NULL;
231 struct smbd_server_connection *sconn = req->sconn;
239 ZERO_STRUCT(ap_rep_wrapped);
240 ZERO_STRUCT(response);
242 /* Normally we will always invalidate the intermediate vuid. */
243 *p_invalidate_vuid = True;
245 mem_ctx = talloc_init("reply_spnego_kerberos");
246 if (mem_ctx == NULL) {
247 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
251 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
252 talloc_destroy(mem_ctx);
253 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
257 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
258 &principal, &logon_info, &ap_rep,
261 data_blob_free(&ticket);
263 if (!NT_STATUS_IS_OK(ret)) {
265 /* Experiment that failed.
266 * See "only happens with a KDC" comment below. */
268 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
271 * Windows in this case returns
272 * NT_STATUS_MORE_PROCESSING_REQUIRED
273 * with a negTokenTarg blob containing an krb5_error
274 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
275 * The client then fixes its clock and continues rather
276 * than giving an error. JRA.
277 * -- Looks like this only happens with a KDC. JRA.
280 bool ok = make_krb5_skew_error(&ap_rep);
282 talloc_destroy(mem_ctx);
283 return ERROR_NT(nt_status_squash(
284 NT_STATUS_LOGON_FAILURE));
286 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
288 response = spnego_gen_auth_response(&ap_rep_wrapped,
289 ret, OID_KERBEROS5_OLD);
290 reply_sesssetup_blob(conn, inbuf, outbuf, response,
291 NT_STATUS_MORE_PROCESSING_REQUIRED);
294 * In this one case we don't invalidate the
295 * intermediate vuid as we're expecting the client
296 * to re-use it for the next sessionsetupX packet. JRA.
299 *p_invalidate_vuid = False;
301 data_blob_free(&ap_rep);
302 data_blob_free(&ap_rep_wrapped);
303 data_blob_free(&response);
304 talloc_destroy(mem_ctx);
305 return -1; /* already replied */
308 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
309 ret = NT_STATUS_LOGON_FAILURE;
312 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
314 talloc_destroy(mem_ctx);
315 reply_nterror(req, nt_status_squash(ret));
319 ret = get_user_from_kerberos_info(talloc_tos(),
320 sconn->remote_hostname,
321 principal, logon_info,
322 &username_was_mapped,
323 &map_domainuser_to_guest,
325 &real_username, &pw);
326 if (!NT_STATUS_IS_OK(ret)) {
327 data_blob_free(&ap_rep);
328 data_blob_free(&session_key);
329 talloc_destroy(mem_ctx);
330 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
334 /* save the PAC data if we have it */
336 netsamlogon_cache_store(user, &logon_info->info3);
339 /* setup the string used by %U */
340 sub_set_smb_name(real_username);
342 /* reload services so that the new %U is taken into account */
343 reload_services(sconn->msg_ctx, sconn->sock, True);
345 ret = make_session_info_krb5(mem_ctx,
346 user, domain, real_username, pw,
347 logon_info, map_domainuser_to_guest,
351 data_blob_free(&session_key);
352 if (!NT_STATUS_IS_OK(ret)) {
353 DEBUG(1, ("make_server_info_krb5 failed!\n"));
354 data_blob_free(&ap_rep);
355 TALLOC_FREE(mem_ctx);
356 reply_nterror(req, nt_status_squash(ret));
360 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
361 sess_vuid = register_initial_vuid(sconn);
364 /* register_existing_vuid keeps the server info */
365 /* register_existing_vuid takes ownership of session_key on success,
366 * no need to free after this on success. A better interface would copy
369 sess_vuid = register_existing_vuid(sconn, sess_vuid,
370 session_info, nullblob, user);
372 reply_outbuf(req, 4, 0);
373 SSVAL(req->outbuf,smb_uid,sess_vuid);
375 if (sess_vuid == UID_FIELD_INVALID ) {
376 ret = NT_STATUS_LOGON_FAILURE;
378 /* current_user_info is changed on new vuid */
379 reload_services(sconn->msg_ctx, sconn->sock, True);
381 SSVAL(req->outbuf, smb_vwv3, 0);
383 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
384 SSVAL(req->outbuf,smb_vwv2,1);
387 SSVAL(req->outbuf, smb_uid, sess_vuid);
389 /* Successful logon. Keep this vuid. */
390 *p_invalidate_vuid = False;
393 /* wrap that up in a nice GSS-API wrapping */
394 if (NT_STATUS_IS_OK(ret)) {
395 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
398 ap_rep_wrapped = data_blob_null;
400 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
402 reply_sesssetup_blob(req, response, ret);
404 data_blob_free(&ap_rep);
405 data_blob_free(&ap_rep_wrapped);
406 data_blob_free(&response);
407 TALLOC_FREE(mem_ctx);
412 /****************************************************************************
413 Send a session setup reply, wrapped in SPNEGO.
414 Get vuid and check first.
415 End the NTLMSSP exchange context if we are OK/complete fail
416 This should be split into two functions, one to handle each
417 leg of the NTLM auth steps.
418 ***************************************************************************/
420 static void reply_spnego_ntlmssp(struct smb_request *req,
422 struct auth_ntlmssp_state **auth_ntlmssp_state,
423 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
427 bool do_invalidate = true;
429 struct auth_session_info *session_info = NULL;
430 struct smbd_server_connection *sconn = req->sconn;
432 if (NT_STATUS_IS_OK(nt_status)) {
433 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
434 (*auth_ntlmssp_state), &session_info);
437 reply_outbuf(req, 4, 0);
439 SSVAL(req->outbuf, smb_uid, vuid);
441 if (NT_STATUS_IS_OK(nt_status)) {
442 DATA_BLOB nullblob = data_blob_null;
444 if (!is_partial_auth_vuid(sconn, vuid)) {
445 nt_status = NT_STATUS_LOGON_FAILURE;
449 /* register_existing_vuid keeps the server info */
450 if (register_existing_vuid(sconn, vuid,
451 session_info, nullblob,
452 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
454 /* The problem is, *auth_ntlmssp_state points
455 * into the vuser this will have
456 * talloc_free()'ed in
457 * register_existing_vuid() */
458 do_invalidate = false;
459 nt_status = NT_STATUS_LOGON_FAILURE;
463 /* current_user_info is changed on new vuid */
464 reload_services(sconn->msg_ctx, sconn->sock, True);
466 SSVAL(req->outbuf, smb_vwv3, 0);
468 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
469 SSVAL(req->outbuf,smb_vwv2,1);
476 response = spnego_gen_auth_response(talloc_tos(),
480 response = *ntlmssp_blob;
483 reply_sesssetup_blob(req, response, nt_status);
485 data_blob_free(&response);
488 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
489 and the other end, that we are not finished yet. */
491 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
492 /* NB. This is *NOT* an error case. JRA */
494 TALLOC_FREE(*auth_ntlmssp_state);
495 if (!NT_STATUS_IS_OK(nt_status)) {
496 /* Kill the intermediate vuid */
497 invalidate_vuid(sconn, vuid);
503 /****************************************************************************
504 Is this a krb5 mechanism ?
505 ****************************************************************************/
507 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
509 DATA_BLOB *pblob_out,
512 char *OIDs[ASN1_MAX_OIDS];
514 NTSTATUS ret = NT_STATUS_OK;
516 *kerb_mechOID = NULL;
518 /* parse out the OIDs and the first sec blob */
519 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
521 return NT_STATUS_LOGON_FAILURE;
524 /* only look at the first OID for determining the mechToken --
525 according to RFC2478, we should choose the one we want
526 and renegotiate, but i smell a client bug here..
528 Problem observed when connecting to a member (samba box)
529 of an AD domain as a user in a Samba domain. Samba member
530 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
531 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
532 NTLMSSP mechtoken. --jerry */
535 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
536 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
537 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
538 if (*kerb_mechOID == NULL) {
539 ret = NT_STATUS_NO_MEMORY;
544 for (i=0;OIDs[i];i++) {
545 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
546 talloc_free(OIDs[i]);
551 /****************************************************************************
552 Fall back from krb5 to NTLMSSP.
553 ****************************************************************************/
555 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
560 reply_outbuf(req, 4, 0);
561 SSVAL(req->outbuf,smb_uid,vuid);
563 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
564 "but set to downgrade to NTLMSSP\n"));
566 response = spnego_gen_auth_response(talloc_tos(), NULL,
567 NT_STATUS_MORE_PROCESSING_REQUIRED,
569 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
570 data_blob_free(&response);
573 /****************************************************************************
574 Reply to a session setup spnego negotiate packet.
575 ****************************************************************************/
577 static void reply_spnego_negotiate(struct smb_request *req,
580 struct auth_ntlmssp_state **auth_ntlmssp_state)
584 char *kerb_mech = NULL;
586 struct smbd_server_connection *sconn = req->sconn;
588 status = parse_spnego_mechanisms(talloc_tos(),
589 blob1, &secblob, &kerb_mech);
590 if (!NT_STATUS_IS_OK(status)) {
591 /* Kill the intermediate vuid */
592 invalidate_vuid(sconn, vuid);
593 reply_nterror(req, nt_status_squash(status));
597 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
598 (unsigned long)secblob.length));
601 if (kerb_mech && ((lp_security()==SEC_ADS) ||
602 USE_KERBEROS_KEYTAB) ) {
603 bool destroy_vuid = True;
604 reply_spnego_kerberos(req, &secblob, kerb_mech,
605 vuid, &destroy_vuid);
606 data_blob_free(&secblob);
608 /* Kill the intermediate vuid */
609 invalidate_vuid(sconn, vuid);
611 TALLOC_FREE(kerb_mech);
616 TALLOC_FREE(*auth_ntlmssp_state);
619 data_blob_free(&secblob);
620 /* The mechtoken is a krb5 ticket, but
621 * we need to fall back to NTLM. */
622 reply_spnego_downgrade_to_ntlmssp(req, vuid);
623 TALLOC_FREE(kerb_mech);
627 status = auth_ntlmssp_start(sconn->remote_address,
629 if (!NT_STATUS_IS_OK(status)) {
630 /* Kill the intermediate vuid */
631 invalidate_vuid(sconn, vuid);
632 reply_nterror(req, nt_status_squash(status));
636 status = auth_ntlmssp_update(*auth_ntlmssp_state,
639 data_blob_free(&secblob);
641 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
642 &chal, status, OID_NTLMSSP, true);
644 data_blob_free(&chal);
646 /* already replied */
650 /****************************************************************************
651 Reply to a session setup spnego auth packet.
652 ****************************************************************************/
654 static void reply_spnego_auth(struct smb_request *req,
657 struct auth_ntlmssp_state **auth_ntlmssp_state)
659 DATA_BLOB auth = data_blob_null;
660 DATA_BLOB auth_reply = data_blob_null;
661 DATA_BLOB secblob = data_blob_null;
662 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
663 struct smbd_server_connection *sconn = req->sconn;
665 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
667 file_save("auth.dat", blob1.data, blob1.length);
669 /* Kill the intermediate vuid */
670 invalidate_vuid(sconn, vuid);
672 reply_nterror(req, nt_status_squash(
673 NT_STATUS_LOGON_FAILURE));
677 if (auth.data[0] == ASN1_APPLICATION(0)) {
678 /* Might be a second negTokenTarg packet */
679 char *kerb_mech = NULL;
681 status = parse_spnego_mechanisms(talloc_tos(),
682 auth, &secblob, &kerb_mech);
684 if (!NT_STATUS_IS_OK(status)) {
685 /* Kill the intermediate vuid */
686 invalidate_vuid(sconn, vuid);
687 reply_nterror(req, nt_status_squash(status));
691 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
692 (unsigned long)secblob.length));
694 if (kerb_mech && ((lp_security()==SEC_ADS) ||
695 USE_KERBEROS_KEYTAB)) {
696 bool destroy_vuid = True;
697 reply_spnego_kerberos(req, &secblob, kerb_mech,
698 vuid, &destroy_vuid);
699 data_blob_free(&secblob);
700 data_blob_free(&auth);
702 /* Kill the intermediate vuid */
703 invalidate_vuid(sconn, vuid);
705 TALLOC_FREE(kerb_mech);
709 /* Can't blunder into NTLMSSP auth if we have
713 /* Kill the intermediate vuid */
714 invalidate_vuid(sconn, vuid);
715 DEBUG(3,("reply_spnego_auth: network "
716 "misconfiguration, client sent us a "
717 "krb5 ticket and kerberos security "
719 reply_nterror(req, nt_status_squash(
720 NT_STATUS_LOGON_FAILURE));
721 TALLOC_FREE(kerb_mech);
725 /* If we get here it wasn't a negTokenTarg auth packet. */
726 data_blob_free(&secblob);
728 if (!*auth_ntlmssp_state) {
729 status = auth_ntlmssp_start(sconn->remote_address,
731 if (!NT_STATUS_IS_OK(status)) {
732 /* Kill the intermediate vuid */
733 invalidate_vuid(sconn, vuid);
734 reply_nterror(req, nt_status_squash(status));
739 status = auth_ntlmssp_update(*auth_ntlmssp_state,
742 data_blob_free(&auth);
744 /* Don't send the mechid as we've already sent this (RFC4178). */
746 reply_spnego_ntlmssp(req, vuid,
748 &auth_reply, status, NULL, true);
750 data_blob_free(&auth_reply);
752 /* and tell smbd that we have already replied to this packet */
756 /****************************************************************************
757 Delete an entry on the list.
758 ****************************************************************************/
760 static void delete_partial_auth(struct smbd_server_connection *sconn,
761 struct pending_auth_data *pad)
766 DLIST_REMOVE(sconn->smb1.pd_list, pad);
767 data_blob_free(&pad->partial_data);
771 /****************************************************************************
772 Search for a partial SPNEGO auth fragment matching an smbpid.
773 ****************************************************************************/
775 static struct pending_auth_data *get_pending_auth_data(
776 struct smbd_server_connection *sconn,
779 struct pending_auth_data *pad;
781 * NOTE: using the smbpid here is completely wrong...
783 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
785 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
786 if (pad->smbpid == smbpid) {
793 /****************************************************************************
794 Check the size of an SPNEGO blob. If we need more return
795 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
796 the blob to be more than 64k.
797 ****************************************************************************/
799 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
800 uint16 smbpid, uint16 vuid,
803 struct pending_auth_data *pad = NULL;
805 size_t needed_len = 0;
807 pad = get_pending_auth_data(sconn, smbpid);
809 /* Ensure we have some data. */
810 if (pblob->length == 0) {
811 /* Caller can cope. */
812 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
813 delete_partial_auth(sconn, pad);
817 /* Were we waiting for more data ? */
820 size_t copy_len = MIN(65536, pblob->length);
822 /* Integer wrap paranoia.... */
824 if (pad->partial_data.length + copy_len <
825 pad->partial_data.length ||
826 pad->partial_data.length + copy_len < copy_len) {
828 DEBUG(2,("check_spnego_blob_complete: integer wrap "
829 "pad->partial_data.length = %u, "
831 (unsigned int)pad->partial_data.length,
832 (unsigned int)copy_len ));
834 delete_partial_auth(sconn, pad);
835 return NT_STATUS_INVALID_PARAMETER;
838 DEBUG(10,("check_spnego_blob_complete: "
839 "pad->partial_data.length = %u, "
840 "pad->needed_len = %u, "
842 "pblob->length = %u,\n",
843 (unsigned int)pad->partial_data.length,
844 (unsigned int)pad->needed_len,
845 (unsigned int)copy_len,
846 (unsigned int)pblob->length ));
848 tmp_blob = data_blob(NULL,
849 pad->partial_data.length + copy_len);
851 /* Concatenate the two (up to copy_len) bytes. */
852 memcpy(tmp_blob.data,
853 pad->partial_data.data,
854 pad->partial_data.length);
855 memcpy(tmp_blob.data + pad->partial_data.length,
859 /* Replace the partial data. */
860 data_blob_free(&pad->partial_data);
861 pad->partial_data = tmp_blob;
862 ZERO_STRUCT(tmp_blob);
865 if (pblob->length >= pad->needed_len) {
866 /* Yes, replace pblob. */
867 data_blob_free(pblob);
868 *pblob = pad->partial_data;
869 ZERO_STRUCT(pad->partial_data);
870 delete_partial_auth(sconn, pad);
874 /* Still need more data. */
875 pad->needed_len -= copy_len;
876 return NT_STATUS_MORE_PROCESSING_REQUIRED;
879 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
880 (pblob->data[0] != ASN1_CONTEXT(1))) {
881 /* Not something we can determine the
887 /* This is a new SPNEGO sessionsetup - see if
888 * the data given in this blob is enough.
891 data = asn1_init(NULL);
893 return NT_STATUS_NO_MEMORY;
896 asn1_load(data, *pblob);
897 if (asn1_start_tag(data, pblob->data[0])) {
898 /* asn1_start_tag checks if the given
899 length of the blob is enough to complete
900 the tag. If it returns true we know
901 there is nothing to do - the blob is
907 if (data->nesting == NULL) {
908 /* Incorrect tag, allocation failed,
909 or reading the tag length failed.
910 Let the caller catch. */
915 /* Here we know asn1_start_tag() has set data->has_error to true.
916 asn1_tag_remaining() will have failed due to the given blob
917 being too short. We need to work out how short. */
919 /* Integer wrap paranoia.... */
921 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
922 data->nesting->taglen + data->nesting->start < data->nesting->start) {
924 DEBUG(2,("check_spnego_blob_complete: integer wrap "
925 "data.nesting->taglen = %u, "
926 "data.nesting->start = %u\n",
927 (unsigned int)data->nesting->taglen,
928 (unsigned int)data->nesting->start ));
931 return NT_STATUS_INVALID_PARAMETER;
934 /* Total length of the needed asn1 is the tag length
935 * plus the current offset. */
937 needed_len = data->nesting->taglen + data->nesting->start;
940 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
941 "pblob->length = %u\n",
942 (unsigned int)needed_len,
943 (unsigned int)pblob->length ));
945 if (needed_len <= pblob->length) {
946 /* Nothing to do - blob is complete. */
947 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
948 above should have caught this !!! */
949 DEBUG(0,("check_spnego_blob_complete: logic "
950 "error (needed_len = %u, "
951 "pblob->length = %u).\n",
952 (unsigned int)needed_len,
953 (unsigned int)pblob->length ));
957 /* Refuse the blob if it's bigger than 64k. */
958 if (needed_len > 65536) {
959 DEBUG(2,("check_spnego_blob_complete: needed_len "
961 (unsigned int)needed_len ));
962 return NT_STATUS_INVALID_PARAMETER;
965 /* We must store this blob until complete. */
966 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
967 return NT_STATUS_NO_MEMORY;
969 pad->needed_len = needed_len - pblob->length;
970 pad->partial_data = data_blob(pblob->data, pblob->length);
971 if (pad->partial_data.data == NULL) {
973 return NT_STATUS_NO_MEMORY;
975 pad->smbpid = smbpid;
977 DLIST_ADD(sconn->smb1.pd_list, pad);
979 return NT_STATUS_MORE_PROCESSING_REQUIRED;
982 /****************************************************************************
983 Reply to a session setup command.
984 conn POINTER CAN BE NULL HERE !
985 ****************************************************************************/
987 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
993 const char *native_os;
994 const char *native_lanman;
995 const char *primary_domain;
997 uint16 data_blob_len = SVAL(req->vwv+7, 0);
998 enum remote_arch_types ra_type = get_remote_arch();
999 int vuid = req->vuid;
1000 user_struct *vuser = NULL;
1001 NTSTATUS status = NT_STATUS_OK;
1002 uint16 smbpid = req->smbpid;
1003 struct smbd_server_connection *sconn = req->sconn;
1005 DEBUG(3,("Doing spnego session setup\n"));
1007 if (global_client_caps == 0) {
1008 global_client_caps = IVAL(req->vwv+10, 0);
1010 if (!(global_client_caps & CAP_STATUS32)) {
1011 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1018 if (data_blob_len == 0) {
1019 /* an invalid request */
1020 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1024 bufrem = smbreq_bufrem(req, p);
1025 /* pull the spnego blob */
1026 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1029 file_save("negotiate.dat", blob1.data, blob1.length);
1032 p2 = (const char *)req->buf + blob1.length;
1034 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1036 native_os = tmp ? tmp : "";
1038 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1040 native_lanman = tmp ? tmp : "";
1042 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1044 primary_domain = tmp ? tmp : "";
1046 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1047 native_os, native_lanman, primary_domain));
1049 if ( ra_type == RA_WIN2K ) {
1050 /* Vista sets neither the OS or lanman strings */
1052 if ( !strlen(native_os) && !strlen(native_lanman) )
1053 set_remote_arch(RA_VISTA);
1055 /* Windows 2003 doesn't set the native lanman string,
1056 but does set primary domain which is a bug I think */
1058 if ( !strlen(native_lanman) ) {
1059 ra_lanman_string( primary_domain );
1061 ra_lanman_string( native_lanman );
1063 } else if ( ra_type == RA_VISTA ) {
1064 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1065 set_remote_arch(RA_OSX);
1069 /* Did we get a valid vuid ? */
1070 if (!is_partial_auth_vuid(sconn, vuid)) {
1071 /* No, then try and see if this is an intermediate sessionsetup
1072 * for a large SPNEGO packet. */
1073 struct pending_auth_data *pad;
1074 pad = get_pending_auth_data(sconn, smbpid);
1076 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1077 "pending vuid %u\n",
1078 (unsigned int)pad->vuid ));
1083 /* Do we have a valid vuid now ? */
1084 if (!is_partial_auth_vuid(sconn, vuid)) {
1085 /* No, start a new authentication setup. */
1086 vuid = register_initial_vuid(sconn);
1087 if (vuid == UID_FIELD_INVALID) {
1088 data_blob_free(&blob1);
1089 reply_nterror(req, nt_status_squash(
1090 NT_STATUS_INVALID_PARAMETER));
1095 vuser = get_partial_auth_user_struct(sconn, vuid);
1096 /* This MUST be valid. */
1098 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1101 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1102 * sessionsetup requests as the Windows limit on the security blob
1103 * field is 4k. Bug #4400. JRA.
1106 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1107 if (!NT_STATUS_IS_OK(status)) {
1108 if (!NT_STATUS_EQUAL(status,
1109 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1110 /* Real error - kill the intermediate vuid */
1111 invalidate_vuid(sconn, vuid);
1113 data_blob_free(&blob1);
1114 reply_nterror(req, nt_status_squash(status));
1118 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1120 /* its a negTokenTarg packet */
1122 reply_spnego_negotiate(req, vuid, blob1,
1123 &vuser->auth_ntlmssp_state);
1124 data_blob_free(&blob1);
1128 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1130 /* its a auth packet */
1132 reply_spnego_auth(req, vuid, blob1,
1133 &vuser->auth_ntlmssp_state);
1134 data_blob_free(&blob1);
1138 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1141 if (!vuser->auth_ntlmssp_state) {
1142 status = auth_ntlmssp_start(sconn->remote_address,
1143 &vuser->auth_ntlmssp_state);
1144 if (!NT_STATUS_IS_OK(status)) {
1145 /* Kill the intermediate vuid */
1146 invalidate_vuid(sconn, vuid);
1147 data_blob_free(&blob1);
1148 reply_nterror(req, nt_status_squash(status));
1153 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1156 data_blob_free(&blob1);
1158 reply_spnego_ntlmssp(req, vuid,
1159 &vuser->auth_ntlmssp_state,
1160 &chal, status, OID_NTLMSSP, false);
1161 data_blob_free(&chal);
1165 /* what sort of packet is this? */
1166 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1168 data_blob_free(&blob1);
1170 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1173 /****************************************************************************
1174 On new VC == 0, shutdown *all* old connections and users.
1175 It seems that only NT4.x does this. At W2K and above (XP etc.).
1176 a new session setup with VC==0 is ignored.
1177 ****************************************************************************/
1179 struct shutdown_state {
1181 struct messaging_context *msg_ctx;
1184 static int shutdown_other_smbds(const struct connections_key *key,
1185 const struct connections_data *crec,
1188 struct shutdown_state *state = (struct shutdown_state *)private_data;
1190 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1191 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1193 if (!process_exists(crec->pid)) {
1194 DEBUG(10, ("process does not exist\n"));
1198 if (procid_is_me(&crec->pid)) {
1199 DEBUG(10, ("It's me\n"));
1203 if (strcmp(state->ip, crec->addr) != 0) {
1204 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1208 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1209 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1212 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1217 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1219 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1220 "compatible we would close all old resources.\n"));
1223 invalidate_all_vuids();
1225 if (lp_reset_on_zero_vc()) {
1227 struct shutdown_state state;
1229 addr = tsocket_address_inet_addr_string(
1230 sconn->remote_address, talloc_tos());
1235 state.msg_ctx = sconn->msg_ctx;
1236 connections_forall_read(shutdown_other_smbds, &state);
1241 /****************************************************************************
1242 Reply to a session setup command.
1243 ****************************************************************************/
1245 void reply_sesssetup_and_X(struct smb_request *req)
1251 DATA_BLOB plaintext_password;
1254 fstring sub_user; /* Sanitised username for substituion */
1256 const char *native_os;
1257 const char *native_lanman;
1258 const char *primary_domain;
1259 struct auth_usersupplied_info *user_info = NULL;
1260 struct auth_serversupplied_info *server_info = NULL;
1261 struct auth_session_info *session_info = NULL;
1262 uint16 smb_flag2 = req->flags2;
1265 struct smbd_server_connection *sconn = req->sconn;
1267 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1269 START_PROFILE(SMBsesssetupX);
1271 ZERO_STRUCT(lm_resp);
1272 ZERO_STRUCT(nt_resp);
1273 ZERO_STRUCT(plaintext_password);
1275 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1277 /* a SPNEGO session setup has 12 command words, whereas a normal
1278 NT1 session setup has 13. See the cifs spec. */
1279 if (req->wct == 12 &&
1280 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1282 if (!sconn->smb1.negprot.spnego) {
1283 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1284 "at SPNEGO session setup when it was not "
1286 reply_nterror(req, nt_status_squash(
1287 NT_STATUS_LOGON_FAILURE));
1288 END_PROFILE(SMBsesssetupX);
1292 if (SVAL(req->vwv+4, 0) == 0) {
1293 setup_new_vc_session(req->sconn);
1296 reply_sesssetup_and_X_spnego(req);
1297 END_PROFILE(SMBsesssetupX);
1301 smb_bufsize = SVAL(req->vwv+2, 0);
1303 if (get_Protocol() < PROTOCOL_NT1) {
1304 uint16 passlen1 = SVAL(req->vwv+7, 0);
1306 /* Never do NT status codes with protocols before NT1 as we
1307 * don't get client caps. */
1308 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1310 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1311 reply_nterror(req, nt_status_squash(
1312 NT_STATUS_INVALID_PARAMETER));
1313 END_PROFILE(SMBsesssetupX);
1318 lm_resp = data_blob(req->buf, passlen1);
1320 plaintext_password = data_blob(req->buf, passlen1+1);
1321 /* Ensure null termination */
1322 plaintext_password.data[passlen1] = 0;
1325 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1326 req->buf + passlen1, STR_TERMINATE);
1327 user = tmp ? tmp : "";
1332 uint16 passlen1 = SVAL(req->vwv+7, 0);
1333 uint16 passlen2 = SVAL(req->vwv+8, 0);
1334 enum remote_arch_types ra_type = get_remote_arch();
1335 const uint8_t *p = req->buf;
1336 const uint8_t *save_p = req->buf;
1340 if(global_client_caps == 0) {
1341 global_client_caps = IVAL(req->vwv+11, 0);
1343 if (!(global_client_caps & CAP_STATUS32)) {
1344 remove_from_common_flags2(
1345 FLAGS2_32_BIT_ERROR_CODES);
1348 /* client_caps is used as final determination if
1349 * client is NT or Win95. This is needed to return
1350 * the correct error codes in some circumstances.
1353 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1354 ra_type == RA_WIN95) {
1355 if(!(global_client_caps & (CAP_NT_SMBS|
1357 set_remote_arch( RA_WIN95);
1363 /* both Win95 and WinNT stuff up the password
1364 * lengths for non-encrypting systems. Uggh.
1366 if passlen1==24 its a win95 system, and its setting
1367 the password length incorrectly. Luckily it still
1368 works with the default code because Win95 will null
1369 terminate the password anyway
1371 if passlen1>0 and passlen2>0 then maybe its a NT box
1372 and its setting passlen2 to some random value which
1373 really stuffs things up. we need to fix that one. */
1375 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1381 /* check for nasty tricks */
1382 if (passlen1 > MAX_PASS_LEN
1383 || passlen1 > smbreq_bufrem(req, p)) {
1384 reply_nterror(req, nt_status_squash(
1385 NT_STATUS_INVALID_PARAMETER));
1386 END_PROFILE(SMBsesssetupX);
1390 if (passlen2 > MAX_PASS_LEN
1391 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1392 reply_nterror(req, nt_status_squash(
1393 NT_STATUS_INVALID_PARAMETER));
1394 END_PROFILE(SMBsesssetupX);
1398 /* Save the lanman2 password and the NT md4 password. */
1400 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1405 lm_resp = data_blob(p, passlen1);
1406 nt_resp = data_blob(p+passlen1, passlen2);
1407 } else if (lp_security() != SEC_SHARE) {
1409 * In share level we should ignore any passwords, so
1410 * only read them if we're not.
1413 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1415 if (unic && (passlen2 == 0) && passlen1) {
1416 /* Only a ascii plaintext password was sent. */
1417 (void)srvstr_pull_talloc(talloc_tos(),
1423 STR_TERMINATE|STR_ASCII);
1425 (void)srvstr_pull_talloc(talloc_tos(),
1430 unic ? passlen2 : passlen1,
1434 reply_nterror(req, nt_status_squash(
1435 NT_STATUS_INVALID_PARAMETER));
1436 END_PROFILE(SMBsesssetupX);
1439 plaintext_password = data_blob(pass, strlen(pass)+1);
1442 p += passlen1 + passlen2;
1444 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1446 user = tmp ? tmp : "";
1448 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1450 domain = tmp ? tmp : "";
1452 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1454 native_os = tmp ? tmp : "";
1456 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1458 native_lanman = tmp ? tmp : "";
1460 /* not documented or decoded by Ethereal but there is one more
1461 * string in the extra bytes which is the same as the
1462 * PrimaryDomain when using extended security. Windows NT 4
1463 * and 2003 use this string to store the native lanman string.
1464 * Windows 9x does not include a string here at all so we have
1465 * to check if we have any extra bytes left */
1467 byte_count = SVAL(req->vwv+13, 0);
1468 if ( PTR_DIFF(p, save_p) < byte_count) {
1469 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1471 primary_domain = tmp ? tmp : "";
1473 primary_domain = talloc_strdup(talloc_tos(), "null");
1476 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1477 "PrimaryDomain=[%s]\n",
1478 domain, native_os, native_lanman, primary_domain));
1480 if ( ra_type == RA_WIN2K ) {
1481 if ( strlen(native_lanman) == 0 )
1482 ra_lanman_string( primary_domain );
1484 ra_lanman_string( native_lanman );
1489 if (SVAL(req->vwv+4, 0) == 0) {
1490 setup_new_vc_session(req->sconn);
1493 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1494 domain, user, get_remote_machine_name()));
1497 if (sconn->smb1.negprot.spnego) {
1499 /* This has to be here, because this is a perfectly
1500 * valid behaviour for guest logons :-( */
1502 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1503 "at 'normal' session setup after "
1504 "negotiating spnego.\n"));
1505 reply_nterror(req, nt_status_squash(
1506 NT_STATUS_LOGON_FAILURE));
1507 END_PROFILE(SMBsesssetupX);
1510 fstrcpy(sub_user, user);
1512 fstrcpy(sub_user, lp_guestaccount());
1515 sub_set_smb_name(sub_user);
1517 reload_services(sconn->msg_ctx, sconn->sock, True);
1519 if (lp_security() == SEC_SHARE) {
1520 char *sub_user_mapped = NULL;
1521 /* In share level we should ignore any passwords */
1523 data_blob_free(&lm_resp);
1524 data_blob_free(&nt_resp);
1525 data_blob_clear_free(&plaintext_password);
1527 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1528 if (!sub_user_mapped) {
1529 reply_nterror(req, NT_STATUS_NO_MEMORY);
1530 END_PROFILE(SMBsesssetupX);
1533 fstrcpy(sub_user, sub_user_mapped);
1534 add_session_user(sconn, sub_user);
1535 add_session_workgroup(sconn, domain);
1536 /* Then force it to null for the benfit of the code below */
1542 nt_status = check_guest_password(sconn->remote_address, &server_info);
1544 } else if (doencrypt) {
1545 struct auth_context *negprot_auth_context = NULL;
1546 negprot_auth_context = sconn->smb1.negprot.auth_context;
1547 if (!negprot_auth_context) {
1548 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1549 "session setup without negprot denied!\n"));
1550 reply_nterror(req, nt_status_squash(
1551 NT_STATUS_LOGON_FAILURE));
1552 END_PROFILE(SMBsesssetupX);
1555 nt_status = make_user_info_for_reply_enc(&user_info, user,
1557 sconn->remote_address,
1559 if (NT_STATUS_IS_OK(nt_status)) {
1560 nt_status = negprot_auth_context->check_ntlm_password(
1561 negprot_auth_context,
1566 struct auth_context *plaintext_auth_context = NULL;
1568 nt_status = make_auth_context_subsystem(
1569 talloc_tos(), &plaintext_auth_context);
1571 if (NT_STATUS_IS_OK(nt_status)) {
1574 plaintext_auth_context->get_ntlm_challenge(
1575 plaintext_auth_context, chal);
1577 if (!make_user_info_for_reply(&user_info,
1579 sconn->remote_address,
1581 plaintext_password)) {
1582 nt_status = NT_STATUS_NO_MEMORY;
1585 if (NT_STATUS_IS_OK(nt_status)) {
1586 nt_status = plaintext_auth_context->check_ntlm_password(
1587 plaintext_auth_context,
1591 TALLOC_FREE(plaintext_auth_context);
1596 free_user_info(&user_info);
1598 if (!NT_STATUS_IS_OK(nt_status)) {
1599 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1603 if (!NT_STATUS_IS_OK(nt_status)) {
1604 data_blob_free(&nt_resp);
1605 data_blob_free(&lm_resp);
1606 data_blob_clear_free(&plaintext_password);
1607 reply_nterror(req, nt_status_squash(nt_status));
1608 END_PROFILE(SMBsesssetupX);
1612 nt_status = create_local_token(req, server_info, NULL, &session_info);
1613 TALLOC_FREE(server_info);
1615 if (!NT_STATUS_IS_OK(nt_status)) {
1616 DEBUG(10, ("create_local_token failed: %s\n",
1617 nt_errstr(nt_status)));
1618 data_blob_free(&nt_resp);
1619 data_blob_free(&lm_resp);
1620 data_blob_clear_free(&plaintext_password);
1621 reply_nterror(req, nt_status_squash(nt_status));
1622 END_PROFILE(SMBsesssetupX);
1626 data_blob_clear_free(&plaintext_password);
1628 /* it's ok - setup a reply */
1629 reply_outbuf(req, 3, 0);
1630 if (get_Protocol() >= PROTOCOL_NT1) {
1631 push_signature(&req->outbuf);
1632 /* perhaps grab OS version here?? */
1635 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1636 SSVAL(req->outbuf,smb_vwv2,1);
1639 /* register the name and uid as being validated, so further connections
1640 to a uid can get through without a password, on the same VC */
1642 if (lp_security() == SEC_SHARE) {
1643 sess_vuid = UID_FIELD_INVALID;
1644 TALLOC_FREE(session_info);
1646 /* Ignore the initial vuid. */
1647 sess_vuid = register_initial_vuid(sconn);
1648 if (sess_vuid == UID_FIELD_INVALID) {
1649 data_blob_free(&nt_resp);
1650 data_blob_free(&lm_resp);
1651 reply_nterror(req, nt_status_squash(
1652 NT_STATUS_LOGON_FAILURE));
1653 END_PROFILE(SMBsesssetupX);
1656 /* register_existing_vuid keeps the session_info */
1657 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1659 nt_resp.data ? nt_resp : lm_resp,
1661 if (sess_vuid == UID_FIELD_INVALID) {
1662 data_blob_free(&nt_resp);
1663 data_blob_free(&lm_resp);
1664 reply_nterror(req, nt_status_squash(
1665 NT_STATUS_LOGON_FAILURE));
1666 END_PROFILE(SMBsesssetupX);
1670 /* current_user_info is changed on new vuid */
1671 reload_services(sconn->msg_ctx, sconn->sock, True);
1674 data_blob_free(&nt_resp);
1675 data_blob_free(&lm_resp);
1677 SSVAL(req->outbuf,smb_uid,sess_vuid);
1678 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1679 req->vuid = sess_vuid;
1681 if (!sconn->smb1.sessions.done_sesssetup) {
1682 sconn->smb1.sessions.max_send =
1683 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1685 sconn->smb1.sessions.done_sesssetup = true;
1687 END_PROFILE(SMBsesssetupX);