source: vendor/current/libcli/auth/credentials.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 23.7 KB
Line 
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
29static 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*/
51static 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*/
75static 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*/
103static 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
126static 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*/
141static 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*/
176void 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*/
186void 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*/
196void 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*/
206void 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*/
216void 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*/
228void 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*/
242void 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/*****************************************************************
254The above functions are common to the client and server interface
255next comes the client specific functions
256******************************************************************/
257
258/*
259 initialise the credentials chain and return the first client
260 credentials
261*/
262
263struct 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
322struct 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*/
344void 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*/
379bool 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/*****************************************************************
392The above functions are common to the client and server interface
393next comes the server specific functions
394******************************************************************/
395
396/*
397 check that a credentials reply from a server is correct
398*/
399static 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*/
415struct 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
486NTSTATUS 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
510static 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 static const char zeros[16];
516 struct netr_SamBaseInfo *base = NULL;
517
518 if (validation == NULL) {
519 return;
520 }
521
522 switch (validation_level) {
523 case 2:
524 if (validation->sam2) {
525 base = &validation->sam2->base;
526 }
527 break;
528 case 3:
529 if (validation->sam3) {
530 base = &validation->sam3->base;
531 }
532 break;
533 case 6:
534 if (validation->sam6) {
535 base = &validation->sam6->base;
536 }
537 break;
538 default:
539 /* If we can't find it, we can't very well decrypt it */
540 return;
541 }
542
543 if (!base) {
544 return;
545 }
546
547 /* find and decyrpt the session keys, return in parameters above */
548 if (validation_level == 6) {
549 /* they aren't encrypted! */
550 } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
551 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
552 if (memcmp(base->key.key, zeros,
553 sizeof(base->key.key)) != 0) {
554 if (do_encrypt) {
555 netlogon_creds_aes_encrypt(creds,
556 base->key.key,
557 sizeof(base->key.key));
558 } else {
559 netlogon_creds_aes_decrypt(creds,
560 base->key.key,
561 sizeof(base->key.key));
562 }
563 }
564
565 if (memcmp(base->LMSessKey.key, zeros,
566 sizeof(base->LMSessKey.key)) != 0) {
567 if (do_encrypt) {
568 netlogon_creds_aes_encrypt(creds,
569 base->LMSessKey.key,
570 sizeof(base->LMSessKey.key));
571
572 } else {
573 netlogon_creds_aes_decrypt(creds,
574 base->LMSessKey.key,
575 sizeof(base->LMSessKey.key));
576 }
577 }
578 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
579 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
580 if (memcmp(base->key.key, zeros,
581 sizeof(base->key.key)) != 0) {
582 netlogon_creds_arcfour_crypt(creds,
583 base->key.key,
584 sizeof(base->key.key));
585 }
586
587 if (memcmp(base->LMSessKey.key, zeros,
588 sizeof(base->LMSessKey.key)) != 0) {
589 netlogon_creds_arcfour_crypt(creds,
590 base->LMSessKey.key,
591 sizeof(base->LMSessKey.key));
592 }
593 } else {
594 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
595 if (memcmp(base->LMSessKey.key, zeros,
596 sizeof(base->LMSessKey.key)) != 0) {
597 if (do_encrypt) {
598 netlogon_creds_des_encrypt_LMKey(creds,
599 &base->LMSessKey);
600 } else {
601 netlogon_creds_des_decrypt_LMKey(creds,
602 &base->LMSessKey);
603 }
604 }
605 }
606}
607
608void netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
609 uint16_t validation_level,
610 union netr_Validation *validation)
611{
612 netlogon_creds_crypt_samlogon_validation(creds, validation_level,
613 validation, false);
614}
615
616void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
617 uint16_t validation_level,
618 union netr_Validation *validation)
619{
620 netlogon_creds_crypt_samlogon_validation(creds, validation_level,
621 validation, true);
622}
623
624static void netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
625 enum netr_LogonInfoClass level,
626 union netr_LogonLevel *logon,
627 bool do_encrypt)
628{
629 static const char zeros[16];
630
631 if (logon == NULL) {
632 return;
633 }
634
635 switch (level) {
636 case NetlogonInteractiveInformation:
637 case NetlogonInteractiveTransitiveInformation:
638 case NetlogonServiceInformation:
639 case NetlogonServiceTransitiveInformation:
640 if (logon->password == NULL) {
641 return;
642 }
643
644 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
645 uint8_t *h;
646
647 h = logon->password->lmpassword.hash;
648 if (memcmp(h, zeros, 16) != 0) {
649 if (do_encrypt) {
650 netlogon_creds_aes_encrypt(creds, h, 16);
651 } else {
652 netlogon_creds_aes_decrypt(creds, h, 16);
653 }
654 }
655
656 h = logon->password->ntpassword.hash;
657 if (memcmp(h, zeros, 16) != 0) {
658 if (do_encrypt) {
659 netlogon_creds_aes_encrypt(creds, h, 16);
660 } else {
661 netlogon_creds_aes_decrypt(creds, h, 16);
662 }
663 }
664 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
665 uint8_t *h;
666
667 h = logon->password->lmpassword.hash;
668 if (memcmp(h, zeros, 16) != 0) {
669 netlogon_creds_arcfour_crypt(creds, h, 16);
670 }
671
672 h = logon->password->ntpassword.hash;
673 if (memcmp(h, zeros, 16) != 0) {
674 netlogon_creds_arcfour_crypt(creds, h, 16);
675 }
676 } else {
677 struct samr_Password *p;
678
679 p = &logon->password->lmpassword;
680 if (memcmp(p->hash, zeros, 16) != 0) {
681 if (do_encrypt) {
682 netlogon_creds_des_encrypt(creds, p);
683 } else {
684 netlogon_creds_des_decrypt(creds, p);
685 }
686 }
687 p = &logon->password->ntpassword;
688 if (memcmp(p->hash, zeros, 16) != 0) {
689 if (do_encrypt) {
690 netlogon_creds_des_encrypt(creds, p);
691 } else {
692 netlogon_creds_des_decrypt(creds, p);
693 }
694 }
695 }
696 break;
697
698 case NetlogonNetworkInformation:
699 case NetlogonNetworkTransitiveInformation:
700 break;
701
702 case NetlogonGenericInformation:
703 if (logon->generic == NULL) {
704 return;
705 }
706
707 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
708 if (do_encrypt) {
709 netlogon_creds_aes_encrypt(creds,
710 logon->generic->data,
711 logon->generic->length);
712 } else {
713 netlogon_creds_aes_decrypt(creds,
714 logon->generic->data,
715 logon->generic->length);
716 }
717 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
718 netlogon_creds_arcfour_crypt(creds,
719 logon->generic->data,
720 logon->generic->length);
721 } else {
722 /* Using DES to verify kerberos tickets makes no sense */
723 }
724 break;
725 }
726}
727
728void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
729 enum netr_LogonInfoClass level,
730 union netr_LogonLevel *logon)
731{
732 netlogon_creds_crypt_samlogon_logon(creds, level, logon, false);
733}
734
735void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
736 enum netr_LogonInfoClass level,
737 union netr_LogonLevel *logon)
738{
739 netlogon_creds_crypt_samlogon_logon(creds, level, logon, true);
740}
741
742union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx,
743 enum netr_LogonInfoClass level,
744 const union netr_LogonLevel *in)
745{
746 union netr_LogonLevel *out;
747
748 if (in == NULL) {
749 return NULL;
750 }
751
752 out = talloc(mem_ctx, union netr_LogonLevel);
753 if (out == NULL) {
754 return NULL;
755 }
756
757 *out = *in;
758
759 switch (level) {
760 case NetlogonInteractiveInformation:
761 case NetlogonInteractiveTransitiveInformation:
762 case NetlogonServiceInformation:
763 case NetlogonServiceTransitiveInformation:
764 if (in->password == NULL) {
765 return out;
766 }
767
768 out->password = talloc(out, struct netr_PasswordInfo);
769 if (out->password == NULL) {
770 talloc_free(out);
771 return NULL;
772 }
773 *out->password = *in->password;
774
775 return out;
776
777 case NetlogonNetworkInformation:
778 case NetlogonNetworkTransitiveInformation:
779 break;
780
781 case NetlogonGenericInformation:
782 if (in->generic == NULL) {
783 return out;
784 }
785
786 out->generic = talloc(out, struct netr_GenericInfo);
787 if (out->generic == NULL) {
788 talloc_free(out);
789 return NULL;
790 }
791 *out->generic = *in->generic;
792
793 if (in->generic->data == NULL) {
794 return out;
795 }
796
797 if (in->generic->length == 0) {
798 return out;
799 }
800
801 out->generic->data = talloc_memdup(out->generic,
802 in->generic->data,
803 in->generic->length);
804 if (out->generic->data == NULL) {
805 talloc_free(out);
806 return NULL;
807 }
808
809 return out;
810 }
811
812 return out;
813}
814
815/*
816 copy a netlogon_creds_CredentialState struct
817*/
818
819struct netlogon_creds_CredentialState *netlogon_creds_copy(TALLOC_CTX *mem_ctx,
820 struct netlogon_creds_CredentialState *creds_in)
821{
822 struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
823
824 if (!creds) {
825 return NULL;
826 }
827
828 creds->sequence = creds_in->sequence;
829 creds->negotiate_flags = creds_in->negotiate_flags;
830 creds->secure_channel_type = creds_in->secure_channel_type;
831
832 creds->computer_name = talloc_strdup(creds, creds_in->computer_name);
833 if (!creds->computer_name) {
834 talloc_free(creds);
835 return NULL;
836 }
837 creds->account_name = talloc_strdup(creds, creds_in->account_name);
838 if (!creds->account_name) {
839 talloc_free(creds);
840 return NULL;
841 }
842
843 if (creds_in->sid) {
844 creds->sid = dom_sid_dup(creds, creds_in->sid);
845 if (!creds->sid) {
846 talloc_free(creds);
847 return NULL;
848 }
849 }
850
851 memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key));
852 memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data));
853 memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data));
854 memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data));
855
856 return creds;
857}
Note: See TracBrowser for help on using the repository browser.