8470815b82eb1be0630e026e7d2a54595a2479f6
[samba.git] / libcli / auth / credentials.c
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 {
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         if (challenge->data[1] == challenge->data[0] &&
49             challenge->data[2] == challenge->data[0] &&
50             challenge->data[3] == challenge->data[0] &&
51             challenge->data[4] == challenge->data[0])
52         {
53                 return false;
54         }
55
56         return true;
57 }
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 {
64         *skip = false;
65
66         if (creds == NULL) {
67                 return NT_STATUS_ACCESS_DENIED;
68         }
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         if (creds->authenticate_kerberos) {
79                 if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
80                         return NT_STATUS_ACCESS_DENIED;
81                 }
82                 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
83                         return NT_STATUS_ACCESS_DENIED;
84                 }
85                 *skip = true;
86         }
87
88         return NT_STATUS_OK;
89 }
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 {
96         *skip = false;
97
98         if (creds == NULL) {
99                 return NT_STATUS_ACCESS_DENIED;
100         }
101
102         if (creds->authenticate_kerberos) {
103                 if (auth_type != DCERPC_AUTH_TYPE_KRB5) {
104                         return NT_STATUS_ACCESS_DENIED;
105                 }
106                 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
107                         return NT_STATUS_ACCESS_DENIED;
108                 }
109         }
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         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH) {
121                 if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
122                         return NT_STATUS_ACCESS_DENIED;
123                 }
124
125                 *skip = true;
126         }
127
128         return NT_STATUS_OK;
129 }
130
131 void netlogon_creds_random_challenge(struct netr_Credential *challenge)
132 {
133         ZERO_STRUCTP(challenge);
134         while (!netlogon_creds_is_random_challenge(challenge)) {
135                 generate_random_buffer(challenge->data, sizeof(challenge->data));
136         }
137 }
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 {
143         NTSTATUS status;
144         int rc;
145
146         if (creds->authenticate_kerberos) {
147                 /*
148                  * The caller should have checked this already...
149                  */
150                 return NT_STATUS_INVALID_PARAMETER_MIX;
151         }
152
153         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
154                 memcpy(out->data, in->data, sizeof(out->data));
155
156                 status = netlogon_creds_aes_encrypt(creds,
157                                                     out->data,
158                                                     sizeof(out->data));
159                 if (!NT_STATUS_IS_OK(status)) {
160                         return status;
161                 }
162         } else {
163                 rc = des_crypt112(out->data, in->data, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
164                 if (rc != 0) {
165                         return gnutls_error_to_ntstatus(rc,
166                                                         NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
167                 }
168         }
169
170         return NT_STATUS_OK;
171 }
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 {
183         uint32_t sum[2];
184         uint8_t sum2[8];
185         int rc;
186
187         sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
188         sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
189
190         SIVAL(sum2,0,sum[0]);
191         SIVAL(sum2,4,sum[1]);
192
193         ZERO_ARRAY(creds->session_key);
194
195         rc = des_crypt128(creds->session_key, sum2, machine_password->hash);
196         if (rc != 0) {
197                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
198         }
199
200         return NT_STATUS_OK;
201 }
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 {
213         uint8_t zero[4] = {0};
214         uint8_t tmp[gnutls_hash_get_len(GNUTLS_DIG_MD5)];
215         gnutls_hash_hd_t hash_hnd = NULL;
216         int rc;
217
218         ZERO_ARRAY(creds->session_key);
219
220         rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
221         if (rc < 0) {
222                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
223         }
224
225         rc = gnutls_hash(hash_hnd, zero, sizeof(zero));
226         if (rc < 0) {
227                 gnutls_hash_deinit(hash_hnd, NULL);
228                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
229         }
230         rc = gnutls_hash(hash_hnd, client_challenge->data, 8);
231         if (rc < 0) {
232                 gnutls_hash_deinit(hash_hnd, NULL);
233                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
234         }
235         rc = gnutls_hash(hash_hnd, server_challenge->data, 8);
236         if (rc < 0) {
237                 gnutls_hash_deinit(hash_hnd, NULL);
238                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
239         }
240
241         gnutls_hash_deinit(hash_hnd, tmp);
242
243         /* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
244         rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
245                               machine_password->hash,
246                               sizeof(machine_password->hash),
247                               tmp,
248                               sizeof(tmp),
249                               creds->session_key);
250         ZERO_ARRAY(tmp);
251
252         if (rc < 0) {
253                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
254         }
255
256         return NT_STATUS_OK;
257 }
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 {
269         gnutls_hmac_hd_t hmac_hnd = NULL;
270         uint8_t digest[gnutls_hmac_get_len(GNUTLS_MAC_SHA256)];
271         int rc;
272
273         ZERO_ARRAY(creds->session_key);
274
275         rc = gnutls_hmac_init(&hmac_hnd,
276                               GNUTLS_MAC_SHA256,
277                               machine_password->hash,
278                               sizeof(machine_password->hash));
279         if (rc < 0) {
280                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
281         }
282         rc = gnutls_hmac(hmac_hnd,
283                          client_challenge->data,
284                          8);
285         if (rc < 0) {
286                 gnutls_hmac_deinit(hmac_hnd, NULL);
287                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
288         }
289         rc  = gnutls_hmac(hmac_hnd,
290                           server_challenge->data,
291                           8);
292         if (rc < 0) {
293                 gnutls_hmac_deinit(hmac_hnd, NULL);
294                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
295         }
296         gnutls_hmac_deinit(hmac_hnd, digest);
297
298         memcpy(creds->session_key, digest, sizeof(creds->session_key));
299
300         ZERO_ARRAY(digest);
301
302         return NT_STATUS_OK;
303 }
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 {
309         NTSTATUS status;
310
311         status = netlogon_creds_step_crypt(creds,
312                                            client_challenge,
313                                            &creds->client);
314         if (!NT_STATUS_IS_OK(status)) {
315                 return status;
316         }
317
318         status = netlogon_creds_step_crypt(creds,
319                                            server_challenge,
320                                            &creds->server);
321         if (!NT_STATUS_IS_OK(status)) {
322                 return status;
323         }
324
325         creds->seed = creds->client;
326
327         return NT_STATUS_OK;
328 }
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 {
336         struct netr_Credential time_cred;
337         NTSTATUS status;
338
339         if (creds->authenticate_kerberos) {
340                 /* This is only called on the client side */
341                 generate_nonce_buffer(creds->seed.data,
342                                       ARRAY_SIZE(creds->seed.data));
343                 generate_nonce_buffer(creds->client.data,
344                                       ARRAY_SIZE(creds->client.data));
345                 generate_nonce_buffer(creds->server.data,
346                                       ARRAY_SIZE(creds->server.data));
347                 return NT_STATUS_OK;
348         }
349
350         DEBUG(5,("\tseed        %08x:%08x\n",
351                  IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
352
353         SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
354         SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
355
356         DEBUG(5,("\tseed+time   %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
357
358         status = netlogon_creds_step_crypt(creds,
359                                            &time_cred,
360                                            &creds->client);
361         if (!NT_STATUS_IS_OK(status)) {
362                 return status;
363         }
364
365         DEBUG(5,("\tCLIENT      %08x:%08x\n",
366                  IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
367
368         SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence + 1);
369         SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
370
371         DEBUG(5,("\tseed+time+1 %08x:%08x\n",
372                  IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
373
374         status = netlogon_creds_step_crypt(creds, &time_cred, &creds->server);
375         if (!NT_STATUS_IS_OK(status)) {
376                 return status;
377         }
378
379         DEBUG(5,("\tSERVER      %08x:%08x\n",
380                  IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
381
382         creds->seed = time_cred;
383
384         return NT_STATUS_OK;
385 }
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 {
393         int rc;
394         struct netr_LMSessionKey tmp;
395
396         rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
397         if (rc < 0) {
398                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
399         }
400         *key = tmp;
401
402         return NT_STATUS_OK;
403 }
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 {
411         int rc;
412         struct netr_LMSessionKey tmp;
413
414         rc = des_crypt56_gnutls(tmp.key, key->key, creds->session_key, SAMBA_GNUTLS_DECRYPT);
415         if (rc < 0) {
416                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
417         }
418         *key = tmp;
419
420         return NT_STATUS_OK;
421 }
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 {
429         struct samr_Password tmp;
430         int rc;
431
432         rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_ENCRYPT);
433         if (rc < 0) {
434                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
435         }
436         *pass = tmp;
437
438         return NT_STATUS_OK;
439 }
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 {
447         struct samr_Password tmp;
448         int rc;
449
450         rc = des_crypt112_16(tmp.hash, pass->hash, creds->session_key, SAMBA_GNUTLS_DECRYPT);
451         if (rc < 0) {
452                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
453         }
454         *pass = tmp;
455
456         return NT_STATUS_OK;
457 }
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 {
466         gnutls_cipher_hd_t cipher_hnd = NULL;
467         gnutls_datum_t session_key = {
468                 .data = creds->session_key,
469                 .size = sizeof(creds->session_key),
470         };
471         int rc;
472
473         rc = gnutls_cipher_init(&cipher_hnd,
474                                 GNUTLS_CIPHER_ARCFOUR_128,
475                                 &session_key,
476                                 NULL);
477         if (rc < 0) {
478                 return gnutls_error_to_ntstatus(rc,
479                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
480         }
481         rc = gnutls_cipher_encrypt(cipher_hnd,
482                                    data,
483                                    len);
484         gnutls_cipher_deinit(cipher_hnd);
485         if (rc < 0) {
486                 return gnutls_error_to_ntstatus(rc,
487                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
488         }
489
490         return NT_STATUS_OK;
491 }
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 {
500         gnutls_cipher_hd_t cipher_hnd = NULL;
501         gnutls_datum_t key = {
502                 .data = creds->session_key,
503                 .size = sizeof(creds->session_key),
504         };
505         uint32_t iv_size =
506                 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
507         uint8_t _iv[iv_size];
508         gnutls_datum_t iv = {
509                 .data = _iv,
510                 .size = iv_size,
511         };
512         int rc;
513
514         ZERO_ARRAY(_iv);
515
516         rc = gnutls_cipher_init(&cipher_hnd,
517                                 GNUTLS_CIPHER_AES_128_CFB8,
518                                 &key,
519                                 &iv);
520         if (rc < 0) {
521                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
522         }
523
524         rc = gnutls_cipher_encrypt(cipher_hnd, data, len);
525         gnutls_cipher_deinit(cipher_hnd);
526         if (rc < 0) {
527                 return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
528         }
529
530         return NT_STATUS_OK;
531 }
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 {
538         gnutls_cipher_hd_t cipher_hnd = NULL;
539         gnutls_datum_t key = {
540                 .data = creds->session_key,
541                 .size = sizeof(creds->session_key),
542         };
543         uint32_t iv_size =
544                 gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_CFB8);
545         uint8_t _iv[iv_size];
546         gnutls_datum_t iv = {
547                 .data = _iv,
548                 .size = iv_size,
549         };
550         int rc;
551
552         ZERO_ARRAY(_iv);
553
554         rc = gnutls_cipher_init(&cipher_hnd,
555                                 GNUTLS_CIPHER_AES_128_CFB8,
556                                 &key,
557                                 &iv);
558         if (rc < 0) {
559                 return gnutls_error_to_ntstatus(rc,
560                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
561         }
562
563         rc = gnutls_cipher_decrypt(cipher_hnd, data, len);
564         gnutls_cipher_deinit(cipher_hnd);
565         if (rc < 0) {
566                 return gnutls_error_to_ntstatus(rc,
567                                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
568         }
569
570         return NT_STATUS_OK;
571 }
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 {
582         struct netlogon_creds_CredentialState *creds = NULL;
583         struct timeval tv = timeval_current();
584         NTTIME now = timeval_to_nttime(&tv);
585         const char *name = NULL;
586
587         creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
588         if (creds == NULL) {
589                 return NULL;
590         }
591
592         if (client_sid == NULL) {
593                 creds->sequence = tv.tv_sec;
594         }
595         creds->negotiate_flags = negotiate_flags;
596         creds->secure_channel_type = secure_channel_type;
597
598         creds->computer_name = talloc_strdup(creds, client_computer_name);
599         if (!creds->computer_name) {
600                 talloc_free(creds);
601                 return NULL;
602         }
603         creds->account_name = talloc_strdup(creds, client_account);
604         if (!creds->account_name) {
605                 talloc_free(creds);
606                 return NULL;
607         }
608
609         creds->client_requested_flags = client_requested_flags;
610         creds->auth_time = now;
611         if (client_sid != NULL) {
612                 creds->client_sid = *client_sid;
613         } else {
614                 creds->client_sid = global_sid_NULL;
615         }
616
617         name = talloc_get_name(creds);
618         _talloc_keep_secret(creds, name);
619         return creds;
620 }
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 {
630         struct netlogon_creds_CredentialState *creds = NULL;
631
632         creds = netlogon_creds_alloc(mem_ctx,
633                                      client_account,
634                                      client_computer_name,
635                                      secure_channel_type,
636                                      client_requested_flags,
637                                      client_sid,
638                                      negotiate_flags);
639         if (creds == NULL) {
640                 return NULL;
641         }
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         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         generate_nonce_buffer(creds->session_key,
669                               ARRAY_SIZE(creds->session_key));
670         generate_nonce_buffer(creds->seed.data,
671                               ARRAY_SIZE(creds->seed.data));
672         generate_nonce_buffer(creds->client.data,
673                               ARRAY_SIZE(creds->client.data));
674         generate_nonce_buffer(creds->server.data,
675                               ARRAY_SIZE(creds->server.data));
676
677         return creds;
678 }
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 {
701         struct netlogon_creds_CredentialState *creds = NULL;
702         NTSTATUS status;
703
704         creds = netlogon_creds_alloc(mem_ctx,
705                                      client_account,
706                                      client_computer_name,
707                                      secure_channel_type,
708                                      client_requested_flags,
709                                      NULL, /* client_sid */
710                                      negotiate_flags);
711         if (!creds) {
712                 return NULL;
713         }
714
715         dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
716         dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
717         dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
718
719         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
720                 status = netlogon_creds_init_hmac_sha256(creds,
721                                                          client_challenge,
722                                                          server_challenge,
723                                                          machine_password);
724                 if (!NT_STATUS_IS_OK(status)) {
725                         talloc_free(creds);
726                         return NULL;
727                 }
728         } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
729                 status = netlogon_creds_init_128bit(creds,
730                                                     client_challenge,
731                                                     server_challenge,
732                                                     machine_password);
733                 if (!NT_STATUS_IS_OK(status)) {
734                         talloc_free(creds);
735                         return NULL;
736                 }
737         } else {
738                 status = netlogon_creds_init_64bit(creds,
739                                                    client_challenge,
740                                                    server_challenge,
741                                                    machine_password);
742                 if (!NT_STATUS_IS_OK(status)) {
743                         talloc_free(creds);
744                         return NULL;
745                 }
746         }
747
748         status = netlogon_creds_first_step(creds,
749                                            client_challenge,
750                                            server_challenge);
751         if (!NT_STATUS_IS_OK(status)) {
752                 talloc_free(creds);
753                 return NULL;
754         }
755
756         dump_data_pw("Session key", creds->session_key, 16);
757         dump_data_pw("Credential ", creds->client.data, 8);
758
759         *initial_credential = creds->client;
760         return creds;
761 }
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 {
774         uint32_t t32n = (uint32_t)time(NULL);
775         NTSTATUS status;
776
777         /*
778          * we always increment and ignore an overflow here
779          */
780         creds->sequence += 2;
781
782         if (t32n > creds->sequence) {
783                 /*
784                  * we may increment more
785                  */
786                 creds->sequence = t32n;
787         } else {
788                 uint32_t d = creds->sequence - t32n;
789
790                 if (d >= INT32_MAX) {
791                         /*
792                          * got an overflow of time_t vs. uint32_t
793                          */
794                         creds->sequence = t32n;
795                 }
796         }
797
798         status = netlogon_creds_step(creds);
799         if (!NT_STATUS_IS_OK(status)) {
800                 return status;
801         }
802
803         next->cred = creds->client;
804         next->timestamp = creds->sequence;
805
806         return NT_STATUS_OK;
807 }
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 {
817         NTSTATUS status;
818         bool skip_crypto = false;
819
820         status = netlogon_creds_no_step_check(creds,
821                                               auth_type,
822                                               auth_level,
823                                               &skip_crypto);
824         if (!NT_STATUS_IS_OK(status)) {
825                 return status;
826         }
827
828         if (skip_crypto) {
829                 return NT_STATUS_OK;
830         }
831
832         if (!received_credentials ||
833             !mem_equal_const_time(received_credentials->data, creds->server.data, 8)) {
834                 DEBUG(2,("credentials check failed\n"));
835                 return NT_STATUS_ACCESS_DENIED;
836         }
837         return NT_STATUS_OK;
838 }
839
840 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds,
841                         const struct netr_Credential *received_credentials)
842 {
843         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
844         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
845         NTSTATUS status;
846
847         status = netlogon_creds_client_verify(creds,
848                                               received_credentials,
849                                               auth_type,
850                                               auth_level);
851         if (!NT_STATUS_IS_OK(status)) {
852                 return false;
853         }
854
855         return true;
856 }
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 {
870         if (!mem_equal_const_time(received_credentials->data, creds->client.data, 8)) {
871                 DEBUG(2,("credentials check failed\n"));
872                 dump_data_pw("client creds", creds->client.data, 8);
873                 dump_data_pw("calc   creds", received_credentials->data, 8);
874                 return false;
875         }
876         return true;
877 }
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 {
896         struct netlogon_creds_CredentialState *creds = NULL;
897         NTSTATUS status;
898         bool ok;
899
900         creds = netlogon_creds_alloc(mem_ctx,
901                                      client_account,
902                                      client_computer_name,
903                                      secure_channel_type,
904                                      client_requested_flags,
905                                      client_sid,
906                                      negotiate_flags);
907         if (!creds) {
908                 return NULL;
909         }
910
911         dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
912         dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
913         dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
914
915         ok = netlogon_creds_is_random_challenge(client_challenge);
916         if (!ok) {
917                 DBG_WARNING("CVE-2020-1472(ZeroLogon): "
918                             "non-random client challenge rejected for "
919                             "client_account[%s] client_computer_name[%s]\n",
920                             log_escape(mem_ctx, client_account),
921                             log_escape(mem_ctx, client_computer_name));
922                 dump_data(DBGLVL_WARNING,
923                           client_challenge->data,
924                           sizeof(client_challenge->data));
925                 talloc_free(creds);
926                 return NULL;
927         }
928
929         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
930                 status = netlogon_creds_init_hmac_sha256(creds,
931                                                          client_challenge,
932                                                          server_challenge,
933                                                          machine_password);
934                 if (!NT_STATUS_IS_OK(status)) {
935                         talloc_free(creds);
936                         return NULL;
937                 }
938         } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
939                 status = netlogon_creds_init_128bit(creds,
940                                                     client_challenge,
941                                                     server_challenge,
942                                                     machine_password);
943                 if (!NT_STATUS_IS_OK(status)) {
944                         talloc_free(creds);
945                         return NULL;
946                 }
947         } else {
948                 status = netlogon_creds_init_64bit(creds,
949                                                    client_challenge,
950                                                    server_challenge,
951                                                    machine_password);
952                 if (!NT_STATUS_IS_OK(status)) {
953                         talloc_free(creds);
954                         return NULL;
955                 }
956         }
957
958         status = netlogon_creds_first_step(creds,
959                                            client_challenge,
960                                            server_challenge);
961         if (!NT_STATUS_IS_OK(status)) {
962                 talloc_free(creds);
963                 return NULL;
964         }
965
966         dump_data_pw("Session key", creds->session_key, 16);
967         dump_data_pw("Client Credential ", creds->client.data, 8);
968         dump_data_pw("Server Credential ", creds->server.data, 8);
969
970         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         if (!netlogon_creds_server_check_internal(creds, credentials_in)) {
975                 talloc_free(creds);
976                 return NULL;
977         }
978
979         *credentials_out = creds->server;
980
981         dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
982
983         return creds;
984 }
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 {
992         NTSTATUS status;
993         bool skip_crypto = false;
994
995         if (!received_authenticator || !return_authenticator) {
996                 return NT_STATUS_INVALID_PARAMETER;
997         }
998
999         status = netlogon_creds_no_step_check(creds,
1000                                               auth_type,
1001                                               auth_level,
1002                                               &skip_crypto);
1003         if (!NT_STATUS_IS_OK(status)) {
1004                 ZERO_STRUCTP(return_authenticator);
1005                 return status;
1006         }
1007         if (skip_crypto) {
1008                 ZERO_STRUCTP(return_authenticator);
1009                 return NT_STATUS_OK;
1010         }
1011
1012         creds->sequence = received_authenticator->timestamp;
1013         status = netlogon_creds_step(creds);
1014         if (!NT_STATUS_IS_OK(status)) {
1015                 ZERO_STRUCTP(return_authenticator);
1016                 return status;
1017         }
1018
1019         if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) {
1020                 return_authenticator->cred = creds->server;
1021                 return_authenticator->timestamp = 0;
1022                 return NT_STATUS_OK;
1023         } else {
1024                 ZERO_STRUCTP(return_authenticator);
1025                 return NT_STATUS_ACCESS_DENIED;
1026         }
1027 }
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 {
1036         struct netr_SamBaseInfo *base = NULL;
1037         NTSTATUS status;
1038         bool skip_crypto = false;
1039
1040         if (validation == NULL) {
1041                 return NT_STATUS_INVALID_PARAMETER;
1042         }
1043
1044         switch (validation_level) {
1045         case 2:
1046                 if (validation->sam2) {
1047                         base = &validation->sam2->base;
1048                 }
1049                 break;
1050         case 3:
1051                 if (validation->sam3) {
1052                         base = &validation->sam3->base;
1053                 }
1054                 break;
1055         case 5:
1056                 /* NetlogonValidationGenericInfo2 */
1057                 if (validation->generic != NULL &&
1058                     validation->generic->length == 0)
1059                 {
1060                         /*
1061                          * For "Kerberos"
1062                          * KERB_VERIFY_PAC_REQUEST there's
1063                          * not response, so there's nothing
1064                          * to encrypt.
1065                          */
1066                         return NT_STATUS_OK;
1067                 }
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                 log_stack_trace();
1081                 return NT_STATUS_INTERNAL_ERROR;
1082         case 6:
1083                 if (validation->sam6) {
1084                         base = &validation->sam6->base;
1085                 }
1086                 break;
1087         case 7:
1088                 /* NetlogonValidationTicketLogon */
1089                 return NT_STATUS_OK;
1090         default:
1091                 /* If we can't find it, we can't very well decrypt it */
1092                 return NT_STATUS_INVALID_INFO_CLASS;
1093         }
1094
1095         if (!base) {
1096                 return NT_STATUS_INVALID_INFO_CLASS;
1097         }
1098
1099         status = netlogon_creds_no_buffer_crypt(creds,
1100                                                 auth_type,
1101                                                 auth_level,
1102                                                 &skip_crypto);
1103         if (!NT_STATUS_IS_OK(status)) {
1104                 return status;
1105         }
1106
1107         /* find and decrypt the session keys, return in parameters above */
1108         if (skip_crypto || validation_level == 6) {
1109                 /* they aren't encrypted! */
1110         } 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                 if (creds->authenticate_kerberos ||
1119                     !all_zero(base->key.key, sizeof(base->key.key))) {
1120                         if (do_encrypt) {
1121                                 status = netlogon_creds_aes_encrypt(
1122                                         creds,
1123                                         base->key.key,
1124                                         sizeof(base->key.key));
1125                         } else {
1126                                 status = netlogon_creds_aes_decrypt(
1127                                         creds,
1128                                         base->key.key,
1129                                         sizeof(base->key.key));
1130                         }
1131                         if (!NT_STATUS_IS_OK(status)) {
1132                                 return status;
1133                         }
1134                 }
1135
1136                 if (creds->authenticate_kerberos ||
1137                     !all_zero(base->LMSessKey.key,
1138                               sizeof(base->LMSessKey.key))) {
1139                         if (do_encrypt) {
1140                                 status = netlogon_creds_aes_encrypt(
1141                                         creds,
1142                                         base->LMSessKey.key,
1143                                         sizeof(base->LMSessKey.key));
1144                         } else {
1145                                 status = netlogon_creds_aes_decrypt(
1146                                         creds,
1147                                         base->LMSessKey.key,
1148                                         sizeof(base->LMSessKey.key));
1149                         }
1150                         if (!NT_STATUS_IS_OK(status)) {
1151                                 return status;
1152                         }
1153                 }
1154         } 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                 if (creds->authenticate_kerberos ||
1163                     !all_zero(base->key.key, sizeof(base->key.key))) {
1164                         status = netlogon_creds_arcfour_crypt(creds,
1165                                                               base->key.key,
1166                                                               sizeof(base->key.key));
1167                         if (!NT_STATUS_IS_OK(status)) {
1168                                 return status;
1169                         }
1170                 }
1171
1172                 if (creds->authenticate_kerberos ||
1173                     !all_zero(base->LMSessKey.key,
1174                               sizeof(base->LMSessKey.key))) {
1175                         status = netlogon_creds_arcfour_crypt(creds,
1176                                                               base->LMSessKey.key,
1177                                                               sizeof(base->LMSessKey.key));
1178                         if (!NT_STATUS_IS_OK(status)) {
1179                                 return status;
1180                         }
1181                 }
1182         } 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                 if (creds->authenticate_kerberos ||
1191                     !all_zero(base->LMSessKey.key,
1192                               sizeof(base->LMSessKey.key))) {
1193                         if (do_encrypt) {
1194                                 status = netlogon_creds_des_encrypt_LMKey(creds,
1195                                                                           &base->LMSessKey);
1196                         } else {
1197                                 status = netlogon_creds_des_decrypt_LMKey(creds,
1198                                                                           &base->LMSessKey);
1199                         }
1200                         if (!NT_STATUS_IS_OK(status)) {
1201                                 return status;
1202                         }
1203                 }
1204         }
1205
1206         return NT_STATUS_OK;
1207 }
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 {
1215         return netlogon_creds_crypt_samlogon_validation(creds,
1216                                                         validation_level,
1217                                                         validation,
1218                                                         auth_type,
1219                                                         auth_level,
1220                                                         false);
1221 }
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 {
1229         return netlogon_creds_crypt_samlogon_validation(creds,
1230                                                         validation_level,
1231                                                         validation,
1232                                                         auth_type,
1233                                                         auth_level,
1234                                                         true);
1235 }
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 {
1244         NTSTATUS status;
1245         bool skip_crypto = false;
1246
1247         status = netlogon_creds_no_buffer_crypt(creds,
1248                                                 auth_type,
1249                                                 auth_level,
1250                                                 &skip_crypto);
1251         if (!NT_STATUS_IS_OK(status)) {
1252                 return status;
1253         }
1254
1255         if (logon == NULL) {
1256                 return NT_STATUS_INVALID_PARAMETER;
1257         }
1258
1259         switch (level) {
1260         case NetlogonInteractiveInformation:
1261         case NetlogonInteractiveTransitiveInformation:
1262         case NetlogonServiceInformation:
1263         case NetlogonServiceTransitiveInformation:
1264                 if (logon->password == NULL) {
1265                         return NT_STATUS_INVALID_PARAMETER;
1266                 }
1267
1268                 if (skip_crypto) {
1269                         break;
1270                 }
1271
1272                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1273                         uint8_t *h;
1274
1275                         h = logon->password->lmpassword.hash;
1276                         if (!all_zero(h, 16)) {
1277                                 if (do_encrypt) {
1278                                         status = netlogon_creds_aes_encrypt(
1279                                                 creds,
1280                                                 h,
1281                                                 16);
1282                                 } else {
1283                                         status = netlogon_creds_aes_decrypt(
1284                                                 creds,
1285                                                 h,
1286                                                 16);
1287                                 }
1288                                 if (!NT_STATUS_IS_OK(status)) {
1289                                         return status;
1290                                 }
1291                         }
1292
1293                         h = logon->password->ntpassword.hash;
1294                         if (!all_zero(h, 16)) {
1295                                 if (do_encrypt) {
1296                                         status = netlogon_creds_aes_encrypt(creds,
1297                                                                    h,
1298                                                                    16);
1299                                 } else {
1300                                         status = netlogon_creds_aes_decrypt(creds,
1301                                                                    h,
1302                                                                    16);
1303                                 }
1304                                 if (!NT_STATUS_IS_OK(status)) {
1305                                         return status;
1306                                 }
1307                         }
1308                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1309                         uint8_t *h;
1310
1311                         h = logon->password->lmpassword.hash;
1312                         if (!all_zero(h, 16)) {
1313                                 status = netlogon_creds_arcfour_crypt(creds,
1314                                                                       h,
1315                                                                       16);
1316                                 if (!NT_STATUS_IS_OK(status)) {
1317                                         return status;
1318                                 }
1319                         }
1320
1321                         h = logon->password->ntpassword.hash;
1322                         if (!all_zero(h, 16)) {
1323                                 status = netlogon_creds_arcfour_crypt(creds,
1324                                                                       h,
1325                                                                       16);
1326                                 if (!NT_STATUS_IS_OK(status)) {
1327                                         return status;
1328                                 }
1329                         }
1330                 } else {
1331                         struct samr_Password *p;
1332
1333                         p = &logon->password->lmpassword;
1334                         if (!all_zero(p->hash, 16)) {
1335                                 if (do_encrypt) {
1336                                         status = netlogon_creds_des_encrypt(creds, p);
1337                                 } else {
1338                                         status = netlogon_creds_des_decrypt(creds, p);
1339                                 }
1340                                 if (!NT_STATUS_IS_OK(status)) {
1341                                         return status;
1342                                 }
1343                         }
1344                         p = &logon->password->ntpassword;
1345                         if (!all_zero(p->hash, 16)) {
1346                                 if (do_encrypt) {
1347                                         status = netlogon_creds_des_encrypt(creds, p);
1348                                 } else {
1349                                         status = netlogon_creds_des_decrypt(creds, p);
1350                                 }
1351                                 if (!NT_STATUS_IS_OK(status)) {
1352                                         return status;
1353                                 }
1354                         }
1355                 }
1356                 break;
1357
1358         case NetlogonNetworkInformation:
1359         case NetlogonNetworkTransitiveInformation:
1360                 break;
1361
1362         case NetlogonGenericInformation:
1363                 if (logon->generic == NULL) {
1364                         return NT_STATUS_INVALID_PARAMETER;
1365                 }
1366
1367                 if (skip_crypto) {
1368                         break;
1369                 }
1370
1371                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1372                         if (do_encrypt) {
1373                                 status = netlogon_creds_aes_encrypt(
1374                                         creds,
1375                                         logon->generic->data,
1376                                         logon->generic->length);
1377                         } else {
1378                                 status = netlogon_creds_aes_decrypt(
1379                                         creds,
1380                                         logon->generic->data,
1381                                         logon->generic->length);
1382                         }
1383                         if (!NT_STATUS_IS_OK(status)) {
1384                                 return status;
1385                         }
1386                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1387                         status = netlogon_creds_arcfour_crypt(creds,
1388                                                               logon->generic->data,
1389                                                               logon->generic->length);
1390                         if (!NT_STATUS_IS_OK(status)) {
1391                                 return status;
1392                         }
1393                 } 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                         return NT_STATUS_INVALID_PARAMETER;
1399                 }
1400                 break;
1401
1402         case NetlogonTicketLogonInformation:
1403                 break;
1404         }
1405
1406         return NT_STATUS_OK;
1407 }
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 {
1415         return netlogon_creds_crypt_samlogon_logon(creds,
1416                                                    level,
1417                                                    logon,
1418                                                    auth_type,
1419                                                    auth_level,
1420                                                    false);
1421 }
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 {
1429         return netlogon_creds_crypt_samlogon_logon(creds,
1430                                                    level,
1431                                                    logon,
1432                                                    auth_type,
1433                                                    auth_level,
1434                                                    true);
1435 }
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 {
1444         NTSTATUS status;
1445         bool skip_crypto = false;
1446
1447         status = netlogon_creds_no_buffer_crypt(creds,
1448                                                 auth_type,
1449                                                 auth_level,
1450                                                 &skip_crypto);
1451         if (!NT_STATUS_IS_OK(status)) {
1452                 return status;
1453         }
1454
1455         if (skip_crypto) {
1456                 return NT_STATUS_OK;
1457         }
1458
1459         if (all_zero(pass->hash, ARRAY_SIZE(pass->hash))) {
1460                 return NT_STATUS_OK;
1461         }
1462
1463         /*
1464          * Even with NETLOGON_NEG_SUPPORTS_AES or
1465          * NETLOGON_NEG_ARCFOUR this uses DES
1466          */
1467
1468         if (do_encrypt) {
1469                 return netlogon_creds_des_encrypt(creds, pass);
1470         }
1471
1472         return netlogon_creds_des_decrypt(creds, pass);
1473 }
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 {
1480         return netlogon_creds_crypt_samr_Password(creds,
1481                                                   pass,
1482                                                   auth_type,
1483                                                   auth_level,
1484                                                   false);
1485 }
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 {
1492         return netlogon_creds_crypt_samr_Password(creds,
1493                                                   pass,
1494                                                   auth_type,
1495                                                   auth_level,
1496                                                   true);
1497 }
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 {
1506         NTSTATUS status;
1507         bool skip_crypto = false;
1508
1509         status = netlogon_creds_no_buffer_crypt(creds,
1510                                                 auth_type,
1511                                                 auth_level,
1512                                                 &skip_crypto);
1513         if (!NT_STATUS_IS_OK(status)) {
1514                 return status;
1515         }
1516
1517         if (skip_crypto) {
1518                 return NT_STATUS_OK;
1519         }
1520
1521         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1522                 if (do_encrypt) {
1523                         return netlogon_creds_aes_encrypt(creds,
1524                                                           pass->data,
1525                                                           ARRAY_SIZE(pass->data));
1526                 }
1527
1528                 return netlogon_creds_aes_decrypt(creds,
1529                                                   pass->data,
1530                                                   ARRAY_SIZE(pass->data));
1531         }
1532
1533         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1534                 return netlogon_creds_arcfour_crypt(creds,
1535                                                     pass->data,
1536                                                     ARRAY_SIZE(pass->data));
1537         }
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         if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
1544                 return NT_STATUS_INVALID_PARAMETER;
1545         }
1546
1547         return NT_STATUS_OK;
1548 }
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 {
1555         return netlogon_creds_crypt_samr_CryptPassword(creds,
1556                                                        pass,
1557                                                        auth_type,
1558                                                        auth_level,
1559                                                        false);
1560 }
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 {
1567         return netlogon_creds_crypt_samr_CryptPassword(creds,
1568                                                        pass,
1569                                                        auth_type,
1570                                                        auth_level,
1571                                                        true);
1572 }
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 {
1582         NTSTATUS status;
1583         bool skip_crypto = false;
1584
1585         status = netlogon_creds_no_buffer_crypt(creds,
1586                                                 auth_type,
1587                                                 auth_level,
1588                                                 &skip_crypto);
1589         if (!NT_STATUS_IS_OK(status)) {
1590                 return status;
1591         }
1592
1593         if (skip_crypto) {
1594                 return NT_STATUS_OK;
1595         }
1596
1597         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1598                 if (do_encrypt) {
1599                         return netlogon_creds_aes_encrypt(creds,
1600                                                           opaque_data,
1601                                                           opaque_length);
1602                 }
1603
1604                 return netlogon_creds_aes_decrypt(creds,
1605                                                   opaque_data,
1606                                                   opaque_length);
1607         }
1608
1609         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1610                 return netlogon_creds_arcfour_crypt(creds,
1611                                                     opaque_data,
1612                                                     opaque_length);
1613         }
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         if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
1620                 return NT_STATUS_INVALID_PARAMETER;
1621         }
1622
1623         return NT_STATUS_OK;
1624 }
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 {
1632         return netlogon_creds_crypt_SendToSam(creds,
1633                                               opaque_data,
1634                                               opaque_length,
1635                                               auth_type,
1636                                               auth_level,
1637                                               false);
1638 }
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 {
1646         return netlogon_creds_crypt_SendToSam(creds,
1647                                               opaque_data,
1648                                               opaque_length,
1649                                               auth_type,
1650                                               auth_level,
1651                                               true);
1652 }
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 {
1658         union netr_LogonLevel *out;
1659
1660         if (in == NULL) {
1661                 return NULL;
1662         }
1663
1664         out = talloc(mem_ctx, union netr_LogonLevel);
1665         if (out == NULL) {
1666                 return NULL;
1667         }
1668
1669         *out = *in;
1670
1671         switch (level) {
1672         case NetlogonInteractiveInformation:
1673         case NetlogonInteractiveTransitiveInformation:
1674         case NetlogonServiceInformation:
1675         case NetlogonServiceTransitiveInformation:
1676                 if (in->password == NULL) {
1677                         return out;
1678                 }
1679
1680                 out->password = talloc(out, struct netr_PasswordInfo);
1681                 if (out->password == NULL) {
1682                         talloc_free(out);
1683                         return NULL;
1684                 }
1685                 *out->password = *in->password;
1686
1687                 return out;
1688
1689         case NetlogonNetworkInformation:
1690         case NetlogonNetworkTransitiveInformation:
1691                 break;
1692
1693         case NetlogonGenericInformation:
1694                 if (in->generic == NULL) {
1695                         return out;
1696                 }
1697
1698                 out->generic = talloc(out, struct netr_GenericInfo);
1699                 if (out->generic == NULL) {
1700                         talloc_free(out);
1701                         return NULL;
1702                 }
1703                 *out->generic = *in->generic;
1704
1705                 if (in->generic->data == NULL) {
1706                         return out;
1707                 }
1708
1709                 if (in->generic->length == 0) {
1710                         return out;
1711                 }
1712
1713                 out->generic->data = talloc_memdup(out->generic,
1714                                                    in->generic->data,
1715                                                    in->generic->length);
1716                 if (out->generic->data == NULL) {
1717                         talloc_free(out);
1718                         return NULL;
1719                 }
1720
1721                 return out;
1722
1723         case NetlogonTicketLogonInformation:
1724                 break;
1725         }
1726
1727         return out;
1728 }
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 {
1738         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
1739         enum ndr_err_code ndr_err;
1740
1741         if (!creds) {
1742                 return NULL;
1743         }
1744
1745         ndr_err = ndr_deepcopy_struct(netlogon_creds_CredentialState,
1746                                       creds_in, creds, creds);
1747         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1748                 TALLOC_FREE(creds);
1749                 return NULL;
1750         }
1751
1752         return creds;
1753 }