Free protect_ids in secret_store_domain_sid() as the caller of fetch_secrets() must...
[Samba/gebeck_regimport.git] / source3 / passdb / machine_account_secrets.c
blob70d7106176f4950a0dfa2982152745f5199d3219
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 #if _SAMBA_BUILD_ == 4
94 char *protect_ids;
95 #endif
96 bool ret;
98 #if _SAMBA_BUILD_ == 4
99 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
100 if (protect_ids) {
101 if (strncmp(protect_ids, "TRUE", 4)) {
102 DEBUG(0, ("Refusing to store a Domain SID, "
103 "it has been marked as protected!\n"));
104 SAFE_FREE(protect_ids);
105 return false;
108 SAFE_FREE(protect_ids);
109 #endif
111 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
113 /* Force a re-query, in case we modified our domain */
114 if (ret)
115 reset_global_sam_sid();
116 return ret;
119 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
121 struct dom_sid *dyn_sid;
122 size_t size = 0;
124 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
126 if (dyn_sid == NULL)
127 return False;
129 if (size != sizeof(struct dom_sid)) {
130 SAFE_FREE(dyn_sid);
131 return False;
134 *sid = *dyn_sid;
135 SAFE_FREE(dyn_sid);
136 return True;
139 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
141 #if _SAMBA_BUILD_ == 4
142 char *protect_ids;
143 #endif
144 fstring key;
146 #if _SAMBA_BUILD_ == 4
147 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
148 if (protect_ids) {
149 if (strncmp(protect_ids, "TRUE", 4)) {
150 DEBUG(0, ("Refusing to store a Domain SID, "
151 "it has been marked as protected!\n"));
152 return false;
155 #endif
157 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
158 if (!strupper_m(key)) {
159 return false;
161 return secrets_store(key, guid, sizeof(struct GUID));
164 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
166 struct GUID *dyn_guid;
167 fstring key;
168 size_t size = 0;
169 struct GUID new_guid;
171 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
172 if (!strupper_m(key)) {
173 return false;
175 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
177 if (!dyn_guid) {
178 if (lp_server_role() == ROLE_DOMAIN_PDC) {
179 new_guid = GUID_random();
180 if (!secrets_store_domain_guid(domain, &new_guid))
181 return False;
182 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
184 if (dyn_guid == NULL) {
185 return False;
189 if (size != sizeof(struct GUID)) {
190 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
191 SAFE_FREE(dyn_guid);
192 return False;
195 *guid = *dyn_guid;
196 SAFE_FREE(dyn_guid);
197 return True;
201 * Form a key for fetching the machine trust account sec channel type
203 * @param domain domain name
205 * @return keystring
207 static const char *machine_sec_channel_type_keystr(const char *domain)
209 char *keystr;
211 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
212 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
213 domain);
214 SMB_ASSERT(keystr != NULL);
215 return keystr;
219 * Form a key for fetching the machine trust account last change time
221 * @param domain domain name
223 * @return keystring
225 static const char *machine_last_change_time_keystr(const char *domain)
227 char *keystr;
229 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
230 SECRETS_MACHINE_LAST_CHANGE_TIME,
231 domain);
232 SMB_ASSERT(keystr != NULL);
233 return keystr;
238 * Form a key for fetching the machine previous trust account password
240 * @param domain domain name
242 * @return keystring
244 static const char *machine_prev_password_keystr(const char *domain)
246 char *keystr;
248 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
249 SECRETS_MACHINE_PASSWORD_PREV, domain);
250 SMB_ASSERT(keystr != NULL);
251 return keystr;
255 * Form a key for fetching the machine trust account password
257 * @param domain domain name
259 * @return keystring
261 static const char *machine_password_keystr(const char *domain)
263 char *keystr;
265 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
266 SECRETS_MACHINE_PASSWORD, domain);
267 SMB_ASSERT(keystr != NULL);
268 return keystr;
272 * Form a key for fetching the machine trust account password
274 * @param domain domain name
276 * @return stored password's key
278 static const char *trust_keystr(const char *domain)
280 char *keystr;
282 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
283 SECRETS_MACHINE_ACCT_PASS, domain);
284 SMB_ASSERT(keystr != NULL);
285 return keystr;
288 /************************************************************************
289 Lock the trust password entry.
290 ************************************************************************/
292 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
294 struct db_context *db_ctx;
295 if (!secrets_init()) {
296 return NULL;
299 db_ctx = secrets_db_ctx();
301 return dbwrap_fetch_locked(
302 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
305 /************************************************************************
306 Routine to get the default secure channel type for trust accounts
307 ************************************************************************/
309 enum netr_SchannelType get_default_sec_channel(void)
311 if (lp_server_role() == ROLE_DOMAIN_BDC ||
312 lp_server_role() == ROLE_DOMAIN_PDC ||
313 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
314 return SEC_CHAN_BDC;
315 } else {
316 return SEC_CHAN_WKSTA;
320 /************************************************************************
321 Routine to get the trust account password for a domain.
322 This only tries to get the legacy hashed version of the password.
323 The user of this function must have locked the trust password file using
324 the above secrets_lock_trust_account_password().
325 ************************************************************************/
327 bool secrets_fetch_trust_account_password_legacy(const char *domain,
328 uint8_t ret_pwd[16],
329 time_t *pass_last_set_time,
330 enum netr_SchannelType *channel)
332 struct machine_acct_pass *pass;
333 size_t size = 0;
335 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
336 trust_keystr(domain), &size))) {
337 DEBUG(5, ("secrets_fetch failed!\n"));
338 return False;
341 if (size != sizeof(*pass)) {
342 DEBUG(0, ("secrets were of incorrect size!\n"));
343 SAFE_FREE(pass);
344 return False;
347 if (pass_last_set_time) {
348 *pass_last_set_time = pass->mod_time;
350 memcpy(ret_pwd, pass->hash, 16);
352 if (channel) {
353 *channel = get_default_sec_channel();
356 SAFE_FREE(pass);
357 return True;
360 /************************************************************************
361 Routine to get the trust account password for a domain.
362 The user of this function must have locked the trust password file using
363 the above secrets_lock_trust_account_password().
364 ************************************************************************/
366 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
367 time_t *pass_last_set_time,
368 enum netr_SchannelType *channel)
370 char *plaintext;
372 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
373 channel);
374 if (plaintext) {
375 DEBUG(4,("Using cleartext machine password\n"));
376 E_md4hash(plaintext, ret_pwd);
377 SAFE_FREE(plaintext);
378 return True;
381 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
382 pass_last_set_time,
383 channel);
386 /************************************************************************
387 Routine to delete the old plaintext machine account password if any
388 ************************************************************************/
390 static bool secrets_delete_prev_machine_password(const char *domain)
392 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
393 if (oldpass == NULL) {
394 return true;
396 SAFE_FREE(oldpass);
397 return secrets_delete(machine_prev_password_keystr(domain));
400 /************************************************************************
401 Routine to delete the plaintext machine account password, old password,
402 sec channel type and last change time from secrets database
403 ************************************************************************/
405 bool secrets_delete_machine_password_ex(const char *domain)
407 if (!secrets_delete_prev_machine_password(domain)) {
408 return false;
410 if (!secrets_delete(machine_password_keystr(domain))) {
411 return false;
413 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
414 return false;
416 return secrets_delete(machine_last_change_time_keystr(domain));
419 /************************************************************************
420 Routine to delete the domain sid
421 ************************************************************************/
423 bool secrets_delete_domain_sid(const char *domain)
425 return secrets_delete(domain_sid_keystr(domain));
428 /************************************************************************
429 Routine to store the previous machine password (by storing the current password
430 as the old)
431 ************************************************************************/
433 static bool secrets_store_prev_machine_password(const char *domain)
435 char *oldpass;
436 bool ret;
438 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
439 if (oldpass == NULL) {
440 return true;
442 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
443 SAFE_FREE(oldpass);
444 return ret;
447 /************************************************************************
448 Routine to set the plaintext machine account password for a realm
449 the password is assumed to be a null terminated ascii string.
450 Before storing
451 ************************************************************************/
453 bool secrets_store_machine_password(const char *pass, const char *domain,
454 enum netr_SchannelType sec_channel)
456 bool ret;
457 uint32_t last_change_time;
458 uint32_t sec_channel_type;
460 if (!secrets_store_prev_machine_password(domain)) {
461 return false;
464 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
465 if (!ret)
466 return ret;
468 SIVAL(&last_change_time, 0, time(NULL));
469 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
471 SIVAL(&sec_channel_type, 0, sec_channel);
472 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
474 return ret;
477 /************************************************************************
478 Set the machine trust account password, the old pw and last change
479 time, domain SID and salting principals based on values passed in
480 (added to supprt the secrets_tdb_sync module on secrets.ldb)
481 ************************************************************************/
483 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
484 const char *realm,
485 const char *salting_principal, uint32_t supported_enc_types,
486 const struct dom_sid *domain_sid, uint32_t last_change_time,
487 bool delete_join)
489 bool ret;
490 uint8_t last_change_time_store[4];
491 TALLOC_CTX *frame = talloc_stackframe();
492 void *value;
494 if (delete_join) {
495 secrets_delete_machine_password_ex(domain);
496 secrets_delete_domain_sid(domain);
497 TALLOC_FREE(frame);
498 return true;
501 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
502 if (!ret) {
503 TALLOC_FREE(frame);
504 return ret;
507 if (oldpass) {
508 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
509 } else {
510 value = secrets_fetch_prev_machine_password(domain);
511 if (value) {
512 SAFE_FREE(value);
513 ret = secrets_delete_prev_machine_password(domain);
516 if (!ret) {
517 TALLOC_FREE(frame);
518 return ret;
521 /* We delete this and instead have the read code fall back to
522 * a default based on server role, as our caller can't specify
523 * this with any more certainty */
524 value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
525 if (value) {
526 SAFE_FREE(value);
527 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
528 if (!ret) {
529 TALLOC_FREE(frame);
530 return ret;
534 SIVAL(&last_change_time_store, 0, last_change_time);
535 ret = secrets_store(machine_last_change_time_keystr(domain),
536 &last_change_time_store, sizeof(last_change_time));
538 if (!ret) {
539 TALLOC_FREE(frame);
540 return ret;
543 ret = secrets_store_domain_sid(domain, domain_sid);
545 if (!ret) {
546 TALLOC_FREE(frame);
547 return ret;
550 if (realm && salting_principal) {
551 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
552 if (!key) {
553 TALLOC_FREE(frame);
554 return false;
556 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
559 TALLOC_FREE(frame);
560 return ret;
564 /************************************************************************
565 Routine to fetch the previous plaintext machine account password for a realm
566 the password is assumed to be a null terminated ascii string.
567 ************************************************************************/
569 char *secrets_fetch_prev_machine_password(const char *domain)
571 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
574 /************************************************************************
575 Routine to fetch the plaintext machine account password for a realm
576 the password is assumed to be a null terminated ascii string.
577 ************************************************************************/
579 char *secrets_fetch_machine_password(const char *domain,
580 time_t *pass_last_set_time,
581 enum netr_SchannelType *channel)
583 char *ret;
584 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
586 if (pass_last_set_time) {
587 size_t size;
588 uint32_t *last_set_time;
589 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
590 if (last_set_time) {
591 *pass_last_set_time = IVAL(last_set_time,0);
592 SAFE_FREE(last_set_time);
593 } else {
594 *pass_last_set_time = 0;
598 if (channel) {
599 size_t size;
600 uint32_t *channel_type;
601 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
602 if (channel_type) {
603 *channel = IVAL(channel_type,0);
604 SAFE_FREE(channel_type);
605 } else {
606 *channel = get_default_sec_channel();
610 return ret;