source: branches/samba-3.5.x/source3/passdb/secrets.c@ 778

Last change on this file since 778 was 480, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.5: trunk update to 3.5.4

File size: 27.3 KB
Line 
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
7
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.
12
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.
17
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/>.
20*/
21
22/* the Samba secrets database stores any generated, private information
23 such as the local SID and machine trust password */
24
25#include "includes.h"
26#include "../libcli/auth/libcli_auth.h"
27#include "librpc/gen_ndr/ndr_secrets.h"
28
29#undef DBGC_CLASS
30#define DBGC_CLASS DBGC_PASSDB
31
32static struct db_context *db_ctx;
33
34/* Urrrg. global.... */
35bool global_machine_password_needs_changing;
36
37/**
38 * Use a TDB to store an incrementing random seed.
39 *
40 * Initialised to the current pid, the very first time Samba starts,
41 * and incremented by one each time it is needed.
42 *
43 * @note Not called by systems with a working /dev/urandom.
44 */
45static void get_rand_seed(void *userdata, int *new_seed)
46{
47 *new_seed = sys_getpid();
48 if (db_ctx) {
49 dbwrap_trans_change_int32_atomic(db_ctx, "INFO/random_seed",
50 new_seed, 1);
51 }
52}
53
54/* open up the secrets database */
55bool secrets_init(void)
56{
57 char *fname = NULL;
58 unsigned char dummy;
59
60 if (db_ctx != NULL)
61 return True;
62
63 fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb",
64 lp_private_dir());
65 if (fname == NULL) {
66 return false;
67 }
68
69 db_ctx = db_open(NULL, fname, 0,
70 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
71
72 if (db_ctx == NULL) {
73 DEBUG(0,("Failed to open %s\n", fname));
74 TALLOC_FREE(fname);
75 return False;
76 }
77
78 TALLOC_FREE(fname);
79
80 /**
81 * Set a reseed function for the crypto random generator
82 *
83 * This avoids a problem where systems without /dev/urandom
84 * could send the same challenge to multiple clients
85 */
86 set_rand_reseed_callback(get_rand_seed, NULL);
87
88 /* Ensure that the reseed is done now, while we are root, etc */
89 generate_random_buffer(&dummy, sizeof(dummy));
90
91 return True;
92}
93
94struct db_context *secrets_db_ctx(void)
95{
96 if (!secrets_init()) {
97 return NULL;
98 }
99
100 return db_ctx;
101}
102
103/*
104 * close secrets.tdb
105 */
106void secrets_shutdown(void)
107{
108 TALLOC_FREE(db_ctx);
109}
110
111/* read a entry from the secrets database - the caller must free the result
112 if size is non-null then the size of the entry is put in there
113 */
114void *secrets_fetch(const char *key, size_t *size)
115{
116 TDB_DATA dbuf;
117 void *result;
118
119 if (!secrets_init()) {
120 return NULL;
121 }
122
123 if (db_ctx->fetch(db_ctx, talloc_tos(), string_tdb_data(key),
124 &dbuf) != 0) {
125 return NULL;
126 }
127
128 result = memdup(dbuf.dptr, dbuf.dsize);
129 if (result == NULL) {
130 return NULL;
131 }
132 TALLOC_FREE(dbuf.dptr);
133
134 if (size) {
135 *size = dbuf.dsize;
136 }
137
138 return result;
139}
140
141/* store a secrets entry
142 */
143bool secrets_store(const char *key, const void *data, size_t size)
144{
145 NTSTATUS status;
146
147 if (!secrets_init()) {
148 return false;
149 }
150
151 status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
152 make_tdb_data((const uint8 *)data, size),
153 TDB_REPLACE);
154 return NT_STATUS_IS_OK(status);
155}
156
157
158/* delete a secets database entry
159 */
160bool secrets_delete(const char *key)
161{
162 NTSTATUS status;
163 if (!secrets_init()) {
164 return false;
165 }
166
167 status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
168
169 return NT_STATUS_IS_OK(status);
170}
171
172/**
173 * Form a key for fetching the domain sid
174 *
175 * @param domain domain name
176 *
177 * @return keystring
178 **/
179static const char *domain_sid_keystr(const char *domain)
180{
181 char *keystr;
182
183 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
184 SECRETS_DOMAIN_SID, domain);
185 SMB_ASSERT(keystr != NULL);
186 return keystr;
187}
188
189bool secrets_store_domain_sid(const char *domain, const DOM_SID *sid)
190{
191 bool ret;
192
193 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(DOM_SID));
194
195 /* Force a re-query, in case we modified our domain */
196 if (ret)
197 reset_global_sam_sid();
198 return ret;
199}
200
201bool secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
202{
203 DOM_SID *dyn_sid;
204 size_t size = 0;
205
206 dyn_sid = (DOM_SID *)secrets_fetch(domain_sid_keystr(domain), &size);
207
208 if (dyn_sid == NULL)
209 return False;
210
211 if (size != sizeof(DOM_SID)) {
212 SAFE_FREE(dyn_sid);
213 return False;
214 }
215
216 *sid = *dyn_sid;
217 SAFE_FREE(dyn_sid);
218 return True;
219}
220
221bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
222{
223 fstring key;
224
225 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
226 strupper_m(key);
227 return secrets_store(key, guid, sizeof(struct GUID));
228}
229
230bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
231{
232 struct GUID *dyn_guid;
233 fstring key;
234 size_t size = 0;
235 struct GUID new_guid;
236
237 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
238 strupper_m(key);
239 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
240
241 if (!dyn_guid) {
242 if (lp_server_role() == ROLE_DOMAIN_PDC) {
243 new_guid = GUID_random();
244 if (!secrets_store_domain_guid(domain, &new_guid))
245 return False;
246 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
247 }
248 if (dyn_guid == NULL) {
249 return False;
250 }
251 }
252
253 if (size != sizeof(struct GUID)) {
254 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
255 SAFE_FREE(dyn_guid);
256 return False;
257 }
258
259 *guid = *dyn_guid;
260 SAFE_FREE(dyn_guid);
261 return True;
262}
263
264bool secrets_store_local_schannel_key(uint8_t schannel_key[16])
265{
266 return secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, schannel_key, 16);
267}
268
269bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16])
270{
271 size_t size = 0;
272 uint8_t *key;
273
274 key = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &size);
275 if (key == NULL) {
276 return false;
277 }
278
279 if (size != 16) {
280 SAFE_FREE(key);
281 return false;
282 }
283
284 memcpy(schannel_key, key, 16);
285 SAFE_FREE(key);
286 return true;
287}
288
289/**
290 * Form a key for fetching the machine trust account sec channel type
291 *
292 * @param domain domain name
293 *
294 * @return keystring
295 **/
296static const char *machine_sec_channel_type_keystr(const char *domain)
297{
298 char *keystr;
299
300 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
301 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
302 domain);
303 SMB_ASSERT(keystr != NULL);
304 return keystr;
305}
306
307/**
308 * Form a key for fetching the machine trust account last change time
309 *
310 * @param domain domain name
311 *
312 * @return keystring
313 **/
314static const char *machine_last_change_time_keystr(const char *domain)
315{
316 char *keystr;
317
318 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
319 SECRETS_MACHINE_LAST_CHANGE_TIME,
320 domain);
321 SMB_ASSERT(keystr != NULL);
322 return keystr;
323}
324
325
326/**
327 * Form a key for fetching the machine previous trust account password
328 *
329 * @param domain domain name
330 *
331 * @return keystring
332 **/
333static const char *machine_prev_password_keystr(const char *domain)
334{
335 char *keystr;
336
337 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
338 SECRETS_MACHINE_PASSWORD_PREV, domain);
339 SMB_ASSERT(keystr != NULL);
340 return keystr;
341}
342
343/**
344 * Form a key for fetching the machine trust account password
345 *
346 * @param domain domain name
347 *
348 * @return keystring
349 **/
350static const char *machine_password_keystr(const char *domain)
351{
352 char *keystr;
353
354 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
355 SECRETS_MACHINE_PASSWORD, domain);
356 SMB_ASSERT(keystr != NULL);
357 return keystr;
358}
359
360/**
361 * Form a key for fetching the machine trust account password
362 *
363 * @param domain domain name
364 *
365 * @return stored password's key
366 **/
367static const char *trust_keystr(const char *domain)
368{
369 char *keystr;
370
371 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
372 SECRETS_MACHINE_ACCT_PASS, domain);
373 SMB_ASSERT(keystr != NULL);
374 return keystr;
375}
376
377/**
378 * Form a key for fetching a trusted domain password
379 *
380 * @param domain trusted domain name
381 *
382 * @return stored password's key
383 **/
384static char *trustdom_keystr(const char *domain)
385{
386 char *keystr;
387
388 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
389 SECRETS_DOMTRUST_ACCT_PASS,
390 domain);
391 SMB_ASSERT(keystr != NULL);
392 return keystr;
393}
394
395/************************************************************************
396 Lock the trust password entry.
397************************************************************************/
398
399void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
400{
401 if (!secrets_init()) {
402 return NULL;
403 }
404
405 return db_ctx->fetch_locked(
406 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
407}
408
409/************************************************************************
410 Routine to get the default secure channel type for trust accounts
411************************************************************************/
412
413enum netr_SchannelType get_default_sec_channel(void)
414{
415 if (lp_server_role() == ROLE_DOMAIN_BDC ||
416 lp_server_role() == ROLE_DOMAIN_PDC) {
417 return SEC_CHAN_BDC;
418 } else {
419 return SEC_CHAN_WKSTA;
420 }
421}
422
423/************************************************************************
424 Routine to get the trust account password for a domain.
425 This only tries to get the legacy hashed version of the password.
426 The user of this function must have locked the trust password file using
427 the above secrets_lock_trust_account_password().
428************************************************************************/
429
430bool secrets_fetch_trust_account_password_legacy(const char *domain,
431 uint8 ret_pwd[16],
432 time_t *pass_last_set_time,
433 enum netr_SchannelType *channel)
434{
435 struct machine_acct_pass *pass;
436 size_t size = 0;
437
438 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
439 trust_keystr(domain), &size))) {
440 DEBUG(5, ("secrets_fetch failed!\n"));
441 return False;
442 }
443
444 if (size != sizeof(*pass)) {
445 DEBUG(0, ("secrets were of incorrect size!\n"));
446 SAFE_FREE(pass);
447 return False;
448 }
449
450 if (pass_last_set_time) {
451 *pass_last_set_time = pass->mod_time;
452 }
453 memcpy(ret_pwd, pass->hash, 16);
454
455 if (channel) {
456 *channel = get_default_sec_channel();
457 }
458
459 /* Test if machine password has expired and needs to be changed */
460 if (lp_machine_password_timeout()) {
461 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
462 (time_t)lp_machine_password_timeout())) {
463 global_machine_password_needs_changing = True;
464 }
465 }
466
467 SAFE_FREE(pass);
468 return True;
469}
470
471/************************************************************************
472 Routine to get the trust account password for a domain.
473 The user of this function must have locked the trust password file using
474 the above secrets_lock_trust_account_password().
475************************************************************************/
476
477bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
478 time_t *pass_last_set_time,
479 enum netr_SchannelType *channel)
480{
481 char *plaintext;
482
483 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
484 channel);
485 if (plaintext) {
486 DEBUG(4,("Using cleartext machine password\n"));
487 E_md4hash(plaintext, ret_pwd);
488 SAFE_FREE(plaintext);
489 return True;
490 }
491
492 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
493 pass_last_set_time,
494 channel);
495}
496
497/************************************************************************
498 Routine to get account password to trusted domain
499************************************************************************/
500
501bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
502 DOM_SID *sid, time_t *pass_last_set_time)
503{
504 struct TRUSTED_DOM_PASS pass;
505 enum ndr_err_code ndr_err;
506
507 /* unpacking structures */
508 DATA_BLOB blob;
509
510 /* fetching trusted domain password structure */
511 if (!(blob.data = (uint8_t *)secrets_fetch(trustdom_keystr(domain),
512 &blob.length))) {
513 DEBUG(5, ("secrets_fetch failed!\n"));
514 return False;
515 }
516
517 /* unpack trusted domain password */
518 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &pass,
519 (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
520 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
521 return false;
522 }
523
524 SAFE_FREE(blob.data);
525
526 /* the trust's password */
527 if (pwd) {
528 *pwd = SMB_STRDUP(pass.pass);
529 if (!*pwd) {
530 return False;
531 }
532 }
533
534 /* last change time */
535 if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
536
537 /* domain sid */
538 if (sid != NULL) sid_copy(sid, &pass.domain_sid);
539
540 return True;
541}
542
543/**
544 * Routine to store the password for trusted domain
545 *
546 * @param domain remote domain name
547 * @param pwd plain text password of trust relationship
548 * @param sid remote domain sid
549 *
550 * @return true if succeeded
551 **/
552
553bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
554 const DOM_SID *sid)
555{
556 bool ret;
557
558 /* packing structures */
559 DATA_BLOB blob;
560 enum ndr_err_code ndr_err;
561 struct TRUSTED_DOM_PASS pass;
562 ZERO_STRUCT(pass);
563
564 pass.uni_name = domain;
565 pass.uni_name_len = strlen(domain)+1;
566
567 /* last change time */
568 pass.mod_time = time(NULL);
569
570 /* password of the trust */
571 pass.pass_len = strlen(pwd);
572 pass.pass = pwd;
573
574 /* domain sid */
575 sid_copy(&pass.domain_sid, sid);
576
577 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), NULL, &pass,
578 (ndr_push_flags_fn_t)ndr_push_TRUSTED_DOM_PASS);
579 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
580 return false;
581 }
582
583 ret = secrets_store(trustdom_keystr(domain), blob.data, blob.length);
584
585 data_blob_free(&blob);
586
587 return ret;
588}
589
590/************************************************************************
591 Routine to delete the old plaintext machine account password if any
592************************************************************************/
593
594static bool secrets_delete_prev_machine_password(const char *domain)
595{
596 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
597 if (oldpass == NULL) {
598 return true;
599 }
600 SAFE_FREE(oldpass);
601 return secrets_delete(machine_prev_password_keystr(domain));
602}
603
604/************************************************************************
605 Routine to delete the plaintext machine account password and old
606 password if any
607************************************************************************/
608
609bool secrets_delete_machine_password(const char *domain)
610{
611 if (!secrets_delete_prev_machine_password(domain)) {
612 return false;
613 }
614 return secrets_delete(machine_password_keystr(domain));
615}
616
617/************************************************************************
618 Routine to delete the plaintext machine account password, old password,
619 sec channel type and last change time from secrets database
620************************************************************************/
621
622bool secrets_delete_machine_password_ex(const char *domain)
623{
624 if (!secrets_delete_prev_machine_password(domain)) {
625 return false;
626 }
627 if (!secrets_delete(machine_password_keystr(domain))) {
628 return false;
629 }
630 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
631 return false;
632 }
633 return secrets_delete(machine_last_change_time_keystr(domain));
634}
635
636/************************************************************************
637 Routine to delete the domain sid
638************************************************************************/
639
640bool secrets_delete_domain_sid(const char *domain)
641{
642 return secrets_delete(domain_sid_keystr(domain));
643}
644
645/************************************************************************
646 Routine to store the previous machine password (by storing the current password
647 as the old)
648************************************************************************/
649
650static bool secrets_store_prev_machine_password(const char *domain)
651{
652 char *oldpass;
653 bool ret;
654
655 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
656 if (oldpass == NULL) {
657 return true;
658 }
659 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
660 SAFE_FREE(oldpass);
661 return ret;
662}
663
664/************************************************************************
665 Routine to set the plaintext machine account password for a realm
666 the password is assumed to be a null terminated ascii string.
667 Before storing
668************************************************************************/
669
670bool secrets_store_machine_password(const char *pass, const char *domain,
671 enum netr_SchannelType sec_channel)
672{
673 bool ret;
674 uint32 last_change_time;
675 uint32 sec_channel_type;
676
677 if (!secrets_store_prev_machine_password(domain)) {
678 return false;
679 }
680
681 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
682 if (!ret)
683 return ret;
684
685 SIVAL(&last_change_time, 0, time(NULL));
686 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
687
688 SIVAL(&sec_channel_type, 0, sec_channel);
689 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
690
691 return ret;
692}
693
694
695/************************************************************************
696 Routine to fetch the previous plaintext machine account password for a realm
697 the password is assumed to be a null terminated ascii string.
698************************************************************************/
699
700char *secrets_fetch_prev_machine_password(const char *domain)
701{
702 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
703}
704
705/************************************************************************
706 Routine to fetch the plaintext machine account password for a realm
707 the password is assumed to be a null terminated ascii string.
708************************************************************************/
709
710char *secrets_fetch_machine_password(const char *domain,
711 time_t *pass_last_set_time,
712 enum netr_SchannelType *channel)
713{
714 char *ret;
715 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
716
717 if (pass_last_set_time) {
718 size_t size;
719 uint32 *last_set_time;
720 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
721 if (last_set_time) {
722 *pass_last_set_time = IVAL(last_set_time,0);
723 SAFE_FREE(last_set_time);
724 } else {
725 *pass_last_set_time = 0;
726 }
727 }
728
729 if (channel) {
730 size_t size;
731 uint32 *channel_type;
732 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
733 if (channel_type) {
734 *channel = IVAL(channel_type,0);
735 SAFE_FREE(channel_type);
736 } else {
737 *channel = get_default_sec_channel();
738 }
739 }
740
741 return ret;
742}
743
744/************************************************************************
745 Routine to delete the password for trusted domain
746************************************************************************/
747
748bool trusted_domain_password_delete(const char *domain)
749{
750 return secrets_delete(trustdom_keystr(domain));
751}
752
753bool secrets_store_ldap_pw(const char* dn, char* pw)
754{
755 char *key = NULL;
756 bool ret;
757
758 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
759 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
760 return False;
761 }
762
763 ret = secrets_store(key, pw, strlen(pw)+1);
764
765 SAFE_FREE(key);
766 return ret;
767}
768
769/*******************************************************************
770 Find the ldap password.
771******************************************************************/
772
773bool fetch_ldap_pw(char **dn, char** pw)
774{
775 char *key = NULL;
776 size_t size = 0;
777
778 *dn = smb_xstrdup(lp_ldap_admin_dn());
779
780 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
781 SAFE_FREE(*dn);
782 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
783 return false;
784 }
785
786 *pw=(char *)secrets_fetch(key, &size);
787 SAFE_FREE(key);
788
789 if (!size) {
790 /* Upgrade 2.2 style entry */
791 char *p;
792 char* old_style_key = SMB_STRDUP(*dn);
793 char *data;
794 fstring old_style_pw;
795
796 if (!old_style_key) {
797 DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
798 return False;
799 }
800
801 for (p=old_style_key; *p; p++)
802 if (*p == ',') *p = '/';
803
804 data=(char *)secrets_fetch(old_style_key, &size);
805 if ((data == NULL) || (size < sizeof(old_style_pw))) {
806 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
807 SAFE_FREE(old_style_key);
808 SAFE_FREE(*dn);
809 SAFE_FREE(data);
810 return False;
811 }
812
813 size = MIN(size, sizeof(fstring)-1);
814 strncpy(old_style_pw, data, size);
815 old_style_pw[size] = 0;
816
817 SAFE_FREE(data);
818
819 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
820 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
821 SAFE_FREE(old_style_key);
822 SAFE_FREE(*dn);
823 return False;
824 }
825 if (!secrets_delete(old_style_key)) {
826 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
827 }
828
829 SAFE_FREE(old_style_key);
830
831 *pw = smb_xstrdup(old_style_pw);
832 }
833
834 return True;
835}
836
837/**
838 * Get trusted domains info from secrets.tdb.
839 **/
840
841struct list_trusted_domains_state {
842 uint32 num_domains;
843 struct trustdom_info **domains;
844};
845
846static int list_trusted_domain(struct db_record *rec, void *private_data)
847{
848 const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
849 struct TRUSTED_DOM_PASS pass;
850 enum ndr_err_code ndr_err;
851 DATA_BLOB blob;
852 struct trustdom_info *dom_info;
853
854 struct list_trusted_domains_state *state =
855 (struct list_trusted_domains_state *)private_data;
856
857 if ((rec->key.dsize < prefix_len)
858 || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
859 prefix_len) != 0)) {
860 return 0;
861 }
862
863 blob = data_blob_const(rec->value.dptr, rec->value.dsize);
864
865 ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &pass,
866 (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
867 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
868 return false;
869 }
870
871 if (pass.domain_sid.num_auths != 4) {
872 DEBUG(0, ("SID %s is not a domain sid, has %d "
873 "auths instead of 4\n",
874 sid_string_dbg(&pass.domain_sid),
875 pass.domain_sid.num_auths));
876 return 0;
877 }
878
879 if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
880 DEBUG(0, ("talloc failed\n"));
881 return 0;
882 }
883
884 dom_info->name = talloc_strdup(dom_info, pass.uni_name);
885 if (!dom_info->name) {
886 TALLOC_FREE(dom_info);
887 return 0;
888 }
889
890 sid_copy(&dom_info->sid, &pass.domain_sid);
891
892 ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
893 &state->domains, &state->num_domains);
894
895 if (state->domains == NULL) {
896 state->num_domains = 0;
897 return -1;
898 }
899 return 0;
900}
901
902NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
903 struct trustdom_info ***domains)
904{
905 struct list_trusted_domains_state state;
906
907 secrets_init();
908
909 if (db_ctx == NULL) {
910 return NT_STATUS_ACCESS_DENIED;
911 }
912
913 state.num_domains = 0;
914
915 /*
916 * Make sure that a talloc context for the trustdom_info structs
917 * exists
918 */
919
920 if (!(state.domains = TALLOC_ARRAY(
921 mem_ctx, struct trustdom_info *, 1))) {
922 return NT_STATUS_NO_MEMORY;
923 }
924
925 db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
926
927 *num_domains = state.num_domains;
928 *domains = state.domains;
929 return NT_STATUS_OK;
930}
931
932/*******************************************************************************
933 Store a complete AFS keyfile into secrets.tdb.
934*******************************************************************************/
935
936bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
937{
938 fstring key;
939
940 if ((cell == NULL) || (keyfile == NULL))
941 return False;
942
943 if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
944 return False;
945
946 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
947 return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
948}
949
950/*******************************************************************************
951 Fetch the current (highest) AFS key from secrets.tdb
952*******************************************************************************/
953bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
954{
955 fstring key;
956 struct afs_keyfile *keyfile;
957 size_t size = 0;
958 uint32 i;
959
960 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
961
962 keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
963
964 if (keyfile == NULL)
965 return False;
966
967 if (size != sizeof(struct afs_keyfile)) {
968 SAFE_FREE(keyfile);
969 return False;
970 }
971
972 i = ntohl(keyfile->nkeys);
973
974 if (i > SECRETS_AFS_MAXKEYS) {
975 SAFE_FREE(keyfile);
976 return False;
977 }
978
979 *result = keyfile->entry[i-1];
980
981 result->kvno = ntohl(result->kvno);
982
983 SAFE_FREE(keyfile);
984
985 return True;
986}
987
988/******************************************************************************
989 When kerberos is not available, choose between anonymous or
990 authenticated connections.
991
992 We need to use an authenticated connection if DCs have the
993 RestrictAnonymous registry entry set > 0, or the "Additional
994 restrictions for anonymous connections" set in the win2k Local
995 Security Policy.
996
997 Caller to free() result in domain, username, password
998*******************************************************************************/
999void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
1000{
1001 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
1002 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
1003 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
1004
1005 if (*username && **username) {
1006
1007 if (!*domain || !**domain)
1008 *domain = smb_xstrdup(lp_workgroup());
1009
1010 if (!*password || !**password)
1011 *password = smb_xstrdup("");
1012
1013 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
1014 *domain, *username));
1015
1016 } else {
1017 DEBUG(3, ("IPC$ connections done anonymously\n"));
1018 *username = smb_xstrdup("");
1019 *domain = smb_xstrdup("");
1020 *password = smb_xstrdup("");
1021 }
1022}
1023
1024bool secrets_store_generic(const char *owner, const char *key, const char *secret)
1025{
1026 char *tdbkey = NULL;
1027 bool ret;
1028
1029 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1030 DEBUG(0, ("asprintf failed!\n"));
1031 return False;
1032 }
1033
1034 ret = secrets_store(tdbkey, secret, strlen(secret)+1);
1035
1036 SAFE_FREE(tdbkey);
1037 return ret;
1038}
1039
1040bool secrets_delete_generic(const char *owner, const char *key)
1041{
1042 char *tdbkey = NULL;
1043 bool ret;
1044
1045 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1046 DEBUG(0, ("asprintf failed!\n"));
1047 return False;
1048 }
1049
1050 ret = secrets_delete(tdbkey);
1051
1052 SAFE_FREE(tdbkey);
1053 return ret;
1054}
1055
1056/*******************************************************************
1057 Find the ldap password.
1058******************************************************************/
1059
1060char *secrets_fetch_generic(const char *owner, const char *key)
1061{
1062 char *secret = NULL;
1063 char *tdbkey = NULL;
1064
1065 if (( ! owner) || ( ! key)) {
1066 DEBUG(1, ("Invalid Paramters"));
1067 return NULL;
1068 }
1069
1070 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1071 DEBUG(0, ("Out of memory!\n"));
1072 return NULL;
1073 }
1074
1075 secret = (char *)secrets_fetch(tdbkey, NULL);
1076 SAFE_FREE(tdbkey);
1077
1078 return secret;
1079}
1080
Note: See TracBrowser for help on using the repository browser.