s4-libcli: Use a do-while loop.
[Samba/bb.git] / source3 / passdb / machine_account_secrets.c
blob6320f4e2f7cc635b95bc19d3a90787404598b63b
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 SAFE_FREE(protect_ids);
153 return false;
156 SAFE_FREE(protect_ids);
157 #endif
159 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
160 if (!strupper_m(key)) {
161 return false;
163 return secrets_store(key, guid, sizeof(struct GUID));
166 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
168 struct GUID *dyn_guid;
169 fstring key;
170 size_t size = 0;
171 struct GUID new_guid;
173 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
174 if (!strupper_m(key)) {
175 return false;
177 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
179 if (!dyn_guid) {
180 if (lp_server_role() == ROLE_DOMAIN_PDC) {
181 new_guid = GUID_random();
182 if (!secrets_store_domain_guid(domain, &new_guid))
183 return False;
184 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
186 if (dyn_guid == NULL) {
187 return False;
191 if (size != sizeof(struct GUID)) {
192 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
193 SAFE_FREE(dyn_guid);
194 return False;
197 *guid = *dyn_guid;
198 SAFE_FREE(dyn_guid);
199 return True;
203 * Form a key for fetching the machine trust account sec channel type
205 * @param domain domain name
207 * @return keystring
209 static const char *machine_sec_channel_type_keystr(const char *domain)
211 char *keystr;
213 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
214 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
215 domain);
216 SMB_ASSERT(keystr != NULL);
217 return keystr;
221 * Form a key for fetching the machine trust account last change time
223 * @param domain domain name
225 * @return keystring
227 static const char *machine_last_change_time_keystr(const char *domain)
229 char *keystr;
231 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
232 SECRETS_MACHINE_LAST_CHANGE_TIME,
233 domain);
234 SMB_ASSERT(keystr != NULL);
235 return keystr;
240 * Form a key for fetching the machine previous trust account password
242 * @param domain domain name
244 * @return keystring
246 static const char *machine_prev_password_keystr(const char *domain)
248 char *keystr;
250 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
251 SECRETS_MACHINE_PASSWORD_PREV, domain);
252 SMB_ASSERT(keystr != NULL);
253 return keystr;
257 * Form a key for fetching the machine trust account password
259 * @param domain domain name
261 * @return keystring
263 static const char *machine_password_keystr(const char *domain)
265 char *keystr;
267 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
268 SECRETS_MACHINE_PASSWORD, domain);
269 SMB_ASSERT(keystr != NULL);
270 return keystr;
274 * Form a key for fetching the machine trust account password
276 * @param domain domain name
278 * @return stored password's key
280 static const char *trust_keystr(const char *domain)
282 char *keystr;
284 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
285 SECRETS_MACHINE_ACCT_PASS, domain);
286 SMB_ASSERT(keystr != NULL);
287 return keystr;
290 /************************************************************************
291 Lock the trust password entry.
292 ************************************************************************/
294 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
296 struct db_context *db_ctx;
297 if (!secrets_init()) {
298 return NULL;
301 db_ctx = secrets_db_ctx();
303 return dbwrap_fetch_locked(
304 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
307 /************************************************************************
308 Routine to get the default secure channel type for trust accounts
309 ************************************************************************/
311 enum netr_SchannelType get_default_sec_channel(void)
313 if (lp_server_role() == ROLE_DOMAIN_BDC ||
314 lp_server_role() == ROLE_DOMAIN_PDC ||
315 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
316 return SEC_CHAN_BDC;
317 } else {
318 return SEC_CHAN_WKSTA;
322 /************************************************************************
323 Routine to get the trust account password for a domain.
324 This only tries to get the legacy hashed version of the password.
325 The user of this function must have locked the trust password file using
326 the above secrets_lock_trust_account_password().
327 ************************************************************************/
329 bool secrets_fetch_trust_account_password_legacy(const char *domain,
330 uint8_t ret_pwd[16],
331 time_t *pass_last_set_time,
332 enum netr_SchannelType *channel)
334 struct machine_acct_pass *pass;
335 size_t size = 0;
337 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
338 trust_keystr(domain), &size))) {
339 DEBUG(5, ("secrets_fetch failed!\n"));
340 return False;
343 if (size != sizeof(*pass)) {
344 DEBUG(0, ("secrets were of incorrect size!\n"));
345 SAFE_FREE(pass);
346 return False;
349 if (pass_last_set_time) {
350 *pass_last_set_time = pass->mod_time;
352 memcpy(ret_pwd, pass->hash, 16);
354 if (channel) {
355 *channel = get_default_sec_channel();
358 SAFE_FREE(pass);
359 return True;
362 /************************************************************************
363 Routine to get the trust account password for a domain.
364 The user of this function must have locked the trust password file using
365 the above secrets_lock_trust_account_password().
366 ************************************************************************/
368 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
369 time_t *pass_last_set_time,
370 enum netr_SchannelType *channel)
372 char *plaintext;
374 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
375 channel);
376 if (plaintext) {
377 DEBUG(4,("Using cleartext machine password\n"));
378 E_md4hash(plaintext, ret_pwd);
379 SAFE_FREE(plaintext);
380 return True;
383 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
384 pass_last_set_time,
385 channel);
388 /************************************************************************
389 Routine to delete the old plaintext machine account password if any
390 ************************************************************************/
392 static bool secrets_delete_prev_machine_password(const char *domain)
394 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
395 if (oldpass == NULL) {
396 return true;
398 SAFE_FREE(oldpass);
399 return secrets_delete(machine_prev_password_keystr(domain));
402 /************************************************************************
403 Routine to delete the plaintext machine account password, old password,
404 sec channel type and last change time from secrets database
405 ************************************************************************/
407 bool secrets_delete_machine_password_ex(const char *domain)
409 if (!secrets_delete_prev_machine_password(domain)) {
410 return false;
412 if (!secrets_delete(machine_password_keystr(domain))) {
413 return false;
415 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
416 return false;
418 return secrets_delete(machine_last_change_time_keystr(domain));
421 /************************************************************************
422 Routine to delete the domain sid
423 ************************************************************************/
425 bool secrets_delete_domain_sid(const char *domain)
427 return secrets_delete(domain_sid_keystr(domain));
430 /************************************************************************
431 Routine to store the previous machine password (by storing the current password
432 as the old)
433 ************************************************************************/
435 static bool secrets_store_prev_machine_password(const char *domain)
437 char *oldpass;
438 bool ret;
440 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
441 if (oldpass == NULL) {
442 return true;
444 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
445 SAFE_FREE(oldpass);
446 return ret;
449 /************************************************************************
450 Routine to set the plaintext machine account password for a realm
451 the password is assumed to be a null terminated ascii string.
452 Before storing
453 ************************************************************************/
455 bool secrets_store_machine_password(const char *pass, const char *domain,
456 enum netr_SchannelType sec_channel)
458 bool ret;
459 uint32_t last_change_time;
460 uint32_t sec_channel_type;
462 if (!secrets_store_prev_machine_password(domain)) {
463 return false;
466 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
467 if (!ret)
468 return ret;
470 SIVAL(&last_change_time, 0, time(NULL));
471 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
473 SIVAL(&sec_channel_type, 0, sec_channel);
474 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
476 return ret;
479 /************************************************************************
480 Set the machine trust account password, the old pw and last change
481 time, domain SID and salting principals based on values passed in
482 (added to supprt the secrets_tdb_sync module on secrets.ldb)
483 ************************************************************************/
485 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
486 const char *realm,
487 const char *salting_principal, uint32_t supported_enc_types,
488 const struct dom_sid *domain_sid, uint32_t last_change_time,
489 bool delete_join)
491 bool ret;
492 uint8_t last_change_time_store[4];
493 TALLOC_CTX *frame = talloc_stackframe();
494 void *value;
496 if (delete_join) {
497 secrets_delete_machine_password_ex(domain);
498 secrets_delete_domain_sid(domain);
499 TALLOC_FREE(frame);
500 return true;
503 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
504 if (!ret) {
505 TALLOC_FREE(frame);
506 return ret;
509 if (oldpass) {
510 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
511 } else {
512 value = secrets_fetch_prev_machine_password(domain);
513 if (value) {
514 SAFE_FREE(value);
515 ret = secrets_delete_prev_machine_password(domain);
518 if (!ret) {
519 TALLOC_FREE(frame);
520 return ret;
523 /* We delete this and instead have the read code fall back to
524 * a default based on server role, as our caller can't specify
525 * this with any more certainty */
526 value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
527 if (value) {
528 SAFE_FREE(value);
529 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
530 if (!ret) {
531 TALLOC_FREE(frame);
532 return ret;
536 SIVAL(&last_change_time_store, 0, last_change_time);
537 ret = secrets_store(machine_last_change_time_keystr(domain),
538 &last_change_time_store, sizeof(last_change_time));
540 if (!ret) {
541 TALLOC_FREE(frame);
542 return ret;
545 ret = secrets_store_domain_sid(domain, domain_sid);
547 if (!ret) {
548 TALLOC_FREE(frame);
549 return ret;
552 if (realm && salting_principal) {
553 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
554 if (!key) {
555 TALLOC_FREE(frame);
556 return false;
558 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
561 TALLOC_FREE(frame);
562 return ret;
566 /************************************************************************
567 Routine to fetch the previous plaintext machine account password for a realm
568 the password is assumed to be a null terminated ascii string.
569 ************************************************************************/
571 char *secrets_fetch_prev_machine_password(const char *domain)
573 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
576 /************************************************************************
577 Routine to fetch the plaintext machine account password for a realm
578 the password is assumed to be a null terminated ascii string.
579 ************************************************************************/
581 char *secrets_fetch_machine_password(const char *domain,
582 time_t *pass_last_set_time,
583 enum netr_SchannelType *channel)
585 char *ret;
586 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
588 if (pass_last_set_time) {
589 size_t size;
590 uint32_t *last_set_time;
591 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
592 if (last_set_time) {
593 *pass_last_set_time = IVAL(last_set_time,0);
594 SAFE_FREE(last_set_time);
595 } else {
596 *pass_last_set_time = 0;
600 if (channel) {
601 size_t size;
602 uint32_t *channel_type;
603 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
604 if (channel_type) {
605 *channel = IVAL(channel_type,0);
606 SAFE_FREE(channel_type);
607 } else {
608 *channel = get_default_sec_channel();
612 return ret;