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)
79 ret = secrets_delete(protect_ids_keystr(domain));
81 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
86 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
88 #if _SAMBA_BUILD_ == 4
93 #if _SAMBA_BUILD_ == 4
94 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
96 if (strncmp(protect_ids, "TRUE", 4)) {
97 DEBUG(0, ("Refusing to store a Domain SID, "
98 "it has been marked as protected!\n"));
104 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
106 /* Force a re-query, in case we modified our domain */
108 reset_global_sam_sid();
112 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
114 struct dom_sid *dyn_sid;
117 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
122 if (size != sizeof(struct dom_sid)) {
132 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
134 #if _SAMBA_BUILD_ == 4
139 #if _SAMBA_BUILD_ == 4
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"));
150 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
151 if (!strupper_m(key)) {
154 return secrets_store(key, guid, sizeof(struct GUID));
157 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
159 struct GUID *dyn_guid;
162 struct GUID new_guid;
164 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
165 if (!strupper_m(key)) {
168 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
171 if (lp_server_role() == ROLE_DOMAIN_PDC) {
172 new_guid = GUID_random();
173 if (!secrets_store_domain_guid(domain, &new_guid))
175 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
177 if (dyn_guid == NULL) {
182 if (size != sizeof(struct GUID)) {
183 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
194 * Form a key for fetching the machine trust account sec channel type
196 * @param domain domain name
200 static const char *machine_sec_channel_type_keystr(const char *domain)
204 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
205 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
207 SMB_ASSERT(keystr != NULL);
212 * Form a key for fetching the machine trust account last change time
214 * @param domain domain name
218 static const char *machine_last_change_time_keystr(const char *domain)
222 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
223 SECRETS_MACHINE_LAST_CHANGE_TIME,
225 SMB_ASSERT(keystr != NULL);
231 * Form a key for fetching the machine previous trust account password
233 * @param domain domain name
237 static const char *machine_prev_password_keystr(const char *domain)
241 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
242 SECRETS_MACHINE_PASSWORD_PREV, domain);
243 SMB_ASSERT(keystr != NULL);
248 * Form a key for fetching the machine trust account password
250 * @param domain domain name
254 static const char *machine_password_keystr(const char *domain)
258 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
259 SECRETS_MACHINE_PASSWORD, domain);
260 SMB_ASSERT(keystr != NULL);
265 * Form a key for fetching the machine trust account password
267 * @param domain domain name
269 * @return stored password's key
271 static const char *trust_keystr(const char *domain)
275 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
276 SECRETS_MACHINE_ACCT_PASS, domain);
277 SMB_ASSERT(keystr != NULL);
281 /************************************************************************
282 Lock the trust password entry.
283 ************************************************************************/
285 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
287 struct db_context *db_ctx;
288 if (!secrets_init()) {
292 db_ctx = secrets_db_ctx();
294 return dbwrap_fetch_locked(
295 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
298 /************************************************************************
299 Routine to get the default secure channel type for trust accounts
300 ************************************************************************/
302 enum netr_SchannelType get_default_sec_channel(void)
304 if (lp_server_role() == ROLE_DOMAIN_BDC ||
305 lp_server_role() == ROLE_DOMAIN_PDC) {
308 return SEC_CHAN_WKSTA;
312 /************************************************************************
313 Routine to get the trust account password for a domain.
314 This only tries to get the legacy hashed version of the password.
315 The user of this function must have locked the trust password file using
316 the above secrets_lock_trust_account_password().
317 ************************************************************************/
319 bool secrets_fetch_trust_account_password_legacy(const char *domain,
321 time_t *pass_last_set_time,
322 enum netr_SchannelType *channel)
324 struct machine_acct_pass *pass;
327 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
328 trust_keystr(domain), &size))) {
329 DEBUG(5, ("secrets_fetch failed!\n"));
333 if (size != sizeof(*pass)) {
334 DEBUG(0, ("secrets were of incorrect size!\n"));
339 if (pass_last_set_time) {
340 *pass_last_set_time = pass->mod_time;
342 memcpy(ret_pwd, pass->hash, 16);
345 *channel = get_default_sec_channel();
352 /************************************************************************
353 Routine to get the trust account password for a domain.
354 The user of this function must have locked the trust password file using
355 the above secrets_lock_trust_account_password().
356 ************************************************************************/
358 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
359 time_t *pass_last_set_time,
360 enum netr_SchannelType *channel)
364 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
367 DEBUG(4,("Using cleartext machine password\n"));
368 E_md4hash(plaintext, ret_pwd);
369 SAFE_FREE(plaintext);
373 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
378 /************************************************************************
379 Routine to delete the old plaintext machine account password if any
380 ************************************************************************/
382 static bool secrets_delete_prev_machine_password(const char *domain)
384 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
385 if (oldpass == NULL) {
389 return secrets_delete(machine_prev_password_keystr(domain));
392 /************************************************************************
393 Routine to delete the plaintext machine account password, old password,
394 sec channel type and last change time from secrets database
395 ************************************************************************/
397 bool secrets_delete_machine_password_ex(const char *domain)
399 if (!secrets_delete_prev_machine_password(domain)) {
402 if (!secrets_delete(machine_password_keystr(domain))) {
405 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
408 return secrets_delete(machine_last_change_time_keystr(domain));
411 /************************************************************************
412 Routine to delete the domain sid
413 ************************************************************************/
415 bool secrets_delete_domain_sid(const char *domain)
417 return secrets_delete(domain_sid_keystr(domain));
420 /************************************************************************
421 Routine to store the previous machine password (by storing the current password
423 ************************************************************************/
425 static bool secrets_store_prev_machine_password(const char *domain)
430 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
431 if (oldpass == NULL) {
434 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
439 /************************************************************************
440 Routine to set the plaintext machine account password for a realm
441 the password is assumed to be a null terminated ascii string.
443 ************************************************************************/
445 bool secrets_store_machine_password(const char *pass, const char *domain,
446 enum netr_SchannelType sec_channel)
449 uint32_t last_change_time;
450 uint32_t sec_channel_type;
452 if (!secrets_store_prev_machine_password(domain)) {
456 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
460 SIVAL(&last_change_time, 0, time(NULL));
461 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
463 SIVAL(&sec_channel_type, 0, sec_channel);
464 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
470 /************************************************************************
471 Routine to fetch the previous plaintext machine account password for a realm
472 the password is assumed to be a null terminated ascii string.
473 ************************************************************************/
475 char *secrets_fetch_prev_machine_password(const char *domain)
477 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
480 /************************************************************************
481 Routine to fetch the plaintext machine account password for a realm
482 the password is assumed to be a null terminated ascii string.
483 ************************************************************************/
485 char *secrets_fetch_machine_password(const char *domain,
486 time_t *pass_last_set_time,
487 enum netr_SchannelType *channel)
490 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
492 if (pass_last_set_time) {
494 uint32_t *last_set_time;
495 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
497 *pass_last_set_time = IVAL(last_set_time,0);
498 SAFE_FREE(last_set_time);
500 *pass_last_set_time = 0;
506 uint32_t *channel_type;
507 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
509 *channel = IVAL(channel_type,0);
510 SAFE_FREE(channel_type);
512 *channel = get_default_sec_channel();