Coverage Report

Created: 2026-01-16 06:47

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