smbd: Use full_path_tos() where appropriate
[Samba/wip.git] / source3 / passdb / machine_account_secrets.c
blob4e35a726382c16678ac76ceba416aeb12b6f9712
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"
32 #include "libcli/security/security.h"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_PASSDB
37 /**
38 * Form a key for fetching the domain sid
40 * @param domain domain name
42 * @return keystring
43 **/
44 static const char *domain_sid_keystr(const char *domain)
46 char *keystr;
48 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
49 SECRETS_DOMAIN_SID, domain);
50 SMB_ASSERT(keystr != NULL);
51 return keystr;
54 static const char *protect_ids_keystr(const char *domain)
56 char *keystr;
58 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
59 SECRETS_PROTECT_IDS, domain);
60 SMB_ASSERT(keystr != NULL);
61 return keystr;
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)
67 bool ret;
69 ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
70 if (!ret) {
71 DEBUG(0, ("Failed to protect the Domain IDs\n"));
73 return ret;
76 bool secrets_clear_domain_protection(const char *domain)
78 bool ret;
79 void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
81 if (protection) {
82 SAFE_FREE(protection);
83 ret = secrets_delete(protect_ids_keystr(domain));
84 if (!ret) {
85 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
87 return ret;
89 return true;
92 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
94 char *protect_ids;
95 bool ret;
97 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
98 if (protect_ids) {
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);
103 return false;
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 */
111 if (ret) {
112 if (dom_sid_equal(get_global_sam_sid(), sid) == false) {
113 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 char *protect_ids;
142 fstring key;
144 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
145 if (protect_ids) {
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);
150 return false;
153 SAFE_FREE(protect_ids);
155 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
156 if (!strupper_m(key)) {
157 return false;
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;
165 fstring key;
166 size_t size = 0;
167 struct GUID new_guid;
169 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
170 if (!strupper_m(key)) {
171 return false;
173 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
175 if (!dyn_guid) {
176 if (lp_server_role() == ROLE_DOMAIN_PDC) {
177 new_guid = GUID_random();
178 if (!secrets_store_domain_guid(domain, &new_guid))
179 return False;
180 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
182 if (dyn_guid == NULL) {
183 return False;
187 if (size != sizeof(struct GUID)) {
188 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
189 SAFE_FREE(dyn_guid);
190 return False;
193 *guid = *dyn_guid;
194 SAFE_FREE(dyn_guid);
195 return True;
199 * Form a key for fetching the machine trust account sec channel type
201 * @param domain domain name
203 * @return keystring
205 static const char *machine_sec_channel_type_keystr(const char *domain)
207 char *keystr;
209 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
210 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
211 domain);
212 SMB_ASSERT(keystr != NULL);
213 return keystr;
217 * Form a key for fetching the machine trust account last change time
219 * @param domain domain name
221 * @return keystring
223 static const char *machine_last_change_time_keystr(const char *domain)
225 char *keystr;
227 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
228 SECRETS_MACHINE_LAST_CHANGE_TIME,
229 domain);
230 SMB_ASSERT(keystr != NULL);
231 return keystr;
236 * Form a key for fetching the machine previous trust account password
238 * @param domain domain name
240 * @return keystring
242 static const char *machine_prev_password_keystr(const char *domain)
244 char *keystr;
246 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
247 SECRETS_MACHINE_PASSWORD_PREV, domain);
248 SMB_ASSERT(keystr != NULL);
249 return keystr;
253 * Form a key for fetching the machine trust account password
255 * @param domain domain name
257 * @return keystring
259 static const char *machine_password_keystr(const char *domain)
261 char *keystr;
263 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
264 SECRETS_MACHINE_PASSWORD, domain);
265 SMB_ASSERT(keystr != NULL);
266 return keystr;
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)
278 char *keystr;
280 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
281 SECRETS_MACHINE_ACCT_PASS, domain);
282 SMB_ASSERT(keystr != NULL);
283 return keystr;
286 /************************************************************************
287 Lock the trust password entry.
288 ************************************************************************/
290 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
292 struct db_context *db_ctx;
293 if (!secrets_init()) {
294 return NULL;
297 db_ctx = secrets_db_ctx();
299 return dbwrap_fetch_locked(
300 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
303 /************************************************************************
304 Routine to get the default secure channel type for trust accounts
305 ************************************************************************/
307 enum netr_SchannelType get_default_sec_channel(void)
309 if (lp_server_role() == ROLE_DOMAIN_BDC ||
310 lp_server_role() == ROLE_DOMAIN_PDC ||
311 lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
312 return SEC_CHAN_BDC;
313 } else {
314 return SEC_CHAN_WKSTA;
318 /************************************************************************
319 Routine to get the trust account password for a domain.
320 This only tries to get the legacy hashed version of the password.
321 The user of this function must have locked the trust password file using
322 the above secrets_lock_trust_account_password().
323 ************************************************************************/
325 bool secrets_fetch_trust_account_password_legacy(const char *domain,
326 uint8_t ret_pwd[16],
327 time_t *pass_last_set_time,
328 enum netr_SchannelType *channel)
330 struct machine_acct_pass *pass;
331 size_t size = 0;
333 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
334 trust_keystr(domain), &size))) {
335 DEBUG(5, ("secrets_fetch failed!\n"));
336 return False;
339 if (size != sizeof(*pass)) {
340 DEBUG(0, ("secrets were of incorrect size!\n"));
341 SAFE_FREE(pass);
342 return False;
345 if (pass_last_set_time) {
346 *pass_last_set_time = pass->mod_time;
348 memcpy(ret_pwd, pass->hash, 16);
350 if (channel) {
351 *channel = get_default_sec_channel();
354 SAFE_FREE(pass);
355 return True;
358 /************************************************************************
359 Routine to get the trust account password for a domain.
360 The user of this function must have locked the trust password file using
361 the above secrets_lock_trust_account_password().
362 ************************************************************************/
364 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
365 time_t *pass_last_set_time,
366 enum netr_SchannelType *channel)
368 char *plaintext;
370 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
371 channel);
372 if (plaintext) {
373 DEBUG(4,("Using cleartext machine password\n"));
374 E_md4hash(plaintext, ret_pwd);
375 SAFE_FREE(plaintext);
376 return True;
379 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
380 pass_last_set_time,
381 channel);
384 /************************************************************************
385 Routine to delete the old plaintext machine account password if any
386 ************************************************************************/
388 static bool secrets_delete_prev_machine_password(const char *domain)
390 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
391 if (oldpass == NULL) {
392 return true;
394 SAFE_FREE(oldpass);
395 return secrets_delete(machine_prev_password_keystr(domain));
398 /************************************************************************
399 Routine to delete the plaintext machine account password, old password,
400 sec channel type and last change time from secrets database
401 ************************************************************************/
403 bool secrets_delete_machine_password_ex(const char *domain)
405 if (!secrets_delete_prev_machine_password(domain)) {
406 return false;
408 if (!secrets_delete(machine_password_keystr(domain))) {
409 return false;
411 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
412 return false;
414 return secrets_delete(machine_last_change_time_keystr(domain));
417 /************************************************************************
418 Routine to delete the domain sid
419 ************************************************************************/
421 bool secrets_delete_domain_sid(const char *domain)
423 return secrets_delete(domain_sid_keystr(domain));
426 /************************************************************************
427 Routine to store the previous machine password (by storing the current password
428 as the old)
429 ************************************************************************/
431 static bool secrets_store_prev_machine_password(const char *domain)
433 char *oldpass;
434 bool ret;
436 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
437 if (oldpass == NULL) {
438 return true;
440 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
441 SAFE_FREE(oldpass);
442 return ret;
445 /************************************************************************
446 Routine to set the plaintext machine account password for a realm
447 the password is assumed to be a null terminated ascii string.
448 Before storing
449 ************************************************************************/
451 bool secrets_store_machine_password(const char *pass, const char *domain,
452 enum netr_SchannelType sec_channel)
454 bool ret;
455 uint32_t last_change_time;
456 uint32_t sec_channel_type;
458 if (!secrets_store_prev_machine_password(domain)) {
459 return false;
462 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
463 if (!ret)
464 return ret;
466 SIVAL(&last_change_time, 0, time(NULL));
467 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
469 SIVAL(&sec_channel_type, 0, sec_channel);
470 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
472 return ret;
475 /************************************************************************
476 Set the machine trust account password, the old pw and last change
477 time, domain SID and salting principals based on values passed in
478 (added to supprt the secrets_tdb_sync module on secrets.ldb)
479 ************************************************************************/
481 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
482 const char *realm,
483 const char *salting_principal, uint32_t supported_enc_types,
484 const struct dom_sid *domain_sid, uint32_t last_change_time,
485 bool delete_join)
487 bool ret;
488 uint8_t last_change_time_store[4];
489 TALLOC_CTX *frame = talloc_stackframe();
490 void *value;
492 if (delete_join) {
493 secrets_delete_machine_password_ex(domain);
494 secrets_delete_domain_sid(domain);
495 TALLOC_FREE(frame);
496 return true;
499 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
500 if (!ret) {
501 TALLOC_FREE(frame);
502 return ret;
505 if (oldpass) {
506 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
507 } else {
508 value = secrets_fetch_prev_machine_password(domain);
509 if (value) {
510 SAFE_FREE(value);
511 ret = secrets_delete_prev_machine_password(domain);
514 if (!ret) {
515 TALLOC_FREE(frame);
516 return ret;
519 /* We delete this and instead have the read code fall back to
520 * a default based on server role, as our caller can't specify
521 * this with any more certainty */
522 value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
523 if (value) {
524 SAFE_FREE(value);
525 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
526 if (!ret) {
527 TALLOC_FREE(frame);
528 return ret;
532 SIVAL(&last_change_time_store, 0, last_change_time);
533 ret = secrets_store(machine_last_change_time_keystr(domain),
534 &last_change_time_store, sizeof(last_change_time));
536 if (!ret) {
537 TALLOC_FREE(frame);
538 return ret;
541 ret = secrets_store_domain_sid(domain, domain_sid);
543 if (!ret) {
544 TALLOC_FREE(frame);
545 return ret;
548 if (realm && salting_principal) {
549 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
550 if (!key) {
551 TALLOC_FREE(frame);
552 return false;
554 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
557 TALLOC_FREE(frame);
558 return ret;
562 /************************************************************************
563 Routine to fetch the previous plaintext machine account password for a realm
564 the password is assumed to be a null terminated ascii string.
565 ************************************************************************/
567 char *secrets_fetch_prev_machine_password(const char *domain)
569 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
572 /************************************************************************
573 Routine to fetch the plaintext machine account password for a realm
574 the password is assumed to be a null terminated ascii string.
575 ************************************************************************/
577 char *secrets_fetch_machine_password(const char *domain,
578 time_t *pass_last_set_time,
579 enum netr_SchannelType *channel)
581 char *ret;
582 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
584 if (pass_last_set_time) {
585 size_t size;
586 uint32_t *last_set_time;
587 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
588 if (last_set_time) {
589 *pass_last_set_time = IVAL(last_set_time,0);
590 SAFE_FREE(last_set_time);
591 } else {
592 *pass_last_set_time = 0;
596 if (channel) {
597 size_t size;
598 uint32_t *channel_type;
599 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
600 if (channel_type) {
601 *channel = IVAL(channel_type,0);
602 SAFE_FREE(channel_type);
603 } else {
604 *channel = get_default_sec_channel();
608 return ret;