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 the old plaintext machine account password if any
375 ************************************************************************/
377 static bool secrets_delete_prev_machine_password(const char *domain)
379 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
380 if (oldpass == NULL) {
384 return secrets_delete_entry(machine_prev_password_keystr(domain));
387 /************************************************************************
388 Routine to delete the plaintext machine account password, old password,
389 sec channel type and last change time from secrets database
390 ************************************************************************/
392 bool secrets_delete_machine_password_ex(const char *domain)
394 if (!secrets_delete_prev_machine_password(domain)) {
397 if (!secrets_delete_entry(machine_password_keystr(domain))) {
400 if (!secrets_delete_entry(machine_sec_channel_type_keystr(domain))) {
403 return secrets_delete_entry(machine_last_change_time_keystr(domain));
406 /************************************************************************
407 Routine to delete the domain sid
408 ************************************************************************/
410 bool secrets_delete_domain_sid(const char *domain)
412 return secrets_delete_entry(domain_sid_keystr(domain));
415 /************************************************************************
416 Routine to store the previous machine password (by storing the current password
418 ************************************************************************/
420 static bool secrets_store_prev_machine_password(const char *domain)
425 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
426 if (oldpass == NULL) {
429 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
434 /************************************************************************
435 Routine to set the plaintext machine account password for a realm
436 the password is assumed to be a null terminated ascii string.
438 ************************************************************************/
440 bool secrets_store_machine_password(const char *pass, const char *domain,
441 enum netr_SchannelType sec_channel)
444 uint32_t last_change_time;
445 uint32_t sec_channel_type;
447 if (!secrets_store_prev_machine_password(domain)) {
451 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
455 SIVAL(&last_change_time, 0, time(NULL));
456 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
458 SIVAL(&sec_channel_type, 0, sec_channel);
459 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
464 /************************************************************************
465 Set the machine trust account password, the old pw and last change
466 time, domain SID and salting principals based on values passed in
467 (added to supprt the secrets_tdb_sync module on secrets.ldb)
468 ************************************************************************/
470 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
472 const char *salting_principal, uint32_t supported_enc_types,
473 const struct dom_sid *domain_sid, uint32_t last_change_time,
474 uint32_t secure_channel_type,
478 uint8_t last_change_time_store[4];
479 TALLOC_CTX *frame = talloc_stackframe();
480 uint8_t sec_channel_bytes[4];
484 secrets_delete_machine_password_ex(domain);
485 secrets_delete_domain_sid(domain);
490 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
497 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
499 value = secrets_fetch_prev_machine_password(domain);
502 ret = secrets_delete_prev_machine_password(domain);
510 if (secure_channel_type == 0) {
511 /* We delete this and instead have the read code fall back to
512 * a default based on server role, as our caller can't specify
513 * this with any more certainty */
514 value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
517 ret = secrets_delete_entry(machine_sec_channel_type_keystr(domain));
524 SIVAL(&sec_channel_bytes, 0, secure_channel_type);
525 ret = secrets_store(machine_sec_channel_type_keystr(domain),
526 &sec_channel_bytes, sizeof(sec_channel_bytes));
533 SIVAL(&last_change_time_store, 0, last_change_time);
534 ret = secrets_store(machine_last_change_time_keystr(domain),
535 &last_change_time_store, sizeof(last_change_time));
542 ret = secrets_store_domain_sid(domain, domain_sid);
549 if (realm && salting_principal) {
550 char *key = des_salt_key(realm);
551 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
558 /************************************************************************
559 Return the standard DES salt key
560 ************************************************************************/
562 char* kerberos_standard_des_salt( void )
566 fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() );
567 (void)strlower_m( salt );
568 fstrcat( salt, lp_realm() );
570 return SMB_STRDUP( salt );
573 /************************************************************************
574 ************************************************************************/
576 static char *des_salt_key(const char *realm)
580 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/DES/%s",
581 SECRETS_SALTING_PRINCIPAL,
583 SMB_ASSERT(keystr != NULL);
587 /************************************************************************
588 ************************************************************************/
590 bool kerberos_secrets_store_des_salt( const char* salt )
595 key = des_salt_key(lp_realm());
597 DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n"));
602 DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n"));
603 secrets_delete_entry( key );
607 DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt));
609 ret = secrets_store( key, salt, strlen(salt)+1 );
616 /************************************************************************
617 ************************************************************************/
620 char* kerberos_secrets_fetch_des_salt( void )
624 key = des_salt_key(lp_realm());
626 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
630 salt = (char*)secrets_fetch( key, NULL );
637 /************************************************************************
638 Routine to get the salting principal for this service.
639 Caller must free if return is not null.
640 ************************************************************************/
642 char *kerberos_secrets_fetch_salt_princ(void)
645 /* lookup new key first */
647 salt_princ_s = kerberos_secrets_fetch_des_salt();
648 if (salt_princ_s == NULL) {
649 /* fall back to host/machine.realm@REALM */
650 salt_princ_s = kerberos_standard_des_salt();
656 /************************************************************************
657 Routine to fetch the previous plaintext machine account password for a realm
658 the password is assumed to be a null terminated ascii string.
659 ************************************************************************/
661 char *secrets_fetch_prev_machine_password(const char *domain)
663 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
666 /************************************************************************
667 Routine to fetch the last change time of the machine account password
669 ************************************************************************/
671 time_t secrets_fetch_pass_last_set_time(const char *domain)
673 uint32_t *last_set_time;
674 time_t pass_last_set_time;
676 last_set_time = secrets_fetch(machine_last_change_time_keystr(domain),
679 pass_last_set_time = IVAL(last_set_time,0);
680 SAFE_FREE(last_set_time);
682 pass_last_set_time = 0;
685 return pass_last_set_time;
688 /************************************************************************
689 Routine to fetch the plaintext machine account password for a realm
690 the password is assumed to be a null terminated ascii string.
691 ************************************************************************/
693 char *secrets_fetch_machine_password(const char *domain,
694 time_t *pass_last_set_time,
695 enum netr_SchannelType *channel)
698 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
700 if (pass_last_set_time) {
701 *pass_last_set_time = secrets_fetch_pass_last_set_time(domain);
706 uint32_t *channel_type;
707 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
709 *channel = IVAL(channel_type,0);
710 SAFE_FREE(channel_type);
712 *channel = get_default_sec_channel();