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);
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) !=
453 /* The problem is, *auth_ntlmssp_state points
454 * into the vuser this will have
455 * talloc_free()'ed in
456 * register_existing_vuid() */
457 do_invalidate = false;
458 nt_status = NT_STATUS_LOGON_FAILURE;
462 /* current_user_info is changed on new vuid */
463 reload_services(sconn->msg_ctx, sconn->sock, True);
465 SSVAL(req->outbuf, smb_vwv3, 0);
467 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
468 SSVAL(req->outbuf,smb_vwv2,1);
475 response = spnego_gen_auth_response(talloc_tos(),
479 response = *ntlmssp_blob;
482 reply_sesssetup_blob(req, response, nt_status);
484 data_blob_free(&response);
487 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
488 and the other end, that we are not finished yet. */
490 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
491 /* NB. This is *NOT* an error case. JRA */
493 TALLOC_FREE(*auth_ntlmssp_state);
494 if (!NT_STATUS_IS_OK(nt_status)) {
495 /* Kill the intermediate vuid */
496 invalidate_vuid(sconn, vuid);
502 /****************************************************************************
503 Is this a krb5 mechanism ?
504 ****************************************************************************/
506 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
508 DATA_BLOB *pblob_out,
511 char *OIDs[ASN1_MAX_OIDS];
513 NTSTATUS ret = NT_STATUS_OK;
515 *kerb_mechOID = NULL;
517 /* parse out the OIDs and the first sec blob */
518 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
520 return NT_STATUS_LOGON_FAILURE;
523 /* only look at the first OID for determining the mechToken --
524 according to RFC2478, we should choose the one we want
525 and renegotiate, but i smell a client bug here..
527 Problem observed when connecting to a member (samba box)
528 of an AD domain as a user in a Samba domain. Samba member
529 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
530 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
531 NTLMSSP mechtoken. --jerry */
534 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
535 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
536 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
537 if (*kerb_mechOID == NULL) {
538 ret = NT_STATUS_NO_MEMORY;
543 for (i=0;OIDs[i];i++) {
544 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
545 talloc_free(OIDs[i]);
550 /****************************************************************************
551 Fall back from krb5 to NTLMSSP.
552 ****************************************************************************/
554 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
559 reply_outbuf(req, 4, 0);
560 SSVAL(req->outbuf,smb_uid,vuid);
562 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
563 "but set to downgrade to NTLMSSP\n"));
565 response = spnego_gen_auth_response(talloc_tos(), NULL,
566 NT_STATUS_MORE_PROCESSING_REQUIRED,
568 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
569 data_blob_free(&response);
572 /****************************************************************************
573 Reply to a session setup spnego negotiate packet.
574 ****************************************************************************/
576 static void reply_spnego_negotiate(struct smb_request *req,
579 struct auth_ntlmssp_state **auth_ntlmssp_state)
583 char *kerb_mech = NULL;
585 struct smbd_server_connection *sconn = req->sconn;
587 status = parse_spnego_mechanisms(talloc_tos(),
588 blob1, &secblob, &kerb_mech);
589 if (!NT_STATUS_IS_OK(status)) {
590 /* Kill the intermediate vuid */
591 invalidate_vuid(sconn, vuid);
592 reply_nterror(req, nt_status_squash(status));
596 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
597 (unsigned long)secblob.length));
600 if (kerb_mech && ((lp_security()==SEC_ADS) ||
601 USE_KERBEROS_KEYTAB) ) {
602 bool destroy_vuid = True;
603 reply_spnego_kerberos(req, &secblob, kerb_mech,
604 vuid, &destroy_vuid);
605 data_blob_free(&secblob);
607 /* Kill the intermediate vuid */
608 invalidate_vuid(sconn, vuid);
610 TALLOC_FREE(kerb_mech);
615 TALLOC_FREE(*auth_ntlmssp_state);
618 data_blob_free(&secblob);
619 /* The mechtoken is a krb5 ticket, but
620 * we need to fall back to NTLM. */
621 reply_spnego_downgrade_to_ntlmssp(req, vuid);
622 TALLOC_FREE(kerb_mech);
626 status = auth_ntlmssp_prepare(sconn->remote_address,
628 if (!NT_STATUS_IS_OK(status)) {
629 /* Kill the intermediate vuid */
630 invalidate_vuid(sconn, vuid);
631 reply_nterror(req, nt_status_squash(status));
635 auth_ntlmssp_want_feature(*auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
637 status = auth_ntlmssp_start(*auth_ntlmssp_state);
638 if (!NT_STATUS_IS_OK(status)) {
639 /* Kill the intermediate vuid */
640 invalidate_vuid(sconn, vuid);
641 reply_nterror(req, nt_status_squash(status));
645 status = auth_ntlmssp_update(*auth_ntlmssp_state, talloc_tos(),
648 data_blob_free(&secblob);
650 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
651 &chal, status, OID_NTLMSSP, true);
653 data_blob_free(&chal);
655 /* already replied */
659 /****************************************************************************
660 Reply to a session setup spnego auth packet.
661 ****************************************************************************/
663 static void reply_spnego_auth(struct smb_request *req,
666 struct auth_ntlmssp_state **auth_ntlmssp_state)
668 DATA_BLOB auth = data_blob_null;
669 DATA_BLOB auth_reply = data_blob_null;
670 DATA_BLOB secblob = data_blob_null;
671 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
672 struct smbd_server_connection *sconn = req->sconn;
674 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
676 file_save("auth.dat", blob1.data, blob1.length);
678 /* Kill the intermediate vuid */
679 invalidate_vuid(sconn, vuid);
681 reply_nterror(req, nt_status_squash(
682 NT_STATUS_LOGON_FAILURE));
686 if (auth.data[0] == ASN1_APPLICATION(0)) {
687 /* Might be a second negTokenTarg packet */
688 char *kerb_mech = NULL;
690 status = parse_spnego_mechanisms(talloc_tos(),
691 auth, &secblob, &kerb_mech);
693 if (!NT_STATUS_IS_OK(status)) {
694 /* Kill the intermediate vuid */
695 invalidate_vuid(sconn, vuid);
696 reply_nterror(req, nt_status_squash(status));
700 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
701 (unsigned long)secblob.length));
703 if (kerb_mech && ((lp_security()==SEC_ADS) ||
704 USE_KERBEROS_KEYTAB)) {
705 bool destroy_vuid = True;
706 reply_spnego_kerberos(req, &secblob, kerb_mech,
707 vuid, &destroy_vuid);
708 data_blob_free(&secblob);
709 data_blob_free(&auth);
711 /* Kill the intermediate vuid */
712 invalidate_vuid(sconn, vuid);
714 TALLOC_FREE(kerb_mech);
718 /* Can't blunder into NTLMSSP auth if we have
722 /* Kill the intermediate vuid */
723 invalidate_vuid(sconn, vuid);
724 DEBUG(3,("reply_spnego_auth: network "
725 "misconfiguration, client sent us a "
726 "krb5 ticket and kerberos security "
728 reply_nterror(req, nt_status_squash(
729 NT_STATUS_LOGON_FAILURE));
730 TALLOC_FREE(kerb_mech);
734 /* If we get here it wasn't a negTokenTarg auth packet. */
735 data_blob_free(&secblob);
737 if (!*auth_ntlmssp_state) {
738 status = auth_ntlmssp_prepare(sconn->remote_address,
740 if (!NT_STATUS_IS_OK(status)) {
741 /* Kill the intermediate vuid */
742 invalidate_vuid(sconn, vuid);
743 reply_nterror(req, nt_status_squash(status));
747 auth_ntlmssp_want_feature(*auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
749 status = auth_ntlmssp_start(*auth_ntlmssp_state);
750 if (!NT_STATUS_IS_OK(status)) {
751 /* Kill the intermediate vuid */
752 invalidate_vuid(sconn, vuid);
753 reply_nterror(req, nt_status_squash(status));
758 status = auth_ntlmssp_update(*auth_ntlmssp_state, talloc_tos(),
761 data_blob_free(&auth);
763 /* Don't send the mechid as we've already sent this (RFC4178). */
765 reply_spnego_ntlmssp(req, vuid,
767 &auth_reply, status, NULL, true);
769 data_blob_free(&auth_reply);
771 /* and tell smbd that we have already replied to this packet */
775 /****************************************************************************
776 Delete an entry on the list.
777 ****************************************************************************/
779 static void delete_partial_auth(struct smbd_server_connection *sconn,
780 struct pending_auth_data *pad)
785 DLIST_REMOVE(sconn->smb1.pd_list, pad);
786 data_blob_free(&pad->partial_data);
790 /****************************************************************************
791 Search for a partial SPNEGO auth fragment matching an smbpid.
792 ****************************************************************************/
794 static struct pending_auth_data *get_pending_auth_data(
795 struct smbd_server_connection *sconn,
798 struct pending_auth_data *pad;
800 * NOTE: using the smbpid here is completely wrong...
802 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
804 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
805 if (pad->smbpid == smbpid) {
812 /****************************************************************************
813 Check the size of an SPNEGO blob. If we need more return
814 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
815 the blob to be more than 64k.
816 ****************************************************************************/
818 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
819 uint16 smbpid, uint16 vuid,
822 struct pending_auth_data *pad = NULL;
824 size_t needed_len = 0;
826 pad = get_pending_auth_data(sconn, smbpid);
828 /* Ensure we have some data. */
829 if (pblob->length == 0) {
830 /* Caller can cope. */
831 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
832 delete_partial_auth(sconn, pad);
836 /* Were we waiting for more data ? */
839 size_t copy_len = MIN(65536, pblob->length);
841 /* Integer wrap paranoia.... */
843 if (pad->partial_data.length + copy_len <
844 pad->partial_data.length ||
845 pad->partial_data.length + copy_len < copy_len) {
847 DEBUG(2,("check_spnego_blob_complete: integer wrap "
848 "pad->partial_data.length = %u, "
850 (unsigned int)pad->partial_data.length,
851 (unsigned int)copy_len ));
853 delete_partial_auth(sconn, pad);
854 return NT_STATUS_INVALID_PARAMETER;
857 DEBUG(10,("check_spnego_blob_complete: "
858 "pad->partial_data.length = %u, "
859 "pad->needed_len = %u, "
861 "pblob->length = %u,\n",
862 (unsigned int)pad->partial_data.length,
863 (unsigned int)pad->needed_len,
864 (unsigned int)copy_len,
865 (unsigned int)pblob->length ));
867 tmp_blob = data_blob(NULL,
868 pad->partial_data.length + copy_len);
870 /* Concatenate the two (up to copy_len) bytes. */
871 memcpy(tmp_blob.data,
872 pad->partial_data.data,
873 pad->partial_data.length);
874 memcpy(tmp_blob.data + pad->partial_data.length,
878 /* Replace the partial data. */
879 data_blob_free(&pad->partial_data);
880 pad->partial_data = tmp_blob;
881 ZERO_STRUCT(tmp_blob);
884 if (pblob->length >= pad->needed_len) {
885 /* Yes, replace pblob. */
886 data_blob_free(pblob);
887 *pblob = pad->partial_data;
888 ZERO_STRUCT(pad->partial_data);
889 delete_partial_auth(sconn, pad);
893 /* Still need more data. */
894 pad->needed_len -= copy_len;
895 return NT_STATUS_MORE_PROCESSING_REQUIRED;
898 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
899 (pblob->data[0] != ASN1_CONTEXT(1))) {
900 /* Not something we can determine the
906 /* This is a new SPNEGO sessionsetup - see if
907 * the data given in this blob is enough.
910 data = asn1_init(NULL);
912 return NT_STATUS_NO_MEMORY;
915 asn1_load(data, *pblob);
916 if (asn1_start_tag(data, pblob->data[0])) {
917 /* asn1_start_tag checks if the given
918 length of the blob is enough to complete
919 the tag. If it returns true we know
920 there is nothing to do - the blob is
926 if (data->nesting == NULL) {
927 /* Incorrect tag, allocation failed,
928 or reading the tag length failed.
929 Let the caller catch. */
934 /* Here we know asn1_start_tag() has set data->has_error to true.
935 asn1_tag_remaining() will have failed due to the given blob
936 being too short. We need to work out how short. */
938 /* Integer wrap paranoia.... */
940 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
941 data->nesting->taglen + data->nesting->start < data->nesting->start) {
943 DEBUG(2,("check_spnego_blob_complete: integer wrap "
944 "data.nesting->taglen = %u, "
945 "data.nesting->start = %u\n",
946 (unsigned int)data->nesting->taglen,
947 (unsigned int)data->nesting->start ));
950 return NT_STATUS_INVALID_PARAMETER;
953 /* Total length of the needed asn1 is the tag length
954 * plus the current offset. */
956 needed_len = data->nesting->taglen + data->nesting->start;
959 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
960 "pblob->length = %u\n",
961 (unsigned int)needed_len,
962 (unsigned int)pblob->length ));
964 if (needed_len <= pblob->length) {
965 /* Nothing to do - blob is complete. */
966 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
967 above should have caught this !!! */
968 DEBUG(0,("check_spnego_blob_complete: logic "
969 "error (needed_len = %u, "
970 "pblob->length = %u).\n",
971 (unsigned int)needed_len,
972 (unsigned int)pblob->length ));
976 /* Refuse the blob if it's bigger than 64k. */
977 if (needed_len > 65536) {
978 DEBUG(2,("check_spnego_blob_complete: needed_len "
980 (unsigned int)needed_len ));
981 return NT_STATUS_INVALID_PARAMETER;
984 /* We must store this blob until complete. */
985 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
986 return NT_STATUS_NO_MEMORY;
988 pad->needed_len = needed_len - pblob->length;
989 pad->partial_data = data_blob(pblob->data, pblob->length);
990 if (pad->partial_data.data == NULL) {
992 return NT_STATUS_NO_MEMORY;
994 pad->smbpid = smbpid;
996 DLIST_ADD(sconn->smb1.pd_list, pad);
998 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1001 /****************************************************************************
1002 Reply to a session setup command.
1003 conn POINTER CAN BE NULL HERE !
1004 ****************************************************************************/
1006 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1012 const char *native_os;
1013 const char *native_lanman;
1014 const char *primary_domain;
1016 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1017 enum remote_arch_types ra_type = get_remote_arch();
1018 int vuid = req->vuid;
1019 user_struct *vuser = NULL;
1020 NTSTATUS status = NT_STATUS_OK;
1021 uint16 smbpid = req->smbpid;
1022 struct smbd_server_connection *sconn = req->sconn;
1024 DEBUG(3,("Doing spnego session setup\n"));
1026 if (global_client_caps == 0) {
1027 global_client_caps = IVAL(req->vwv+10, 0);
1029 if (!(global_client_caps & CAP_STATUS32)) {
1030 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1037 if (data_blob_len == 0) {
1038 /* an invalid request */
1039 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1043 bufrem = smbreq_bufrem(req, p);
1044 /* pull the spnego blob */
1045 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1048 file_save("negotiate.dat", blob1.data, blob1.length);
1051 p2 = (const char *)req->buf + blob1.length;
1053 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1055 native_os = tmp ? tmp : "";
1057 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1059 native_lanman = tmp ? tmp : "";
1061 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1063 primary_domain = tmp ? tmp : "";
1065 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1066 native_os, native_lanman, primary_domain));
1068 if ( ra_type == RA_WIN2K ) {
1069 /* Vista sets neither the OS or lanman strings */
1071 if ( !strlen(native_os) && !strlen(native_lanman) )
1072 set_remote_arch(RA_VISTA);
1074 /* Windows 2003 doesn't set the native lanman string,
1075 but does set primary domain which is a bug I think */
1077 if ( !strlen(native_lanman) ) {
1078 ra_lanman_string( primary_domain );
1080 ra_lanman_string( native_lanman );
1082 } else if ( ra_type == RA_VISTA ) {
1083 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1084 set_remote_arch(RA_OSX);
1088 /* Did we get a valid vuid ? */
1089 if (!is_partial_auth_vuid(sconn, vuid)) {
1090 /* No, then try and see if this is an intermediate sessionsetup
1091 * for a large SPNEGO packet. */
1092 struct pending_auth_data *pad;
1093 pad = get_pending_auth_data(sconn, smbpid);
1095 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1096 "pending vuid %u\n",
1097 (unsigned int)pad->vuid ));
1102 /* Do we have a valid vuid now ? */
1103 if (!is_partial_auth_vuid(sconn, vuid)) {
1104 /* No, start a new authentication setup. */
1105 vuid = register_initial_vuid(sconn);
1106 if (vuid == UID_FIELD_INVALID) {
1107 data_blob_free(&blob1);
1108 reply_nterror(req, nt_status_squash(
1109 NT_STATUS_INVALID_PARAMETER));
1114 vuser = get_partial_auth_user_struct(sconn, vuid);
1115 /* This MUST be valid. */
1117 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1120 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1121 * sessionsetup requests as the Windows limit on the security blob
1122 * field is 4k. Bug #4400. JRA.
1125 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 if (!NT_STATUS_EQUAL(status,
1128 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1129 /* Real error - kill the intermediate vuid */
1130 invalidate_vuid(sconn, vuid);
1132 data_blob_free(&blob1);
1133 reply_nterror(req, nt_status_squash(status));
1137 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1139 /* its a negTokenTarg packet */
1141 reply_spnego_negotiate(req, vuid, blob1,
1142 &vuser->auth_ntlmssp_state);
1143 data_blob_free(&blob1);
1147 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1149 /* its a auth packet */
1151 reply_spnego_auth(req, vuid, blob1,
1152 &vuser->auth_ntlmssp_state);
1153 data_blob_free(&blob1);
1157 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1160 if (!vuser->auth_ntlmssp_state) {
1161 status = auth_ntlmssp_prepare(sconn->remote_address,
1162 &vuser->auth_ntlmssp_state);
1163 if (!NT_STATUS_IS_OK(status)) {
1164 /* Kill the intermediate vuid */
1165 invalidate_vuid(sconn, vuid);
1166 data_blob_free(&blob1);
1167 reply_nterror(req, nt_status_squash(status));
1171 auth_ntlmssp_want_feature(vuser->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
1173 status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 /* Kill the intermediate vuid */
1176 invalidate_vuid(sconn, vuid);
1177 data_blob_free(&blob1);
1178 reply_nterror(req, nt_status_squash(status));
1183 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1187 data_blob_free(&blob1);
1189 reply_spnego_ntlmssp(req, vuid,
1190 &vuser->auth_ntlmssp_state,
1191 &chal, status, OID_NTLMSSP, false);
1192 data_blob_free(&chal);
1196 /* what sort of packet is this? */
1197 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1199 data_blob_free(&blob1);
1201 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1204 /****************************************************************************
1205 On new VC == 0, shutdown *all* old connections and users.
1206 It seems that only NT4.x does this. At W2K and above (XP etc.).
1207 a new session setup with VC==0 is ignored.
1208 ****************************************************************************/
1210 struct shutdown_state {
1212 struct messaging_context *msg_ctx;
1215 static int shutdown_other_smbds(const struct connections_key *key,
1216 const struct connections_data *crec,
1219 struct shutdown_state *state = (struct shutdown_state *)private_data;
1221 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1222 server_id_str(talloc_tos(), &crec->pid), crec->addr));
1224 if (!process_exists(crec->pid)) {
1225 DEBUG(10, ("process does not exist\n"));
1229 if (procid_is_me(&crec->pid)) {
1230 DEBUG(10, ("It's me\n"));
1234 if (strcmp(state->ip, crec->addr) != 0) {
1235 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1239 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1240 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1243 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1248 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1250 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1251 "compatible we would close all old resources.\n"));
1254 invalidate_all_vuids();
1256 if (lp_reset_on_zero_vc()) {
1258 struct shutdown_state state;
1260 addr = tsocket_address_inet_addr_string(
1261 sconn->remote_address, talloc_tos());
1266 state.msg_ctx = sconn->msg_ctx;
1267 connections_forall_read(shutdown_other_smbds, &state);
1272 /****************************************************************************
1273 Reply to a session setup command.
1274 ****************************************************************************/
1276 void reply_sesssetup_and_X(struct smb_request *req)
1282 DATA_BLOB plaintext_password;
1285 fstring sub_user; /* Sanitised username for substituion */
1287 const char *native_os;
1288 const char *native_lanman;
1289 const char *primary_domain;
1290 struct auth_usersupplied_info *user_info = NULL;
1291 struct auth_serversupplied_info *server_info = NULL;
1292 struct auth_session_info *session_info = NULL;
1293 uint16 smb_flag2 = req->flags2;
1296 struct smbd_server_connection *sconn = req->sconn;
1298 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1300 START_PROFILE(SMBsesssetupX);
1302 ZERO_STRUCT(lm_resp);
1303 ZERO_STRUCT(nt_resp);
1304 ZERO_STRUCT(plaintext_password);
1306 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1308 /* a SPNEGO session setup has 12 command words, whereas a normal
1309 NT1 session setup has 13. See the cifs spec. */
1310 if (req->wct == 12 &&
1311 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1313 if (!sconn->smb1.negprot.spnego) {
1314 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1315 "at SPNEGO session setup when it was not "
1317 reply_nterror(req, nt_status_squash(
1318 NT_STATUS_LOGON_FAILURE));
1319 END_PROFILE(SMBsesssetupX);
1323 if (SVAL(req->vwv+4, 0) == 0) {
1324 setup_new_vc_session(req->sconn);
1327 reply_sesssetup_and_X_spnego(req);
1328 END_PROFILE(SMBsesssetupX);
1332 smb_bufsize = SVAL(req->vwv+2, 0);
1334 if (get_Protocol() < PROTOCOL_NT1) {
1335 uint16 passlen1 = SVAL(req->vwv+7, 0);
1337 /* Never do NT status codes with protocols before NT1 as we
1338 * don't get client caps. */
1339 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1341 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1342 reply_nterror(req, nt_status_squash(
1343 NT_STATUS_INVALID_PARAMETER));
1344 END_PROFILE(SMBsesssetupX);
1349 lm_resp = data_blob(req->buf, passlen1);
1351 plaintext_password = data_blob(req->buf, passlen1+1);
1352 /* Ensure null termination */
1353 plaintext_password.data[passlen1] = 0;
1356 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1357 req->buf + passlen1, STR_TERMINATE);
1358 user = tmp ? tmp : "";
1363 uint16 passlen1 = SVAL(req->vwv+7, 0);
1364 uint16 passlen2 = SVAL(req->vwv+8, 0);
1365 enum remote_arch_types ra_type = get_remote_arch();
1366 const uint8_t *p = req->buf;
1367 const uint8_t *save_p = req->buf;
1371 if(global_client_caps == 0) {
1372 global_client_caps = IVAL(req->vwv+11, 0);
1374 if (!(global_client_caps & CAP_STATUS32)) {
1375 remove_from_common_flags2(
1376 FLAGS2_32_BIT_ERROR_CODES);
1379 /* client_caps is used as final determination if
1380 * client is NT or Win95. This is needed to return
1381 * the correct error codes in some circumstances.
1384 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1385 ra_type == RA_WIN95) {
1386 if(!(global_client_caps & (CAP_NT_SMBS|
1388 set_remote_arch( RA_WIN95);
1394 /* both Win95 and WinNT stuff up the password
1395 * lengths for non-encrypting systems. Uggh.
1397 if passlen1==24 its a win95 system, and its setting
1398 the password length incorrectly. Luckily it still
1399 works with the default code because Win95 will null
1400 terminate the password anyway
1402 if passlen1>0 and passlen2>0 then maybe its a NT box
1403 and its setting passlen2 to some random value which
1404 really stuffs things up. we need to fix that one. */
1406 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1412 /* check for nasty tricks */
1413 if (passlen1 > MAX_PASS_LEN
1414 || passlen1 > smbreq_bufrem(req, p)) {
1415 reply_nterror(req, nt_status_squash(
1416 NT_STATUS_INVALID_PARAMETER));
1417 END_PROFILE(SMBsesssetupX);
1421 if (passlen2 > MAX_PASS_LEN
1422 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1423 reply_nterror(req, nt_status_squash(
1424 NT_STATUS_INVALID_PARAMETER));
1425 END_PROFILE(SMBsesssetupX);
1429 /* Save the lanman2 password and the NT md4 password. */
1431 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1436 lm_resp = data_blob(p, passlen1);
1437 nt_resp = data_blob(p+passlen1, passlen2);
1438 } else if (lp_security() != SEC_SHARE) {
1440 * In share level we should ignore any passwords, so
1441 * only read them if we're not.
1444 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1446 if (unic && (passlen2 == 0) && passlen1) {
1447 /* Only a ascii plaintext password was sent. */
1448 (void)srvstr_pull_talloc(talloc_tos(),
1454 STR_TERMINATE|STR_ASCII);
1456 (void)srvstr_pull_talloc(talloc_tos(),
1461 unic ? passlen2 : passlen1,
1465 reply_nterror(req, nt_status_squash(
1466 NT_STATUS_INVALID_PARAMETER));
1467 END_PROFILE(SMBsesssetupX);
1470 plaintext_password = data_blob(pass, strlen(pass)+1);
1473 p += passlen1 + passlen2;
1475 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1477 user = tmp ? tmp : "";
1479 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1481 domain = tmp ? tmp : "";
1483 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1485 native_os = tmp ? tmp : "";
1487 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1489 native_lanman = tmp ? tmp : "";
1491 /* not documented or decoded by Ethereal but there is one more
1492 * string in the extra bytes which is the same as the
1493 * PrimaryDomain when using extended security. Windows NT 4
1494 * and 2003 use this string to store the native lanman string.
1495 * Windows 9x does not include a string here at all so we have
1496 * to check if we have any extra bytes left */
1498 byte_count = SVAL(req->vwv+13, 0);
1499 if ( PTR_DIFF(p, save_p) < byte_count) {
1500 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1502 primary_domain = tmp ? tmp : "";
1504 primary_domain = talloc_strdup(talloc_tos(), "null");
1507 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1508 "PrimaryDomain=[%s]\n",
1509 domain, native_os, native_lanman, primary_domain));
1511 if ( ra_type == RA_WIN2K ) {
1512 if ( strlen(native_lanman) == 0 )
1513 ra_lanman_string( primary_domain );
1515 ra_lanman_string( native_lanman );
1520 if (SVAL(req->vwv+4, 0) == 0) {
1521 setup_new_vc_session(req->sconn);
1524 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1525 domain, user, get_remote_machine_name()));
1528 if (sconn->smb1.negprot.spnego) {
1530 /* This has to be here, because this is a perfectly
1531 * valid behaviour for guest logons :-( */
1533 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1534 "at 'normal' session setup after "
1535 "negotiating spnego.\n"));
1536 reply_nterror(req, nt_status_squash(
1537 NT_STATUS_LOGON_FAILURE));
1538 END_PROFILE(SMBsesssetupX);
1541 fstrcpy(sub_user, user);
1543 fstrcpy(sub_user, lp_guestaccount());
1546 sub_set_smb_name(sub_user);
1548 reload_services(sconn->msg_ctx, sconn->sock, True);
1550 if (lp_security() == SEC_SHARE) {
1551 char *sub_user_mapped = NULL;
1552 /* In share level we should ignore any passwords */
1554 data_blob_free(&lm_resp);
1555 data_blob_free(&nt_resp);
1556 data_blob_clear_free(&plaintext_password);
1558 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1559 if (!sub_user_mapped) {
1560 reply_nterror(req, NT_STATUS_NO_MEMORY);
1561 END_PROFILE(SMBsesssetupX);
1564 fstrcpy(sub_user, sub_user_mapped);
1565 add_session_user(sconn, sub_user);
1566 add_session_workgroup(sconn, domain);
1567 /* Then force it to null for the benfit of the code below */
1573 nt_status = check_guest_password(sconn->remote_address, &server_info);
1575 } else if (doencrypt) {
1576 struct auth_context *negprot_auth_context = NULL;
1577 negprot_auth_context = sconn->smb1.negprot.auth_context;
1578 if (!negprot_auth_context) {
1579 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1580 "session setup without negprot denied!\n"));
1581 reply_nterror(req, nt_status_squash(
1582 NT_STATUS_LOGON_FAILURE));
1583 END_PROFILE(SMBsesssetupX);
1586 nt_status = make_user_info_for_reply_enc(&user_info, user,
1588 sconn->remote_address,
1590 if (NT_STATUS_IS_OK(nt_status)) {
1591 nt_status = negprot_auth_context->check_ntlm_password(
1592 negprot_auth_context,
1597 struct auth_context *plaintext_auth_context = NULL;
1599 nt_status = make_auth_context_subsystem(
1600 talloc_tos(), &plaintext_auth_context);
1602 if (NT_STATUS_IS_OK(nt_status)) {
1605 plaintext_auth_context->get_ntlm_challenge(
1606 plaintext_auth_context, chal);
1608 if (!make_user_info_for_reply(&user_info,
1610 sconn->remote_address,
1612 plaintext_password)) {
1613 nt_status = NT_STATUS_NO_MEMORY;
1616 if (NT_STATUS_IS_OK(nt_status)) {
1617 nt_status = plaintext_auth_context->check_ntlm_password(
1618 plaintext_auth_context,
1622 TALLOC_FREE(plaintext_auth_context);
1627 free_user_info(&user_info);
1629 if (!NT_STATUS_IS_OK(nt_status)) {
1630 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1634 if (!NT_STATUS_IS_OK(nt_status)) {
1635 data_blob_free(&nt_resp);
1636 data_blob_free(&lm_resp);
1637 data_blob_clear_free(&plaintext_password);
1638 reply_nterror(req, nt_status_squash(nt_status));
1639 END_PROFILE(SMBsesssetupX);
1643 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
1644 TALLOC_FREE(server_info);
1646 if (!NT_STATUS_IS_OK(nt_status)) {
1647 DEBUG(10, ("create_local_token failed: %s\n",
1648 nt_errstr(nt_status)));
1649 data_blob_free(&nt_resp);
1650 data_blob_free(&lm_resp);
1651 data_blob_clear_free(&plaintext_password);
1652 reply_nterror(req, nt_status_squash(nt_status));
1653 END_PROFILE(SMBsesssetupX);
1657 data_blob_clear_free(&plaintext_password);
1659 /* it's ok - setup a reply */
1660 reply_outbuf(req, 3, 0);
1661 if (get_Protocol() >= PROTOCOL_NT1) {
1662 push_signature(&req->outbuf);
1663 /* perhaps grab OS version here?? */
1666 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1667 SSVAL(req->outbuf,smb_vwv2,1);
1670 /* register the name and uid as being validated, so further connections
1671 to a uid can get through without a password, on the same VC */
1673 if (lp_security() == SEC_SHARE) {
1674 sess_vuid = UID_FIELD_INVALID;
1675 TALLOC_FREE(session_info);
1677 /* Ignore the initial vuid. */
1678 sess_vuid = register_initial_vuid(sconn);
1679 if (sess_vuid == UID_FIELD_INVALID) {
1680 data_blob_free(&nt_resp);
1681 data_blob_free(&lm_resp);
1682 reply_nterror(req, nt_status_squash(
1683 NT_STATUS_LOGON_FAILURE));
1684 END_PROFILE(SMBsesssetupX);
1687 /* register_existing_vuid keeps the session_info */
1688 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1690 nt_resp.data ? nt_resp : lm_resp);
1691 if (sess_vuid == UID_FIELD_INVALID) {
1692 data_blob_free(&nt_resp);
1693 data_blob_free(&lm_resp);
1694 reply_nterror(req, nt_status_squash(
1695 NT_STATUS_LOGON_FAILURE));
1696 END_PROFILE(SMBsesssetupX);
1700 /* current_user_info is changed on new vuid */
1701 reload_services(sconn->msg_ctx, sconn->sock, True);
1704 data_blob_free(&nt_resp);
1705 data_blob_free(&lm_resp);
1707 SSVAL(req->outbuf,smb_uid,sess_vuid);
1708 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1709 req->vuid = sess_vuid;
1711 if (!sconn->smb1.sessions.done_sesssetup) {
1712 sconn->smb1.sessions.max_send =
1713 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1715 sconn->smb1.sessions.done_sesssetup = true;
1717 END_PROFILE(SMBsesssetupX);