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/globals.h"
28
extern enum protocol_types Protocol;
31
on a logon error possibly map the error to success if "map to guest"
34
static NTSTATUS do_map_to_guest(NTSTATUS status,
35
auth_serversupplied_info **server_info,
36
const char *user, const char *domain)
38
if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
39
if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
40
(lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
41
DEBUG(3,("No such user %s [%s] - using guest account\n",
43
status = make_server_info_guest(NULL, server_info);
47
if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
48
if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
49
DEBUG(3,("Registered username %s for guest access\n",
51
status = make_server_info_guest(NULL, server_info);
58
/****************************************************************************
59
Add the standard 'Samba' signature to the end of the session setup.
60
****************************************************************************/
62
static int push_signature(uint8 **outbuf)
69
tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
71
if (tmp == -1) return -1;
74
if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
75
tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
79
tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
82
if (tmp == -1) return -1;
85
tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
87
if (tmp == -1) return -1;
93
/****************************************************************************
94
Start the signing engine if needed. Don't fail signing here.
95
****************************************************************************/
97
static void sessionsetup_start_signing_engine(
98
const auth_serversupplied_info *server_info,
101
if (!server_info->guest && !srv_signing_started()) {
102
/* We need to start the signing engine
103
* here but a W2K client sends the old
104
* "BSRSPYL " signature instead of the
105
* correct one. Subsequent packets will
108
srv_check_sign_mac((char *)inbuf, False);
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(auth_serversupplied_info **server_info)
143
struct auth_context *auth_context;
144
auth_usersupplied_info *user_info = NULL;
147
unsigned char chal[8];
151
DEBUG(3,("Got anonymous request\n"));
153
if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
158
if (!make_user_info_guest(&user_info)) {
159
(auth_context->free)(&auth_context);
160
return NT_STATUS_NO_MEMORY;
163
nt_status = auth_context->check_ntlm_password(auth_context,
166
(auth_context->free)(&auth_context);
167
free_user_info(&user_info);
175
/* Experiment that failed. See "only happens with a KDC" comment below. */
176
/****************************************************************************
177
Cerate a clock skew error blob for a Windows client.
178
****************************************************************************/
180
static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
182
krb5_context context = NULL;
183
krb5_error_code kerr = 0;
185
krb5_principal host_princ = NULL;
186
char *host_princ_s = NULL;
189
*pblob_out = data_blob_null;
191
initialize_krb5_error_table();
192
kerr = krb5_init_context(&context);
196
/* Create server principal. */
197
asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
201
strlower_m(host_princ_s);
203
kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
205
DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
206
"for name %s: Error %s\n",
207
host_princ_s, error_message(kerr) ));
211
kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
214
DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
215
"failed: Error %s\n",
216
error_message(kerr) ));
220
*pblob_out = data_blob(reply.data, reply.length);
221
kerberos_free_data_contents(context,&reply);
227
SAFE_FREE(host_princ_s);
230
krb5_free_principal(context, host_princ);
232
krb5_free_context(context);
237
/****************************************************************************
238
Reply to a session setup spnego negotiate packet for kerberos.
239
****************************************************************************/
241
static void reply_spnego_kerberos(struct smb_request *req,
245
bool *p_invalidate_vuid)
249
char *client, *p, *domain;
250
fstring netbios_domain_name;
253
int sess_vuid = req->vuid;
254
NTSTATUS ret = NT_STATUS_OK;
255
struct PAC_DATA *pac_data = NULL;
256
DATA_BLOB ap_rep, ap_rep_wrapped, response;
257
auth_serversupplied_info *server_info = NULL;
258
DATA_BLOB session_key = data_blob_null;
260
DATA_BLOB nullblob = data_blob_null;
261
fstring real_username;
262
bool map_domainuser_to_guest = False;
263
bool username_was_mapped;
264
struct PAC_LOGON_INFO *logon_info = NULL;
268
ZERO_STRUCT(ap_rep_wrapped);
269
ZERO_STRUCT(response);
271
/* Normally we will always invalidate the intermediate vuid. */
272
*p_invalidate_vuid = True;
274
mem_ctx = talloc_init("reply_spnego_kerberos");
275
if (mem_ctx == NULL) {
276
reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
280
if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
281
talloc_destroy(mem_ctx);
282
reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
286
ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
287
&client, &pac_data, &ap_rep,
290
data_blob_free(&ticket);
292
if (!NT_STATUS_IS_OK(ret)) {
294
/* Experiment that failed.
295
* See "only happens with a KDC" comment below. */
297
if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
300
* Windows in this case returns
301
* NT_STATUS_MORE_PROCESSING_REQUIRED
302
* with a negTokenTarg blob containing an krb5_error
303
* struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
304
* The client then fixes its clock and continues rather
305
* than giving an error. JRA.
306
* -- Looks like this only happens with a KDC. JRA.
309
bool ok = make_krb5_skew_error(&ap_rep);
311
talloc_destroy(mem_ctx);
312
return ERROR_NT(nt_status_squash(
313
NT_STATUS_LOGON_FAILURE));
315
ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
317
response = spnego_gen_auth_response(&ap_rep_wrapped,
318
ret, OID_KERBEROS5_OLD);
319
reply_sesssetup_blob(conn, inbuf, outbuf, response,
320
NT_STATUS_MORE_PROCESSING_REQUIRED);
323
* In this one case we don't invalidate the
324
* intermediate vuid as we're expecting the client
325
* to re-use it for the next sessionsetupX packet. JRA.
328
*p_invalidate_vuid = False;
330
data_blob_free(&ap_rep);
331
data_blob_free(&ap_rep_wrapped);
332
data_blob_free(&response);
333
talloc_destroy(mem_ctx);
334
return -1; /* already replied */
337
if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
338
ret = NT_STATUS_LOGON_FAILURE;
341
DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
343
talloc_destroy(mem_ctx);
344
reply_nterror(req, nt_status_squash(ret));
348
DEBUG(3,("Ticket name is [%s]\n", client));
350
p = strchr_m(client, '@');
352
DEBUG(3,("Doesn't look like a valid principal\n"));
353
data_blob_free(&ap_rep);
354
data_blob_free(&session_key);
355
talloc_destroy(mem_ctx);
356
reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
362
/* save the PAC data if we have it */
365
logon_info = get_logon_info_from_pac(pac_data);
367
netsamlogon_cache_store( client, &logon_info->info3 );
371
if (!strequal(p+1, lp_realm())) {
372
DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
373
if (!lp_allow_trusted_domains()) {
374
data_blob_free(&ap_rep);
375
data_blob_free(&session_key);
376
talloc_destroy(mem_ctx);
377
reply_nterror(req, nt_status_squash(
378
NT_STATUS_LOGON_FAILURE));
383
/* this gives a fully qualified user name (ie. with full realm).
384
that leads to very long usernames, but what else can we do? */
388
if (logon_info && logon_info->info3.base.domain.string) {
389
fstrcpy(netbios_domain_name,
390
logon_info->info3.base.domain.string);
391
domain = netbios_domain_name;
392
DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
396
/* If we have winbind running, we can (and must) shorten the
397
username by using the short netbios name. Otherwise we will
398
have inconsistent user names. With Kerberos, we get the
399
fully qualified realm, with ntlmssp we get the short
400
name. And even w2k3 does use ntlmssp if you for example
401
connect to an ip address. */
404
struct wbcDomainInfo *info = NULL;
406
DEBUG(10, ("Mapping [%s] to short name\n", domain));
408
wbc_status = wbcDomainInfo(domain, &info);
410
if (WBC_ERROR_IS_OK(wbc_status)) {
412
fstrcpy(netbios_domain_name,
416
domain = netbios_domain_name;
417
DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
419
DEBUG(3, ("Could not find short name: %s\n",
420
wbcErrorString(wbc_status)));
424
fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
426
/* lookup the passwd struct, create a new user if necessary */
428
username_was_mapped = map_username( user );
430
pw = smb_getpwnam( mem_ctx, user, real_username, True );
433
/* if a real user check pam account restrictions */
434
/* only really perfomed if "obey pam restriction" is true */
435
/* do this before an eventual mapping to guest occurs */
436
ret = smb_pam_accountcheck(pw->pw_name);
437
if ( !NT_STATUS_IS_OK(ret)) {
438
DEBUG(1,("PAM account restriction "
439
"prevents user login\n"));
440
data_blob_free(&ap_rep);
441
data_blob_free(&session_key);
442
TALLOC_FREE(mem_ctx);
443
reply_nterror(req, nt_status_squash(ret));
450
/* this was originally the behavior of Samba 2.2, if a user
451
did not have a local uid but has been authenticated, then
452
map them to a guest account */
454
if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
455
map_domainuser_to_guest = True;
456
fstrcpy(user,lp_guestaccount());
457
pw = smb_getpwnam( mem_ctx, user, real_username, True );
460
/* extra sanity check that the guest account is valid */
463
DEBUG(1,("Username %s is invalid on this system\n",
465
data_blob_free(&ap_rep);
466
data_blob_free(&session_key);
467
TALLOC_FREE(mem_ctx);
468
reply_nterror(req, nt_status_squash(
469
NT_STATUS_LOGON_FAILURE));
474
/* setup the string used by %U */
476
sub_set_smb_name( real_username );
477
reload_services(True);
479
if ( map_domainuser_to_guest ) {
480
make_server_info_guest(NULL, &server_info);
481
} else if (logon_info) {
482
/* pass the unmapped username here since map_username()
483
will be called again from inside make_server_info_info3() */
485
ret = make_server_info_info3(mem_ctx, client, domain,
486
&server_info, &logon_info->info3);
487
if ( !NT_STATUS_IS_OK(ret) ) {
488
DEBUG(1,("make_server_info_info3 failed: %s!\n",
490
data_blob_free(&ap_rep);
491
data_blob_free(&session_key);
492
TALLOC_FREE(mem_ctx);
493
reply_nterror(req, nt_status_squash(ret));
498
ret = make_server_info_pw(&server_info, real_username, pw);
500
if ( !NT_STATUS_IS_OK(ret) ) {
501
DEBUG(1,("make_server_info_pw failed: %s!\n",
503
data_blob_free(&ap_rep);
504
data_blob_free(&session_key);
505
TALLOC_FREE(mem_ctx);
506
reply_nterror(req, nt_status_squash(ret));
510
/* make_server_info_pw does not set the domain. Without this
511
* we end up with the local netbios name in substitutions for
514
if (server_info->sam_account != NULL) {
515
pdb_set_domain(server_info->sam_account,
520
server_info->nss_token |= username_was_mapped;
522
/* we need to build the token for the user. make_server_info_guest()
525
if ( !server_info->ptok ) {
526
ret = create_local_token( server_info );
527
if ( !NT_STATUS_IS_OK(ret) ) {
528
DEBUG(10,("failed to create local token: %s\n",
530
data_blob_free(&ap_rep);
531
data_blob_free(&session_key);
532
TALLOC_FREE( mem_ctx );
533
TALLOC_FREE( server_info );
534
reply_nterror(req, nt_status_squash(ret));
539
if (!is_partial_auth_vuid(sess_vuid)) {
540
sess_vuid = register_initial_vuid();
543
data_blob_free(&server_info->user_session_key);
544
server_info->user_session_key = session_key;
545
session_key = data_blob_null;
547
/* register_existing_vuid keeps the server info */
548
/* register_existing_vuid takes ownership of session_key on success,
549
* no need to free after this on success. A better interface would copy
552
sess_vuid = register_existing_vuid(sess_vuid,
557
reply_outbuf(req, 4, 0);
558
SSVAL(req->outbuf,smb_uid,sess_vuid);
560
if (sess_vuid == UID_FIELD_INVALID ) {
561
ret = NT_STATUS_LOGON_FAILURE;
563
/* current_user_info is changed on new vuid */
564
reload_services( True );
566
SSVAL(req->outbuf, smb_vwv3, 0);
568
if (server_info->guest) {
569
SSVAL(req->outbuf,smb_vwv2,1);
572
SSVAL(req->outbuf, smb_uid, sess_vuid);
574
sessionsetup_start_signing_engine(server_info, req->inbuf);
575
/* Successful logon. Keep this vuid. */
576
*p_invalidate_vuid = False;
579
/* wrap that up in a nice GSS-API wrapping */
580
if (NT_STATUS_IS_OK(ret)) {
581
ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
584
ap_rep_wrapped = data_blob_null;
586
response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
588
reply_sesssetup_blob(req, response, ret);
590
data_blob_free(&ap_rep);
591
data_blob_free(&ap_rep_wrapped);
592
data_blob_free(&response);
593
TALLOC_FREE(mem_ctx);
598
/****************************************************************************
599
Send a session setup reply, wrapped in SPNEGO.
600
Get vuid and check first.
601
End the NTLMSSP exchange context if we are OK/complete fail
602
This should be split into two functions, one to handle each
603
leg of the NTLM auth steps.
604
***************************************************************************/
606
static void reply_spnego_ntlmssp(struct smb_request *req,
608
AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
609
DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
614
struct auth_serversupplied_info *server_info = NULL;
616
if (NT_STATUS_IS_OK(nt_status)) {
617
server_info = (*auth_ntlmssp_state)->server_info;
619
nt_status = do_map_to_guest(nt_status,
621
(*auth_ntlmssp_state)->ntlmssp_state->user,
622
(*auth_ntlmssp_state)->ntlmssp_state->domain);
625
reply_outbuf(req, 4, 0);
627
SSVAL(req->outbuf, smb_uid, vuid);
629
if (NT_STATUS_IS_OK(nt_status)) {
630
DATA_BLOB nullblob = data_blob_null;
632
if (!is_partial_auth_vuid(vuid)) {
633
nt_status = NT_STATUS_LOGON_FAILURE;
637
data_blob_free(&server_info->user_session_key);
638
server_info->user_session_key =
641
(*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
642
(*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
644
/* register_existing_vuid keeps the server info */
645
if (register_existing_vuid(vuid,
646
server_info, nullblob,
647
(*auth_ntlmssp_state)->ntlmssp_state->user) !=
649
nt_status = NT_STATUS_LOGON_FAILURE;
653
(*auth_ntlmssp_state)->server_info = NULL;
655
/* current_user_info is changed on new vuid */
656
reload_services( True );
658
SSVAL(req->outbuf, smb_vwv3, 0);
660
if (server_info->guest) {
661
SSVAL(req->outbuf,smb_vwv2,1);
664
sessionsetup_start_signing_engine(server_info,
665
(uint8 *)req->inbuf);
671
response = spnego_gen_auth_response(ntlmssp_blob,
674
response = *ntlmssp_blob;
677
reply_sesssetup_blob(req, response, nt_status);
679
data_blob_free(&response);
682
/* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
683
and the other end, that we are not finished yet. */
685
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
686
/* NB. This is *NOT* an error case. JRA */
687
auth_ntlmssp_end(auth_ntlmssp_state);
688
if (!NT_STATUS_IS_OK(nt_status)) {
689
/* Kill the intermediate vuid */
690
invalidate_vuid(vuid);
695
/****************************************************************************
696
Is this a krb5 mechanism ?
697
****************************************************************************/
699
NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
700
DATA_BLOB *pblob_out,
703
char *OIDs[ASN1_MAX_OIDS];
705
NTSTATUS ret = NT_STATUS_OK;
707
*kerb_mechOID = NULL;
709
/* parse out the OIDs and the first sec blob */
710
if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
711
return NT_STATUS_LOGON_FAILURE;
714
/* only look at the first OID for determining the mechToken --
715
according to RFC2478, we should choose the one we want
716
and renegotiate, but i smell a client bug here..
718
Problem observed when connecting to a member (samba box)
719
of an AD domain as a user in a Samba domain. Samba member
720
server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
721
client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
722
NTLMSSP mechtoken. --jerry */
725
if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
726
strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
727
*kerb_mechOID = SMB_STRDUP(OIDs[0]);
728
if (*kerb_mechOID == NULL) {
729
ret = NT_STATUS_NO_MEMORY;
734
for (i=0;OIDs[i];i++) {
735
DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
736
talloc_free(OIDs[i]);
741
/****************************************************************************
742
Fall back from krb5 to NTLMSSP.
743
****************************************************************************/
745
static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
750
reply_outbuf(req, 4, 0);
751
SSVAL(req->outbuf,smb_uid,vuid);
753
DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
754
"but set to downgrade to NTLMSSP\n"));
756
response = spnego_gen_auth_response(NULL,
757
NT_STATUS_MORE_PROCESSING_REQUIRED,
759
reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
760
data_blob_free(&response);
763
/****************************************************************************
764
Reply to a session setup spnego negotiate packet.
765
****************************************************************************/
767
static void reply_spnego_negotiate(struct smb_request *req,
770
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
774
char *kerb_mech = NULL;
777
status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
778
if (!NT_STATUS_IS_OK(status)) {
779
/* Kill the intermediate vuid */
780
invalidate_vuid(vuid);
781
reply_nterror(req, nt_status_squash(status));
785
DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
786
(unsigned long)secblob.length));
789
if (kerb_mech && ((lp_security()==SEC_ADS) ||
790
USE_KERBEROS_KEYTAB) ) {
791
bool destroy_vuid = True;
792
reply_spnego_kerberos(req, &secblob, kerb_mech,
793
vuid, &destroy_vuid);
794
data_blob_free(&secblob);
796
/* Kill the intermediate vuid */
797
invalidate_vuid(vuid);
799
SAFE_FREE(kerb_mech);
804
if (*auth_ntlmssp_state) {
805
auth_ntlmssp_end(auth_ntlmssp_state);
809
data_blob_free(&secblob);
810
/* The mechtoken is a krb5 ticket, but
811
* we need to fall back to NTLM. */
812
reply_spnego_downgrade_to_ntlmssp(req, vuid);
813
SAFE_FREE(kerb_mech);
817
status = auth_ntlmssp_start(auth_ntlmssp_state);
818
if (!NT_STATUS_IS_OK(status)) {
819
/* Kill the intermediate vuid */
820
invalidate_vuid(vuid);
821
reply_nterror(req, nt_status_squash(status));
825
status = auth_ntlmssp_update(*auth_ntlmssp_state,
828
data_blob_free(&secblob);
830
reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
831
&chal, status, OID_NTLMSSP, true);
833
data_blob_free(&chal);
835
/* already replied */
839
/****************************************************************************
840
Reply to a session setup spnego auth packet.
841
****************************************************************************/
843
static void reply_spnego_auth(struct smb_request *req,
846
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
848
DATA_BLOB auth = data_blob_null;
849
DATA_BLOB auth_reply = data_blob_null;
850
DATA_BLOB secblob = data_blob_null;
851
NTSTATUS status = NT_STATUS_LOGON_FAILURE;
853
if (!spnego_parse_auth(blob1, &auth)) {
855
file_save("auth.dat", blob1.data, blob1.length);
857
/* Kill the intermediate vuid */
858
invalidate_vuid(vuid);
860
reply_nterror(req, nt_status_squash(
861
NT_STATUS_LOGON_FAILURE));
865
if (auth.data[0] == ASN1_APPLICATION(0)) {
866
/* Might be a second negTokenTarg packet */
867
char *kerb_mech = NULL;
869
status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
871
if (!NT_STATUS_IS_OK(status)) {
872
/* Kill the intermediate vuid */
873
invalidate_vuid(vuid);
874
reply_nterror(req, nt_status_squash(status));
878
DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
879
(unsigned long)secblob.length));
881
if (kerb_mech && ((lp_security()==SEC_ADS) ||
882
USE_KERBEROS_KEYTAB)) {
883
bool destroy_vuid = True;
884
reply_spnego_kerberos(req, &secblob, kerb_mech,
885
vuid, &destroy_vuid);
886
data_blob_free(&secblob);
887
data_blob_free(&auth);
889
/* Kill the intermediate vuid */
890
invalidate_vuid(vuid);
892
SAFE_FREE(kerb_mech);
896
/* Can't blunder into NTLMSSP auth if we have
900
/* Kill the intermediate vuid */
901
invalidate_vuid(vuid);
902
DEBUG(3,("reply_spnego_auth: network "
903
"misconfiguration, client sent us a "
904
"krb5 ticket and kerberos security "
906
reply_nterror(req, nt_status_squash(
907
NT_STATUS_LOGON_FAILURE));
908
SAFE_FREE(kerb_mech);
912
/* If we get here it wasn't a negTokenTarg auth packet. */
913
data_blob_free(&secblob);
915
if (!*auth_ntlmssp_state) {
916
status = auth_ntlmssp_start(auth_ntlmssp_state);
917
if (!NT_STATUS_IS_OK(status)) {
918
/* Kill the intermediate vuid */
919
invalidate_vuid(vuid);
920
reply_nterror(req, nt_status_squash(status));
925
status = auth_ntlmssp_update(*auth_ntlmssp_state,
928
data_blob_free(&auth);
930
/* Don't send the mechid as we've already sent this (RFC4178). */
932
reply_spnego_ntlmssp(req, vuid,
934
&auth_reply, status, NULL, true);
936
data_blob_free(&auth_reply);
938
/* and tell smbd that we have already replied to this packet */
942
/****************************************************************************
943
Delete an entry on the list.
944
****************************************************************************/
946
static void delete_partial_auth(struct pending_auth_data *pad)
951
DLIST_REMOVE(pd_list, pad);
952
data_blob_free(&pad->partial_data);
956
/****************************************************************************
957
Search for a partial SPNEGO auth fragment matching an smbpid.
958
****************************************************************************/
960
static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
962
struct pending_auth_data *pad;
964
for (pad = pd_list; pad; pad = pad->next) {
965
if (pad->smbpid == smbpid) {
972
/****************************************************************************
973
Check the size of an SPNEGO blob. If we need more return
974
NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
975
the blob to be more than 64k.
976
****************************************************************************/
978
static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
981
struct pending_auth_data *pad = NULL;
983
size_t needed_len = 0;
985
pad = get_pending_auth_data(smbpid);
987
/* Ensure we have some data. */
988
if (pblob->length == 0) {
989
/* Caller can cope. */
990
DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
991
delete_partial_auth(pad);
995
/* Were we waiting for more data ? */
998
size_t copy_len = MIN(65536, pblob->length);
1000
/* Integer wrap paranoia.... */
1002
if (pad->partial_data.length + copy_len <
1003
pad->partial_data.length ||
1004
pad->partial_data.length + copy_len < copy_len) {
1006
DEBUG(2,("check_spnego_blob_complete: integer wrap "
1007
"pad->partial_data.length = %u, "
1009
(unsigned int)pad->partial_data.length,
1010
(unsigned int)copy_len ));
1012
delete_partial_auth(pad);
1013
return NT_STATUS_INVALID_PARAMETER;
1016
DEBUG(10,("check_spnego_blob_complete: "
1017
"pad->partial_data.length = %u, "
1018
"pad->needed_len = %u, "
1020
"pblob->length = %u,\n",
1021
(unsigned int)pad->partial_data.length,
1022
(unsigned int)pad->needed_len,
1023
(unsigned int)copy_len,
1024
(unsigned int)pblob->length ));
1026
tmp_blob = data_blob(NULL,
1027
pad->partial_data.length + copy_len);
1029
/* Concatenate the two (up to copy_len) bytes. */
1030
memcpy(tmp_blob.data,
1031
pad->partial_data.data,
1032
pad->partial_data.length);
1033
memcpy(tmp_blob.data + pad->partial_data.length,
1037
/* Replace the partial data. */
1038
data_blob_free(&pad->partial_data);
1039
pad->partial_data = tmp_blob;
1040
ZERO_STRUCT(tmp_blob);
1043
if (pblob->length >= pad->needed_len) {
1044
/* Yes, replace pblob. */
1045
data_blob_free(pblob);
1046
*pblob = pad->partial_data;
1047
ZERO_STRUCT(pad->partial_data);
1048
delete_partial_auth(pad);
1049
return NT_STATUS_OK;
1052
/* Still need more data. */
1053
pad->needed_len -= copy_len;
1054
return NT_STATUS_MORE_PROCESSING_REQUIRED;
1057
if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1058
(pblob->data[0] != ASN1_CONTEXT(1))) {
1059
/* Not something we can determine the
1062
return NT_STATUS_OK;
1065
/* This is a new SPNEGO sessionsetup - see if
1066
* the data given in this blob is enough.
1069
data = asn1_init(NULL);
1071
return NT_STATUS_NO_MEMORY;
1074
asn1_load(data, *pblob);
1075
asn1_start_tag(data, pblob->data[0]);
1076
if (data->has_error || data->nesting == NULL) {
1078
/* Let caller catch. */
1079
return NT_STATUS_OK;
1082
/* Integer wrap paranoia.... */
1084
if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1085
data->nesting->taglen + data->nesting->start < data->nesting->start) {
1087
DEBUG(2,("check_spnego_blob_complete: integer wrap "
1088
"data.nesting->taglen = %u, "
1089
"data.nesting->start = %u\n",
1090
(unsigned int)data->nesting->taglen,
1091
(unsigned int)data->nesting->start ));
1094
return NT_STATUS_INVALID_PARAMETER;
1097
/* Total length of the needed asn1 is the tag length
1098
* plus the current offset. */
1100
needed_len = data->nesting->taglen + data->nesting->start;
1103
DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1104
"pblob->length = %u\n",
1105
(unsigned int)needed_len,
1106
(unsigned int)pblob->length ));
1108
if (needed_len <= pblob->length) {
1109
/* Nothing to do - blob is complete. */
1110
return NT_STATUS_OK;
1113
/* Refuse the blob if it's bigger than 64k. */
1114
if (needed_len > 65536) {
1115
DEBUG(2,("check_spnego_blob_complete: needed_len "
1117
(unsigned int)needed_len ));
1118
return NT_STATUS_INVALID_PARAMETER;
1121
/* We must store this blob until complete. */
1122
if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1123
return NT_STATUS_NO_MEMORY;
1125
pad->needed_len = needed_len - pblob->length;
1126
pad->partial_data = data_blob(pblob->data, pblob->length);
1127
if (pad->partial_data.data == NULL) {
1129
return NT_STATUS_NO_MEMORY;
1131
pad->smbpid = smbpid;
1133
DLIST_ADD(pd_list, pad);
1135
return NT_STATUS_MORE_PROCESSING_REQUIRED;
1138
/****************************************************************************
1139
Reply to a session setup command.
1140
conn POINTER CAN BE NULL HERE !
1141
****************************************************************************/
1143
static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1149
const char *native_os;
1150
const char *native_lanman;
1151
const char *primary_domain;
1153
uint16 data_blob_len = SVAL(req->vwv+7, 0);
1154
enum remote_arch_types ra_type = get_remote_arch();
1155
int vuid = req->vuid;
1156
user_struct *vuser = NULL;
1157
NTSTATUS status = NT_STATUS_OK;
1158
uint16 smbpid = req->smbpid;
1160
DEBUG(3,("Doing spnego session setup\n"));
1162
if (global_client_caps == 0) {
1163
global_client_caps = IVAL(req->vwv+10, 0);
1165
if (!(global_client_caps & CAP_STATUS32)) {
1166
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1173
if (data_blob_len == 0) {
1174
/* an invalid request */
1175
reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1179
bufrem = smbreq_bufrem(req, p);
1180
/* pull the spnego blob */
1181
blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1184
file_save("negotiate.dat", blob1.data, blob1.length);
1187
p2 = (char *)req->buf + blob1.length;
1189
p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1191
native_os = tmp ? tmp : "";
1193
p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1195
native_lanman = tmp ? tmp : "";
1197
p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1199
primary_domain = tmp ? tmp : "";
1201
DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1202
native_os, native_lanman, primary_domain));
1204
if ( ra_type == RA_WIN2K ) {
1205
/* Vista sets neither the OS or lanman strings */
1207
if ( !strlen(native_os) && !strlen(native_lanman) )
1208
set_remote_arch(RA_VISTA);
1210
/* Windows 2003 doesn't set the native lanman string,
1211
but does set primary domain which is a bug I think */
1213
if ( !strlen(native_lanman) ) {
1214
ra_lanman_string( primary_domain );
1216
ra_lanman_string( native_lanman );
1220
/* Did we get a valid vuid ? */
1221
if (!is_partial_auth_vuid(vuid)) {
1222
/* No, then try and see if this is an intermediate sessionsetup
1223
* for a large SPNEGO packet. */
1224
struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1226
DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1227
"pending vuid %u\n",
1228
(unsigned int)pad->vuid ));
1233
/* Do we have a valid vuid now ? */
1234
if (!is_partial_auth_vuid(vuid)) {
1235
/* No, start a new authentication setup. */
1236
vuid = register_initial_vuid();
1237
if (vuid == UID_FIELD_INVALID) {
1238
data_blob_free(&blob1);
1239
reply_nterror(req, nt_status_squash(
1240
NT_STATUS_INVALID_PARAMETER));
1245
vuser = get_partial_auth_user_struct(vuid);
1246
/* This MUST be valid. */
1248
smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1251
/* Large (greater than 4k) SPNEGO blobs are split into multiple
1252
* sessionsetup requests as the Windows limit on the security blob
1253
* field is 4k. Bug #4400. JRA.
1256
status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1257
if (!NT_STATUS_IS_OK(status)) {
1258
if (!NT_STATUS_EQUAL(status,
1259
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1260
/* Real error - kill the intermediate vuid */
1261
invalidate_vuid(vuid);
1263
data_blob_free(&blob1);
1264
reply_nterror(req, nt_status_squash(status));
1268
if (blob1.data[0] == ASN1_APPLICATION(0)) {
1270
/* its a negTokenTarg packet */
1272
reply_spnego_negotiate(req, vuid, blob1,
1273
&vuser->auth_ntlmssp_state);
1274
data_blob_free(&blob1);
1278
if (blob1.data[0] == ASN1_CONTEXT(1)) {
1280
/* its a auth packet */
1282
reply_spnego_auth(req, vuid, blob1,
1283
&vuser->auth_ntlmssp_state);
1284
data_blob_free(&blob1);
1288
if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1291
if (!vuser->auth_ntlmssp_state) {
1292
status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1293
if (!NT_STATUS_IS_OK(status)) {
1294
/* Kill the intermediate vuid */
1295
invalidate_vuid(vuid);
1296
data_blob_free(&blob1);
1297
reply_nterror(req, nt_status_squash(status));
1302
status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1305
data_blob_free(&blob1);
1307
reply_spnego_ntlmssp(req, vuid,
1308
&vuser->auth_ntlmssp_state,
1309
&chal, status, OID_NTLMSSP, false);
1310
data_blob_free(&chal);
1314
/* what sort of packet is this? */
1315
DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1317
data_blob_free(&blob1);
1319
reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1322
/****************************************************************************
1323
On new VC == 0, shutdown *all* old connections and users.
1324
It seems that only NT4.x does this. At W2K and above (XP etc.).
1325
a new session setup with VC==0 is ignored.
1326
****************************************************************************/
1328
static int shutdown_other_smbds(struct db_record *rec,
1329
const struct connections_key *key,
1330
const struct connections_data *crec,
1333
const char *ip = (const char *)private_data;
1335
if (!process_exists(crec->pid)) {
1339
if (procid_is_me(&crec->pid)) {
1343
if (strcmp(ip, crec->addr) != 0) {
1347
DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1348
"(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1350
messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1355
static void setup_new_vc_session(void)
1357
char addr[INET6_ADDRSTRLEN];
1359
DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1360
"compatible we would close all old resources.\n"));
1363
invalidate_all_vuids();
1365
if (lp_reset_on_zero_vc()) {
1366
connections_forall(shutdown_other_smbds,
1367
CONST_DISCARD(void *,
1368
client_addr(get_client_fd(),addr,sizeof(addr))));
1372
/****************************************************************************
1373
Reply to a session setup command.
1374
****************************************************************************/
1376
void reply_sesssetup_and_X(struct smb_request *req)
1382
DATA_BLOB plaintext_password;
1385
fstring sub_user; /* Sainitised username for substituion */
1387
const char *native_os;
1388
const char *native_lanman;
1389
const char *primary_domain;
1390
auth_usersupplied_info *user_info = NULL;
1391
auth_serversupplied_info *server_info = NULL;
1392
uint16 smb_flag2 = req->flags2;
1396
bool doencrypt = global_encrypted_passwords_negotiated;
1398
START_PROFILE(SMBsesssetupX);
1400
ZERO_STRUCT(lm_resp);
1401
ZERO_STRUCT(nt_resp);
1402
ZERO_STRUCT(plaintext_password);
1404
DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1406
/* a SPNEGO session setup has 12 command words, whereas a normal
1407
NT1 session setup has 13. See the cifs spec. */
1408
if (req->wct == 12 &&
1409
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1411
if (!global_spnego_negotiated) {
1412
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1413
"at SPNEGO session setup when it was not "
1415
reply_nterror(req, nt_status_squash(
1416
NT_STATUS_LOGON_FAILURE));
1417
END_PROFILE(SMBsesssetupX);
1421
if (SVAL(req->vwv+4, 0) == 0) {
1422
setup_new_vc_session();
1425
reply_sesssetup_and_X_spnego(req);
1426
END_PROFILE(SMBsesssetupX);
1430
smb_bufsize = SVAL(req->vwv+2, 0);
1432
if (Protocol < PROTOCOL_NT1) {
1433
uint16 passlen1 = SVAL(req->vwv+7, 0);
1435
/* Never do NT status codes with protocols before NT1 as we
1436
* don't get client caps. */
1437
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1439
if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1440
reply_nterror(req, nt_status_squash(
1441
NT_STATUS_INVALID_PARAMETER));
1442
END_PROFILE(SMBsesssetupX);
1447
lm_resp = data_blob(req->buf, passlen1);
1449
plaintext_password = data_blob(req->buf, passlen1+1);
1450
/* Ensure null termination */
1451
plaintext_password.data[passlen1] = 0;
1454
srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1455
req->buf + passlen1, STR_TERMINATE);
1456
user = tmp ? tmp : "";
1461
uint16 passlen1 = SVAL(req->vwv+7, 0);
1462
uint16 passlen2 = SVAL(req->vwv+8, 0);
1463
enum remote_arch_types ra_type = get_remote_arch();
1464
const uint8_t *p = req->buf;
1465
const uint8_t *save_p = req->buf;
1469
if(global_client_caps == 0) {
1470
global_client_caps = IVAL(req->vwv+11, 0);
1472
if (!(global_client_caps & CAP_STATUS32)) {
1473
remove_from_common_flags2(
1474
FLAGS2_32_BIT_ERROR_CODES);
1477
/* client_caps is used as final determination if
1478
* client is NT or Win95. This is needed to return
1479
* the correct error codes in some circumstances.
1482
if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1483
ra_type == RA_WIN95) {
1484
if(!(global_client_caps & (CAP_NT_SMBS|
1486
set_remote_arch( RA_WIN95);
1492
/* both Win95 and WinNT stuff up the password
1493
* lengths for non-encrypting systems. Uggh.
1495
if passlen1==24 its a win95 system, and its setting
1496
the password length incorrectly. Luckily it still
1497
works with the default code because Win95 will null
1498
terminate the password anyway
1500
if passlen1>0 and passlen2>0 then maybe its a NT box
1501
and its setting passlen2 to some random value which
1502
really stuffs things up. we need to fix that one. */
1504
if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1510
/* check for nasty tricks */
1511
if (passlen1 > MAX_PASS_LEN
1512
|| passlen1 > smbreq_bufrem(req, p)) {
1513
reply_nterror(req, nt_status_squash(
1514
NT_STATUS_INVALID_PARAMETER));
1515
END_PROFILE(SMBsesssetupX);
1519
if (passlen2 > MAX_PASS_LEN
1520
|| passlen2 > smbreq_bufrem(req, p+passlen1)) {
1521
reply_nterror(req, nt_status_squash(
1522
NT_STATUS_INVALID_PARAMETER));
1523
END_PROFILE(SMBsesssetupX);
1527
/* Save the lanman2 password and the NT md4 password. */
1529
if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1534
lm_resp = data_blob(p, passlen1);
1535
nt_resp = data_blob(p+passlen1, passlen2);
1536
} else if (lp_security() != SEC_SHARE) {
1538
* In share level we should ignore any passwords, so
1539
* only read them if we're not.
1542
bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1544
if (unic && (passlen2 == 0) && passlen1) {
1545
/* Only a ascii plaintext password was sent. */
1546
(void)srvstr_pull_talloc(talloc_tos(),
1552
STR_TERMINATE|STR_ASCII);
1554
(void)srvstr_pull_talloc(talloc_tos(),
1559
unic ? passlen2 : passlen1,
1563
reply_nterror(req, nt_status_squash(
1564
NT_STATUS_INVALID_PARAMETER));
1565
END_PROFILE(SMBsesssetupX);
1568
plaintext_password = data_blob(pass, strlen(pass)+1);
1571
p += passlen1 + passlen2;
1573
p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1575
user = tmp ? tmp : "";
1577
p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1579
domain = tmp ? tmp : "";
1581
p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1583
native_os = tmp ? tmp : "";
1585
p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1587
native_lanman = tmp ? tmp : "";
1589
/* not documented or decoded by Ethereal but there is one more
1590
* string in the extra bytes which is the same as the
1591
* PrimaryDomain when using extended security. Windows NT 4
1592
* and 2003 use this string to store the native lanman string.
1593
* Windows 9x does not include a string here at all so we have
1594
* to check if we have any extra bytes left */
1596
byte_count = SVAL(req->vwv+13, 0);
1597
if ( PTR_DIFF(p, save_p) < byte_count) {
1598
p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1600
primary_domain = tmp ? tmp : "";
1602
primary_domain = talloc_strdup(talloc_tos(), "null");
1605
DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1606
"PrimaryDomain=[%s]\n",
1607
domain, native_os, native_lanman, primary_domain));
1609
if ( ra_type == RA_WIN2K ) {
1610
if ( strlen(native_lanman) == 0 )
1611
ra_lanman_string( primary_domain );
1613
ra_lanman_string( native_lanman );
1618
if (SVAL(req->vwv+4, 0) == 0) {
1619
setup_new_vc_session();
1622
DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1623
domain, user, get_remote_machine_name()));
1626
if (global_spnego_negotiated) {
1628
/* This has to be here, because this is a perfectly
1629
* valid behaviour for guest logons :-( */
1631
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1632
"at 'normal' session setup after "
1633
"negotiating spnego.\n"));
1634
reply_nterror(req, nt_status_squash(
1635
NT_STATUS_LOGON_FAILURE));
1636
END_PROFILE(SMBsesssetupX);
1639
fstrcpy(sub_user, user);
1641
fstrcpy(sub_user, lp_guestaccount());
1644
sub_set_smb_name(sub_user);
1646
reload_services(True);
1648
if (lp_security() == SEC_SHARE) {
1649
/* In share level we should ignore any passwords */
1651
data_blob_free(&lm_resp);
1652
data_blob_free(&nt_resp);
1653
data_blob_clear_free(&plaintext_password);
1655
map_username(sub_user);
1656
add_session_user(sub_user);
1657
add_session_workgroup(domain);
1658
/* Then force it to null for the benfit of the code below */
1664
nt_status = check_guest_password(&server_info);
1666
} else if (doencrypt) {
1667
if (!negprot_global_auth_context) {
1668
DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1669
"session setup without negprot denied!\n"));
1670
reply_nterror(req, nt_status_squash(
1671
NT_STATUS_LOGON_FAILURE));
1672
END_PROFILE(SMBsesssetupX);
1675
nt_status = make_user_info_for_reply_enc(&user_info, user,
1678
if (NT_STATUS_IS_OK(nt_status)) {
1679
nt_status = negprot_global_auth_context->check_ntlm_password(
1680
negprot_global_auth_context,
1685
struct auth_context *plaintext_auth_context = NULL;
1687
nt_status = make_auth_context_subsystem(
1688
&plaintext_auth_context);
1690
if (NT_STATUS_IS_OK(nt_status)) {
1693
plaintext_auth_context->get_ntlm_challenge(
1694
plaintext_auth_context, chal);
1696
if (!make_user_info_for_reply(&user_info,
1698
plaintext_password)) {
1699
nt_status = NT_STATUS_NO_MEMORY;
1702
if (NT_STATUS_IS_OK(nt_status)) {
1703
nt_status = plaintext_auth_context->check_ntlm_password(
1704
plaintext_auth_context,
1708
(plaintext_auth_context->free)(
1709
&plaintext_auth_context);
1714
free_user_info(&user_info);
1716
if (!NT_STATUS_IS_OK(nt_status)) {
1717
nt_status = do_map_to_guest(nt_status, &server_info,
1721
if (!NT_STATUS_IS_OK(nt_status)) {
1722
data_blob_free(&nt_resp);
1723
data_blob_free(&lm_resp);
1724
data_blob_clear_free(&plaintext_password);
1725
reply_nterror(req, nt_status_squash(nt_status));
1726
END_PROFILE(SMBsesssetupX);
1730
/* Ensure we can't possible take a code path leading to a
1733
reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1734
END_PROFILE(SMBsesssetupX);
1738
if (!server_info->ptok) {
1739
nt_status = create_local_token(server_info);
1741
if (!NT_STATUS_IS_OK(nt_status)) {
1742
DEBUG(10, ("create_local_token failed: %s\n",
1743
nt_errstr(nt_status)));
1744
data_blob_free(&nt_resp);
1745
data_blob_free(&lm_resp);
1746
data_blob_clear_free(&plaintext_password);
1747
reply_nterror(req, nt_status_squash(nt_status));
1748
END_PROFILE(SMBsesssetupX);
1753
data_blob_clear_free(&plaintext_password);
1755
/* it's ok - setup a reply */
1756
reply_outbuf(req, 3, 0);
1757
if (Protocol >= PROTOCOL_NT1) {
1758
push_signature(&req->outbuf);
1759
/* perhaps grab OS version here?? */
1762
if (server_info->guest) {
1763
SSVAL(req->outbuf,smb_vwv2,1);
1766
/* register the name and uid as being validated, so further connections
1767
to a uid can get through without a password, on the same VC */
1769
if (lp_security() == SEC_SHARE) {
1770
sess_vuid = UID_FIELD_INVALID;
1771
TALLOC_FREE(server_info);
1773
/* Ignore the initial vuid. */
1774
sess_vuid = register_initial_vuid();
1775
if (sess_vuid == UID_FIELD_INVALID) {
1776
data_blob_free(&nt_resp);
1777
data_blob_free(&lm_resp);
1778
reply_nterror(req, nt_status_squash(
1779
NT_STATUS_LOGON_FAILURE));
1780
END_PROFILE(SMBsesssetupX);
1783
/* register_existing_vuid keeps the server info */
1784
sess_vuid = register_existing_vuid(sess_vuid,
1786
nt_resp.data ? nt_resp : lm_resp,
1788
if (sess_vuid == UID_FIELD_INVALID) {
1789
data_blob_free(&nt_resp);
1790
data_blob_free(&lm_resp);
1791
reply_nterror(req, nt_status_squash(
1792
NT_STATUS_LOGON_FAILURE));
1793
END_PROFILE(SMBsesssetupX);
1797
/* current_user_info is changed on new vuid */
1798
reload_services( True );
1800
sessionsetup_start_signing_engine(server_info, req->inbuf);
1803
data_blob_free(&nt_resp);
1804
data_blob_free(&lm_resp);
1806
SSVAL(req->outbuf,smb_uid,sess_vuid);
1807
SSVAL(req->inbuf,smb_uid,sess_vuid);
1808
req->vuid = sess_vuid;
1810
if (!done_sesssetup)
1811
max_send = MIN(max_send,smb_bufsize);
1813
done_sesssetup = True;
1815
END_PROFILE(SMBsesssetupX);