talloc: Fix CID 1373621 Unchecked return value
[Samba.git] / source3 / passdb / machine_account_secrets.c
blob3f097ab4055691cb6ee627768284f6a94f96b4b0
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 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) {
295 return SEC_CHAN_BDC;
296 } else {
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,
309 uint8_t ret_pwd[16],
310 time_t *pass_last_set_time,
311 enum netr_SchannelType *channel)
313 struct machine_acct_pass *pass;
314 size_t size = 0;
316 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
317 trust_keystr(domain), &size))) {
318 DEBUG(5, ("secrets_fetch failed!\n"));
319 return False;
322 if (size != sizeof(*pass)) {
323 DEBUG(0, ("secrets were of incorrect size!\n"));
324 SAFE_FREE(pass);
325 return False;
328 if (pass_last_set_time) {
329 *pass_last_set_time = pass->mod_time;
331 memcpy(ret_pwd, pass->hash, 16);
333 if (channel) {
334 *channel = get_default_sec_channel();
337 SAFE_FREE(pass);
338 return True;
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)
351 char *plaintext;
353 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
354 channel);
355 if (plaintext) {
356 DEBUG(4,("Using cleartext machine password\n"));
357 E_md4hash(plaintext, ret_pwd);
358 SAFE_FREE(plaintext);
359 return True;
362 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
363 pass_last_set_time,
364 channel);
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) {
375 return true;
377 SAFE_FREE(oldpass);
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)) {
389 return false;
391 if (!secrets_delete(machine_password_keystr(domain))) {
392 return false;
394 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
395 return false;
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
411 as the old)
412 ************************************************************************/
414 static bool secrets_store_prev_machine_password(const char *domain)
416 char *oldpass;
417 bool ret;
419 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
420 if (oldpass == NULL) {
421 return true;
423 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
424 SAFE_FREE(oldpass);
425 return ret;
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.
431 Before storing
432 ************************************************************************/
434 bool secrets_store_machine_password(const char *pass, const char *domain,
435 enum netr_SchannelType sec_channel)
437 bool ret;
438 uint32_t last_change_time;
439 uint32_t sec_channel_type;
441 if (!secrets_store_prev_machine_password(domain)) {
442 return false;
445 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
446 if (!ret)
447 return ret;
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));
455 return ret;
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,
465 const char *realm,
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,
469 bool delete_join)
471 bool ret;
472 uint8_t last_change_time_store[4];
473 TALLOC_CTX *frame = talloc_stackframe();
474 uint8_t sec_channel_bytes[4];
475 void *value;
477 if (delete_join) {
478 secrets_delete_machine_password_ex(domain);
479 secrets_delete_domain_sid(domain);
480 TALLOC_FREE(frame);
481 return true;
484 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
485 if (!ret) {
486 TALLOC_FREE(frame);
487 return ret;
490 if (oldpass) {
491 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
492 } else {
493 value = secrets_fetch_prev_machine_password(domain);
494 if (value) {
495 SAFE_FREE(value);
496 ret = secrets_delete_prev_machine_password(domain);
499 if (!ret) {
500 TALLOC_FREE(frame);
501 return ret;
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);
509 if (value) {
510 SAFE_FREE(value);
511 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
512 if (!ret) {
513 TALLOC_FREE(frame);
514 return ret;
517 } else {
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));
521 if (!ret) {
522 TALLOC_FREE(frame);
523 return ret;
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));
531 if (!ret) {
532 TALLOC_FREE(frame);
533 return ret;
536 ret = secrets_store_domain_sid(domain, domain_sid);
538 if (!ret) {
539 TALLOC_FREE(frame);
540 return ret;
543 if (realm && salting_principal) {
544 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
545 if (!key) {
546 TALLOC_FREE(frame);
547 return false;
549 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
552 TALLOC_FREE(frame);
553 return ret;
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 last change time of the machine account password
569 for a realm
570 ************************************************************************/
572 time_t secrets_fetch_pass_last_set_time(const char *domain)
574 uint32_t *last_set_time;
575 time_t pass_last_set_time;
577 last_set_time = secrets_fetch(machine_last_change_time_keystr(domain),
578 NULL);
579 if (last_set_time) {
580 pass_last_set_time = IVAL(last_set_time,0);
581 SAFE_FREE(last_set_time);
582 } else {
583 pass_last_set_time = 0;
586 return pass_last_set_time;
589 /************************************************************************
590 Routine to fetch the plaintext machine account password for a realm
591 the password is assumed to be a null terminated ascii string.
592 ************************************************************************/
594 char *secrets_fetch_machine_password(const char *domain,
595 time_t *pass_last_set_time,
596 enum netr_SchannelType *channel)
598 char *ret;
599 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
601 if (pass_last_set_time) {
602 *pass_last_set_time = secrets_fetch_pass_last_set_time(domain);
605 if (channel) {
606 size_t size;
607 uint32_t *channel_type;
608 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
609 if (channel_type) {
610 *channel = IVAL(channel_type,0);
611 SAFE_FREE(channel_type);
612 } else {
613 *channel = get_default_sec_channel();
617 return ret;