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
)
96 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
98 if (strncmp(protect_ids
, "TRUE", 4)) {
99 DEBUG(0, ("Refusing to store a Domain SID, "
100 "it has been marked as protected!\n"));
101 SAFE_FREE(protect_ids
);
105 SAFE_FREE(protect_ids
);
107 ret
= secrets_store(domain_sid_keystr(domain
), sid
, sizeof(struct dom_sid
));
109 /* Force a re-query, in case we modified our domain */
111 reset_global_sam_sid();
115 bool secrets_fetch_domain_sid(const char *domain
, struct dom_sid
*sid
)
117 struct dom_sid
*dyn_sid
;
120 dyn_sid
= (struct dom_sid
*)secrets_fetch(domain_sid_keystr(domain
), &size
);
125 if (size
!= sizeof(struct dom_sid
)) {
135 bool secrets_store_domain_guid(const char *domain
, struct GUID
*guid
)
140 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
142 if (strncmp(protect_ids
, "TRUE", 4)) {
143 DEBUG(0, ("Refusing to store a Domain SID, "
144 "it has been marked as protected!\n"));
145 SAFE_FREE(protect_ids
);
149 SAFE_FREE(protect_ids
);
151 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
152 if (!strupper_m(key
)) {
155 return secrets_store(key
, guid
, sizeof(struct GUID
));
158 bool secrets_fetch_domain_guid(const char *domain
, struct GUID
*guid
)
160 struct GUID
*dyn_guid
;
163 struct GUID new_guid
;
165 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
166 if (!strupper_m(key
)) {
169 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
172 if (lp_server_role() == ROLE_DOMAIN_PDC
) {
173 new_guid
= GUID_random();
174 if (!secrets_store_domain_guid(domain
, &new_guid
))
176 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
178 if (dyn_guid
== NULL
) {
183 if (size
!= sizeof(struct GUID
)) {
184 DEBUG(1,("UUID size %d is wrong!\n", (int)size
));
195 * Form a key for fetching the machine trust account sec channel type
197 * @param domain domain name
201 static const char *machine_sec_channel_type_keystr(const char *domain
)
205 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
206 SECRETS_MACHINE_SEC_CHANNEL_TYPE
,
208 SMB_ASSERT(keystr
!= NULL
);
213 * Form a key for fetching the machine trust account last change time
215 * @param domain domain name
219 static const char *machine_last_change_time_keystr(const char *domain
)
223 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
224 SECRETS_MACHINE_LAST_CHANGE_TIME
,
226 SMB_ASSERT(keystr
!= NULL
);
232 * Form a key for fetching the machine previous trust account password
234 * @param domain domain name
238 static const char *machine_prev_password_keystr(const char *domain
)
242 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
243 SECRETS_MACHINE_PASSWORD_PREV
, domain
);
244 SMB_ASSERT(keystr
!= NULL
);
249 * Form a key for fetching the machine trust account password
251 * @param domain domain name
255 static const char *machine_password_keystr(const char *domain
)
259 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
260 SECRETS_MACHINE_PASSWORD
, domain
);
261 SMB_ASSERT(keystr
!= NULL
);
266 * Form a key for fetching the machine trust account password
268 * @param domain domain name
270 * @return stored password's key
272 static const char *trust_keystr(const char *domain
)
276 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
277 SECRETS_MACHINE_ACCT_PASS
, domain
);
278 SMB_ASSERT(keystr
!= NULL
);
282 /************************************************************************
283 Lock the trust password entry.
284 ************************************************************************/
286 void *secrets_get_trust_account_lock(TALLOC_CTX
*mem_ctx
, const char *domain
)
288 struct db_context
*db_ctx
;
289 if (!secrets_init()) {
293 db_ctx
= secrets_db_ctx();
295 return dbwrap_fetch_locked(
296 db_ctx
, mem_ctx
, string_term_tdb_data(trust_keystr(domain
)));
299 /************************************************************************
300 Routine to get the default secure channel type for trust accounts
301 ************************************************************************/
303 enum netr_SchannelType
get_default_sec_channel(void)
305 if (lp_server_role() == ROLE_DOMAIN_BDC
||
306 lp_server_role() == ROLE_DOMAIN_PDC
||
307 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
310 return SEC_CHAN_WKSTA
;
314 /************************************************************************
315 Routine to get the trust account password for a domain.
316 This only tries to get the legacy hashed version of the password.
317 The user of this function must have locked the trust password file using
318 the above secrets_lock_trust_account_password().
319 ************************************************************************/
321 bool secrets_fetch_trust_account_password_legacy(const char *domain
,
323 time_t *pass_last_set_time
,
324 enum netr_SchannelType
*channel
)
326 struct machine_acct_pass
*pass
;
329 if (!(pass
= (struct machine_acct_pass
*)secrets_fetch(
330 trust_keystr(domain
), &size
))) {
331 DEBUG(5, ("secrets_fetch failed!\n"));
335 if (size
!= sizeof(*pass
)) {
336 DEBUG(0, ("secrets were of incorrect size!\n"));
341 if (pass_last_set_time
) {
342 *pass_last_set_time
= pass
->mod_time
;
344 memcpy(ret_pwd
, pass
->hash
, 16);
347 *channel
= get_default_sec_channel();
354 /************************************************************************
355 Routine to get the trust account password for a domain.
356 The user of this function must have locked the trust password file using
357 the above secrets_lock_trust_account_password().
358 ************************************************************************/
360 bool secrets_fetch_trust_account_password(const char *domain
, uint8_t ret_pwd
[16],
361 time_t *pass_last_set_time
,
362 enum netr_SchannelType
*channel
)
366 plaintext
= secrets_fetch_machine_password(domain
, pass_last_set_time
,
369 DEBUG(4,("Using cleartext machine password\n"));
370 E_md4hash(plaintext
, ret_pwd
);
371 SAFE_FREE(plaintext
);
375 return secrets_fetch_trust_account_password_legacy(domain
, ret_pwd
,
380 /************************************************************************
381 Routine to delete the old plaintext machine account password if any
382 ************************************************************************/
384 static bool secrets_delete_prev_machine_password(const char *domain
)
386 char *oldpass
= (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
387 if (oldpass
== NULL
) {
391 return secrets_delete(machine_prev_password_keystr(domain
));
394 /************************************************************************
395 Routine to delete the plaintext machine account password, old password,
396 sec channel type and last change time from secrets database
397 ************************************************************************/
399 bool secrets_delete_machine_password_ex(const char *domain
)
401 if (!secrets_delete_prev_machine_password(domain
)) {
404 if (!secrets_delete(machine_password_keystr(domain
))) {
407 if (!secrets_delete(machine_sec_channel_type_keystr(domain
))) {
410 return secrets_delete(machine_last_change_time_keystr(domain
));
413 /************************************************************************
414 Routine to delete the domain sid
415 ************************************************************************/
417 bool secrets_delete_domain_sid(const char *domain
)
419 return secrets_delete(domain_sid_keystr(domain
));
422 /************************************************************************
423 Routine to store the previous machine password (by storing the current password
425 ************************************************************************/
427 static bool secrets_store_prev_machine_password(const char *domain
)
432 oldpass
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
433 if (oldpass
== NULL
) {
436 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
441 /************************************************************************
442 Routine to set the plaintext machine account password for a realm
443 the password is assumed to be a null terminated ascii string.
445 ************************************************************************/
447 bool secrets_store_machine_password(const char *pass
, const char *domain
,
448 enum netr_SchannelType sec_channel
)
451 uint32_t last_change_time
;
452 uint32_t sec_channel_type
;
454 if (!secrets_store_prev_machine_password(domain
)) {
458 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
462 SIVAL(&last_change_time
, 0, time(NULL
));
463 ret
= secrets_store(machine_last_change_time_keystr(domain
), &last_change_time
, sizeof(last_change_time
));
465 SIVAL(&sec_channel_type
, 0, sec_channel
);
466 ret
= secrets_store(machine_sec_channel_type_keystr(domain
), &sec_channel_type
, sizeof(sec_channel_type
));
471 /************************************************************************
472 Set the machine trust account password, the old pw and last change
473 time, domain SID and salting principals based on values passed in
474 (added to supprt the secrets_tdb_sync module on secrets.ldb)
475 ************************************************************************/
477 bool secrets_store_machine_pw_sync(const char *pass
, const char *oldpass
, const char *domain
,
479 const char *salting_principal
, uint32_t supported_enc_types
,
480 const struct dom_sid
*domain_sid
, uint32_t last_change_time
,
484 uint8_t last_change_time_store
[4];
485 TALLOC_CTX
*frame
= talloc_stackframe();
489 secrets_delete_machine_password_ex(domain
);
490 secrets_delete_domain_sid(domain
);
495 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
502 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
504 value
= secrets_fetch_prev_machine_password(domain
);
507 ret
= secrets_delete_prev_machine_password(domain
);
515 /* We delete this and instead have the read code fall back to
516 * a default based on server role, as our caller can't specify
517 * this with any more certainty */
518 value
= secrets_fetch(machine_sec_channel_type_keystr(domain
), NULL
);
521 ret
= secrets_delete(machine_sec_channel_type_keystr(domain
));
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
);
544 if (realm
&& salting_principal
) {
545 char *key
= talloc_asprintf(frame
, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL
, realm
);
550 ret
= secrets_store(key
, salting_principal
, strlen(salting_principal
)+1 );
558 /************************************************************************
559 Routine to fetch the previous plaintext machine account password for a realm
560 the password is assumed to be a null terminated ascii string.
561 ************************************************************************/
563 char *secrets_fetch_prev_machine_password(const char *domain
)
565 return (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
568 /************************************************************************
569 Routine to fetch the plaintext machine account password for a realm
570 the password is assumed to be a null terminated ascii string.
571 ************************************************************************/
573 char *secrets_fetch_machine_password(const char *domain
,
574 time_t *pass_last_set_time
,
575 enum netr_SchannelType
*channel
)
578 ret
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
580 if (pass_last_set_time
) {
582 uint32_t *last_set_time
;
583 last_set_time
= (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain
), &size
);
585 *pass_last_set_time
= IVAL(last_set_time
,0);
586 SAFE_FREE(last_set_time
);
588 *pass_last_set_time
= 0;
594 uint32_t *channel_type
;
595 channel_type
= (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain
), &size
);
597 *channel
= IVAL(channel_type
,0);
598 SAFE_FREE(channel_type
);
600 *channel
= get_default_sec_channel();