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"
37 /* For split krb5 SPNEGO blobs. */
38 struct pending_auth_data
{
39 struct pending_auth_data
*prev
, *next
;
40 uint16 vuid
; /* Tag for this entry. */
41 uint16 smbpid
; /* Alternate tag for this entry. */
43 DATA_BLOB partial_data
;
47 on a logon error possibly map the error to success if "map to guest"
50 NTSTATUS
do_map_to_guest(NTSTATUS status
,
51 struct auth_serversupplied_info
**server_info
,
52 const char *user
, const char *domain
)
54 user
= user
? user
: "";
55 domain
= domain
? domain
: "";
57 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
58 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER
) ||
59 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
)) {
60 DEBUG(3,("No such user %s [%s] - using guest account\n",
62 status
= make_server_info_guest(NULL
, server_info
);
66 if (NT_STATUS_EQUAL(status
, NT_STATUS_WRONG_PASSWORD
)) {
67 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
) {
68 DEBUG(3,("Registered username %s for guest access\n",
70 status
= make_server_info_guest(NULL
, server_info
);
77 /****************************************************************************
78 Add the standard 'Samba' signature to the end of the session setup.
79 ****************************************************************************/
81 static int push_signature(uint8
**outbuf
)
88 tmp
= message_push_string(outbuf
, "Unix", STR_TERMINATE
);
90 if (tmp
== -1) return -1;
93 if (asprintf(&lanman
, "Samba %s", samba_version_string()) != -1) {
94 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
98 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
101 if (tmp
== -1) return -1;
104 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
106 if (tmp
== -1) return -1;
112 /****************************************************************************
113 Send a security blob via a session setup reply.
114 ****************************************************************************/
116 static void reply_sesssetup_blob(struct smb_request
*req
,
120 if (!NT_STATUS_IS_OK(nt_status
) &&
121 !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
122 reply_nterror(req
, nt_status_squash(nt_status
));
126 nt_status
= nt_status_squash(nt_status
);
127 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
128 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
129 SSVAL(req
->outbuf
, smb_vwv3
, blob
.length
);
131 if ((message_push_blob(&req
->outbuf
, blob
) == -1)
132 || (push_signature(&req
->outbuf
) == -1)) {
133 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
137 /****************************************************************************
138 Do a 'guest' logon, getting back the
139 ****************************************************************************/
141 static NTSTATUS
check_guest_password(struct auth_serversupplied_info
**server_info
)
143 struct auth_context
*auth_context
;
144 struct auth_usersupplied_info
*user_info
= NULL
;
147 static unsigned char chal
[8] = { 0, };
149 DEBUG(3,("Got anonymous request\n"));
151 nt_status
= make_auth_context_fixed(talloc_tos(), &auth_context
, chal
);
152 if (!NT_STATUS_IS_OK(nt_status
)) {
156 if (!make_user_info_guest(&user_info
)) {
157 TALLOC_FREE(auth_context
);
158 return NT_STATUS_NO_MEMORY
;
161 nt_status
= auth_context
->check_ntlm_password(auth_context
,
164 TALLOC_FREE(auth_context
);
165 free_user_info(&user_info
);
173 /* Experiment that failed. See "only happens with a KDC" comment below. */
174 /****************************************************************************
175 Cerate a clock skew error blob for a Windows client.
176 ****************************************************************************/
178 static bool make_krb5_skew_error(DATA_BLOB
*pblob_out
)
180 krb5_context context
= NULL
;
181 krb5_error_code kerr
= 0;
183 krb5_principal host_princ
= NULL
;
184 char *host_princ_s
= NULL
;
187 *pblob_out
= data_blob_null
;
189 initialize_krb5_error_table();
190 kerr
= krb5_init_context(&context
);
194 /* Create server principal. */
195 asprintf(&host_princ_s
, "%s$@%s", global_myname(), lp_realm());
199 strlower_m(host_princ_s
);
201 kerr
= smb_krb5_parse_name(context
, host_princ_s
, &host_princ
);
203 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
204 "for name %s: Error %s\n",
205 host_princ_s
, error_message(kerr
) ));
209 kerr
= smb_krb5_mk_error(context
, KRB5KRB_AP_ERR_SKEW
,
212 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
213 "failed: Error %s\n",
214 error_message(kerr
) ));
218 *pblob_out
= data_blob(reply
.data
, reply
.length
);
219 kerberos_free_data_contents(context
,&reply
);
225 SAFE_FREE(host_princ_s
);
228 krb5_free_principal(context
, host_princ
);
230 krb5_free_context(context
);
235 /****************************************************************************
236 Reply to a session setup spnego negotiate packet for kerberos.
237 ****************************************************************************/
239 static void reply_spnego_kerberos(struct smb_request
*req
,
243 bool *p_invalidate_vuid
)
248 int sess_vuid
= req
->vuid
;
249 NTSTATUS ret
= NT_STATUS_OK
;
250 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
251 struct auth_serversupplied_info
*session_info
= NULL
;
252 DATA_BLOB session_key
= data_blob_null
;
254 DATA_BLOB nullblob
= data_blob_null
;
255 bool map_domainuser_to_guest
= False
;
256 bool username_was_mapped
;
257 struct PAC_LOGON_INFO
*logon_info
= NULL
;
258 struct smbd_server_connection
*sconn
= req
->sconn
;
266 ZERO_STRUCT(ap_rep_wrapped
);
267 ZERO_STRUCT(response
);
269 /* Normally we will always invalidate the intermediate vuid. */
270 *p_invalidate_vuid
= True
;
272 mem_ctx
= talloc_init("reply_spnego_kerberos");
273 if (mem_ctx
== NULL
) {
274 reply_nterror(req
, nt_status_squash(NT_STATUS_NO_MEMORY
));
278 if (!spnego_parse_krb5_wrap(mem_ctx
, *secblob
, &ticket
, tok_id
)) {
279 talloc_destroy(mem_ctx
);
280 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
284 ret
= ads_verify_ticket(mem_ctx
, lp_realm(), 0, &ticket
,
285 &principal
, &logon_info
, &ap_rep
,
288 data_blob_free(&ticket
);
290 if (!NT_STATUS_IS_OK(ret
)) {
292 /* Experiment that failed.
293 * See "only happens with a KDC" comment below. */
295 if (NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
298 * Windows in this case returns
299 * NT_STATUS_MORE_PROCESSING_REQUIRED
300 * with a negTokenTarg blob containing an krb5_error
301 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
302 * The client then fixes its clock and continues rather
303 * than giving an error. JRA.
304 * -- Looks like this only happens with a KDC. JRA.
307 bool ok
= make_krb5_skew_error(&ap_rep
);
309 talloc_destroy(mem_ctx
);
310 return ERROR_NT(nt_status_squash(
311 NT_STATUS_LOGON_FAILURE
));
313 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
315 response
= spnego_gen_auth_response(&ap_rep_wrapped
,
316 ret
, OID_KERBEROS5_OLD
);
317 reply_sesssetup_blob(conn
, inbuf
, outbuf
, response
,
318 NT_STATUS_MORE_PROCESSING_REQUIRED
);
321 * In this one case we don't invalidate the
322 * intermediate vuid as we're expecting the client
323 * to re-use it for the next sessionsetupX packet. JRA.
326 *p_invalidate_vuid
= False
;
328 data_blob_free(&ap_rep
);
329 data_blob_free(&ap_rep_wrapped
);
330 data_blob_free(&response
);
331 talloc_destroy(mem_ctx
);
332 return -1; /* already replied */
335 if (!NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
336 ret
= NT_STATUS_LOGON_FAILURE
;
339 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
341 talloc_destroy(mem_ctx
);
342 reply_nterror(req
, nt_status_squash(ret
));
346 ret
= get_user_from_kerberos_info(talloc_tos(),
347 sconn
->client_id
.name
,
348 principal
, logon_info
,
349 &username_was_mapped
,
350 &map_domainuser_to_guest
,
352 &real_username
, &pw
);
353 if (!NT_STATUS_IS_OK(ret
)) {
354 data_blob_free(&ap_rep
);
355 data_blob_free(&session_key
);
356 talloc_destroy(mem_ctx
);
357 reply_nterror(req
,nt_status_squash(NT_STATUS_LOGON_FAILURE
));
361 /* save the PAC data if we have it */
363 netsamlogon_cache_store(user
, &logon_info
->info3
);
366 /* setup the string used by %U */
367 sub_set_smb_name(real_username
);
369 /* reload services so that the new %U is taken into account */
370 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
372 ret
= make_session_info_krb5(mem_ctx
,
373 user
, domain
, real_username
, pw
,
374 logon_info
, map_domainuser_to_guest
,
378 data_blob_free(&session_key
);
379 if (!NT_STATUS_IS_OK(ret
)) {
380 DEBUG(1, ("make_server_info_krb5 failed!\n"));
381 data_blob_free(&ap_rep
);
382 TALLOC_FREE(mem_ctx
);
383 reply_nterror(req
, nt_status_squash(ret
));
387 if (!is_partial_auth_vuid(sconn
, sess_vuid
)) {
388 sess_vuid
= register_initial_vuid(sconn
);
391 /* register_existing_vuid keeps the server info */
392 /* register_existing_vuid takes ownership of session_key on success,
393 * no need to free after this on success. A better interface would copy
396 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
397 session_info
, nullblob
, user
);
399 reply_outbuf(req
, 4, 0);
400 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
402 if (sess_vuid
== UID_FIELD_INVALID
) {
403 ret
= NT_STATUS_LOGON_FAILURE
;
405 /* current_user_info is changed on new vuid */
406 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
408 SSVAL(req
->outbuf
, smb_vwv3
, 0);
410 if (session_info
->guest
) {
411 SSVAL(req
->outbuf
,smb_vwv2
,1);
414 SSVAL(req
->outbuf
, smb_uid
, sess_vuid
);
416 /* Successful logon. Keep this vuid. */
417 *p_invalidate_vuid
= False
;
420 /* wrap that up in a nice GSS-API wrapping */
421 if (NT_STATUS_IS_OK(ret
)) {
422 ap_rep_wrapped
= spnego_gen_krb5_wrap(talloc_tos(), ap_rep
,
425 ap_rep_wrapped
= data_blob_null
;
427 response
= spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped
, ret
,
429 reply_sesssetup_blob(req
, response
, ret
);
431 data_blob_free(&ap_rep
);
432 data_blob_free(&ap_rep_wrapped
);
433 data_blob_free(&response
);
434 TALLOC_FREE(mem_ctx
);
439 /****************************************************************************
440 Send a session setup reply, wrapped in SPNEGO.
441 Get vuid and check first.
442 End the NTLMSSP exchange context if we are OK/complete fail
443 This should be split into two functions, one to handle each
444 leg of the NTLM auth steps.
445 ***************************************************************************/
447 static void reply_spnego_ntlmssp(struct smb_request
*req
,
449 struct auth_ntlmssp_state
**auth_ntlmssp_state
,
450 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
,
454 bool do_invalidate
= true;
456 struct auth_serversupplied_info
*session_info
= NULL
;
457 struct smbd_server_connection
*sconn
= req
->sconn
;
459 if (NT_STATUS_IS_OK(nt_status
)) {
460 nt_status
= auth_ntlmssp_steal_session_info(talloc_tos(),
461 (*auth_ntlmssp_state
), &session_info
);
463 /* Note that this session_info won't have a session
464 * key. But for map to guest, that's exactly the right
465 * thing - we can't reasonably guess the key the
466 * client wants, as the password was wrong */
467 nt_status
= do_map_to_guest(nt_status
,
469 auth_ntlmssp_get_username(*auth_ntlmssp_state
),
470 auth_ntlmssp_get_domain(*auth_ntlmssp_state
));
473 reply_outbuf(req
, 4, 0);
475 SSVAL(req
->outbuf
, smb_uid
, vuid
);
477 if (NT_STATUS_IS_OK(nt_status
)) {
478 DATA_BLOB nullblob
= data_blob_null
;
480 if (!is_partial_auth_vuid(sconn
, vuid
)) {
481 nt_status
= NT_STATUS_LOGON_FAILURE
;
485 /* register_existing_vuid keeps the server info */
486 if (register_existing_vuid(sconn
, vuid
,
487 session_info
, nullblob
,
488 auth_ntlmssp_get_username(*auth_ntlmssp_state
)) !=
490 /* The problem is, *auth_ntlmssp_state points
491 * into the vuser this will have
492 * talloc_free()'ed in
493 * register_existing_vuid() */
494 do_invalidate
= false;
495 nt_status
= NT_STATUS_LOGON_FAILURE
;
499 /* current_user_info is changed on new vuid */
500 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
502 SSVAL(req
->outbuf
, smb_vwv3
, 0);
504 if (session_info
->guest
) {
505 SSVAL(req
->outbuf
,smb_vwv2
,1);
512 response
= spnego_gen_auth_response(talloc_tos(),
516 response
= *ntlmssp_blob
;
519 reply_sesssetup_blob(req
, response
, nt_status
);
521 data_blob_free(&response
);
524 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
525 and the other end, that we are not finished yet. */
527 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
528 /* NB. This is *NOT* an error case. JRA */
530 TALLOC_FREE(*auth_ntlmssp_state
);
531 if (!NT_STATUS_IS_OK(nt_status
)) {
532 /* Kill the intermediate vuid */
533 invalidate_vuid(sconn
, vuid
);
539 /****************************************************************************
540 Is this a krb5 mechanism ?
541 ****************************************************************************/
543 NTSTATUS
parse_spnego_mechanisms(TALLOC_CTX
*ctx
,
545 DATA_BLOB
*pblob_out
,
548 char *OIDs
[ASN1_MAX_OIDS
];
550 NTSTATUS ret
= NT_STATUS_OK
;
552 *kerb_mechOID
= NULL
;
554 /* parse out the OIDs and the first sec blob */
555 if (!spnego_parse_negTokenInit(ctx
, blob_in
, OIDs
, NULL
, pblob_out
) ||
557 return NT_STATUS_LOGON_FAILURE
;
560 /* only look at the first OID for determining the mechToken --
561 according to RFC2478, we should choose the one we want
562 and renegotiate, but i smell a client bug here..
564 Problem observed when connecting to a member (samba box)
565 of an AD domain as a user in a Samba domain. Samba member
566 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
567 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
568 NTLMSSP mechtoken. --jerry */
571 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
572 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
573 *kerb_mechOID
= talloc_strdup(ctx
, OIDs
[0]);
574 if (*kerb_mechOID
== NULL
) {
575 ret
= NT_STATUS_NO_MEMORY
;
580 for (i
=0;OIDs
[i
];i
++) {
581 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs
[i
]));
582 talloc_free(OIDs
[i
]);
587 /****************************************************************************
588 Fall back from krb5 to NTLMSSP.
589 ****************************************************************************/
591 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request
*req
,
596 reply_outbuf(req
, 4, 0);
597 SSVAL(req
->outbuf
,smb_uid
,vuid
);
599 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
600 "but set to downgrade to NTLMSSP\n"));
602 response
= spnego_gen_auth_response(talloc_tos(), NULL
,
603 NT_STATUS_MORE_PROCESSING_REQUIRED
,
605 reply_sesssetup_blob(req
, response
, NT_STATUS_MORE_PROCESSING_REQUIRED
);
606 data_blob_free(&response
);
609 /****************************************************************************
610 Reply to a session setup spnego negotiate packet.
611 ****************************************************************************/
613 static void reply_spnego_negotiate(struct smb_request
*req
,
616 struct auth_ntlmssp_state
**auth_ntlmssp_state
)
620 char *kerb_mech
= NULL
;
622 struct smbd_server_connection
*sconn
= req
->sconn
;
624 status
= parse_spnego_mechanisms(talloc_tos(),
625 blob1
, &secblob
, &kerb_mech
);
626 if (!NT_STATUS_IS_OK(status
)) {
627 /* Kill the intermediate vuid */
628 invalidate_vuid(sconn
, vuid
);
629 reply_nterror(req
, nt_status_squash(status
));
633 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
634 (unsigned long)secblob
.length
));
637 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
638 USE_KERBEROS_KEYTAB
) ) {
639 bool destroy_vuid
= True
;
640 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
641 vuid
, &destroy_vuid
);
642 data_blob_free(&secblob
);
644 /* Kill the intermediate vuid */
645 invalidate_vuid(sconn
, vuid
);
647 TALLOC_FREE(kerb_mech
);
652 TALLOC_FREE(*auth_ntlmssp_state
);
655 data_blob_free(&secblob
);
656 /* The mechtoken is a krb5 ticket, but
657 * we need to fall back to NTLM. */
658 reply_spnego_downgrade_to_ntlmssp(req
, vuid
);
659 TALLOC_FREE(kerb_mech
);
663 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
664 if (!NT_STATUS_IS_OK(status
)) {
665 /* Kill the intermediate vuid */
666 invalidate_vuid(sconn
, vuid
);
667 reply_nterror(req
, nt_status_squash(status
));
671 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
674 data_blob_free(&secblob
);
676 reply_spnego_ntlmssp(req
, vuid
, auth_ntlmssp_state
,
677 &chal
, status
, OID_NTLMSSP
, true);
679 data_blob_free(&chal
);
681 /* already replied */
685 /****************************************************************************
686 Reply to a session setup spnego auth packet.
687 ****************************************************************************/
689 static void reply_spnego_auth(struct smb_request
*req
,
692 struct auth_ntlmssp_state
**auth_ntlmssp_state
)
694 DATA_BLOB auth
= data_blob_null
;
695 DATA_BLOB auth_reply
= data_blob_null
;
696 DATA_BLOB secblob
= data_blob_null
;
697 NTSTATUS status
= NT_STATUS_LOGON_FAILURE
;
698 struct smbd_server_connection
*sconn
= req
->sconn
;
700 if (!spnego_parse_auth(talloc_tos(), blob1
, &auth
)) {
702 file_save("auth.dat", blob1
.data
, blob1
.length
);
704 /* Kill the intermediate vuid */
705 invalidate_vuid(sconn
, vuid
);
707 reply_nterror(req
, nt_status_squash(
708 NT_STATUS_LOGON_FAILURE
));
712 if (auth
.data
[0] == ASN1_APPLICATION(0)) {
713 /* Might be a second negTokenTarg packet */
714 char *kerb_mech
= NULL
;
716 status
= parse_spnego_mechanisms(talloc_tos(),
717 auth
, &secblob
, &kerb_mech
);
719 if (!NT_STATUS_IS_OK(status
)) {
720 /* Kill the intermediate vuid */
721 invalidate_vuid(sconn
, vuid
);
722 reply_nterror(req
, nt_status_squash(status
));
726 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
727 (unsigned long)secblob
.length
));
729 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
730 USE_KERBEROS_KEYTAB
)) {
731 bool destroy_vuid
= True
;
732 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
733 vuid
, &destroy_vuid
);
734 data_blob_free(&secblob
);
735 data_blob_free(&auth
);
737 /* Kill the intermediate vuid */
738 invalidate_vuid(sconn
, vuid
);
740 TALLOC_FREE(kerb_mech
);
744 /* Can't blunder into NTLMSSP auth if we have
748 /* Kill the intermediate vuid */
749 invalidate_vuid(sconn
, vuid
);
750 DEBUG(3,("reply_spnego_auth: network "
751 "misconfiguration, client sent us a "
752 "krb5 ticket and kerberos security "
754 reply_nterror(req
, nt_status_squash(
755 NT_STATUS_LOGON_FAILURE
));
756 TALLOC_FREE(kerb_mech
);
760 /* If we get here it wasn't a negTokenTarg auth packet. */
761 data_blob_free(&secblob
);
763 if (!*auth_ntlmssp_state
) {
764 status
= auth_ntlmssp_start(auth_ntlmssp_state
);
765 if (!NT_STATUS_IS_OK(status
)) {
766 /* Kill the intermediate vuid */
767 invalidate_vuid(sconn
, vuid
);
768 reply_nterror(req
, nt_status_squash(status
));
773 status
= auth_ntlmssp_update(*auth_ntlmssp_state
,
776 data_blob_free(&auth
);
778 /* Don't send the mechid as we've already sent this (RFC4178). */
780 reply_spnego_ntlmssp(req
, vuid
,
782 &auth_reply
, status
, NULL
, true);
784 data_blob_free(&auth_reply
);
786 /* and tell smbd that we have already replied to this packet */
790 /****************************************************************************
791 Delete an entry on the list.
792 ****************************************************************************/
794 static void delete_partial_auth(struct smbd_server_connection
*sconn
,
795 struct pending_auth_data
*pad
)
800 DLIST_REMOVE(sconn
->smb1
.pd_list
, pad
);
801 data_blob_free(&pad
->partial_data
);
805 /****************************************************************************
806 Search for a partial SPNEGO auth fragment matching an smbpid.
807 ****************************************************************************/
809 static struct pending_auth_data
*get_pending_auth_data(
810 struct smbd_server_connection
*sconn
,
813 struct pending_auth_data
*pad
;
815 * NOTE: using the smbpid here is completely wrong...
817 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
819 for (pad
= sconn
->smb1
.pd_list
; pad
; pad
= pad
->next
) {
820 if (pad
->smbpid
== smbpid
) {
827 /****************************************************************************
828 Check the size of an SPNEGO blob. If we need more return
829 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
830 the blob to be more than 64k.
831 ****************************************************************************/
833 static NTSTATUS
check_spnego_blob_complete(struct smbd_server_connection
*sconn
,
834 uint16 smbpid
, uint16 vuid
,
837 struct pending_auth_data
*pad
= NULL
;
839 size_t needed_len
= 0;
841 pad
= get_pending_auth_data(sconn
, smbpid
);
843 /* Ensure we have some data. */
844 if (pblob
->length
== 0) {
845 /* Caller can cope. */
846 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
847 delete_partial_auth(sconn
, pad
);
851 /* Were we waiting for more data ? */
854 size_t copy_len
= MIN(65536, pblob
->length
);
856 /* Integer wrap paranoia.... */
858 if (pad
->partial_data
.length
+ copy_len
<
859 pad
->partial_data
.length
||
860 pad
->partial_data
.length
+ copy_len
< copy_len
) {
862 DEBUG(2,("check_spnego_blob_complete: integer wrap "
863 "pad->partial_data.length = %u, "
865 (unsigned int)pad
->partial_data
.length
,
866 (unsigned int)copy_len
));
868 delete_partial_auth(sconn
, pad
);
869 return NT_STATUS_INVALID_PARAMETER
;
872 DEBUG(10,("check_spnego_blob_complete: "
873 "pad->partial_data.length = %u, "
874 "pad->needed_len = %u, "
876 "pblob->length = %u,\n",
877 (unsigned int)pad
->partial_data
.length
,
878 (unsigned int)pad
->needed_len
,
879 (unsigned int)copy_len
,
880 (unsigned int)pblob
->length
));
882 tmp_blob
= data_blob(NULL
,
883 pad
->partial_data
.length
+ copy_len
);
885 /* Concatenate the two (up to copy_len) bytes. */
886 memcpy(tmp_blob
.data
,
887 pad
->partial_data
.data
,
888 pad
->partial_data
.length
);
889 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
893 /* Replace the partial data. */
894 data_blob_free(&pad
->partial_data
);
895 pad
->partial_data
= tmp_blob
;
896 ZERO_STRUCT(tmp_blob
);
899 if (pblob
->length
>= pad
->needed_len
) {
900 /* Yes, replace pblob. */
901 data_blob_free(pblob
);
902 *pblob
= pad
->partial_data
;
903 ZERO_STRUCT(pad
->partial_data
);
904 delete_partial_auth(sconn
, pad
);
908 /* Still need more data. */
909 pad
->needed_len
-= copy_len
;
910 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
913 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
914 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
915 /* Not something we can determine the
921 /* This is a new SPNEGO sessionsetup - see if
922 * the data given in this blob is enough.
925 data
= asn1_init(NULL
);
927 return NT_STATUS_NO_MEMORY
;
930 asn1_load(data
, *pblob
);
931 asn1_start_tag(data
, pblob
->data
[0]);
932 if (data
->has_error
|| data
->nesting
== NULL
) {
934 /* Let caller catch. */
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. */
969 /* Refuse the blob if it's bigger than 64k. */
970 if (needed_len
> 65536) {
971 DEBUG(2,("check_spnego_blob_complete: needed_len "
973 (unsigned int)needed_len
));
974 return NT_STATUS_INVALID_PARAMETER
;
977 /* We must store this blob until complete. */
978 if (!(pad
= SMB_MALLOC_P(struct pending_auth_data
))) {
979 return NT_STATUS_NO_MEMORY
;
981 pad
->needed_len
= needed_len
- pblob
->length
;
982 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
983 if (pad
->partial_data
.data
== NULL
) {
985 return NT_STATUS_NO_MEMORY
;
987 pad
->smbpid
= smbpid
;
989 DLIST_ADD(sconn
->smb1
.pd_list
, pad
);
991 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
994 /****************************************************************************
995 Reply to a session setup command.
996 conn POINTER CAN BE NULL HERE !
997 ****************************************************************************/
999 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
1005 const char *native_os
;
1006 const char *native_lanman
;
1007 const char *primary_domain
;
1009 uint16 data_blob_len
= SVAL(req
->vwv
+7, 0);
1010 enum remote_arch_types ra_type
= get_remote_arch();
1011 int vuid
= req
->vuid
;
1012 user_struct
*vuser
= NULL
;
1013 NTSTATUS status
= NT_STATUS_OK
;
1014 uint16 smbpid
= req
->smbpid
;
1015 struct smbd_server_connection
*sconn
= req
->sconn
;
1017 DEBUG(3,("Doing spnego session setup\n"));
1019 if (global_client_caps
== 0) {
1020 global_client_caps
= IVAL(req
->vwv
+10, 0);
1022 if (!(global_client_caps
& CAP_STATUS32
)) {
1023 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1030 if (data_blob_len
== 0) {
1031 /* an invalid request */
1032 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1036 bufrem
= smbreq_bufrem(req
, p
);
1037 /* pull the spnego blob */
1038 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
1041 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
1044 p2
= (char *)req
->buf
+ blob1
.length
;
1046 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1048 native_os
= tmp
? tmp
: "";
1050 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1052 native_lanman
= tmp
? tmp
: "";
1054 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1056 primary_domain
= tmp
? tmp
: "";
1058 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1059 native_os
, native_lanman
, primary_domain
));
1061 if ( ra_type
== RA_WIN2K
) {
1062 /* Vista sets neither the OS or lanman strings */
1064 if ( !strlen(native_os
) && !strlen(native_lanman
) )
1065 set_remote_arch(RA_VISTA
);
1067 /* Windows 2003 doesn't set the native lanman string,
1068 but does set primary domain which is a bug I think */
1070 if ( !strlen(native_lanman
) ) {
1071 ra_lanman_string( primary_domain
);
1073 ra_lanman_string( native_lanman
);
1075 } else if ( ra_type
== RA_VISTA
) {
1076 if ( strncmp(native_os
, "Mac OS X", 8) == 0 ) {
1077 set_remote_arch(RA_OSX
);
1081 /* Did we get a valid vuid ? */
1082 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1083 /* No, then try and see if this is an intermediate sessionsetup
1084 * for a large SPNEGO packet. */
1085 struct pending_auth_data
*pad
;
1086 pad
= get_pending_auth_data(sconn
, smbpid
);
1088 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1089 "pending vuid %u\n",
1090 (unsigned int)pad
->vuid
));
1095 /* Do we have a valid vuid now ? */
1096 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1097 /* No, start a new authentication setup. */
1098 vuid
= register_initial_vuid(sconn
);
1099 if (vuid
== UID_FIELD_INVALID
) {
1100 data_blob_free(&blob1
);
1101 reply_nterror(req
, nt_status_squash(
1102 NT_STATUS_INVALID_PARAMETER
));
1107 vuser
= get_partial_auth_user_struct(sconn
, vuid
);
1108 /* This MUST be valid. */
1110 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1113 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1114 * sessionsetup requests as the Windows limit on the security blob
1115 * field is 4k. Bug #4400. JRA.
1118 status
= check_spnego_blob_complete(sconn
, smbpid
, vuid
, &blob1
);
1119 if (!NT_STATUS_IS_OK(status
)) {
1120 if (!NT_STATUS_EQUAL(status
,
1121 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1122 /* Real error - kill the intermediate vuid */
1123 invalidate_vuid(sconn
, vuid
);
1125 data_blob_free(&blob1
);
1126 reply_nterror(req
, nt_status_squash(status
));
1130 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
1132 /* its a negTokenTarg packet */
1134 reply_spnego_negotiate(req
, vuid
, blob1
,
1135 &vuser
->auth_ntlmssp_state
);
1136 data_blob_free(&blob1
);
1140 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
1142 /* its a auth packet */
1144 reply_spnego_auth(req
, vuid
, blob1
,
1145 &vuser
->auth_ntlmssp_state
);
1146 data_blob_free(&blob1
);
1150 if (strncmp((char *)(blob1
.data
), "NTLMSSP", 7) == 0) {
1153 if (!vuser
->auth_ntlmssp_state
) {
1154 status
= auth_ntlmssp_start(&vuser
->auth_ntlmssp_state
);
1155 if (!NT_STATUS_IS_OK(status
)) {
1156 /* Kill the intermediate vuid */
1157 invalidate_vuid(sconn
, vuid
);
1158 data_blob_free(&blob1
);
1159 reply_nterror(req
, nt_status_squash(status
));
1164 status
= auth_ntlmssp_update(vuser
->auth_ntlmssp_state
,
1167 data_blob_free(&blob1
);
1169 reply_spnego_ntlmssp(req
, vuid
,
1170 &vuser
->auth_ntlmssp_state
,
1171 &chal
, status
, OID_NTLMSSP
, false);
1172 data_blob_free(&chal
);
1176 /* what sort of packet is this? */
1177 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1179 data_blob_free(&blob1
);
1181 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1184 /****************************************************************************
1185 On new VC == 0, shutdown *all* old connections and users.
1186 It seems that only NT4.x does this. At W2K and above (XP etc.).
1187 a new session setup with VC==0 is ignored.
1188 ****************************************************************************/
1190 struct shutdown_state
{
1192 struct messaging_context
*msg_ctx
;
1195 static int shutdown_other_smbds(const struct connections_key
*key
,
1196 const struct connections_data
*crec
,
1199 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
1201 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1202 procid_str(talloc_tos(), &crec
->pid
), crec
->addr
));
1204 if (!process_exists(crec
->pid
)) {
1205 DEBUG(10, ("process does not exist\n"));
1209 if (procid_is_me(&crec
->pid
)) {
1210 DEBUG(10, ("It's me\n"));
1214 if (strcmp(state
->ip
, crec
->addr
) != 0) {
1215 DEBUG(10, ("%s does not match %s\n", state
->ip
, crec
->addr
));
1219 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1220 "(IP %s)\n", (unsigned int)procid_to_pid(&crec
->pid
),
1223 messaging_send(state
->msg_ctx
, crec
->pid
, MSG_SHUTDOWN
,
1228 static void setup_new_vc_session(struct smbd_server_connection
*sconn
)
1230 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1231 "compatible we would close all old resources.\n"));
1234 invalidate_all_vuids();
1236 if (lp_reset_on_zero_vc()) {
1238 struct shutdown_state state
;
1240 addr
= tsocket_address_inet_addr_string(
1241 sconn
->remote_address
, talloc_tos());
1246 state
.msg_ctx
= sconn
->msg_ctx
;
1247 connections_forall_read(shutdown_other_smbds
, &state
);
1252 /****************************************************************************
1253 Reply to a session setup command.
1254 ****************************************************************************/
1256 void reply_sesssetup_and_X(struct smb_request
*req
)
1262 DATA_BLOB plaintext_password
;
1265 fstring sub_user
; /* Sanitised username for substituion */
1267 const char *native_os
;
1268 const char *native_lanman
;
1269 const char *primary_domain
;
1270 struct auth_usersupplied_info
*user_info
= NULL
;
1271 struct auth_serversupplied_info
*server_info
= NULL
;
1272 struct auth_serversupplied_info
*session_info
= NULL
;
1273 uint16 smb_flag2
= req
->flags2
;
1276 struct smbd_server_connection
*sconn
= req
->sconn
;
1278 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
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 /* a SPNEGO session setup has 12 command words, whereas a normal
1289 NT1 session setup has 13. See the cifs spec. */
1290 if (req
->wct
== 12 &&
1291 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
1293 if (!sconn
->smb1
.negprot
.spnego
) {
1294 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1295 "at SPNEGO session setup when it was not "
1297 reply_nterror(req
, nt_status_squash(
1298 NT_STATUS_LOGON_FAILURE
));
1299 END_PROFILE(SMBsesssetupX
);
1303 if (SVAL(req
->vwv
+4, 0) == 0) {
1304 setup_new_vc_session(req
->sconn
);
1307 reply_sesssetup_and_X_spnego(req
);
1308 END_PROFILE(SMBsesssetupX
);
1312 smb_bufsize
= SVAL(req
->vwv
+2, 0);
1314 if (get_Protocol() < PROTOCOL_NT1
) {
1315 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1317 /* Never do NT status codes with protocols before NT1 as we
1318 * don't get client caps. */
1319 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1321 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
1322 reply_nterror(req
, nt_status_squash(
1323 NT_STATUS_INVALID_PARAMETER
));
1324 END_PROFILE(SMBsesssetupX
);
1329 lm_resp
= data_blob(req
->buf
, passlen1
);
1331 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
1332 /* Ensure null termination */
1333 plaintext_password
.data
[passlen1
] = 0;
1336 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
1337 req
->buf
+ passlen1
, STR_TERMINATE
);
1338 user
= tmp
? tmp
: "";
1343 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1344 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
1345 enum remote_arch_types ra_type
= get_remote_arch();
1346 const uint8_t *p
= req
->buf
;
1347 const uint8_t *save_p
= req
->buf
;
1351 if(global_client_caps
== 0) {
1352 global_client_caps
= IVAL(req
->vwv
+11, 0);
1354 if (!(global_client_caps
& CAP_STATUS32
)) {
1355 remove_from_common_flags2(
1356 FLAGS2_32_BIT_ERROR_CODES
);
1359 /* client_caps is used as final determination if
1360 * client is NT or Win95. This is needed to return
1361 * the correct error codes in some circumstances.
1364 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
1365 ra_type
== RA_WIN95
) {
1366 if(!(global_client_caps
& (CAP_NT_SMBS
|
1368 set_remote_arch( RA_WIN95
);
1374 /* both Win95 and WinNT stuff up the password
1375 * lengths for non-encrypting systems. Uggh.
1377 if passlen1==24 its a win95 system, and its setting
1378 the password length incorrectly. Luckily it still
1379 works with the default code because Win95 will null
1380 terminate the password anyway
1382 if passlen1>0 and passlen2>0 then maybe its a NT box
1383 and its setting passlen2 to some random value which
1384 really stuffs things up. we need to fix that one. */
1386 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
1392 /* check for nasty tricks */
1393 if (passlen1
> MAX_PASS_LEN
1394 || passlen1
> smbreq_bufrem(req
, p
)) {
1395 reply_nterror(req
, nt_status_squash(
1396 NT_STATUS_INVALID_PARAMETER
));
1397 END_PROFILE(SMBsesssetupX
);
1401 if (passlen2
> MAX_PASS_LEN
1402 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
1403 reply_nterror(req
, nt_status_squash(
1404 NT_STATUS_INVALID_PARAMETER
));
1405 END_PROFILE(SMBsesssetupX
);
1409 /* Save the lanman2 password and the NT md4 password. */
1411 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1416 lm_resp
= data_blob(p
, passlen1
);
1417 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1418 } else if (lp_security() != SEC_SHARE
) {
1420 * In share level we should ignore any passwords, so
1421 * only read them if we're not.
1424 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
1426 if (unic
&& (passlen2
== 0) && passlen1
) {
1427 /* Only a ascii plaintext password was sent. */
1428 (void)srvstr_pull_talloc(talloc_tos(),
1434 STR_TERMINATE
|STR_ASCII
);
1436 (void)srvstr_pull_talloc(talloc_tos(),
1441 unic
? passlen2
: passlen1
,
1445 reply_nterror(req
, nt_status_squash(
1446 NT_STATUS_INVALID_PARAMETER
));
1447 END_PROFILE(SMBsesssetupX
);
1450 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1453 p
+= passlen1
+ passlen2
;
1455 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1457 user
= tmp
? tmp
: "";
1459 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1461 domain
= tmp
? tmp
: "";
1463 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1465 native_os
= tmp
? tmp
: "";
1467 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1469 native_lanman
= tmp
? tmp
: "";
1471 /* not documented or decoded by Ethereal but there is one more
1472 * string in the extra bytes which is the same as the
1473 * PrimaryDomain when using extended security. Windows NT 4
1474 * and 2003 use this string to store the native lanman string.
1475 * Windows 9x does not include a string here at all so we have
1476 * to check if we have any extra bytes left */
1478 byte_count
= SVAL(req
->vwv
+13, 0);
1479 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
1480 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1482 primary_domain
= tmp
? tmp
: "";
1484 primary_domain
= talloc_strdup(talloc_tos(), "null");
1487 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1488 "PrimaryDomain=[%s]\n",
1489 domain
, native_os
, native_lanman
, primary_domain
));
1491 if ( ra_type
== RA_WIN2K
) {
1492 if ( strlen(native_lanman
) == 0 )
1493 ra_lanman_string( primary_domain
);
1495 ra_lanman_string( native_lanman
);
1500 if (SVAL(req
->vwv
+4, 0) == 0) {
1501 setup_new_vc_session(req
->sconn
);
1504 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1505 domain
, user
, get_remote_machine_name()));
1508 if (sconn
->smb1
.negprot
.spnego
) {
1510 /* This has to be here, because this is a perfectly
1511 * valid behaviour for guest logons :-( */
1513 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1514 "at 'normal' session setup after "
1515 "negotiating spnego.\n"));
1516 reply_nterror(req
, nt_status_squash(
1517 NT_STATUS_LOGON_FAILURE
));
1518 END_PROFILE(SMBsesssetupX
);
1521 fstrcpy(sub_user
, user
);
1523 fstrcpy(sub_user
, lp_guestaccount());
1526 sub_set_smb_name(sub_user
);
1528 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
1530 if (lp_security() == SEC_SHARE
) {
1531 char *sub_user_mapped
= NULL
;
1532 /* In share level we should ignore any passwords */
1534 data_blob_free(&lm_resp
);
1535 data_blob_free(&nt_resp
);
1536 data_blob_clear_free(&plaintext_password
);
1538 (void)map_username(talloc_tos(), sub_user
, &sub_user_mapped
);
1539 if (!sub_user_mapped
) {
1540 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1541 END_PROFILE(SMBsesssetupX
);
1544 fstrcpy(sub_user
, sub_user_mapped
);
1545 add_session_user(sconn
, sub_user
);
1546 add_session_workgroup(sconn
, domain
);
1547 /* Then force it to null for the benfit of the code below */
1553 nt_status
= check_guest_password(&server_info
);
1555 } else if (doencrypt
) {
1556 struct auth_context
*negprot_auth_context
= NULL
;
1557 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
1558 if (!negprot_auth_context
) {
1559 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1560 "session setup without negprot denied!\n"));
1561 reply_nterror(req
, nt_status_squash(
1562 NT_STATUS_LOGON_FAILURE
));
1563 END_PROFILE(SMBsesssetupX
);
1566 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
1569 if (NT_STATUS_IS_OK(nt_status
)) {
1570 nt_status
= negprot_auth_context
->check_ntlm_password(
1571 negprot_auth_context
,
1576 struct auth_context
*plaintext_auth_context
= NULL
;
1578 nt_status
= make_auth_context_subsystem(
1579 talloc_tos(), &plaintext_auth_context
);
1581 if (NT_STATUS_IS_OK(nt_status
)) {
1584 plaintext_auth_context
->get_ntlm_challenge(
1585 plaintext_auth_context
, chal
);
1587 if (!make_user_info_for_reply(&user_info
,
1589 plaintext_password
)) {
1590 nt_status
= NT_STATUS_NO_MEMORY
;
1593 if (NT_STATUS_IS_OK(nt_status
)) {
1594 nt_status
= plaintext_auth_context
->check_ntlm_password(
1595 plaintext_auth_context
,
1599 TALLOC_FREE(plaintext_auth_context
);
1604 free_user_info(&user_info
);
1606 if (!NT_STATUS_IS_OK(nt_status
)) {
1607 nt_status
= do_map_to_guest(nt_status
, &server_info
,
1611 if (!NT_STATUS_IS_OK(nt_status
)) {
1612 data_blob_free(&nt_resp
);
1613 data_blob_free(&lm_resp
);
1614 data_blob_clear_free(&plaintext_password
);
1615 reply_nterror(req
, nt_status_squash(nt_status
));
1616 END_PROFILE(SMBsesssetupX
);
1620 nt_status
= create_local_token(req
, server_info
, NULL
, &session_info
);
1621 TALLOC_FREE(server_info
);
1623 if (!NT_STATUS_IS_OK(nt_status
)) {
1624 DEBUG(10, ("create_local_token failed: %s\n",
1625 nt_errstr(nt_status
)));
1626 data_blob_free(&nt_resp
);
1627 data_blob_free(&lm_resp
);
1628 data_blob_clear_free(&plaintext_password
);
1629 reply_nterror(req
, nt_status_squash(nt_status
));
1630 END_PROFILE(SMBsesssetupX
);
1634 data_blob_clear_free(&plaintext_password
);
1636 /* it's ok - setup a reply */
1637 reply_outbuf(req
, 3, 0);
1638 if (get_Protocol() >= PROTOCOL_NT1
) {
1639 push_signature(&req
->outbuf
);
1640 /* perhaps grab OS version here?? */
1643 if (session_info
->guest
) {
1644 SSVAL(req
->outbuf
,smb_vwv2
,1);
1647 /* register the name and uid as being validated, so further connections
1648 to a uid can get through without a password, on the same VC */
1650 if (lp_security() == SEC_SHARE
) {
1651 sess_vuid
= UID_FIELD_INVALID
;
1652 TALLOC_FREE(session_info
);
1654 /* Ignore the initial vuid. */
1655 sess_vuid
= register_initial_vuid(sconn
);
1656 if (sess_vuid
== UID_FIELD_INVALID
) {
1657 data_blob_free(&nt_resp
);
1658 data_blob_free(&lm_resp
);
1659 reply_nterror(req
, nt_status_squash(
1660 NT_STATUS_LOGON_FAILURE
));
1661 END_PROFILE(SMBsesssetupX
);
1664 /* register_existing_vuid keeps the session_info */
1665 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
1667 nt_resp
.data
? nt_resp
: lm_resp
,
1669 if (sess_vuid
== UID_FIELD_INVALID
) {
1670 data_blob_free(&nt_resp
);
1671 data_blob_free(&lm_resp
);
1672 reply_nterror(req
, nt_status_squash(
1673 NT_STATUS_LOGON_FAILURE
));
1674 END_PROFILE(SMBsesssetupX
);
1678 /* current_user_info is changed on new vuid */
1679 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
1682 data_blob_free(&nt_resp
);
1683 data_blob_free(&lm_resp
);
1685 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1686 SSVAL(req
->inbuf
,smb_uid
,sess_vuid
);
1687 req
->vuid
= sess_vuid
;
1689 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
1690 sconn
->smb1
.sessions
.max_send
=
1691 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
1693 sconn
->smb1
.sessions
.done_sesssetup
= true;
1695 END_PROFILE(SMBsesssetupX
);