~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/sesssetup.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/CIFS implementation.
 
3
   handle SMBsessionsetup
 
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
 
10
 
 
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.
 
15
 
 
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.
 
20
 
 
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/>.
 
23
*/
 
24
 
 
25
#include "includes.h"
 
26
#include "smbd/globals.h"
 
27
 
 
28
extern enum protocol_types Protocol;
 
29
 
 
30
/*
 
31
  on a logon error possibly map the error to success if "map to guest"
 
32
  is set approriately
 
33
*/
 
34
static NTSTATUS do_map_to_guest(NTSTATUS status,
 
35
                                auth_serversupplied_info **server_info,
 
36
                                const char *user, const char *domain)
 
37
{
 
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",
 
42
                                 user, domain));
 
43
                        status = make_server_info_guest(NULL, server_info);
 
44
                }
 
45
        }
 
46
 
 
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",
 
50
                                user));
 
51
                        status = make_server_info_guest(NULL, server_info);
 
52
                }
 
53
        }
 
54
 
 
55
        return status;
 
56
}
 
57
 
 
58
/****************************************************************************
 
59
 Add the standard 'Samba' signature to the end of the session setup.
 
60
****************************************************************************/
 
61
 
 
62
static int push_signature(uint8 **outbuf)
 
63
{
 
64
        char *lanman;
 
65
        int result, tmp;
 
66
 
 
67
        result = 0;
 
68
 
 
69
        tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
 
70
 
 
71
        if (tmp == -1) return -1;
 
72
        result += tmp;
 
73
 
 
74
        if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
 
75
                tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
 
76
                SAFE_FREE(lanman);
 
77
        }
 
78
        else {
 
79
                tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
 
80
        }
 
81
 
 
82
        if (tmp == -1) return -1;
 
83
        result += tmp;
 
84
 
 
85
        tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
 
86
 
 
87
        if (tmp == -1) return -1;
 
88
        result += tmp;
 
89
 
 
90
        return result;
 
91
}
 
92
 
 
93
/****************************************************************************
 
94
 Start the signing engine if needed. Don't fail signing here.
 
95
****************************************************************************/
 
96
 
 
97
static void sessionsetup_start_signing_engine(
 
98
                        const auth_serversupplied_info *server_info,
 
99
                        const uint8 *inbuf)
 
100
{
 
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
 
106
                 * be correct.
 
107
                 */
 
108
                srv_check_sign_mac((char *)inbuf, False);
 
109
        }
 
110
}
 
111
 
 
112
/****************************************************************************
 
113
 Send a security blob via a session setup reply.
 
114
****************************************************************************/
 
115
 
 
116
static void reply_sesssetup_blob(struct smb_request *req,
 
117
                                 DATA_BLOB blob,
 
118
                                 NTSTATUS nt_status)
 
119
{
 
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));
 
123
                return;
 
124
        }
 
125
 
 
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);
 
130
 
 
131
        if ((message_push_blob(&req->outbuf, blob) == -1)
 
132
            || (push_signature(&req->outbuf) == -1)) {
 
133
                reply_nterror(req, NT_STATUS_NO_MEMORY);
 
134
        }
 
135
}
 
136
 
 
137
/****************************************************************************
 
138
 Do a 'guest' logon, getting back the
 
139
****************************************************************************/
 
140
 
 
141
static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
 
142
{
 
143
        struct auth_context *auth_context;
 
144
        auth_usersupplied_info *user_info = NULL;
 
145
 
 
146
        NTSTATUS nt_status;
 
147
        unsigned char chal[8];
 
148
 
 
149
        ZERO_STRUCT(chal);
 
150
 
 
151
        DEBUG(3,("Got anonymous request\n"));
 
152
 
 
153
        if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
 
154
                                        chal))) {
 
155
                return nt_status;
 
156
        }
 
157
 
 
158
        if (!make_user_info_guest(&user_info)) {
 
159
                (auth_context->free)(&auth_context);
 
160
                return NT_STATUS_NO_MEMORY;
 
161
        }
 
162
 
 
163
        nt_status = auth_context->check_ntlm_password(auth_context,
 
164
                                                user_info,
 
165
                                                server_info);
 
166
        (auth_context->free)(&auth_context);
 
167
        free_user_info(&user_info);
 
168
        return nt_status;
 
169
}
 
170
 
 
171
 
 
172
#ifdef HAVE_KRB5
 
173
 
 
174
#if 0
 
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
****************************************************************************/
 
179
 
 
180
static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
 
181
{
 
182
        krb5_context context = NULL;
 
183
        krb5_error_code kerr = 0;
 
184
        krb5_data reply;
 
185
        krb5_principal host_princ = NULL;
 
186
        char *host_princ_s = NULL;
 
187
        bool ret = False;
 
188
 
 
189
        *pblob_out = data_blob_null;
 
190
 
 
191
        initialize_krb5_error_table();
 
192
        kerr = krb5_init_context(&context);
 
193
        if (kerr) {
 
194
                return False;
 
195
        }
 
196
        /* Create server principal. */
 
197
        asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
 
198
        if (!host_princ_s) {
 
199
                goto out;
 
200
        }
 
201
        strlower_m(host_princ_s);
 
202
 
 
203
        kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
 
204
        if (kerr) {
 
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) ));
 
208
                goto out;
 
209
        }
 
210
 
 
211
        kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
 
212
                        host_princ, &reply);
 
213
        if (kerr) {
 
214
                DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
 
215
                        "failed: Error %s\n",
 
216
                        error_message(kerr) ));
 
217
                goto out;
 
218
        }
 
219
 
 
220
        *pblob_out = data_blob(reply.data, reply.length);
 
221
        kerberos_free_data_contents(context,&reply);
 
222
        ret = True;
 
223
 
 
224
  out:
 
225
 
 
226
        if (host_princ_s) {
 
227
                SAFE_FREE(host_princ_s);
 
228
        }
 
229
        if (host_princ) {
 
230
                krb5_free_principal(context, host_princ);
 
231
        }
 
232
        krb5_free_context(context);
 
233
        return ret;
 
234
}
 
235
#endif
 
236
 
 
237
/****************************************************************************
 
238
 Reply to a session setup spnego negotiate packet for kerberos.
 
239
****************************************************************************/
 
240
 
 
241
static void reply_spnego_kerberos(struct smb_request *req,
 
242
                                  DATA_BLOB *secblob,
 
243
                                  const char *mechOID,
 
244
                                  uint16 vuid,
 
245
                                  bool *p_invalidate_vuid)
 
246
{
 
247
        TALLOC_CTX *mem_ctx;
 
248
        DATA_BLOB ticket;
 
249
        char *client, *p, *domain;
 
250
        fstring netbios_domain_name;
 
251
        struct passwd *pw;
 
252
        fstring user;
 
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;
 
259
        uint8 tok_id[2];
 
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;
 
265
 
 
266
        ZERO_STRUCT(ticket);
 
267
        ZERO_STRUCT(ap_rep);
 
268
        ZERO_STRUCT(ap_rep_wrapped);
 
269
        ZERO_STRUCT(response);
 
270
 
 
271
        /* Normally we will always invalidate the intermediate vuid. */
 
272
        *p_invalidate_vuid = True;
 
273
 
 
274
        mem_ctx = talloc_init("reply_spnego_kerberos");
 
275
        if (mem_ctx == NULL) {
 
276
                reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
 
277
                return;
 
278
        }
 
279
 
 
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));
 
283
                return;
 
284
        }
 
285
 
 
286
        ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
 
287
                                &client, &pac_data, &ap_rep,
 
288
                                &session_key, True);
 
289
 
 
290
        data_blob_free(&ticket);
 
291
 
 
292
        if (!NT_STATUS_IS_OK(ret)) {
 
293
#if 0
 
294
                /* Experiment that failed.
 
295
                 * See "only happens with a KDC" comment below. */
 
296
 
 
297
                if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
 
298
 
 
299
                        /*
 
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.
 
307
                         */
 
308
 
 
309
                        bool ok = make_krb5_skew_error(&ap_rep);
 
310
                        if (!ok) {
 
311
                                talloc_destroy(mem_ctx);
 
312
                                return ERROR_NT(nt_status_squash(
 
313
                                                NT_STATUS_LOGON_FAILURE));
 
314
                        }
 
315
                        ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
 
316
                                        TOK_ID_KRB_ERROR);
 
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);
 
321
 
 
322
                        /*
 
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.
 
326
                         */
 
327
 
 
328
                        *p_invalidate_vuid = False;
 
329
 
 
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 */
 
335
                }
 
336
#else
 
337
                if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
 
338
                        ret = NT_STATUS_LOGON_FAILURE;
 
339
                }
 
340
#endif
 
341
                DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
 
342
                                nt_errstr(ret)));
 
343
                talloc_destroy(mem_ctx);
 
344
                reply_nterror(req, nt_status_squash(ret));
 
345
                return;
 
346
        }
 
347
 
 
348
        DEBUG(3,("Ticket name is [%s]\n", client));
 
349
 
 
350
        p = strchr_m(client, '@');
 
351
        if (!p) {
 
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));
 
357
                return;
 
358
        }
 
359
 
 
360
        *p = 0;
 
361
 
 
362
        /* save the PAC data if we have it */
 
363
 
 
364
        if (pac_data) {
 
365
                logon_info = get_logon_info_from_pac(pac_data);
 
366
                if (logon_info) {
 
367
                        netsamlogon_cache_store( client, &logon_info->info3 );
 
368
                }
 
369
        }
 
370
 
 
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));
 
379
                        return;
 
380
                }
 
381
        }
 
382
 
 
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? */
 
385
 
 
386
        domain = p+1;
 
387
 
 
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));
 
393
 
 
394
        } else {
 
395
 
 
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. */
 
402
 
 
403
                wbcErr wbc_status;
 
404
                struct wbcDomainInfo *info = NULL;
 
405
 
 
406
                DEBUG(10, ("Mapping [%s] to short name\n", domain));
 
407
 
 
408
                wbc_status = wbcDomainInfo(domain, &info);
 
409
 
 
410
                if (WBC_ERROR_IS_OK(wbc_status)) {
 
411
 
 
412
                        fstrcpy(netbios_domain_name,
 
413
                                info->short_name);
 
414
 
 
415
                        wbcFreeMemory(info);
 
416
                        domain = netbios_domain_name;
 
417
                        DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
 
418
                } else {
 
419
                        DEBUG(3, ("Could not find short name: %s\n",
 
420
                                wbcErrorString(wbc_status)));
 
421
                }
 
422
        }
 
423
 
 
424
        fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
 
425
 
 
426
        /* lookup the passwd struct, create a new user if necessary */
 
427
 
 
428
        username_was_mapped = map_username( user );
 
429
 
 
430
        pw = smb_getpwnam( mem_ctx, user, real_username, True );
 
431
 
 
432
        if (pw) {
 
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));
 
444
                        return;
 
445
                }
 
446
        }
 
447
 
 
448
        if (!pw) {
 
449
 
 
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 */
 
453
 
 
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 );
 
458
                }
 
459
 
 
460
                /* extra sanity check that the guest account is valid */
 
461
 
 
462
                if ( !pw ) {
 
463
                        DEBUG(1,("Username %s is invalid on this system\n",
 
464
                                user));
 
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));
 
470
                        return;
 
471
                }
 
472
        }
 
473
 
 
474
        /* setup the string used by %U */
 
475
 
 
476
        sub_set_smb_name( real_username );
 
477
        reload_services(True);
 
478
 
 
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() */
 
484
 
 
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",
 
489
                                 nt_errstr(ret)));
 
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));
 
494
                        return;
 
495
                }
 
496
 
 
497
        } else {
 
498
                ret = make_server_info_pw(&server_info, real_username, pw);
 
499
 
 
500
                if ( !NT_STATUS_IS_OK(ret) ) {
 
501
                        DEBUG(1,("make_server_info_pw failed: %s!\n",
 
502
                                 nt_errstr(ret)));
 
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));
 
507
                        return;
 
508
                }
 
509
 
 
510
                /* make_server_info_pw does not set the domain. Without this
 
511
                 * we end up with the local netbios name in substitutions for
 
512
                 * %D. */
 
513
 
 
514
                if (server_info->sam_account != NULL) {
 
515
                        pdb_set_domain(server_info->sam_account,
 
516
                                        domain, PDB_SET);
 
517
                }
 
518
        }
 
519
 
 
520
        server_info->nss_token |= username_was_mapped;
 
521
 
 
522
        /* we need to build the token for the user. make_server_info_guest()
 
523
           already does this */
 
524
 
 
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",
 
529
                                nt_errstr(ret)));
 
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));
 
535
                        return;
 
536
                }
 
537
        }
 
538
 
 
539
        if (!is_partial_auth_vuid(sess_vuid)) {
 
540
                sess_vuid = register_initial_vuid();
 
541
        }
 
542
 
 
543
        data_blob_free(&server_info->user_session_key);
 
544
        server_info->user_session_key = session_key;
 
545
        session_key = data_blob_null;
 
546
 
 
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
 
550
         * it.... */
 
551
 
 
552
        sess_vuid = register_existing_vuid(sess_vuid,
 
553
                                        server_info,
 
554
                                        nullblob,
 
555
                                        client);
 
556
 
 
557
        reply_outbuf(req, 4, 0);
 
558
        SSVAL(req->outbuf,smb_uid,sess_vuid);
 
559
 
 
560
        if (sess_vuid == UID_FIELD_INVALID ) {
 
561
                ret = NT_STATUS_LOGON_FAILURE;
 
562
        } else {
 
563
                /* current_user_info is changed on new vuid */
 
564
                reload_services( True );
 
565
 
 
566
                SSVAL(req->outbuf, smb_vwv3, 0);
 
567
 
 
568
                if (server_info->guest) {
 
569
                        SSVAL(req->outbuf,smb_vwv2,1);
 
570
                }
 
571
 
 
572
                SSVAL(req->outbuf, smb_uid, sess_vuid);
 
573
 
 
574
                sessionsetup_start_signing_engine(server_info, req->inbuf);
 
575
                /* Successful logon. Keep this vuid. */
 
576
                *p_invalidate_vuid = False;
 
577
        }
 
578
 
 
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,
 
582
                                TOK_ID_KRB_AP_REP);
 
583
        } else {
 
584
                ap_rep_wrapped = data_blob_null;
 
585
        }
 
586
        response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
 
587
                        mechOID);
 
588
        reply_sesssetup_blob(req, response, ret);
 
589
 
 
590
        data_blob_free(&ap_rep);
 
591
        data_blob_free(&ap_rep_wrapped);
 
592
        data_blob_free(&response);
 
593
        TALLOC_FREE(mem_ctx);
 
594
}
 
595
 
 
596
#endif
 
597
 
 
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
***************************************************************************/
 
605
 
 
606
static void reply_spnego_ntlmssp(struct smb_request *req,
 
607
                                 uint16 vuid,
 
608
                                 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
 
609
                                 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
 
610
                                 const char *OID,
 
611
                                 bool wrap)
 
612
{
 
613
        DATA_BLOB response;
 
614
        struct auth_serversupplied_info *server_info = NULL;
 
615
 
 
616
        if (NT_STATUS_IS_OK(nt_status)) {
 
617
                server_info = (*auth_ntlmssp_state)->server_info;
 
618
        } else {
 
619
                nt_status = do_map_to_guest(nt_status,
 
620
                            &server_info,
 
621
                            (*auth_ntlmssp_state)->ntlmssp_state->user,
 
622
                            (*auth_ntlmssp_state)->ntlmssp_state->domain);
 
623
        }
 
624
 
 
625
        reply_outbuf(req, 4, 0);
 
626
 
 
627
        SSVAL(req->outbuf, smb_uid, vuid);
 
628
 
 
629
        if (NT_STATUS_IS_OK(nt_status)) {
 
630
                DATA_BLOB nullblob = data_blob_null;
 
631
 
 
632
                if (!is_partial_auth_vuid(vuid)) {
 
633
                        nt_status = NT_STATUS_LOGON_FAILURE;
 
634
                        goto out;
 
635
                }
 
636
 
 
637
                data_blob_free(&server_info->user_session_key);
 
638
                server_info->user_session_key =
 
639
                        data_blob_talloc(
 
640
                        server_info,
 
641
                        (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
 
642
                        (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
 
643
 
 
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) !=
 
648
                                        vuid) {
 
649
                        nt_status = NT_STATUS_LOGON_FAILURE;
 
650
                        goto out;
 
651
                }
 
652
 
 
653
                (*auth_ntlmssp_state)->server_info = NULL;
 
654
 
 
655
                /* current_user_info is changed on new vuid */
 
656
                reload_services( True );
 
657
 
 
658
                SSVAL(req->outbuf, smb_vwv3, 0);
 
659
 
 
660
                if (server_info->guest) {
 
661
                        SSVAL(req->outbuf,smb_vwv2,1);
 
662
                }
 
663
 
 
664
                sessionsetup_start_signing_engine(server_info,
 
665
                                                  (uint8 *)req->inbuf);
 
666
        }
 
667
 
 
668
  out:
 
669
 
 
670
        if (wrap) {
 
671
                response = spnego_gen_auth_response(ntlmssp_blob,
 
672
                                nt_status, OID);
 
673
        } else {
 
674
                response = *ntlmssp_blob;
 
675
        }
 
676
 
 
677
        reply_sesssetup_blob(req, response, nt_status);
 
678
        if (wrap) {
 
679
                data_blob_free(&response);
 
680
        }
 
681
 
 
682
        /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
 
683
           and the other end, that we are not finished yet. */
 
684
 
 
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);
 
691
                }
 
692
        }
 
693
}
 
694
 
 
695
/****************************************************************************
 
696
 Is this a krb5 mechanism ?
 
697
****************************************************************************/
 
698
 
 
699
NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
 
700
                DATA_BLOB *pblob_out,
 
701
                char **kerb_mechOID)
 
702
{
 
703
        char *OIDs[ASN1_MAX_OIDS];
 
704
        int i;
 
705
        NTSTATUS ret = NT_STATUS_OK;
 
706
 
 
707
        *kerb_mechOID = NULL;
 
708
 
 
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;
 
712
        }
 
713
 
 
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..
 
717
 
 
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              */
 
723
 
 
724
#ifdef HAVE_KRB5
 
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;
 
730
                }
 
731
        }
 
732
#endif
 
733
 
 
734
        for (i=0;OIDs[i];i++) {
 
735
                DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
 
736
                talloc_free(OIDs[i]);
 
737
        }
 
738
        return ret;
 
739
}
 
740
 
 
741
/****************************************************************************
 
742
 Fall back from krb5 to NTLMSSP.
 
743
****************************************************************************/
 
744
 
 
745
static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
 
746
                                                uint16 vuid)
 
747
{
 
748
        DATA_BLOB response;
 
749
 
 
750
        reply_outbuf(req, 4, 0);
 
751
        SSVAL(req->outbuf,smb_uid,vuid);
 
752
 
 
753
        DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
 
754
                "but set to downgrade to NTLMSSP\n"));
 
755
 
 
756
        response = spnego_gen_auth_response(NULL,
 
757
                        NT_STATUS_MORE_PROCESSING_REQUIRED,
 
758
                        OID_NTLMSSP);
 
759
        reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
 
760
        data_blob_free(&response);
 
761
}
 
762
 
 
763
/****************************************************************************
 
764
 Reply to a session setup spnego negotiate packet.
 
765
****************************************************************************/
 
766
 
 
767
static void reply_spnego_negotiate(struct smb_request *req,
 
768
                                   uint16 vuid,
 
769
                                   DATA_BLOB blob1,
 
770
                                   AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 
771
{
 
772
        DATA_BLOB secblob;
 
773
        DATA_BLOB chal;
 
774
        char *kerb_mech = NULL;
 
775
        NTSTATUS status;
 
776
 
 
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));
 
782
                return;
 
783
        }
 
784
 
 
785
        DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
 
786
                                (unsigned long)secblob.length));
 
787
 
 
788
#ifdef HAVE_KRB5
 
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);
 
795
                if (destroy_vuid) {
 
796
                        /* Kill the intermediate vuid */
 
797
                        invalidate_vuid(vuid);
 
798
                }
 
799
                SAFE_FREE(kerb_mech);
 
800
                return;
 
801
        }
 
802
#endif
 
803
 
 
804
        if (*auth_ntlmssp_state) {
 
805
                auth_ntlmssp_end(auth_ntlmssp_state);
 
806
        }
 
807
 
 
808
        if (kerb_mech) {
 
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);
 
814
                return;
 
815
        }
 
816
 
 
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));
 
822
                return;
 
823
        }
 
824
 
 
825
        status = auth_ntlmssp_update(*auth_ntlmssp_state,
 
826
                                        secblob, &chal);
 
827
 
 
828
        data_blob_free(&secblob);
 
829
 
 
830
        reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
 
831
                             &chal, status, OID_NTLMSSP, true);
 
832
 
 
833
        data_blob_free(&chal);
 
834
 
 
835
        /* already replied */
 
836
        return;
 
837
}
 
838
 
 
839
/****************************************************************************
 
840
 Reply to a session setup spnego auth packet.
 
841
****************************************************************************/
 
842
 
 
843
static void reply_spnego_auth(struct smb_request *req,
 
844
                              uint16 vuid,
 
845
                              DATA_BLOB blob1,
 
846
                              AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 
847
{
 
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;
 
852
 
 
853
        if (!spnego_parse_auth(blob1, &auth)) {
 
854
#if 0
 
855
                file_save("auth.dat", blob1.data, blob1.length);
 
856
#endif
 
857
                /* Kill the intermediate vuid */
 
858
                invalidate_vuid(vuid);
 
859
 
 
860
                reply_nterror(req, nt_status_squash(
 
861
                                      NT_STATUS_LOGON_FAILURE));
 
862
                return;
 
863
        }
 
864
 
 
865
        if (auth.data[0] == ASN1_APPLICATION(0)) {
 
866
                /* Might be a second negTokenTarg packet */
 
867
                char *kerb_mech = NULL;
 
868
 
 
869
                status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
 
870
 
 
871
                if (!NT_STATUS_IS_OK(status)) {
 
872
                        /* Kill the intermediate vuid */
 
873
                        invalidate_vuid(vuid);
 
874
                        reply_nterror(req, nt_status_squash(status));
 
875
                        return;
 
876
                }
 
877
 
 
878
                DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
 
879
                                (unsigned long)secblob.length));
 
880
#ifdef HAVE_KRB5
 
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);
 
888
                        if (destroy_vuid) {
 
889
                                /* Kill the intermediate vuid */
 
890
                                invalidate_vuid(vuid);
 
891
                        }
 
892
                        SAFE_FREE(kerb_mech);
 
893
                        return;
 
894
                }
 
895
#endif
 
896
                /* Can't blunder into NTLMSSP auth if we have
 
897
                 * a krb5 ticket. */
 
898
 
 
899
                if (kerb_mech) {
 
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 "
 
905
                                "not enabled\n"));
 
906
                        reply_nterror(req, nt_status_squash(
 
907
                                        NT_STATUS_LOGON_FAILURE));
 
908
                        SAFE_FREE(kerb_mech);
 
909
                }
 
910
        }
 
911
 
 
912
        /* If we get here it wasn't a negTokenTarg auth packet. */
 
913
        data_blob_free(&secblob);
 
914
 
 
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));
 
921
                        return;
 
922
                }
 
923
        }
 
924
 
 
925
        status = auth_ntlmssp_update(*auth_ntlmssp_state,
 
926
                                        auth, &auth_reply);
 
927
 
 
928
        data_blob_free(&auth);
 
929
 
 
930
        /* Don't send the mechid as we've already sent this (RFC4178). */
 
931
 
 
932
        reply_spnego_ntlmssp(req, vuid,
 
933
                             auth_ntlmssp_state,
 
934
                             &auth_reply, status, NULL, true);
 
935
 
 
936
        data_blob_free(&auth_reply);
 
937
 
 
938
        /* and tell smbd that we have already replied to this packet */
 
939
        return;
 
940
}
 
941
 
 
942
/****************************************************************************
 
943
 Delete an entry on the list.
 
944
****************************************************************************/
 
945
 
 
946
static void delete_partial_auth(struct pending_auth_data *pad)
 
947
{
 
948
        if (!pad) {
 
949
                return;
 
950
        }
 
951
        DLIST_REMOVE(pd_list, pad);
 
952
        data_blob_free(&pad->partial_data);
 
953
        SAFE_FREE(pad);
 
954
}
 
955
 
 
956
/****************************************************************************
 
957
 Search for a partial SPNEGO auth fragment matching an smbpid.
 
958
****************************************************************************/
 
959
 
 
960
static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
 
961
{
 
962
        struct pending_auth_data *pad;
 
963
 
 
964
        for (pad = pd_list; pad; pad = pad->next) {
 
965
                if (pad->smbpid == smbpid) {
 
966
                        break;
 
967
                }
 
968
        }
 
969
        return pad;
 
970
}
 
971
 
 
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
****************************************************************************/
 
977
 
 
978
static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
 
979
                DATA_BLOB *pblob)
 
980
{
 
981
        struct pending_auth_data *pad = NULL;
 
982
        ASN1_DATA *data;
 
983
        size_t needed_len = 0;
 
984
 
 
985
        pad = get_pending_auth_data(smbpid);
 
986
 
 
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);
 
992
                return NT_STATUS_OK;
 
993
        }
 
994
 
 
995
        /* Were we waiting for more data ? */
 
996
        if (pad) {
 
997
                DATA_BLOB tmp_blob;
 
998
                size_t copy_len = MIN(65536, pblob->length);
 
999
 
 
1000
                /* Integer wrap paranoia.... */
 
1001
 
 
1002
                if (pad->partial_data.length + copy_len <
 
1003
                                pad->partial_data.length ||
 
1004
                    pad->partial_data.length + copy_len < copy_len) {
 
1005
 
 
1006
                        DEBUG(2,("check_spnego_blob_complete: integer wrap "
 
1007
                                "pad->partial_data.length = %u, "
 
1008
                                "copy_len = %u\n",
 
1009
                                (unsigned int)pad->partial_data.length,
 
1010
                                (unsigned int)copy_len ));
 
1011
 
 
1012
                        delete_partial_auth(pad);
 
1013
                        return NT_STATUS_INVALID_PARAMETER;
 
1014
                }
 
1015
 
 
1016
                DEBUG(10,("check_spnego_blob_complete: "
 
1017
                        "pad->partial_data.length = %u, "
 
1018
                        "pad->needed_len = %u, "
 
1019
                        "copy_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 ));
 
1025
 
 
1026
                tmp_blob = data_blob(NULL,
 
1027
                                pad->partial_data.length + copy_len);
 
1028
 
 
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,
 
1034
                        pblob->data,
 
1035
                        copy_len);
 
1036
 
 
1037
                /* Replace the partial data. */
 
1038
                data_blob_free(&pad->partial_data);
 
1039
                pad->partial_data = tmp_blob;
 
1040
                ZERO_STRUCT(tmp_blob);
 
1041
 
 
1042
                /* Are we done ? */
 
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;
 
1050
                }
 
1051
 
 
1052
                /* Still need more data. */
 
1053
                pad->needed_len -= copy_len;
 
1054
                return NT_STATUS_MORE_PROCESSING_REQUIRED;
 
1055
        }
 
1056
 
 
1057
        if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
 
1058
            (pblob->data[0] != ASN1_CONTEXT(1))) {
 
1059
                /* Not something we can determine the
 
1060
                 * length of.
 
1061
                 */
 
1062
                return NT_STATUS_OK;
 
1063
        }
 
1064
 
 
1065
        /* This is a new SPNEGO sessionsetup - see if
 
1066
         * the data given in this blob is enough.
 
1067
         */
 
1068
 
 
1069
        data = asn1_init(NULL);
 
1070
        if (data == NULL) {
 
1071
                return NT_STATUS_NO_MEMORY;
 
1072
        }
 
1073
 
 
1074
        asn1_load(data, *pblob);
 
1075
        asn1_start_tag(data, pblob->data[0]);
 
1076
        if (data->has_error || data->nesting == NULL) {
 
1077
                asn1_free(data);
 
1078
                /* Let caller catch. */
 
1079
                return NT_STATUS_OK;
 
1080
        }
 
1081
 
 
1082
        /* Integer wrap paranoia.... */
 
1083
 
 
1084
        if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
 
1085
            data->nesting->taglen + data->nesting->start < data->nesting->start) {
 
1086
 
 
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 ));
 
1092
 
 
1093
                asn1_free(data);
 
1094
                return NT_STATUS_INVALID_PARAMETER;
 
1095
        }
 
1096
 
 
1097
        /* Total length of the needed asn1 is the tag length
 
1098
         * plus the current offset. */
 
1099
 
 
1100
        needed_len = data->nesting->taglen + data->nesting->start;
 
1101
        asn1_free(data);
 
1102
 
 
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 ));
 
1107
 
 
1108
        if (needed_len <= pblob->length) {
 
1109
                /* Nothing to do - blob is complete. */
 
1110
                return NT_STATUS_OK;
 
1111
        }
 
1112
 
 
1113
        /* Refuse the blob if it's bigger than 64k. */
 
1114
        if (needed_len > 65536) {
 
1115
                DEBUG(2,("check_spnego_blob_complete: needed_len "
 
1116
                        "too large (%u)\n",
 
1117
                        (unsigned int)needed_len ));
 
1118
                return NT_STATUS_INVALID_PARAMETER;
 
1119
        }
 
1120
 
 
1121
        /* We must store this blob until complete. */
 
1122
        if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
 
1123
                return NT_STATUS_NO_MEMORY;
 
1124
        }
 
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) {
 
1128
                SAFE_FREE(pad);
 
1129
                return NT_STATUS_NO_MEMORY;
 
1130
        }
 
1131
        pad->smbpid = smbpid;
 
1132
        pad->vuid = vuid;
 
1133
        DLIST_ADD(pd_list, pad);
 
1134
 
 
1135
        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 
1136
}
 
1137
 
 
1138
/****************************************************************************
 
1139
 Reply to a session setup command.
 
1140
 conn POINTER CAN BE NULL HERE !
 
1141
****************************************************************************/
 
1142
 
 
1143
static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
1144
{
 
1145
        const uint8 *p;
 
1146
        DATA_BLOB blob1;
 
1147
        size_t bufrem;
 
1148
        char *tmp;
 
1149
        const char *native_os;
 
1150
        const char *native_lanman;
 
1151
        const char *primary_domain;
 
1152
        const char *p2;
 
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;
 
1159
 
 
1160
        DEBUG(3,("Doing spnego session setup\n"));
 
1161
 
 
1162
        if (global_client_caps == 0) {
 
1163
                global_client_caps = IVAL(req->vwv+10, 0);
 
1164
 
 
1165
                if (!(global_client_caps & CAP_STATUS32)) {
 
1166
                        remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
 
1167
                }
 
1168
 
 
1169
        }
 
1170
 
 
1171
        p = req->buf;
 
1172
 
 
1173
        if (data_blob_len == 0) {
 
1174
                /* an invalid request */
 
1175
                reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
 
1176
                return;
 
1177
        }
 
1178
 
 
1179
        bufrem = smbreq_bufrem(req, p);
 
1180
        /* pull the spnego blob */
 
1181
        blob1 = data_blob(p, MIN(bufrem, data_blob_len));
 
1182
 
 
1183
#if 0
 
1184
        file_save("negotiate.dat", blob1.data, blob1.length);
 
1185
#endif
 
1186
 
 
1187
        p2 = (char *)req->buf + blob1.length;
 
1188
 
 
1189
        p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
 
1190
                                     STR_TERMINATE);
 
1191
        native_os = tmp ? tmp : "";
 
1192
 
 
1193
        p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
 
1194
                                     STR_TERMINATE);
 
1195
        native_lanman = tmp ? tmp : "";
 
1196
 
 
1197
        p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
 
1198
                                     STR_TERMINATE);
 
1199
        primary_domain = tmp ? tmp : "";
 
1200
 
 
1201
        DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
 
1202
                native_os, native_lanman, primary_domain));
 
1203
 
 
1204
        if ( ra_type == RA_WIN2K ) {
 
1205
                /* Vista sets neither the OS or lanman strings */
 
1206
 
 
1207
                if ( !strlen(native_os) && !strlen(native_lanman) )
 
1208
                        set_remote_arch(RA_VISTA);
 
1209
 
 
1210
                /* Windows 2003 doesn't set the native lanman string,
 
1211
                   but does set primary domain which is a bug I think */
 
1212
 
 
1213
                if ( !strlen(native_lanman) ) {
 
1214
                        ra_lanman_string( primary_domain );
 
1215
                } else {
 
1216
                        ra_lanman_string( native_lanman );
 
1217
                }
 
1218
        }
 
1219
 
 
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);
 
1225
                if (pad) {
 
1226
                        DEBUG(10,("reply_sesssetup_and_X_spnego: found "
 
1227
                                "pending vuid %u\n",
 
1228
                                (unsigned int)pad->vuid ));
 
1229
                        vuid = pad->vuid;
 
1230
                }
 
1231
        }
 
1232
 
 
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));
 
1241
                        return;
 
1242
                }
 
1243
        }
 
1244
 
 
1245
        vuser = get_partial_auth_user_struct(vuid);
 
1246
        /* This MUST be valid. */
 
1247
        if (!vuser) {
 
1248
                smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
 
1249
        }
 
1250
 
 
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.
 
1254
         */
 
1255
 
 
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);
 
1262
                }
 
1263
                data_blob_free(&blob1);
 
1264
                reply_nterror(req, nt_status_squash(status));
 
1265
                return;
 
1266
        }
 
1267
 
 
1268
        if (blob1.data[0] == ASN1_APPLICATION(0)) {
 
1269
 
 
1270
                /* its a negTokenTarg packet */
 
1271
 
 
1272
                reply_spnego_negotiate(req, vuid, blob1,
 
1273
                                       &vuser->auth_ntlmssp_state);
 
1274
                data_blob_free(&blob1);
 
1275
                return;
 
1276
        }
 
1277
 
 
1278
        if (blob1.data[0] == ASN1_CONTEXT(1)) {
 
1279
 
 
1280
                /* its a auth packet */
 
1281
 
 
1282
                reply_spnego_auth(req, vuid, blob1,
 
1283
                                  &vuser->auth_ntlmssp_state);
 
1284
                data_blob_free(&blob1);
 
1285
                return;
 
1286
        }
 
1287
 
 
1288
        if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
 
1289
                DATA_BLOB chal;
 
1290
 
 
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));
 
1298
                                return;
 
1299
                        }
 
1300
                }
 
1301
 
 
1302
                status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
 
1303
                                                blob1, &chal);
 
1304
 
 
1305
                data_blob_free(&blob1);
 
1306
 
 
1307
                reply_spnego_ntlmssp(req, vuid,
 
1308
                                     &vuser->auth_ntlmssp_state,
 
1309
                                     &chal, status, OID_NTLMSSP, false);
 
1310
                data_blob_free(&chal);
 
1311
                return;
 
1312
        }
 
1313
 
 
1314
        /* what sort of packet is this? */
 
1315
        DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
 
1316
 
 
1317
        data_blob_free(&blob1);
 
1318
 
 
1319
        reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
 
1320
}
 
1321
 
 
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
****************************************************************************/
 
1327
 
 
1328
static int shutdown_other_smbds(struct db_record *rec,
 
1329
                                const struct connections_key *key,
 
1330
                                const struct connections_data *crec,
 
1331
                                void *private_data)
 
1332
{
 
1333
        const char *ip = (const char *)private_data;
 
1334
 
 
1335
        if (!process_exists(crec->pid)) {
 
1336
                return 0;
 
1337
        }
 
1338
 
 
1339
        if (procid_is_me(&crec->pid)) {
 
1340
                return 0;
 
1341
        }
 
1342
 
 
1343
        if (strcmp(ip, crec->addr) != 0) {
 
1344
                return 0;
 
1345
        }
 
1346
 
 
1347
        DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
 
1348
                 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
 
1349
 
 
1350
        messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
 
1351
                       &data_blob_null);
 
1352
        return 0;
 
1353
}
 
1354
 
 
1355
static void setup_new_vc_session(void)
 
1356
{
 
1357
        char addr[INET6_ADDRSTRLEN];
 
1358
 
 
1359
        DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
 
1360
                "compatible we would close all old resources.\n"));
 
1361
#if 0
 
1362
        conn_close_all();
 
1363
        invalidate_all_vuids();
 
1364
#endif
 
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))));
 
1369
        }
 
1370
}
 
1371
 
 
1372
/****************************************************************************
 
1373
 Reply to a session setup command.
 
1374
****************************************************************************/
 
1375
 
 
1376
void reply_sesssetup_and_X(struct smb_request *req)
 
1377
{
 
1378
        int sess_vuid;
 
1379
        int smb_bufsize;
 
1380
        DATA_BLOB lm_resp;
 
1381
        DATA_BLOB nt_resp;
 
1382
        DATA_BLOB plaintext_password;
 
1383
        char *tmp;
 
1384
        const char *user;
 
1385
        fstring sub_user; /* Sainitised username for substituion */
 
1386
        const char *domain;
 
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;
 
1393
 
 
1394
        NTSTATUS nt_status;
 
1395
 
 
1396
        bool doencrypt = global_encrypted_passwords_negotiated;
 
1397
 
 
1398
        START_PROFILE(SMBsesssetupX);
 
1399
 
 
1400
        ZERO_STRUCT(lm_resp);
 
1401
        ZERO_STRUCT(nt_resp);
 
1402
        ZERO_STRUCT(plaintext_password);
 
1403
 
 
1404
        DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
 
1405
 
 
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)) {
 
1410
 
 
1411
                if (!global_spnego_negotiated) {
 
1412
                        DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
 
1413
                                 "at SPNEGO session setup when it was not "
 
1414
                                 "negotiated.\n"));
 
1415
                        reply_nterror(req, nt_status_squash(
 
1416
                                              NT_STATUS_LOGON_FAILURE));
 
1417
                        END_PROFILE(SMBsesssetupX);
 
1418
                        return;
 
1419
                }
 
1420
 
 
1421
                if (SVAL(req->vwv+4, 0) == 0) {
 
1422
                        setup_new_vc_session();
 
1423
                }
 
1424
 
 
1425
                reply_sesssetup_and_X_spnego(req);
 
1426
                END_PROFILE(SMBsesssetupX);
 
1427
                return;
 
1428
        }
 
1429
 
 
1430
        smb_bufsize = SVAL(req->vwv+2, 0);
 
1431
 
 
1432
        if (Protocol < PROTOCOL_NT1) {
 
1433
                uint16 passlen1 = SVAL(req->vwv+7, 0);
 
1434
 
 
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);
 
1438
 
 
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);
 
1443
                        return;
 
1444
                }
 
1445
 
 
1446
                if (doencrypt) {
 
1447
                        lm_resp = data_blob(req->buf, passlen1);
 
1448
                } else {
 
1449
                        plaintext_password = data_blob(req->buf, passlen1+1);
 
1450
                        /* Ensure null termination */
 
1451
                        plaintext_password.data[passlen1] = 0;
 
1452
                }
 
1453
 
 
1454
                srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
 
1455
                                       req->buf + passlen1, STR_TERMINATE);
 
1456
                user = tmp ? tmp : "";
 
1457
 
 
1458
                domain = "";
 
1459
 
 
1460
        } else {
 
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;
 
1466
                uint16 byte_count;
 
1467
 
 
1468
 
 
1469
                if(global_client_caps == 0) {
 
1470
                        global_client_caps = IVAL(req->vwv+11, 0);
 
1471
 
 
1472
                        if (!(global_client_caps & CAP_STATUS32)) {
 
1473
                                remove_from_common_flags2(
 
1474
                                                FLAGS2_32_BIT_ERROR_CODES);
 
1475
                        }
 
1476
 
 
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.
 
1480
                        */
 
1481
 
 
1482
                        if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
 
1483
                                        ra_type == RA_WIN95) {
 
1484
                                if(!(global_client_caps & (CAP_NT_SMBS|
 
1485
                                                        CAP_STATUS32))) {
 
1486
                                        set_remote_arch( RA_WIN95);
 
1487
                                }
 
1488
                        }
 
1489
                }
 
1490
 
 
1491
                if (!doencrypt) {
 
1492
                        /* both Win95 and WinNT stuff up the password
 
1493
                         * lengths for non-encrypting systems. Uggh.
 
1494
 
 
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
 
1499
 
 
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.  */
 
1503
 
 
1504
                        if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
 
1505
                                        passlen2 != 1) {
 
1506
                                passlen2 = 0;
 
1507
                        }
 
1508
                }
 
1509
 
 
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);
 
1516
                        return;
 
1517
                }
 
1518
 
 
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);
 
1524
                        return;
 
1525
                }
 
1526
 
 
1527
                /* Save the lanman2 password and the NT md4 password. */
 
1528
 
 
1529
                if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
 
1530
                        doencrypt = False;
 
1531
                }
 
1532
 
 
1533
                if (doencrypt) {
 
1534
                        lm_resp = data_blob(p, passlen1);
 
1535
                        nt_resp = data_blob(p+passlen1, passlen2);
 
1536
                } else if (lp_security() != SEC_SHARE) {
 
1537
                        /*
 
1538
                         * In share level we should ignore any passwords, so
 
1539
                         * only read them if we're not.
 
1540
                         */
 
1541
                        char *pass = NULL;
 
1542
                        bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
 
1543
 
 
1544
                        if (unic && (passlen2 == 0) && passlen1) {
 
1545
                                /* Only a ascii plaintext password was sent. */
 
1546
                                (void)srvstr_pull_talloc(talloc_tos(),
 
1547
                                                        req->inbuf,
 
1548
                                                        req->flags2,
 
1549
                                                        &pass,
 
1550
                                                        req->buf,
 
1551
                                                        passlen1,
 
1552
                                                        STR_TERMINATE|STR_ASCII);
 
1553
                        } else {
 
1554
                                (void)srvstr_pull_talloc(talloc_tos(),
 
1555
                                                        req->inbuf,
 
1556
                                                        req->flags2,
 
1557
                                                        &pass,
 
1558
                                                        req->buf,
 
1559
                                                        unic ? passlen2 : passlen1,
 
1560
                                                        STR_TERMINATE);
 
1561
                        }
 
1562
                        if (!pass) {
 
1563
                                reply_nterror(req, nt_status_squash(
 
1564
                                              NT_STATUS_INVALID_PARAMETER));
 
1565
                                END_PROFILE(SMBsesssetupX);
 
1566
                                return;
 
1567
                        }
 
1568
                        plaintext_password = data_blob(pass, strlen(pass)+1);
 
1569
                }
 
1570
 
 
1571
                p += passlen1 + passlen2;
 
1572
 
 
1573
                p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
 
1574
                                            STR_TERMINATE);
 
1575
                user = tmp ? tmp : "";
 
1576
 
 
1577
                p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
 
1578
                                            STR_TERMINATE);
 
1579
                domain = tmp ? tmp : "";
 
1580
 
 
1581
                p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
 
1582
                                            STR_TERMINATE);
 
1583
                native_os = tmp ? tmp : "";
 
1584
 
 
1585
                p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
 
1586
                                            STR_TERMINATE);
 
1587
                native_lanman = tmp ? tmp : "";
 
1588
 
 
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 */
 
1595
 
 
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,
 
1599
                                                    STR_TERMINATE);
 
1600
                        primary_domain = tmp ? tmp : "";
 
1601
                } else {
 
1602
                        primary_domain = talloc_strdup(talloc_tos(), "null");
 
1603
                }
 
1604
 
 
1605
                DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
 
1606
                        "PrimaryDomain=[%s]\n",
 
1607
                        domain, native_os, native_lanman, primary_domain));
 
1608
 
 
1609
                if ( ra_type == RA_WIN2K ) {
 
1610
                        if ( strlen(native_lanman) == 0 )
 
1611
                                ra_lanman_string( primary_domain );
 
1612
                        else
 
1613
                                ra_lanman_string( native_lanman );
 
1614
                }
 
1615
 
 
1616
        }
 
1617
 
 
1618
        if (SVAL(req->vwv+4, 0) == 0) {
 
1619
                setup_new_vc_session();
 
1620
        }
 
1621
 
 
1622
        DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
 
1623
                                domain, user, get_remote_machine_name()));
 
1624
 
 
1625
        if (*user) {
 
1626
                if (global_spnego_negotiated) {
 
1627
 
 
1628
                        /* This has to be here, because this is a perfectly
 
1629
                         * valid behaviour for guest logons :-( */
 
1630
 
 
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);
 
1637
                        return;
 
1638
                }
 
1639
                fstrcpy(sub_user, user);
 
1640
        } else {
 
1641
                fstrcpy(sub_user, lp_guestaccount());
 
1642
        }
 
1643
 
 
1644
        sub_set_smb_name(sub_user);
 
1645
 
 
1646
        reload_services(True);
 
1647
 
 
1648
        if (lp_security() == SEC_SHARE) {
 
1649
                /* In share level we should ignore any passwords */
 
1650
 
 
1651
                data_blob_free(&lm_resp);
 
1652
                data_blob_free(&nt_resp);
 
1653
                data_blob_clear_free(&plaintext_password);
 
1654
 
 
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 */
 
1659
                user = "";
 
1660
        }
 
1661
 
 
1662
        if (!*user) {
 
1663
 
 
1664
                nt_status = check_guest_password(&server_info);
 
1665
 
 
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);
 
1673
                        return;
 
1674
                }
 
1675
                nt_status = make_user_info_for_reply_enc(&user_info, user,
 
1676
                                                domain,
 
1677
                                                lm_resp, nt_resp);
 
1678
                if (NT_STATUS_IS_OK(nt_status)) {
 
1679
                        nt_status = negprot_global_auth_context->check_ntlm_password(
 
1680
                                        negprot_global_auth_context,
 
1681
                                        user_info,
 
1682
                                        &server_info);
 
1683
                }
 
1684
        } else {
 
1685
                struct auth_context *plaintext_auth_context = NULL;
 
1686
 
 
1687
                nt_status = make_auth_context_subsystem(
 
1688
                                &plaintext_auth_context);
 
1689
 
 
1690
                if (NT_STATUS_IS_OK(nt_status)) {
 
1691
                        uint8_t chal[8];
 
1692
 
 
1693
                        plaintext_auth_context->get_ntlm_challenge(
 
1694
                                        plaintext_auth_context, chal);
 
1695
 
 
1696
                        if (!make_user_info_for_reply(&user_info,
 
1697
                                                      user, domain, chal,
 
1698
                                                      plaintext_password)) {
 
1699
                                nt_status = NT_STATUS_NO_MEMORY;
 
1700
                        }
 
1701
 
 
1702
                        if (NT_STATUS_IS_OK(nt_status)) {
 
1703
                                nt_status = plaintext_auth_context->check_ntlm_password(
 
1704
                                                plaintext_auth_context,
 
1705
                                                user_info,
 
1706
                                                &server_info);
 
1707
 
 
1708
                                (plaintext_auth_context->free)(
 
1709
                                                &plaintext_auth_context);
 
1710
                        }
 
1711
                }
 
1712
        }
 
1713
 
 
1714
        free_user_info(&user_info);
 
1715
 
 
1716
        if (!NT_STATUS_IS_OK(nt_status)) {
 
1717
                nt_status = do_map_to_guest(nt_status, &server_info,
 
1718
                                user, domain);
 
1719
        }
 
1720
 
 
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);
 
1727
                return;
 
1728
        }
 
1729
 
 
1730
        /* Ensure we can't possible take a code path leading to a
 
1731
         * null defref. */
 
1732
        if (!server_info) {
 
1733
                reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
 
1734
                END_PROFILE(SMBsesssetupX);
 
1735
                return;
 
1736
        }
 
1737
 
 
1738
        if (!server_info->ptok) {
 
1739
                nt_status = create_local_token(server_info);
 
1740
 
 
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);
 
1749
                        return;
 
1750
                }
 
1751
        }
 
1752
 
 
1753
        data_blob_clear_free(&plaintext_password);
 
1754
 
 
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?? */
 
1760
        }
 
1761
 
 
1762
        if (server_info->guest) {
 
1763
                SSVAL(req->outbuf,smb_vwv2,1);
 
1764
        }
 
1765
 
 
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 */
 
1768
 
 
1769
        if (lp_security() == SEC_SHARE) {
 
1770
                sess_vuid = UID_FIELD_INVALID;
 
1771
                TALLOC_FREE(server_info);
 
1772
        } else {
 
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);
 
1781
                        return;
 
1782
                }
 
1783
                /* register_existing_vuid keeps the server info */
 
1784
                sess_vuid = register_existing_vuid(sess_vuid,
 
1785
                                        server_info,
 
1786
                                        nt_resp.data ? nt_resp : lm_resp,
 
1787
                                        sub_user);
 
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);
 
1794
                        return;
 
1795
                }
 
1796
 
 
1797
                /* current_user_info is changed on new vuid */
 
1798
                reload_services( True );
 
1799
 
 
1800
                sessionsetup_start_signing_engine(server_info, req->inbuf);
 
1801
        }
 
1802
 
 
1803
        data_blob_free(&nt_resp);
 
1804
        data_blob_free(&lm_resp);
 
1805
 
 
1806
        SSVAL(req->outbuf,smb_uid,sess_vuid);
 
1807
        SSVAL(req->inbuf,smb_uid,sess_vuid);
 
1808
        req->vuid = sess_vuid;
 
1809
 
 
1810
        if (!done_sesssetup)
 
1811
                max_send = MIN(max_send,smb_bufsize);
 
1812
 
 
1813
        done_sesssetup = True;
 
1814
 
 
1815
        END_PROFILE(SMBsesssetupX);
 
1816
        chain_reply(req);
 
1817
        return;
 
1818
}