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"
30 #include "../librpc/ndr/libndr.h"
33 #define DBGC_CLASS DBGC_PASSDB
35 /* Urrrg. global.... */
36 bool global_machine_password_needs_changing;
39 * Form a key for fetching the domain sid
41 * @param domain domain name
45 static const char *domain_sid_keystr(const char *domain)
49 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
50 SECRETS_DOMAIN_SID, domain);
51 SMB_ASSERT(keystr != NULL);
55 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
59 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
61 /* Force a re-query, in case we modified our domain */
63 reset_global_sam_sid();
67 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
69 struct dom_sid *dyn_sid;
72 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
77 if (size != sizeof(struct dom_sid)) {
87 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
91 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
93 return secrets_store(key, guid, sizeof(struct GUID));
96 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
98 struct GUID *dyn_guid;
101 struct GUID new_guid;
103 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
105 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
108 if (lp_server_role() == ROLE_DOMAIN_PDC) {
109 new_guid = GUID_random();
110 if (!secrets_store_domain_guid(domain, &new_guid))
112 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
114 if (dyn_guid == NULL) {
119 if (size != sizeof(struct GUID)) {
120 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
131 * Form a key for fetching the machine trust account sec channel type
133 * @param domain domain name
137 static const char *machine_sec_channel_type_keystr(const char *domain)
141 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
142 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
144 SMB_ASSERT(keystr != NULL);
149 * Form a key for fetching the machine trust account last change time
151 * @param domain domain name
155 static const char *machine_last_change_time_keystr(const char *domain)
159 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
160 SECRETS_MACHINE_LAST_CHANGE_TIME,
162 SMB_ASSERT(keystr != NULL);
168 * Form a key for fetching the machine previous trust account password
170 * @param domain domain name
174 static const char *machine_prev_password_keystr(const char *domain)
178 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
179 SECRETS_MACHINE_PASSWORD_PREV, domain);
180 SMB_ASSERT(keystr != NULL);
185 * Form a key for fetching the machine trust account password
187 * @param domain domain name
191 static const char *machine_password_keystr(const char *domain)
195 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
196 SECRETS_MACHINE_PASSWORD, domain);
197 SMB_ASSERT(keystr != NULL);
202 * Form a key for fetching the machine trust account password
204 * @param domain domain name
206 * @return stored password's key
208 static const char *trust_keystr(const char *domain)
212 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
213 SECRETS_MACHINE_ACCT_PASS, domain);
214 SMB_ASSERT(keystr != NULL);
218 /************************************************************************
219 Lock the trust password entry.
220 ************************************************************************/
222 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
224 struct db_context *db_ctx;
225 if (!secrets_init()) {
229 db_ctx = secrets_db_ctx();
231 return db_ctx->fetch_locked(
232 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
235 /************************************************************************
236 Routine to get the default secure channel type for trust accounts
237 ************************************************************************/
239 enum netr_SchannelType get_default_sec_channel(void)
241 if (lp_server_role() == ROLE_DOMAIN_BDC ||
242 lp_server_role() == ROLE_DOMAIN_PDC) {
245 return SEC_CHAN_WKSTA;
249 /************************************************************************
250 Routine to get the trust account password for a domain.
251 This only tries to get the legacy hashed version of the password.
252 The user of this function must have locked the trust password file using
253 the above secrets_lock_trust_account_password().
254 ************************************************************************/
256 bool secrets_fetch_trust_account_password_legacy(const char *domain,
258 time_t *pass_last_set_time,
259 enum netr_SchannelType *channel)
261 struct machine_acct_pass *pass;
264 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
265 trust_keystr(domain), &size))) {
266 DEBUG(5, ("secrets_fetch failed!\n"));
270 if (size != sizeof(*pass)) {
271 DEBUG(0, ("secrets were of incorrect size!\n"));
276 if (pass_last_set_time) {
277 *pass_last_set_time = pass->mod_time;
279 memcpy(ret_pwd, pass->hash, 16);
282 *channel = get_default_sec_channel();
285 /* Test if machine password has expired and needs to be changed */
286 if (lp_machine_password_timeout()) {
287 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
288 (time_t)lp_machine_password_timeout())) {
289 global_machine_password_needs_changing = True;
297 /************************************************************************
298 Routine to get the trust account password for a domain.
299 The user of this function must have locked the trust password file using
300 the above secrets_lock_trust_account_password().
301 ************************************************************************/
303 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
304 time_t *pass_last_set_time,
305 enum netr_SchannelType *channel)
309 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
312 DEBUG(4,("Using cleartext machine password\n"));
313 E_md4hash(plaintext, ret_pwd);
314 SAFE_FREE(plaintext);
318 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
323 /************************************************************************
324 Routine to delete the old plaintext machine account password if any
325 ************************************************************************/
327 static bool secrets_delete_prev_machine_password(const char *domain)
329 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
330 if (oldpass == NULL) {
334 return secrets_delete(machine_prev_password_keystr(domain));
337 /************************************************************************
338 Routine to delete the plaintext machine account password and old
340 ************************************************************************/
342 bool secrets_delete_machine_password(const char *domain)
344 if (!secrets_delete_prev_machine_password(domain)) {
347 return secrets_delete(machine_password_keystr(domain));
350 /************************************************************************
351 Routine to delete the plaintext machine account password, old password,
352 sec channel type and last change time from secrets database
353 ************************************************************************/
355 bool secrets_delete_machine_password_ex(const char *domain)
357 if (!secrets_delete_prev_machine_password(domain)) {
360 if (!secrets_delete(machine_password_keystr(domain))) {
363 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
366 return secrets_delete(machine_last_change_time_keystr(domain));
369 /************************************************************************
370 Routine to delete the domain sid
371 ************************************************************************/
373 bool secrets_delete_domain_sid(const char *domain)
375 return secrets_delete(domain_sid_keystr(domain));
378 /************************************************************************
379 Routine to store the previous machine password (by storing the current password
381 ************************************************************************/
383 static bool secrets_store_prev_machine_password(const char *domain)
388 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
389 if (oldpass == NULL) {
392 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
397 /************************************************************************
398 Routine to set the plaintext machine account password for a realm
399 the password is assumed to be a null terminated ascii string.
401 ************************************************************************/
403 bool secrets_store_machine_password(const char *pass, const char *domain,
404 enum netr_SchannelType sec_channel)
407 uint32 last_change_time;
408 uint32 sec_channel_type;
410 if (!secrets_store_prev_machine_password(domain)) {
414 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
418 SIVAL(&last_change_time, 0, time(NULL));
419 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
421 SIVAL(&sec_channel_type, 0, sec_channel);
422 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
428 /************************************************************************
429 Routine to fetch the previous plaintext machine account password for a realm
430 the password is assumed to be a null terminated ascii string.
431 ************************************************************************/
433 char *secrets_fetch_prev_machine_password(const char *domain)
435 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
438 /************************************************************************
439 Routine to fetch the plaintext machine account password for a realm
440 the password is assumed to be a null terminated ascii string.
441 ************************************************************************/
443 char *secrets_fetch_machine_password(const char *domain,
444 time_t *pass_last_set_time,
445 enum netr_SchannelType *channel)
448 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
450 if (pass_last_set_time) {
452 uint32 *last_set_time;
453 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
455 *pass_last_set_time = IVAL(last_set_time,0);
456 SAFE_FREE(last_set_time);
458 *pass_last_set_time = 0;
464 uint32 *channel_type;
465 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
467 *channel = IVAL(channel_type,0);
468 SAFE_FREE(channel_type);
470 *channel = get_default_sec_channel();