s4-ldb: cope better with corruption of tdb records
[Samba/aatanasov.git] / source3 / passdb / secrets.c
blob0e66e3cf01e2f36fc73f29a7575a1dcce975b8a8
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 "../libcli/auth/libcli_auth.h"
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
31 static struct db_context *db_ctx;
33 /* Urrrg. global.... */
34 bool global_machine_password_needs_changing;
36 /**
37 * Use a TDB to store an incrementing random seed.
39 * Initialised to the current pid, the very first time Samba starts,
40 * and incremented by one each time it is needed.
42 * @note Not called by systems with a working /dev/urandom.
44 static void get_rand_seed(void *userdata, int *new_seed)
46 *new_seed = sys_getpid();
47 if (db_ctx) {
48 dbwrap_trans_change_int32_atomic(db_ctx, "INFO/random_seed",
49 new_seed, 1);
53 /* open up the secrets database */
54 bool secrets_init(void)
56 char *fname = NULL;
57 unsigned char dummy;
59 if (db_ctx != NULL)
60 return True;
62 fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb",
63 lp_private_dir());
64 if (fname == NULL) {
65 return false;
68 db_ctx = db_open(NULL, fname, 0,
69 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
71 if (db_ctx == NULL) {
72 DEBUG(0,("Failed to open %s\n", fname));
73 TALLOC_FREE(fname);
74 return False;
77 TALLOC_FREE(fname);
79 /**
80 * Set a reseed function for the crypto random generator
82 * This avoids a problem where systems without /dev/urandom
83 * could send the same challenge to multiple clients
85 set_rand_reseed_callback(get_rand_seed, NULL);
87 /* Ensure that the reseed is done now, while we are root, etc */
88 generate_random_buffer(&dummy, sizeof(dummy));
90 return True;
93 struct db_context *secrets_db_ctx(void)
95 if (!secrets_init()) {
96 return NULL;
99 return db_ctx;
103 * close secrets.tdb
105 void secrets_shutdown(void)
107 TALLOC_FREE(db_ctx);
110 /* read a entry from the secrets database - the caller must free the result
111 if size is non-null then the size of the entry is put in there
113 void *secrets_fetch(const char *key, size_t *size)
115 TDB_DATA dbuf;
116 void *result;
118 if (!secrets_init()) {
119 return NULL;
122 if (db_ctx->fetch(db_ctx, talloc_tos(), string_tdb_data(key),
123 &dbuf) != 0) {
124 return NULL;
127 result = memdup(dbuf.dptr, dbuf.dsize);
128 if (result == NULL) {
129 return NULL;
131 TALLOC_FREE(dbuf.dptr);
133 if (size) {
134 *size = dbuf.dsize;
137 return result;
140 /* store a secrets entry
142 bool secrets_store(const char *key, const void *data, size_t size)
144 NTSTATUS status;
146 if (!secrets_init()) {
147 return false;
150 status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
151 make_tdb_data((const uint8 *)data, size),
152 TDB_REPLACE);
153 return NT_STATUS_IS_OK(status);
157 /* delete a secets database entry
159 bool secrets_delete(const char *key)
161 NTSTATUS status;
162 if (!secrets_init()) {
163 return false;
166 status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
168 return NT_STATUS_IS_OK(status);
172 * Form a key for fetching the domain sid
174 * @param domain domain name
176 * @return keystring
178 static const char *domain_sid_keystr(const char *domain)
180 char *keystr;
182 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
183 SECRETS_DOMAIN_SID, domain);
184 SMB_ASSERT(keystr != NULL);
185 return keystr;
188 bool secrets_store_domain_sid(const char *domain, const DOM_SID *sid)
190 bool ret;
192 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(DOM_SID));
194 /* Force a re-query, in case we modified our domain */
195 if (ret)
196 reset_global_sam_sid();
197 return ret;
200 bool secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
202 DOM_SID *dyn_sid;
203 size_t size = 0;
205 dyn_sid = (DOM_SID *)secrets_fetch(domain_sid_keystr(domain), &size);
207 if (dyn_sid == NULL)
208 return False;
210 if (size != sizeof(DOM_SID)) {
211 SAFE_FREE(dyn_sid);
212 return False;
215 *sid = *dyn_sid;
216 SAFE_FREE(dyn_sid);
217 return True;
220 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
222 fstring key;
224 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
225 strupper_m(key);
226 return secrets_store(key, guid, sizeof(struct GUID));
229 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
231 struct GUID *dyn_guid;
232 fstring key;
233 size_t size = 0;
234 struct GUID new_guid;
236 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
237 strupper_m(key);
238 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
240 if (!dyn_guid) {
241 if (lp_server_role() == ROLE_DOMAIN_PDC) {
242 new_guid = GUID_random();
243 if (!secrets_store_domain_guid(domain, &new_guid))
244 return False;
245 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
247 if (dyn_guid == NULL) {
248 return False;
252 if (size != sizeof(struct GUID)) {
253 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
254 SAFE_FREE(dyn_guid);
255 return False;
258 *guid = *dyn_guid;
259 SAFE_FREE(dyn_guid);
260 return True;
263 bool secrets_store_local_schannel_key(uint8_t schannel_key[16])
265 return secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, schannel_key, 16);
268 bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16])
270 size_t size = 0;
271 uint8_t *key;
273 key = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &size);
274 if (key == NULL) {
275 return false;
278 if (size != 16) {
279 SAFE_FREE(key);
280 return false;
283 memcpy(schannel_key, key, 16);
284 SAFE_FREE(key);
285 return true;
289 * Form a key for fetching the machine trust account sec channel type
291 * @param domain domain name
293 * @return keystring
295 static const char *machine_sec_channel_type_keystr(const char *domain)
297 char *keystr;
299 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
300 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
301 domain);
302 SMB_ASSERT(keystr != NULL);
303 return keystr;
307 * Form a key for fetching the machine trust account last change time
309 * @param domain domain name
311 * @return keystring
313 static const char *machine_last_change_time_keystr(const char *domain)
315 char *keystr;
317 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
318 SECRETS_MACHINE_LAST_CHANGE_TIME,
319 domain);
320 SMB_ASSERT(keystr != NULL);
321 return keystr;
326 * Form a key for fetching the machine trust account password
328 * @param domain domain name
330 * @return keystring
332 static const char *machine_password_keystr(const char *domain)
334 char *keystr;
336 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
337 SECRETS_MACHINE_PASSWORD, domain);
338 SMB_ASSERT(keystr != NULL);
339 return keystr;
343 * Form a key for fetching the machine trust account password
345 * @param domain domain name
347 * @return stored password's key
349 static const char *trust_keystr(const char *domain)
351 char *keystr;
353 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
354 SECRETS_MACHINE_ACCT_PASS, domain);
355 SMB_ASSERT(keystr != NULL);
356 return keystr;
360 * Form a key for fetching a trusted domain password
362 * @param domain trusted domain name
364 * @return stored password's key
366 static char *trustdom_keystr(const char *domain)
368 char *keystr;
370 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
371 SECRETS_DOMTRUST_ACCT_PASS,
372 domain);
373 SMB_ASSERT(keystr != NULL);
374 return keystr;
377 /************************************************************************
378 Lock the trust password entry.
379 ************************************************************************/
381 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
383 if (!secrets_init()) {
384 return NULL;
387 return db_ctx->fetch_locked(
388 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
391 /************************************************************************
392 Routine to get the default secure channel type for trust accounts
393 ************************************************************************/
395 uint32 get_default_sec_channel(void)
397 if (lp_server_role() == ROLE_DOMAIN_BDC ||
398 lp_server_role() == ROLE_DOMAIN_PDC) {
399 return SEC_CHAN_BDC;
400 } else {
401 return SEC_CHAN_WKSTA;
405 /************************************************************************
406 Routine to get the trust account password for a domain.
407 This only tries to get the legacy hashed version of the password.
408 The user of this function must have locked the trust password file using
409 the above secrets_lock_trust_account_password().
410 ************************************************************************/
412 bool secrets_fetch_trust_account_password_legacy(const char *domain,
413 uint8 ret_pwd[16],
414 time_t *pass_last_set_time,
415 uint32 *channel)
417 struct machine_acct_pass *pass;
418 size_t size = 0;
420 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
421 trust_keystr(domain), &size))) {
422 DEBUG(5, ("secrets_fetch failed!\n"));
423 return False;
426 if (size != sizeof(*pass)) {
427 DEBUG(0, ("secrets were of incorrect size!\n"));
428 SAFE_FREE(pass);
429 return False;
432 if (pass_last_set_time) {
433 *pass_last_set_time = pass->mod_time;
435 memcpy(ret_pwd, pass->hash, 16);
437 if (channel) {
438 *channel = get_default_sec_channel();
441 /* Test if machine password has expired and needs to be changed */
442 if (lp_machine_password_timeout()) {
443 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
444 (time_t)lp_machine_password_timeout())) {
445 global_machine_password_needs_changing = True;
449 SAFE_FREE(pass);
450 return True;
453 /************************************************************************
454 Routine to get the trust account password for a domain.
455 The user of this function must have locked the trust password file using
456 the above secrets_lock_trust_account_password().
457 ************************************************************************/
459 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
460 time_t *pass_last_set_time,
461 uint32 *channel)
463 char *plaintext;
465 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
466 channel);
467 if (plaintext) {
468 DEBUG(4,("Using cleartext machine password\n"));
469 E_md4hash(plaintext, ret_pwd);
470 SAFE_FREE(plaintext);
471 return True;
474 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
475 pass_last_set_time,
476 channel);
480 * Pack SID passed by pointer
482 * @param pack_buf pointer to buffer which is to be filled with packed data
483 * @param bufsize size of packing buffer
484 * @param sid pointer to sid to be packed
486 * @return length of the packed representation of the whole structure
488 static size_t tdb_sid_pack(uint8 *pack_buf, int bufsize, DOM_SID* sid)
490 int idx;
491 size_t len = 0;
492 uint8 *p = pack_buf;
493 int remaining_space = pack_buf ? bufsize : 0;
495 if (!sid) {
496 return -1;
499 len += tdb_pack(p, remaining_space, "bb", sid->sid_rev_num,
500 sid->num_auths);
501 if (pack_buf) {
502 p = pack_buf + len;
503 remaining_space = bufsize - len;
506 for (idx = 0; idx < 6; idx++) {
507 len += tdb_pack(p, remaining_space, "b",
508 sid->id_auth[idx]);
509 if (pack_buf) {
510 p = pack_buf + len;
511 remaining_space = bufsize - len;
515 for (idx = 0; idx < MAXSUBAUTHS; idx++) {
516 len += tdb_pack(p, remaining_space, "d",
517 sid->sub_auths[idx]);
518 if (pack_buf) {
519 p = pack_buf + len;
520 remaining_space = bufsize - len;
524 return len;
528 * Unpack SID into a pointer
530 * @param pack_buf pointer to buffer with packed representation
531 * @param bufsize size of the buffer
532 * @param sid pointer to sid structure to be filled with unpacked data
534 * @return size of structure unpacked from buffer
536 static size_t tdb_sid_unpack(uint8 *pack_buf, int bufsize, DOM_SID* sid)
538 int idx, len = 0;
540 if (!sid || !pack_buf) return -1;
542 len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
543 &sid->sid_rev_num, &sid->num_auths);
545 for (idx = 0; idx < 6; idx++) {
546 len += tdb_unpack(pack_buf + len, bufsize - len, "b",
547 &sid->id_auth[idx]);
550 for (idx = 0; idx < MAXSUBAUTHS; idx++) {
551 len += tdb_unpack(pack_buf + len, bufsize - len, "d",
552 &sid->sub_auths[idx]);
555 return len;
559 * Pack TRUSTED_DOM_PASS passed by pointer
561 * @param pack_buf pointer to buffer which is to be filled with packed data
562 * @param bufsize size of the buffer
563 * @param pass pointer to trusted domain password to be packed
565 * @return length of the packed representation of the whole structure
567 static size_t tdb_trusted_dom_pass_pack(uint8 *pack_buf, int bufsize,
568 TRUSTED_DOM_PASS* pass)
570 int idx, len = 0;
571 uint8 *p = pack_buf;
572 int remaining_space = pack_buf ? bufsize : 0;
574 if (!pass) {
575 return -1;
578 /* packing unicode domain name and password */
579 len += tdb_pack(p, remaining_space, "d",
580 pass->uni_name_len);
581 if (pack_buf) {
582 p = pack_buf + len;
583 remaining_space = bufsize - len;
586 for (idx = 0; idx < 32; idx++) {
587 len += tdb_pack(p, remaining_space, "w",
588 pass->uni_name[idx]);
589 if (pack_buf) {
590 p = pack_buf + len;
591 remaining_space = bufsize - len;
595 len += tdb_pack(p, remaining_space, "dPd", pass->pass_len,
596 pass->pass, pass->mod_time);
597 if (pack_buf) {
598 p = pack_buf + len;
599 remaining_space = bufsize - len;
602 /* packing SID structure */
603 len += tdb_sid_pack(p, remaining_space, &pass->domain_sid);
604 if (pack_buf) {
605 p = pack_buf + len;
606 remaining_space = bufsize - len;
609 return len;
614 * Unpack TRUSTED_DOM_PASS passed by pointer
616 * @param pack_buf pointer to buffer with packed representation
617 * @param bufsize size of the buffer
618 * @param pass pointer to trusted domain password to be filled with unpacked data
620 * @return size of structure unpacked from buffer
622 static size_t tdb_trusted_dom_pass_unpack(uint8 *pack_buf, int bufsize,
623 TRUSTED_DOM_PASS* pass)
625 int idx, len = 0;
626 char *passp = NULL;
628 if (!pack_buf || !pass) return -1;
630 /* unpack unicode domain name and plaintext password */
631 len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
633 for (idx = 0; idx < 32; idx++)
634 len += tdb_unpack(pack_buf + len, bufsize - len, "w",
635 &pass->uni_name[idx]);
637 len += tdb_unpack(pack_buf + len, bufsize - len, "dPd",
638 &pass->pass_len, &passp, &pass->mod_time);
639 if (passp) {
640 fstrcpy(pass->pass, passp);
642 SAFE_FREE(passp);
644 /* unpack domain sid */
645 len += tdb_sid_unpack(pack_buf + len, bufsize - len,
646 &pass->domain_sid);
648 return len;
651 /************************************************************************
652 Routine to get account password to trusted domain
653 ************************************************************************/
655 bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
656 DOM_SID *sid, time_t *pass_last_set_time)
658 struct trusted_dom_pass pass;
659 size_t size = 0;
661 /* unpacking structures */
662 uint8 *pass_buf;
663 int pass_len = 0;
665 ZERO_STRUCT(pass);
667 /* fetching trusted domain password structure */
668 if (!(pass_buf = (uint8 *)secrets_fetch(trustdom_keystr(domain),
669 &size))) {
670 DEBUG(5, ("secrets_fetch failed!\n"));
671 return False;
674 /* unpack trusted domain password */
675 pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass);
676 SAFE_FREE(pass_buf);
678 if (pass_len != size) {
679 DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
680 return False;
683 /* the trust's password */
684 if (pwd) {
685 *pwd = SMB_STRDUP(pass.pass);
686 if (!*pwd) {
687 return False;
691 /* last change time */
692 if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
694 /* domain sid */
695 if (sid != NULL) sid_copy(sid, &pass.domain_sid);
697 return True;
701 * Routine to store the password for trusted domain
703 * @param domain remote domain name
704 * @param pwd plain text password of trust relationship
705 * @param sid remote domain sid
707 * @return true if succeeded
710 bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
711 const DOM_SID *sid)
713 smb_ucs2_t *uni_dom_name;
714 bool ret;
715 size_t converted_size;
717 /* packing structures */
718 uint8 *pass_buf = NULL;
719 int pass_len = 0;
721 struct trusted_dom_pass pass;
722 ZERO_STRUCT(pass);
724 if (!push_ucs2_talloc(talloc_tos(), &uni_dom_name, domain, &converted_size)) {
725 DEBUG(0, ("Could not convert domain name %s to unicode\n",
726 domain));
727 return False;
730 strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
731 pass.uni_name_len = strlen_w(uni_dom_name)+1;
732 TALLOC_FREE(uni_dom_name);
734 /* last change time */
735 pass.mod_time = time(NULL);
737 /* password of the trust */
738 pass.pass_len = strlen(pwd);
739 fstrcpy(pass.pass, pwd);
741 /* domain sid */
742 sid_copy(&pass.domain_sid, sid);
744 /* Calculate the length. */
745 pass_len = tdb_trusted_dom_pass_pack(NULL, 0, &pass);
746 pass_buf = talloc_array(talloc_tos(), uint8, pass_len);
747 if (!pass_buf) {
748 return false;
750 pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_len, &pass);
751 ret = secrets_store(trustdom_keystr(domain), (void *)pass_buf,
752 pass_len);
753 TALLOC_FREE(pass_buf);
754 return ret;
757 /************************************************************************
758 Routine to delete the plaintext machine account password
759 ************************************************************************/
761 bool secrets_delete_machine_password(const char *domain)
763 return secrets_delete(machine_password_keystr(domain));
766 /************************************************************************
767 Routine to delete the plaintext machine account password, sec channel type and
768 last change time from secrets database
769 ************************************************************************/
771 bool secrets_delete_machine_password_ex(const char *domain)
773 if (!secrets_delete(machine_password_keystr(domain))) {
774 return false;
776 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
777 return false;
779 return secrets_delete(machine_last_change_time_keystr(domain));
782 /************************************************************************
783 Routine to delete the domain sid
784 ************************************************************************/
786 bool secrets_delete_domain_sid(const char *domain)
788 return secrets_delete(domain_sid_keystr(domain));
791 /************************************************************************
792 Routine to set the plaintext machine account password for a realm
793 the password is assumed to be a null terminated ascii string
794 ************************************************************************/
796 bool secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
798 bool ret;
799 uint32 last_change_time;
800 uint32 sec_channel_type;
802 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
803 if (!ret)
804 return ret;
806 SIVAL(&last_change_time, 0, time(NULL));
807 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
809 SIVAL(&sec_channel_type, 0, sec_channel);
810 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
812 return ret;
815 /************************************************************************
816 Routine to fetch the plaintext machine account password for a realm
817 the password is assumed to be a null terminated ascii string.
818 ************************************************************************/
820 char *secrets_fetch_machine_password(const char *domain,
821 time_t *pass_last_set_time,
822 uint32 *channel)
824 char *ret;
825 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
827 if (pass_last_set_time) {
828 size_t size;
829 uint32 *last_set_time;
830 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
831 if (last_set_time) {
832 *pass_last_set_time = IVAL(last_set_time,0);
833 SAFE_FREE(last_set_time);
834 } else {
835 *pass_last_set_time = 0;
839 if (channel) {
840 size_t size;
841 uint32 *channel_type;
842 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
843 if (channel_type) {
844 *channel = IVAL(channel_type,0);
845 SAFE_FREE(channel_type);
846 } else {
847 *channel = get_default_sec_channel();
851 return ret;
854 /************************************************************************
855 Routine to delete the password for trusted domain
856 ************************************************************************/
858 bool trusted_domain_password_delete(const char *domain)
860 return secrets_delete(trustdom_keystr(domain));
863 bool secrets_store_ldap_pw(const char* dn, char* pw)
865 char *key = NULL;
866 bool ret;
868 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
869 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
870 return False;
873 ret = secrets_store(key, pw, strlen(pw)+1);
875 SAFE_FREE(key);
876 return ret;
879 /*******************************************************************
880 Find the ldap password.
881 ******************************************************************/
883 bool fetch_ldap_pw(char **dn, char** pw)
885 char *key = NULL;
886 size_t size = 0;
888 *dn = smb_xstrdup(lp_ldap_admin_dn());
890 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
891 SAFE_FREE(*dn);
892 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
895 *pw=(char *)secrets_fetch(key, &size);
896 SAFE_FREE(key);
898 if (!size) {
899 /* Upgrade 2.2 style entry */
900 char *p;
901 char* old_style_key = SMB_STRDUP(*dn);
902 char *data;
903 fstring old_style_pw;
905 if (!old_style_key) {
906 DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
907 return False;
910 for (p=old_style_key; *p; p++)
911 if (*p == ',') *p = '/';
913 data=(char *)secrets_fetch(old_style_key, &size);
914 if ((data == NULL) || (size < sizeof(old_style_pw))) {
915 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
916 SAFE_FREE(old_style_key);
917 SAFE_FREE(*dn);
918 SAFE_FREE(data);
919 return False;
922 size = MIN(size, sizeof(fstring)-1);
923 strncpy(old_style_pw, data, size);
924 old_style_pw[size] = 0;
926 SAFE_FREE(data);
928 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
929 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
930 SAFE_FREE(old_style_key);
931 SAFE_FREE(*dn);
932 return False;
934 if (!secrets_delete(old_style_key)) {
935 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
938 SAFE_FREE(old_style_key);
940 *pw = smb_xstrdup(old_style_pw);
943 return True;
947 * Get trusted domains info from secrets.tdb.
950 struct list_trusted_domains_state {
951 uint32 num_domains;
952 struct trustdom_info **domains;
955 static int list_trusted_domain(struct db_record *rec, void *private_data)
957 const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
958 size_t converted_size, packed_size = 0;
959 struct trusted_dom_pass pass;
960 struct trustdom_info *dom_info;
962 struct list_trusted_domains_state *state =
963 (struct list_trusted_domains_state *)private_data;
965 if ((rec->key.dsize < prefix_len)
966 || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
967 prefix_len) != 0)) {
968 return 0;
971 packed_size = tdb_trusted_dom_pass_unpack(
972 rec->value.dptr, rec->value.dsize, &pass);
974 if (rec->value.dsize != packed_size) {
975 DEBUG(2, ("Secrets record is invalid!\n"));
976 return 0;
979 if (pass.domain_sid.num_auths != 4) {
980 DEBUG(0, ("SID %s is not a domain sid, has %d "
981 "auths instead of 4\n",
982 sid_string_dbg(&pass.domain_sid),
983 pass.domain_sid.num_auths));
984 return 0;
987 if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
988 DEBUG(0, ("talloc failed\n"));
989 return 0;
992 if (!pull_ucs2_talloc(dom_info, &dom_info->name, pass.uni_name,
993 &converted_size)) {
994 DEBUG(2, ("pull_ucs2_talloc failed\n"));
995 TALLOC_FREE(dom_info);
996 return 0;
999 sid_copy(&dom_info->sid, &pass.domain_sid);
1001 ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
1002 &state->domains, &state->num_domains);
1004 if (state->domains == NULL) {
1005 state->num_domains = 0;
1006 return -1;
1008 return 0;
1011 NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
1012 struct trustdom_info ***domains)
1014 struct list_trusted_domains_state state;
1016 secrets_init();
1018 if (db_ctx == NULL) {
1019 return NT_STATUS_ACCESS_DENIED;
1022 state.num_domains = 0;
1025 * Make sure that a talloc context for the trustdom_info structs
1026 * exists
1029 if (!(state.domains = TALLOC_ARRAY(
1030 mem_ctx, struct trustdom_info *, 1))) {
1031 return NT_STATUS_NO_MEMORY;
1034 db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
1036 *num_domains = state.num_domains;
1037 *domains = state.domains;
1038 return NT_STATUS_OK;
1041 /*******************************************************************************
1042 Store a complete AFS keyfile into secrets.tdb.
1043 *******************************************************************************/
1045 bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
1047 fstring key;
1049 if ((cell == NULL) || (keyfile == NULL))
1050 return False;
1052 if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
1053 return False;
1055 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
1056 return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
1059 /*******************************************************************************
1060 Fetch the current (highest) AFS key from secrets.tdb
1061 *******************************************************************************/
1062 bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
1064 fstring key;
1065 struct afs_keyfile *keyfile;
1066 size_t size = 0;
1067 uint32 i;
1069 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
1071 keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
1073 if (keyfile == NULL)
1074 return False;
1076 if (size != sizeof(struct afs_keyfile)) {
1077 SAFE_FREE(keyfile);
1078 return False;
1081 i = ntohl(keyfile->nkeys);
1083 if (i > SECRETS_AFS_MAXKEYS) {
1084 SAFE_FREE(keyfile);
1085 return False;
1088 *result = keyfile->entry[i-1];
1090 result->kvno = ntohl(result->kvno);
1092 SAFE_FREE(keyfile);
1094 return True;
1097 /******************************************************************************
1098 When kerberos is not available, choose between anonymous or
1099 authenticated connections.
1101 We need to use an authenticated connection if DCs have the
1102 RestrictAnonymous registry entry set > 0, or the "Additional
1103 restrictions for anonymous connections" set in the win2k Local
1104 Security Policy.
1106 Caller to free() result in domain, username, password
1107 *******************************************************************************/
1108 void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
1110 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
1111 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
1112 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
1114 if (*username && **username) {
1116 if (!*domain || !**domain)
1117 *domain = smb_xstrdup(lp_workgroup());
1119 if (!*password || !**password)
1120 *password = smb_xstrdup("");
1122 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
1123 *domain, *username));
1125 } else {
1126 DEBUG(3, ("IPC$ connections done anonymously\n"));
1127 *username = smb_xstrdup("");
1128 *domain = smb_xstrdup("");
1129 *password = smb_xstrdup("");
1133 /******************************************************************************
1134 Open or create the schannel session store tdb.
1135 *******************************************************************************/
1137 #define SCHANNEL_STORE_VERSION_1 1
1138 #define SCHANNEL_STORE_VERSION_2 2
1139 #define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_2
1141 TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
1143 TDB_DATA vers;
1144 uint32 ver;
1145 TDB_CONTEXT *tdb_sc = NULL;
1146 char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", lp_private_dir());
1148 if (!fname) {
1149 return NULL;
1152 tdb_sc = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
1154 if (!tdb_sc) {
1155 DEBUG(0,("open_schannel_session_store: Failed to open %s\n", fname));
1156 TALLOC_FREE(fname);
1157 return NULL;
1160 again:
1161 vers = tdb_fetch_bystring(tdb_sc, "SCHANNEL_STORE_VERSION");
1162 if (vers.dptr == NULL) {
1163 /* First opener, no version. */
1164 SIVAL(&ver,0,SCHANNEL_STORE_VERSION_CURRENT);
1165 vers.dptr = (uint8 *)&ver;
1166 vers.dsize = 4;
1167 tdb_store_bystring(tdb_sc, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE);
1168 vers.dptr = NULL;
1169 } else if (vers.dsize == 4) {
1170 ver = IVAL(vers.dptr,0);
1171 if (ver != SCHANNEL_STORE_VERSION_CURRENT) {
1172 DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
1173 (int)ver, fname ));
1174 tdb_wipe_all(tdb_sc);
1175 goto again;
1177 } else {
1178 tdb_close(tdb_sc);
1179 tdb_sc = NULL;
1180 DEBUG(0,("open_schannel_session_store: wrong version number size %d in %s\n",
1181 (int)vers.dsize, fname ));
1184 SAFE_FREE(vers.dptr);
1185 TALLOC_FREE(fname);
1187 return tdb_sc;
1190 bool secrets_store_generic(const char *owner, const char *key, const char *secret)
1192 char *tdbkey = NULL;
1193 bool ret;
1195 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1196 DEBUG(0, ("asprintf failed!\n"));
1197 return False;
1200 ret = secrets_store(tdbkey, secret, strlen(secret)+1);
1202 SAFE_FREE(tdbkey);
1203 return ret;
1206 /*******************************************************************
1207 Find the ldap password.
1208 ******************************************************************/
1210 char *secrets_fetch_generic(const char *owner, const char *key)
1212 char *secret = NULL;
1213 char *tdbkey = NULL;
1215 if (( ! owner) || ( ! key)) {
1216 DEBUG(1, ("Invalid Paramters"));
1217 return NULL;
1220 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1221 DEBUG(0, ("Out of memory!\n"));
1222 return NULL;
1225 secret = (char *)secrets_fetch(tdbkey, NULL);
1226 SAFE_FREE(tdbkey);
1228 return secret;