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"));
104 SAFE_FREE(protect_ids
);
108 SAFE_FREE(protect_ids
);
111 ret
= secrets_store(domain_sid_keystr(domain
), sid
, sizeof(struct dom_sid
));
113 /* Force a re-query, in case we modified our domain */
115 reset_global_sam_sid();
119 bool secrets_fetch_domain_sid(const char *domain
, struct dom_sid
*sid
)
121 struct dom_sid
*dyn_sid
;
124 dyn_sid
= (struct dom_sid
*)secrets_fetch(domain_sid_keystr(domain
), &size
);
129 if (size
!= sizeof(struct dom_sid
)) {
139 bool secrets_store_domain_guid(const char *domain
, struct GUID
*guid
)
141 #if _SAMBA_BUILD_ == 4
146 #if _SAMBA_BUILD_ == 4
147 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
149 if (strncmp(protect_ids
, "TRUE", 4)) {
150 DEBUG(0, ("Refusing to store a Domain SID, "
151 "it has been marked as protected!\n"));
152 SAFE_FREE(protect_ids
);
156 SAFE_FREE(protect_ids
);
159 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
160 if (!strupper_m(key
)) {
163 return secrets_store(key
, guid
, sizeof(struct GUID
));
166 bool secrets_fetch_domain_guid(const char *domain
, struct GUID
*guid
)
168 struct GUID
*dyn_guid
;
171 struct GUID new_guid
;
173 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
174 if (!strupper_m(key
)) {
177 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
180 if (lp_server_role() == ROLE_DOMAIN_PDC
) {
181 new_guid
= GUID_random();
182 if (!secrets_store_domain_guid(domain
, &new_guid
))
184 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
186 if (dyn_guid
== NULL
) {
191 if (size
!= sizeof(struct GUID
)) {
192 DEBUG(1,("UUID size %d is wrong!\n", (int)size
));
203 * Form a key for fetching the machine trust account sec channel type
205 * @param domain domain name
209 static const char *machine_sec_channel_type_keystr(const char *domain
)
213 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
214 SECRETS_MACHINE_SEC_CHANNEL_TYPE
,
216 SMB_ASSERT(keystr
!= NULL
);
221 * Form a key for fetching the machine trust account last change time
223 * @param domain domain name
227 static const char *machine_last_change_time_keystr(const char *domain
)
231 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
232 SECRETS_MACHINE_LAST_CHANGE_TIME
,
234 SMB_ASSERT(keystr
!= NULL
);
240 * Form a key for fetching the machine previous trust account password
242 * @param domain domain name
246 static const char *machine_prev_password_keystr(const char *domain
)
250 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
251 SECRETS_MACHINE_PASSWORD_PREV
, domain
);
252 SMB_ASSERT(keystr
!= NULL
);
257 * Form a key for fetching the machine trust account password
259 * @param domain domain name
263 static const char *machine_password_keystr(const char *domain
)
267 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
268 SECRETS_MACHINE_PASSWORD
, domain
);
269 SMB_ASSERT(keystr
!= NULL
);
274 * Form a key for fetching the machine trust account password
276 * @param domain domain name
278 * @return stored password's key
280 static const char *trust_keystr(const char *domain
)
284 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
285 SECRETS_MACHINE_ACCT_PASS
, domain
);
286 SMB_ASSERT(keystr
!= NULL
);
290 /************************************************************************
291 Lock the trust password entry.
292 ************************************************************************/
294 void *secrets_get_trust_account_lock(TALLOC_CTX
*mem_ctx
, const char *domain
)
296 struct db_context
*db_ctx
;
297 if (!secrets_init()) {
301 db_ctx
= secrets_db_ctx();
303 return dbwrap_fetch_locked(
304 db_ctx
, mem_ctx
, string_term_tdb_data(trust_keystr(domain
)));
307 /************************************************************************
308 Routine to get the default secure channel type for trust accounts
309 ************************************************************************/
311 enum netr_SchannelType
get_default_sec_channel(void)
313 if (lp_server_role() == ROLE_DOMAIN_BDC
||
314 lp_server_role() == ROLE_DOMAIN_PDC
||
315 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
318 return SEC_CHAN_WKSTA
;
322 /************************************************************************
323 Routine to get the trust account password for a domain.
324 This only tries to get the legacy hashed version of the password.
325 The user of this function must have locked the trust password file using
326 the above secrets_lock_trust_account_password().
327 ************************************************************************/
329 bool secrets_fetch_trust_account_password_legacy(const char *domain
,
331 time_t *pass_last_set_time
,
332 enum netr_SchannelType
*channel
)
334 struct machine_acct_pass
*pass
;
337 if (!(pass
= (struct machine_acct_pass
*)secrets_fetch(
338 trust_keystr(domain
), &size
))) {
339 DEBUG(5, ("secrets_fetch failed!\n"));
343 if (size
!= sizeof(*pass
)) {
344 DEBUG(0, ("secrets were of incorrect size!\n"));
349 if (pass_last_set_time
) {
350 *pass_last_set_time
= pass
->mod_time
;
352 memcpy(ret_pwd
, pass
->hash
, 16);
355 *channel
= get_default_sec_channel();
362 /************************************************************************
363 Routine to get the trust account password for a domain.
364 The user of this function must have locked the trust password file using
365 the above secrets_lock_trust_account_password().
366 ************************************************************************/
368 bool secrets_fetch_trust_account_password(const char *domain
, uint8_t ret_pwd
[16],
369 time_t *pass_last_set_time
,
370 enum netr_SchannelType
*channel
)
374 plaintext
= secrets_fetch_machine_password(domain
, pass_last_set_time
,
377 DEBUG(4,("Using cleartext machine password\n"));
378 E_md4hash(plaintext
, ret_pwd
);
379 SAFE_FREE(plaintext
);
383 return secrets_fetch_trust_account_password_legacy(domain
, ret_pwd
,
388 /************************************************************************
389 Routine to delete the old plaintext machine account password if any
390 ************************************************************************/
392 static bool secrets_delete_prev_machine_password(const char *domain
)
394 char *oldpass
= (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
395 if (oldpass
== NULL
) {
399 return secrets_delete(machine_prev_password_keystr(domain
));
402 /************************************************************************
403 Routine to delete the plaintext machine account password, old password,
404 sec channel type and last change time from secrets database
405 ************************************************************************/
407 bool secrets_delete_machine_password_ex(const char *domain
)
409 if (!secrets_delete_prev_machine_password(domain
)) {
412 if (!secrets_delete(machine_password_keystr(domain
))) {
415 if (!secrets_delete(machine_sec_channel_type_keystr(domain
))) {
418 return secrets_delete(machine_last_change_time_keystr(domain
));
421 /************************************************************************
422 Routine to delete the domain sid
423 ************************************************************************/
425 bool secrets_delete_domain_sid(const char *domain
)
427 return secrets_delete(domain_sid_keystr(domain
));
430 /************************************************************************
431 Routine to store the previous machine password (by storing the current password
433 ************************************************************************/
435 static bool secrets_store_prev_machine_password(const char *domain
)
440 oldpass
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
441 if (oldpass
== NULL
) {
444 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
449 /************************************************************************
450 Routine to set the plaintext machine account password for a realm
451 the password is assumed to be a null terminated ascii string.
453 ************************************************************************/
455 bool secrets_store_machine_password(const char *pass
, const char *domain
,
456 enum netr_SchannelType sec_channel
)
459 uint32_t last_change_time
;
460 uint32_t sec_channel_type
;
462 if (!secrets_store_prev_machine_password(domain
)) {
466 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
470 SIVAL(&last_change_time
, 0, time(NULL
));
471 ret
= secrets_store(machine_last_change_time_keystr(domain
), &last_change_time
, sizeof(last_change_time
));
473 SIVAL(&sec_channel_type
, 0, sec_channel
);
474 ret
= secrets_store(machine_sec_channel_type_keystr(domain
), &sec_channel_type
, sizeof(sec_channel_type
));
479 /************************************************************************
480 Set the machine trust account password, the old pw and last change
481 time, domain SID and salting principals based on values passed in
482 (added to supprt the secrets_tdb_sync module on secrets.ldb)
483 ************************************************************************/
485 bool secrets_store_machine_pw_sync(const char *pass
, const char *oldpass
, const char *domain
,
487 const char *salting_principal
, uint32_t supported_enc_types
,
488 const struct dom_sid
*domain_sid
, uint32_t last_change_time
,
492 uint8_t last_change_time_store
[4];
493 TALLOC_CTX
*frame
= talloc_stackframe();
497 secrets_delete_machine_password_ex(domain
);
498 secrets_delete_domain_sid(domain
);
503 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
510 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
512 value
= secrets_fetch_prev_machine_password(domain
);
515 ret
= secrets_delete_prev_machine_password(domain
);
523 /* We delete this and instead have the read code fall back to
524 * a default based on server role, as our caller can't specify
525 * this with any more certainty */
526 value
= secrets_fetch(machine_sec_channel_type_keystr(domain
), NULL
);
529 ret
= secrets_delete(machine_sec_channel_type_keystr(domain
));
536 SIVAL(&last_change_time_store
, 0, last_change_time
);
537 ret
= secrets_store(machine_last_change_time_keystr(domain
),
538 &last_change_time_store
, sizeof(last_change_time
));
545 ret
= secrets_store_domain_sid(domain
, domain_sid
);
552 if (realm
&& salting_principal
) {
553 char *key
= talloc_asprintf(frame
, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL
, realm
);
558 ret
= secrets_store(key
, salting_principal
, strlen(salting_principal
)+1 );
566 /************************************************************************
567 Routine to fetch the previous plaintext machine account password for a realm
568 the password is assumed to be a null terminated ascii string.
569 ************************************************************************/
571 char *secrets_fetch_prev_machine_password(const char *domain
)
573 return (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
576 /************************************************************************
577 Routine to fetch the plaintext machine account password for a realm
578 the password is assumed to be a null terminated ascii string.
579 ************************************************************************/
581 char *secrets_fetch_machine_password(const char *domain
,
582 time_t *pass_last_set_time
,
583 enum netr_SchannelType
*channel
)
586 ret
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
588 if (pass_last_set_time
) {
590 uint32_t *last_set_time
;
591 last_set_time
= (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain
), &size
);
593 *pass_last_set_time
= IVAL(last_set_time
,0);
594 SAFE_FREE(last_set_time
);
596 *pass_last_set_time
= 0;
602 uint32_t *channel_type
;
603 channel_type
= (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain
), &size
);
605 *channel
= IVAL(channel_type
,0);
606 SAFE_FREE(channel_type
);
608 *channel
= get_default_sec_channel();