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"));
157 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
158 if (!strupper_m(key
)) {
161 return secrets_store(key
, guid
, sizeof(struct GUID
));
164 bool secrets_fetch_domain_guid(const char *domain
, struct GUID
*guid
)
166 struct GUID
*dyn_guid
;
169 struct GUID new_guid
;
171 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
172 if (!strupper_m(key
)) {
175 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
178 if (lp_server_role() == ROLE_DOMAIN_PDC
) {
179 new_guid
= GUID_random();
180 if (!secrets_store_domain_guid(domain
, &new_guid
))
182 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
184 if (dyn_guid
== NULL
) {
189 if (size
!= sizeof(struct GUID
)) {
190 DEBUG(1,("UUID size %d is wrong!\n", (int)size
));
201 * Form a key for fetching the machine trust account sec channel type
203 * @param domain domain name
207 static const char *machine_sec_channel_type_keystr(const char *domain
)
211 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
212 SECRETS_MACHINE_SEC_CHANNEL_TYPE
,
214 SMB_ASSERT(keystr
!= NULL
);
219 * Form a key for fetching the machine trust account last change time
221 * @param domain domain name
225 static const char *machine_last_change_time_keystr(const char *domain
)
229 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
230 SECRETS_MACHINE_LAST_CHANGE_TIME
,
232 SMB_ASSERT(keystr
!= NULL
);
238 * Form a key for fetching the machine previous trust account password
240 * @param domain domain name
244 static const char *machine_prev_password_keystr(const char *domain
)
248 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
249 SECRETS_MACHINE_PASSWORD_PREV
, domain
);
250 SMB_ASSERT(keystr
!= NULL
);
255 * Form a key for fetching the machine trust account password
257 * @param domain domain name
261 static const char *machine_password_keystr(const char *domain
)
265 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
266 SECRETS_MACHINE_PASSWORD
, domain
);
267 SMB_ASSERT(keystr
!= NULL
);
272 * Form a key for fetching the machine trust account password
274 * @param domain domain name
276 * @return stored password's key
278 static const char *trust_keystr(const char *domain
)
282 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
283 SECRETS_MACHINE_ACCT_PASS
, domain
);
284 SMB_ASSERT(keystr
!= NULL
);
288 /************************************************************************
289 Lock the trust password entry.
290 ************************************************************************/
292 void *secrets_get_trust_account_lock(TALLOC_CTX
*mem_ctx
, const char *domain
)
294 struct db_context
*db_ctx
;
295 if (!secrets_init()) {
299 db_ctx
= secrets_db_ctx();
301 return dbwrap_fetch_locked(
302 db_ctx
, mem_ctx
, string_term_tdb_data(trust_keystr(domain
)));
305 /************************************************************************
306 Routine to get the default secure channel type for trust accounts
307 ************************************************************************/
309 enum netr_SchannelType
get_default_sec_channel(void)
311 if (lp_server_role() == ROLE_DOMAIN_BDC
||
312 lp_server_role() == ROLE_DOMAIN_PDC
||
313 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
316 return SEC_CHAN_WKSTA
;
320 /************************************************************************
321 Routine to get the trust account password for a domain.
322 This only tries to get the legacy hashed version of the password.
323 The user of this function must have locked the trust password file using
324 the above secrets_lock_trust_account_password().
325 ************************************************************************/
327 bool secrets_fetch_trust_account_password_legacy(const char *domain
,
329 time_t *pass_last_set_time
,
330 enum netr_SchannelType
*channel
)
332 struct machine_acct_pass
*pass
;
335 if (!(pass
= (struct machine_acct_pass
*)secrets_fetch(
336 trust_keystr(domain
), &size
))) {
337 DEBUG(5, ("secrets_fetch failed!\n"));
341 if (size
!= sizeof(*pass
)) {
342 DEBUG(0, ("secrets were of incorrect size!\n"));
347 if (pass_last_set_time
) {
348 *pass_last_set_time
= pass
->mod_time
;
350 memcpy(ret_pwd
, pass
->hash
, 16);
353 *channel
= get_default_sec_channel();
360 /************************************************************************
361 Routine to get the trust account password for a domain.
362 The user of this function must have locked the trust password file using
363 the above secrets_lock_trust_account_password().
364 ************************************************************************/
366 bool secrets_fetch_trust_account_password(const char *domain
, uint8_t ret_pwd
[16],
367 time_t *pass_last_set_time
,
368 enum netr_SchannelType
*channel
)
372 plaintext
= secrets_fetch_machine_password(domain
, pass_last_set_time
,
375 DEBUG(4,("Using cleartext machine password\n"));
376 E_md4hash(plaintext
, ret_pwd
);
377 SAFE_FREE(plaintext
);
381 return secrets_fetch_trust_account_password_legacy(domain
, ret_pwd
,
386 /************************************************************************
387 Routine to delete the old plaintext machine account password if any
388 ************************************************************************/
390 static bool secrets_delete_prev_machine_password(const char *domain
)
392 char *oldpass
= (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
393 if (oldpass
== NULL
) {
397 return secrets_delete(machine_prev_password_keystr(domain
));
400 /************************************************************************
401 Routine to delete the plaintext machine account password, old password,
402 sec channel type and last change time from secrets database
403 ************************************************************************/
405 bool secrets_delete_machine_password_ex(const char *domain
)
407 if (!secrets_delete_prev_machine_password(domain
)) {
410 if (!secrets_delete(machine_password_keystr(domain
))) {
413 if (!secrets_delete(machine_sec_channel_type_keystr(domain
))) {
416 return secrets_delete(machine_last_change_time_keystr(domain
));
419 /************************************************************************
420 Routine to delete the domain sid
421 ************************************************************************/
423 bool secrets_delete_domain_sid(const char *domain
)
425 return secrets_delete(domain_sid_keystr(domain
));
428 /************************************************************************
429 Routine to store the previous machine password (by storing the current password
431 ************************************************************************/
433 static bool secrets_store_prev_machine_password(const char *domain
)
438 oldpass
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
439 if (oldpass
== NULL
) {
442 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
447 /************************************************************************
448 Routine to set the plaintext machine account password for a realm
449 the password is assumed to be a null terminated ascii string.
451 ************************************************************************/
453 bool secrets_store_machine_password(const char *pass
, const char *domain
,
454 enum netr_SchannelType sec_channel
)
457 uint32_t last_change_time
;
458 uint32_t sec_channel_type
;
460 if (!secrets_store_prev_machine_password(domain
)) {
464 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
468 SIVAL(&last_change_time
, 0, time(NULL
));
469 ret
= secrets_store(machine_last_change_time_keystr(domain
), &last_change_time
, sizeof(last_change_time
));
471 SIVAL(&sec_channel_type
, 0, sec_channel
);
472 ret
= secrets_store(machine_sec_channel_type_keystr(domain
), &sec_channel_type
, sizeof(sec_channel_type
));
477 /************************************************************************
478 Set the machine trust account password, the old pw and last change
479 time, domain SID and salting principals based on values passed in
480 (added to supprt the secrets_tdb_sync module on secrets.ldb)
481 ************************************************************************/
483 bool secrets_store_machine_pw_sync(const char *pass
, const char *oldpass
, const char *domain
,
485 const char *salting_principal
, uint32_t supported_enc_types
,
486 const struct dom_sid
*domain_sid
, uint32_t last_change_time
,
490 uint8_t last_change_time_store
[4];
491 TALLOC_CTX
*frame
= talloc_stackframe();
495 secrets_delete_machine_password_ex(domain
);
496 secrets_delete_domain_sid(domain
);
501 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
508 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
510 value
= secrets_fetch_prev_machine_password(domain
);
513 ret
= secrets_delete_prev_machine_password(domain
);
521 /* We delete this and instead have the read code fall back to
522 * a default based on server role, as our caller can't specify
523 * this with any more certainty */
524 value
= secrets_fetch(machine_sec_channel_type_keystr(domain
), NULL
);
527 ret
= secrets_delete(machine_sec_channel_type_keystr(domain
));
534 SIVAL(&last_change_time_store
, 0, last_change_time
);
535 ret
= secrets_store(machine_last_change_time_keystr(domain
),
536 &last_change_time_store
, sizeof(last_change_time
));
543 ret
= secrets_store_domain_sid(domain
, domain_sid
);
550 if (realm
&& salting_principal
) {
551 char *key
= talloc_asprintf(frame
, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL
, realm
);
556 ret
= secrets_store(key
, salting_principal
, strlen(salting_principal
)+1 );
564 /************************************************************************
565 Routine to fetch the previous plaintext machine account password for a realm
566 the password is assumed to be a null terminated ascii string.
567 ************************************************************************/
569 char *secrets_fetch_prev_machine_password(const char *domain
)
571 return (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
574 /************************************************************************
575 Routine to fetch the plaintext machine account password for a realm
576 the password is assumed to be a null terminated ascii string.
577 ************************************************************************/
579 char *secrets_fetch_machine_password(const char *domain
,
580 time_t *pass_last_set_time
,
581 enum netr_SchannelType
*channel
)
584 ret
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
586 if (pass_last_set_time
) {
588 uint32_t *last_set_time
;
589 last_set_time
= (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain
), &size
);
591 *pass_last_set_time
= IVAL(last_set_time
,0);
592 SAFE_FREE(last_set_time
);
594 *pass_last_set_time
= 0;
600 uint32_t *channel_type
;
601 channel_type
= (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain
), &size
);
603 *channel
= IVAL(channel_type
,0);
604 SAFE_FREE(channel_type
);
606 *channel
= get_default_sec_channel();