netlogon_creds_cli: Remove unused code
[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 "../lib/crypto/crypto.h"
26 #include "libcli/auth/libcli_auth.h"
27 #include "../libcli/security/dom_sid.h"
28
29 static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
30                                       const struct netr_Credential *in,
31                                       struct netr_Credential *out)
32 {
33         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
34                 AES_KEY key;
35                 uint8_t iv[AES_BLOCK_SIZE];
36
37                 AES_set_encrypt_key(creds->session_key, 128, &key);
38                 ZERO_STRUCT(iv);
39
40                 aes_cfb8_encrypt(in->data, out->data, 8, &key, iv, AES_ENCRYPT);
41         } else {
42                 des_crypt112(out->data, in->data, creds->session_key, 1);
43         }
44 }
45
46 /*
47   initialise the credentials state for old-style 64 bit session keys
48
49   this call is made after the netr_ServerReqChallenge call
50 */
51 static void netlogon_creds_init_64bit(struct netlogon_creds_CredentialState *creds,
52                                       const struct netr_Credential *client_challenge,
53                                       const struct netr_Credential *server_challenge,
54                                       const struct samr_Password *machine_password)
55 {
56         uint32_t sum[2];
57         uint8_t sum2[8];
58
59         sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
60         sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
61
62         SIVAL(sum2,0,sum[0]);
63         SIVAL(sum2,4,sum[1]);
64
65         ZERO_STRUCT(creds->session_key);
66
67         des_crypt128(creds->session_key, sum2, machine_password->hash);
68 }
69
70 /*
71   initialise the credentials state for ADS-style 128 bit session keys
72
73   this call is made after the netr_ServerReqChallenge call
74 */
75 static void netlogon_creds_init_128bit(struct netlogon_creds_CredentialState *creds,
76                                        const struct netr_Credential *client_challenge,
77                                        const struct netr_Credential *server_challenge,
78                                        const struct samr_Password *machine_password)
79 {
80         unsigned char zero[4], tmp[16];
81         HMACMD5Context ctx;
82         MD5_CTX md5;
83
84         ZERO_STRUCT(creds->session_key);
85
86         memset(zero, 0, sizeof(zero));
87
88         hmac_md5_init_rfc2104(machine_password->hash, sizeof(machine_password->hash), &ctx);
89         MD5Init(&md5);
90         MD5Update(&md5, zero, sizeof(zero));
91         MD5Update(&md5, client_challenge->data, 8);
92         MD5Update(&md5, server_challenge->data, 8);
93         MD5Final(tmp, &md5);
94         hmac_md5_update(tmp, sizeof(tmp), &ctx);
95         hmac_md5_final(creds->session_key, &ctx);
96 }
97
98 /*
99   initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
100
101   this call is made after the netr_ServerReqChallenge call
102 */
103 static void netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState *creds,
104                                             const struct netr_Credential *client_challenge,
105                                             const struct netr_Credential *server_challenge,
106                                             const struct samr_Password *machine_password)
107 {
108         struct HMACSHA256Context ctx;
109         uint8_t digest[SHA256_DIGEST_LENGTH];
110
111         ZERO_STRUCT(creds->session_key);
112
113         hmac_sha256_init(machine_password->hash,
114                          sizeof(machine_password->hash),
115                          &ctx);
116         hmac_sha256_update(client_challenge->data, 8, &ctx);
117         hmac_sha256_update(server_challenge->data, 8, &ctx);
118         hmac_sha256_final(digest, &ctx);
119
120         memcpy(creds->session_key, digest, sizeof(creds->session_key));
121
122         ZERO_STRUCT(digest);
123         ZERO_STRUCT(ctx);
124 }
125
126 static void netlogon_creds_first_step(struct netlogon_creds_CredentialState *creds,
127                                       const struct netr_Credential *client_challenge,
128                                       const struct netr_Credential *server_challenge)
129 {
130         netlogon_creds_step_crypt(creds, client_challenge, &creds->client);
131
132         netlogon_creds_step_crypt(creds, server_challenge, &creds->server);
133
134         creds->seed = creds->client;
135 }
136
137 /*
138   step the credentials to the next element in the chain, updating the
139   current client and server credentials and the seed
140 */
141 static void netlogon_creds_step(struct netlogon_creds_CredentialState *creds)
142 {
143         struct netr_Credential time_cred;
144
145         DEBUG(5,("\tseed        %08x:%08x\n",
146                  IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
147
148         SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
149         SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
150
151         DEBUG(5,("\tseed+time   %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
152
153         netlogon_creds_step_crypt(creds, &time_cred, &creds->client);
154
155         DEBUG(5,("\tCLIENT      %08x:%08x\n",
156                  IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
157
158         SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence + 1);
159         SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
160
161         DEBUG(5,("\tseed+time+1 %08x:%08x\n",
162                  IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
163
164         netlogon_creds_step_crypt(creds, &time_cred, &creds->server);
165
166         DEBUG(5,("\tSERVER      %08x:%08x\n",
167                  IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
168
169         creds->seed = time_cred;
170 }
171
172
173 /*
174   DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
175 */
176 void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key)
177 {
178         struct netr_LMSessionKey tmp;
179         des_crypt56(tmp.key, key->key, creds->session_key, 1);
180         *key = tmp;
181 }
182
183 /*
184   DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
185 */
186 void netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key)
187 {
188         struct netr_LMSessionKey tmp;
189         des_crypt56(tmp.key, key->key, creds->session_key, 0);
190         *key = tmp;
191 }
192
193 /*
194   DES encrypt a 16 byte password buffer using the session key
195 */
196 void netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass)
197 {
198         struct samr_Password tmp;
199         des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 1);
200         *pass = tmp;
201 }
202
203 /*
204   DES decrypt a 16 byte password buffer using the session key
205 */
206 void netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass)
207 {
208         struct samr_Password tmp;
209         des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 0);
210         *pass = tmp;
211 }
212
213 /*
214   ARCFOUR encrypt/decrypt a password buffer using the session key
215 */
216 void netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
217 {
218         DATA_BLOB session_key = data_blob(creds->session_key, 16);
219
220         arcfour_crypt_blob(data, len, &session_key);
221
222         data_blob_free(&session_key);
223 }
224
225 /*
226   AES encrypt a password buffer using the session key
227 */
228 void netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
229 {
230         AES_KEY key;
231         uint8_t iv[AES_BLOCK_SIZE];
232
233         AES_set_encrypt_key(creds->session_key, 128, &key);
234         ZERO_STRUCT(iv);
235
236         aes_cfb8_encrypt(data, data, len, &key, iv, AES_ENCRYPT);
237 }
238
239 /*
240   AES decrypt a password buffer using the session key
241 */
242 void netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
243 {
244         AES_KEY key;
245         uint8_t iv[AES_BLOCK_SIZE];
246
247         AES_set_encrypt_key(creds->session_key, 128, &key);
248         ZERO_STRUCT(iv);
249
250         aes_cfb8_encrypt(data, data, len, &key, iv, AES_DECRYPT);
251 }
252
253 /*****************************************************************
254 The above functions are common to the client and server interface
255 next comes the client specific functions
256 ******************************************************************/
257
258 /*
259   initialise the credentials chain and return the first client
260   credentials
261 */
262
263 struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx,
264                                                                   const char *client_account,
265                                                                   const char *client_computer_name,
266                                                                   uint16_t secure_channel_type,
267                                                                   const struct netr_Credential *client_challenge,
268                                                                   const struct netr_Credential *server_challenge,
269                                                                   const struct samr_Password *machine_password,
270                                                                   struct netr_Credential *initial_credential,
271                                                                   uint32_t negotiate_flags)
272 {
273         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
274
275         if (!creds) {
276                 return NULL;
277         }
278
279         creds->sequence = time(NULL);
280         creds->negotiate_flags = negotiate_flags;
281         creds->secure_channel_type = secure_channel_type;
282
283         creds->computer_name = talloc_strdup(creds, client_computer_name);
284         if (!creds->computer_name) {
285                 talloc_free(creds);
286                 return NULL;
287         }
288         creds->account_name = talloc_strdup(creds, client_account);
289         if (!creds->account_name) {
290                 talloc_free(creds);
291                 return NULL;
292         }
293
294         dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
295         dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
296         dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
297
298         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
299                 netlogon_creds_init_hmac_sha256(creds,
300                                                 client_challenge,
301                                                 server_challenge,
302                                                 machine_password);
303         } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
304                 netlogon_creds_init_128bit(creds, client_challenge, server_challenge, machine_password);
305         } else {
306                 netlogon_creds_init_64bit(creds, client_challenge, server_challenge, machine_password);
307         }
308
309         netlogon_creds_first_step(creds, client_challenge, server_challenge);
310
311         dump_data_pw("Session key", creds->session_key, 16);
312         dump_data_pw("Credential ", creds->client.data, 8);
313
314         *initial_credential = creds->client;
315         return creds;
316 }
317
318 /*
319   initialise the credentials structure with only a session key.  The caller better know what they are doing!
320  */
321
322 struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx,
323                                                                               const uint8_t session_key[16])
324 {
325         struct netlogon_creds_CredentialState *creds;
326
327         creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
328         if (!creds) {
329                 return NULL;
330         }
331
332         memcpy(creds->session_key, session_key, 16);
333
334         return creds;
335 }
336
337 /*
338   step the credentials to the next element in the chain, updating the
339   current client and server credentials and the seed
340
341   produce the next authenticator in the sequence ready to send to
342   the server
343 */
344 void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
345                                 struct netr_Authenticator *next)
346 {
347         uint32_t t32n = (uint32_t)time(NULL);
348
349         /*
350          * we always increment and ignore an overflow here
351          */
352         creds->sequence += 2;
353
354         if (t32n > creds->sequence) {
355                 /*
356                  * we may increment more
357                  */
358                 creds->sequence = t32n;
359         } else {
360                 uint32_t d = creds->sequence - t32n;
361
362                 if (d >= INT32_MAX) {
363                         /*
364                          * got an overflow of time_t vs. uint32_t
365                          */
366                         creds->sequence = t32n;
367                 }
368         }
369
370         netlogon_creds_step(creds);
371
372         next->cred = creds->client;
373         next->timestamp = creds->sequence;
374 }
375
376 /*
377   check that a credentials reply from a server is correct
378 */
379 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds,
380                         const struct netr_Credential *received_credentials)
381 {
382         if (!received_credentials ||
383             memcmp(received_credentials->data, creds->server.data, 8) != 0) {
384                 DEBUG(2,("credentials check failed\n"));
385                 return false;
386         }
387         return true;
388 }
389
390
391 /*****************************************************************
392 The above functions are common to the client and server interface
393 next comes the server specific functions
394 ******************************************************************/
395
396 /*
397   check that a credentials reply from a server is correct
398 */
399 static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState *creds,
400                                                  const struct netr_Credential *received_credentials)
401 {
402         if (memcmp(received_credentials->data, creds->client.data, 8) != 0) {
403                 DEBUG(2,("credentials check failed\n"));
404                 dump_data_pw("client creds", creds->client.data, 8);
405                 dump_data_pw("calc   creds", received_credentials->data, 8);
406                 return false;
407         }
408         return true;
409 }
410
411 /*
412   initialise the credentials chain and return the first server
413   credentials
414 */
415 struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *mem_ctx,
416                                                                   const char *client_account,
417                                                                   const char *client_computer_name,
418                                                                   uint16_t secure_channel_type,
419                                                                   const struct netr_Credential *client_challenge,
420                                                                   const struct netr_Credential *server_challenge,
421                                                                   const struct samr_Password *machine_password,
422                                                                   const struct netr_Credential *credentials_in,
423                                                                   struct netr_Credential *credentials_out,
424                                                                   uint32_t negotiate_flags)
425 {
426
427         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
428
429         if (!creds) {
430                 return NULL;
431         }
432
433         creds->negotiate_flags = negotiate_flags;
434         creds->secure_channel_type = secure_channel_type;
435
436         dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
437         dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
438         dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash));
439
440         creds->computer_name = talloc_strdup(creds, client_computer_name);
441         if (!creds->computer_name) {
442                 talloc_free(creds);
443                 return NULL;
444         }
445         creds->account_name = talloc_strdup(creds, client_account);
446         if (!creds->account_name) {
447                 talloc_free(creds);
448                 return NULL;
449         }
450
451         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
452                 netlogon_creds_init_hmac_sha256(creds,
453                                                 client_challenge,
454                                                 server_challenge,
455                                                 machine_password);
456         } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
457                 netlogon_creds_init_128bit(creds, client_challenge, server_challenge,
458                                            machine_password);
459         } else {
460                 netlogon_creds_init_64bit(creds, client_challenge, server_challenge,
461                                           machine_password);
462         }
463
464         netlogon_creds_first_step(creds, client_challenge, server_challenge);
465
466         dump_data_pw("Session key", creds->session_key, 16);
467         dump_data_pw("Client Credential ", creds->client.data, 8);
468         dump_data_pw("Server Credential ", creds->server.data, 8);
469
470         dump_data_pw("Credentials in", credentials_in->data, sizeof(credentials_in->data));
471
472         /* And before we leak information about the machine account
473          * password, check that they got the first go right */
474         if (!netlogon_creds_server_check_internal(creds, credentials_in)) {
475                 talloc_free(creds);
476                 return NULL;
477         }
478
479         *credentials_out = creds->server;
480
481         dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
482
483         return creds;
484 }
485
486 NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds,
487                                  const struct netr_Authenticator *received_authenticator,
488                                  struct netr_Authenticator *return_authenticator)
489 {
490         if (!received_authenticator || !return_authenticator) {
491                 return NT_STATUS_INVALID_PARAMETER;
492         }
493
494         if (!creds) {
495                 return NT_STATUS_ACCESS_DENIED;
496         }
497
498         creds->sequence = received_authenticator->timestamp;
499         netlogon_creds_step(creds);
500         if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) {
501                 return_authenticator->cred = creds->server;
502                 return_authenticator->timestamp = 0;
503                 return NT_STATUS_OK;
504         } else {
505                 ZERO_STRUCTP(return_authenticator);
506                 return NT_STATUS_ACCESS_DENIED;
507         }
508 }
509
510 static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
511                                                      uint16_t validation_level,
512                                                      union netr_Validation *validation,
513                                                      bool do_encrypt)
514 {
515         struct netr_SamBaseInfo *base = NULL;
516
517         if (validation == NULL) {
518                 return;
519         }
520
521         switch (validation_level) {
522         case 2:
523                 if (validation->sam2) {
524                         base = &validation->sam2->base;
525                 }
526                 break;
527         case 3:
528                 if (validation->sam3) {
529                         base = &validation->sam3->base;
530                 }
531                 break;
532         case 6:
533                 if (validation->sam6) {
534                         base = &validation->sam6->base;
535                 }
536                 break;
537         default:
538                 /* If we can't find it, we can't very well decrypt it */
539                 return;
540         }
541
542         if (!base) {
543                 return;
544         }
545
546         /* find and decyrpt the session keys, return in parameters above */
547         if (validation_level == 6) {
548                 /* they aren't encrypted! */
549         } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
550                 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
551                 if (!all_zero(base->key.key, sizeof(base->key.key))) {
552                         if (do_encrypt) {
553                                 netlogon_creds_aes_encrypt(creds,
554                                             base->key.key,
555                                             sizeof(base->key.key));
556                         } else {
557                                 netlogon_creds_aes_decrypt(creds,
558                                             base->key.key,
559                                             sizeof(base->key.key));
560                         }
561                 }
562
563                 if (!all_zero(base->LMSessKey.key,
564                               sizeof(base->LMSessKey.key))) {
565                         if (do_encrypt) {
566                                 netlogon_creds_aes_encrypt(creds,
567                                             base->LMSessKey.key,
568                                             sizeof(base->LMSessKey.key));
569
570                         } else {
571                                 netlogon_creds_aes_decrypt(creds,
572                                             base->LMSessKey.key,
573                                             sizeof(base->LMSessKey.key));
574                         }
575                 }
576         } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
577                 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
578                 if (!all_zero(base->key.key, sizeof(base->key.key))) {
579                         netlogon_creds_arcfour_crypt(creds,
580                                             base->key.key,
581                                             sizeof(base->key.key));
582                 }
583
584                 if (!all_zero(base->LMSessKey.key,
585                               sizeof(base->LMSessKey.key))) {
586                         netlogon_creds_arcfour_crypt(creds,
587                                             base->LMSessKey.key,
588                                             sizeof(base->LMSessKey.key));
589                 }
590         } else {
591                 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
592                 if (!all_zero(base->LMSessKey.key,
593                               sizeof(base->LMSessKey.key))) {
594                         if (do_encrypt) {
595                                 netlogon_creds_des_encrypt_LMKey(creds,
596                                                 &base->LMSessKey);
597                         } else {
598                                 netlogon_creds_des_decrypt_LMKey(creds,
599                                                 &base->LMSessKey);
600                         }
601                 }
602         }
603 }
604
605 void netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
606                                                 uint16_t validation_level,
607                                                 union netr_Validation *validation)
608 {
609         netlogon_creds_crypt_samlogon_validation(creds, validation_level,
610                                                         validation, false);
611 }
612
613 void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
614                                                 uint16_t validation_level,
615                                                 union netr_Validation *validation)
616 {
617         netlogon_creds_crypt_samlogon_validation(creds, validation_level,
618                                                         validation, true);
619 }
620
621 static void netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
622                                                 enum netr_LogonInfoClass level,
623                                                 union netr_LogonLevel *logon,
624                                                 bool do_encrypt)
625 {
626         if (logon == NULL) {
627                 return;
628         }
629
630         switch (level) {
631         case NetlogonInteractiveInformation:
632         case NetlogonInteractiveTransitiveInformation:
633         case NetlogonServiceInformation:
634         case NetlogonServiceTransitiveInformation:
635                 if (logon->password == NULL) {
636                         return;
637                 }
638
639                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
640                         uint8_t *h;
641
642                         h = logon->password->lmpassword.hash;
643                         if (!all_zero(h, 16)) {
644                                 if (do_encrypt) {
645                                         netlogon_creds_aes_encrypt(creds, h, 16);
646                                 } else {
647                                         netlogon_creds_aes_decrypt(creds, h, 16);
648                                 }
649                         }
650
651                         h = logon->password->ntpassword.hash;
652                         if (!all_zero(h, 16)) {
653                                 if (do_encrypt) {
654                                         netlogon_creds_aes_encrypt(creds, h, 16);
655                                 } else {
656                                         netlogon_creds_aes_decrypt(creds, h, 16);
657                                 }
658                         }
659                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
660                         uint8_t *h;
661
662                         h = logon->password->lmpassword.hash;
663                         if (!all_zero(h, 16)) {
664                                 netlogon_creds_arcfour_crypt(creds, h, 16);
665                         }
666
667                         h = logon->password->ntpassword.hash;
668                         if (!all_zero(h, 16)) {
669                                 netlogon_creds_arcfour_crypt(creds, h, 16);
670                         }
671                 } else {
672                         struct samr_Password *p;
673
674                         p = &logon->password->lmpassword;
675                         if (!all_zero(p->hash, 16)) {
676                                 if (do_encrypt) {
677                                         netlogon_creds_des_encrypt(creds, p);
678                                 } else {
679                                         netlogon_creds_des_decrypt(creds, p);
680                                 }
681                         }
682                         p = &logon->password->ntpassword;
683                         if (!all_zero(p->hash, 16)) {
684                                 if (do_encrypt) {
685                                         netlogon_creds_des_encrypt(creds, p);
686                                 } else {
687                                         netlogon_creds_des_decrypt(creds, p);
688                                 }
689                         }
690                 }
691                 break;
692
693         case NetlogonNetworkInformation:
694         case NetlogonNetworkTransitiveInformation:
695                 break;
696
697         case NetlogonGenericInformation:
698                 if (logon->generic == NULL) {
699                         return;
700                 }
701
702                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
703                         if (do_encrypt) {
704                                 netlogon_creds_aes_encrypt(creds,
705                                                 logon->generic->data,
706                                                 logon->generic->length);
707                         } else {
708                                 netlogon_creds_aes_decrypt(creds,
709                                                 logon->generic->data,
710                                                 logon->generic->length);
711                         }
712                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
713                         netlogon_creds_arcfour_crypt(creds,
714                                                      logon->generic->data,
715                                                      logon->generic->length);
716                 } else {
717                         /* Using DES to verify kerberos tickets makes no sense */
718                 }
719                 break;
720         }
721 }
722
723 void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
724                                            enum netr_LogonInfoClass level,
725                                            union netr_LogonLevel *logon)
726 {
727         netlogon_creds_crypt_samlogon_logon(creds, level, logon, false);
728 }
729
730 void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
731                                            enum netr_LogonInfoClass level,
732                                            union netr_LogonLevel *logon)
733 {
734         netlogon_creds_crypt_samlogon_logon(creds, level, logon, true);
735 }
736
737 union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx,
738                                         enum netr_LogonInfoClass level,
739                                         const union netr_LogonLevel *in)
740 {
741         union netr_LogonLevel *out;
742
743         if (in == NULL) {
744                 return NULL;
745         }
746
747         out = talloc(mem_ctx, union netr_LogonLevel);
748         if (out == NULL) {
749                 return NULL;
750         }
751
752         *out = *in;
753
754         switch (level) {
755         case NetlogonInteractiveInformation:
756         case NetlogonInteractiveTransitiveInformation:
757         case NetlogonServiceInformation:
758         case NetlogonServiceTransitiveInformation:
759                 if (in->password == NULL) {
760                         return out;
761                 }
762
763                 out->password = talloc(out, struct netr_PasswordInfo);
764                 if (out->password == NULL) {
765                         talloc_free(out);
766                         return NULL;
767                 }
768                 *out->password = *in->password;
769
770                 return out;
771
772         case NetlogonNetworkInformation:
773         case NetlogonNetworkTransitiveInformation:
774                 break;
775
776         case NetlogonGenericInformation:
777                 if (in->generic == NULL) {
778                         return out;
779                 }
780
781                 out->generic = talloc(out, struct netr_GenericInfo);
782                 if (out->generic == NULL) {
783                         talloc_free(out);
784                         return NULL;
785                 }
786                 *out->generic = *in->generic;
787
788                 if (in->generic->data == NULL) {
789                         return out;
790                 }
791
792                 if (in->generic->length == 0) {
793                         return out;
794                 }
795
796                 out->generic->data = talloc_memdup(out->generic,
797                                                    in->generic->data,
798                                                    in->generic->length);
799                 if (out->generic->data == NULL) {
800                         talloc_free(out);
801                         return NULL;
802                 }
803
804                 return out;
805         }
806
807         return out;
808 }
809
810 /*
811   copy a netlogon_creds_CredentialState struct
812 */
813
814 struct netlogon_creds_CredentialState *netlogon_creds_copy(
815         TALLOC_CTX *mem_ctx,
816         const struct netlogon_creds_CredentialState *creds_in)
817 {
818         struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
819
820         if (!creds) {
821                 return NULL;
822         }
823
824         creds->sequence                 = creds_in->sequence;
825         creds->negotiate_flags          = creds_in->negotiate_flags;
826         creds->secure_channel_type      = creds_in->secure_channel_type;
827
828         creds->computer_name = talloc_strdup(creds, creds_in->computer_name);
829         if (!creds->computer_name) {
830                 talloc_free(creds);
831                 return NULL;
832         }
833         creds->account_name = talloc_strdup(creds, creds_in->account_name);
834         if (!creds->account_name) {
835                 talloc_free(creds);
836                 return NULL;
837         }
838
839         if (creds_in->sid) {
840                 creds->sid = dom_sid_dup(creds, creds_in->sid);
841                 if (!creds->sid) {
842                         talloc_free(creds);
843                         return NULL;
844                 }
845         }
846
847         memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key));
848         memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data));
849         memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data));
850         memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data));
851
852         return creds;
853 }