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 "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.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, conn_snum_used, 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);
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, conn_snum_used, 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 gensec_security **gensec_security,
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 = gensec_session_info(*gensec_security,
438 reply_outbuf(req, 4, 0);
440 SSVAL(req->outbuf, smb_uid, vuid);
442 if (NT_STATUS_IS_OK(nt_status)) {
443 DATA_BLOB nullblob = data_blob_null;
445 if (!is_partial_auth_vuid(sconn, vuid)) {
446 nt_status = NT_STATUS_LOGON_FAILURE;
450 /* register_existing_vuid keeps the server info */
451 if (register_existing_vuid(sconn, vuid,
452 session_info, nullblob) !=
454 /* The problem is, *gensec_security 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, conn_snum_used, 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(*gensec_security);
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 gensec_security **gensec_security)
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(*gensec_security);
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_generic_prepare(NULL, 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 gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY);
637 gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
639 status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP);
640 if (!NT_STATUS_IS_OK(status)) {
641 /* Kill the intermediate vuid */
642 invalidate_vuid(sconn, vuid);
643 reply_nterror(req, nt_status_squash(status));
647 status = gensec_update(*gensec_security, talloc_tos(),
648 NULL, secblob, &chal);
650 data_blob_free(&secblob);
652 reply_spnego_ntlmssp(req, vuid, gensec_security,
653 &chal, status, OID_NTLMSSP, true);
655 data_blob_free(&chal);
657 /* already replied */
661 /****************************************************************************
662 Reply to a session setup spnego auth packet.
663 ****************************************************************************/
665 static void reply_spnego_auth(struct smb_request *req,
668 struct gensec_security **gensec_security)
670 DATA_BLOB auth = data_blob_null;
671 DATA_BLOB auth_reply = data_blob_null;
672 DATA_BLOB secblob = data_blob_null;
673 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
674 struct smbd_server_connection *sconn = req->sconn;
676 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
678 file_save("auth.dat", blob1.data, blob1.length);
680 /* Kill the intermediate vuid */
681 invalidate_vuid(sconn, vuid);
683 reply_nterror(req, nt_status_squash(
684 NT_STATUS_LOGON_FAILURE));
688 if (auth.data[0] == ASN1_APPLICATION(0)) {
689 /* Might be a second negTokenTarg packet */
690 char *kerb_mech = NULL;
692 status = parse_spnego_mechanisms(talloc_tos(),
693 auth, &secblob, &kerb_mech);
695 if (!NT_STATUS_IS_OK(status)) {
696 /* Kill the intermediate vuid */
697 invalidate_vuid(sconn, vuid);
698 reply_nterror(req, nt_status_squash(status));
702 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
703 (unsigned long)secblob.length));
705 if (kerb_mech && ((lp_security()==SEC_ADS) ||
706 USE_KERBEROS_KEYTAB)) {
707 bool destroy_vuid = True;
708 reply_spnego_kerberos(req, &secblob, kerb_mech,
709 vuid, &destroy_vuid);
710 data_blob_free(&secblob);
711 data_blob_free(&auth);
713 /* Kill the intermediate vuid */
714 invalidate_vuid(sconn, vuid);
716 TALLOC_FREE(kerb_mech);
720 /* Can't blunder into NTLMSSP auth if we have
724 /* Kill the intermediate vuid */
725 invalidate_vuid(sconn, vuid);
726 DEBUG(3,("reply_spnego_auth: network "
727 "misconfiguration, client sent us a "
728 "krb5 ticket and kerberos security "
730 reply_nterror(req, nt_status_squash(
731 NT_STATUS_LOGON_FAILURE));
732 TALLOC_FREE(kerb_mech);
736 /* If we get here it wasn't a negTokenTarg auth packet. */
737 data_blob_free(&secblob);
739 if (!*gensec_security) {
740 status = auth_generic_prepare(NULL, sconn->remote_address,
742 if (!NT_STATUS_IS_OK(status)) {
743 /* Kill the intermediate vuid */
744 invalidate_vuid(sconn, vuid);
745 reply_nterror(req, nt_status_squash(status));
749 gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY);
750 gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
752 status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP);
753 if (!NT_STATUS_IS_OK(status)) {
754 /* Kill the intermediate vuid */
755 invalidate_vuid(sconn, vuid);
756 reply_nterror(req, nt_status_squash(status));
761 status = gensec_update(*gensec_security, talloc_tos(),
762 NULL, auth, &auth_reply);
764 data_blob_free(&auth);
766 /* Don't send the mechid as we've already sent this (RFC4178). */
768 reply_spnego_ntlmssp(req, vuid,
770 &auth_reply, status, NULL, true);
772 data_blob_free(&auth_reply);
774 /* and tell smbd that we have already replied to this packet */
778 /****************************************************************************
779 Delete an entry on the list.
780 ****************************************************************************/
782 static void delete_partial_auth(struct smbd_server_connection *sconn,
783 struct pending_auth_data *pad)
788 DLIST_REMOVE(sconn->smb1.pd_list, pad);
789 data_blob_free(&pad->partial_data);
793 /****************************************************************************
794 Search for a partial SPNEGO auth fragment matching an smbpid.
795 ****************************************************************************/
797 static struct pending_auth_data *get_pending_auth_data(
798 struct smbd_server_connection *sconn,
801 struct pending_auth_data *pad;
803 * NOTE: using the smbpid here is completely wrong...
805 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
807 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
808 if (pad->smbpid == smbpid) {
815 /****************************************************************************
816 Check the size of an SPNEGO blob. If we need more return
817 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
818 the blob to be more than 64k.
819 ****************************************************************************/
821 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
822 uint16 smbpid, uint16 vuid,
825 struct pending_auth_data *pad = NULL;
827 size_t needed_len = 0;
829 pad = get_pending_auth_data(sconn, smbpid);
831 /* Ensure we have some data. */
832 if (pblob->length == 0) {
833 /* Caller can cope. */
834 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
835 delete_partial_auth(sconn, pad);
839 /* Were we waiting for more data ? */
842 size_t copy_len = MIN(65536, pblob->length);
844 /* Integer wrap paranoia.... */
846 if (pad->partial_data.length + copy_len <
847 pad->partial_data.length ||
848 pad->partial_data.length + copy_len < copy_len) {
850 DEBUG(2,("check_spnego_blob_complete: integer wrap "
851 "pad->partial_data.length = %u, "
853 (unsigned int)pad->partial_data.length,
854 (unsigned int)copy_len ));
856 delete_partial_auth(sconn, pad);
857 return NT_STATUS_INVALID_PARAMETER;
860 DEBUG(10,("check_spnego_blob_complete: "
861 "pad->partial_data.length = %u, "
862 "pad->needed_len = %u, "
864 "pblob->length = %u,\n",
865 (unsigned int)pad->partial_data.length,
866 (unsigned int)pad->needed_len,
867 (unsigned int)copy_len,
868 (unsigned int)pblob->length ));
870 tmp_blob = data_blob(NULL,
871 pad->partial_data.length + copy_len);
873 /* Concatenate the two (up to copy_len) bytes. */
874 memcpy(tmp_blob.data,
875 pad->partial_data.data,
876 pad->partial_data.length);
877 memcpy(tmp_blob.data + pad->partial_data.length,
881 /* Replace the partial data. */
882 data_blob_free(&pad->partial_data);
883 pad->partial_data = tmp_blob;
884 ZERO_STRUCT(tmp_blob);
887 if (pblob->length >= pad->needed_len) {
888 /* Yes, replace pblob. */
889 data_blob_free(pblob);
890 *pblob = pad->partial_data;
891 ZERO_STRUCT(pad->partial_data);
892 delete_partial_auth(sconn, pad);
896 /* Still need more data. */
897 pad->needed_len -= copy_len;
898 return NT_STATUS_MORE_PROCESSING_REQUIRED;
901 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
902 (pblob->data[0] != ASN1_CONTEXT(1))) {
903 /* Not something we can determine the
909 /* This is a new SPNEGO sessionsetup - see if
910 * the data given in this blob is enough.
913 data = asn1_init(NULL);
915 return NT_STATUS_NO_MEMORY;
918 asn1_load(data, *pblob);
919 if (asn1_start_tag(data, pblob->data[0])) {
920 /* asn1_start_tag checks if the given
921 length of the blob is enough to complete
922 the tag. If it returns true we know
923 there is nothing to do - the blob is
929 if (data->nesting == NULL) {
930 /* Incorrect tag, allocation failed,
931 or reading the tag length failed.
932 Let the caller catch. */
937 /* Here we know asn1_start_tag() has set data->has_error to true.
938 asn1_tag_remaining() will have failed due to the given blob
939 being too short. We need to work out how short. */
941 /* Integer wrap paranoia.... */
943 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
944 data->nesting->taglen + data->nesting->start < data->nesting->start) {
946 DEBUG(2,("check_spnego_blob_complete: integer wrap "
947 "data.nesting->taglen = %u, "
948 "data.nesting->start = %u\n",
949 (unsigned int)data->nesting->taglen,
950 (unsigned int)data->nesting->start ));
953 return NT_STATUS_INVALID_PARAMETER;
956 /* Total length of the needed asn1 is the tag length
957 * plus the current offset. */
959 needed_len = data->nesting->taglen + data->nesting->start;
962 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
963 "pblob->length = %u\n",
964 (unsigned int)needed_len,
965 (unsigned int)pblob->length ));
967 if (needed_len <= pblob->length) {
968 /* Nothing to do - blob is complete. */
969 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
970 above should have caught this !!! */
971 DEBUG(0,("check_spnego_blob_complete: logic "
972 "error (needed_len = %u, "
973 "pblob->length = %u).\n",
974 (unsigned int)needed_len,
975 (unsigned int)pblob->length ));
979 /* Refuse the blob if it's bigger than 64k. */
980 if (needed_len > 65536) {
981 DEBUG(2,("check_spnego_blob_complete: needed_len "
983 (unsigned int)needed_len ));
984 return NT_STATUS_INVALID_PARAMETER;
987 /* We must store this blob until complete. */
988 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
989 return NT_STATUS_NO_MEMORY;
991 pad->needed_len = needed_len - pblob->length;
992 pad->partial_data = data_blob(pblob->data, pblob->length);
993 if (pad->partial_data.data == NULL) {
995 return NT_STATUS_NO_MEMORY;
997 pad->smbpid = smbpid;
999 DLIST_ADD(sconn->smb1.pd_list, pad);
1001 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1004 /****************************************************************************
1005 Reply to a session setup command.
1006 conn POINTER CAN BE NULL HERE !
1007 ****************************************************************************/
1009 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1015 const char *native_os;
1016 const char *native_lanman;
1017 const char *primary_domain;
1019 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1020 enum remote_arch_types ra_type = get_remote_arch();
1021 int vuid = req->vuid;
1022 user_struct *vuser = NULL;
1023 NTSTATUS status = NT_STATUS_OK;
1024 uint16 smbpid = req->smbpid;
1025 struct smbd_server_connection *sconn = req->sconn;
1028 DEBUG(3,("Doing spnego session setup\n"));
1030 if (global_client_caps == 0) {
1031 global_client_caps = IVAL(req->vwv+10, 0);
1033 if (!(global_client_caps & CAP_STATUS32)) {
1034 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1041 if (data_blob_len == 0) {
1042 /* an invalid request */
1043 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1047 bufrem = smbreq_bufrem(req, p);
1048 /* pull the spnego blob */
1049 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1052 file_save("negotiate.dat", blob1.data, blob1.length);
1055 p2 = (const char *)req->buf + blob1.length;
1057 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1059 native_os = tmp ? tmp : "";
1061 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1063 native_lanman = tmp ? tmp : "";
1065 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1067 primary_domain = tmp ? tmp : "";
1069 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1070 native_os, native_lanman, primary_domain));
1072 if ( ra_type == RA_WIN2K ) {
1073 /* Vista sets neither the OS or lanman strings */
1075 if ( !strlen(native_os) && !strlen(native_lanman) )
1076 set_remote_arch(RA_VISTA);
1078 /* Windows 2003 doesn't set the native lanman string,
1079 but does set primary domain which is a bug I think */
1081 if ( !strlen(native_lanman) ) {
1082 ra_lanman_string( primary_domain );
1084 ra_lanman_string( native_lanman );
1086 } else if ( ra_type == RA_VISTA ) {
1087 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1088 set_remote_arch(RA_OSX);
1092 /* Did we get a valid vuid ? */
1093 if (!is_partial_auth_vuid(sconn, vuid)) {
1094 /* No, then try and see if this is an intermediate sessionsetup
1095 * for a large SPNEGO packet. */
1096 struct pending_auth_data *pad;
1097 pad = get_pending_auth_data(sconn, smbpid);
1099 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1100 "pending vuid %u\n",
1101 (unsigned int)pad->vuid ));
1106 /* Do we have a valid vuid now ? */
1107 if (!is_partial_auth_vuid(sconn, vuid)) {
1108 /* No, start a new authentication setup. */
1109 vuid = register_initial_vuid(sconn);
1110 if (vuid == UID_FIELD_INVALID) {
1111 data_blob_free(&blob1);
1112 reply_nterror(req, nt_status_squash(
1113 NT_STATUS_INVALID_PARAMETER));
1118 vuser = get_partial_auth_user_struct(sconn, vuid);
1119 /* This MUST be valid. */
1121 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1124 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1125 * sessionsetup requests as the Windows limit on the security blob
1126 * field is 4k. Bug #4400. JRA.
1129 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1130 if (!NT_STATUS_IS_OK(status)) {
1131 if (!NT_STATUS_EQUAL(status,
1132 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1133 /* Real error - kill the intermediate vuid */
1134 invalidate_vuid(sconn, vuid);
1136 data_blob_free(&blob1);
1137 reply_nterror(req, nt_status_squash(status));
1141 if (!vuser->gensec_security) {
1142 status = auth_generic_prepare(vuser, sconn->remote_address,
1143 &vuser->gensec_security);
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));
1152 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
1153 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
1155 if (sconn->use_gensec_hook) {
1156 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
1158 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_NTLMSSP);
1160 if (!NT_STATUS_IS_OK(status)) {
1161 /* Kill the intermediate vuid */
1162 invalidate_vuid(sconn, vuid);
1163 data_blob_free(&blob1);
1164 reply_nterror(req, nt_status_squash(status));
1169 status = gensec_update(vuser->gensec_security,
1173 data_blob_free(&blob1);
1175 reply_spnego_ntlmssp(req, vuid,
1176 &vuser->gensec_security,
1177 &chal, status, NULL, false);
1178 data_blob_free(&chal);
1182 /****************************************************************************
1183 On new VC == 0, shutdown *all* old connections and users.
1184 It seems that only NT4.x does this. At W2K and above (XP etc.).
1185 a new session setup with VC==0 is ignored.
1186 ****************************************************************************/
1188 struct shutdown_state {
1190 struct messaging_context *msg_ctx;
1193 static int shutdown_other_smbds(const struct connections_key *key,
1194 const struct connections_data *crec,
1197 struct shutdown_state *state = (struct shutdown_state *)private_data;
1199 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1200 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1202 if (!process_exists(crec->pid)) {
1203 DEBUG(10, ("process does not exist\n"));
1207 if (procid_is_me(&crec->pid)) {
1208 DEBUG(10, ("It's me\n"));
1212 if (strcmp(state->ip, crec->addr) != 0) {
1213 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1217 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1218 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1221 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1226 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1228 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1229 "compatible we would close all old resources.\n"));
1232 invalidate_all_vuids();
1234 if (lp_reset_on_zero_vc()) {
1236 struct shutdown_state state;
1238 addr = tsocket_address_inet_addr_string(
1239 sconn->remote_address, talloc_tos());
1244 state.msg_ctx = sconn->msg_ctx;
1245 connections_forall_read(shutdown_other_smbds, &state);
1250 /****************************************************************************
1251 Reply to a session setup command.
1252 ****************************************************************************/
1254 void reply_sesssetup_and_X(struct smb_request *req)
1260 DATA_BLOB plaintext_password;
1263 fstring sub_user; /* Sanitised username for substituion */
1265 const char *native_os;
1266 const char *native_lanman;
1267 const char *primary_domain;
1268 struct auth_usersupplied_info *user_info = NULL;
1269 struct auth_serversupplied_info *server_info = NULL;
1270 struct auth_session_info *session_info = NULL;
1271 uint16 smb_flag2 = req->flags2;
1274 struct smbd_server_connection *sconn = req->sconn;
1276 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1277 bool signing_allowed = false;
1278 bool signing_mandatory = false;
1280 START_PROFILE(SMBsesssetupX);
1282 ZERO_STRUCT(lm_resp);
1283 ZERO_STRUCT(nt_resp);
1284 ZERO_STRUCT(plaintext_password);
1286 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1288 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
1289 signing_allowed = true;
1291 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
1292 signing_mandatory = true;
1296 * We can call srv_set_signing_negotiated() each time.
1297 * It finds out when it needs to turn into a noop
1300 srv_set_signing_negotiated(req->sconn,
1304 /* a SPNEGO session setup has 12 command words, whereas a normal
1305 NT1 session setup has 13. See the cifs spec. */
1306 if (req->wct == 12 &&
1307 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1309 if (!sconn->smb1.negprot.spnego) {
1310 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1311 "at SPNEGO session setup when it was not "
1313 reply_nterror(req, nt_status_squash(
1314 NT_STATUS_LOGON_FAILURE));
1315 END_PROFILE(SMBsesssetupX);
1319 if (SVAL(req->vwv+4, 0) == 0) {
1320 setup_new_vc_session(req->sconn);
1323 reply_sesssetup_and_X_spnego(req);
1324 END_PROFILE(SMBsesssetupX);
1328 smb_bufsize = SVAL(req->vwv+2, 0);
1330 if (get_Protocol() < PROTOCOL_NT1) {
1331 uint16 passlen1 = SVAL(req->vwv+7, 0);
1333 /* Never do NT status codes with protocols before NT1 as we
1334 * don't get client caps. */
1335 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1337 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1338 reply_nterror(req, nt_status_squash(
1339 NT_STATUS_INVALID_PARAMETER));
1340 END_PROFILE(SMBsesssetupX);
1345 lm_resp = data_blob(req->buf, passlen1);
1347 plaintext_password = data_blob(req->buf, passlen1+1);
1348 /* Ensure null termination */
1349 plaintext_password.data[passlen1] = 0;
1352 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1353 req->buf + passlen1, STR_TERMINATE);
1354 user = tmp ? tmp : "";
1359 uint16 passlen1 = SVAL(req->vwv+7, 0);
1360 uint16 passlen2 = SVAL(req->vwv+8, 0);
1361 enum remote_arch_types ra_type = get_remote_arch();
1362 const uint8_t *p = req->buf;
1363 const uint8_t *save_p = req->buf;
1367 if(global_client_caps == 0) {
1368 global_client_caps = IVAL(req->vwv+11, 0);
1370 if (!(global_client_caps & CAP_STATUS32)) {
1371 remove_from_common_flags2(
1372 FLAGS2_32_BIT_ERROR_CODES);
1375 /* client_caps is used as final determination if
1376 * client is NT or Win95. This is needed to return
1377 * the correct error codes in some circumstances.
1380 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1381 ra_type == RA_WIN95) {
1382 if(!(global_client_caps & (CAP_NT_SMBS|
1384 set_remote_arch( RA_WIN95);
1390 /* both Win95 and WinNT stuff up the password
1391 * lengths for non-encrypting systems. Uggh.
1393 if passlen1==24 its a win95 system, and its setting
1394 the password length incorrectly. Luckily it still
1395 works with the default code because Win95 will null
1396 terminate the password anyway
1398 if passlen1>0 and passlen2>0 then maybe its a NT box
1399 and its setting passlen2 to some random value which
1400 really stuffs things up. we need to fix that one. */
1402 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1408 /* check for nasty tricks */
1409 if (passlen1 > MAX_PASS_LEN
1410 || passlen1 > smbreq_bufrem(req, p)) {
1411 reply_nterror(req, nt_status_squash(
1412 NT_STATUS_INVALID_PARAMETER));
1413 END_PROFILE(SMBsesssetupX);
1417 if (passlen2 > MAX_PASS_LEN
1418 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1419 reply_nterror(req, nt_status_squash(
1420 NT_STATUS_INVALID_PARAMETER));
1421 END_PROFILE(SMBsesssetupX);
1425 /* Save the lanman2 password and the NT md4 password. */
1427 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1432 lm_resp = data_blob(p, passlen1);
1433 nt_resp = data_blob(p+passlen1, passlen2);
1434 } else if (lp_security() != SEC_SHARE) {
1436 * In share level we should ignore any passwords, so
1437 * only read them if we're not.
1440 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1442 if (unic && (passlen2 == 0) && passlen1) {
1443 /* Only a ascii plaintext password was sent. */
1444 (void)srvstr_pull_talloc(talloc_tos(),
1450 STR_TERMINATE|STR_ASCII);
1452 (void)srvstr_pull_talloc(talloc_tos(),
1457 unic ? passlen2 : passlen1,
1461 reply_nterror(req, nt_status_squash(
1462 NT_STATUS_INVALID_PARAMETER));
1463 END_PROFILE(SMBsesssetupX);
1466 plaintext_password = data_blob(pass, strlen(pass)+1);
1469 p += passlen1 + passlen2;
1471 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1473 user = tmp ? tmp : "";
1475 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1477 domain = tmp ? tmp : "";
1479 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1481 native_os = tmp ? tmp : "";
1483 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1485 native_lanman = tmp ? tmp : "";
1487 /* not documented or decoded by Ethereal but there is one more
1488 * string in the extra bytes which is the same as the
1489 * PrimaryDomain when using extended security. Windows NT 4
1490 * and 2003 use this string to store the native lanman string.
1491 * Windows 9x does not include a string here at all so we have
1492 * to check if we have any extra bytes left */
1494 byte_count = SVAL(req->vwv+13, 0);
1495 if ( PTR_DIFF(p, save_p) < byte_count) {
1496 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1498 primary_domain = tmp ? tmp : "";
1500 primary_domain = talloc_strdup(talloc_tos(), "null");
1503 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1504 "PrimaryDomain=[%s]\n",
1505 domain, native_os, native_lanman, primary_domain));
1507 if ( ra_type == RA_WIN2K ) {
1508 if ( strlen(native_lanman) == 0 )
1509 ra_lanman_string( primary_domain );
1511 ra_lanman_string( native_lanman );
1516 if (SVAL(req->vwv+4, 0) == 0) {
1517 setup_new_vc_session(req->sconn);
1520 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1521 domain, user, get_remote_machine_name()));
1524 if (sconn->smb1.negprot.spnego) {
1526 /* This has to be here, because this is a perfectly
1527 * valid behaviour for guest logons :-( */
1529 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1530 "at 'normal' session setup after "
1531 "negotiating spnego.\n"));
1532 reply_nterror(req, nt_status_squash(
1533 NT_STATUS_LOGON_FAILURE));
1534 END_PROFILE(SMBsesssetupX);
1537 fstrcpy(sub_user, user);
1539 fstrcpy(sub_user, "");
1542 sub_set_smb_name(sub_user);
1544 reload_services(sconn, conn_snum_used, true);
1546 if (lp_security() == SEC_SHARE) {
1547 char *sub_user_mapped = NULL;
1548 /* In share level we should ignore any passwords */
1550 data_blob_free(&lm_resp);
1551 data_blob_free(&nt_resp);
1552 data_blob_clear_free(&plaintext_password);
1554 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1555 if (!sub_user_mapped) {
1556 reply_nterror(req, NT_STATUS_NO_MEMORY);
1557 END_PROFILE(SMBsesssetupX);
1560 fstrcpy(sub_user, sub_user_mapped);
1561 add_session_user(sconn, sub_user);
1562 add_session_workgroup(sconn, domain);
1563 /* Then force it to null for the benfit of the code below */
1569 nt_status = check_guest_password(sconn->remote_address, &server_info);
1571 } else if (doencrypt) {
1572 struct auth_context *negprot_auth_context = NULL;
1573 negprot_auth_context = sconn->smb1.negprot.auth_context;
1574 if (!negprot_auth_context) {
1575 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1576 "session setup without negprot denied!\n"));
1577 reply_nterror(req, nt_status_squash(
1578 NT_STATUS_LOGON_FAILURE));
1579 END_PROFILE(SMBsesssetupX);
1582 nt_status = make_user_info_for_reply_enc(&user_info, user,
1584 sconn->remote_address,
1586 if (NT_STATUS_IS_OK(nt_status)) {
1587 nt_status = negprot_auth_context->check_ntlm_password(
1588 negprot_auth_context,
1593 struct auth_context *plaintext_auth_context = NULL;
1595 nt_status = make_auth_context_subsystem(
1596 talloc_tos(), &plaintext_auth_context);
1598 if (NT_STATUS_IS_OK(nt_status)) {
1601 plaintext_auth_context->get_ntlm_challenge(
1602 plaintext_auth_context, chal);
1604 if (!make_user_info_for_reply(&user_info,
1606 sconn->remote_address,
1608 plaintext_password)) {
1609 nt_status = NT_STATUS_NO_MEMORY;
1612 if (NT_STATUS_IS_OK(nt_status)) {
1613 nt_status = plaintext_auth_context->check_ntlm_password(
1614 plaintext_auth_context,
1618 TALLOC_FREE(plaintext_auth_context);
1623 free_user_info(&user_info);
1625 if (!NT_STATUS_IS_OK(nt_status)) {
1626 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1630 if (!NT_STATUS_IS_OK(nt_status)) {
1631 data_blob_free(&nt_resp);
1632 data_blob_free(&lm_resp);
1633 data_blob_clear_free(&plaintext_password);
1634 reply_nterror(req, nt_status_squash(nt_status));
1635 END_PROFILE(SMBsesssetupX);
1639 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
1640 TALLOC_FREE(server_info);
1642 if (!NT_STATUS_IS_OK(nt_status)) {
1643 DEBUG(10, ("create_local_token failed: %s\n",
1644 nt_errstr(nt_status)));
1645 data_blob_free(&nt_resp);
1646 data_blob_free(&lm_resp);
1647 data_blob_clear_free(&plaintext_password);
1648 reply_nterror(req, nt_status_squash(nt_status));
1649 END_PROFILE(SMBsesssetupX);
1653 data_blob_clear_free(&plaintext_password);
1655 /* it's ok - setup a reply */
1656 reply_outbuf(req, 3, 0);
1657 if (get_Protocol() >= PROTOCOL_NT1) {
1658 push_signature(&req->outbuf);
1659 /* perhaps grab OS version here?? */
1662 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1663 SSVAL(req->outbuf,smb_vwv2,1);
1666 /* register the name and uid as being validated, so further connections
1667 to a uid can get through without a password, on the same VC */
1669 if (lp_security() == SEC_SHARE) {
1670 sess_vuid = UID_FIELD_INVALID;
1671 TALLOC_FREE(session_info);
1673 /* Ignore the initial vuid. */
1674 sess_vuid = register_initial_vuid(sconn);
1675 if (sess_vuid == UID_FIELD_INVALID) {
1676 data_blob_free(&nt_resp);
1677 data_blob_free(&lm_resp);
1678 reply_nterror(req, nt_status_squash(
1679 NT_STATUS_LOGON_FAILURE));
1680 END_PROFILE(SMBsesssetupX);
1683 /* register_existing_vuid keeps the session_info */
1684 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1686 nt_resp.data ? nt_resp : lm_resp);
1687 if (sess_vuid == UID_FIELD_INVALID) {
1688 data_blob_free(&nt_resp);
1689 data_blob_free(&lm_resp);
1690 reply_nterror(req, nt_status_squash(
1691 NT_STATUS_LOGON_FAILURE));
1692 END_PROFILE(SMBsesssetupX);
1696 /* current_user_info is changed on new vuid */
1697 reload_services(sconn, conn_snum_used, true);
1700 data_blob_free(&nt_resp);
1701 data_blob_free(&lm_resp);
1703 SSVAL(req->outbuf,smb_uid,sess_vuid);
1704 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1705 req->vuid = sess_vuid;
1707 if (!sconn->smb1.sessions.done_sesssetup) {
1708 sconn->smb1.sessions.max_send =
1709 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1711 sconn->smb1.sessions.done_sesssetup = true;
1713 END_PROFILE(SMBsesssetupX);