2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "smbd/smbd.h"
27 #include "smbd/globals.h"
28 #include "../libcli/auth/spnego.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "ntlmssp_wrap.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
36 #include "smbprofile.h"
38 /* For split krb5 SPNEGO blobs. */
39 struct pending_auth_data {
40 struct pending_auth_data *prev, *next;
41 uint16 vuid; /* Tag for this entry. */
42 uint16 smbpid; /* Alternate tag for this entry. */
44 DATA_BLOB partial_data;
48 on a logon error possibly map the error to success if "map to guest"
51 NTSTATUS do_map_to_guest(NTSTATUS status,
52 struct auth_serversupplied_info **server_info,
53 const char *user, const char *domain)
55 user = user ? user : "";
56 domain = domain ? domain : "";
58 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
59 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
60 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
61 DEBUG(3,("No such user %s [%s] - using guest account\n",
63 status = make_server_info_guest(NULL, server_info);
67 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
68 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
69 DEBUG(3,("Registered username %s for guest access\n",
71 status = make_server_info_guest(NULL, server_info);
78 /****************************************************************************
79 Add the standard 'Samba' signature to the end of the session setup.
80 ****************************************************************************/
82 static int push_signature(uint8 **outbuf)
89 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
91 if (tmp == -1) return -1;
94 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
95 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
99 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
102 if (tmp == -1) return -1;
105 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
107 if (tmp == -1) return -1;
113 /****************************************************************************
114 Send a security blob via a session setup reply.
115 ****************************************************************************/
117 static void reply_sesssetup_blob(struct smb_request *req,
121 if (!NT_STATUS_IS_OK(nt_status) &&
122 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
123 reply_nterror(req, nt_status_squash(nt_status));
127 nt_status = nt_status_squash(nt_status);
128 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
129 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
130 SSVAL(req->outbuf, smb_vwv3, blob.length);
132 if ((message_push_blob(&req->outbuf, blob) == -1)
133 || (push_signature(&req->outbuf) == -1)) {
134 reply_nterror(req, NT_STATUS_NO_MEMORY);
138 /****************************************************************************
139 Do a 'guest' logon, getting back the
140 ****************************************************************************/
142 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
144 struct auth_context *auth_context;
145 struct auth_usersupplied_info *user_info = NULL;
148 static unsigned char chal[8] = { 0, };
150 DEBUG(3,("Got anonymous request\n"));
152 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
153 if (!NT_STATUS_IS_OK(nt_status)) {
157 if (!make_user_info_guest(&user_info)) {
158 TALLOC_FREE(auth_context);
159 return NT_STATUS_NO_MEMORY;
162 nt_status = auth_context->check_ntlm_password(auth_context,
165 TALLOC_FREE(auth_context);
166 free_user_info(&user_info);
174 /* Experiment that failed. See "only happens with a KDC" comment below. */
175 /****************************************************************************
176 Cerate a clock skew error blob for a Windows client.
177 ****************************************************************************/
179 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
181 krb5_context context = NULL;
182 krb5_error_code kerr = 0;
184 krb5_principal host_princ = NULL;
185 char *host_princ_s = NULL;
188 *pblob_out = data_blob_null;
190 initialize_krb5_error_table();
191 kerr = krb5_init_context(&context);
195 /* Create server principal. */
196 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
200 strlower_m(host_princ_s);
202 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
204 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
205 "for name %s: Error %s\n",
206 host_princ_s, error_message(kerr) ));
210 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
213 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
214 "failed: Error %s\n",
215 error_message(kerr) ));
219 *pblob_out = data_blob(reply.data, reply.length);
220 kerberos_free_data_contents(context,&reply);
226 SAFE_FREE(host_princ_s);
229 krb5_free_principal(context, host_princ);
231 krb5_free_context(context);
236 /****************************************************************************
237 Reply to a session setup spnego negotiate packet for kerberos.
238 ****************************************************************************/
240 static void reply_spnego_kerberos(struct smb_request *req,
244 bool *p_invalidate_vuid)
249 int sess_vuid = req->vuid;
250 NTSTATUS ret = NT_STATUS_OK;
251 DATA_BLOB ap_rep, ap_rep_wrapped, response;
252 struct auth_serversupplied_info *session_info = NULL;
253 DATA_BLOB session_key = data_blob_null;
255 DATA_BLOB nullblob = data_blob_null;
256 bool map_domainuser_to_guest = False;
257 bool username_was_mapped;
258 struct PAC_LOGON_INFO *logon_info = NULL;
259 struct smbd_server_connection *sconn = req->sconn;
267 ZERO_STRUCT(ap_rep_wrapped);
268 ZERO_STRUCT(response);
270 /* Normally we will always invalidate the intermediate vuid. */
271 *p_invalidate_vuid = True;
273 mem_ctx = talloc_init("reply_spnego_kerberos");
274 if (mem_ctx == NULL) {
275 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
279 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
280 talloc_destroy(mem_ctx);
281 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
285 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
286 &principal, &logon_info, &ap_rep,
289 data_blob_free(&ticket);
291 if (!NT_STATUS_IS_OK(ret)) {
293 /* Experiment that failed.
294 * See "only happens with a KDC" comment below. */
296 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
299 * Windows in this case returns
300 * NT_STATUS_MORE_PROCESSING_REQUIRED
301 * with a negTokenTarg blob containing an krb5_error
302 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
303 * The client then fixes its clock and continues rather
304 * than giving an error. JRA.
305 * -- Looks like this only happens with a KDC. JRA.
308 bool ok = make_krb5_skew_error(&ap_rep);
310 talloc_destroy(mem_ctx);
311 return ERROR_NT(nt_status_squash(
312 NT_STATUS_LOGON_FAILURE));
314 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
316 response = spnego_gen_auth_response(&ap_rep_wrapped,
317 ret, OID_KERBEROS5_OLD);
318 reply_sesssetup_blob(conn, inbuf, outbuf, response,
319 NT_STATUS_MORE_PROCESSING_REQUIRED);
322 * In this one case we don't invalidate the
323 * intermediate vuid as we're expecting the client
324 * to re-use it for the next sessionsetupX packet. JRA.
327 *p_invalidate_vuid = False;
329 data_blob_free(&ap_rep);
330 data_blob_free(&ap_rep_wrapped);
331 data_blob_free(&response);
332 talloc_destroy(mem_ctx);
333 return -1; /* already replied */
336 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
337 ret = NT_STATUS_LOGON_FAILURE;
340 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
342 talloc_destroy(mem_ctx);
343 reply_nterror(req, nt_status_squash(ret));
347 ret = get_user_from_kerberos_info(talloc_tos(),
348 sconn->client_id.name,
349 principal, logon_info,
350 &username_was_mapped,
351 &map_domainuser_to_guest,
353 &real_username, &pw);
354 if (!NT_STATUS_IS_OK(ret)) {
355 data_blob_free(&ap_rep);
356 data_blob_free(&session_key);
357 talloc_destroy(mem_ctx);
358 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
362 /* save the PAC data if we have it */
364 netsamlogon_cache_store(user, &logon_info->info3);
367 /* setup the string used by %U */
368 sub_set_smb_name(real_username);
370 /* reload services so that the new %U is taken into account */
371 reload_services(sconn->msg_ctx, sconn->sock, True);
373 ret = make_session_info_krb5(mem_ctx,
374 user, domain, real_username, pw,
375 logon_info, map_domainuser_to_guest,
379 data_blob_free(&session_key);
380 if (!NT_STATUS_IS_OK(ret)) {
381 DEBUG(1, ("make_server_info_krb5 failed!\n"));
382 data_blob_free(&ap_rep);
383 TALLOC_FREE(mem_ctx);
384 reply_nterror(req, nt_status_squash(ret));
388 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
389 sess_vuid = register_initial_vuid(sconn);
392 /* register_existing_vuid keeps the server info */
393 /* register_existing_vuid takes ownership of session_key on success,
394 * no need to free after this on success. A better interface would copy
397 sess_vuid = register_existing_vuid(sconn, sess_vuid,
398 session_info, nullblob, user);
400 reply_outbuf(req, 4, 0);
401 SSVAL(req->outbuf,smb_uid,sess_vuid);
403 if (sess_vuid == UID_FIELD_INVALID ) {
404 ret = NT_STATUS_LOGON_FAILURE;
406 /* current_user_info is changed on new vuid */
407 reload_services(sconn->msg_ctx, sconn->sock, True);
409 SSVAL(req->outbuf, smb_vwv3, 0);
411 if (session_info->guest) {
412 SSVAL(req->outbuf,smb_vwv2,1);
415 SSVAL(req->outbuf, smb_uid, sess_vuid);
417 /* Successful logon. Keep this vuid. */
418 *p_invalidate_vuid = False;
421 /* wrap that up in a nice GSS-API wrapping */
422 if (NT_STATUS_IS_OK(ret)) {
423 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
426 ap_rep_wrapped = data_blob_null;
428 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
430 reply_sesssetup_blob(req, response, ret);
432 data_blob_free(&ap_rep);
433 data_blob_free(&ap_rep_wrapped);
434 data_blob_free(&response);
435 TALLOC_FREE(mem_ctx);
440 /****************************************************************************
441 Send a session setup reply, wrapped in SPNEGO.
442 Get vuid and check first.
443 End the NTLMSSP exchange context if we are OK/complete fail
444 This should be split into two functions, one to handle each
445 leg of the NTLM auth steps.
446 ***************************************************************************/
448 static void reply_spnego_ntlmssp(struct smb_request *req,
450 struct auth_ntlmssp_state **auth_ntlmssp_state,
451 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
455 bool do_invalidate = true;
457 struct auth_serversupplied_info *session_info = NULL;
458 struct smbd_server_connection *sconn = req->sconn;
460 if (NT_STATUS_IS_OK(nt_status)) {
461 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
462 (*auth_ntlmssp_state), &session_info);
464 /* Note that this session_info won't have a session
465 * key. But for map to guest, that's exactly the right
466 * thing - we can't reasonably guess the key the
467 * client wants, as the password was wrong */
468 nt_status = do_map_to_guest(nt_status,
470 auth_ntlmssp_get_username(*auth_ntlmssp_state),
471 auth_ntlmssp_get_domain(*auth_ntlmssp_state));
474 reply_outbuf(req, 4, 0);
476 SSVAL(req->outbuf, smb_uid, vuid);
478 if (NT_STATUS_IS_OK(nt_status)) {
479 DATA_BLOB nullblob = data_blob_null;
481 if (!is_partial_auth_vuid(sconn, vuid)) {
482 nt_status = NT_STATUS_LOGON_FAILURE;
486 /* register_existing_vuid keeps the server info */
487 if (register_existing_vuid(sconn, vuid,
488 session_info, nullblob,
489 auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
491 /* The problem is, *auth_ntlmssp_state points
492 * into the vuser this will have
493 * talloc_free()'ed in
494 * register_existing_vuid() */
495 do_invalidate = false;
496 nt_status = NT_STATUS_LOGON_FAILURE;
500 /* current_user_info is changed on new vuid */
501 reload_services(sconn->msg_ctx, sconn->sock, True);
503 SSVAL(req->outbuf, smb_vwv3, 0);
505 if (session_info->guest) {
506 SSVAL(req->outbuf,smb_vwv2,1);
513 response = spnego_gen_auth_response(talloc_tos(),
517 response = *ntlmssp_blob;
520 reply_sesssetup_blob(req, response, nt_status);
522 data_blob_free(&response);
525 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
526 and the other end, that we are not finished yet. */
528 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
529 /* NB. This is *NOT* an error case. JRA */
531 TALLOC_FREE(*auth_ntlmssp_state);
532 if (!NT_STATUS_IS_OK(nt_status)) {
533 /* Kill the intermediate vuid */
534 invalidate_vuid(sconn, vuid);
540 /****************************************************************************
541 Is this a krb5 mechanism ?
542 ****************************************************************************/
544 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
546 DATA_BLOB *pblob_out,
549 char *OIDs[ASN1_MAX_OIDS];
551 NTSTATUS ret = NT_STATUS_OK;
553 *kerb_mechOID = NULL;
555 /* parse out the OIDs and the first sec blob */
556 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
558 return NT_STATUS_LOGON_FAILURE;
561 /* only look at the first OID for determining the mechToken --
562 according to RFC2478, we should choose the one we want
563 and renegotiate, but i smell a client bug here..
565 Problem observed when connecting to a member (samba box)
566 of an AD domain as a user in a Samba domain. Samba member
567 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
568 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
569 NTLMSSP mechtoken. --jerry */
572 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
573 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
574 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
575 if (*kerb_mechOID == NULL) {
576 ret = NT_STATUS_NO_MEMORY;
581 for (i=0;OIDs[i];i++) {
582 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
583 talloc_free(OIDs[i]);
588 /****************************************************************************
589 Fall back from krb5 to NTLMSSP.
590 ****************************************************************************/
592 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
597 reply_outbuf(req, 4, 0);
598 SSVAL(req->outbuf,smb_uid,vuid);
600 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
601 "but set to downgrade to NTLMSSP\n"));
603 response = spnego_gen_auth_response(talloc_tos(), NULL,
604 NT_STATUS_MORE_PROCESSING_REQUIRED,
606 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
607 data_blob_free(&response);
610 /****************************************************************************
611 Reply to a session setup spnego negotiate packet.
612 ****************************************************************************/
614 static void reply_spnego_negotiate(struct smb_request *req,
617 struct auth_ntlmssp_state **auth_ntlmssp_state)
621 char *kerb_mech = NULL;
623 struct smbd_server_connection *sconn = req->sconn;
625 status = parse_spnego_mechanisms(talloc_tos(),
626 blob1, &secblob, &kerb_mech);
627 if (!NT_STATUS_IS_OK(status)) {
628 /* Kill the intermediate vuid */
629 invalidate_vuid(sconn, vuid);
630 reply_nterror(req, nt_status_squash(status));
634 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
635 (unsigned long)secblob.length));
638 if (kerb_mech && ((lp_security()==SEC_ADS) ||
639 USE_KERBEROS_KEYTAB) ) {
640 bool destroy_vuid = True;
641 reply_spnego_kerberos(req, &secblob, kerb_mech,
642 vuid, &destroy_vuid);
643 data_blob_free(&secblob);
645 /* Kill the intermediate vuid */
646 invalidate_vuid(sconn, vuid);
648 TALLOC_FREE(kerb_mech);
653 TALLOC_FREE(*auth_ntlmssp_state);
656 data_blob_free(&secblob);
657 /* The mechtoken is a krb5 ticket, but
658 * we need to fall back to NTLM. */
659 reply_spnego_downgrade_to_ntlmssp(req, vuid);
660 TALLOC_FREE(kerb_mech);
664 status = auth_ntlmssp_start(auth_ntlmssp_state);
665 if (!NT_STATUS_IS_OK(status)) {
666 /* Kill the intermediate vuid */
667 invalidate_vuid(sconn, vuid);
668 reply_nterror(req, nt_status_squash(status));
672 status = auth_ntlmssp_update(*auth_ntlmssp_state,
675 data_blob_free(&secblob);
677 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
678 &chal, status, OID_NTLMSSP, true);
680 data_blob_free(&chal);
682 /* already replied */
686 /****************************************************************************
687 Reply to a session setup spnego auth packet.
688 ****************************************************************************/
690 static void reply_spnego_auth(struct smb_request *req,
693 struct auth_ntlmssp_state **auth_ntlmssp_state)
695 DATA_BLOB auth = data_blob_null;
696 DATA_BLOB auth_reply = data_blob_null;
697 DATA_BLOB secblob = data_blob_null;
698 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
699 struct smbd_server_connection *sconn = req->sconn;
701 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
703 file_save("auth.dat", blob1.data, blob1.length);
705 /* Kill the intermediate vuid */
706 invalidate_vuid(sconn, vuid);
708 reply_nterror(req, nt_status_squash(
709 NT_STATUS_LOGON_FAILURE));
713 if (auth.data[0] == ASN1_APPLICATION(0)) {
714 /* Might be a second negTokenTarg packet */
715 char *kerb_mech = NULL;
717 status = parse_spnego_mechanisms(talloc_tos(),
718 auth, &secblob, &kerb_mech);
720 if (!NT_STATUS_IS_OK(status)) {
721 /* Kill the intermediate vuid */
722 invalidate_vuid(sconn, vuid);
723 reply_nterror(req, nt_status_squash(status));
727 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
728 (unsigned long)secblob.length));
730 if (kerb_mech && ((lp_security()==SEC_ADS) ||
731 USE_KERBEROS_KEYTAB)) {
732 bool destroy_vuid = True;
733 reply_spnego_kerberos(req, &secblob, kerb_mech,
734 vuid, &destroy_vuid);
735 data_blob_free(&secblob);
736 data_blob_free(&auth);
738 /* Kill the intermediate vuid */
739 invalidate_vuid(sconn, vuid);
741 TALLOC_FREE(kerb_mech);
745 /* Can't blunder into NTLMSSP auth if we have
749 /* Kill the intermediate vuid */
750 invalidate_vuid(sconn, vuid);
751 DEBUG(3,("reply_spnego_auth: network "
752 "misconfiguration, client sent us a "
753 "krb5 ticket and kerberos security "
755 reply_nterror(req, nt_status_squash(
756 NT_STATUS_LOGON_FAILURE));
757 TALLOC_FREE(kerb_mech);
761 /* If we get here it wasn't a negTokenTarg auth packet. */
762 data_blob_free(&secblob);
764 if (!*auth_ntlmssp_state) {
765 status = auth_ntlmssp_start(auth_ntlmssp_state);
766 if (!NT_STATUS_IS_OK(status)) {
767 /* Kill the intermediate vuid */
768 invalidate_vuid(sconn, vuid);
769 reply_nterror(req, nt_status_squash(status));
774 status = auth_ntlmssp_update(*auth_ntlmssp_state,
777 data_blob_free(&auth);
779 /* Don't send the mechid as we've already sent this (RFC4178). */
781 reply_spnego_ntlmssp(req, vuid,
783 &auth_reply, status, NULL, true);
785 data_blob_free(&auth_reply);
787 /* and tell smbd that we have already replied to this packet */
791 /****************************************************************************
792 Delete an entry on the list.
793 ****************************************************************************/
795 static void delete_partial_auth(struct smbd_server_connection *sconn,
796 struct pending_auth_data *pad)
801 DLIST_REMOVE(sconn->smb1.pd_list, pad);
802 data_blob_free(&pad->partial_data);
806 /****************************************************************************
807 Search for a partial SPNEGO auth fragment matching an smbpid.
808 ****************************************************************************/
810 static struct pending_auth_data *get_pending_auth_data(
811 struct smbd_server_connection *sconn,
814 struct pending_auth_data *pad;
816 * NOTE: using the smbpid here is completely wrong...
818 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
820 for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
821 if (pad->smbpid == smbpid) {
828 /****************************************************************************
829 Check the size of an SPNEGO blob. If we need more return
830 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
831 the blob to be more than 64k.
832 ****************************************************************************/
834 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
835 uint16 smbpid, uint16 vuid,
838 struct pending_auth_data *pad = NULL;
840 size_t needed_len = 0;
842 pad = get_pending_auth_data(sconn, smbpid);
844 /* Ensure we have some data. */
845 if (pblob->length == 0) {
846 /* Caller can cope. */
847 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
848 delete_partial_auth(sconn, pad);
852 /* Were we waiting for more data ? */
855 size_t copy_len = MIN(65536, pblob->length);
857 /* Integer wrap paranoia.... */
859 if (pad->partial_data.length + copy_len <
860 pad->partial_data.length ||
861 pad->partial_data.length + copy_len < copy_len) {
863 DEBUG(2,("check_spnego_blob_complete: integer wrap "
864 "pad->partial_data.length = %u, "
866 (unsigned int)pad->partial_data.length,
867 (unsigned int)copy_len ));
869 delete_partial_auth(sconn, pad);
870 return NT_STATUS_INVALID_PARAMETER;
873 DEBUG(10,("check_spnego_blob_complete: "
874 "pad->partial_data.length = %u, "
875 "pad->needed_len = %u, "
877 "pblob->length = %u,\n",
878 (unsigned int)pad->partial_data.length,
879 (unsigned int)pad->needed_len,
880 (unsigned int)copy_len,
881 (unsigned int)pblob->length ));
883 tmp_blob = data_blob(NULL,
884 pad->partial_data.length + copy_len);
886 /* Concatenate the two (up to copy_len) bytes. */
887 memcpy(tmp_blob.data,
888 pad->partial_data.data,
889 pad->partial_data.length);
890 memcpy(tmp_blob.data + pad->partial_data.length,
894 /* Replace the partial data. */
895 data_blob_free(&pad->partial_data);
896 pad->partial_data = tmp_blob;
897 ZERO_STRUCT(tmp_blob);
900 if (pblob->length >= pad->needed_len) {
901 /* Yes, replace pblob. */
902 data_blob_free(pblob);
903 *pblob = pad->partial_data;
904 ZERO_STRUCT(pad->partial_data);
905 delete_partial_auth(sconn, pad);
909 /* Still need more data. */
910 pad->needed_len -= copy_len;
911 return NT_STATUS_MORE_PROCESSING_REQUIRED;
914 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
915 (pblob->data[0] != ASN1_CONTEXT(1))) {
916 /* Not something we can determine the
922 /* This is a new SPNEGO sessionsetup - see if
923 * the data given in this blob is enough.
926 data = asn1_init(NULL);
928 return NT_STATUS_NO_MEMORY;
931 asn1_load(data, *pblob);
932 asn1_start_tag(data, pblob->data[0]);
933 if (data->has_error || data->nesting == NULL) {
935 /* Let caller catch. */
939 /* Integer wrap paranoia.... */
941 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
942 data->nesting->taglen + data->nesting->start < data->nesting->start) {
944 DEBUG(2,("check_spnego_blob_complete: integer wrap "
945 "data.nesting->taglen = %u, "
946 "data.nesting->start = %u\n",
947 (unsigned int)data->nesting->taglen,
948 (unsigned int)data->nesting->start ));
951 return NT_STATUS_INVALID_PARAMETER;
954 /* Total length of the needed asn1 is the tag length
955 * plus the current offset. */
957 needed_len = data->nesting->taglen + data->nesting->start;
960 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
961 "pblob->length = %u\n",
962 (unsigned int)needed_len,
963 (unsigned int)pblob->length ));
965 if (needed_len <= pblob->length) {
966 /* Nothing to do - blob is complete. */
970 /* Refuse the blob if it's bigger than 64k. */
971 if (needed_len > 65536) {
972 DEBUG(2,("check_spnego_blob_complete: needed_len "
974 (unsigned int)needed_len ));
975 return NT_STATUS_INVALID_PARAMETER;
978 /* We must store this blob until complete. */
979 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
980 return NT_STATUS_NO_MEMORY;
982 pad->needed_len = needed_len - pblob->length;
983 pad->partial_data = data_blob(pblob->data, pblob->length);
984 if (pad->partial_data.data == NULL) {
986 return NT_STATUS_NO_MEMORY;
988 pad->smbpid = smbpid;
990 DLIST_ADD(sconn->smb1.pd_list, pad);
992 return NT_STATUS_MORE_PROCESSING_REQUIRED;
995 /****************************************************************************
996 Reply to a session setup command.
997 conn POINTER CAN BE NULL HERE !
998 ****************************************************************************/
1000 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1006 const char *native_os;
1007 const char *native_lanman;
1008 const char *primary_domain;
1010 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1011 enum remote_arch_types ra_type = get_remote_arch();
1012 int vuid = req->vuid;
1013 user_struct *vuser = NULL;
1014 NTSTATUS status = NT_STATUS_OK;
1015 uint16 smbpid = req->smbpid;
1016 struct smbd_server_connection *sconn = req->sconn;
1018 DEBUG(3,("Doing spnego session setup\n"));
1020 if (global_client_caps == 0) {
1021 global_client_caps = IVAL(req->vwv+10, 0);
1023 if (!(global_client_caps & CAP_STATUS32)) {
1024 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1031 if (data_blob_len == 0) {
1032 /* an invalid request */
1033 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1037 bufrem = smbreq_bufrem(req, p);
1038 /* pull the spnego blob */
1039 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1042 file_save("negotiate.dat", blob1.data, blob1.length);
1045 p2 = (char *)req->buf + blob1.length;
1047 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1049 native_os = tmp ? tmp : "";
1051 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1053 native_lanman = tmp ? tmp : "";
1055 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1057 primary_domain = tmp ? tmp : "";
1059 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1060 native_os, native_lanman, primary_domain));
1062 if ( ra_type == RA_WIN2K ) {
1063 /* Vista sets neither the OS or lanman strings */
1065 if ( !strlen(native_os) && !strlen(native_lanman) )
1066 set_remote_arch(RA_VISTA);
1068 /* Windows 2003 doesn't set the native lanman string,
1069 but does set primary domain which is a bug I think */
1071 if ( !strlen(native_lanman) ) {
1072 ra_lanman_string( primary_domain );
1074 ra_lanman_string( native_lanman );
1076 } else if ( ra_type == RA_VISTA ) {
1077 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1078 set_remote_arch(RA_OSX);
1082 /* Did we get a valid vuid ? */
1083 if (!is_partial_auth_vuid(sconn, vuid)) {
1084 /* No, then try and see if this is an intermediate sessionsetup
1085 * for a large SPNEGO packet. */
1086 struct pending_auth_data *pad;
1087 pad = get_pending_auth_data(sconn, smbpid);
1089 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1090 "pending vuid %u\n",
1091 (unsigned int)pad->vuid ));
1096 /* Do we have a valid vuid now ? */
1097 if (!is_partial_auth_vuid(sconn, vuid)) {
1098 /* No, start a new authentication setup. */
1099 vuid = register_initial_vuid(sconn);
1100 if (vuid == UID_FIELD_INVALID) {
1101 data_blob_free(&blob1);
1102 reply_nterror(req, nt_status_squash(
1103 NT_STATUS_INVALID_PARAMETER));
1108 vuser = get_partial_auth_user_struct(sconn, vuid);
1109 /* This MUST be valid. */
1111 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1114 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1115 * sessionsetup requests as the Windows limit on the security blob
1116 * field is 4k. Bug #4400. JRA.
1119 status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 if (!NT_STATUS_EQUAL(status,
1122 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1123 /* Real error - kill the intermediate vuid */
1124 invalidate_vuid(sconn, vuid);
1126 data_blob_free(&blob1);
1127 reply_nterror(req, nt_status_squash(status));
1131 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1133 /* its a negTokenTarg packet */
1135 reply_spnego_negotiate(req, vuid, blob1,
1136 &vuser->auth_ntlmssp_state);
1137 data_blob_free(&blob1);
1141 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1143 /* its a auth packet */
1145 reply_spnego_auth(req, vuid, blob1,
1146 &vuser->auth_ntlmssp_state);
1147 data_blob_free(&blob1);
1151 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1154 if (!vuser->auth_ntlmssp_state) {
1155 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1156 if (!NT_STATUS_IS_OK(status)) {
1157 /* Kill the intermediate vuid */
1158 invalidate_vuid(sconn, vuid);
1159 data_blob_free(&blob1);
1160 reply_nterror(req, nt_status_squash(status));
1165 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1168 data_blob_free(&blob1);
1170 reply_spnego_ntlmssp(req, vuid,
1171 &vuser->auth_ntlmssp_state,
1172 &chal, status, OID_NTLMSSP, false);
1173 data_blob_free(&chal);
1177 /* what sort of packet is this? */
1178 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1180 data_blob_free(&blob1);
1182 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1185 /****************************************************************************
1186 On new VC == 0, shutdown *all* old connections and users.
1187 It seems that only NT4.x does this. At W2K and above (XP etc.).
1188 a new session setup with VC==0 is ignored.
1189 ****************************************************************************/
1191 struct shutdown_state {
1193 struct messaging_context *msg_ctx;
1196 static int shutdown_other_smbds(const struct connections_key *key,
1197 const struct connections_data *crec,
1200 struct shutdown_state *state = (struct shutdown_state *)private_data;
1202 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1203 procid_str(talloc_tos(), &crec->pid), crec->addr));
1205 if (!process_exists(crec->pid)) {
1206 DEBUG(10, ("process does not exist\n"));
1210 if (procid_is_me(&crec->pid)) {
1211 DEBUG(10, ("It's me\n"));
1215 if (strcmp(state->ip, crec->addr) != 0) {
1216 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1220 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1221 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1224 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1229 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1231 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1232 "compatible we would close all old resources.\n"));
1235 invalidate_all_vuids();
1237 if (lp_reset_on_zero_vc()) {
1239 struct shutdown_state state;
1241 addr = tsocket_address_inet_addr_string(
1242 sconn->remote_address, talloc_tos());
1247 state.msg_ctx = sconn->msg_ctx;
1248 connections_forall_read(shutdown_other_smbds, &state);
1253 /****************************************************************************
1254 Reply to a session setup command.
1255 ****************************************************************************/
1257 void reply_sesssetup_and_X(struct smb_request *req)
1263 DATA_BLOB plaintext_password;
1266 fstring sub_user; /* Sanitised username for substituion */
1268 const char *native_os;
1269 const char *native_lanman;
1270 const char *primary_domain;
1271 struct auth_usersupplied_info *user_info = NULL;
1272 struct auth_serversupplied_info *server_info = NULL;
1273 struct auth_serversupplied_info *session_info = NULL;
1274 uint16 smb_flag2 = req->flags2;
1277 struct smbd_server_connection *sconn = req->sconn;
1279 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1281 START_PROFILE(SMBsesssetupX);
1283 ZERO_STRUCT(lm_resp);
1284 ZERO_STRUCT(nt_resp);
1285 ZERO_STRUCT(plaintext_password);
1287 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1289 /* a SPNEGO session setup has 12 command words, whereas a normal
1290 NT1 session setup has 13. See the cifs spec. */
1291 if (req->wct == 12 &&
1292 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1294 if (!sconn->smb1.negprot.spnego) {
1295 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1296 "at SPNEGO session setup when it was not "
1298 reply_nterror(req, nt_status_squash(
1299 NT_STATUS_LOGON_FAILURE));
1300 END_PROFILE(SMBsesssetupX);
1304 if (SVAL(req->vwv+4, 0) == 0) {
1305 setup_new_vc_session(req->sconn);
1308 reply_sesssetup_and_X_spnego(req);
1309 END_PROFILE(SMBsesssetupX);
1313 smb_bufsize = SVAL(req->vwv+2, 0);
1315 if (get_Protocol() < PROTOCOL_NT1) {
1316 uint16 passlen1 = SVAL(req->vwv+7, 0);
1318 /* Never do NT status codes with protocols before NT1 as we
1319 * don't get client caps. */
1320 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1322 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1323 reply_nterror(req, nt_status_squash(
1324 NT_STATUS_INVALID_PARAMETER));
1325 END_PROFILE(SMBsesssetupX);
1330 lm_resp = data_blob(req->buf, passlen1);
1332 plaintext_password = data_blob(req->buf, passlen1+1);
1333 /* Ensure null termination */
1334 plaintext_password.data[passlen1] = 0;
1337 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1338 req->buf + passlen1, STR_TERMINATE);
1339 user = tmp ? tmp : "";
1344 uint16 passlen1 = SVAL(req->vwv+7, 0);
1345 uint16 passlen2 = SVAL(req->vwv+8, 0);
1346 enum remote_arch_types ra_type = get_remote_arch();
1347 const uint8_t *p = req->buf;
1348 const uint8_t *save_p = req->buf;
1352 if(global_client_caps == 0) {
1353 global_client_caps = IVAL(req->vwv+11, 0);
1355 if (!(global_client_caps & CAP_STATUS32)) {
1356 remove_from_common_flags2(
1357 FLAGS2_32_BIT_ERROR_CODES);
1360 /* client_caps is used as final determination if
1361 * client is NT or Win95. This is needed to return
1362 * the correct error codes in some circumstances.
1365 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1366 ra_type == RA_WIN95) {
1367 if(!(global_client_caps & (CAP_NT_SMBS|
1369 set_remote_arch( RA_WIN95);
1375 /* both Win95 and WinNT stuff up the password
1376 * lengths for non-encrypting systems. Uggh.
1378 if passlen1==24 its a win95 system, and its setting
1379 the password length incorrectly. Luckily it still
1380 works with the default code because Win95 will null
1381 terminate the password anyway
1383 if passlen1>0 and passlen2>0 then maybe its a NT box
1384 and its setting passlen2 to some random value which
1385 really stuffs things up. we need to fix that one. */
1387 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1393 /* check for nasty tricks */
1394 if (passlen1 > MAX_PASS_LEN
1395 || passlen1 > smbreq_bufrem(req, p)) {
1396 reply_nterror(req, nt_status_squash(
1397 NT_STATUS_INVALID_PARAMETER));
1398 END_PROFILE(SMBsesssetupX);
1402 if (passlen2 > MAX_PASS_LEN
1403 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1404 reply_nterror(req, nt_status_squash(
1405 NT_STATUS_INVALID_PARAMETER));
1406 END_PROFILE(SMBsesssetupX);
1410 /* Save the lanman2 password and the NT md4 password. */
1412 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1417 lm_resp = data_blob(p, passlen1);
1418 nt_resp = data_blob(p+passlen1, passlen2);
1419 } else if (lp_security() != SEC_SHARE) {
1421 * In share level we should ignore any passwords, so
1422 * only read them if we're not.
1425 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1427 if (unic && (passlen2 == 0) && passlen1) {
1428 /* Only a ascii plaintext password was sent. */
1429 (void)srvstr_pull_talloc(talloc_tos(),
1435 STR_TERMINATE|STR_ASCII);
1437 (void)srvstr_pull_talloc(talloc_tos(),
1442 unic ? passlen2 : passlen1,
1446 reply_nterror(req, nt_status_squash(
1447 NT_STATUS_INVALID_PARAMETER));
1448 END_PROFILE(SMBsesssetupX);
1451 plaintext_password = data_blob(pass, strlen(pass)+1);
1454 p += passlen1 + passlen2;
1456 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1458 user = tmp ? tmp : "";
1460 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1462 domain = tmp ? tmp : "";
1464 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1466 native_os = tmp ? tmp : "";
1468 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1470 native_lanman = tmp ? tmp : "";
1472 /* not documented or decoded by Ethereal but there is one more
1473 * string in the extra bytes which is the same as the
1474 * PrimaryDomain when using extended security. Windows NT 4
1475 * and 2003 use this string to store the native lanman string.
1476 * Windows 9x does not include a string here at all so we have
1477 * to check if we have any extra bytes left */
1479 byte_count = SVAL(req->vwv+13, 0);
1480 if ( PTR_DIFF(p, save_p) < byte_count) {
1481 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1483 primary_domain = tmp ? tmp : "";
1485 primary_domain = talloc_strdup(talloc_tos(), "null");
1488 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1489 "PrimaryDomain=[%s]\n",
1490 domain, native_os, native_lanman, primary_domain));
1492 if ( ra_type == RA_WIN2K ) {
1493 if ( strlen(native_lanman) == 0 )
1494 ra_lanman_string( primary_domain );
1496 ra_lanman_string( native_lanman );
1501 if (SVAL(req->vwv+4, 0) == 0) {
1502 setup_new_vc_session(req->sconn);
1505 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1506 domain, user, get_remote_machine_name()));
1509 if (sconn->smb1.negprot.spnego) {
1511 /* This has to be here, because this is a perfectly
1512 * valid behaviour for guest logons :-( */
1514 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1515 "at 'normal' session setup after "
1516 "negotiating spnego.\n"));
1517 reply_nterror(req, nt_status_squash(
1518 NT_STATUS_LOGON_FAILURE));
1519 END_PROFILE(SMBsesssetupX);
1522 fstrcpy(sub_user, user);
1524 fstrcpy(sub_user, lp_guestaccount());
1527 sub_set_smb_name(sub_user);
1529 reload_services(sconn->msg_ctx, sconn->sock, True);
1531 if (lp_security() == SEC_SHARE) {
1532 char *sub_user_mapped = NULL;
1533 /* In share level we should ignore any passwords */
1535 data_blob_free(&lm_resp);
1536 data_blob_free(&nt_resp);
1537 data_blob_clear_free(&plaintext_password);
1539 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1540 if (!sub_user_mapped) {
1541 reply_nterror(req, NT_STATUS_NO_MEMORY);
1542 END_PROFILE(SMBsesssetupX);
1545 fstrcpy(sub_user, sub_user_mapped);
1546 add_session_user(sconn, sub_user);
1547 add_session_workgroup(sconn, domain);
1548 /* Then force it to null for the benfit of the code below */
1554 nt_status = check_guest_password(&server_info);
1556 } else if (doencrypt) {
1557 struct auth_context *negprot_auth_context = NULL;
1558 negprot_auth_context = sconn->smb1.negprot.auth_context;
1559 if (!negprot_auth_context) {
1560 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1561 "session setup without negprot denied!\n"));
1562 reply_nterror(req, nt_status_squash(
1563 NT_STATUS_LOGON_FAILURE));
1564 END_PROFILE(SMBsesssetupX);
1567 nt_status = make_user_info_for_reply_enc(&user_info, user,
1570 if (NT_STATUS_IS_OK(nt_status)) {
1571 nt_status = negprot_auth_context->check_ntlm_password(
1572 negprot_auth_context,
1577 struct auth_context *plaintext_auth_context = NULL;
1579 nt_status = make_auth_context_subsystem(
1580 talloc_tos(), &plaintext_auth_context);
1582 if (NT_STATUS_IS_OK(nt_status)) {
1585 plaintext_auth_context->get_ntlm_challenge(
1586 plaintext_auth_context, chal);
1588 if (!make_user_info_for_reply(&user_info,
1590 plaintext_password)) {
1591 nt_status = NT_STATUS_NO_MEMORY;
1594 if (NT_STATUS_IS_OK(nt_status)) {
1595 nt_status = plaintext_auth_context->check_ntlm_password(
1596 plaintext_auth_context,
1600 TALLOC_FREE(plaintext_auth_context);
1605 free_user_info(&user_info);
1607 if (!NT_STATUS_IS_OK(nt_status)) {
1608 nt_status = do_map_to_guest(nt_status, &server_info,
1612 if (!NT_STATUS_IS_OK(nt_status)) {
1613 data_blob_free(&nt_resp);
1614 data_blob_free(&lm_resp);
1615 data_blob_clear_free(&plaintext_password);
1616 reply_nterror(req, nt_status_squash(nt_status));
1617 END_PROFILE(SMBsesssetupX);
1621 nt_status = create_local_token(req, server_info, NULL, &session_info);
1622 TALLOC_FREE(server_info);
1624 if (!NT_STATUS_IS_OK(nt_status)) {
1625 DEBUG(10, ("create_local_token failed: %s\n",
1626 nt_errstr(nt_status)));
1627 data_blob_free(&nt_resp);
1628 data_blob_free(&lm_resp);
1629 data_blob_clear_free(&plaintext_password);
1630 reply_nterror(req, nt_status_squash(nt_status));
1631 END_PROFILE(SMBsesssetupX);
1635 data_blob_clear_free(&plaintext_password);
1637 /* it's ok - setup a reply */
1638 reply_outbuf(req, 3, 0);
1639 if (get_Protocol() >= PROTOCOL_NT1) {
1640 push_signature(&req->outbuf);
1641 /* perhaps grab OS version here?? */
1644 if (session_info->guest) {
1645 SSVAL(req->outbuf,smb_vwv2,1);
1648 /* register the name and uid as being validated, so further connections
1649 to a uid can get through without a password, on the same VC */
1651 if (lp_security() == SEC_SHARE) {
1652 sess_vuid = UID_FIELD_INVALID;
1653 TALLOC_FREE(session_info);
1655 /* Ignore the initial vuid. */
1656 sess_vuid = register_initial_vuid(sconn);
1657 if (sess_vuid == UID_FIELD_INVALID) {
1658 data_blob_free(&nt_resp);
1659 data_blob_free(&lm_resp);
1660 reply_nterror(req, nt_status_squash(
1661 NT_STATUS_LOGON_FAILURE));
1662 END_PROFILE(SMBsesssetupX);
1665 /* register_existing_vuid keeps the session_info */
1666 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1668 nt_resp.data ? nt_resp : lm_resp,
1670 if (sess_vuid == UID_FIELD_INVALID) {
1671 data_blob_free(&nt_resp);
1672 data_blob_free(&lm_resp);
1673 reply_nterror(req, nt_status_squash(
1674 NT_STATUS_LOGON_FAILURE));
1675 END_PROFILE(SMBsesssetupX);
1679 /* current_user_info is changed on new vuid */
1680 reload_services(sconn->msg_ctx, sconn->sock, True);
1683 data_blob_free(&nt_resp);
1684 data_blob_free(&lm_resp);
1686 SSVAL(req->outbuf,smb_uid,sess_vuid);
1687 SSVAL(req->inbuf,smb_uid,sess_vuid);
1688 req->vuid = sess_vuid;
1690 if (!sconn->smb1.sessions.done_sesssetup) {
1691 sconn->smb1.sessions.max_send =
1692 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1694 sconn->smb1.sessions.done_sesssetup = true;
1696 END_PROFILE(SMBsesssetupX);