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);
152 return secrets_store(key, guid, sizeof(struct GUID));
155 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
157 struct GUID *dyn_guid;
160 struct GUID new_guid;
162 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
164 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
167 if (lp_server_role() == ROLE_DOMAIN_PDC) {
168 new_guid = GUID_random();
169 if (!secrets_store_domain_guid(domain, &new_guid))
171 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
173 if (dyn_guid == NULL) {
178 if (size != sizeof(struct GUID)) {
179 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
190 * Form a key for fetching the machine trust account sec channel type
192 * @param domain domain name
196 static const char *machine_sec_channel_type_keystr(const char *domain)
200 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
201 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
203 SMB_ASSERT(keystr != NULL);
208 * Form a key for fetching the machine trust account last change time
210 * @param domain domain name
214 static const char *machine_last_change_time_keystr(const char *domain)
218 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
219 SECRETS_MACHINE_LAST_CHANGE_TIME,
221 SMB_ASSERT(keystr != NULL);
227 * Form a key for fetching the machine previous trust account password
229 * @param domain domain name
233 static const char *machine_prev_password_keystr(const char *domain)
237 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
238 SECRETS_MACHINE_PASSWORD_PREV, domain);
239 SMB_ASSERT(keystr != NULL);
244 * Form a key for fetching the machine trust account password
246 * @param domain domain name
250 static const char *machine_password_keystr(const char *domain)
254 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
255 SECRETS_MACHINE_PASSWORD, domain);
256 SMB_ASSERT(keystr != NULL);
261 * Form a key for fetching the machine trust account password
263 * @param domain domain name
265 * @return stored password's key
267 static const char *trust_keystr(const char *domain)
271 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
272 SECRETS_MACHINE_ACCT_PASS, domain);
273 SMB_ASSERT(keystr != NULL);
277 /************************************************************************
278 Lock the trust password entry.
279 ************************************************************************/
281 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
283 struct db_context *db_ctx;
284 if (!secrets_init()) {
288 db_ctx = secrets_db_ctx();
290 return dbwrap_fetch_locked(
291 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
294 /************************************************************************
295 Routine to get the default secure channel type for trust accounts
296 ************************************************************************/
298 enum netr_SchannelType get_default_sec_channel(void)
300 if (lp_server_role() == ROLE_DOMAIN_BDC ||
301 lp_server_role() == ROLE_DOMAIN_PDC) {
304 return SEC_CHAN_WKSTA;
308 /************************************************************************
309 Routine to get the trust account password for a domain.
310 This only tries to get the legacy hashed version of the password.
311 The user of this function must have locked the trust password file using
312 the above secrets_lock_trust_account_password().
313 ************************************************************************/
315 bool secrets_fetch_trust_account_password_legacy(const char *domain,
317 time_t *pass_last_set_time,
318 enum netr_SchannelType *channel)
320 struct machine_acct_pass *pass;
323 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
324 trust_keystr(domain), &size))) {
325 DEBUG(5, ("secrets_fetch failed!\n"));
329 if (size != sizeof(*pass)) {
330 DEBUG(0, ("secrets were of incorrect size!\n"));
335 if (pass_last_set_time) {
336 *pass_last_set_time = pass->mod_time;
338 memcpy(ret_pwd, pass->hash, 16);
341 *channel = get_default_sec_channel();
348 /************************************************************************
349 Routine to get the trust account password for a domain.
350 The user of this function must have locked the trust password file using
351 the above secrets_lock_trust_account_password().
352 ************************************************************************/
354 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
355 time_t *pass_last_set_time,
356 enum netr_SchannelType *channel)
360 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
363 DEBUG(4,("Using cleartext machine password\n"));
364 E_md4hash(plaintext, ret_pwd);
365 SAFE_FREE(plaintext);
369 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
374 /************************************************************************
375 Routine to delete the old plaintext machine account password if any
376 ************************************************************************/
378 static bool secrets_delete_prev_machine_password(const char *domain)
380 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
381 if (oldpass == NULL) {
385 return secrets_delete(machine_prev_password_keystr(domain));
388 /************************************************************************
389 Routine to delete the plaintext machine account password, old password,
390 sec channel type and last change time from secrets database
391 ************************************************************************/
393 bool secrets_delete_machine_password_ex(const char *domain)
395 if (!secrets_delete_prev_machine_password(domain)) {
398 if (!secrets_delete(machine_password_keystr(domain))) {
401 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
404 return secrets_delete(machine_last_change_time_keystr(domain));
407 /************************************************************************
408 Routine to delete the domain sid
409 ************************************************************************/
411 bool secrets_delete_domain_sid(const char *domain)
413 return secrets_delete(domain_sid_keystr(domain));
416 /************************************************************************
417 Routine to store the previous machine password (by storing the current password
419 ************************************************************************/
421 static bool secrets_store_prev_machine_password(const char *domain)
426 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
427 if (oldpass == NULL) {
430 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
435 /************************************************************************
436 Routine to set the plaintext machine account password for a realm
437 the password is assumed to be a null terminated ascii string.
439 ************************************************************************/
441 bool secrets_store_machine_password(const char *pass, const char *domain,
442 enum netr_SchannelType sec_channel)
445 uint32 last_change_time;
446 uint32 sec_channel_type;
448 if (!secrets_store_prev_machine_password(domain)) {
452 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
456 SIVAL(&last_change_time, 0, time(NULL));
457 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
459 SIVAL(&sec_channel_type, 0, sec_channel);
460 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
466 /************************************************************************
467 Routine to fetch the previous plaintext machine account password for a realm
468 the password is assumed to be a null terminated ascii string.
469 ************************************************************************/
471 char *secrets_fetch_prev_machine_password(const char *domain)
473 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
476 /************************************************************************
477 Routine to fetch the plaintext machine account password for a realm
478 the password is assumed to be a null terminated ascii string.
479 ************************************************************************/
481 char *secrets_fetch_machine_password(const char *domain,
482 time_t *pass_last_set_time,
483 enum netr_SchannelType *channel)
486 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
488 if (pass_last_set_time) {
490 uint32 *last_set_time;
491 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
493 *pass_last_set_time = IVAL(last_set_time,0);
494 SAFE_FREE(last_set_time);
496 *pass_last_set_time = 0;
502 uint32 *channel_type;
503 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
505 *channel = IVAL(channel_type,0);
506 SAFE_FREE(channel_type);
508 *channel = get_default_sec_channel();