param: allow special functions to be common across the two loadparms
[Samba.git] / source3 / passdb / machine_account_secrets.c
blob5758efe819c548e52ddc6d6d5817d905b8ce07d0
1 /*
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 */
25 #include "includes.h"
26 #include "passdb.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "secrets.h"
29 #include "dbwrap/dbwrap.h"
30 #include "../librpc/ndr/libndr.h"
31 #include "util_tdb.h"
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_PASSDB
36 /**
37 * Form a key for fetching the domain sid
39 * @param domain domain name
41 * @return keystring
42 **/
43 static const char *domain_sid_keystr(const char *domain)
45 char *keystr;
47 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
48 SECRETS_DOMAIN_SID, domain);
49 SMB_ASSERT(keystr != NULL);
50 return keystr;
53 static const char *protect_ids_keystr(const char *domain)
55 char *keystr;
57 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
58 SECRETS_PROTECT_IDS, domain);
59 SMB_ASSERT(keystr != NULL);
60 return keystr;
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)
66 bool ret;
68 ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
69 if (!ret) {
70 DEBUG(0, ("Failed to protect the Domain IDs\n"));
72 return ret;
75 bool secrets_clear_domain_protection(const char *domain)
77 bool ret;
78 void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
80 if (protection) {
81 SAFE_FREE(protection);
82 ret = secrets_delete(protect_ids_keystr(domain));
83 if (!ret) {
84 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
86 return ret;
88 return true;
91 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
93 char *protect_ids;
94 bool ret;
96 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
97 if (protect_ids) {
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);
102 return false;
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 */
110 if (ret)
111 reset_global_sam_sid();
112 return ret;
115 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
117 struct dom_sid *dyn_sid;
118 size_t size = 0;
120 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
122 if (dyn_sid == NULL)
123 return False;
125 if (size != sizeof(struct dom_sid)) {
126 SAFE_FREE(dyn_sid);
127 return False;
130 *sid = *dyn_sid;
131 SAFE_FREE(dyn_sid);
132 return True;
135 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
137 char *protect_ids;
138 fstring key;
140 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
141 if (protect_ids) {
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);
146 return false;
149 SAFE_FREE(protect_ids);
151 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
152 if (!strupper_m(key)) {
153 return false;
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;
161 fstring key;
162 size_t size = 0;
163 struct GUID new_guid;
165 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
166 if (!strupper_m(key)) {
167 return false;
169 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
171 if (!dyn_guid) {
172 if (lp_server_role() == ROLE_DOMAIN_PDC) {
173 new_guid = GUID_random();
174 if (!secrets_store_domain_guid(domain, &new_guid))
175 return False;
176 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
178 if (dyn_guid == NULL) {
179 return False;
183 if (size != sizeof(struct GUID)) {
184 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
185 SAFE_FREE(dyn_guid);
186 return False;
189 *guid = *dyn_guid;
190 SAFE_FREE(dyn_guid);
191 return True;
195 * Form a key for fetching the machine trust account sec channel type
197 * @param domain domain name
199 * @return keystring
201 static const char *machine_sec_channel_type_keystr(const char *domain)
203 char *keystr;
205 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
206 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
207 domain);
208 SMB_ASSERT(keystr != NULL);
209 return keystr;
213 * Form a key for fetching the machine trust account last change time
215 * @param domain domain name
217 * @return keystring
219 static const char *machine_last_change_time_keystr(const char *domain)
221 char *keystr;
223 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
224 SECRETS_MACHINE_LAST_CHANGE_TIME,
225 domain);
226 SMB_ASSERT(keystr != NULL);
227 return keystr;
232 * Form a key for fetching the machine previous trust account password
234 * @param domain domain name
236 * @return keystring
238 static const char *machine_prev_password_keystr(const char *domain)
240 char *keystr;
242 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
243 SECRETS_MACHINE_PASSWORD_PREV, domain);
244 SMB_ASSERT(keystr != NULL);
245 return keystr;
249 * Form a key for fetching the machine trust account password
251 * @param domain domain name
253 * @return keystring
255 static const char *machine_password_keystr(const char *domain)
257 char *keystr;
259 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
260 SECRETS_MACHINE_PASSWORD, domain);
261 SMB_ASSERT(keystr != NULL);
262 return keystr;
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)
274 char *keystr;
276 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
277 SECRETS_MACHINE_ACCT_PASS, domain);
278 SMB_ASSERT(keystr != NULL);
279 return keystr;
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()) {
290 return NULL;
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) {
308 return SEC_CHAN_BDC;
309 } else {
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,
322 uint8_t ret_pwd[16],
323 time_t *pass_last_set_time,
324 enum netr_SchannelType *channel)
326 struct machine_acct_pass *pass;
327 size_t size = 0;
329 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
330 trust_keystr(domain), &size))) {
331 DEBUG(5, ("secrets_fetch failed!\n"));
332 return False;
335 if (size != sizeof(*pass)) {
336 DEBUG(0, ("secrets were of incorrect size!\n"));
337 SAFE_FREE(pass);
338 return False;
341 if (pass_last_set_time) {
342 *pass_last_set_time = pass->mod_time;
344 memcpy(ret_pwd, pass->hash, 16);
346 if (channel) {
347 *channel = get_default_sec_channel();
350 SAFE_FREE(pass);
351 return True;
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)
364 char *plaintext;
366 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
367 channel);
368 if (plaintext) {
369 DEBUG(4,("Using cleartext machine password\n"));
370 E_md4hash(plaintext, ret_pwd);
371 SAFE_FREE(plaintext);
372 return True;
375 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
376 pass_last_set_time,
377 channel);
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) {
388 return true;
390 SAFE_FREE(oldpass);
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)) {
402 return false;
404 if (!secrets_delete(machine_password_keystr(domain))) {
405 return false;
407 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
408 return false;
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
424 as the old)
425 ************************************************************************/
427 static bool secrets_store_prev_machine_password(const char *domain)
429 char *oldpass;
430 bool ret;
432 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
433 if (oldpass == NULL) {
434 return true;
436 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
437 SAFE_FREE(oldpass);
438 return ret;
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.
444 Before storing
445 ************************************************************************/
447 bool secrets_store_machine_password(const char *pass, const char *domain,
448 enum netr_SchannelType sec_channel)
450 bool ret;
451 uint32_t last_change_time;
452 uint32_t sec_channel_type;
454 if (!secrets_store_prev_machine_password(domain)) {
455 return false;
458 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
459 if (!ret)
460 return ret;
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));
468 return ret;
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,
478 const char *realm,
479 const char *salting_principal, uint32_t supported_enc_types,
480 const struct dom_sid *domain_sid, uint32_t last_change_time,
481 bool delete_join)
483 bool ret;
484 uint8_t last_change_time_store[4];
485 TALLOC_CTX *frame = talloc_stackframe();
486 void *value;
488 if (delete_join) {
489 secrets_delete_machine_password_ex(domain);
490 secrets_delete_domain_sid(domain);
491 TALLOC_FREE(frame);
492 return true;
495 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
496 if (!ret) {
497 TALLOC_FREE(frame);
498 return ret;
501 if (oldpass) {
502 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
503 } else {
504 value = secrets_fetch_prev_machine_password(domain);
505 if (value) {
506 SAFE_FREE(value);
507 ret = secrets_delete_prev_machine_password(domain);
510 if (!ret) {
511 TALLOC_FREE(frame);
512 return ret;
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);
519 if (value) {
520 SAFE_FREE(value);
521 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
522 if (!ret) {
523 TALLOC_FREE(frame);
524 return ret;
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));
532 if (!ret) {
533 TALLOC_FREE(frame);
534 return ret;
537 ret = secrets_store_domain_sid(domain, domain_sid);
539 if (!ret) {
540 TALLOC_FREE(frame);
541 return ret;
544 if (realm && salting_principal) {
545 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
546 if (!key) {
547 TALLOC_FREE(frame);
548 return false;
550 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
553 TALLOC_FREE(frame);
554 return ret;
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)
577 char *ret;
578 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
580 if (pass_last_set_time) {
581 size_t size;
582 uint32_t *last_set_time;
583 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
584 if (last_set_time) {
585 *pass_last_set_time = IVAL(last_set_time,0);
586 SAFE_FREE(last_set_time);
587 } else {
588 *pass_last_set_time = 0;
592 if (channel) {
593 size_t size;
594 uint32_t *channel_type;
595 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
596 if (channel_type) {
597 *channel = IVAL(channel_type,0);
598 SAFE_FREE(channel_type);
599 } else {
600 *channel = get_default_sec_channel();
604 return ret;