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 */
27 #include "../libcli/auth/libcli_auth.h"
29 #include "dbwrap/dbwrap.h"
30 #include "../librpc/ndr/libndr.h"
32 #include "libcli/security/security.h"
35 #define DBGC_CLASS DBGC_PASSDB
37 static char *des_salt_key(const char *realm);
40 * Form a key for fetching the domain sid
42 * @param domain domain name
46 static const char *domain_sid_keystr(const char *domain)
50 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
51 SECRETS_DOMAIN_SID, domain);
52 SMB_ASSERT(keystr != NULL);
56 static const char *domain_guid_keystr(const char *domain)
60 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
61 SECRETS_DOMAIN_GUID, domain);
62 SMB_ASSERT(keystr != NULL);
66 static const char *protect_ids_keystr(const char *domain)
70 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
71 SECRETS_PROTECT_IDS, domain);
72 SMB_ASSERT(keystr != NULL);
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)
81 ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
83 DEBUG(0, ("Failed to protect the Domain IDs\n"));
88 bool secrets_clear_domain_protection(const char *domain)
91 void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
94 SAFE_FREE(protection);
95 ret = secrets_delete_entry(protect_ids_keystr(domain));
97 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
104 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
109 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
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);
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 */
124 if (dom_sid_equal(get_global_sam_sid(), sid) == false) {
125 reset_global_sam_sid();
131 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
133 struct dom_sid *dyn_sid;
136 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
141 if (size != sizeof(struct dom_sid)) {
151 bool secrets_store_domain_guid(const char *domain, const struct GUID *guid)
156 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
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);
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;
176 struct GUID new_guid;
178 key = domain_guid_keystr(domain);
179 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
182 if (lp_server_role() == ROLE_DOMAIN_PDC) {
183 new_guid = GUID_random();
184 if (!secrets_store_domain_guid(domain, &new_guid))
186 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
188 if (dyn_guid == NULL) {
193 if (size != sizeof(struct GUID)) {
194 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
205 * Form a key for fetching the machine trust account sec channel type
207 * @param domain domain name
211 static const char *machine_sec_channel_type_keystr(const char *domain)
215 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
216 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
218 SMB_ASSERT(keystr != NULL);
223 * Form a key for fetching the machine trust account last change time
225 * @param domain domain name
229 static const char *machine_last_change_time_keystr(const char *domain)
233 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
234 SECRETS_MACHINE_LAST_CHANGE_TIME,
236 SMB_ASSERT(keystr != NULL);
242 * Form a key for fetching the machine previous trust account password
244 * @param domain domain name
248 static const char *machine_prev_password_keystr(const char *domain)
252 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
253 SECRETS_MACHINE_PASSWORD_PREV, domain);
254 SMB_ASSERT(keystr != NULL);
259 * Form a key for fetching the machine trust account password
261 * @param domain domain name
265 static const char *machine_password_keystr(const char *domain)
269 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
270 SECRETS_MACHINE_PASSWORD, domain);
271 SMB_ASSERT(keystr != NULL);
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)
286 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
287 SECRETS_MACHINE_ACCT_PASS, domain);
288 SMB_ASSERT(keystr != NULL);
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) {
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,
316 time_t *pass_last_set_time,
317 enum netr_SchannelType *channel)
319 struct machine_acct_pass *pass;
322 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
323 trust_keystr(domain), &size))) {
324 DEBUG(5, ("secrets_fetch failed!\n"));
328 if (size != sizeof(*pass)) {
329 DEBUG(0, ("secrets were of incorrect size!\n"));
334 if (pass_last_set_time) {
335 *pass_last_set_time = pass->mod_time;
337 memcpy(ret_pwd, pass->hash, 16);
340 *channel = get_default_sec_channel();
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)
359 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
362 DEBUG(4,("Using cleartext machine password\n"));
363 E_md4hash(plaintext, ret_pwd);
364 SAFE_FREE(plaintext);
368 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
373 /************************************************************************
374 Routine to delete all information related to the domain joined machine.
375 ************************************************************************/
377 bool secrets_delete_machine_password_ex(const char *domain, const char *realm)
379 const char *tmpkey = NULL;
383 tmpkey = des_salt_key(domain);
384 ok = secrets_delete(tmpkey);
390 tmpkey = domain_guid_keystr(domain);
391 ok = secrets_delete(tmpkey);
396 tmpkey = machine_prev_password_keystr(domain);
397 ok = secrets_delete(tmpkey);
402 tmpkey = machine_password_keystr(domain);
403 ok = secrets_delete(tmpkey);
408 tmpkey = machine_sec_channel_type_keystr(domain);
409 ok = secrets_delete(tmpkey);
414 tmpkey = machine_last_change_time_keystr(domain);
415 ok = secrets_delete(tmpkey);
420 tmpkey = domain_sid_keystr(domain);
421 ok = secrets_delete(tmpkey);
429 /************************************************************************
430 Routine to delete the domain sid
431 ************************************************************************/
433 bool secrets_delete_domain_sid(const char *domain)
435 return secrets_delete_entry(domain_sid_keystr(domain));
438 /************************************************************************
439 Routine to store the previous machine password (by storing the current password
441 ************************************************************************/
443 static bool secrets_store_prev_machine_password(const char *domain)
448 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
449 if (oldpass == NULL) {
452 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
457 /************************************************************************
458 Routine to set the plaintext machine account password for a realm
459 the password is assumed to be a null terminated ascii string.
461 ************************************************************************/
463 bool secrets_store_machine_password(const char *pass, const char *domain,
464 enum netr_SchannelType sec_channel)
467 uint32_t last_change_time;
468 uint32_t sec_channel_type;
470 if (!secrets_store_prev_machine_password(domain)) {
474 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
478 SIVAL(&last_change_time, 0, time(NULL));
479 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
481 SIVAL(&sec_channel_type, 0, sec_channel);
482 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
487 /************************************************************************
488 Set the machine trust account password, the old pw and last change
489 time, domain SID and salting principals based on values passed in
490 (added to supprt the secrets_tdb_sync module on secrets.ldb)
491 ************************************************************************/
493 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
495 const char *salting_principal, uint32_t supported_enc_types,
496 const struct dom_sid *domain_sid, uint32_t last_change_time,
497 uint32_t secure_channel_type,
501 uint8_t last_change_time_store[4];
502 TALLOC_CTX *frame = talloc_stackframe();
503 uint8_t sec_channel_bytes[4];
506 secrets_delete_machine_password_ex(domain, realm);
511 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
518 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
520 ret = secrets_delete(machine_prev_password_keystr(domain));
527 if (secure_channel_type == 0) {
528 /* We delete this and instead have the read code fall back to
529 * a default based on server role, as our caller can't specify
530 * this with any more certainty */
531 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
537 SIVAL(&sec_channel_bytes, 0, secure_channel_type);
538 ret = secrets_store(machine_sec_channel_type_keystr(domain),
539 &sec_channel_bytes, sizeof(sec_channel_bytes));
546 SIVAL(&last_change_time_store, 0, last_change_time);
547 ret = secrets_store(machine_last_change_time_keystr(domain),
548 &last_change_time_store, sizeof(last_change_time));
555 ret = secrets_store_domain_sid(domain, domain_sid);
563 char *key = des_salt_key(realm);
565 if (salting_principal != NULL) {
566 ret = secrets_store(key,
568 strlen(salting_principal)+1);
570 ret = secrets_delete(key);
578 /************************************************************************
579 Return the standard DES salt key
580 ************************************************************************/
582 char* kerberos_standard_des_salt( void )
586 fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() );
587 (void)strlower_m( salt );
588 fstrcat( salt, lp_realm() );
590 return SMB_STRDUP( salt );
593 /************************************************************************
594 ************************************************************************/
596 static char *des_salt_key(const char *realm)
600 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/DES/%s",
601 SECRETS_SALTING_PRINCIPAL,
603 SMB_ASSERT(keystr != NULL);
607 /************************************************************************
608 ************************************************************************/
610 bool kerberos_secrets_store_des_salt( const char* salt )
615 key = des_salt_key(lp_realm());
617 DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n"));
622 DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n"));
623 secrets_delete_entry( key );
627 DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt));
629 ret = secrets_store( key, salt, strlen(salt)+1 );
636 /************************************************************************
637 ************************************************************************/
640 char* kerberos_secrets_fetch_des_salt( void )
644 key = des_salt_key(lp_realm());
646 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
650 salt = (char*)secrets_fetch( key, NULL );
657 /************************************************************************
658 Routine to get the salting principal for this service.
659 Caller must free if return is not null.
660 ************************************************************************/
662 char *kerberos_secrets_fetch_salt_princ(void)
665 /* lookup new key first */
667 salt_princ_s = kerberos_secrets_fetch_des_salt();
668 if (salt_princ_s == NULL) {
669 /* fall back to host/machine.realm@REALM */
670 salt_princ_s = kerberos_standard_des_salt();
676 /************************************************************************
677 Routine to fetch the previous plaintext machine account password for a realm
678 the password is assumed to be a null terminated ascii string.
679 ************************************************************************/
681 char *secrets_fetch_prev_machine_password(const char *domain)
683 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
686 /************************************************************************
687 Routine to fetch the last change time of the machine account password
689 ************************************************************************/
691 time_t secrets_fetch_pass_last_set_time(const char *domain)
693 uint32_t *last_set_time;
694 time_t pass_last_set_time;
696 last_set_time = secrets_fetch(machine_last_change_time_keystr(domain),
699 pass_last_set_time = IVAL(last_set_time,0);
700 SAFE_FREE(last_set_time);
702 pass_last_set_time = 0;
705 return pass_last_set_time;
708 /************************************************************************
709 Routine to fetch the plaintext machine account password for a realm
710 the password is assumed to be a null terminated ascii string.
711 ************************************************************************/
713 char *secrets_fetch_machine_password(const char *domain,
714 time_t *pass_last_set_time,
715 enum netr_SchannelType *channel)
718 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
720 if (pass_last_set_time) {
721 *pass_last_set_time = secrets_fetch_pass_last_set_time(domain);
726 uint32_t *channel_type;
727 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
729 *channel = IVAL(channel_type,0);
730 SAFE_FREE(channel_type);
732 *channel = get_default_sec_channel();