s3:secrets: rewrite secrets_delete_machine_password_ex() using helper variables
[Samba.git] / source3 / passdb / machine_account_secrets.c
blob56a944246b8d5fc146031b01a52703daa5ea1ff7
1 /*
2 Unix SMB/CIFS implementation.
3 Copyright (C) Andrew Tridgell 1992-2001
4 Copyright (C) Andrew Bartlett 2002
5 Copyright (C) Rafal Szczesniak 2002
6 Copyright (C) Tim Potter 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* the Samba secrets database stores any generated, private information
23 such as the local SID and machine trust password */
25 #include "includes.h"
26 #include "passdb.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "secrets.h"
29 #include "dbwrap/dbwrap.h"
30 #include "../librpc/ndr/libndr.h"
31 #include "util_tdb.h"
32 #include "libcli/security/security.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_PASSDB
37 static char *des_salt_key(const char *realm);
39 /**
40 * Form a key for fetching the domain sid
42 * @param domain domain name
44 * @return keystring
45 **/
46 static const char *domain_sid_keystr(const char *domain)
48 char *keystr;
50 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
51 SECRETS_DOMAIN_SID, domain);
52 SMB_ASSERT(keystr != NULL);
53 return keystr;
56 static const char *domain_guid_keystr(const char *domain)
58 char *keystr;
60 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
61 SECRETS_DOMAIN_GUID, domain);
62 SMB_ASSERT(keystr != NULL);
63 return keystr;
66 static const char *protect_ids_keystr(const char *domain)
68 char *keystr;
70 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
71 SECRETS_PROTECT_IDS, domain);
72 SMB_ASSERT(keystr != NULL);
73 return keystr;
76 /* N O T E: never use this outside of passdb modules that store the SID on their own */
77 bool secrets_mark_domain_protected(const char *domain)
79 bool ret;
81 ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
82 if (!ret) {
83 DEBUG(0, ("Failed to protect the Domain IDs\n"));
85 return ret;
88 bool secrets_clear_domain_protection(const char *domain)
90 bool ret;
91 void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
93 if (protection) {
94 SAFE_FREE(protection);
95 ret = secrets_delete_entry(protect_ids_keystr(domain));
96 if (!ret) {
97 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
99 return ret;
101 return true;
104 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
106 char *protect_ids;
107 bool ret;
109 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
110 if (protect_ids) {
111 if (strncmp(protect_ids, "TRUE", 4)) {
112 DEBUG(0, ("Refusing to store a Domain SID, "
113 "it has been marked as protected!\n"));
114 SAFE_FREE(protect_ids);
115 return false;
118 SAFE_FREE(protect_ids);
120 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
122 /* Force a re-query, in the case where we modified our domain */
123 if (ret) {
124 if (dom_sid_equal(get_global_sam_sid(), sid) == false) {
125 reset_global_sam_sid();
128 return ret;
131 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
133 struct dom_sid *dyn_sid;
134 size_t size = 0;
136 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
138 if (dyn_sid == NULL)
139 return False;
141 if (size != sizeof(struct dom_sid)) {
142 SAFE_FREE(dyn_sid);
143 return False;
146 *sid = *dyn_sid;
147 SAFE_FREE(dyn_sid);
148 return True;
151 bool secrets_store_domain_guid(const char *domain, const struct GUID *guid)
153 char *protect_ids;
154 const char *key;
156 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
157 if (protect_ids) {
158 if (strncmp(protect_ids, "TRUE", 4)) {
159 DEBUG(0, ("Refusing to store a Domain SID, "
160 "it has been marked as protected!\n"));
161 SAFE_FREE(protect_ids);
162 return false;
165 SAFE_FREE(protect_ids);
167 key = domain_guid_keystr(domain);
168 return secrets_store(key, guid, sizeof(struct GUID));
171 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
173 struct GUID *dyn_guid;
174 const char *key;
175 size_t size = 0;
176 struct GUID new_guid;
178 key = domain_guid_keystr(domain);
179 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
181 if (!dyn_guid) {
182 if (lp_server_role() == ROLE_DOMAIN_PDC) {
183 new_guid = GUID_random();
184 if (!secrets_store_domain_guid(domain, &new_guid))
185 return False;
186 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
188 if (dyn_guid == NULL) {
189 return False;
193 if (size != sizeof(struct GUID)) {
194 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
195 SAFE_FREE(dyn_guid);
196 return False;
199 *guid = *dyn_guid;
200 SAFE_FREE(dyn_guid);
201 return True;
205 * Form a key for fetching the machine trust account sec channel type
207 * @param domain domain name
209 * @return keystring
211 static const char *machine_sec_channel_type_keystr(const char *domain)
213 char *keystr;
215 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
216 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
217 domain);
218 SMB_ASSERT(keystr != NULL);
219 return keystr;
223 * Form a key for fetching the machine trust account last change time
225 * @param domain domain name
227 * @return keystring
229 static const char *machine_last_change_time_keystr(const char *domain)
231 char *keystr;
233 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
234 SECRETS_MACHINE_LAST_CHANGE_TIME,
235 domain);
236 SMB_ASSERT(keystr != NULL);
237 return keystr;
242 * Form a key for fetching the machine previous trust account password
244 * @param domain domain name
246 * @return keystring
248 static const char *machine_prev_password_keystr(const char *domain)
250 char *keystr;
252 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
253 SECRETS_MACHINE_PASSWORD_PREV, domain);
254 SMB_ASSERT(keystr != NULL);
255 return keystr;
259 * Form a key for fetching the machine trust account password
261 * @param domain domain name
263 * @return keystring
265 static const char *machine_password_keystr(const char *domain)
267 char *keystr;
269 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
270 SECRETS_MACHINE_PASSWORD, domain);
271 SMB_ASSERT(keystr != NULL);
272 return keystr;
276 * Form a key for fetching the machine trust account password
278 * @param domain domain name
280 * @return stored password's key
282 static const char *trust_keystr(const char *domain)
284 char *keystr;
286 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
287 SECRETS_MACHINE_ACCT_PASS, domain);
288 SMB_ASSERT(keystr != NULL);
289 return keystr;
292 /************************************************************************
293 Routine to get the default secure channel type for trust accounts
294 ************************************************************************/
296 enum netr_SchannelType get_default_sec_channel(void)
298 if (lp_server_role() == ROLE_DOMAIN_BDC ||
299 lp_server_role() == ROLE_DOMAIN_PDC ||
300 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
301 return SEC_CHAN_BDC;
302 } else {
303 return SEC_CHAN_WKSTA;
307 /************************************************************************
308 Routine to get the trust account password for a domain.
309 This only tries to get the legacy hashed version of the password.
310 The user of this function must have locked the trust password file using
311 the above secrets_lock_trust_account_password().
312 ************************************************************************/
314 bool secrets_fetch_trust_account_password_legacy(const char *domain,
315 uint8_t ret_pwd[16],
316 time_t *pass_last_set_time,
317 enum netr_SchannelType *channel)
319 struct machine_acct_pass *pass;
320 size_t size = 0;
322 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
323 trust_keystr(domain), &size))) {
324 DEBUG(5, ("secrets_fetch failed!\n"));
325 return False;
328 if (size != sizeof(*pass)) {
329 DEBUG(0, ("secrets were of incorrect size!\n"));
330 SAFE_FREE(pass);
331 return False;
334 if (pass_last_set_time) {
335 *pass_last_set_time = pass->mod_time;
337 memcpy(ret_pwd, pass->hash, 16);
339 if (channel) {
340 *channel = get_default_sec_channel();
343 SAFE_FREE(pass);
344 return True;
347 /************************************************************************
348 Routine to get the trust account password for a domain.
349 The user of this function must have locked the trust password file using
350 the above secrets_lock_trust_account_password().
351 ************************************************************************/
353 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
354 time_t *pass_last_set_time,
355 enum netr_SchannelType *channel)
357 char *plaintext;
359 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
360 channel);
361 if (plaintext) {
362 DEBUG(4,("Using cleartext machine password\n"));
363 E_md4hash(plaintext, ret_pwd);
364 SAFE_FREE(plaintext);
365 return True;
368 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
369 pass_last_set_time,
370 channel);
373 /************************************************************************
374 Routine to delete the plaintext machine account password, old password,
375 sec channel type and last change time from secrets database
376 ************************************************************************/
378 bool secrets_delete_machine_password_ex(const char *domain)
380 const char *tmpkey = NULL;
381 bool ok;
383 tmpkey = machine_prev_password_keystr(domain);
384 ok = secrets_delete(tmpkey);
385 if (!ok) {
386 return false;
389 tmpkey = machine_password_keystr(domain);
390 ok = secrets_delete_entry(tmpkey);
391 if (!ok) {
392 return false;
395 tmpkey = machine_sec_channel_type_keystr(domain);
396 ok = secrets_delete_entry(tmpkey);
397 if (!ok) {
398 return false;
401 tmpkey = machine_last_change_time_keystr(domain);
402 ok = secrets_delete_entry(tmpkey);
403 if (!ok) {
404 return false;
407 return true;
410 /************************************************************************
411 Routine to delete the domain sid
412 ************************************************************************/
414 bool secrets_delete_domain_sid(const char *domain)
416 return secrets_delete_entry(domain_sid_keystr(domain));
419 /************************************************************************
420 Routine to store the previous machine password (by storing the current password
421 as the old)
422 ************************************************************************/
424 static bool secrets_store_prev_machine_password(const char *domain)
426 char *oldpass;
427 bool ret;
429 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
430 if (oldpass == NULL) {
431 return true;
433 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
434 SAFE_FREE(oldpass);
435 return ret;
438 /************************************************************************
439 Routine to set the plaintext machine account password for a realm
440 the password is assumed to be a null terminated ascii string.
441 Before storing
442 ************************************************************************/
444 bool secrets_store_machine_password(const char *pass, const char *domain,
445 enum netr_SchannelType sec_channel)
447 bool ret;
448 uint32_t last_change_time;
449 uint32_t sec_channel_type;
451 if (!secrets_store_prev_machine_password(domain)) {
452 return false;
455 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
456 if (!ret)
457 return ret;
459 SIVAL(&last_change_time, 0, time(NULL));
460 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
462 SIVAL(&sec_channel_type, 0, sec_channel);
463 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
465 return ret;
468 /************************************************************************
469 Set the machine trust account password, the old pw and last change
470 time, domain SID and salting principals based on values passed in
471 (added to supprt the secrets_tdb_sync module on secrets.ldb)
472 ************************************************************************/
474 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
475 const char *realm,
476 const char *salting_principal, uint32_t supported_enc_types,
477 const struct dom_sid *domain_sid, uint32_t last_change_time,
478 uint32_t secure_channel_type,
479 bool delete_join)
481 bool ret;
482 uint8_t last_change_time_store[4];
483 TALLOC_CTX *frame = talloc_stackframe();
484 uint8_t sec_channel_bytes[4];
486 if (delete_join) {
487 secrets_delete_machine_password_ex(domain);
488 secrets_delete_domain_sid(domain);
489 TALLOC_FREE(frame);
490 return true;
493 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
494 if (!ret) {
495 TALLOC_FREE(frame);
496 return ret;
499 if (oldpass) {
500 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
501 } else {
502 ret = secrets_delete(machine_prev_password_keystr(domain));
504 if (!ret) {
505 TALLOC_FREE(frame);
506 return ret;
509 if (secure_channel_type == 0) {
510 /* We delete this and instead have the read code fall back to
511 * a default based on server role, as our caller can't specify
512 * this with any more certainty */
513 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
514 if (!ret) {
515 TALLOC_FREE(frame);
516 return ret;
518 } else {
519 SIVAL(&sec_channel_bytes, 0, secure_channel_type);
520 ret = secrets_store(machine_sec_channel_type_keystr(domain),
521 &sec_channel_bytes, sizeof(sec_channel_bytes));
522 if (!ret) {
523 TALLOC_FREE(frame);
524 return ret;
528 SIVAL(&last_change_time_store, 0, last_change_time);
529 ret = secrets_store(machine_last_change_time_keystr(domain),
530 &last_change_time_store, sizeof(last_change_time));
532 if (!ret) {
533 TALLOC_FREE(frame);
534 return ret;
537 ret = secrets_store_domain_sid(domain, domain_sid);
539 if (!ret) {
540 TALLOC_FREE(frame);
541 return ret;
544 if (realm != NULL) {
545 char *key = des_salt_key(realm);
547 if (salting_principal != NULL) {
548 ret = secrets_store(key,
549 salting_principal,
550 strlen(salting_principal)+1);
551 } else {
552 ret = secrets_delete(key);
556 TALLOC_FREE(frame);
557 return ret;
560 /************************************************************************
561 Return the standard DES salt key
562 ************************************************************************/
564 char* kerberos_standard_des_salt( void )
566 fstring salt;
568 fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() );
569 (void)strlower_m( salt );
570 fstrcat( salt, lp_realm() );
572 return SMB_STRDUP( salt );
575 /************************************************************************
576 ************************************************************************/
578 static char *des_salt_key(const char *realm)
580 char *keystr;
582 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/DES/%s",
583 SECRETS_SALTING_PRINCIPAL,
584 realm);
585 SMB_ASSERT(keystr != NULL);
586 return keystr;
589 /************************************************************************
590 ************************************************************************/
592 bool kerberos_secrets_store_des_salt( const char* salt )
594 char* key;
595 bool ret;
597 key = des_salt_key(lp_realm());
598 if (key == NULL) {
599 DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n"));
600 return False;
603 if ( !salt ) {
604 DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n"));
605 secrets_delete_entry( key );
606 return True;
609 DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt));
611 ret = secrets_store( key, salt, strlen(salt)+1 );
613 TALLOC_FREE(key);
615 return ret;
618 /************************************************************************
619 ************************************************************************/
621 static
622 char* kerberos_secrets_fetch_des_salt( void )
624 char *salt, *key;
626 key = des_salt_key(lp_realm());
627 if (key == NULL) {
628 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
629 return NULL;
632 salt = (char*)secrets_fetch( key, NULL );
634 TALLOC_FREE(key);
636 return salt;
639 /************************************************************************
640 Routine to get the salting principal for this service.
641 Caller must free if return is not null.
642 ************************************************************************/
644 char *kerberos_secrets_fetch_salt_princ(void)
646 char *salt_princ_s;
647 /* lookup new key first */
649 salt_princ_s = kerberos_secrets_fetch_des_salt();
650 if (salt_princ_s == NULL) {
651 /* fall back to host/machine.realm@REALM */
652 salt_princ_s = kerberos_standard_des_salt();
655 return salt_princ_s;
658 /************************************************************************
659 Routine to fetch the previous plaintext machine account password for a realm
660 the password is assumed to be a null terminated ascii string.
661 ************************************************************************/
663 char *secrets_fetch_prev_machine_password(const char *domain)
665 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
668 /************************************************************************
669 Routine to fetch the last change time of the machine account password
670 for a realm
671 ************************************************************************/
673 time_t secrets_fetch_pass_last_set_time(const char *domain)
675 uint32_t *last_set_time;
676 time_t pass_last_set_time;
678 last_set_time = secrets_fetch(machine_last_change_time_keystr(domain),
679 NULL);
680 if (last_set_time) {
681 pass_last_set_time = IVAL(last_set_time,0);
682 SAFE_FREE(last_set_time);
683 } else {
684 pass_last_set_time = 0;
687 return pass_last_set_time;
690 /************************************************************************
691 Routine to fetch the plaintext machine account password for a realm
692 the password is assumed to be a null terminated ascii string.
693 ************************************************************************/
695 char *secrets_fetch_machine_password(const char *domain,
696 time_t *pass_last_set_time,
697 enum netr_SchannelType *channel)
699 char *ret;
700 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
702 if (pass_last_set_time) {
703 *pass_last_set_time = secrets_fetch_pass_last_set_time(domain);
706 if (channel) {
707 size_t size;
708 uint32_t *channel_type;
709 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
710 if (channel_type) {
711 *channel = IVAL(channel_type,0);
712 SAFE_FREE(channel_type);
713 } else {
714 *channel = get_default_sec_channel();
718 return ret;