2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "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"
39 #include "auth/gensec/gensec.h"
41 /* For split krb5 SPNEGO blobs. */
42 struct pending_auth_data
{
43 struct pending_auth_data
*prev
, *next
;
44 uint16 vuid
; /* Tag for this entry. */
45 uint16 smbpid
; /* Alternate tag for this entry. */
47 DATA_BLOB partial_data
;
50 /****************************************************************************
51 Add the standard 'Samba' signature to the end of the session setup.
52 ****************************************************************************/
54 static int push_signature(uint8
**outbuf
)
61 tmp
= message_push_string(outbuf
, "Unix", STR_TERMINATE
);
63 if (tmp
== -1) return -1;
66 if (asprintf(&lanman
, "Samba %s", samba_version_string()) != -1) {
67 tmp
= message_push_string(outbuf
, lanman
, STR_TERMINATE
);
71 tmp
= message_push_string(outbuf
, "Samba", STR_TERMINATE
);
74 if (tmp
== -1) return -1;
77 tmp
= message_push_string(outbuf
, lp_workgroup(), STR_TERMINATE
);
79 if (tmp
== -1) return -1;
85 /****************************************************************************
86 Send a security blob via a session setup reply.
87 ****************************************************************************/
89 static void reply_sesssetup_blob(struct smb_request
*req
,
93 if (!NT_STATUS_IS_OK(nt_status
) &&
94 !NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
95 reply_nterror(req
, nt_status_squash(nt_status
));
99 nt_status
= nt_status_squash(nt_status
);
100 SIVAL(req
->outbuf
, smb_rcls
, NT_STATUS_V(nt_status
));
101 SSVAL(req
->outbuf
, smb_vwv0
, 0xFF); /* no chaining possible */
102 SSVAL(req
->outbuf
, smb_vwv3
, blob
.length
);
104 if ((message_push_blob(&req
->outbuf
, blob
) == -1)
105 || (push_signature(&req
->outbuf
) == -1)) {
106 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
110 /****************************************************************************
111 Do a 'guest' logon, getting back the
112 ****************************************************************************/
114 static NTSTATUS
check_guest_password(const struct tsocket_address
*remote_address
,
115 struct auth_serversupplied_info
**server_info
)
117 struct auth_context
*auth_context
;
118 struct auth_usersupplied_info
*user_info
= NULL
;
121 static unsigned char chal
[8] = { 0, };
123 DEBUG(3,("Got anonymous request\n"));
125 nt_status
= make_auth_context_fixed(talloc_tos(), &auth_context
, chal
);
126 if (!NT_STATUS_IS_OK(nt_status
)) {
130 if (!make_user_info_guest(remote_address
, &user_info
)) {
131 TALLOC_FREE(auth_context
);
132 return NT_STATUS_NO_MEMORY
;
135 nt_status
= auth_context
->check_ntlm_password(auth_context
,
138 TALLOC_FREE(auth_context
);
139 free_user_info(&user_info
);
147 /* Experiment that failed. See "only happens with a KDC" comment below. */
148 /****************************************************************************
149 Cerate a clock skew error blob for a Windows client.
150 ****************************************************************************/
152 static bool make_krb5_skew_error(DATA_BLOB
*pblob_out
)
154 krb5_context context
= NULL
;
155 krb5_error_code kerr
= 0;
157 krb5_principal host_princ
= NULL
;
158 char *host_princ_s
= NULL
;
161 *pblob_out
= data_blob_null
;
163 initialize_krb5_error_table();
164 kerr
= krb5_init_context(&context
);
168 /* Create server principal. */
169 asprintf(&host_princ_s
, "%s$@%s", lp_netbios_name(), lp_realm());
173 strlower_m(host_princ_s
);
175 kerr
= smb_krb5_parse_name(context
, host_princ_s
, &host_princ
);
177 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
178 "for name %s: Error %s\n",
179 host_princ_s
, error_message(kerr
) ));
183 kerr
= smb_krb5_mk_error(context
, KRB5KRB_AP_ERR_SKEW
,
186 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
187 "failed: Error %s\n",
188 error_message(kerr
) ));
192 *pblob_out
= data_blob(reply
.data
, reply
.length
);
193 kerberos_free_data_contents(context
,&reply
);
199 SAFE_FREE(host_princ_s
);
202 krb5_free_principal(context
, host_princ
);
204 krb5_free_context(context
);
209 /****************************************************************************
210 Reply to a session setup spnego negotiate packet for kerberos.
211 ****************************************************************************/
213 static void reply_spnego_kerberos(struct smb_request
*req
,
217 bool *p_invalidate_vuid
)
222 int sess_vuid
= req
->vuid
;
223 NTSTATUS ret
= NT_STATUS_OK
;
224 DATA_BLOB ap_rep
, ap_rep_wrapped
, response
;
225 struct auth_session_info
*session_info
= NULL
;
226 DATA_BLOB session_key
= data_blob_null
;
228 DATA_BLOB nullblob
= data_blob_null
;
229 bool map_domainuser_to_guest
= False
;
230 bool username_was_mapped
;
231 struct PAC_LOGON_INFO
*logon_info
= NULL
;
232 struct smbd_server_connection
*sconn
= req
->sconn
;
240 ZERO_STRUCT(ap_rep_wrapped
);
241 ZERO_STRUCT(response
);
243 /* Normally we will always invalidate the intermediate vuid. */
244 *p_invalidate_vuid
= True
;
246 mem_ctx
= talloc_init("reply_spnego_kerberos");
247 if (mem_ctx
== NULL
) {
248 reply_nterror(req
, nt_status_squash(NT_STATUS_NO_MEMORY
));
252 if (!spnego_parse_krb5_wrap(mem_ctx
, *secblob
, &ticket
, tok_id
)) {
253 talloc_destroy(mem_ctx
);
254 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
258 ret
= ads_verify_ticket(mem_ctx
, lp_realm(), 0, &ticket
,
259 &principal
, &logon_info
, &ap_rep
,
262 data_blob_free(&ticket
);
264 if (!NT_STATUS_IS_OK(ret
)) {
266 /* Experiment that failed.
267 * See "only happens with a KDC" comment below. */
269 if (NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
272 * Windows in this case returns
273 * NT_STATUS_MORE_PROCESSING_REQUIRED
274 * with a negTokenTarg blob containing an krb5_error
275 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
276 * The client then fixes its clock and continues rather
277 * than giving an error. JRA.
278 * -- Looks like this only happens with a KDC. JRA.
281 bool ok
= make_krb5_skew_error(&ap_rep
);
283 talloc_destroy(mem_ctx
);
284 return ERROR_NT(nt_status_squash(
285 NT_STATUS_LOGON_FAILURE
));
287 ap_rep_wrapped
= spnego_gen_krb5_wrap(ap_rep
,
289 response
= spnego_gen_auth_response(&ap_rep_wrapped
,
290 ret
, OID_KERBEROS5_OLD
);
291 reply_sesssetup_blob(conn
, inbuf
, outbuf
, response
,
292 NT_STATUS_MORE_PROCESSING_REQUIRED
);
295 * In this one case we don't invalidate the
296 * intermediate vuid as we're expecting the client
297 * to re-use it for the next sessionsetupX packet. JRA.
300 *p_invalidate_vuid
= False
;
302 data_blob_free(&ap_rep
);
303 data_blob_free(&ap_rep_wrapped
);
304 data_blob_free(&response
);
305 talloc_destroy(mem_ctx
);
306 return -1; /* already replied */
309 if (!NT_STATUS_EQUAL(ret
, NT_STATUS_TIME_DIFFERENCE_AT_DC
)) {
310 ret
= NT_STATUS_LOGON_FAILURE
;
313 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
315 talloc_destroy(mem_ctx
);
316 reply_nterror(req
, nt_status_squash(ret
));
320 ret
= get_user_from_kerberos_info(talloc_tos(),
321 sconn
->remote_hostname
,
322 principal
, logon_info
,
323 &username_was_mapped
,
324 &map_domainuser_to_guest
,
326 &real_username
, &pw
);
327 if (!NT_STATUS_IS_OK(ret
)) {
328 data_blob_free(&ap_rep
);
329 data_blob_free(&session_key
);
330 talloc_destroy(mem_ctx
);
331 reply_nterror(req
,nt_status_squash(NT_STATUS_LOGON_FAILURE
));
335 /* save the PAC data if we have it */
337 netsamlogon_cache_store(user
, &logon_info
->info3
);
340 /* setup the string used by %U */
341 sub_set_smb_name(real_username
);
343 /* reload services so that the new %U is taken into account */
344 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
346 ret
= make_session_info_krb5(mem_ctx
,
347 user
, domain
, real_username
, pw
,
348 logon_info
, map_domainuser_to_guest
,
352 data_blob_free(&session_key
);
353 if (!NT_STATUS_IS_OK(ret
)) {
354 DEBUG(1, ("make_server_info_krb5 failed!\n"));
355 data_blob_free(&ap_rep
);
356 TALLOC_FREE(mem_ctx
);
357 reply_nterror(req
, nt_status_squash(ret
));
361 if (!is_partial_auth_vuid(sconn
, sess_vuid
)) {
362 sess_vuid
= register_initial_vuid(sconn
);
365 /* register_existing_vuid keeps the server info */
366 /* register_existing_vuid takes ownership of session_key on success,
367 * no need to free after this on success. A better interface would copy
370 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
371 session_info
, nullblob
);
373 reply_outbuf(req
, 4, 0);
374 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
376 if (sess_vuid
== UID_FIELD_INVALID
) {
377 ret
= NT_STATUS_LOGON_FAILURE
;
379 /* current_user_info is changed on new vuid */
380 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
382 SSVAL(req
->outbuf
, smb_vwv3
, 0);
384 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
385 SSVAL(req
->outbuf
,smb_vwv2
,1);
388 SSVAL(req
->outbuf
, smb_uid
, sess_vuid
);
390 /* Successful logon. Keep this vuid. */
391 *p_invalidate_vuid
= False
;
394 /* wrap that up in a nice GSS-API wrapping */
395 if (NT_STATUS_IS_OK(ret
)) {
396 ap_rep_wrapped
= spnego_gen_krb5_wrap(talloc_tos(), ap_rep
,
399 ap_rep_wrapped
= data_blob_null
;
401 response
= spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped
, ret
,
403 reply_sesssetup_blob(req
, response
, ret
);
405 data_blob_free(&ap_rep
);
406 data_blob_free(&ap_rep_wrapped
);
407 data_blob_free(&response
);
408 TALLOC_FREE(mem_ctx
);
413 /****************************************************************************
414 Send a session setup reply, wrapped in SPNEGO.
415 Get vuid and check first.
416 End the NTLMSSP exchange context if we are OK/complete fail
417 This should be split into two functions, one to handle each
418 leg of the NTLM auth steps.
419 ***************************************************************************/
421 static void reply_spnego_ntlmssp(struct smb_request
*req
,
423 struct auth_ntlmssp_state
**auth_ntlmssp_state
,
424 DATA_BLOB
*ntlmssp_blob
, NTSTATUS nt_status
,
428 bool do_invalidate
= true;
430 struct auth_session_info
*session_info
= NULL
;
431 struct smbd_server_connection
*sconn
= req
->sconn
;
433 if (NT_STATUS_IS_OK(nt_status
)) {
434 nt_status
= gensec_session_info((*auth_ntlmssp_state
)->gensec_security
,
439 reply_outbuf(req
, 4, 0);
441 SSVAL(req
->outbuf
, smb_uid
, vuid
);
443 if (NT_STATUS_IS_OK(nt_status
)) {
444 DATA_BLOB nullblob
= data_blob_null
;
446 if (!is_partial_auth_vuid(sconn
, vuid
)) {
447 nt_status
= NT_STATUS_LOGON_FAILURE
;
451 /* register_existing_vuid keeps the server info */
452 if (register_existing_vuid(sconn
, vuid
,
453 session_info
, nullblob
) !=
455 /* The problem is, *auth_ntlmssp_state points
456 * into the vuser this will have
457 * talloc_free()'ed in
458 * register_existing_vuid() */
459 do_invalidate
= false;
460 nt_status
= NT_STATUS_LOGON_FAILURE
;
464 /* current_user_info is changed on new vuid */
465 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
467 SSVAL(req
->outbuf
, smb_vwv3
, 0);
469 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
470 SSVAL(req
->outbuf
,smb_vwv2
,1);
477 response
= spnego_gen_auth_response(talloc_tos(),
481 response
= *ntlmssp_blob
;
484 reply_sesssetup_blob(req
, response
, nt_status
);
486 data_blob_free(&response
);
489 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
490 and the other end, that we are not finished yet. */
492 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
493 /* NB. This is *NOT* an error case. JRA */
495 TALLOC_FREE(*auth_ntlmssp_state
);
496 if (!NT_STATUS_IS_OK(nt_status
)) {
497 /* Kill the intermediate vuid */
498 invalidate_vuid(sconn
, vuid
);
504 /****************************************************************************
505 Is this a krb5 mechanism ?
506 ****************************************************************************/
508 NTSTATUS
parse_spnego_mechanisms(TALLOC_CTX
*ctx
,
510 DATA_BLOB
*pblob_out
,
513 char *OIDs
[ASN1_MAX_OIDS
];
515 NTSTATUS ret
= NT_STATUS_OK
;
517 *kerb_mechOID
= NULL
;
519 /* parse out the OIDs and the first sec blob */
520 if (!spnego_parse_negTokenInit(ctx
, blob_in
, OIDs
, NULL
, pblob_out
) ||
522 return NT_STATUS_LOGON_FAILURE
;
525 /* only look at the first OID for determining the mechToken --
526 according to RFC2478, we should choose the one we want
527 and renegotiate, but i smell a client bug here..
529 Problem observed when connecting to a member (samba box)
530 of an AD domain as a user in a Samba domain. Samba member
531 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
532 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
533 NTLMSSP mechtoken. --jerry */
536 if (strcmp(OID_KERBEROS5
, OIDs
[0]) == 0 ||
537 strcmp(OID_KERBEROS5_OLD
, OIDs
[0]) == 0) {
538 *kerb_mechOID
= talloc_strdup(ctx
, OIDs
[0]);
539 if (*kerb_mechOID
== NULL
) {
540 ret
= NT_STATUS_NO_MEMORY
;
545 for (i
=0;OIDs
[i
];i
++) {
546 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs
[i
]));
547 talloc_free(OIDs
[i
]);
552 /****************************************************************************
553 Fall back from krb5 to NTLMSSP.
554 ****************************************************************************/
556 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request
*req
,
561 reply_outbuf(req
, 4, 0);
562 SSVAL(req
->outbuf
,smb_uid
,vuid
);
564 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
565 "but set to downgrade to NTLMSSP\n"));
567 response
= spnego_gen_auth_response(talloc_tos(), NULL
,
568 NT_STATUS_MORE_PROCESSING_REQUIRED
,
570 reply_sesssetup_blob(req
, response
, NT_STATUS_MORE_PROCESSING_REQUIRED
);
571 data_blob_free(&response
);
574 /****************************************************************************
575 Reply to a session setup spnego negotiate packet.
576 ****************************************************************************/
578 static void reply_spnego_negotiate(struct smb_request
*req
,
581 struct auth_ntlmssp_state
**auth_ntlmssp_state
)
585 char *kerb_mech
= NULL
;
587 struct smbd_server_connection
*sconn
= req
->sconn
;
589 status
= parse_spnego_mechanisms(talloc_tos(),
590 blob1
, &secblob
, &kerb_mech
);
591 if (!NT_STATUS_IS_OK(status
)) {
592 /* Kill the intermediate vuid */
593 invalidate_vuid(sconn
, vuid
);
594 reply_nterror(req
, nt_status_squash(status
));
598 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
599 (unsigned long)secblob
.length
));
602 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
603 USE_KERBEROS_KEYTAB
) ) {
604 bool destroy_vuid
= True
;
605 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
606 vuid
, &destroy_vuid
);
607 data_blob_free(&secblob
);
609 /* Kill the intermediate vuid */
610 invalidate_vuid(sconn
, vuid
);
612 TALLOC_FREE(kerb_mech
);
617 TALLOC_FREE(*auth_ntlmssp_state
);
620 data_blob_free(&secblob
);
621 /* The mechtoken is a krb5 ticket, but
622 * we need to fall back to NTLM. */
623 reply_spnego_downgrade_to_ntlmssp(req
, vuid
);
624 TALLOC_FREE(kerb_mech
);
628 status
= auth_ntlmssp_prepare(sconn
->remote_address
,
630 if (!NT_STATUS_IS_OK(status
)) {
631 /* Kill the intermediate vuid */
632 invalidate_vuid(sconn
, vuid
);
633 reply_nterror(req
, nt_status_squash(status
));
637 gensec_want_feature((*auth_ntlmssp_state
)->gensec_security
, GENSEC_FEATURE_SESSION_KEY
);
639 status
= auth_ntlmssp_start(*auth_ntlmssp_state
);
640 if (!NT_STATUS_IS_OK(status
)) {
641 /* Kill the intermediate vuid */
642 invalidate_vuid(sconn
, vuid
);
643 reply_nterror(req
, nt_status_squash(status
));
647 status
= gensec_update((*auth_ntlmssp_state
)->gensec_security
, talloc_tos(),
648 NULL
, secblob
, &chal
);
650 data_blob_free(&secblob
);
652 reply_spnego_ntlmssp(req
, vuid
, auth_ntlmssp_state
,
653 &chal
, status
, OID_NTLMSSP
, true);
655 data_blob_free(&chal
);
657 /* already replied */
661 /****************************************************************************
662 Reply to a session setup spnego auth packet.
663 ****************************************************************************/
665 static void reply_spnego_auth(struct smb_request
*req
,
668 struct auth_ntlmssp_state
**auth_ntlmssp_state
)
670 DATA_BLOB auth
= data_blob_null
;
671 DATA_BLOB auth_reply
= data_blob_null
;
672 DATA_BLOB secblob
= data_blob_null
;
673 NTSTATUS status
= NT_STATUS_LOGON_FAILURE
;
674 struct smbd_server_connection
*sconn
= req
->sconn
;
676 if (!spnego_parse_auth(talloc_tos(), blob1
, &auth
)) {
678 file_save("auth.dat", blob1
.data
, blob1
.length
);
680 /* Kill the intermediate vuid */
681 invalidate_vuid(sconn
, vuid
);
683 reply_nterror(req
, nt_status_squash(
684 NT_STATUS_LOGON_FAILURE
));
688 if (auth
.data
[0] == ASN1_APPLICATION(0)) {
689 /* Might be a second negTokenTarg packet */
690 char *kerb_mech
= NULL
;
692 status
= parse_spnego_mechanisms(talloc_tos(),
693 auth
, &secblob
, &kerb_mech
);
695 if (!NT_STATUS_IS_OK(status
)) {
696 /* Kill the intermediate vuid */
697 invalidate_vuid(sconn
, vuid
);
698 reply_nterror(req
, nt_status_squash(status
));
702 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
703 (unsigned long)secblob
.length
));
705 if (kerb_mech
&& ((lp_security()==SEC_ADS
) ||
706 USE_KERBEROS_KEYTAB
)) {
707 bool destroy_vuid
= True
;
708 reply_spnego_kerberos(req
, &secblob
, kerb_mech
,
709 vuid
, &destroy_vuid
);
710 data_blob_free(&secblob
);
711 data_blob_free(&auth
);
713 /* Kill the intermediate vuid */
714 invalidate_vuid(sconn
, vuid
);
716 TALLOC_FREE(kerb_mech
);
720 /* Can't blunder into NTLMSSP auth if we have
724 /* Kill the intermediate vuid */
725 invalidate_vuid(sconn
, vuid
);
726 DEBUG(3,("reply_spnego_auth: network "
727 "misconfiguration, client sent us a "
728 "krb5 ticket and kerberos security "
730 reply_nterror(req
, nt_status_squash(
731 NT_STATUS_LOGON_FAILURE
));
732 TALLOC_FREE(kerb_mech
);
736 /* If we get here it wasn't a negTokenTarg auth packet. */
737 data_blob_free(&secblob
);
739 if (!*auth_ntlmssp_state
) {
740 status
= auth_ntlmssp_prepare(sconn
->remote_address
,
742 if (!NT_STATUS_IS_OK(status
)) {
743 /* Kill the intermediate vuid */
744 invalidate_vuid(sconn
, vuid
);
745 reply_nterror(req
, nt_status_squash(status
));
749 gensec_want_feature((*auth_ntlmssp_state
)->gensec_security
, GENSEC_FEATURE_SESSION_KEY
);
751 status
= auth_ntlmssp_start(*auth_ntlmssp_state
);
752 if (!NT_STATUS_IS_OK(status
)) {
753 /* Kill the intermediate vuid */
754 invalidate_vuid(sconn
, vuid
);
755 reply_nterror(req
, nt_status_squash(status
));
760 status
= gensec_update((*auth_ntlmssp_state
)->gensec_security
, talloc_tos(),
761 NULL
, auth
, &auth_reply
);
763 data_blob_free(&auth
);
765 /* Don't send the mechid as we've already sent this (RFC4178). */
767 reply_spnego_ntlmssp(req
, vuid
,
769 &auth_reply
, status
, NULL
, true);
771 data_blob_free(&auth_reply
);
773 /* and tell smbd that we have already replied to this packet */
777 /****************************************************************************
778 Delete an entry on the list.
779 ****************************************************************************/
781 static void delete_partial_auth(struct smbd_server_connection
*sconn
,
782 struct pending_auth_data
*pad
)
787 DLIST_REMOVE(sconn
->smb1
.pd_list
, pad
);
788 data_blob_free(&pad
->partial_data
);
792 /****************************************************************************
793 Search for a partial SPNEGO auth fragment matching an smbpid.
794 ****************************************************************************/
796 static struct pending_auth_data
*get_pending_auth_data(
797 struct smbd_server_connection
*sconn
,
800 struct pending_auth_data
*pad
;
802 * NOTE: using the smbpid here is completely wrong...
804 * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
806 for (pad
= sconn
->smb1
.pd_list
; pad
; pad
= pad
->next
) {
807 if (pad
->smbpid
== smbpid
) {
814 /****************************************************************************
815 Check the size of an SPNEGO blob. If we need more return
816 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
817 the blob to be more than 64k.
818 ****************************************************************************/
820 static NTSTATUS
check_spnego_blob_complete(struct smbd_server_connection
*sconn
,
821 uint16 smbpid
, uint16 vuid
,
824 struct pending_auth_data
*pad
= NULL
;
826 size_t needed_len
= 0;
828 pad
= get_pending_auth_data(sconn
, smbpid
);
830 /* Ensure we have some data. */
831 if (pblob
->length
== 0) {
832 /* Caller can cope. */
833 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
834 delete_partial_auth(sconn
, pad
);
838 /* Were we waiting for more data ? */
841 size_t copy_len
= MIN(65536, pblob
->length
);
843 /* Integer wrap paranoia.... */
845 if (pad
->partial_data
.length
+ copy_len
<
846 pad
->partial_data
.length
||
847 pad
->partial_data
.length
+ copy_len
< copy_len
) {
849 DEBUG(2,("check_spnego_blob_complete: integer wrap "
850 "pad->partial_data.length = %u, "
852 (unsigned int)pad
->partial_data
.length
,
853 (unsigned int)copy_len
));
855 delete_partial_auth(sconn
, pad
);
856 return NT_STATUS_INVALID_PARAMETER
;
859 DEBUG(10,("check_spnego_blob_complete: "
860 "pad->partial_data.length = %u, "
861 "pad->needed_len = %u, "
863 "pblob->length = %u,\n",
864 (unsigned int)pad
->partial_data
.length
,
865 (unsigned int)pad
->needed_len
,
866 (unsigned int)copy_len
,
867 (unsigned int)pblob
->length
));
869 tmp_blob
= data_blob(NULL
,
870 pad
->partial_data
.length
+ copy_len
);
872 /* Concatenate the two (up to copy_len) bytes. */
873 memcpy(tmp_blob
.data
,
874 pad
->partial_data
.data
,
875 pad
->partial_data
.length
);
876 memcpy(tmp_blob
.data
+ pad
->partial_data
.length
,
880 /* Replace the partial data. */
881 data_blob_free(&pad
->partial_data
);
882 pad
->partial_data
= tmp_blob
;
883 ZERO_STRUCT(tmp_blob
);
886 if (pblob
->length
>= pad
->needed_len
) {
887 /* Yes, replace pblob. */
888 data_blob_free(pblob
);
889 *pblob
= pad
->partial_data
;
890 ZERO_STRUCT(pad
->partial_data
);
891 delete_partial_auth(sconn
, pad
);
895 /* Still need more data. */
896 pad
->needed_len
-= copy_len
;
897 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
900 if ((pblob
->data
[0] != ASN1_APPLICATION(0)) &&
901 (pblob
->data
[0] != ASN1_CONTEXT(1))) {
902 /* Not something we can determine the
908 /* This is a new SPNEGO sessionsetup - see if
909 * the data given in this blob is enough.
912 data
= asn1_init(NULL
);
914 return NT_STATUS_NO_MEMORY
;
917 asn1_load(data
, *pblob
);
918 if (asn1_start_tag(data
, pblob
->data
[0])) {
919 /* asn1_start_tag checks if the given
920 length of the blob is enough to complete
921 the tag. If it returns true we know
922 there is nothing to do - the blob is
928 if (data
->nesting
== NULL
) {
929 /* Incorrect tag, allocation failed,
930 or reading the tag length failed.
931 Let the caller catch. */
936 /* Here we know asn1_start_tag() has set data->has_error to true.
937 asn1_tag_remaining() will have failed due to the given blob
938 being too short. We need to work out how short. */
940 /* Integer wrap paranoia.... */
942 if (data
->nesting
->taglen
+ data
->nesting
->start
< data
->nesting
->taglen
||
943 data
->nesting
->taglen
+ data
->nesting
->start
< data
->nesting
->start
) {
945 DEBUG(2,("check_spnego_blob_complete: integer wrap "
946 "data.nesting->taglen = %u, "
947 "data.nesting->start = %u\n",
948 (unsigned int)data
->nesting
->taglen
,
949 (unsigned int)data
->nesting
->start
));
952 return NT_STATUS_INVALID_PARAMETER
;
955 /* Total length of the needed asn1 is the tag length
956 * plus the current offset. */
958 needed_len
= data
->nesting
->taglen
+ data
->nesting
->start
;
961 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
962 "pblob->length = %u\n",
963 (unsigned int)needed_len
,
964 (unsigned int)pblob
->length
));
966 if (needed_len
<= pblob
->length
) {
967 /* Nothing to do - blob is complete. */
968 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
969 above should have caught this !!! */
970 DEBUG(0,("check_spnego_blob_complete: logic "
971 "error (needed_len = %u, "
972 "pblob->length = %u).\n",
973 (unsigned int)needed_len
,
974 (unsigned int)pblob
->length
));
978 /* Refuse the blob if it's bigger than 64k. */
979 if (needed_len
> 65536) {
980 DEBUG(2,("check_spnego_blob_complete: needed_len "
982 (unsigned int)needed_len
));
983 return NT_STATUS_INVALID_PARAMETER
;
986 /* We must store this blob until complete. */
987 if (!(pad
= SMB_MALLOC_P(struct pending_auth_data
))) {
988 return NT_STATUS_NO_MEMORY
;
990 pad
->needed_len
= needed_len
- pblob
->length
;
991 pad
->partial_data
= data_blob(pblob
->data
, pblob
->length
);
992 if (pad
->partial_data
.data
== NULL
) {
994 return NT_STATUS_NO_MEMORY
;
996 pad
->smbpid
= smbpid
;
998 DLIST_ADD(sconn
->smb1
.pd_list
, pad
);
1000 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
1003 /****************************************************************************
1004 Reply to a session setup command.
1005 conn POINTER CAN BE NULL HERE !
1006 ****************************************************************************/
1008 static void reply_sesssetup_and_X_spnego(struct smb_request
*req
)
1014 const char *native_os
;
1015 const char *native_lanman
;
1016 const char *primary_domain
;
1018 uint16 data_blob_len
= SVAL(req
->vwv
+7, 0);
1019 enum remote_arch_types ra_type
= get_remote_arch();
1020 int vuid
= req
->vuid
;
1021 user_struct
*vuser
= NULL
;
1022 NTSTATUS status
= NT_STATUS_OK
;
1023 uint16 smbpid
= req
->smbpid
;
1024 struct smbd_server_connection
*sconn
= req
->sconn
;
1026 DEBUG(3,("Doing spnego session setup\n"));
1028 if (global_client_caps
== 0) {
1029 global_client_caps
= IVAL(req
->vwv
+10, 0);
1031 if (!(global_client_caps
& CAP_STATUS32
)) {
1032 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1039 if (data_blob_len
== 0) {
1040 /* an invalid request */
1041 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1045 bufrem
= smbreq_bufrem(req
, p
);
1046 /* pull the spnego blob */
1047 blob1
= data_blob(p
, MIN(bufrem
, data_blob_len
));
1050 file_save("negotiate.dat", blob1
.data
, blob1
.length
);
1053 p2
= (const char *)req
->buf
+ blob1
.length
;
1055 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1057 native_os
= tmp
? tmp
: "";
1059 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1061 native_lanman
= tmp
? tmp
: "";
1063 p2
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p2
,
1065 primary_domain
= tmp
? tmp
: "";
1067 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1068 native_os
, native_lanman
, primary_domain
));
1070 if ( ra_type
== RA_WIN2K
) {
1071 /* Vista sets neither the OS or lanman strings */
1073 if ( !strlen(native_os
) && !strlen(native_lanman
) )
1074 set_remote_arch(RA_VISTA
);
1076 /* Windows 2003 doesn't set the native lanman string,
1077 but does set primary domain which is a bug I think */
1079 if ( !strlen(native_lanman
) ) {
1080 ra_lanman_string( primary_domain
);
1082 ra_lanman_string( native_lanman
);
1084 } else if ( ra_type
== RA_VISTA
) {
1085 if ( strncmp(native_os
, "Mac OS X", 8) == 0 ) {
1086 set_remote_arch(RA_OSX
);
1090 /* Did we get a valid vuid ? */
1091 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1092 /* No, then try and see if this is an intermediate sessionsetup
1093 * for a large SPNEGO packet. */
1094 struct pending_auth_data
*pad
;
1095 pad
= get_pending_auth_data(sconn
, smbpid
);
1097 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1098 "pending vuid %u\n",
1099 (unsigned int)pad
->vuid
));
1104 /* Do we have a valid vuid now ? */
1105 if (!is_partial_auth_vuid(sconn
, vuid
)) {
1106 /* No, start a new authentication setup. */
1107 vuid
= register_initial_vuid(sconn
);
1108 if (vuid
== UID_FIELD_INVALID
) {
1109 data_blob_free(&blob1
);
1110 reply_nterror(req
, nt_status_squash(
1111 NT_STATUS_INVALID_PARAMETER
));
1116 vuser
= get_partial_auth_user_struct(sconn
, vuid
);
1117 /* This MUST be valid. */
1119 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1122 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1123 * sessionsetup requests as the Windows limit on the security blob
1124 * field is 4k. Bug #4400. JRA.
1127 status
= check_spnego_blob_complete(sconn
, smbpid
, vuid
, &blob1
);
1128 if (!NT_STATUS_IS_OK(status
)) {
1129 if (!NT_STATUS_EQUAL(status
,
1130 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1131 /* Real error - kill the intermediate vuid */
1132 invalidate_vuid(sconn
, vuid
);
1134 data_blob_free(&blob1
);
1135 reply_nterror(req
, nt_status_squash(status
));
1139 /* Handle either raw NTLMSSP or hand off the whole blob to
1140 * GENSEC. The processing at this layer is essentially
1141 * identical regardless. In particular, both rely only on the
1142 * status code (not the contents of the packet) and do not
1143 * wrap the result */
1144 if (sconn
->use_gensec_hook
|| ntlmssp_blob_matches_magic(&blob1
)) {
1147 if (!vuser
->auth_ntlmssp_state
) {
1148 status
= auth_ntlmssp_prepare(sconn
->remote_address
,
1149 &vuser
->auth_ntlmssp_state
);
1150 if (!NT_STATUS_IS_OK(status
)) {
1151 /* Kill the intermediate vuid */
1152 invalidate_vuid(sconn
, vuid
);
1153 data_blob_free(&blob1
);
1154 reply_nterror(req
, nt_status_squash(status
));
1158 gensec_want_feature(vuser
->auth_ntlmssp_state
->gensec_security
, GENSEC_FEATURE_SESSION_KEY
);
1160 if (sconn
->use_gensec_hook
) {
1161 status
= auth_generic_start(vuser
->auth_ntlmssp_state
, GENSEC_OID_SPNEGO
);
1163 status
= auth_ntlmssp_start(vuser
->auth_ntlmssp_state
);
1165 if (!NT_STATUS_IS_OK(status
)) {
1166 /* Kill the intermediate vuid */
1167 invalidate_vuid(sconn
, vuid
);
1168 data_blob_free(&blob1
);
1169 reply_nterror(req
, nt_status_squash(status
));
1174 status
= gensec_update(vuser
->auth_ntlmssp_state
->gensec_security
,
1178 data_blob_free(&blob1
);
1180 reply_spnego_ntlmssp(req
, vuid
,
1181 &vuser
->auth_ntlmssp_state
,
1182 &chal
, status
, NULL
, false);
1183 data_blob_free(&chal
);
1187 if (blob1
.data
[0] == ASN1_APPLICATION(0)) {
1189 /* its a negTokenTarg packet */
1191 reply_spnego_negotiate(req
, vuid
, blob1
,
1192 &vuser
->auth_ntlmssp_state
);
1193 data_blob_free(&blob1
);
1197 if (blob1
.data
[0] == ASN1_CONTEXT(1)) {
1199 /* its a auth packet */
1201 reply_spnego_auth(req
, vuid
, blob1
,
1202 &vuser
->auth_ntlmssp_state
);
1203 data_blob_free(&blob1
);
1207 /* what sort of packet is this? */
1208 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1210 data_blob_free(&blob1
);
1212 reply_nterror(req
, nt_status_squash(NT_STATUS_LOGON_FAILURE
));
1215 /****************************************************************************
1216 On new VC == 0, shutdown *all* old connections and users.
1217 It seems that only NT4.x does this. At W2K and above (XP etc.).
1218 a new session setup with VC==0 is ignored.
1219 ****************************************************************************/
1221 struct shutdown_state
{
1223 struct messaging_context
*msg_ctx
;
1226 static int shutdown_other_smbds(const struct connections_key
*key
,
1227 const struct connections_data
*crec
,
1230 struct shutdown_state
*state
= (struct shutdown_state
*)private_data
;
1232 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1233 server_id_str(talloc_tos(), &crec
->pid
), crec
->addr
));
1235 if (!process_exists(crec
->pid
)) {
1236 DEBUG(10, ("process does not exist\n"));
1240 if (procid_is_me(&crec
->pid
)) {
1241 DEBUG(10, ("It's me\n"));
1245 if (strcmp(state
->ip
, crec
->addr
) != 0) {
1246 DEBUG(10, ("%s does not match %s\n", state
->ip
, crec
->addr
));
1250 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1251 "(IP %s)\n", (unsigned int)procid_to_pid(&crec
->pid
),
1254 messaging_send(state
->msg_ctx
, crec
->pid
, MSG_SHUTDOWN
,
1259 static void setup_new_vc_session(struct smbd_server_connection
*sconn
)
1261 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1262 "compatible we would close all old resources.\n"));
1265 invalidate_all_vuids();
1267 if (lp_reset_on_zero_vc()) {
1269 struct shutdown_state state
;
1271 addr
= tsocket_address_inet_addr_string(
1272 sconn
->remote_address
, talloc_tos());
1277 state
.msg_ctx
= sconn
->msg_ctx
;
1278 connections_forall_read(shutdown_other_smbds
, &state
);
1283 /****************************************************************************
1284 Reply to a session setup command.
1285 ****************************************************************************/
1287 void reply_sesssetup_and_X(struct smb_request
*req
)
1293 DATA_BLOB plaintext_password
;
1296 fstring sub_user
; /* Sanitised username for substituion */
1298 const char *native_os
;
1299 const char *native_lanman
;
1300 const char *primary_domain
;
1301 struct auth_usersupplied_info
*user_info
= NULL
;
1302 struct auth_serversupplied_info
*server_info
= NULL
;
1303 struct auth_session_info
*session_info
= NULL
;
1304 uint16 smb_flag2
= req
->flags2
;
1307 struct smbd_server_connection
*sconn
= req
->sconn
;
1309 bool doencrypt
= sconn
->smb1
.negprot
.encrypted_passwords
;
1310 bool signing_allowed
= false;
1311 bool signing_mandatory
= false;
1313 START_PROFILE(SMBsesssetupX
);
1315 ZERO_STRUCT(lm_resp
);
1316 ZERO_STRUCT(nt_resp
);
1317 ZERO_STRUCT(plaintext_password
);
1319 DEBUG(3,("wct=%d flg2=0x%x\n", req
->wct
, req
->flags2
));
1321 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES
) {
1322 signing_allowed
= true;
1324 if (req
->flags2
& FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED
) {
1325 signing_mandatory
= true;
1329 * We can call srv_set_signing_negotiated() each time.
1330 * It finds out when it needs to turn into a noop
1333 srv_set_signing_negotiated(req
->sconn
,
1337 /* a SPNEGO session setup has 12 command words, whereas a normal
1338 NT1 session setup has 13. See the cifs spec. */
1339 if (req
->wct
== 12 &&
1340 (req
->flags2
& FLAGS2_EXTENDED_SECURITY
)) {
1342 if (!sconn
->smb1
.negprot
.spnego
) {
1343 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1344 "at SPNEGO session setup when it was not "
1346 reply_nterror(req
, nt_status_squash(
1347 NT_STATUS_LOGON_FAILURE
));
1348 END_PROFILE(SMBsesssetupX
);
1352 if (SVAL(req
->vwv
+4, 0) == 0) {
1353 setup_new_vc_session(req
->sconn
);
1356 reply_sesssetup_and_X_spnego(req
);
1357 END_PROFILE(SMBsesssetupX
);
1361 smb_bufsize
= SVAL(req
->vwv
+2, 0);
1363 if (get_Protocol() < PROTOCOL_NT1
) {
1364 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1366 /* Never do NT status codes with protocols before NT1 as we
1367 * don't get client caps. */
1368 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES
);
1370 if ((passlen1
> MAX_PASS_LEN
) || (passlen1
> req
->buflen
)) {
1371 reply_nterror(req
, nt_status_squash(
1372 NT_STATUS_INVALID_PARAMETER
));
1373 END_PROFILE(SMBsesssetupX
);
1378 lm_resp
= data_blob(req
->buf
, passlen1
);
1380 plaintext_password
= data_blob(req
->buf
, passlen1
+1);
1381 /* Ensure null termination */
1382 plaintext_password
.data
[passlen1
] = 0;
1385 srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
,
1386 req
->buf
+ passlen1
, STR_TERMINATE
);
1387 user
= tmp
? tmp
: "";
1392 uint16 passlen1
= SVAL(req
->vwv
+7, 0);
1393 uint16 passlen2
= SVAL(req
->vwv
+8, 0);
1394 enum remote_arch_types ra_type
= get_remote_arch();
1395 const uint8_t *p
= req
->buf
;
1396 const uint8_t *save_p
= req
->buf
;
1400 if(global_client_caps
== 0) {
1401 global_client_caps
= IVAL(req
->vwv
+11, 0);
1403 if (!(global_client_caps
& CAP_STATUS32
)) {
1404 remove_from_common_flags2(
1405 FLAGS2_32_BIT_ERROR_CODES
);
1408 /* client_caps is used as final determination if
1409 * client is NT or Win95. This is needed to return
1410 * the correct error codes in some circumstances.
1413 if(ra_type
== RA_WINNT
|| ra_type
== RA_WIN2K
||
1414 ra_type
== RA_WIN95
) {
1415 if(!(global_client_caps
& (CAP_NT_SMBS
|
1417 set_remote_arch( RA_WIN95
);
1423 /* both Win95 and WinNT stuff up the password
1424 * lengths for non-encrypting systems. Uggh.
1426 if passlen1==24 its a win95 system, and its setting
1427 the password length incorrectly. Luckily it still
1428 works with the default code because Win95 will null
1429 terminate the password anyway
1431 if passlen1>0 and passlen2>0 then maybe its a NT box
1432 and its setting passlen2 to some random value which
1433 really stuffs things up. we need to fix that one. */
1435 if (passlen1
> 0 && passlen2
> 0 && passlen2
!= 24 &&
1441 /* check for nasty tricks */
1442 if (passlen1
> MAX_PASS_LEN
1443 || passlen1
> smbreq_bufrem(req
, p
)) {
1444 reply_nterror(req
, nt_status_squash(
1445 NT_STATUS_INVALID_PARAMETER
));
1446 END_PROFILE(SMBsesssetupX
);
1450 if (passlen2
> MAX_PASS_LEN
1451 || passlen2
> smbreq_bufrem(req
, p
+passlen1
)) {
1452 reply_nterror(req
, nt_status_squash(
1453 NT_STATUS_INVALID_PARAMETER
));
1454 END_PROFILE(SMBsesssetupX
);
1458 /* Save the lanman2 password and the NT md4 password. */
1460 if ((doencrypt
) && (passlen1
!= 0) && (passlen1
!= 24)) {
1465 lm_resp
= data_blob(p
, passlen1
);
1466 nt_resp
= data_blob(p
+passlen1
, passlen2
);
1467 } else if (lp_security() != SEC_SHARE
) {
1469 * In share level we should ignore any passwords, so
1470 * only read them if we're not.
1473 bool unic
= smb_flag2
& FLAGS2_UNICODE_STRINGS
;
1475 if (unic
&& (passlen2
== 0) && passlen1
) {
1476 /* Only a ascii plaintext password was sent. */
1477 (void)srvstr_pull_talloc(talloc_tos(),
1483 STR_TERMINATE
|STR_ASCII
);
1485 (void)srvstr_pull_talloc(talloc_tos(),
1490 unic
? passlen2
: passlen1
,
1494 reply_nterror(req
, nt_status_squash(
1495 NT_STATUS_INVALID_PARAMETER
));
1496 END_PROFILE(SMBsesssetupX
);
1499 plaintext_password
= data_blob(pass
, strlen(pass
)+1);
1502 p
+= passlen1
+ passlen2
;
1504 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1506 user
= tmp
? tmp
: "";
1508 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1510 domain
= tmp
? tmp
: "";
1512 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1514 native_os
= tmp
? tmp
: "";
1516 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1518 native_lanman
= tmp
? tmp
: "";
1520 /* not documented or decoded by Ethereal but there is one more
1521 * string in the extra bytes which is the same as the
1522 * PrimaryDomain when using extended security. Windows NT 4
1523 * and 2003 use this string to store the native lanman string.
1524 * Windows 9x does not include a string here at all so we have
1525 * to check if we have any extra bytes left */
1527 byte_count
= SVAL(req
->vwv
+13, 0);
1528 if ( PTR_DIFF(p
, save_p
) < byte_count
) {
1529 p
+= srvstr_pull_req_talloc(talloc_tos(), req
, &tmp
, p
,
1531 primary_domain
= tmp
? tmp
: "";
1533 primary_domain
= talloc_strdup(talloc_tos(), "null");
1536 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1537 "PrimaryDomain=[%s]\n",
1538 domain
, native_os
, native_lanman
, primary_domain
));
1540 if ( ra_type
== RA_WIN2K
) {
1541 if ( strlen(native_lanman
) == 0 )
1542 ra_lanman_string( primary_domain
);
1544 ra_lanman_string( native_lanman
);
1549 if (SVAL(req
->vwv
+4, 0) == 0) {
1550 setup_new_vc_session(req
->sconn
);
1553 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1554 domain
, user
, get_remote_machine_name()));
1557 if (sconn
->smb1
.negprot
.spnego
) {
1559 /* This has to be here, because this is a perfectly
1560 * valid behaviour for guest logons :-( */
1562 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1563 "at 'normal' session setup after "
1564 "negotiating spnego.\n"));
1565 reply_nterror(req
, nt_status_squash(
1566 NT_STATUS_LOGON_FAILURE
));
1567 END_PROFILE(SMBsesssetupX
);
1570 fstrcpy(sub_user
, user
);
1572 fstrcpy(sub_user
, "");
1575 sub_set_smb_name(sub_user
);
1577 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
1579 if (lp_security() == SEC_SHARE
) {
1580 char *sub_user_mapped
= NULL
;
1581 /* In share level we should ignore any passwords */
1583 data_blob_free(&lm_resp
);
1584 data_blob_free(&nt_resp
);
1585 data_blob_clear_free(&plaintext_password
);
1587 (void)map_username(talloc_tos(), sub_user
, &sub_user_mapped
);
1588 if (!sub_user_mapped
) {
1589 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1590 END_PROFILE(SMBsesssetupX
);
1593 fstrcpy(sub_user
, sub_user_mapped
);
1594 add_session_user(sconn
, sub_user
);
1595 add_session_workgroup(sconn
, domain
);
1596 /* Then force it to null for the benfit of the code below */
1602 nt_status
= check_guest_password(sconn
->remote_address
, &server_info
);
1604 } else if (doencrypt
) {
1605 struct auth_context
*negprot_auth_context
= NULL
;
1606 negprot_auth_context
= sconn
->smb1
.negprot
.auth_context
;
1607 if (!negprot_auth_context
) {
1608 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1609 "session setup without negprot denied!\n"));
1610 reply_nterror(req
, nt_status_squash(
1611 NT_STATUS_LOGON_FAILURE
));
1612 END_PROFILE(SMBsesssetupX
);
1615 nt_status
= make_user_info_for_reply_enc(&user_info
, user
,
1617 sconn
->remote_address
,
1619 if (NT_STATUS_IS_OK(nt_status
)) {
1620 nt_status
= negprot_auth_context
->check_ntlm_password(
1621 negprot_auth_context
,
1626 struct auth_context
*plaintext_auth_context
= NULL
;
1628 nt_status
= make_auth_context_subsystem(
1629 talloc_tos(), &plaintext_auth_context
);
1631 if (NT_STATUS_IS_OK(nt_status
)) {
1634 plaintext_auth_context
->get_ntlm_challenge(
1635 plaintext_auth_context
, chal
);
1637 if (!make_user_info_for_reply(&user_info
,
1639 sconn
->remote_address
,
1641 plaintext_password
)) {
1642 nt_status
= NT_STATUS_NO_MEMORY
;
1645 if (NT_STATUS_IS_OK(nt_status
)) {
1646 nt_status
= plaintext_auth_context
->check_ntlm_password(
1647 plaintext_auth_context
,
1651 TALLOC_FREE(plaintext_auth_context
);
1656 free_user_info(&user_info
);
1658 if (!NT_STATUS_IS_OK(nt_status
)) {
1659 nt_status
= do_map_to_guest_server_info(nt_status
, &server_info
,
1663 if (!NT_STATUS_IS_OK(nt_status
)) {
1664 data_blob_free(&nt_resp
);
1665 data_blob_free(&lm_resp
);
1666 data_blob_clear_free(&plaintext_password
);
1667 reply_nterror(req
, nt_status_squash(nt_status
));
1668 END_PROFILE(SMBsesssetupX
);
1672 nt_status
= create_local_token(req
, server_info
, NULL
, sub_user
, &session_info
);
1673 TALLOC_FREE(server_info
);
1675 if (!NT_STATUS_IS_OK(nt_status
)) {
1676 DEBUG(10, ("create_local_token failed: %s\n",
1677 nt_errstr(nt_status
)));
1678 data_blob_free(&nt_resp
);
1679 data_blob_free(&lm_resp
);
1680 data_blob_clear_free(&plaintext_password
);
1681 reply_nterror(req
, nt_status_squash(nt_status
));
1682 END_PROFILE(SMBsesssetupX
);
1686 data_blob_clear_free(&plaintext_password
);
1688 /* it's ok - setup a reply */
1689 reply_outbuf(req
, 3, 0);
1690 if (get_Protocol() >= PROTOCOL_NT1
) {
1691 push_signature(&req
->outbuf
);
1692 /* perhaps grab OS version here?? */
1695 if (security_session_user_level(session_info
, NULL
) < SECURITY_USER
) {
1696 SSVAL(req
->outbuf
,smb_vwv2
,1);
1699 /* register the name and uid as being validated, so further connections
1700 to a uid can get through without a password, on the same VC */
1702 if (lp_security() == SEC_SHARE
) {
1703 sess_vuid
= UID_FIELD_INVALID
;
1704 TALLOC_FREE(session_info
);
1706 /* Ignore the initial vuid. */
1707 sess_vuid
= register_initial_vuid(sconn
);
1708 if (sess_vuid
== UID_FIELD_INVALID
) {
1709 data_blob_free(&nt_resp
);
1710 data_blob_free(&lm_resp
);
1711 reply_nterror(req
, nt_status_squash(
1712 NT_STATUS_LOGON_FAILURE
));
1713 END_PROFILE(SMBsesssetupX
);
1716 /* register_existing_vuid keeps the session_info */
1717 sess_vuid
= register_existing_vuid(sconn
, sess_vuid
,
1719 nt_resp
.data
? nt_resp
: lm_resp
);
1720 if (sess_vuid
== UID_FIELD_INVALID
) {
1721 data_blob_free(&nt_resp
);
1722 data_blob_free(&lm_resp
);
1723 reply_nterror(req
, nt_status_squash(
1724 NT_STATUS_LOGON_FAILURE
));
1725 END_PROFILE(SMBsesssetupX
);
1729 /* current_user_info is changed on new vuid */
1730 reload_services(sconn
->msg_ctx
, sconn
->sock
, True
);
1733 data_blob_free(&nt_resp
);
1734 data_blob_free(&lm_resp
);
1736 SSVAL(req
->outbuf
,smb_uid
,sess_vuid
);
1737 SSVAL(discard_const_p(char, req
->inbuf
),smb_uid
,sess_vuid
);
1738 req
->vuid
= sess_vuid
;
1740 if (!sconn
->smb1
.sessions
.done_sesssetup
) {
1741 sconn
->smb1
.sessions
.max_send
=
1742 MIN(sconn
->smb1
.sessions
.max_send
,smb_bufsize
);
1744 sconn
->smb1
.sessions
.done_sesssetup
= true;
1746 END_PROFILE(SMBsesssetupX
);