selftest: temporary skip samba.blackbox.pdbtest.s4winbind
[Samba.git] / libcli / auth / credentials.c
blobddff5e9d924aaf48cd0a613125b783e01246d505
1 /*
2 Unix SMB/CIFS implementation.
4 code to manipulate domain credentials
6 Copyright (C) Andrew Tridgell 1997-2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
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.
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.
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/>.
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"
29 static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
30 const struct netr_Credential *in,
31 struct netr_Credential *out)
33 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
34 AES_KEY key;
35 uint8_t iv[AES_BLOCK_SIZE];
37 AES_set_encrypt_key(creds->session_key, 128, &key);
38 ZERO_STRUCT(iv);
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);
47 initialise the credentials state for old-style 64 bit session keys
49 this call is made after the netr_ServerReqChallenge call
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)
56 uint32_t sum[2];
57 uint8_t sum2[8];
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);
62 SIVAL(sum2,0,sum[0]);
63 SIVAL(sum2,4,sum[1]);
65 ZERO_STRUCT(creds->session_key);
67 des_crypt128(creds->session_key, sum2, machine_password->hash);
71 initialise the credentials state for ADS-style 128 bit session keys
73 this call is made after the netr_ServerReqChallenge call
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)
80 unsigned char zero[4], tmp[16];
81 HMACMD5Context ctx;
82 MD5_CTX md5;
84 ZERO_STRUCT(creds->session_key);
86 memset(zero, 0, sizeof(zero));
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);
99 initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys
101 this call is made after the netr_ServerReqChallenge call
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)
108 struct HMACSHA256Context ctx;
109 uint8_t digest[SHA256_DIGEST_LENGTH];
111 ZERO_STRUCT(creds->session_key);
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);
120 memcpy(creds->session_key, digest, sizeof(creds->session_key));
122 ZERO_STRUCT(digest);
123 ZERO_STRUCT(ctx);
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)
130 netlogon_creds_step_crypt(creds, client_challenge, &creds->client);
132 netlogon_creds_step_crypt(creds, server_challenge, &creds->server);
134 creds->seed = creds->client;
138 step the credentials to the next element in the chain, updating the
139 current client and server credentials and the seed
141 static void netlogon_creds_step(struct netlogon_creds_CredentialState *creds)
143 struct netr_Credential time_cred;
145 DEBUG(5,("\tseed %08x:%08x\n",
146 IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
148 SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
149 SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
151 DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
153 netlogon_creds_step_crypt(creds, &time_cred, &creds->client);
155 DEBUG(5,("\tCLIENT %08x:%08x\n",
156 IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
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));
161 DEBUG(5,("\tseed+time+1 %08x:%08x\n",
162 IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
164 netlogon_creds_step_crypt(creds, &time_cred, &creds->server);
166 DEBUG(5,("\tSERVER %08x:%08x\n",
167 IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
169 creds->seed = time_cred;
174 DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
176 void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key)
178 struct netr_LMSessionKey tmp;
179 des_crypt56(tmp.key, key->key, creds->session_key, 1);
180 *key = tmp;
184 DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
186 void netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key)
188 struct netr_LMSessionKey tmp;
189 des_crypt56(tmp.key, key->key, creds->session_key, 0);
190 *key = tmp;
194 DES encrypt a 16 byte password buffer using the session key
196 void netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass)
198 struct samr_Password tmp;
199 des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 1);
200 *pass = tmp;
204 DES decrypt a 16 byte password buffer using the session key
206 void netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass)
208 struct samr_Password tmp;
209 des_crypt112_16(tmp.hash, pass->hash, creds->session_key, 0);
210 *pass = tmp;
214 ARCFOUR encrypt/decrypt a password buffer using the session key
216 void netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
218 DATA_BLOB session_key = data_blob(creds->session_key, 16);
220 arcfour_crypt_blob(data, len, &session_key);
222 data_blob_free(&session_key);
226 AES encrypt a password buffer using the session key
228 void netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
230 AES_KEY key;
231 uint8_t iv[AES_BLOCK_SIZE];
233 AES_set_encrypt_key(creds->session_key, 128, &key);
234 ZERO_STRUCT(iv);
236 aes_cfb8_encrypt(data, data, len, &key, iv, AES_ENCRYPT);
240 AES decrypt a password buffer using the session key
242 void netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len)
244 AES_KEY key;
245 uint8_t iv[AES_BLOCK_SIZE];
247 AES_set_encrypt_key(creds->session_key, 128, &key);
248 ZERO_STRUCT(iv);
250 aes_cfb8_encrypt(data, data, len, &key, iv, AES_DECRYPT);
253 /*****************************************************************
254 The above functions are common to the client and server interface
255 next comes the client specific functions
256 ******************************************************************/
259 initialise the credentials chain and return the first client
260 credentials
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)
273 struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
275 if (!creds) {
276 return NULL;
279 creds->sequence = time(NULL);
280 creds->negotiate_flags = negotiate_flags;
281 creds->secure_channel_type = secure_channel_type;
283 creds->computer_name = talloc_strdup(creds, client_computer_name);
284 if (!creds->computer_name) {
285 talloc_free(creds);
286 return NULL;
288 creds->account_name = talloc_strdup(creds, client_account);
289 if (!creds->account_name) {
290 talloc_free(creds);
291 return NULL;
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));
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);
309 netlogon_creds_first_step(creds, client_challenge, server_challenge);
311 dump_data_pw("Session key", creds->session_key, 16);
312 dump_data_pw("Credential ", creds->client.data, 8);
314 *initial_credential = creds->client;
315 return creds;
319 initialise the credentials structure with only a session key. The caller better know what they are doing!
322 struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx,
323 const uint8_t session_key[16])
325 struct netlogon_creds_CredentialState *creds;
327 creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
328 if (!creds) {
329 return NULL;
332 memcpy(creds->session_key, session_key, 16);
334 return creds;
338 step the credentials to the next element in the chain, updating the
339 current client and server credentials and the seed
341 produce the next authenticator in the sequence ready to send to
342 the server
344 void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds,
345 struct netr_Authenticator *next)
347 uint32_t t32n = (uint32_t)time(NULL);
350 * we always increment and ignore an overflow here
352 creds->sequence += 2;
354 if (t32n > creds->sequence) {
356 * we may increment more
358 creds->sequence = t32n;
359 } else {
360 uint32_t d = creds->sequence - t32n;
362 if (d >= INT32_MAX) {
364 * got an overflow of time_t vs. uint32_t
366 creds->sequence = t32n;
370 netlogon_creds_step(creds);
372 next->cred = creds->client;
373 next->timestamp = creds->sequence;
377 check that a credentials reply from a server is correct
379 bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds,
380 const struct netr_Credential *received_credentials)
382 if (!received_credentials ||
383 memcmp(received_credentials->data, creds->server.data, 8) != 0) {
384 DEBUG(2,("credentials check failed\n"));
385 return false;
387 return true;
391 /*****************************************************************
392 The above functions are common to the client and server interface
393 next comes the server specific functions
394 ******************************************************************/
397 check that a credentials reply from a server is correct
399 static bool netlogon_creds_server_check_internal(const struct netlogon_creds_CredentialState *creds,
400 const struct netr_Credential *received_credentials)
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;
408 return true;
412 initialise the credentials chain and return the first server
413 credentials
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)
427 struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
429 if (!creds) {
430 return NULL;
433 creds->negotiate_flags = negotiate_flags;
434 creds->secure_channel_type = secure_channel_type;
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));
440 creds->computer_name = talloc_strdup(creds, client_computer_name);
441 if (!creds->computer_name) {
442 talloc_free(creds);
443 return NULL;
445 creds->account_name = talloc_strdup(creds, client_account);
446 if (!creds->account_name) {
447 talloc_free(creds);
448 return NULL;
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);
464 netlogon_creds_first_step(creds, client_challenge, server_challenge);
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);
470 dump_data_pw("Credentials in", credentials_in->data, sizeof(credentials_in->data));
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;
479 *credentials_out = creds->server;
481 dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data));
483 return creds;
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)
490 if (!received_authenticator || !return_authenticator) {
491 return NT_STATUS_INVALID_PARAMETER;
494 if (!creds) {
495 return NT_STATUS_ACCESS_DENIED;
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;
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)
515 struct netr_SamBaseInfo *base = NULL;
517 if (validation == NULL) {
518 return;
521 switch (validation_level) {
522 case 2:
523 if (validation->sam2) {
524 base = &validation->sam2->base;
526 break;
527 case 3:
528 if (validation->sam3) {
529 base = &validation->sam3->base;
531 break;
532 case 6:
533 if (validation->sam6) {
534 base = &validation->sam6->base;
536 break;
537 default:
538 /* If we can't find it, we can't very well decrypt it */
539 return;
542 if (!base) {
543 return;
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));
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));
570 } else {
571 netlogon_creds_aes_decrypt(creds,
572 base->LMSessKey.key,
573 sizeof(base->LMSessKey.key));
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));
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));
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);
605 void netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
606 uint16_t validation_level,
607 union netr_Validation *validation)
609 netlogon_creds_crypt_samlogon_validation(creds, validation_level,
610 validation, false);
613 void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds,
614 uint16_t validation_level,
615 union netr_Validation *validation)
617 netlogon_creds_crypt_samlogon_validation(creds, validation_level,
618 validation, true);
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)
626 if (logon == NULL) {
627 return;
630 switch (level) {
631 case NetlogonInteractiveInformation:
632 case NetlogonInteractiveTransitiveInformation:
633 case NetlogonServiceInformation:
634 case NetlogonServiceTransitiveInformation:
635 if (logon->password == NULL) {
636 return;
639 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
640 uint8_t *h;
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);
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);
659 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
660 uint8_t *h;
662 h = logon->password->lmpassword.hash;
663 if (!all_zero(h, 16)) {
664 netlogon_creds_arcfour_crypt(creds, h, 16);
667 h = logon->password->ntpassword.hash;
668 if (!all_zero(h, 16)) {
669 netlogon_creds_arcfour_crypt(creds, h, 16);
671 } else {
672 struct samr_Password *p;
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);
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);
691 break;
693 case NetlogonNetworkInformation:
694 case NetlogonNetworkTransitiveInformation:
695 break;
697 case NetlogonGenericInformation:
698 if (logon->generic == NULL) {
699 return;
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);
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 */
719 break;
723 void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
724 enum netr_LogonInfoClass level,
725 union netr_LogonLevel *logon)
727 netlogon_creds_crypt_samlogon_logon(creds, level, logon, false);
730 void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds,
731 enum netr_LogonInfoClass level,
732 union netr_LogonLevel *logon)
734 netlogon_creds_crypt_samlogon_logon(creds, level, logon, true);
737 union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx,
738 enum netr_LogonInfoClass level,
739 const union netr_LogonLevel *in)
741 union netr_LogonLevel *out;
743 if (in == NULL) {
744 return NULL;
747 out = talloc(mem_ctx, union netr_LogonLevel);
748 if (out == NULL) {
749 return NULL;
752 *out = *in;
754 switch (level) {
755 case NetlogonInteractiveInformation:
756 case NetlogonInteractiveTransitiveInformation:
757 case NetlogonServiceInformation:
758 case NetlogonServiceTransitiveInformation:
759 if (in->password == NULL) {
760 return out;
763 out->password = talloc(out, struct netr_PasswordInfo);
764 if (out->password == NULL) {
765 talloc_free(out);
766 return NULL;
768 *out->password = *in->password;
770 return out;
772 case NetlogonNetworkInformation:
773 case NetlogonNetworkTransitiveInformation:
774 break;
776 case NetlogonGenericInformation:
777 if (in->generic == NULL) {
778 return out;
781 out->generic = talloc(out, struct netr_GenericInfo);
782 if (out->generic == NULL) {
783 talloc_free(out);
784 return NULL;
786 *out->generic = *in->generic;
788 if (in->generic->data == NULL) {
789 return out;
792 if (in->generic->length == 0) {
793 return out;
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;
804 return out;
807 return out;
811 copy a netlogon_creds_CredentialState struct
814 struct netlogon_creds_CredentialState *netlogon_creds_copy(TALLOC_CTX *mem_ctx,
815 struct netlogon_creds_CredentialState *creds_in)
817 struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
819 if (!creds) {
820 return NULL;
823 creds->sequence = creds_in->sequence;
824 creds->negotiate_flags = creds_in->negotiate_flags;
825 creds->secure_channel_type = creds_in->secure_channel_type;
827 creds->computer_name = talloc_strdup(creds, creds_in->computer_name);
828 if (!creds->computer_name) {
829 talloc_free(creds);
830 return NULL;
832 creds->account_name = talloc_strdup(creds, creds_in->account_name);
833 if (!creds->account_name) {
834 talloc_free(creds);
835 return NULL;
838 if (creds_in->sid) {
839 creds->sid = dom_sid_dup(creds, creds_in->sid);
840 if (!creds->sid) {
841 talloc_free(creds);
842 return NULL;
846 memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key));
847 memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data));
848 memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data));
849 memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data));
851 return creds;