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"
34 #define DBGC_CLASS DBGC_PASSDB
37 * Form a key for fetching the domain sid
39 * @param domain domain name
43 static const char *domain_sid_keystr(const char *domain
)
47 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
48 SECRETS_DOMAIN_SID
, domain
);
49 SMB_ASSERT(keystr
!= NULL
);
53 static const char *protect_ids_keystr(const char *domain
)
57 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
58 SECRETS_PROTECT_IDS
, domain
);
59 SMB_ASSERT(keystr
!= NULL
);
63 /* N O T E: never use this outside of passdb modules that store the SID on their own */
64 bool secrets_mark_domain_protected(const char *domain
)
68 ret
= secrets_store(protect_ids_keystr(domain
), "TRUE", 5);
70 DEBUG(0, ("Failed to protect the Domain IDs\n"));
75 bool secrets_clear_domain_protection(const char *domain
)
78 void *protection
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
81 SAFE_FREE(protection
);
82 ret
= secrets_delete(protect_ids_keystr(domain
));
84 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
91 bool secrets_store_domain_sid(const char *domain
, const struct dom_sid
*sid
)
93 #if _SAMBA_BUILD_ == 4
98 #if _SAMBA_BUILD_ == 4
99 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
101 if (strncmp(protect_ids
, "TRUE", 4)) {
102 DEBUG(0, ("Refusing to store a Domain SID, "
103 "it has been marked as protected!\n"));
109 ret
= secrets_store(domain_sid_keystr(domain
), sid
, sizeof(struct dom_sid
));
111 /* Force a re-query, in case we modified our domain */
113 reset_global_sam_sid();
117 bool secrets_fetch_domain_sid(const char *domain
, struct dom_sid
*sid
)
119 struct dom_sid
*dyn_sid
;
122 dyn_sid
= (struct dom_sid
*)secrets_fetch(domain_sid_keystr(domain
), &size
);
127 if (size
!= sizeof(struct dom_sid
)) {
137 bool secrets_store_domain_guid(const char *domain
, struct GUID
*guid
)
139 #if _SAMBA_BUILD_ == 4
144 #if _SAMBA_BUILD_ == 4
145 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
147 if (strncmp(protect_ids
, "TRUE", 4)) {
148 DEBUG(0, ("Refusing to store a Domain SID, "
149 "it has been marked as protected!\n"));
155 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
156 if (!strupper_m(key
)) {
159 return secrets_store(key
, guid
, sizeof(struct GUID
));
162 bool secrets_fetch_domain_guid(const char *domain
, struct GUID
*guid
)
164 struct GUID
*dyn_guid
;
167 struct GUID new_guid
;
169 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
170 if (!strupper_m(key
)) {
173 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
176 if (lp_server_role() == ROLE_DOMAIN_PDC
) {
177 new_guid
= GUID_random();
178 if (!secrets_store_domain_guid(domain
, &new_guid
))
180 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
182 if (dyn_guid
== NULL
) {
187 if (size
!= sizeof(struct GUID
)) {
188 DEBUG(1,("UUID size %d is wrong!\n", (int)size
));
199 * Form a key for fetching the machine trust account sec channel type
201 * @param domain domain name
205 static const char *machine_sec_channel_type_keystr(const char *domain
)
209 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
210 SECRETS_MACHINE_SEC_CHANNEL_TYPE
,
212 SMB_ASSERT(keystr
!= NULL
);
217 * Form a key for fetching the machine trust account last change time
219 * @param domain domain name
223 static const char *machine_last_change_time_keystr(const char *domain
)
227 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
228 SECRETS_MACHINE_LAST_CHANGE_TIME
,
230 SMB_ASSERT(keystr
!= NULL
);
236 * Form a key for fetching the machine previous trust account password
238 * @param domain domain name
242 static const char *machine_prev_password_keystr(const char *domain
)
246 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
247 SECRETS_MACHINE_PASSWORD_PREV
, domain
);
248 SMB_ASSERT(keystr
!= NULL
);
253 * Form a key for fetching the machine trust account password
255 * @param domain domain name
259 static const char *machine_password_keystr(const char *domain
)
263 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
264 SECRETS_MACHINE_PASSWORD
, domain
);
265 SMB_ASSERT(keystr
!= NULL
);
270 * Form a key for fetching the machine trust account password
272 * @param domain domain name
274 * @return stored password's key
276 static const char *trust_keystr(const char *domain
)
280 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
281 SECRETS_MACHINE_ACCT_PASS
, domain
);
282 SMB_ASSERT(keystr
!= NULL
);
286 /************************************************************************
287 Lock the trust password entry.
288 ************************************************************************/
290 void *secrets_get_trust_account_lock(TALLOC_CTX
*mem_ctx
, const char *domain
)
292 struct db_context
*db_ctx
;
293 if (!secrets_init()) {
297 db_ctx
= secrets_db_ctx();
299 return dbwrap_fetch_locked(
300 db_ctx
, mem_ctx
, string_term_tdb_data(trust_keystr(domain
)));
303 /************************************************************************
304 Routine to get the default secure channel type for trust accounts
305 ************************************************************************/
307 enum netr_SchannelType
get_default_sec_channel(void)
309 if (lp_server_role() == ROLE_DOMAIN_BDC
||
310 lp_server_role() == ROLE_DOMAIN_PDC
||
311 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
314 return SEC_CHAN_WKSTA
;
318 /************************************************************************
319 Routine to get the trust account password for a domain.
320 This only tries to get the legacy hashed version of the password.
321 The user of this function must have locked the trust password file using
322 the above secrets_lock_trust_account_password().
323 ************************************************************************/
325 bool secrets_fetch_trust_account_password_legacy(const char *domain
,
327 time_t *pass_last_set_time
,
328 enum netr_SchannelType
*channel
)
330 struct machine_acct_pass
*pass
;
333 if (!(pass
= (struct machine_acct_pass
*)secrets_fetch(
334 trust_keystr(domain
), &size
))) {
335 DEBUG(5, ("secrets_fetch failed!\n"));
339 if (size
!= sizeof(*pass
)) {
340 DEBUG(0, ("secrets were of incorrect size!\n"));
345 if (pass_last_set_time
) {
346 *pass_last_set_time
= pass
->mod_time
;
348 memcpy(ret_pwd
, pass
->hash
, 16);
351 *channel
= get_default_sec_channel();
358 /************************************************************************
359 Routine to get the trust account password for a domain.
360 The user of this function must have locked the trust password file using
361 the above secrets_lock_trust_account_password().
362 ************************************************************************/
364 bool secrets_fetch_trust_account_password(const char *domain
, uint8_t ret_pwd
[16],
365 time_t *pass_last_set_time
,
366 enum netr_SchannelType
*channel
)
370 plaintext
= secrets_fetch_machine_password(domain
, pass_last_set_time
,
373 DEBUG(4,("Using cleartext machine password\n"));
374 E_md4hash(plaintext
, ret_pwd
);
375 SAFE_FREE(plaintext
);
379 return secrets_fetch_trust_account_password_legacy(domain
, ret_pwd
,
384 /************************************************************************
385 Routine to delete the old plaintext machine account password if any
386 ************************************************************************/
388 static bool secrets_delete_prev_machine_password(const char *domain
)
390 char *oldpass
= (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
391 if (oldpass
== NULL
) {
395 return secrets_delete(machine_prev_password_keystr(domain
));
398 /************************************************************************
399 Routine to delete the plaintext machine account password, old password,
400 sec channel type and last change time from secrets database
401 ************************************************************************/
403 bool secrets_delete_machine_password_ex(const char *domain
)
405 if (!secrets_delete_prev_machine_password(domain
)) {
408 if (!secrets_delete(machine_password_keystr(domain
))) {
411 if (!secrets_delete(machine_sec_channel_type_keystr(domain
))) {
414 return secrets_delete(machine_last_change_time_keystr(domain
));
417 /************************************************************************
418 Routine to delete the domain sid
419 ************************************************************************/
421 bool secrets_delete_domain_sid(const char *domain
)
423 return secrets_delete(domain_sid_keystr(domain
));
426 /************************************************************************
427 Routine to store the previous machine password (by storing the current password
429 ************************************************************************/
431 static bool secrets_store_prev_machine_password(const char *domain
)
436 oldpass
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
437 if (oldpass
== NULL
) {
440 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
445 /************************************************************************
446 Routine to set the plaintext machine account password for a realm
447 the password is assumed to be a null terminated ascii string.
449 ************************************************************************/
451 bool secrets_store_machine_password(const char *pass
, const char *domain
,
452 enum netr_SchannelType sec_channel
)
455 uint32_t last_change_time
;
456 uint32_t sec_channel_type
;
458 if (!secrets_store_prev_machine_password(domain
)) {
462 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
466 SIVAL(&last_change_time
, 0, time(NULL
));
467 ret
= secrets_store(machine_last_change_time_keystr(domain
), &last_change_time
, sizeof(last_change_time
));
469 SIVAL(&sec_channel_type
, 0, sec_channel
);
470 ret
= secrets_store(machine_sec_channel_type_keystr(domain
), &sec_channel_type
, sizeof(sec_channel_type
));
475 /************************************************************************
476 Set the machine trust account password, the old pw and last change
477 time, domain SID and salting principals based on values passed in
478 (added to supprt the secrets_tdb_sync module on secrets.ldb)
479 ************************************************************************/
481 bool secrets_store_machine_pw_sync(const char *pass
, const char *oldpass
, const char *domain
,
483 const char *salting_principal
, uint32_t supported_enc_types
,
484 const struct dom_sid
*domain_sid
, uint32_t last_change_time
,
488 uint8_t last_change_time_store
[4];
489 TALLOC_CTX
*frame
= talloc_stackframe();
493 secrets_delete_machine_password_ex(domain
);
494 secrets_delete_domain_sid(domain
);
499 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
506 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
508 value
= secrets_fetch_prev_machine_password(domain
);
511 ret
= secrets_delete_prev_machine_password(domain
);
519 /* We delete this and instead have the read code fall back to
520 * a default based on server role, as our caller can't specify
521 * this with any more certainty */
522 value
= secrets_fetch(machine_sec_channel_type_keystr(domain
), NULL
);
525 ret
= secrets_delete(machine_sec_channel_type_keystr(domain
));
532 SIVAL(&last_change_time_store
, 0, last_change_time
);
533 ret
= secrets_store(machine_last_change_time_keystr(domain
),
534 &last_change_time_store
, sizeof(last_change_time
));
541 ret
= secrets_store_domain_sid(domain
, domain_sid
);
548 if (realm
&& salting_principal
) {
549 char *key
= talloc_asprintf(frame
, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL
, realm
);
554 ret
= secrets_store(key
, salting_principal
, strlen(salting_principal
)+1 );
562 /************************************************************************
563 Routine to fetch the previous plaintext machine account password for a realm
564 the password is assumed to be a null terminated ascii string.
565 ************************************************************************/
567 char *secrets_fetch_prev_machine_password(const char *domain
)
569 return (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
572 /************************************************************************
573 Routine to fetch the plaintext machine account password for a realm
574 the password is assumed to be a null terminated ascii string.
575 ************************************************************************/
577 char *secrets_fetch_machine_password(const char *domain
,
578 time_t *pass_last_set_time
,
579 enum netr_SchannelType
*channel
)
582 ret
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
584 if (pass_last_set_time
) {
586 uint32_t *last_set_time
;
587 last_set_time
= (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain
), &size
);
589 *pass_last_set_time
= IVAL(last_set_time
,0);
590 SAFE_FREE(last_set_time
);
592 *pass_last_set_time
= 0;
598 uint32_t *channel_type
;
599 channel_type
= (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain
), &size
);
601 *channel
= IVAL(channel_type
,0);
602 SAFE_FREE(channel_type
);
604 *channel
= get_default_sec_channel();