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 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
;
383 tmpkey
= machine_prev_password_keystr(domain
);
384 ok
= secrets_delete(tmpkey
);
389 tmpkey
= machine_password_keystr(domain
);
390 ok
= secrets_delete_entry(tmpkey
);
395 tmpkey
= machine_sec_channel_type_keystr(domain
);
396 ok
= secrets_delete_entry(tmpkey
);
401 tmpkey
= machine_last_change_time_keystr(domain
);
402 ok
= secrets_delete_entry(tmpkey
);
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
422 ************************************************************************/
424 static bool secrets_store_prev_machine_password(const char *domain
)
429 oldpass
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
430 if (oldpass
== NULL
) {
433 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
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.
442 ************************************************************************/
444 bool secrets_store_machine_password(const char *pass
, const char *domain
,
445 enum netr_SchannelType sec_channel
)
448 uint32_t last_change_time
;
449 uint32_t sec_channel_type
;
451 if (!secrets_store_prev_machine_password(domain
)) {
455 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
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
));
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
,
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
,
482 uint8_t last_change_time_store
[4];
483 TALLOC_CTX
*frame
= talloc_stackframe();
484 uint8_t sec_channel_bytes
[4];
487 secrets_delete_machine_password_ex(domain
);
488 secrets_delete_domain_sid(domain
);
493 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
500 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
502 ret
= secrets_delete(machine_prev_password_keystr(domain
));
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
));
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
));
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
));
537 ret
= secrets_store_domain_sid(domain
, domain_sid
);
545 char *key
= des_salt_key(realm
);
547 if (salting_principal
!= NULL
) {
548 ret
= secrets_store(key
,
550 strlen(salting_principal
)+1);
552 ret
= secrets_delete(key
);
560 /************************************************************************
561 Return the standard DES salt key
562 ************************************************************************/
564 char* kerberos_standard_des_salt( void )
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
)
582 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/DES/%s",
583 SECRETS_SALTING_PRINCIPAL
,
585 SMB_ASSERT(keystr
!= NULL
);
589 /************************************************************************
590 ************************************************************************/
592 bool kerberos_secrets_store_des_salt( const char* salt
)
597 key
= des_salt_key(lp_realm());
599 DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n"));
604 DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n"));
605 secrets_delete_entry( key
);
609 DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt
));
611 ret
= secrets_store( key
, salt
, strlen(salt
)+1 );
618 /************************************************************************
619 ************************************************************************/
622 char* kerberos_secrets_fetch_des_salt( void )
626 key
= des_salt_key(lp_realm());
628 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
632 salt
= (char*)secrets_fetch( key
, NULL
);
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)
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();
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
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
),
681 pass_last_set_time
= IVAL(last_set_time
,0);
682 SAFE_FREE(last_set_time
);
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
)
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
);
708 uint32_t *channel_type
;
709 channel_type
= (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain
), &size
);
711 *channel
= IVAL(channel_type
,0);
712 SAFE_FREE(channel_type
);
714 *channel
= get_default_sec_channel();