Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/auth/credentials.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   code to manipulate domain credentials
5
6
   Copyright (C) Andrew Tridgell 1997-2003
7
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
8
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
#include "includes.h"
24
#include "system/time.h"
25
#include "librpc/gen_ndr/ndr_schannel.h"
26
#include "libcli/auth/libcli_auth.h"
27
#include "../libcli/security/dom_sid.h"
28
#include "lib/util/util_str_escape.h"
29
30
#include "lib/crypto/gnutls_helpers.h"
31
#include <gnutls/gnutls.h>
32
#include <gnutls/crypto.h>
33
34
#undef netlogon_creds_des_encrypt
35
#undef netlogon_creds_des_decrypt
36
#undef netlogon_creds_arcfour_crypt
37
#undef netlogon_creds_aes_encrypt
38
#undef netlogon_creds_aes_decrypt
39
40
bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge)
41
0
{
42
  /*
43
   * If none of the first 5 bytes of the client challenge is unique, the
44
   * server MUST fail session-key negotiation without further processing
45
   * of the following steps.
46
   */
47
48
0
  if (challenge->data[1] == challenge->data[0] &&
49
0
      challenge->data[2] == challenge->data[0] &&
50
0
      challenge->data[3] == challenge->data[0] &&
51
0
      challenge->data[4] == challenge->data[0])
52
0
  {
53
0
    return false;
54
0
  }
55
56
0
  return true;
57
0
}
58
59
static NTSTATUS netlogon_creds_no_step_check(struct netlogon_creds_CredentialState *creds,
60
               enum dcerpc_AuthType auth_type,
61
               enum dcerpc_AuthLevel auth_level,
62
               bool *skip)
63
0
{
64
0
  *skip = false;
65
66
0
  if (creds == NULL) {
67
0
    return NT_STATUS_ACCESS_DENIED;
68
0
  }
69
70
  /*
71
   * Only if ServerAuthenticateKerberos() was
72
   * used the content of the netr_Authenticator
73
   * values are not checked.
74
   *
75
   * It is independent from the
76
   * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH flag.
77
   */
78
0
  if (creds->authenticate_kerberos) {
79
0
    if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
80
0
      return NT_STATUS_ACCESS_DENIED;
81
0
    }
82
0
    if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
83
0
      return NT_STATUS_ACCESS_DENIED;
84
0
    }
85
0
    *skip = true;
86
0
  }
87
88
0
  return NT_STATUS_OK;
89
0
}
90
91
static NTSTATUS netlogon_creds_no_buffer_crypt(struct netlogon_creds_CredentialState *creds,
92
                 enum dcerpc_AuthType auth_type,
93
                 enum dcerpc_AuthLevel auth_level,
94
                 bool *skip)
95
0
{
96
0
  *skip = false;
97
98
0
  if (creds == NULL) {
99
0
    return NT_STATUS_ACCESS_DENIED;
100
0
  }
101
102
0
  if (creds->authenticate_kerberos) {
103
0
    if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
104
0
      return NT_STATUS_ACCESS_DENIED;
105
0
    }
106
0
    if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
107
0
      return NT_STATUS_ACCESS_DENIED;
108
0
    }
109
0
  }
110
111
  /*
112
   * Even if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH is
113
   * negotiated within ServerAuthenticate3()
114
   * encryption on application buffers is skipped.
115
   *
116
   * Also ServerAuthenticateKerberos() without
117
   * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH uses
118
   * encryption with a random session key.
119
   */
120
0
  if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
121
0
    if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
122
0
      return NT_STATUS_ACCESS_DENIED;
123
0
    }
124
125
0
    *skip = true;
126
0
  }
127
128
0
  return NT_STATUS_OK;
129
0
}
130
131
void netlogon_creds_random_challenge(struct netr_Credential *challenge)
132
0
{
133
0
  ZERO_STRUCTP(challenge);
134
0
  while (!netlogon_creds_is_random_challenge(challenge)) {
135
0
    generate_random_buffer(challenge->data, sizeof(challenge->data));
136
0
  }
137
0
}
138
139
static NTSTATUS netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
140
            const struct netr_Credential *in,
141
            struct netr_Credential *out)
142
0
{
143
0
  NTSTATUS status;
144
0
  int rc;
145
146
0
  if (creds->authenticate_kerberos) {
147
    /*
148
     * The caller should have checked this already...
149
     */
150
0
    return NT_STATUS_INVALID_PARAMETER_MIX;
151
0
  }
152
153
0
  if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
154
0
    memcpy(out->data, in->data, sizeof(out->data));
155
156
0
    status = netlogon_creds_aes_encrypt(creds,
157
0
                out->data,
158
0
                sizeof(out->data));
159
0
    if (!NT_STATUS_IS_OK(status)) {
160
0
      return status;
161
0
    }
162
0
  } else {
163
0
    rc = des_crypt112(out->data, in->data, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
164
0
    if (rc != 0) {
165
0
      return gnutls_error_to_ntstatus(rc,
166
0
              NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
167
0
    }
168
0
  }
169
170
0
  return NT_STATUS_OK;
171
0
}
172
173
/*
174
  initialise the credentials state for old-style 64 bit session keys
175
176
  this call is made after the netr_ServerReqChallenge call
177
*/
178
static NTSTATUS netlogon_creds_init_64bit(struct netlogon_creds_CredentialState *creds,
179
           const struct netr_Credential *client_challenge,
180
           const struct netr_Credential *server_challenge,
181
           const struct samr_Password *machine_password)
182
0
{
183
0
  uint32_t sum[2];
184
0
  uint8_t sum2[8];
185
0
  int rc;
186
187
0
  sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
188
0
  sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
189
190
0
  SIVAL(sum2,0,sum[0]);
191
0
  SIVAL(sum2,4,sum[1]);
192
193
0
  ZERO_ARRAY(creds->session_key);
194
195
0
  rc = des_crypt128(creds->session_key, sum2, machine_password->hash);
196
0
  if (rc != 0) {
197
0
    ZERO_ARRAY(sum);
198
0
    ZERO_ARRAY(sum2);
199
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
200
0
  }
201
202
0
  ZERO_ARRAY(sum);
203
0
  ZERO_ARRAY(sum2);
204
0
  return NT_STATUS_OK;
205
0
}
206
207
/*
208
  initialise the credentials state for ADS-style 128 bit session keys
209
210
  this call is made after the netr_ServerReqChallenge call
211
*/
212
static NTSTATUS netlogon_creds_init_128bit(struct netlogon_creds_CredentialState *creds,
213
               const struct netr_Credential *client_challenge,
214
               const struct netr_Credential *server_challenge,
215
               const struct samr_Password *machine_password)
216
0
{
217
0
  uint8_t zero[4] = {0};
218
0
  uint8_t tmp[gnutls_hash_get_len(GNUTLS_DIG_MD5)];
219
0
  gnutls_hash_hd_t hash_hnd = NULL;
220
0
  int rc;
221
222
0
  ZERO_ARRAY(creds->session_key);
223
224
0
  rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
225
0
  if (rc < 0) {
226
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
227
0
  }
228
229
0
  rc = gnutls_hash(hash_hnd, zero, sizeof(zero));
230
0
  if (rc < 0) {
231
0
    gnutls_hash_deinit(hash_hnd, NULL);
232
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
233
0
  }
234
0
  rc = gnutls_hash(hash_hnd, client_challenge->data, 8);
235
0
  if (rc < 0) {
236
0
    gnutls_hash_deinit(hash_hnd, NULL);
237
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
238
0
  }
239
0
  rc = gnutls_hash(hash_hnd, server_challenge->data, 8);
240
0
  if (rc < 0) {
241
0
    gnutls_hash_deinit(hash_hnd, NULL);
242
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
243
0
  }
244
245
0
  gnutls_hash_deinit(hash_hnd, tmp);
246
247
  /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
248
0
  rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
249
0
            machine_password->hash,
250
0
            sizeof(machine_password->hash),
251
0
            tmp,
252
0
            sizeof(tmp),
253
0
            creds->session_key);
254
0
  ZERO_ARRAY(tmp);
255
256
0
  if (rc < 0) {
257
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
258
0
  }
259
260
0
  return NT_STATUS_OK;
261
0
}
262
263
/*
264
  initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
265
266
  this call is made after the netr_ServerReqChallenge call
267
*/
268
static NTSTATUS netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState *creds,
269
            const struct netr_Credential *client_challenge,
270
            const struct netr_Credential *server_challenge,
271
            const struct samr_Password *machine_password)
272
0
{
273
0
  gnutls_hmac_hd_t hmac_hnd = NULL;
274
0
  uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
275
0
  int rc;
276
277
0
  ZERO_ARRAY(creds->session_key);
278
279
0
  rc = gnutls_hmac_init(&hmac_hnd,
280
0
            GNUTLS_MAC_SHA256,
281
0
            machine_password->hash,
282
0
            sizeof(machine_password->hash));
283
0
  if (rc < 0) {
284
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
285
0
  }
286
0
  rc = gnutls_hmac(hmac_hnd,
287
0
       client_challenge->data,
288
0
       8);
289
0
  if (rc < 0) {
290
0
    gnutls_hmac_deinit(hmac_hnd, NULL);
291
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
292
0
  }
293
0
  rc  = gnutls_hmac(hmac_hnd,
294
0
        server_challenge->data,
295
0
        8);
296
0
  if (rc < 0) {
297
0
    gnutls_hmac_deinit(hmac_hnd, NULL);
298
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
299
0
  }
300
0
  gnutls_hmac_deinit(hmac_hnd, digest);
301
302
0
  memcpy(creds->session_key, digest, sizeof(creds->session_key));
303
304
0
  ZERO_ARRAY(digest);
305
306
0
  return NT_STATUS_OK;
307
0
}
308
309
static NTSTATUS netlogon_creds_first_step(struct netlogon_creds_CredentialState *creds,
310
            const struct netr_Credential *client_challenge,
311
            const struct netr_Credential *server_challenge)
312
0
{
313
0
  NTSTATUS status;
314
315
0
  status = netlogon_creds_step_crypt(creds,
316
0
             client_challenge,
317
0
             &creds->client);
318
0
  if (!NT_STATUS_IS_OK(status)) {
319
0
    return status;
320
0
  }
321
322
0
  status = netlogon_creds_step_crypt(creds,
323
0
             server_challenge,
324
0
             &creds->server);
325
0
  if (!NT_STATUS_IS_OK(status)) {
326
0
    return status;
327
0
  }
328
329
0
  creds->seed = creds->client;
330
331
0
  return NT_STATUS_OK;
332
0
}
333
334
/*
335
  step the credentials to the next element in the chain, updating the
336
  current client and server credentials and the seed
337
*/
338
static NTSTATUS netlogon_creds_step(struct netlogon_creds_CredentialState *creds)
339
0
{
340
0
  struct netr_Credential time_cred;
341
0
  NTSTATUS status;
342
343
0
  if (creds->authenticate_kerberos) {
344
    /* This is only called on the client side */
345
0
    generate_nonce_buffer(creds->seed.data,
346
0
              ARRAY_SIZE(creds->seed.data));
347
0
    generate_nonce_buffer(creds->client.data,
348
0
              ARRAY_SIZE(creds->client.data));
349
0
    generate_nonce_buffer(creds->server.data,
350
0
              ARRAY_SIZE(creds->server.data));
351
0
    return NT_STATUS_OK;
352
0
  }
353
354
0
  DEBUG(5,("\tseed        %08x:%08x\n",
355
0
     IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
356
357
0
  SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
358
0
  SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
359
360
0
  DEBUG(5,("\tseed+time   %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
361
362
0
  status = netlogon_creds_step_crypt(creds,
363
0
             &time_cred,
364
0
             &creds->client);
365
0
  if (!NT_STATUS_IS_OK(status)) {
366
0
    return status;
367
0
  }
368
369
0
  DEBUG(5,("\tCLIENT      %08x:%08x\n",
370
0
     IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
371
372
0
  SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence + 1);
373
0
  SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
374
375
0
  DEBUG(5,("\tseed+time+1 %08x:%08x\n",
376
0
     IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
377
378
0
  status = netlogon_creds_step_crypt(creds, &time_cred, &creds->server);
379
0
  if (!NT_STATUS_IS_OK(status)) {
380
0
    return status;
381
0
  }
382
383
0
  DEBUG(5,("\tSERVER      %08x:%08x\n",
384
0
     IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
385
386
0
  creds->seed = time_cred;
387
388
0
  return NT_STATUS_OK;
389
0
}
390
391
/*
392
  DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
393
*/
394
static NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds,
395
            struct netr_LMSessionKey *key)
396
0
{
397
0
  int rc;
398
0
  struct netr_LMSessionKey tmp;
399
400
0
  rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
401
0
  if (rc < 0) {
402
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
403
0
  }
404
0
  *key = tmp;
405
0
  ZERO_STRUCT(tmp);
406
407
0
  return NT_STATUS_OK;
408
0
}
409
410
/*
411
  DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
412
*/
413
static NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds,
414
            struct netr_LMSessionKey *key)
415
0
{
416
0
  int rc;
417
0
  struct netr_LMSessionKey tmp;
418
419
0
  rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_DECRYPT);
420
0
  if (rc < 0) {
421
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
422
0
  }
423
0
  *key = tmp;
424
0
  ZERO_STRUCT(tmp);
425
426
0
  return NT_STATUS_OK;
427
0
}
428
429
/*
430
  DES encrypt a 16 byte password buffer using the session key
431
*/
432
NTSTATUS netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds,
433
            struct samr_Password *pass)
434
0
{
435
0
  struct samr_Password tmp;
436
0
  int rc;
437
438
0
  rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
439
0
  if (rc < 0) {
440
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
441
0
  }
442
0
  *pass = tmp;
443
0
  ZERO_STRUCT(tmp);
444
445
0
  return NT_STATUS_OK;
446
0
}
447
448
/*
449
  DES decrypt a 16 byte password buffer using the session key
450
*/
451
NTSTATUS netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds,
452
            struct samr_Password *pass)
453
0
{
454
0
  struct samr_Password tmp;
455
0
  int rc;
456
457
0
  rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_DECRYPT);
458
0
  if (rc < 0) {
459
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
460
0
  }
461
0
  *pass = tmp;
462
0
  ZERO_STRUCT(tmp);
463
464
0
  return NT_STATUS_OK;
465
0
}
466
467
/*
468
  ARCFOUR encrypt/decrypt a password buffer using the session key
469
*/
470
NTSTATUS netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds,
471
              uint8_t *data,
472
              size_t len)
473
0
{
474
0
  gnutls_cipher_hd_t cipher_hnd = NULL;
475
0
  gnutls_datum_t session_key = {
476
0
    .data = creds->session_key,
477
0
    .size = sizeof(creds->session_key),
478
0
  };
479
0
  int rc;
480
481
0
  rc = gnutls_cipher_init(&cipher_hnd,
482
0
        GNUTLS_CIPHER_ARCFOUR_128,
483
0
        &session_key,
484
0
        NULL);
485
0
  if (rc < 0) {
486
0
    return gnutls_error_to_ntstatus(rc,
487
0
            NT_STATUS_CRYPTO_SYSTEM_INVALID);
488
0
  }
489
0
  rc = gnutls_cipher_encrypt(cipher_hnd,
490
0
           data,
491
0
           len);
492
0
  gnutls_cipher_deinit(cipher_hnd);
493
0
  if (rc < 0) {
494
0
    return gnutls_error_to_ntstatus(rc,
495
0
            NT_STATUS_CRYPTO_SYSTEM_INVALID);
496
0
  }
497
498
0
  return NT_STATUS_OK;
499
0
}
500
501
/*
502
  AES encrypt a password buffer using the session key
503
*/
504
NTSTATUS netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds,
505
            uint8_t *data,
506
            size_t len)
507
0
{
508
0
  gnutls_cipher_hd_t cipher_hnd = NULL;
509
0
  gnutls_datum_t key = {
510
0
    .data = creds->session_key,
511
0
    .size = sizeof(creds->session_key),
512
0
  };
513
0
  uint32_t iv_size =
514
0
    gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
515
0
  uint8_t _iv[iv_size];
516
0
  gnutls_datum_t iv = {
517
0
    .data = _iv,
518
0
    .size = iv_size,
519
0
  };
520
0
  int rc;
521
522
0
  ZERO_ARRAY(_iv);
523
524
0
  rc = gnutls_cipher_init(&cipher_hnd,
525
0
        GNUTLS_CIPHER_AES_128_CFB8,
526
0
        &key,
527
0
        &iv);
528
0
  if (rc < 0) {
529
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
530
0
  }
531
532
0
  rc = gnutls_cipher_encrypt(cipher_hnd, data, len);
533
0
  gnutls_cipher_deinit(cipher_hnd);
534
0
  if (rc < 0) {
535
0
    return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
536
0
  }
537
538
0
  return NT_STATUS_OK;
539
0
}
540
541
/*
542
  AES decrypt a password buffer using the session key
543
*/
544
NTSTATUS netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
545
0
{
546
0
  gnutls_cipher_hd_t cipher_hnd = NULL;
547
0
  gnutls_datum_t key = {
548
0
    .data = creds->session_key,
549
0
    .size = sizeof(creds->session_key),
550
0
  };
551
0
  uint32_t iv_size =
552
0
    gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
553
0
  uint8_t _iv[iv_size];
554
0
  gnutls_datum_t iv = {
555
0
    .data = _iv,
556
0
    .size = iv_size,
557
0
  };
558
0
  int rc;
559
560
0
  ZERO_ARRAY(_iv);
561
562
0
  rc = gnutls_cipher_init(&cipher_hnd,
563
0
        GNUTLS_CIPHER_AES_128_CFB8,
564
0
        &key,
565
0
        &iv);
566
0
  if (rc < 0) {
567
0
    return gnutls_error_to_ntstatus(rc,
568
0
            NT_STATUS_CRYPTO_SYSTEM_INVALID);
569
0
  }
570
571
0
  rc = gnutls_cipher_decrypt(cipher_hnd, data, len);
572
0
  gnutls_cipher_deinit(cipher_hnd);
573
0
  if (rc < 0) {
574
0
    return gnutls_error_to_ntstatus(rc,
575
0
            NT_STATUS_CRYPTO_SYSTEM_INVALID);
576
0
  }
577
578
0
  return NT_STATUS_OK;
579
0
}
580
581
static struct netlogon_creds_CredentialState *
582
netlogon_creds_alloc(TALLOC_CTX *mem_ctx,
583
         const char *client_account,
584
         const char *client_computer_name,
585
         uint16_t secure_channel_type,
586
         uint32_t client_requested_flags,
587
         const struct dom_sid *client_sid,
588
         uint32_t negotiate_flags)
589
0
{
590
0
  struct netlogon_creds_CredentialState *creds = NULL;
591
0
  struct timeval tv = timeval_current();
592
0
  NTTIME now = timeval_to_nttime(&tv);
593
0
  const char *name = NULL;
594
595
0
  creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
596
0
  if (creds == NULL) {
597
0
    return NULL;
598
0
  }
599
600
0
  if (client_sid == NULL) {
601
0
    creds->sequence = tv.tv_sec;
602
0
  }
603
0
  creds->negotiate_flags = negotiate_flags;
604
0
  creds->secure_channel_type = secure_channel_type;
605
606
0
  creds->computer_name = talloc_strdup(creds, client_computer_name);
607
0
  if (!creds->computer_name) {
608
0
    talloc_free(creds);
609
0
    return NULL;
610
0
  }
611
0
  creds->account_name = talloc_strdup(creds, client_account);
612
0
  if (!creds->account_name) {
613
0
    talloc_free(creds);
614
0
    return NULL;
615
0
  }
616
617
0
  creds->client_requested_flags = client_requested_flags;
618
0
  creds->auth_time = now;
619
0
  if (client_sid != NULL) {
620
0
    creds->client_sid = *client_sid;
621
0
  } else {
622
0
    creds->client_sid = global_sid_NULL;
623
0
  }
624
625
0
  name = talloc_get_name(creds);
626
0
  _talloc_keep_secret(creds, name);
627
0
  return creds;
628
0
}
629
630
struct netlogon_creds_CredentialState *netlogon_creds_kerberos_init(TALLOC_CTX *mem_ctx,
631
                    const char *client_account,
632
                    const char *client_computer_name,
633
                    uint16_t secure_channel_type,
634
                    uint32_t client_requested_flags,
635
                    const struct dom_sid *client_sid,
636
                    uint32_t negotiate_flags)
637
0
{
638
0
  struct netlogon_creds_CredentialState *creds = NULL;
639
640
0
  creds = netlogon_creds_alloc(mem_ctx,
641
0
             client_account,
642
0
             client_computer_name,
643
0
             secure_channel_type,
644
0
             client_requested_flags,
645
0
             client_sid,
646
0
             negotiate_flags);
647
0
  if (creds == NULL) {
648
0
    return NULL;
649
0
  }
650
651
  /*
652
   * Some Windows versions used
653
   * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
654
   * as a dummy flag in ServerAuthenticate3,
655
   * so we should not use
656
   * NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
657
   * for any logic decisions.
658
   *
659
   * So we use a dedicated bool that
660
   * is only set if ServerAuthenticateKerberos
661
   * was really used. And for that we assert
662
   * that NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
663
   * is set too.
664
   */
665
0
  creds->authenticate_kerberos = true;
666
667
  /*
668
   * This should not be required, but we better
669
   * make sure we would not use a zero session key...
670
   *
671
   * It seems that's what Windows is also doing...
672
   * as the values in netr_ServerPasswordGet() are
673
   * encrypted in random ways if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
674
   * is missing in netr_ServerAuthenticateKerberos().
675
   */
676
0
  generate_nonce_buffer(creds->session_key,
677
0
            ARRAY_SIZE(creds->session_key));
678
0
  generate_nonce_buffer(creds->seed.data,
679
0
            ARRAY_SIZE(creds->seed.data));
680
0
  generate_nonce_buffer(creds->client.data,
681
0
            ARRAY_SIZE(creds->client.data));
682
0
  generate_nonce_buffer(creds->server.data,
683
0
            ARRAY_SIZE(creds->server.data));
684
685
0
  return creds;
686
0
}
687
688
/*****************************************************************
689
The above functions are common to the client and server interface
690
next comes the client specific functions
691
******************************************************************/
692
693
/*
694
  initialise the credentials chain and return the first client
695
  credentials
696
*/
697
698
struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx,
699
                  const char *client_account,
700
                  const char *client_computer_name,
701
                  uint16_t secure_channel_type,
702
                  const struct netr_Credential *client_challenge,
703
                  const struct netr_Credential *server_challenge,
704
                  const struct samr_Password *machine_password,
705
                  struct netr_Credential *initial_credential,
706
                  uint32_t client_requested_flags,
707
                  uint32_t negotiate_flags)
708
0
{
709
0
  struct netlogon_creds_CredentialState *creds = NULL;
710
0
  NTSTATUS status;
711
712
0
  creds = netlogon_creds_alloc(mem_ctx,
713
0
             client_account,
714
0
             client_computer_name,
715
0
             secure_channel_type,
716
0
             client_requested_flags,
717
0
             NULL, /* client_sid */
718
0
             negotiate_flags);
719
0
  if (!creds) {
720
0
    return NULL;
721
0
  }
722
723
0
  dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
724
0
  dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
725
0
  dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
726
727
0
  if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
728
0
    status = netlogon_creds_init_hmac_sha256(creds,
729
0
               client_challenge,
730
0
               server_challenge,
731
0
               machine_password);
732
0
    if (!NT_STATUS_IS_OK(status)) {
733
0
      talloc_free(creds);
734
0
      return NULL;
735
0
    }
736
0
  } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
737
0
    status = netlogon_creds_init_128bit(creds,
738
0
                client_challenge,
739
0
                server_challenge,
740
0
                machine_password);
741
0
    if (!NT_STATUS_IS_OK(status)) {
742
0
      talloc_free(creds);
743
0
      return NULL;
744
0
    }
745
0
  } else {
746
0
    status = netlogon_creds_init_64bit(creds,
747
0
               client_challenge,
748
0
               server_challenge,
749
0
               machine_password);
750
0
    if (!NT_STATUS_IS_OK(status)) {
751
0
      talloc_free(creds);
752
0
      return NULL;
753
0
    }
754
0
  }
755
756
0
  status = netlogon_creds_first_step(creds,
757
0
             client_challenge,
758
0
             server_challenge);
759
0
  if (!NT_STATUS_IS_OK(status)) {
760
0
    talloc_free(creds);
761
0
    return NULL;
762
0
  }
763
764
0
  dump_data_pw("Session key", creds->session_key, 16);
765
0
  dump_data_pw("Credential ", creds->client.data, 8);
766
767
0
  *initial_credential = creds->client;
768
0
  return creds;
769
0
}
770
771
/*
772
  step the credentials to the next element in the chain, updating the
773
  current client and server credentials and the seed
774
775
  produce the next authenticator in the sequence ready to send to
776
  the server
777
*/
778
NTSTATUS
779
netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
780
            struct netr_Authenticator *next)
781
0
{
782
0
  uint32_t t32n = (uint32_t)time(NULL);
783
0
  NTSTATUS status;
784
785
  /*
786
   * we always increment and ignore an overflow here
787
   */
788
0
  creds->sequence += 2;
789
790
0
  if (t32n > creds->sequence) {
791
    /*
792
     * we may increment more
793
     */
794
0
    creds->sequence = t32n;
795
0
  } else {
796
0
    uint32_t d = creds->sequence - t32n;
797
798
0
    if (d >= INT32_MAX) {
799
      /*
800
       * got an overflow of time_t vs. uint32_t
801
       */
802
0
      creds->sequence = t32n;
803
0
    }
804
0
  }
805
806
0
  status = netlogon_creds_step(creds);
807
0
  if (!NT_STATUS_IS_OK(status)) {
808
0
    return status;
809
0
  }
810
811
0
  next->cred = creds->client;
812
0
  next->timestamp = creds->sequence;
813
814
0
  return NT_STATUS_OK;
815
0
}
816
817
/*
818
  check that a credentials reply from a server is correct
819
*/
820
NTSTATUS netlogon_creds_client_verify(struct netlogon_creds_CredentialState *creds,
821
      const struct netr_Credential *received_credentials,
822
      enum dcerpc_AuthType auth_type,
823
      enum dcerpc_AuthLevel auth_level)
824
0
{
825
0
  NTSTATUS status;
826
0
  bool skip_crypto = false;
827
828
0
  status = netlogon_creds_no_step_check(creds,
829
0
                auth_type,
830
0
                auth_level,
831
0
                &skip_crypto);
832
0
  if (!NT_STATUS_IS_OK(status)) {
833
0
    return status;
834
0
  }
835
836
0
  if (skip_crypto) {
837
0
    return NT_STATUS_OK;
838
0
  }
839
840
0
  if (!received_credentials ||
841
0
      !mem_equal_const_time(received_credentials->data, creds->server.data, 8)) {
842
0
    DEBUG(2,("credentials check failed\n"));
843
0
    return NT_STATUS_ACCESS_DENIED;
844
0
  }
845
0
  return NT_STATUS_OK;
846
0
}
847
848
bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds,
849
      const struct netr_Credential *received_credentials)
850
0
{
851
0
  enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
852
0
  enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
853
0
  NTSTATUS status;
854
855
0
  status = netlogon_creds_client_verify(creds,
856
0
                received_credentials,
857
0
                auth_type,
858
0
                auth_level);
859
0
  if (!NT_STATUS_IS_OK(status)) {
860
0
    return false;
861
0
  }
862
863
0
  return true;
864
0
}
865
866
867
/*****************************************************************
868
The above functions are common to the client and server interface
869
next comes the server specific functions
870
******************************************************************/
871
872
/*
873
  check that a credentials reply from a server is correct
874
*/
875
static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState *creds,
876
             const struct netr_Credential *received_credentials)
877
0
{
878
0
  if (!mem_equal_const_time(received_credentials->data, creds->client.data, 8)) {
879
0
    DEBUG(2,("credentials check failed\n"));
880
0
    dump_data_pw("client creds", creds->client.data, 8);
881
0
    dump_data_pw("calc   creds", received_credentials->data, 8);
882
0
    return false;
883
0
  }
884
0
  return true;
885
0
}
886
887
/*
888
  initialise the credentials chain and return the first server
889
  credentials
890
*/
891
struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *mem_ctx,
892
                  const char *client_account,
893
                  const char *client_computer_name,
894
                  uint16_t secure_channel_type,
895
                  const struct netr_Credential *client_challenge,
896
                  const struct netr_Credential *server_challenge,
897
                  const struct samr_Password *machine_password,
898
                  const struct netr_Credential *credentials_in,
899
                  struct netr_Credential *credentials_out,
900
                  uint32_t client_requested_flags,
901
                  const struct dom_sid *client_sid,
902
                  uint32_t negotiate_flags)
903
0
{
904
0
  struct netlogon_creds_CredentialState *creds = NULL;
905
0
  NTSTATUS status;
906
0
  bool ok;
907
908
0
  creds = netlogon_creds_alloc(mem_ctx,
909
0
             client_account,
910
0
             client_computer_name,
911
0
             secure_channel_type,
912
0
             client_requested_flags,
913
0
             client_sid,
914
0
             negotiate_flags);
915
0
  if (!creds) {
916
0
    return NULL;
917
0
  }
918
919
0
  dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
920
0
  dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
921
0
  dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
922
923
0
  ok = netlogon_creds_is_random_challenge(client_challenge);
924
0
  if (!ok) {
925
0
    DBG_WARNING("CVE-2020-1472(ZeroLogon): "
926
0
          "non-random client challenge rejected for "
927
0
          "client_account[%s] client_computer_name[%s]\n",
928
0
          log_escape(mem_ctx, client_account),
929
0
          log_escape(mem_ctx, client_computer_name));
930
0
    dump_data(DBGLVL_WARNING,
931
0
        client_challenge->data,
932
0
        sizeof(client_challenge->data));
933
0
    talloc_free(creds);
934
0
    return NULL;
935
0
  }
936
937
0
  if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
938
0
    status = netlogon_creds_init_hmac_sha256(creds,
939
0
               client_challenge,
940
0
               server_challenge,
941
0
               machine_password);
942
0
    if (!NT_STATUS_IS_OK(status)) {
943
0
      talloc_free(creds);
944
0
      return NULL;
945
0
    }
946
0
  } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
947
0
    status = netlogon_creds_init_128bit(creds,
948
0
                client_challenge,
949
0
                server_challenge,
950
0
                machine_password);
951
0
    if (!NT_STATUS_IS_OK(status)) {
952
0
      talloc_free(creds);
953
0
      return NULL;
954
0
    }
955
0
  } else {
956
0
    status = netlogon_creds_init_64bit(creds,
957
0
               client_challenge,
958
0
               server_challenge,
959
0
               machine_password);
960
0
    if (!NT_STATUS_IS_OK(status)) {
961
0
      talloc_free(creds);
962
0
      return NULL;
963
0
    }
964
0
  }
965
966
0
  status = netlogon_creds_first_step(creds,
967
0
             client_challenge,
968
0
             server_challenge);
969
0
  if (!NT_STATUS_IS_OK(status)) {
970
0
    talloc_free(creds);
971
0
    return NULL;
972
0
  }
973
974
0
  dump_data_pw("Session key", creds->session_key, 16);
975
0
  dump_data_pw("Client Credential ", creds->client.data, 8);
976
0
  dump_data_pw("Server Credential ", creds->server.data, 8);
977
978
0
  dump_data_pw("Credentials in", credentials_in->data, sizeof(credentials_in->data));
979
980
  /* And before we leak information about the machine account
981
   * password, check that they got the first go right */
982
0
  if (!netlogon_creds_server_check_internal(creds, credentials_in)) {
983
0
    talloc_free(creds);
984
0
    return NULL;
985
0
  }
986
987
0
  *credentials_out = creds->server;
988
989
0
  dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
990
991
0
  return creds;
992
0
}
993
994
NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds,
995
         const struct netr_Authenticator *received_authenticator,
996
         struct netr_Authenticator *return_authenticator,
997
         enum dcerpc_AuthType auth_type,
998
         enum dcerpc_AuthLevel auth_level)
999
0
{
1000
0
  NTSTATUS status;
1001
0
  bool skip_crypto = false;
1002
1003
0
  if (!received_authenticator || !return_authenticator) {
1004
0
    return NT_STATUS_INVALID_PARAMETER;
1005
0
  }
1006
1007
0
  status = netlogon_creds_no_step_check(creds,
1008
0
                auth_type,
1009
0
                auth_level,
1010
0
                &skip_crypto);
1011
0
  if (!NT_STATUS_IS_OK(status)) {
1012
0
    ZERO_STRUCTP(return_authenticator);
1013
0
    return status;
1014
0
  }
1015
0
  if (skip_crypto) {
1016
0
    ZERO_STRUCTP(return_authenticator);
1017
0
    return NT_STATUS_OK;
1018
0
  }
1019
1020
0
  creds->sequence = received_authenticator->timestamp;
1021
0
  status = netlogon_creds_step(creds);
1022
0
  if (!NT_STATUS_IS_OK(status)) {
1023
0
    ZERO_STRUCTP(return_authenticator);
1024
0
    return status;
1025
0
  }
1026
1027
0
  if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) {
1028
0
    return_authenticator->cred = creds->server;
1029
0
    return_authenticator->timestamp = 0;
1030
0
    return NT_STATUS_OK;
1031
0
  } else {
1032
0
    ZERO_STRUCTP(return_authenticator);
1033
0
    return NT_STATUS_ACCESS_DENIED;
1034
0
  }
1035
0
}
1036
1037
static NTSTATUS netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
1038
               uint16_t validation_level,
1039
               union netr_Validation *validation,
1040
               enum dcerpc_AuthType auth_type,
1041
               enum dcerpc_AuthLevel auth_level,
1042
               bool do_encrypt)
1043
0
{
1044
0
  struct netr_SamBaseInfo *base = NULL;
1045
0
  NTSTATUS status;
1046
0
  bool skip_crypto = false;
1047
1048
0
  if (validation == NULL) {
1049
0
    return NT_STATUS_INVALID_PARAMETER;
1050
0
  }
1051
1052
0
  switch (validation_level) {
1053
0
  case 2:
1054
0
    if (validation->sam2) {
1055
0
      base = &validation->sam2->base;
1056
0
    }
1057
0
    break;
1058
0
  case 3:
1059
0
    if (validation->sam3) {
1060
0
      base = &validation->sam3->base;
1061
0
    }
1062
0
    break;
1063
0
  case 5:
1064
    /* NetlogonValidationGenericInfo2 */
1065
0
    if (validation->generic != NULL &&
1066
0
        validation->generic->length == 0)
1067
0
    {
1068
      /*
1069
       * For "Kerberos"
1070
       * KERB_VERIFY_PAC_REQUEST there's
1071
       * not response, so there's nothing
1072
       * to encrypt.
1073
       */
1074
0
      return NT_STATUS_OK;
1075
0
    }
1076
1077
    /*
1078
     * We don't know if encryption is
1079
     * required or not yet.
1080
     *
1081
     * We would have to do tests
1082
     * with DIGEST_VALIDATION_RESP
1083
     *
1084
     * But as we don't support that
1085
     * yet, we just return an error
1086
     * for now.
1087
     */
1088
0
    log_stack_trace();
1089
0
    return NT_STATUS_INTERNAL_ERROR;
1090
0
  case 6:
1091
0
    if (validation->sam6) {
1092
0
      base = &validation->sam6->base;
1093
0
    }
1094
0
    break;
1095
0
  case 7:
1096
    /* NetlogonValidationTicketLogon */
1097
0
    return NT_STATUS_OK;
1098
0
  default:
1099
    /* If we can't find it, we can't very well decrypt it */
1100
0
    return NT_STATUS_INVALID_INFO_CLASS;
1101
0
  }
1102
1103
0
  if (!base) {
1104
0
    return NT_STATUS_INVALID_INFO_CLASS;
1105
0
  }
1106
1107
0
  status = netlogon_creds_no_buffer_crypt(creds,
1108
0
            auth_type,
1109
0
            auth_level,
1110
0
            &skip_crypto);
1111
0
  if (!NT_STATUS_IS_OK(status)) {
1112
0
    return status;
1113
0
  }
1114
1115
  /* find and decrypt the session keys, return in parameters above */
1116
0
  if (skip_crypto || validation_level == 6) {
1117
    /* they aren't encrypted! */
1118
0
  } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1119
    /*
1120
     * Don't crypt an all-zero key, it would give away
1121
     * the NETLOGON pipe session key
1122
     *
1123
     * But for ServerAuthenticateKerberos we don't care
1124
     * as we use a random key
1125
     */
1126
0
    if (creds->authenticate_kerberos ||
1127
0
        !all_zero(base->key.key, sizeof(base->key.key))) {
1128
0
      if (do_encrypt) {
1129
0
        status = netlogon_creds_aes_encrypt(
1130
0
          creds,
1131
0
          base->key.key,
1132
0
          sizeof(base->key.key));
1133
0
      } else {
1134
0
        status = netlogon_creds_aes_decrypt(
1135
0
          creds,
1136
0
          base->key.key,
1137
0
          sizeof(base->key.key));
1138
0
      }
1139
0
      if (!NT_STATUS_IS_OK(status)) {
1140
0
        return status;
1141
0
      }
1142
0
    }
1143
1144
0
    if (creds->authenticate_kerberos ||
1145
0
        !all_zero(base->LMSessKey.key,
1146
0
            sizeof(base->LMSessKey.key))) {
1147
0
      if (do_encrypt) {
1148
0
        status = netlogon_creds_aes_encrypt(
1149
0
          creds,
1150
0
          base->LMSessKey.key,
1151
0
          sizeof(base->LMSessKey.key));
1152
0
      } else {
1153
0
        status = netlogon_creds_aes_decrypt(
1154
0
          creds,
1155
0
          base->LMSessKey.key,
1156
0
          sizeof(base->LMSessKey.key));
1157
0
      }
1158
0
      if (!NT_STATUS_IS_OK(status)) {
1159
0
        return status;
1160
0
      }
1161
0
    }
1162
0
  } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1163
    /*
1164
     * Don't crypt an all-zero key, it would give away
1165
     * the NETLOGON pipe session key
1166
     *
1167
     * But for ServerAuthenticateKerberos we don't care
1168
     * as we use a random key
1169
     */
1170
0
    if (creds->authenticate_kerberos ||
1171
0
        !all_zero(base->key.key, sizeof(base->key.key))) {
1172
0
      status = netlogon_creds_arcfour_crypt(creds,
1173
0
                    base->key.key,
1174
0
                    sizeof(base->key.key));
1175
0
      if (!NT_STATUS_IS_OK(status)) {
1176
0
        return status;
1177
0
      }
1178
0
    }
1179
1180
0
    if (creds->authenticate_kerberos ||
1181
0
        !all_zero(base->LMSessKey.key,
1182
0
            sizeof(base->LMSessKey.key))) {
1183
0
      status = netlogon_creds_arcfour_crypt(creds,
1184
0
                    base->LMSessKey.key,
1185
0
                    sizeof(base->LMSessKey.key));
1186
0
      if (!NT_STATUS_IS_OK(status)) {
1187
0
        return status;
1188
0
      }
1189
0
    }
1190
0
  } else {
1191
    /*
1192
     * Don't crypt an all-zero key, it would give away
1193
     * the NETLOGON pipe session key
1194
     *
1195
     * But for ServerAuthenticateKerberos we don't care
1196
     * as we use a random key
1197
     */
1198
0
    if (creds->authenticate_kerberos ||
1199
0
        !all_zero(base->LMSessKey.key,
1200
0
            sizeof(base->LMSessKey.key))) {
1201
0
      if (do_encrypt) {
1202
0
        status = netlogon_creds_des_encrypt_LMKey(creds,
1203
0
                    &base->LMSessKey);
1204
0
      } else {
1205
0
        status = netlogon_creds_des_decrypt_LMKey(creds,
1206
0
                    &base->LMSessKey);
1207
0
      }
1208
0
      if (!NT_STATUS_IS_OK(status)) {
1209
0
        return status;
1210
0
      }
1211
0
    }
1212
0
  }
1213
1214
0
  return NT_STATUS_OK;
1215
0
}
1216
1217
NTSTATUS netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
1218
                uint16_t validation_level,
1219
                union netr_Validation *validation,
1220
                enum dcerpc_AuthType auth_type,
1221
                enum dcerpc_AuthLevel auth_level)
1222
0
{
1223
0
  return netlogon_creds_crypt_samlogon_validation(creds,
1224
0
              validation_level,
1225
0
              validation,
1226
0
              auth_type,
1227
0
              auth_level,
1228
0
              false);
1229
0
}
1230
1231
NTSTATUS netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
1232
                uint16_t validation_level,
1233
                union netr_Validation *validation,
1234
                enum dcerpc_AuthType auth_type,
1235
                enum dcerpc_AuthLevel auth_level)
1236
0
{
1237
0
  return netlogon_creds_crypt_samlogon_validation(creds,
1238
0
              validation_level,
1239
0
              validation,
1240
0
              auth_type,
1241
0
              auth_level,
1242
0
              true);
1243
0
}
1244
1245
static NTSTATUS netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
1246
                enum netr_LogonInfoClass level,
1247
                union netr_LogonLevel *logon,
1248
                enum dcerpc_AuthType auth_type,
1249
                enum dcerpc_AuthLevel auth_level,
1250
                bool do_encrypt)
1251
0
{
1252
0
  NTSTATUS status;
1253
0
  bool skip_crypto = false;
1254
1255
0
  status = netlogon_creds_no_buffer_crypt(creds,
1256
0
            auth_type,
1257
0
            auth_level,
1258
0
            &skip_crypto);
1259
0
  if (!NT_STATUS_IS_OK(status)) {
1260
0
    return status;
1261
0
  }
1262
1263
0
  if (logon == NULL) {
1264
0
    return NT_STATUS_INVALID_PARAMETER;
1265
0
  }
1266
1267
0
  switch (level) {
1268
0
  case NetlogonInteractiveInformation:
1269
0
  case NetlogonInteractiveTransitiveInformation:
1270
0
  case NetlogonServiceInformation:
1271
0
  case NetlogonServiceTransitiveInformation:
1272
0
    if (logon->password == NULL) {
1273
0
      return NT_STATUS_INVALID_PARAMETER;
1274
0
    }
1275
1276
0
    if (skip_crypto) {
1277
0
      break;
1278
0
    }
1279
1280
0
    if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1281
0
      uint8_t *h;
1282
1283
0
      h = logon->password->lmpassword.hash;
1284
0
      if (!all_zero(h, 16)) {
1285
0
        if (do_encrypt) {
1286
0
          status = netlogon_creds_aes_encrypt(
1287
0
            creds,
1288
0
            h,
1289
0
            16);
1290
0
        } else {
1291
0
          status = netlogon_creds_aes_decrypt(
1292
0
            creds,
1293
0
            h,
1294
0
            16);
1295
0
        }
1296
0
        if (!NT_STATUS_IS_OK(status)) {
1297
0
          return status;
1298
0
        }
1299
0
      }
1300
1301
0
      h = logon->password->ntpassword.hash;
1302
0
      if (!all_zero(h, 16)) {
1303
0
        if (do_encrypt) {
1304
0
          status = netlogon_creds_aes_encrypt(creds,
1305
0
                   h,
1306
0
                   16);
1307
0
        } else {
1308
0
          status = netlogon_creds_aes_decrypt(creds,
1309
0
                   h,
1310
0
                   16);
1311
0
        }
1312
0
        if (!NT_STATUS_IS_OK(status)) {
1313
0
          return status;
1314
0
        }
1315
0
      }
1316
0
    } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1317
0
      uint8_t *h;
1318
1319
0
      h = logon->password->lmpassword.hash;
1320
0
      if (!all_zero(h, 16)) {
1321
0
        status = netlogon_creds_arcfour_crypt(creds,
1322
0
                      h,
1323
0
                      16);
1324
0
        if (!NT_STATUS_IS_OK(status)) {
1325
0
          return status;
1326
0
        }
1327
0
      }
1328
1329
0
      h = logon->password->ntpassword.hash;
1330
0
      if (!all_zero(h, 16)) {
1331
0
        status = netlogon_creds_arcfour_crypt(creds,
1332
0
                      h,
1333
0
                      16);
1334
0
        if (!NT_STATUS_IS_OK(status)) {
1335
0
          return status;
1336
0
        }
1337
0
      }
1338
0
    } else {
1339
0
      struct samr_Password *p;
1340
1341
0
      p = &logon->password->lmpassword;
1342
0
      if (!all_zero(p->hash, 16)) {
1343
0
        if (do_encrypt) {
1344
0
          status = netlogon_creds_des_encrypt(creds, p);
1345
0
        } else {
1346
0
          status = netlogon_creds_des_decrypt(creds, p);
1347
0
        }
1348
0
        if (!NT_STATUS_IS_OK(status)) {
1349
0
          return status;
1350
0
        }
1351
0
      }
1352
0
      p = &logon->password->ntpassword;
1353
0
      if (!all_zero(p->hash, 16)) {
1354
0
        if (do_encrypt) {
1355
0
          status = netlogon_creds_des_encrypt(creds, p);
1356
0
        } else {
1357
0
          status = netlogon_creds_des_decrypt(creds, p);
1358
0
        }
1359
0
        if (!NT_STATUS_IS_OK(status)) {
1360
0
          return status;
1361
0
        }
1362
0
      }
1363
0
    }
1364
0
    break;
1365
1366
0
  case NetlogonNetworkInformation:
1367
0
  case NetlogonNetworkTransitiveInformation:
1368
0
    break;
1369
1370
0
  case NetlogonGenericInformation:
1371
0
    if (logon->generic == NULL) {
1372
0
      return NT_STATUS_INVALID_PARAMETER;
1373
0
    }
1374
1375
0
    if (skip_crypto) {
1376
0
      break;
1377
0
    }
1378
1379
0
    if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1380
0
      if (do_encrypt) {
1381
0
        status = netlogon_creds_aes_encrypt(
1382
0
          creds,
1383
0
          logon->generic->data,
1384
0
          logon->generic->length);
1385
0
      } else {
1386
0
        status = netlogon_creds_aes_decrypt(
1387
0
          creds,
1388
0
          logon->generic->data,
1389
0
          logon->generic->length);
1390
0
      }
1391
0
      if (!NT_STATUS_IS_OK(status)) {
1392
0
        return status;
1393
0
      }
1394
0
    } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1395
0
      status = netlogon_creds_arcfour_crypt(creds,
1396
0
                    logon->generic->data,
1397
0
                    logon->generic->length);
1398
0
      if (!NT_STATUS_IS_OK(status)) {
1399
0
        return status;
1400
0
      }
1401
0
    } else if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
1402
      /*
1403
       * Using DES to verify kerberos tickets makes no sense,
1404
       * but if the connection is encrypted we don't care...
1405
       */
1406
0
      return NT_STATUS_INVALID_PARAMETER;
1407
0
    }
1408
0
    break;
1409
1410
0
  case NetlogonTicketLogonInformation:
1411
0
    break;
1412
0
  }
1413
1414
0
  return NT_STATUS_OK;
1415
0
}
1416
1417
NTSTATUS netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
1418
                 enum netr_LogonInfoClass level,
1419
                 union netr_LogonLevel *logon,
1420
                 enum dcerpc_AuthType auth_type,
1421
                 enum dcerpc_AuthLevel auth_level)
1422
0
{
1423
0
  return netlogon_creds_crypt_samlogon_logon(creds,
1424
0
               level,
1425
0
               logon,
1426
0
               auth_type,
1427
0
               auth_level,
1428
0
               false);
1429
0
}
1430
1431
NTSTATUS netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
1432
                 enum netr_LogonInfoClass level,
1433
                 union netr_LogonLevel *logon,
1434
                 enum dcerpc_AuthType auth_type,
1435
                 enum dcerpc_AuthLevel auth_level)
1436
0
{
1437
0
  return netlogon_creds_crypt_samlogon_logon(creds,
1438
0
               level,
1439
0
               logon,
1440
0
               auth_type,
1441
0
               auth_level,
1442
0
               true);
1443
0
}
1444
1445
static NTSTATUS netlogon_creds_crypt_samr_Password(
1446
    struct netlogon_creds_CredentialState *creds,
1447
    struct samr_Password *pass,
1448
    enum dcerpc_AuthType auth_type,
1449
    enum dcerpc_AuthLevel auth_level,
1450
    bool do_encrypt)
1451
0
{
1452
0
  NTSTATUS status;
1453
0
  bool skip_crypto = false;
1454
1455
0
  status = netlogon_creds_no_buffer_crypt(creds,
1456
0
            auth_type,
1457
0
            auth_level,
1458
0
            &skip_crypto);
1459
0
  if (!NT_STATUS_IS_OK(status)) {
1460
0
    return status;
1461
0
  }
1462
1463
0
  if (skip_crypto) {
1464
0
    return NT_STATUS_OK;
1465
0
  }
1466
1467
0
  if (all_zero(pass->hash, ARRAY_SIZE(pass->hash))) {
1468
0
    return NT_STATUS_OK;
1469
0
  }
1470
1471
  /*
1472
   * Even with NETLOGON_NEG_SUPPORTS_AES or
1473
   * NETLOGON_NEG_ARCFOUR this uses DES
1474
   */
1475
1476
0
  if (do_encrypt) {
1477
0
    return netlogon_creds_des_encrypt(creds, pass);
1478
0
  }
1479
1480
0
  return netlogon_creds_des_decrypt(creds, pass);
1481
0
}
1482
1483
NTSTATUS netlogon_creds_decrypt_samr_Password(struct netlogon_creds_CredentialState *creds,
1484
                struct samr_Password *pass,
1485
                enum dcerpc_AuthType auth_type,
1486
                enum dcerpc_AuthLevel auth_level)
1487
0
{
1488
0
  return netlogon_creds_crypt_samr_Password(creds,
1489
0
              pass,
1490
0
              auth_type,
1491
0
              auth_level,
1492
0
              false);
1493
0
}
1494
1495
NTSTATUS netlogon_creds_encrypt_samr_Password(struct netlogon_creds_CredentialState *creds,
1496
                struct samr_Password *pass,
1497
                enum dcerpc_AuthType auth_type,
1498
                enum dcerpc_AuthLevel auth_level)
1499
0
{
1500
0
  return netlogon_creds_crypt_samr_Password(creds,
1501
0
              pass,
1502
0
              auth_type,
1503
0
              auth_level,
1504
0
              true);
1505
0
}
1506
1507
static NTSTATUS netlogon_creds_crypt_samr_CryptPassword(
1508
    struct netlogon_creds_CredentialState *creds,
1509
    struct samr_CryptPassword *pass,
1510
    enum dcerpc_AuthType auth_type,
1511
    enum dcerpc_AuthLevel auth_level,
1512
    bool do_encrypt)
1513
0
{
1514
0
  NTSTATUS status;
1515
0
  bool skip_crypto = false;
1516
1517
0
  status = netlogon_creds_no_buffer_crypt(creds,
1518
0
            auth_type,
1519
0
            auth_level,
1520
0
            &skip_crypto);
1521
0
  if (!NT_STATUS_IS_OK(status)) {
1522
0
    return status;
1523
0
  }
1524
1525
0
  if (skip_crypto) {
1526
0
    return NT_STATUS_OK;
1527
0
  }
1528
1529
0
  if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1530
0
    if (do_encrypt) {
1531
0
      return netlogon_creds_aes_encrypt(creds,
1532
0
                pass->data,
1533
0
                ARRAY_SIZE(pass->data));
1534
0
    }
1535
1536
0
    return netlogon_creds_aes_decrypt(creds,
1537
0
              pass->data,
1538
0
              ARRAY_SIZE(pass->data));
1539
0
  }
1540
1541
0
  if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1542
0
    return netlogon_creds_arcfour_crypt(creds,
1543
0
                pass->data,
1544
0
                ARRAY_SIZE(pass->data));
1545
0
  }
1546
1547
  /*
1548
   * Using DES to verify to encrypt the password makes no sense,
1549
   * but if the connection is encrypted we don't care...
1550
   */
1551
0
  if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
1552
0
    return NT_STATUS_INVALID_PARAMETER;
1553
0
  }
1554
1555
0
  return NT_STATUS_OK;
1556
0
}
1557
1558
NTSTATUS netlogon_creds_decrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds,
1559
               struct samr_CryptPassword *pass,
1560
               enum dcerpc_AuthType auth_type,
1561
               enum dcerpc_AuthLevel auth_level)
1562
0
{
1563
0
  return netlogon_creds_crypt_samr_CryptPassword(creds,
1564
0
                   pass,
1565
0
                   auth_type,
1566
0
                   auth_level,
1567
0
                   false);
1568
0
}
1569
1570
NTSTATUS netlogon_creds_encrypt_samr_CryptPassword(struct netlogon_creds_CredentialState *creds,
1571
               struct samr_CryptPassword *pass,
1572
               enum dcerpc_AuthType auth_type,
1573
               enum dcerpc_AuthLevel auth_level)
1574
0
{
1575
0
  return netlogon_creds_crypt_samr_CryptPassword(creds,
1576
0
                   pass,
1577
0
                   auth_type,
1578
0
                   auth_level,
1579
0
                   true);
1580
0
}
1581
1582
static NTSTATUS netlogon_creds_crypt_SendToSam(
1583
    struct netlogon_creds_CredentialState *creds,
1584
    uint8_t *opaque_data,
1585
    size_t opaque_length,
1586
    enum dcerpc_AuthType auth_type,
1587
    enum dcerpc_AuthLevel auth_level,
1588
    bool do_encrypt)
1589
0
{
1590
0
  NTSTATUS status;
1591
0
  bool skip_crypto = false;
1592
1593
0
  status = netlogon_creds_no_buffer_crypt(creds,
1594
0
            auth_type,
1595
0
            auth_level,
1596
0
            &skip_crypto);
1597
0
  if (!NT_STATUS_IS_OK(status)) {
1598
0
    return status;
1599
0
  }
1600
1601
0
  if (skip_crypto) {
1602
0
    return NT_STATUS_OK;
1603
0
  }
1604
1605
0
  if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1606
0
    if (do_encrypt) {
1607
0
      return netlogon_creds_aes_encrypt(creds,
1608
0
                opaque_data,
1609
0
                opaque_length);
1610
0
    }
1611
1612
0
    return netlogon_creds_aes_decrypt(creds,
1613
0
              opaque_data,
1614
0
              opaque_length);
1615
0
  }
1616
1617
0
  if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1618
0
    return netlogon_creds_arcfour_crypt(creds,
1619
0
                opaque_data,
1620
0
                opaque_length);
1621
0
  }
1622
1623
  /*
1624
   * Using DES to verify to encrypt the data makes no sense,
1625
   * but if the connection is encrypted we don't care...
1626
   */
1627
0
  if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
1628
0
    return NT_STATUS_INVALID_PARAMETER;
1629
0
  }
1630
1631
0
  return NT_STATUS_OK;
1632
0
}
1633
1634
NTSTATUS netlogon_creds_decrypt_SendToSam(struct netlogon_creds_CredentialState *creds,
1635
            uint8_t *opaque_data,
1636
            size_t opaque_length,
1637
            enum dcerpc_AuthType auth_type,
1638
            enum dcerpc_AuthLevel auth_level)
1639
0
{
1640
0
  return netlogon_creds_crypt_SendToSam(creds,
1641
0
                opaque_data,
1642
0
                opaque_length,
1643
0
                auth_type,
1644
0
                auth_level,
1645
0
                false);
1646
0
}
1647
1648
NTSTATUS netlogon_creds_encrypt_SendToSam(struct netlogon_creds_CredentialState *creds,
1649
            uint8_t *opaque_data,
1650
            size_t opaque_length,
1651
            enum dcerpc_AuthType auth_type,
1652
            enum dcerpc_AuthLevel auth_level)
1653
0
{
1654
0
  return netlogon_creds_crypt_SendToSam(creds,
1655
0
                opaque_data,
1656
0
                opaque_length,
1657
0
                auth_type,
1658
0
                auth_level,
1659
0
                true);
1660
0
}
1661
1662
union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx,
1663
          enum netr_LogonInfoClass level,
1664
          const union netr_LogonLevel *in)
1665
0
{
1666
0
  union netr_LogonLevel *out;
1667
1668
0
  if (in == NULL) {
1669
0
    return NULL;
1670
0
  }
1671
1672
0
  out = talloc(mem_ctx, union netr_LogonLevel);
1673
0
  if (out == NULL) {
1674
0
    return NULL;
1675
0
  }
1676
1677
0
  *out = *in;
1678
1679
0
  switch (level) {
1680
0
  case NetlogonInteractiveInformation:
1681
0
  case NetlogonInteractiveTransitiveInformation:
1682
0
  case NetlogonServiceInformation:
1683
0
  case NetlogonServiceTransitiveInformation:
1684
0
    if (in->password == NULL) {
1685
0
      return out;
1686
0
    }
1687
1688
0
    out->password = talloc(out, struct netr_PasswordInfo);
1689
0
    if (out->password == NULL) {
1690
0
      talloc_free(out);
1691
0
      return NULL;
1692
0
    }
1693
0
    *out->password = *in->password;
1694
1695
0
    return out;
1696
1697
0
  case NetlogonNetworkInformation:
1698
0
  case NetlogonNetworkTransitiveInformation:
1699
0
    break;
1700
1701
0
  case NetlogonGenericInformation:
1702
0
    if (in->generic == NULL) {
1703
0
      return out;
1704
0
    }
1705
1706
0
    out->generic = talloc(out, struct netr_GenericInfo);
1707
0
    if (out->generic == NULL) {
1708
0
      talloc_free(out);
1709
0
      return NULL;
1710
0
    }
1711
0
    *out->generic = *in->generic;
1712
1713
0
    if (in->generic->data == NULL) {
1714
0
      return out;
1715
0
    }
1716
1717
0
    if (in->generic->length == 0) {
1718
0
      return out;
1719
0
    }
1720
1721
0
    out->generic->data = talloc_memdup(out->generic,
1722
0
               in->generic->data,
1723
0
               in->generic->length);
1724
0
    if (out->generic->data == NULL) {
1725
0
      talloc_free(out);
1726
0
      return NULL;
1727
0
    }
1728
1729
0
    return out;
1730
1731
0
  case NetlogonTicketLogonInformation:
1732
0
    break;
1733
0
  }
1734
1735
0
  return out;
1736
0
}
1737
1738
/*
1739
  copy a netlogon_creds_CredentialState struct
1740
*/
1741
1742
struct netlogon_creds_CredentialState *netlogon_creds_copy(
1743
  TALLOC_CTX *mem_ctx,
1744
  const struct netlogon_creds_CredentialState *creds_in)
1745
0
{
1746
0
  struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
1747
0
  enum ndr_err_code ndr_err;
1748
1749
0
  if (!creds) {
1750
0
    return NULL;
1751
0
  }
1752
1753
0
  talloc_keep_secret(creds);
1754
1755
0
  ndr_err = ndr_deepcopy_struct(netlogon_creds_CredentialState,
1756
0
              creds_in, creds, creds);
1757
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1758
0
    TALLOC_FREE(creds);
1759
0
    return NULL;
1760
0
  }
1761
1762
0
  return creds;
1763
0
}