Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/auth/ntlmssp/ntlmssp_client.c
Line
Count
Source
1
/*
2
   Unix SMB/Netbios implementation.
3
   Version 3.0
4
   handle NLTMSSP, client server side parsing
5
6
   Copyright (C) Andrew Tridgell      2001
7
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
8
   Copyright (C) Stefan Metzmacher 2005
9
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
struct auth_session_info;
25
26
#include "includes.h"
27
#include "auth/ntlmssp/ntlmssp.h"
28
#include "../libcli/auth/libcli_auth.h"
29
#include "auth/credentials/credentials.h"
30
#include "auth/gensec/gensec.h"
31
#include "auth/gensec/gensec_internal.h"
32
#include "param/param.h"
33
#include "auth/ntlmssp/ntlmssp_private.h"
34
#include "../librpc/gen_ndr/ndr_ntlmssp.h"
35
#include "../auth/ntlmssp/ntlmssp_ndr.h"
36
#include "../nsswitch/libwbclient/wbclient.h"
37
38
#include "lib/crypto/gnutls_helpers.h"
39
#include <gnutls/gnutls.h>
40
#include <gnutls/crypto.h>
41
42
#undef DBGC_CLASS
43
0
#define DBGC_CLASS DBGC_AUTH
44
45
/*********************************************************************
46
 Client side NTLMSSP
47
*********************************************************************/
48
49
/**
50
 * Next state function for the Initial packet
51
 *
52
 * @param ntlmssp_state NTLMSSP State
53
 * @param out_mem_ctx The DATA_BLOB *out will be allocated on this context
54
 * @param in A NULL data blob (input ignored)
55
 * @param out The initial negotiate request to the server, as an talloc()ed DATA_BLOB, on out_mem_ctx
56
 * @return Errors or NT_STATUS_OK.
57
 */
58
59
NTSTATUS ntlmssp_client_initial(struct gensec_security *gensec_security,
60
        TALLOC_CTX *out_mem_ctx,
61
        DATA_BLOB in, DATA_BLOB *out)
62
0
{
63
0
  struct gensec_ntlmssp_context *gensec_ntlmssp =
64
0
    talloc_get_type_abort(gensec_security->private_data,
65
0
              struct gensec_ntlmssp_context);
66
0
  struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
67
0
  NTSTATUS status;
68
0
  const DATA_BLOB version_blob = ntlmssp_version_blob();
69
70
  /* generate the ntlmssp negotiate packet */
71
0
  status = msrpc_gen(out_mem_ctx,
72
0
      out, "CddAAb",
73
0
      "NTLMSSP",
74
0
      NTLMSSP_NEGOTIATE,
75
0
      ntlmssp_state->neg_flags,
76
0
      "", /* domain */
77
0
      "", /* workstation */
78
0
      version_blob.data, version_blob.length);
79
0
  if (!NT_STATUS_IS_OK(status)) {
80
0
    DEBUG(0, ("ntlmssp_client_initial: failed to generate "
81
0
        "ntlmssp negotiate packet\n"));
82
0
    return status;
83
0
  }
84
85
0
  if (DEBUGLEVEL >= 10) {
86
0
    struct NEGOTIATE_MESSAGE *negotiate = talloc(
87
0
      ntlmssp_state, struct NEGOTIATE_MESSAGE);
88
0
    if (negotiate != NULL) {
89
0
      status = ntlmssp_pull_NEGOTIATE_MESSAGE(
90
0
        out, negotiate, negotiate);
91
0
      if (NT_STATUS_IS_OK(status)) {
92
0
        NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
93
0
            negotiate);
94
0
      }
95
0
      TALLOC_FREE(negotiate);
96
0
    }
97
0
  }
98
99
0
  ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
100
0
                   *out);
101
0
  if (ntlmssp_state->negotiate_blob.length != out->length) {
102
0
    return NT_STATUS_NO_MEMORY;
103
0
  }
104
105
0
  ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
106
107
0
  return NT_STATUS_MORE_PROCESSING_REQUIRED;
108
0
}
109
110
NTSTATUS gensec_ntlmssp_resume_ccache(struct gensec_security *gensec_security,
111
        TALLOC_CTX *out_mem_ctx,
112
        DATA_BLOB in, DATA_BLOB *out)
113
0
{
114
0
  struct gensec_ntlmssp_context *gensec_ntlmssp =
115
0
    talloc_get_type_abort(gensec_security->private_data,
116
0
              struct gensec_ntlmssp_context);
117
0
  struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
118
0
  uint32_t neg_flags = 0;
119
0
  uint32_t ntlmssp_command;
120
0
  NTSTATUS status;
121
0
  bool ok;
122
123
0
  *out = data_blob_null;
124
125
0
  if (in.length == 0) {
126
    /*
127
     * This is compat code for older callers
128
     * which were missing the "initial_blob"/"negotiate_blob".
129
     *
130
     * That means we can't calculate the NTLMSSP_MIC
131
     * field correctly and need to force the
132
     * old_spnego behaviour.
133
     */
134
0
    DEBUG(10, ("%s: in.length==%u force_old_spnego!\n",
135
0
         __func__, (unsigned int)in.length));
136
0
    ntlmssp_state->force_old_spnego = true;
137
0
    ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
138
0
    ntlmssp_state->required_flags = 0;
139
0
    ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
140
0
    return NT_STATUS_MORE_PROCESSING_REQUIRED;
141
0
  }
142
143
  /* parse the NTLMSSP packet */
144
145
0
  ok = msrpc_parse(ntlmssp_state, &in, "Cdd",
146
0
       "NTLMSSP",
147
0
       &ntlmssp_command,
148
0
       &neg_flags);
149
0
  if (!ok) {
150
0
    DEBUG(1, ("%s: failed to parse NTLMSSP Negotiate of length %u\n",
151
0
      __func__, (unsigned int)in.length));
152
0
    dump_data(2, in.data, in.length);
153
0
    return NT_STATUS_INVALID_PARAMETER;
154
0
  }
155
156
0
  if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
157
0
    DEBUG(1, ("%s: no NTLMSSP Negotiate message (length %u)\n",
158
0
      __func__, (unsigned int)in.length));
159
0
    dump_data(2, in.data, in.length);
160
0
    return NT_STATUS_INVALID_PARAMETER;
161
0
  }
162
163
0
  ntlmssp_state->neg_flags = neg_flags;
164
0
  DEBUG(3, ("Imported Negotiate flags:\n"));
165
0
  debug_ntlmssp_flags(neg_flags);
166
167
0
  if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
168
0
    ntlmssp_state->unicode = true;
169
0
  } else {
170
0
    ntlmssp_state->unicode = false;
171
0
  }
172
173
0
  if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
174
0
    gensec_security->want_features |= GENSEC_FEATURE_SIGN;
175
0
  }
176
177
0
  if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
178
0
    gensec_security->want_features |= GENSEC_FEATURE_SEAL;
179
0
  }
180
181
0
  ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
182
0
  ntlmssp_state->required_flags = 0;
183
184
0
  if (DEBUGLEVEL >= 10) {
185
0
    struct NEGOTIATE_MESSAGE *negotiate = talloc(
186
0
      ntlmssp_state, struct NEGOTIATE_MESSAGE);
187
0
    if (negotiate != NULL) {
188
0
      status = ntlmssp_pull_NEGOTIATE_MESSAGE(
189
0
        &in, negotiate, negotiate);
190
0
      if (NT_STATUS_IS_OK(status)) {
191
0
        NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
192
0
            negotiate);
193
0
      }
194
0
      TALLOC_FREE(negotiate);
195
0
    }
196
0
  }
197
198
0
  ntlmssp_state->negotiate_blob = data_blob_dup_talloc(ntlmssp_state,
199
0
                   in);
200
0
  if (ntlmssp_state->negotiate_blob.length != in.length) {
201
0
    return NT_STATUS_NO_MEMORY;
202
0
  }
203
204
0
  ntlmssp_state->expected_state = NTLMSSP_CHALLENGE;
205
206
0
  return NT_STATUS_MORE_PROCESSING_REQUIRED;
207
0
}
208
209
/**
210
 * Next state function for the Challenge Packet.  Generate an auth packet.
211
 *
212
 * @param gensec_security GENSEC state
213
 * @param out_mem_ctx Memory context for *out
214
 * @param in The server challnege, as a DATA_BLOB.  reply.data must be NULL
215
 * @param out The next request (auth packet) to the server, as an allocated DATA_BLOB, on the out_mem_ctx context
216
 * @return Errors or NT_STATUS_OK.
217
 */
218
219
NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
220
          TALLOC_CTX *out_mem_ctx,
221
          const DATA_BLOB in, DATA_BLOB *out)
222
0
{
223
0
  struct gensec_ntlmssp_context *gensec_ntlmssp =
224
0
    talloc_get_type_abort(gensec_security->private_data,
225
0
              struct gensec_ntlmssp_context);
226
0
  struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
227
0
  uint32_t chal_flags, ntlmssp_command, unkn1 = 0, unkn2 = 0;
228
0
  DATA_BLOB server_domain_blob;
229
0
  DATA_BLOB challenge_blob;
230
0
  DATA_BLOB target_info = {};
231
0
  char *server_domain;
232
0
  const char *chal_parse_string;
233
0
  const char *chal_parse_string_short = NULL;
234
0
  const char *auth_gen_string;
235
0
  DATA_BLOB lm_response = {};
236
0
  DATA_BLOB nt_response = {};
237
0
  DATA_BLOB session_key = {};
238
0
  DATA_BLOB lm_session_key = {};
239
0
  DATA_BLOB encrypted_session_key = {};
240
0
  NTSTATUS nt_status;
241
0
  int flags = 0;
242
0
  const char *user = NULL, *domain = NULL, *workstation = NULL;
243
0
  bool is_anonymous = false;
244
0
  const DATA_BLOB version_blob = ntlmssp_version_blob();
245
0
  const NTTIME *server_timestamp = NULL;
246
0
  uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
247
0
  DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
248
0
  gnutls_hmac_hd_t hmac_hnd = NULL;
249
0
  int rc;
250
251
0
  TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
252
0
  if (!mem_ctx) {
253
0
    return NT_STATUS_NO_MEMORY;
254
0
  }
255
256
0
  if (!msrpc_parse(mem_ctx,
257
0
       &in, "CdBd",
258
0
       "NTLMSSP",
259
0
       &ntlmssp_command,
260
0
       &server_domain_blob,
261
0
       &chal_flags)) {
262
0
    DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
263
0
    dump_data(2, in.data, in.length);
264
0
    talloc_free(mem_ctx);
265
266
0
    return NT_STATUS_INVALID_PARAMETER;
267
0
  }
268
269
0
  data_blob_free(&server_domain_blob);
270
271
0
  DEBUG(3, ("Got challenge flags:\n"));
272
0
  debug_ntlmssp_flags(chal_flags);
273
274
0
  nt_status = ntlmssp_handle_neg_flags(ntlmssp_state,
275
0
               chal_flags, "challenge");
276
0
  if (!NT_STATUS_IS_OK(nt_status)) {
277
0
    return nt_status;
278
0
  }
279
280
0
  if (ntlmssp_state->unicode) {
281
0
    if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
282
0
      chal_parse_string = "CdUdbddB";
283
0
    } else {
284
0
      chal_parse_string = "CdUdbdd";
285
0
      chal_parse_string_short = "CdUdb";
286
0
    }
287
0
    auth_gen_string = "CdBBUUUBdbb";
288
0
  } else {
289
0
    if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
290
0
      chal_parse_string = "CdAdbddB";
291
0
    } else {
292
0
      chal_parse_string = "CdAdbdd";
293
0
      chal_parse_string_short = "CdAdb";
294
0
    }
295
296
0
    auth_gen_string = "CdBBAAABdbb";
297
0
  }
298
299
0
  if (!msrpc_parse(mem_ctx,
300
0
       &in, chal_parse_string,
301
0
       "NTLMSSP",
302
0
       &ntlmssp_command,
303
0
       &server_domain,
304
0
       &chal_flags,
305
0
       &challenge_blob, 8,
306
0
       &unkn1, &unkn2,
307
0
       &target_info)) {
308
309
0
    bool ok = false;
310
311
0
    DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
312
313
0
    if (chal_parse_string_short != NULL) {
314
      /*
315
       * In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
316
       * is not used, some NTLMSSP servers don't return
317
       * the unused unkn1 and unkn2 fields.
318
       * See bug:
319
       * https://bugzilla.samba.org/show_bug.cgi?id=10016
320
       * for packet traces.
321
       * Try and parse again without them.
322
       */
323
0
      ok = msrpc_parse(mem_ctx,
324
0
        &in, chal_parse_string_short,
325
0
        "NTLMSSP",
326
0
        &ntlmssp_command,
327
0
        &server_domain,
328
0
        &chal_flags,
329
0
        &challenge_blob, 8);
330
0
      if (!ok) {
331
0
        DEBUG(1, ("Failed to short parse "
332
0
          "the NTLMSSP Challenge: (#2)\n"));
333
0
      }
334
0
    }
335
336
0
    if (!ok) {
337
0
      dump_data(2, in.data, in.length);
338
0
      talloc_free(mem_ctx);
339
0
      return NT_STATUS_INVALID_PARAMETER;
340
0
    }
341
0
  }
342
343
0
  if (DEBUGLEVEL >= 10) {
344
0
    struct CHALLENGE_MESSAGE *challenge =
345
0
      talloc(ntlmssp_state, struct CHALLENGE_MESSAGE);
346
0
    if (challenge != NULL) {
347
0
      NTSTATUS status;
348
0
      challenge->NegotiateFlags = chal_flags;
349
0
      status = ntlmssp_pull_CHALLENGE_MESSAGE(
350
0
          &in, challenge, challenge);
351
0
      if (NT_STATUS_IS_OK(status)) {
352
0
        NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
353
0
            challenge);
354
0
      }
355
0
      TALLOC_FREE(challenge);
356
0
    }
357
0
  }
358
359
0
  if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
360
0
    ntlmssp_state->server.is_standalone = true;
361
0
  } else {
362
0
    ntlmssp_state->server.is_standalone = false;
363
0
  }
364
  /* TODO: parse struct_blob and fill in the rest */
365
0
  ntlmssp_state->server.netbios_name = "";
366
0
  ntlmssp_state->server.netbios_domain = talloc_move(ntlmssp_state, &server_domain);
367
0
  ntlmssp_state->server.dns_name = "";
368
0
  ntlmssp_state->server.dns_domain = "";
369
370
0
  if (challenge_blob.length != 8) {
371
0
    talloc_free(mem_ctx);
372
0
    return NT_STATUS_INVALID_PARAMETER;
373
0
  }
374
375
0
  is_anonymous = cli_credentials_is_anonymous(gensec_security->credentials);
376
0
  cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx,
377
0
             &user, &domain);
378
379
0
  workstation = cli_credentials_get_workstation(gensec_security->credentials);
380
381
0
  if (user == NULL) {
382
0
    DEBUG(10, ("User is NULL, returning INVALID_PARAMETER\n"));
383
0
    return NT_STATUS_INVALID_PARAMETER;
384
0
  }
385
386
0
  if (domain == NULL) {
387
0
    DEBUG(10, ("Domain is NULL, returning INVALID_PARAMETER\n"));
388
0
    return NT_STATUS_INVALID_PARAMETER;
389
0
  }
390
391
0
  if (workstation == NULL) {
392
0
    DEBUG(10, ("Workstation is NULL, returning INVALID_PARAMETER\n"));
393
0
    return NT_STATUS_INVALID_PARAMETER;
394
0
  }
395
396
0
  if (is_anonymous) {
397
0
    ntlmssp_state->neg_flags |= NTLMSSP_ANONYMOUS;
398
    /*
399
     * don't use the ccache for anonymous auth
400
     */
401
0
    ntlmssp_state->use_ccache = false;
402
0
  }
403
0
  if (ntlmssp_state->use_ccache) {
404
0
    struct samr_Password *nt_hash = NULL;
405
406
    /*
407
     * If we have a password given we don't
408
     * use the ccache
409
     */
410
0
    nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials,
411
0
                  mem_ctx);
412
0
    if (nt_hash != NULL) {
413
0
      TALLOC_FREE(nt_hash);
414
0
      ntlmssp_state->use_ccache = false;
415
0
    }
416
0
  }
417
418
0
  if (ntlmssp_state->use_ccache) {
419
0
    struct wbcCredentialCacheParams params;
420
0
    struct wbcCredentialCacheInfo *info = NULL;
421
0
    struct wbcAuthErrorInfo *error = NULL;
422
0
    struct wbcNamedBlob auth_blobs[2];
423
0
    const struct wbcBlob *wbc_auth_blob = NULL;
424
0
    const struct wbcBlob *wbc_session_key = NULL;
425
0
    wbcErr wbc_status;
426
0
    size_t i;
427
0
    bool new_spnego = false;
428
429
0
    params.account_name = user;
430
0
    params.domain_name = domain;
431
0
    params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
432
433
0
    auth_blobs[0].name = "challenge_blob";
434
0
    auth_blobs[0].flags = 0;
435
0
    auth_blobs[0].blob.data = in.data;
436
0
    auth_blobs[0].blob.length = in.length;
437
0
    auth_blobs[1].name = "negotiate_blob";
438
0
    auth_blobs[1].flags = 0;
439
0
    auth_blobs[1].blob.data = ntlmssp_state->negotiate_blob.data;
440
0
    auth_blobs[1].blob.length = ntlmssp_state->negotiate_blob.length;
441
0
    params.num_blobs = ARRAY_SIZE(auth_blobs);
442
0
    params.blobs = auth_blobs;
443
444
0
    wbc_status = wbcCredentialCache(&params, &info, &error);
445
0
    wbcFreeMemory(error);
446
0
    if (!WBC_ERROR_IS_OK(wbc_status)) {
447
0
      return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
448
0
    }
449
450
0
    for (i=0; i<info->num_blobs; i++) {
451
0
      if (strequal(info->blobs[i].name, "auth_blob")) {
452
0
        wbc_auth_blob = &info->blobs[i].blob;
453
0
      }
454
0
      if (strequal(info->blobs[i].name, "session_key")) {
455
0
        wbc_session_key = &info->blobs[i].blob;
456
0
      }
457
0
      if (strequal(info->blobs[i].name, "new_spnego")) {
458
0
        new_spnego = true;
459
0
      }
460
0
    }
461
0
    if ((wbc_auth_blob == NULL) || (wbc_session_key == NULL)) {
462
0
      wbcFreeMemory(info);
463
0
      return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
464
0
    }
465
466
0
    session_key = data_blob_talloc_s(mem_ctx,
467
0
             wbc_session_key->data,
468
0
             wbc_session_key->length);
469
0
    if (session_key.length != wbc_session_key->length) {
470
0
      wbcFreeMemory(info);
471
0
      return NT_STATUS_NO_MEMORY;
472
0
    }
473
0
    *out = data_blob_talloc_s(mem_ctx,
474
0
            wbc_auth_blob->data,
475
0
            wbc_auth_blob->length);
476
0
    if (out->length != wbc_auth_blob->length) {
477
0
      wbcFreeMemory(info);
478
0
      return NT_STATUS_NO_MEMORY;
479
0
    }
480
0
    ntlmssp_state->new_spnego = new_spnego;
481
482
0
    wbcFreeMemory(info);
483
0
    goto done;
484
0
  }
485
486
0
  if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
487
0
    flags |= CLI_CRED_NTLM2;
488
0
  }
489
0
  if (ntlmssp_state->use_ntlmv2) {
490
0
    flags |= CLI_CRED_NTLMv2_AUTH;
491
0
  }
492
0
  if (ntlmssp_state->use_nt_response) {
493
0
    flags |= CLI_CRED_NTLM_AUTH;
494
0
  }
495
0
  if (ntlmssp_state->allow_lm_response) {
496
0
    flags |= CLI_CRED_LANMAN_AUTH;
497
0
  }
498
499
0
  if (target_info.length != 0 && !is_anonymous) {
500
0
    struct AV_PAIR *pairs = NULL;
501
0
    uint32_t count = 0;
502
0
    enum ndr_err_code err;
503
0
    struct AV_PAIR *timestamp = NULL;
504
0
    struct AV_PAIR *eol = NULL;
505
0
    uint32_t i = 0;
506
0
    const char *service = NULL;
507
0
    const char *hostname = NULL;
508
509
0
    err = ndr_pull_struct_blob(&target_info,
510
0
          ntlmssp_state,
511
0
          &ntlmssp_state->server.av_pair_list,
512
0
          (ndr_pull_flags_fn_t)ndr_pull_AV_PAIR_LIST);
513
0
    if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
514
0
      return ndr_map_error2ntstatus(err);
515
0
    }
516
517
0
    count = ntlmssp_state->server.av_pair_list.count;
518
    /*
519
     * We need room for Flags, SingleHost,
520
     * ChannelBindings and Target
521
     */
522
0
    pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR,
523
0
            count + 4);
524
0
    if (pairs == NULL) {
525
0
      return NT_STATUS_NO_MEMORY;
526
0
    }
527
528
0
    for (i = 0; i < count; i++) {
529
0
      pairs[i] = ntlmssp_state->server.av_pair_list.pair[i];
530
0
    }
531
532
0
    ntlmssp_state->client.av_pair_list.count = count;
533
0
    ntlmssp_state->client.av_pair_list.pair = pairs;
534
535
0
    eol = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
536
0
            MsvAvEOL);
537
0
    if (eol == NULL) {
538
0
      return NT_STATUS_INVALID_PARAMETER;
539
0
    }
540
541
0
    timestamp = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
542
0
            MsvAvTimestamp);
543
0
    if (timestamp != NULL) {
544
0
      uint32_t sign_features =
545
0
          GENSEC_FEATURE_SESSION_KEY |
546
0
          GENSEC_FEATURE_SIGN |
547
0
          GENSEC_FEATURE_SEAL;
548
549
0
      server_timestamp = &timestamp->Value.AvTimestamp;
550
551
0
      if (ntlmssp_state->force_old_spnego) {
552
0
        sign_features = 0;
553
0
      }
554
555
0
      if (gensec_security->want_features & sign_features) {
556
0
        struct AV_PAIR *av_flags = NULL;
557
558
0
        av_flags = ndr_ntlmssp_find_av(&ntlmssp_state->client.av_pair_list,
559
0
                     MsvAvFlags);
560
0
        if (av_flags == NULL) {
561
0
          av_flags = eol;
562
0
          eol++;
563
0
          count++;
564
0
          *eol = *av_flags;
565
0
          av_flags->AvId = MsvAvFlags;
566
0
          av_flags->Value.AvFlags = 0;
567
0
        }
568
569
0
        av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
570
0
        ntlmssp_state->new_spnego = true;
571
0
      }
572
0
    }
573
574
0
    {
575
0
      struct AV_PAIR *SingleHost = NULL;
576
577
0
      SingleHost = eol;
578
0
      eol++;
579
0
      count++;
580
0
      *eol = *SingleHost;
581
582
      /*
583
       * This is not really used, but we want to
584
       * add some more random bytes and match
585
       * Windows.
586
       */
587
0
      SingleHost->AvId = MsvAvSingleHost;
588
0
      SingleHost->Value.AvSingleHost.token_info.Flags = 0;
589
0
      SingleHost->Value.AvSingleHost.token_info.TokenIL = 0;
590
0
      generate_random_buffer(SingleHost->Value.AvSingleHost.token_info.MachineId,
591
0
          sizeof(SingleHost->Value.AvSingleHost.token_info.MachineId));
592
0
      SingleHost->Value.AvSingleHost.remaining = data_blob_null;
593
0
    }
594
595
0
    if (!(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL)
596
0
        || gensec_security->channel_bindings != NULL)
597
0
    {
598
0
      struct AV_PAIR *ChannelBindings = NULL;
599
600
0
      ChannelBindings = eol;
601
0
      eol++;
602
0
      count++;
603
0
      *eol = *ChannelBindings;
604
605
0
      ChannelBindings->AvId = MsvChannelBindings;
606
0
      nt_status = ntlmssp_hash_channel_bindings(gensec_security,
607
0
          ChannelBindings->Value.ChannelBindings);
608
0
      if (!NT_STATUS_IS_OK(nt_status)) {
609
0
        return nt_status;
610
0
      }
611
0
    }
612
613
0
    service = gensec_get_target_service(gensec_security);
614
0
    hostname = gensec_get_target_hostname(gensec_security);
615
0
    if (service != NULL && hostname != NULL) {
616
0
      struct AV_PAIR *target = NULL;
617
618
0
      target = eol;
619
0
      eol++;
620
0
      count++;
621
0
      *eol = *target;
622
623
0
      target->AvId = MsvAvTargetName;
624
0
      target->Value.AvTargetName = talloc_asprintf(pairs, "%s/%s",
625
0
                     service,
626
0
                     hostname);
627
0
      if (target->Value.AvTargetName == NULL) {
628
0
        return NT_STATUS_NO_MEMORY;
629
0
      }
630
0
    }
631
632
0
    ntlmssp_state->client.av_pair_list.count = count;
633
0
    ntlmssp_state->client.av_pair_list.pair = pairs;
634
635
0
    err = ndr_push_struct_blob(&target_info,
636
0
          ntlmssp_state,
637
0
          &ntlmssp_state->client.av_pair_list,
638
0
          (ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
639
0
    if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
640
0
      return NT_STATUS_NO_MEMORY;
641
0
    }
642
0
  }
643
644
0
  nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx,
645
0
                  &flags, challenge_blob,
646
0
                  server_timestamp, target_info,
647
0
                  &lm_response, &nt_response,
648
0
                  &lm_session_key, &session_key);
649
0
  if (!NT_STATUS_IS_OK(nt_status)) {
650
0
    return nt_status;
651
0
  }
652
653
0
  if (!(flags & CLI_CRED_LANMAN_AUTH)) {
654
    /* LM Key is still possible, just silly, so we do not
655
     * allow it. Fortunately all LM crypto is off by
656
     * default and we require command line options to end
657
     * up here */
658
0
    ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
659
0
  }
660
661
0
  if (!(flags & CLI_CRED_NTLM2)) {
662
    /* NTLM2 is incompatible... */
663
0
    ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
664
0
  }
665
666
0
  if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
667
0
      && ntlmssp_state->allow_lm_key && lm_session_key.length == 16) {
668
0
    DATA_BLOB new_session_key = data_blob_talloc_s(mem_ctx,
669
0
                     NULL,
670
0
                     16);
671
0
    if (new_session_key.data == NULL) {
672
0
      return NT_STATUS_NO_MEMORY;
673
0
    }
674
0
    if (lm_response.length == 24) {
675
0
      nt_status = SMBsesskeygen_lm_sess_key(lm_session_key.data,
676
0
                    lm_response.data,
677
0
                    new_session_key.data);
678
0
      if (!NT_STATUS_IS_OK(nt_status)) {
679
0
        return nt_status;
680
0
      }
681
0
    } else {
682
0
      static const uint8_t zeros[24];
683
0
      nt_status = SMBsesskeygen_lm_sess_key(lm_session_key.data,
684
0
                                                              zeros,
685
0
                                                              new_session_key.data);
686
0
      if (!NT_STATUS_IS_OK(nt_status)) {
687
0
        return nt_status;
688
0
      }
689
0
    }
690
0
    session_key = new_session_key;
691
0
    dump_data_pw("LM session key\n", session_key.data, session_key.length);
692
0
  }
693
694
695
  /* Key exchange encryptes a new client-generated session key with
696
     the password-derived key */
697
0
  if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
698
    /* Make up a new session key */
699
0
    uint8_t client_session_key[16];
700
0
    gnutls_cipher_hd_t cipher_hnd;
701
0
    gnutls_datum_t enc_session_key = {
702
0
      .data = session_key.data,
703
0
      .size = session_key.length,
704
0
    };
705
706
0
    generate_random_buffer(client_session_key, sizeof(client_session_key));
707
708
    /* Encrypt the new session key with the old one */
709
0
    encrypted_session_key = data_blob_talloc_s(ntlmssp_state,
710
0
               client_session_key, sizeof(client_session_key));
711
0
    if (encrypted_session_key.data == NULL) {
712
0
      nt_status = NT_STATUS_NO_MEMORY;
713
0
      ZERO_ARRAY(client_session_key);
714
0
      goto done;
715
0
    }
716
0
    dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
717
718
0
    rc = gnutls_cipher_init(&cipher_hnd,
719
0
          GNUTLS_CIPHER_ARCFOUR_128,
720
0
          &enc_session_key,
721
0
          NULL);
722
0
    if (rc < 0) {
723
0
      nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
724
0
      ZERO_ARRAY(client_session_key);
725
0
      goto done;
726
0
    }
727
0
    rc = gnutls_cipher_encrypt(cipher_hnd,
728
0
             encrypted_session_key.data,
729
0
             encrypted_session_key.length);
730
0
    gnutls_cipher_deinit(cipher_hnd);
731
0
    if (rc < 0) {
732
0
      nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
733
0
      ZERO_ARRAY(client_session_key);
734
0
      goto done;
735
0
    }
736
737
0
    dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
738
739
    /* Mark the new session key as the 'real' session key */
740
0
    session_key = data_blob_talloc_s(mem_ctx,
741
0
             client_session_key,
742
0
             sizeof(client_session_key));
743
0
    ZERO_ARRAY(client_session_key);
744
0
    if (session_key.data == NULL) {
745
0
      nt_status = NT_STATUS_NO_MEMORY;
746
0
      goto done;
747
0
    }
748
0
  }
749
750
  /* this generates the actual auth packet */
751
0
  nt_status = msrpc_gen(mem_ctx,
752
0
           out, auth_gen_string,
753
0
           "NTLMSSP",
754
0
           NTLMSSP_AUTH,
755
0
           lm_response.data, lm_response.length,
756
0
           nt_response.data, nt_response.length,
757
0
           domain,
758
0
           user,
759
0
           workstation,
760
0
           encrypted_session_key.data, encrypted_session_key.length,
761
0
           ntlmssp_state->neg_flags,
762
0
           version_blob.data, version_blob.length,
763
0
           mic_blob.data, mic_blob.length);
764
0
  if (!NT_STATUS_IS_OK(nt_status)) {
765
0
    talloc_free(mem_ctx);
766
0
    return nt_status;
767
0
  }
768
769
0
  if (DEBUGLEVEL >= 10) {
770
0
    struct AUTHENTICATE_MESSAGE *authenticate =
771
0
      talloc(ntlmssp_state, struct AUTHENTICATE_MESSAGE);
772
0
    if (authenticate != NULL) {
773
0
      NTSTATUS status;
774
0
      authenticate->NegotiateFlags = ntlmssp_state->neg_flags;
775
0
      status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
776
0
        out, authenticate, authenticate);
777
0
      if (NT_STATUS_IS_OK(status)) {
778
0
        NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
779
0
            authenticate);
780
0
      }
781
0
      TALLOC_FREE(authenticate);
782
0
    }
783
0
  }
784
785
  /*
786
   * We always include the MIC, even without:
787
   * av_flags->Value.AvFlags |= NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE;
788
   * ntlmssp_state->new_spnego = true;
789
   *
790
   * This matches a Windows client.
791
   */
792
0
  rc = gnutls_hmac_init(&hmac_hnd,
793
0
            GNUTLS_MAC_MD5,
794
0
       session_key.data,
795
0
       MIN(session_key.length, 64));
796
0
  if (rc < 0) {
797
0
    nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
798
0
    goto done;
799
0
  }
800
801
0
  rc = gnutls_hmac(hmac_hnd,
802
0
       ntlmssp_state->negotiate_blob.data,
803
0
       ntlmssp_state->negotiate_blob.length);
804
0
  if (rc < 0) {
805
0
    gnutls_hmac_deinit(hmac_hnd, NULL);
806
0
    nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
807
0
    goto done;
808
0
  }
809
0
  rc = gnutls_hmac(hmac_hnd, in.data, in.length);
810
0
  if (rc < 0) {
811
0
    gnutls_hmac_deinit(hmac_hnd, NULL);
812
0
    nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
813
0
    goto done;
814
0
  }
815
0
  rc = gnutls_hmac(hmac_hnd, out->data, out->length);
816
0
  if (rc < 0) {
817
0
    gnutls_hmac_deinit(hmac_hnd, NULL);
818
0
    nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
819
0
    goto done;
820
0
  }
821
822
0
  gnutls_hmac_deinit(hmac_hnd, mic_buffer);
823
824
0
  memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
825
0
  ZERO_ARRAY(mic_buffer);
826
827
0
  nt_status = NT_STATUS_OK;
828
0
done:
829
0
  ZERO_ARRAY_LEN(ntlmssp_state->negotiate_blob.data,
830
0
           ntlmssp_state->negotiate_blob.length);
831
0
  data_blob_free(&ntlmssp_state->negotiate_blob);
832
833
0
  ntlmssp_state->session_key = session_key;
834
0
  talloc_steal(ntlmssp_state, session_key.data);
835
836
0
  DEBUG(3, ("NTLMSSP: Set final flags:\n"));
837
0
  debug_ntlmssp_flags(ntlmssp_state->neg_flags);
838
839
0
  talloc_steal(out_mem_ctx, out->data);
840
841
0
  ntlmssp_state->expected_state = NTLMSSP_DONE;
842
843
0
  if (gensec_ntlmssp_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
844
0
    nt_status = ntlmssp_sign_init(ntlmssp_state);
845
0
    if (!NT_STATUS_IS_OK(nt_status)) {
846
0
      DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
847
0
          nt_errstr(nt_status)));
848
0
      talloc_free(mem_ctx);
849
0
      return nt_status;
850
0
    }
851
0
  }
852
853
0
  talloc_free(mem_ctx);
854
0
  return nt_status;
855
0
}
856
857
NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
858
0
{
859
0
  struct gensec_ntlmssp_context *gensec_ntlmssp;
860
0
  struct ntlmssp_state *ntlmssp_state;
861
0
  NTSTATUS nt_status;
862
863
0
  nt_status = gensec_ntlmssp_start(gensec_security);
864
0
  NT_STATUS_NOT_OK_RETURN(nt_status);
865
866
0
  gensec_ntlmssp =
867
0
    talloc_get_type_abort(gensec_security->private_data,
868
0
              struct gensec_ntlmssp_context);
869
870
0
  ntlmssp_state = talloc_zero(gensec_ntlmssp,
871
0
            struct ntlmssp_state);
872
0
  if (!ntlmssp_state) {
873
0
    return NT_STATUS_NO_MEMORY;
874
0
  }
875
876
0
  gensec_ntlmssp->ntlmssp_state = ntlmssp_state;
877
878
0
  ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
879
880
0
  ntlmssp_state->role = NTLMSSP_CLIENT;
881
882
0
  ntlmssp_state->client.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx);
883
0
  ntlmssp_state->client.netbios_name = cli_credentials_get_workstation(gensec_security->credentials);
884
885
0
  ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true);
886
887
0
  ntlmssp_state->use_nt_response = \
888
0
    gensec_setting_bool(gensec_security->settings,
889
0
            "ntlmssp_client",
890
0
            "send_nt_response",
891
0
            true);
892
893
0
  ntlmssp_state->allow_lm_response = lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx);
894
895
0
  ntlmssp_state->allow_lm_key = (ntlmssp_state->allow_lm_response
896
0
                && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false)
897
0
              || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)));
898
899
0
  ntlmssp_state->use_ntlmv2 = lpcfg_client_ntlmv2_auth(gensec_security->settings->lp_ctx);
900
901
0
  ntlmssp_state->force_old_spnego = gensec_setting_bool(gensec_security->settings,
902
0
            "ntlmssp_client", "force_old_spnego", false);
903
904
0
  ntlmssp_state->expected_state = NTLMSSP_INITIAL;
905
906
0
  ntlmssp_state->neg_flags =
907
0
    NTLMSSP_NEGOTIATE_NTLM |
908
0
    NTLMSSP_NEGOTIATE_VERSION |
909
0
    NTLMSSP_REQUEST_TARGET;
910
911
0
  if (ntlmssp_state->unicode) {
912
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
913
0
  } else {
914
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
915
0
  }
916
917
0
  if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) {
918
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;
919
0
  }
920
921
0
  if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "56bit", false)) {
922
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;
923
0
  }
924
925
0
  if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)) {
926
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
927
0
  }
928
929
0
  if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "keyexchange", true)) {
930
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
931
0
  }
932
933
0
  if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "alwayssign", true)) {
934
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
935
0
  }
936
937
0
  if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "ntlm2", true)) {
938
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
939
0
  } else {
940
    /* apparently we can't do ntlmv2 if we don't do ntlm2 */
941
0
    ntlmssp_state->use_ntlmv2 = false;
942
0
  }
943
944
0
  if (ntlmssp_state->use_ntlmv2) {
945
0
    ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_NTLM2;
946
0
    ntlmssp_state->allow_lm_response = false;
947
0
    ntlmssp_state->allow_lm_key = false;
948
0
  }
949
950
0
  if (ntlmssp_state->allow_lm_key) {
951
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
952
0
  }
953
954
0
  if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
955
    /*
956
     * We need to set this to allow a later SetPassword
957
     * via the SAMR pipe to succeed. Strange.... We could
958
     * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
959
     *
960
     * Without this, Windows will not create the master key
961
     * that it thinks is only used for NTLMSSP signing and
962
     * sealing.  (It is actually pulled out and used directly)
963
     *
964
     * We don't require this here as some servers (e.g. NetAPP)
965
     * doesn't support this.
966
     */
967
0
    ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
968
0
  }
969
0
  if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
970
0
    ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
971
972
0
    if (gensec_security->want_features & GENSEC_FEATURE_LDAP_STYLE) {
973
      /*
974
       * We need to handle NTLMSSP_NEGOTIATE_SIGN as
975
       * NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
976
       * is requested.
977
       */
978
0
      ntlmssp_state->force_wrap_seal = true;
979
0
    }
980
0
  }
981
0
  if (ntlmssp_state->force_wrap_seal) {
982
0
    bool ret;
983
984
    /*
985
     * We want also work against old Samba servers
986
     * which didn't had GENSEC_FEATURE_LDAP_STYLE
987
     * we negotiate SEAL too. We may remove this
988
     * in a few years. As all servers should have
989
     * GENSEC_FEATURE_LDAP_STYLE by then.
990
     */
991
0
    ret = gensec_setting_bool(gensec_security->settings,
992
0
            "ntlmssp_client",
993
0
            "ldap_style_send_seal",
994
0
            true);
995
0
    if (ret) {
996
0
      ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
997
0
    }
998
0
  }
999
0
  if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
1000
0
    ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
1001
0
    ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
1002
0
  }
1003
0
  if (gensec_security->want_features & GENSEC_FEATURE_NTLM_CCACHE) {
1004
0
    ntlmssp_state->use_ccache = true;
1005
0
  }
1006
1007
0
  ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
1008
0
  ntlmssp_state->conf_flags = ntlmssp_state->neg_flags;
1009
1010
0
  return NT_STATUS_OK;
1011
0
}
1012
1013
NTSTATUS gensec_ntlmssp_resume_ccache_start(struct gensec_security *gensec_security)
1014
0
{
1015
0
  struct gensec_ntlmssp_context *gensec_ntlmssp = NULL;
1016
0
  NTSTATUS status;
1017
1018
0
  status = gensec_ntlmssp_client_start(gensec_security);
1019
0
  if (!NT_STATUS_IS_OK(status)) {
1020
0
    return status;
1021
0
  }
1022
1023
0
  gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data,
1024
0
                 struct gensec_ntlmssp_context);
1025
0
  gensec_ntlmssp->ntlmssp_state->use_ccache = false;
1026
0
  gensec_ntlmssp->ntlmssp_state->resume_ccache = true;
1027
0
  gensec_ntlmssp->ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
1028
1029
0
  return NT_STATUS_OK;
1030
0
}