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"
32 #include "libcli/security/security.h"
35 #define DBGC_CLASS DBGC_PASSDB
38 * Form a key for fetching the domain sid
40 * @param domain domain name
44 static const char *domain_sid_keystr(const char *domain
)
48 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
49 SECRETS_DOMAIN_SID
, domain
);
50 SMB_ASSERT(keystr
!= NULL
);
54 static const char *protect_ids_keystr(const char *domain
)
58 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
59 SECRETS_PROTECT_IDS
, domain
);
60 SMB_ASSERT(keystr
!= NULL
);
64 /* N O T E: never use this outside of passdb modules that store the SID on their own */
65 bool secrets_mark_domain_protected(const char *domain
)
69 ret
= secrets_store(protect_ids_keystr(domain
), "TRUE", 5);
71 DEBUG(0, ("Failed to protect the Domain IDs\n"));
76 bool secrets_clear_domain_protection(const char *domain
)
79 void *protection
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
82 SAFE_FREE(protection
);
83 ret
= secrets_delete(protect_ids_keystr(domain
));
85 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
92 bool secrets_store_domain_sid(const char *domain
, const struct dom_sid
*sid
)
97 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
99 if (strncmp(protect_ids
, "TRUE", 4)) {
100 DEBUG(0, ("Refusing to store a Domain SID, "
101 "it has been marked as protected!\n"));
102 SAFE_FREE(protect_ids
);
106 SAFE_FREE(protect_ids
);
108 ret
= secrets_store(domain_sid_keystr(domain
), sid
, sizeof(struct dom_sid
));
110 /* Force a re-query, in the case where we modified our domain */
112 if (dom_sid_equal(get_global_sam_sid(), sid
) == false) {
113 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
)
144 protect_ids
= secrets_fetch(protect_ids_keystr(domain
), NULL
);
146 if (strncmp(protect_ids
, "TRUE", 4)) {
147 DEBUG(0, ("Refusing to store a Domain SID, "
148 "it has been marked as protected!\n"));
149 SAFE_FREE(protect_ids
);
153 SAFE_FREE(protect_ids
);
155 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
156 if (!strupper_m(key
)) {
159 return secrets_store(key
, guid
, sizeof(struct GUID
));
162 bool secrets_fetch_domain_guid(const char *domain
, struct GUID
*guid
)
164 struct GUID
*dyn_guid
;
167 struct GUID new_guid
;
169 slprintf(key
, sizeof(key
)-1, "%s/%s", SECRETS_DOMAIN_GUID
, domain
);
170 if (!strupper_m(key
)) {
173 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
176 if (lp_server_role() == ROLE_DOMAIN_PDC
) {
177 new_guid
= GUID_random();
178 if (!secrets_store_domain_guid(domain
, &new_guid
))
180 dyn_guid
= (struct GUID
*)secrets_fetch(key
, &size
);
182 if (dyn_guid
== NULL
) {
187 if (size
!= sizeof(struct GUID
)) {
188 DEBUG(1,("UUID size %d is wrong!\n", (int)size
));
199 * Form a key for fetching the machine trust account sec channel type
201 * @param domain domain name
205 static const char *machine_sec_channel_type_keystr(const char *domain
)
209 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
210 SECRETS_MACHINE_SEC_CHANNEL_TYPE
,
212 SMB_ASSERT(keystr
!= NULL
);
217 * Form a key for fetching the machine trust account last change time
219 * @param domain domain name
223 static const char *machine_last_change_time_keystr(const char *domain
)
227 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
228 SECRETS_MACHINE_LAST_CHANGE_TIME
,
230 SMB_ASSERT(keystr
!= NULL
);
236 * Form a key for fetching the machine previous trust account password
238 * @param domain domain name
242 static const char *machine_prev_password_keystr(const char *domain
)
246 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
247 SECRETS_MACHINE_PASSWORD_PREV
, domain
);
248 SMB_ASSERT(keystr
!= NULL
);
253 * Form a key for fetching the machine trust account password
255 * @param domain domain name
259 static const char *machine_password_keystr(const char *domain
)
263 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
264 SECRETS_MACHINE_PASSWORD
, domain
);
265 SMB_ASSERT(keystr
!= NULL
);
270 * Form a key for fetching the machine trust account password
272 * @param domain domain name
274 * @return stored password's key
276 static const char *trust_keystr(const char *domain
)
280 keystr
= talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
281 SECRETS_MACHINE_ACCT_PASS
, domain
);
282 SMB_ASSERT(keystr
!= NULL
);
286 /************************************************************************
287 Routine to get the default secure channel type for trust accounts
288 ************************************************************************/
290 enum netr_SchannelType
get_default_sec_channel(void)
292 if (lp_server_role() == ROLE_DOMAIN_BDC
||
293 lp_server_role() == ROLE_DOMAIN_PDC
||
294 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
297 return SEC_CHAN_WKSTA
;
301 /************************************************************************
302 Routine to get the trust account password for a domain.
303 This only tries to get the legacy hashed version of the password.
304 The user of this function must have locked the trust password file using
305 the above secrets_lock_trust_account_password().
306 ************************************************************************/
308 bool secrets_fetch_trust_account_password_legacy(const char *domain
,
310 time_t *pass_last_set_time
,
311 enum netr_SchannelType
*channel
)
313 struct machine_acct_pass
*pass
;
316 if (!(pass
= (struct machine_acct_pass
*)secrets_fetch(
317 trust_keystr(domain
), &size
))) {
318 DEBUG(5, ("secrets_fetch failed!\n"));
322 if (size
!= sizeof(*pass
)) {
323 DEBUG(0, ("secrets were of incorrect size!\n"));
328 if (pass_last_set_time
) {
329 *pass_last_set_time
= pass
->mod_time
;
331 memcpy(ret_pwd
, pass
->hash
, 16);
334 *channel
= get_default_sec_channel();
341 /************************************************************************
342 Routine to get the trust account password for a domain.
343 The user of this function must have locked the trust password file using
344 the above secrets_lock_trust_account_password().
345 ************************************************************************/
347 bool secrets_fetch_trust_account_password(const char *domain
, uint8_t ret_pwd
[16],
348 time_t *pass_last_set_time
,
349 enum netr_SchannelType
*channel
)
353 plaintext
= secrets_fetch_machine_password(domain
, pass_last_set_time
,
356 DEBUG(4,("Using cleartext machine password\n"));
357 E_md4hash(plaintext
, ret_pwd
);
358 SAFE_FREE(plaintext
);
362 return secrets_fetch_trust_account_password_legacy(domain
, ret_pwd
,
367 /************************************************************************
368 Routine to delete the old plaintext machine account password if any
369 ************************************************************************/
371 static bool secrets_delete_prev_machine_password(const char *domain
)
373 char *oldpass
= (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
374 if (oldpass
== NULL
) {
378 return secrets_delete(machine_prev_password_keystr(domain
));
381 /************************************************************************
382 Routine to delete the plaintext machine account password, old password,
383 sec channel type and last change time from secrets database
384 ************************************************************************/
386 bool secrets_delete_machine_password_ex(const char *domain
)
388 if (!secrets_delete_prev_machine_password(domain
)) {
391 if (!secrets_delete(machine_password_keystr(domain
))) {
394 if (!secrets_delete(machine_sec_channel_type_keystr(domain
))) {
397 return secrets_delete(machine_last_change_time_keystr(domain
));
400 /************************************************************************
401 Routine to delete the domain sid
402 ************************************************************************/
404 bool secrets_delete_domain_sid(const char *domain
)
406 return secrets_delete(domain_sid_keystr(domain
));
409 /************************************************************************
410 Routine to store the previous machine password (by storing the current password
412 ************************************************************************/
414 static bool secrets_store_prev_machine_password(const char *domain
)
419 oldpass
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
420 if (oldpass
== NULL
) {
423 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
428 /************************************************************************
429 Routine to set the plaintext machine account password for a realm
430 the password is assumed to be a null terminated ascii string.
432 ************************************************************************/
434 bool secrets_store_machine_password(const char *pass
, const char *domain
,
435 enum netr_SchannelType sec_channel
)
438 uint32_t last_change_time
;
439 uint32_t sec_channel_type
;
441 if (!secrets_store_prev_machine_password(domain
)) {
445 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
449 SIVAL(&last_change_time
, 0, time(NULL
));
450 ret
= secrets_store(machine_last_change_time_keystr(domain
), &last_change_time
, sizeof(last_change_time
));
452 SIVAL(&sec_channel_type
, 0, sec_channel
);
453 ret
= secrets_store(machine_sec_channel_type_keystr(domain
), &sec_channel_type
, sizeof(sec_channel_type
));
458 /************************************************************************
459 Set the machine trust account password, the old pw and last change
460 time, domain SID and salting principals based on values passed in
461 (added to supprt the secrets_tdb_sync module on secrets.ldb)
462 ************************************************************************/
464 bool secrets_store_machine_pw_sync(const char *pass
, const char *oldpass
, const char *domain
,
466 const char *salting_principal
, uint32_t supported_enc_types
,
467 const struct dom_sid
*domain_sid
, uint32_t last_change_time
,
468 uint32_t secure_channel_type
,
472 uint8_t last_change_time_store
[4];
473 TALLOC_CTX
*frame
= talloc_stackframe();
474 uint8_t sec_channel_bytes
[4];
478 secrets_delete_machine_password_ex(domain
);
479 secrets_delete_domain_sid(domain
);
484 ret
= secrets_store(machine_password_keystr(domain
), pass
, strlen(pass
)+1);
491 ret
= secrets_store(machine_prev_password_keystr(domain
), oldpass
, strlen(oldpass
)+1);
493 value
= secrets_fetch_prev_machine_password(domain
);
496 ret
= secrets_delete_prev_machine_password(domain
);
504 if (secure_channel_type
== 0) {
505 /* We delete this and instead have the read code fall back to
506 * a default based on server role, as our caller can't specify
507 * this with any more certainty */
508 value
= secrets_fetch(machine_sec_channel_type_keystr(domain
), NULL
);
511 ret
= secrets_delete(machine_sec_channel_type_keystr(domain
));
518 SIVAL(&sec_channel_bytes
, 0, secure_channel_type
);
519 ret
= secrets_store(machine_sec_channel_type_keystr(domain
),
520 &sec_channel_bytes
, sizeof(sec_channel_bytes
));
527 SIVAL(&last_change_time_store
, 0, last_change_time
);
528 ret
= secrets_store(machine_last_change_time_keystr(domain
),
529 &last_change_time_store
, sizeof(last_change_time
));
536 ret
= secrets_store_domain_sid(domain
, domain_sid
);
543 if (realm
&& salting_principal
) {
544 char *key
= talloc_asprintf(frame
, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL
, realm
);
549 ret
= secrets_store(key
, salting_principal
, strlen(salting_principal
)+1 );
557 /************************************************************************
558 Routine to fetch the previous plaintext machine account password for a realm
559 the password is assumed to be a null terminated ascii string.
560 ************************************************************************/
562 char *secrets_fetch_prev_machine_password(const char *domain
)
564 return (char *)secrets_fetch(machine_prev_password_keystr(domain
), NULL
);
567 /************************************************************************
568 Routine to fetch the plaintext machine account password for a realm
569 the password is assumed to be a null terminated ascii string.
570 ************************************************************************/
572 char *secrets_fetch_machine_password(const char *domain
,
573 time_t *pass_last_set_time
,
574 enum netr_SchannelType
*channel
)
577 ret
= (char *)secrets_fetch(machine_password_keystr(domain
), NULL
);
579 if (pass_last_set_time
) {
581 uint32_t *last_set_time
;
582 last_set_time
= (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain
), &size
);
584 *pass_last_set_time
= IVAL(last_set_time
,0);
585 SAFE_FREE(last_set_time
);
587 *pass_last_set_time
= 0;
593 uint32_t *channel_type
;
594 channel_type
= (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain
), &size
);
596 *channel
= IVAL(channel_type
,0);
597 SAFE_FREE(channel_type
);
599 *channel
= get_default_sec_channel();