source: trunk/samba/source/passdb/secrets.c@ 133

Last change on this file since 133 was 133, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0pre3

File size: 33.0 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
27#undef DBGC_CLASS
28#define DBGC_CLASS DBGC_PASSDB
29
30static struct db_context *db_ctx;
31
32/* Urrrg. global.... */
33bool global_machine_password_needs_changing;
34
35/**
36 * Use a TDB to store an incrementing random seed.
37 *
38 * Initialised to the current pid, the very first time Samba starts,
39 * and incremented by one each time it is needed.
40 *
41 * @note Not called by systems with a working /dev/urandom.
42 */
43static void get_rand_seed(int *new_seed)
44{
45 *new_seed = sys_getpid();
46 if (db_ctx) {
47 dbwrap_change_int32_atomic(db_ctx, "INFO/random_seed",
48 new_seed, 1);
49 }
50}
51
52/* open up the secrets database */
53bool secrets_init(void)
54{
55 char *fname = NULL;
56 unsigned char dummy;
57
58 if (db_ctx != NULL)
59 return True;
60
61 fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb",
62 lp_private_dir());
63 if (fname == NULL) {
64 return false;
65 }
66
67 db_ctx = db_open_trans(NULL, fname, 0,
68 TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
69
70 if (db_ctx == NULL) {
71 DEBUG(0,("Failed to open %s\n", fname));
72 TALLOC_FREE(fname);
73 return False;
74 }
75
76 TALLOC_FREE(fname);
77
78 /**
79 * Set a reseed function for the crypto random generator
80 *
81 * This avoids a problem where systems without /dev/urandom
82 * could send the same challenge to multiple clients
83 */
84 set_rand_reseed_callback(get_rand_seed);
85
86 /* Ensure that the reseed is done now, while we are root, etc */
87 generate_random_buffer(&dummy, sizeof(dummy));
88
89 return True;
90}
91
92struct db_context *secrets_db_ctx(void)
93{
94 if (!secrets_init()) {
95 return NULL;
96 }
97
98 return db_ctx;
99}
100
101/*
102 * close secrets.tdb
103 */
104void secrets_shutdown(void)
105{
106 TALLOC_FREE(db_ctx);
107}
108
109/* read a entry from the secrets database - the caller must free the result
110 if size is non-null then the size of the entry is put in there
111 */
112void *secrets_fetch(const char *key, size_t *size)
113{
114 TDB_DATA dbuf;
115 void *result;
116
117 if (!secrets_init()) {
118 return NULL;
119 }
120
121 if (db_ctx->fetch(db_ctx, talloc_tos(), string_tdb_data(key),
122 &dbuf) != 0) {
123 return NULL;
124 }
125
126 result = memdup(dbuf.dptr, dbuf.dsize);
127 if (result == NULL) {
128 return NULL;
129 }
130 TALLOC_FREE(dbuf.dptr);
131
132 if (size) {
133 *size = dbuf.dsize;
134 }
135
136 return result;
137}
138
139/* store a secrets entry
140 */
141bool secrets_store(const char *key, const void *data, size_t size)
142{
143 NTSTATUS status;
144
145 if (!secrets_init()) {
146 return false;
147 }
148
149 status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
150 make_tdb_data((const uint8 *)data, size),
151 TDB_REPLACE);
152 return NT_STATUS_IS_OK(status);
153}
154
155
156/* delete a secets database entry
157 */
158bool secrets_delete(const char *key)
159{
160 NTSTATUS status;
161 if (!secrets_init()) {
162 return false;
163 }
164
165 status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
166
167 return NT_STATUS_IS_OK(status);
168}
169
170/**
171 * Form a key for fetching the domain sid
172 *
173 * @param domain domain name
174 *
175 * @return keystring
176 **/
177static const char *domain_sid_keystr(const char *domain)
178{
179 char *keystr;
180
181 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
182 SECRETS_DOMAIN_SID, domain);
183 SMB_ASSERT(keystr != NULL);
184 return keystr;
185}
186
187bool secrets_store_domain_sid(const char *domain, const DOM_SID *sid)
188{
189 bool ret;
190
191 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(DOM_SID));
192
193 /* Force a re-query, in case we modified our domain */
194 if (ret)
195 reset_global_sam_sid();
196 return ret;
197}
198
199bool secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
200{
201 DOM_SID *dyn_sid;
202 size_t size = 0;
203
204 dyn_sid = (DOM_SID *)secrets_fetch(domain_sid_keystr(domain), &size);
205
206 if (dyn_sid == NULL)
207 return False;
208
209 if (size != sizeof(DOM_SID)) {
210 SAFE_FREE(dyn_sid);
211 return False;
212 }
213
214 *sid = *dyn_sid;
215 SAFE_FREE(dyn_sid);
216 return True;
217}
218
219bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
220{
221 fstring key;
222
223 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
224 strupper_m(key);
225 return secrets_store(key, guid, sizeof(struct GUID));
226}
227
228bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
229{
230 struct GUID *dyn_guid;
231 fstring key;
232 size_t size = 0;
233 struct GUID new_guid;
234
235 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
236 strupper_m(key);
237 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
238
239 if (!dyn_guid) {
240 if (lp_server_role() == ROLE_DOMAIN_PDC) {
241 smb_uuid_generate_random(&new_guid);
242 if (!secrets_store_domain_guid(domain, &new_guid))
243 return False;
244 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
245 }
246 if (dyn_guid == NULL) {
247 return False;
248 }
249 }
250
251 if (size != sizeof(struct GUID)) {
252 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
253 SAFE_FREE(dyn_guid);
254 return False;
255 }
256
257 *guid = *dyn_guid;
258 SAFE_FREE(dyn_guid);
259 return True;
260}
261
262/**
263 * Form a key for fetching the machine trust account sec channel type
264 *
265 * @param domain domain name
266 *
267 * @return keystring
268 **/
269static const char *machine_sec_channel_type_keystr(const char *domain)
270{
271 char *keystr;
272
273 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
274 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
275 domain);
276 SMB_ASSERT(keystr != NULL);
277 return keystr;
278}
279
280/**
281 * Form a key for fetching the machine trust account last change time
282 *
283 * @param domain domain name
284 *
285 * @return keystring
286 **/
287static const char *machine_last_change_time_keystr(const char *domain)
288{
289 char *keystr;
290
291 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
292 SECRETS_MACHINE_LAST_CHANGE_TIME,
293 domain);
294 SMB_ASSERT(keystr != NULL);
295 return keystr;
296}
297
298
299/**
300 * Form a key for fetching the machine trust account password
301 *
302 * @param domain domain name
303 *
304 * @return keystring
305 **/
306static const char *machine_password_keystr(const char *domain)
307{
308 char *keystr;
309
310 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
311 SECRETS_MACHINE_PASSWORD, domain);
312 SMB_ASSERT(keystr != NULL);
313 return keystr;
314}
315
316/**
317 * Form a key for fetching the machine trust account password
318 *
319 * @param domain domain name
320 *
321 * @return stored password's key
322 **/
323static const char *trust_keystr(const char *domain)
324{
325 char *keystr;
326
327 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
328 SECRETS_MACHINE_ACCT_PASS, domain);
329 SMB_ASSERT(keystr != NULL);
330 return keystr;
331}
332
333/**
334 * Form a key for fetching a trusted domain password
335 *
336 * @param domain trusted domain name
337 *
338 * @return stored password's key
339 **/
340static char *trustdom_keystr(const char *domain)
341{
342 char *keystr;
343
344 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
345 SECRETS_DOMTRUST_ACCT_PASS,
346 domain);
347 SMB_ASSERT(keystr != NULL);
348 return keystr;
349}
350
351/************************************************************************
352 Lock the trust password entry.
353************************************************************************/
354
355void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
356{
357 if (!secrets_init()) {
358 return NULL;
359 }
360
361 return db_ctx->fetch_locked(
362 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
363}
364
365/************************************************************************
366 Routine to get the default secure channel type for trust accounts
367************************************************************************/
368
369uint32 get_default_sec_channel(void)
370{
371 if (lp_server_role() == ROLE_DOMAIN_BDC ||
372 lp_server_role() == ROLE_DOMAIN_PDC) {
373 return SEC_CHAN_BDC;
374 } else {
375 return SEC_CHAN_WKSTA;
376 }
377}
378
379/************************************************************************
380 Routine to get the trust account password for a domain.
381 This only tries to get the legacy hashed version of the password.
382 The user of this function must have locked the trust password file using
383 the above secrets_lock_trust_account_password().
384************************************************************************/
385
386bool secrets_fetch_trust_account_password_legacy(const char *domain,
387 uint8 ret_pwd[16],
388 time_t *pass_last_set_time,
389 uint32 *channel)
390{
391 struct machine_acct_pass *pass;
392 size_t size = 0;
393
394 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
395 trust_keystr(domain), &size))) {
396 DEBUG(5, ("secrets_fetch failed!\n"));
397 return False;
398 }
399
400 if (size != sizeof(*pass)) {
401 DEBUG(0, ("secrets were of incorrect size!\n"));
402 return False;
403 }
404
405 if (pass_last_set_time) {
406 *pass_last_set_time = pass->mod_time;
407 }
408 memcpy(ret_pwd, pass->hash, 16);
409
410 if (channel) {
411 *channel = get_default_sec_channel();
412 }
413
414 /* Test if machine password has expired and needs to be changed */
415 if (lp_machine_password_timeout()) {
416 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
417 (time_t)lp_machine_password_timeout())) {
418 global_machine_password_needs_changing = True;
419 }
420 }
421
422 SAFE_FREE(pass);
423 return True;
424}
425
426/************************************************************************
427 Routine to get the trust account password for a domain.
428 The user of this function must have locked the trust password file using
429 the above secrets_lock_trust_account_password().
430************************************************************************/
431
432bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
433 time_t *pass_last_set_time,
434 uint32 *channel)
435{
436 char *plaintext;
437
438 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
439 channel);
440 if (plaintext) {
441 DEBUG(4,("Using cleartext machine password\n"));
442 E_md4hash(plaintext, ret_pwd);
443 SAFE_FREE(plaintext);
444 return True;
445 }
446
447 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
448 pass_last_set_time,
449 channel);
450}
451
452/**
453 * Pack SID passed by pointer
454 *
455 * @param pack_buf pointer to buffer which is to be filled with packed data
456 * @param bufsize size of packing buffer
457 * @param sid pointer to sid to be packed
458 *
459 * @return length of the packed representation of the whole structure
460 **/
461static size_t tdb_sid_pack(uint8 *pack_buf, int bufsize, DOM_SID* sid)
462{
463 int idx;
464 size_t len = 0;
465 uint8 *p = pack_buf;
466 int remaining_space = pack_buf ? bufsize : 0;
467
468 if (!sid) {
469 return -1;
470 }
471
472 len += tdb_pack(p, remaining_space, "bb", sid->sid_rev_num,
473 sid->num_auths);
474 if (pack_buf) {
475 p = pack_buf + len;
476 remaining_space = bufsize - len;
477 }
478
479 for (idx = 0; idx < 6; idx++) {
480 len += tdb_pack(p, remaining_space, "b",
481 sid->id_auth[idx]);
482 if (pack_buf) {
483 p = pack_buf + len;
484 remaining_space = bufsize - len;
485 }
486 }
487
488 for (idx = 0; idx < MAXSUBAUTHS; idx++) {
489 len += tdb_pack(p, remaining_space, "d",
490 sid->sub_auths[idx]);
491 if (pack_buf) {
492 p = pack_buf + len;
493 remaining_space = bufsize - len;
494 }
495 }
496
497 return len;
498}
499
500/**
501 * Unpack SID into a pointer
502 *
503 * @param pack_buf pointer to buffer with packed representation
504 * @param bufsize size of the buffer
505 * @param sid pointer to sid structure to be filled with unpacked data
506 *
507 * @return size of structure unpacked from buffer
508 **/
509static size_t tdb_sid_unpack(uint8 *pack_buf, int bufsize, DOM_SID* sid)
510{
511 int idx, len = 0;
512
513 if (!sid || !pack_buf) return -1;
514
515 len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
516 &sid->sid_rev_num, &sid->num_auths);
517
518 for (idx = 0; idx < 6; idx++) {
519 len += tdb_unpack(pack_buf + len, bufsize - len, "b",
520 &sid->id_auth[idx]);
521 }
522
523 for (idx = 0; idx < MAXSUBAUTHS; idx++) {
524 len += tdb_unpack(pack_buf + len, bufsize - len, "d",
525 &sid->sub_auths[idx]);
526 }
527
528 return len;
529}
530
531/**
532 * Pack TRUSTED_DOM_PASS passed by pointer
533 *
534 * @param pack_buf pointer to buffer which is to be filled with packed data
535 * @param bufsize size of the buffer
536 * @param pass pointer to trusted domain password to be packed
537 *
538 * @return length of the packed representation of the whole structure
539 **/
540static size_t tdb_trusted_dom_pass_pack(uint8 *pack_buf, int bufsize,
541 TRUSTED_DOM_PASS* pass)
542{
543 int idx, len = 0;
544 uint8 *p = pack_buf;
545 int remaining_space = pack_buf ? bufsize : 0;
546
547 if (!pass) {
548 return -1;
549 }
550
551 /* packing unicode domain name and password */
552 len += tdb_pack(p, remaining_space, "d",
553 pass->uni_name_len);
554 if (pack_buf) {
555 p = pack_buf + len;
556 remaining_space = bufsize - len;
557 }
558
559 for (idx = 0; idx < 32; idx++) {
560 len += tdb_pack(p, remaining_space, "w",
561 pass->uni_name[idx]);
562 if (pack_buf) {
563 p = pack_buf + len;
564 remaining_space = bufsize - len;
565 }
566 }
567
568 len += tdb_pack(p, remaining_space, "dPd", pass->pass_len,
569 pass->pass, pass->mod_time);
570 if (pack_buf) {
571 p = pack_buf + len;
572 remaining_space = bufsize - len;
573 }
574
575 /* packing SID structure */
576 len += tdb_sid_pack(p, remaining_space, &pass->domain_sid);
577 if (pack_buf) {
578 p = pack_buf + len;
579 remaining_space = bufsize - len;
580 }
581
582 return len;
583}
584
585
586/**
587 * Unpack TRUSTED_DOM_PASS passed by pointer
588 *
589 * @param pack_buf pointer to buffer with packed representation
590 * @param bufsize size of the buffer
591 * @param pass pointer to trusted domain password to be filled with unpacked data
592 *
593 * @return size of structure unpacked from buffer
594 **/
595static size_t tdb_trusted_dom_pass_unpack(uint8 *pack_buf, int bufsize,
596 TRUSTED_DOM_PASS* pass)
597{
598 int idx, len = 0;
599 char *passp = NULL;
600
601 if (!pack_buf || !pass) return -1;
602
603 /* unpack unicode domain name and plaintext password */
604 len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
605
606 for (idx = 0; idx < 32; idx++)
607 len += tdb_unpack(pack_buf + len, bufsize - len, "w",
608 &pass->uni_name[idx]);
609
610 len += tdb_unpack(pack_buf + len, bufsize - len, "dPd",
611 &pass->pass_len, &passp, &pass->mod_time);
612 if (passp) {
613 fstrcpy(pass->pass, passp);
614 }
615 SAFE_FREE(passp);
616
617 /* unpack domain sid */
618 len += tdb_sid_unpack(pack_buf + len, bufsize - len,
619 &pass->domain_sid);
620
621 return len;
622}
623
624/************************************************************************
625 Routine to get account password to trusted domain
626************************************************************************/
627
628bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
629 DOM_SID *sid, time_t *pass_last_set_time)
630{
631 struct trusted_dom_pass pass;
632 size_t size = 0;
633
634 /* unpacking structures */
635 uint8 *pass_buf;
636 int pass_len = 0;
637
638 ZERO_STRUCT(pass);
639
640 /* fetching trusted domain password structure */
641 if (!(pass_buf = (uint8 *)secrets_fetch(trustdom_keystr(domain),
642 &size))) {
643 DEBUG(5, ("secrets_fetch failed!\n"));
644 return False;
645 }
646
647 /* unpack trusted domain password */
648 pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass);
649 SAFE_FREE(pass_buf);
650
651 if (pass_len != size) {
652 DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
653 return False;
654 }
655
656 /* the trust's password */
657 if (pwd) {
658 *pwd = SMB_STRDUP(pass.pass);
659 if (!*pwd) {
660 return False;
661 }
662 }
663
664 /* last change time */
665 if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
666
667 /* domain sid */
668 if (sid != NULL) sid_copy(sid, &pass.domain_sid);
669
670 return True;
671}
672
673/**
674 * Routine to store the password for trusted domain
675 *
676 * @param domain remote domain name
677 * @param pwd plain text password of trust relationship
678 * @param sid remote domain sid
679 *
680 * @return true if succeeded
681 **/
682
683bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
684 const DOM_SID *sid)
685{
686 smb_ucs2_t *uni_dom_name;
687 bool ret;
688
689 /* packing structures */
690 uint8 *pass_buf = NULL;
691 int pass_len = 0;
692
693 struct trusted_dom_pass pass;
694 ZERO_STRUCT(pass);
695
696 if (push_ucs2_allocate(&uni_dom_name, domain) == (size_t)-1) {
697 DEBUG(0, ("Could not convert domain name %s to unicode\n",
698 domain));
699 return False;
700 }
701
702 strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
703 pass.uni_name_len = strlen_w(uni_dom_name)+1;
704 SAFE_FREE(uni_dom_name);
705
706 /* last change time */
707 pass.mod_time = time(NULL);
708
709 /* password of the trust */
710 pass.pass_len = strlen(pwd);
711 fstrcpy(pass.pass, pwd);
712
713 /* domain sid */
714 sid_copy(&pass.domain_sid, sid);
715
716 /* Calculate the length. */
717 pass_len = tdb_trusted_dom_pass_pack(NULL, 0, &pass);
718 pass_buf = SMB_MALLOC_ARRAY(uint8, pass_len);
719 if (!pass_buf) {
720 return false;
721 }
722 pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_len, &pass);
723 ret = secrets_store(trustdom_keystr(domain), (void *)pass_buf,
724 pass_len);
725 SAFE_FREE(pass_buf);
726 return ret;
727}
728
729/************************************************************************
730 Routine to delete the plaintext machine account password
731************************************************************************/
732
733bool secrets_delete_machine_password(const char *domain)
734{
735 return secrets_delete(machine_password_keystr(domain));
736}
737
738/************************************************************************
739 Routine to delete the plaintext machine account password, sec channel type and
740 last change time from secrets database
741************************************************************************/
742
743bool secrets_delete_machine_password_ex(const char *domain)
744{
745 if (!secrets_delete(machine_password_keystr(domain))) {
746 return false;
747 }
748 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
749 return false;
750 }
751 return secrets_delete(machine_last_change_time_keystr(domain));
752}
753
754/************************************************************************
755 Routine to delete the domain sid
756************************************************************************/
757
758bool secrets_delete_domain_sid(const char *domain)
759{
760 return secrets_delete(domain_sid_keystr(domain));
761}
762
763/************************************************************************
764 Routine to set the plaintext machine account password for a realm
765the password is assumed to be a null terminated ascii string
766************************************************************************/
767
768bool secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
769{
770 bool ret;
771 uint32 last_change_time;
772 uint32 sec_channel_type;
773
774 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
775 if (!ret)
776 return ret;
777
778 SIVAL(&last_change_time, 0, time(NULL));
779 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
780
781 SIVAL(&sec_channel_type, 0, sec_channel);
782 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
783
784 return ret;
785}
786
787/************************************************************************
788 Routine to fetch the plaintext machine account password for a realm
789 the password is assumed to be a null terminated ascii string.
790************************************************************************/
791
792char *secrets_fetch_machine_password(const char *domain,
793 time_t *pass_last_set_time,
794 uint32 *channel)
795{
796 char *ret;
797 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
798
799 if (pass_last_set_time) {
800 size_t size;
801 uint32 *last_set_time;
802 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
803 if (last_set_time) {
804 *pass_last_set_time = IVAL(last_set_time,0);
805 SAFE_FREE(last_set_time);
806 } else {
807 *pass_last_set_time = 0;
808 }
809 }
810
811 if (channel) {
812 size_t size;
813 uint32 *channel_type;
814 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
815 if (channel_type) {
816 *channel = IVAL(channel_type,0);
817 SAFE_FREE(channel_type);
818 } else {
819 *channel = get_default_sec_channel();
820 }
821 }
822
823 return ret;
824}
825
826/************************************************************************
827 Routine to delete the password for trusted domain
828************************************************************************/
829
830bool trusted_domain_password_delete(const char *domain)
831{
832 return secrets_delete(trustdom_keystr(domain));
833}
834
835bool secrets_store_ldap_pw(const char* dn, char* pw)
836{
837 char *key = NULL;
838 bool ret;
839
840 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
841 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
842 return False;
843 }
844
845 ret = secrets_store(key, pw, strlen(pw)+1);
846
847 SAFE_FREE(key);
848 return ret;
849}
850
851/*******************************************************************
852 Find the ldap password.
853******************************************************************/
854
855bool fetch_ldap_pw(char **dn, char** pw)
856{
857 char *key = NULL;
858 size_t size = 0;
859
860 *dn = smb_xstrdup(lp_ldap_admin_dn());
861
862 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
863 SAFE_FREE(*dn);
864 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
865 }
866
867 *pw=(char *)secrets_fetch(key, &size);
868 SAFE_FREE(key);
869
870 if (!size) {
871 /* Upgrade 2.2 style entry */
872 char *p;
873 char* old_style_key = SMB_STRDUP(*dn);
874 char *data;
875 fstring old_style_pw;
876
877 if (!old_style_key) {
878 DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
879 return False;
880 }
881
882 for (p=old_style_key; *p; p++)
883 if (*p == ',') *p = '/';
884
885 data=(char *)secrets_fetch(old_style_key, &size);
886 if (!size && size < sizeof(old_style_pw)) {
887 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
888 SAFE_FREE(old_style_key);
889 SAFE_FREE(*dn);
890 return False;
891 }
892
893 size = MIN(size, sizeof(fstring)-1);
894 strncpy(old_style_pw, data, size);
895 old_style_pw[size] = 0;
896
897 SAFE_FREE(data);
898
899 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
900 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
901 SAFE_FREE(old_style_key);
902 SAFE_FREE(*dn);
903 return False;
904 }
905 if (!secrets_delete(old_style_key)) {
906 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
907 }
908
909 SAFE_FREE(old_style_key);
910
911 *pw = smb_xstrdup(old_style_pw);
912 }
913
914 return True;
915}
916
917/**
918 * Get trusted domains info from secrets.tdb.
919 **/
920
921struct list_trusted_domains_state {
922 uint32 num_domains;
923 struct trustdom_info **domains;
924};
925
926static int list_trusted_domain(struct db_record *rec, void *private_data)
927{
928 const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
929 size_t packed_size = 0;
930 struct trusted_dom_pass pass;
931 struct trustdom_info *dom_info;
932
933 struct list_trusted_domains_state *state =
934 (struct list_trusted_domains_state *)private_data;
935
936 if ((rec->key.dsize < prefix_len)
937 || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
938 prefix_len) != 0)) {
939 return 0;
940 }
941
942 packed_size = tdb_trusted_dom_pass_unpack(
943 rec->value.dptr, rec->value.dsize, &pass);
944
945 if (rec->value.dsize != packed_size) {
946 DEBUG(2, ("Secrets record is invalid!\n"));
947 return 0;
948 }
949
950 if (pass.domain_sid.num_auths != 4) {
951 DEBUG(0, ("SID %s is not a domain sid, has %d "
952 "auths instead of 4\n",
953 sid_string_dbg(&pass.domain_sid),
954 pass.domain_sid.num_auths));
955 return 0;
956 }
957
958 if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
959 DEBUG(0, ("talloc failed\n"));
960 return 0;
961 }
962
963 if (pull_ucs2_talloc(dom_info, &dom_info->name,
964 pass.uni_name) == (size_t)-1) {
965 DEBUG(2, ("pull_ucs2_talloc failed\n"));
966 TALLOC_FREE(dom_info);
967 return 0;
968 }
969
970 sid_copy(&dom_info->sid, &pass.domain_sid);
971
972 ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
973 &state->domains, &state->num_domains);
974
975 if (state->domains == NULL) {
976 state->num_domains = 0;
977 return -1;
978 }
979 return 0;
980}
981
982NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
983 struct trustdom_info ***domains)
984{
985 struct list_trusted_domains_state state;
986
987 secrets_init();
988
989 if (db_ctx == NULL) {
990 return NT_STATUS_ACCESS_DENIED;
991 }
992
993 state.num_domains = 0;
994
995 /*
996 * Make sure that a talloc context for the trustdom_info structs
997 * exists
998 */
999
1000 if (!(state.domains = TALLOC_ARRAY(
1001 mem_ctx, struct trustdom_info *, 1))) {
1002 return NT_STATUS_NO_MEMORY;
1003 }
1004
1005 db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
1006
1007 *num_domains = state.num_domains;
1008 *domains = state.domains;
1009 return NT_STATUS_OK;
1010}
1011
1012/*******************************************************************************
1013 Store a complete AFS keyfile into secrets.tdb.
1014*******************************************************************************/
1015
1016bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
1017{
1018 fstring key;
1019
1020 if ((cell == NULL) || (keyfile == NULL))
1021 return False;
1022
1023 if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
1024 return False;
1025
1026 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
1027 return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
1028}
1029
1030/*******************************************************************************
1031 Fetch the current (highest) AFS key from secrets.tdb
1032*******************************************************************************/
1033bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
1034{
1035 fstring key;
1036 struct afs_keyfile *keyfile;
1037 size_t size = 0;
1038 uint32 i;
1039
1040 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
1041
1042 keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
1043
1044 if (keyfile == NULL)
1045 return False;
1046
1047 if (size != sizeof(struct afs_keyfile)) {
1048 SAFE_FREE(keyfile);
1049 return False;
1050 }
1051
1052 i = ntohl(keyfile->nkeys);
1053
1054 if (i > SECRETS_AFS_MAXKEYS) {
1055 SAFE_FREE(keyfile);
1056 return False;
1057 }
1058
1059 *result = keyfile->entry[i-1];
1060
1061 result->kvno = ntohl(result->kvno);
1062
1063 return True;
1064}
1065
1066/******************************************************************************
1067 When kerberos is not available, choose between anonymous or
1068 authenticated connections.
1069
1070 We need to use an authenticated connection if DCs have the
1071 RestrictAnonymous registry entry set > 0, or the "Additional
1072 restrictions for anonymous connections" set in the win2k Local
1073 Security Policy.
1074
1075 Caller to free() result in domain, username, password
1076*******************************************************************************/
1077void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
1078{
1079 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
1080 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
1081 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
1082
1083 if (*username && **username) {
1084
1085 if (!*domain || !**domain)
1086 *domain = smb_xstrdup(lp_workgroup());
1087
1088 if (!*password || !**password)
1089 *password = smb_xstrdup("");
1090
1091 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
1092 *domain, *username));
1093
1094 } else {
1095 DEBUG(3, ("IPC$ connections done anonymously\n"));
1096 *username = smb_xstrdup("");
1097 *domain = smb_xstrdup("");
1098 *password = smb_xstrdup("");
1099 }
1100}
1101
1102/******************************************************************************
1103 Open or create the schannel session store tdb.
1104*******************************************************************************/
1105
1106static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
1107{
1108 TDB_DATA vers;
1109 uint32 ver;
1110 TDB_CONTEXT *tdb_sc = NULL;
1111 char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", lp_private_dir());
1112
1113 if (!fname) {
1114 return NULL;
1115 }
1116
1117 tdb_sc = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
1118
1119 if (!tdb_sc) {
1120 DEBUG(0,("open_schannel_session_store: Failed to open %s\n", fname));
1121 TALLOC_FREE(fname);
1122 return NULL;
1123 }
1124
1125 vers = tdb_fetch_bystring(tdb_sc, "SCHANNEL_STORE_VERSION");
1126 if (vers.dptr == NULL) {
1127 /* First opener, no version. */
1128 SIVAL(&ver,0,1);
1129 vers.dptr = (uint8 *)&ver;
1130 vers.dsize = 4;
1131 tdb_store_bystring(tdb_sc, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE);
1132 vers.dptr = NULL;
1133 } else if (vers.dsize == 4) {
1134 ver = IVAL(vers.dptr,0);
1135 if (ver != 1) {
1136 tdb_close(tdb_sc);
1137 tdb_sc = NULL;
1138 DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
1139 (int)ver, fname ));
1140 }
1141 } else {
1142 tdb_close(tdb_sc);
1143 tdb_sc = NULL;
1144 DEBUG(0,("open_schannel_session_store: wrong version number size %d in %s\n",
1145 (int)vers.dsize, fname ));
1146 }
1147
1148 SAFE_FREE(vers.dptr);
1149 TALLOC_FREE(fname);
1150
1151 return tdb_sc;
1152}
1153
1154/******************************************************************************
1155 Store the schannel state after an AUTH2 call.
1156 Note we must be root here.
1157*******************************************************************************/
1158
1159bool secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx,
1160 const char *remote_machine,
1161 const struct dcinfo *pdc)
1162{
1163 TDB_CONTEXT *tdb_sc = NULL;
1164 TDB_DATA value;
1165 bool ret;
1166 char *keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
1167 SECRETS_SCHANNEL_STATE,
1168 remote_machine);
1169 if (!keystr) {
1170 return False;
1171 }
1172
1173 /* Work out how large the record is. */
1174 value.dsize = tdb_pack(NULL, 0, "dBBBBBfff",
1175 pdc->sequence,
1176 8, pdc->seed_chal.data,
1177 8, pdc->clnt_chal.data,
1178 8, pdc->srv_chal.data,
1179 16, pdc->sess_key,
1180 16, pdc->mach_pw,
1181 pdc->mach_acct,
1182 pdc->remote_machine,
1183 pdc->domain);
1184
1185 value.dptr = TALLOC_ARRAY(mem_ctx, uint8, value.dsize);
1186 if (!value.dptr) {
1187 TALLOC_FREE(keystr);
1188 return False;
1189 }
1190
1191 value.dsize = tdb_pack(value.dptr, value.dsize, "dBBBBBfff",
1192 pdc->sequence,
1193 8, pdc->seed_chal.data,
1194 8, pdc->clnt_chal.data,
1195 8, pdc->srv_chal.data,
1196 16, pdc->sess_key,
1197 16, pdc->mach_pw,
1198 pdc->mach_acct,
1199 pdc->remote_machine,
1200 pdc->domain);
1201
1202 tdb_sc = open_schannel_session_store(mem_ctx);
1203 if (!tdb_sc) {
1204 TALLOC_FREE(keystr);
1205 TALLOC_FREE(value.dptr);
1206 return False;
1207 }
1208
1209 ret = (tdb_store_bystring(tdb_sc, keystr, value, TDB_REPLACE) == 0 ? True : False);
1210
1211 DEBUG(3,("secrets_store_schannel_session_info: stored schannel info with key %s\n",
1212 keystr ));
1213
1214 tdb_close(tdb_sc);
1215 TALLOC_FREE(keystr);
1216 TALLOC_FREE(value.dptr);
1217 return ret;
1218}
1219
1220/******************************************************************************
1221 Restore the schannel state on a client reconnect.
1222 Note we must be root here.
1223*******************************************************************************/
1224
1225bool secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
1226 const char *remote_machine,
1227 struct dcinfo **ppdc)
1228{
1229 TDB_CONTEXT *tdb_sc = NULL;
1230 TDB_DATA value;
1231 unsigned char *pseed_chal = NULL;
1232 unsigned char *pclnt_chal = NULL;
1233 unsigned char *psrv_chal = NULL;
1234 unsigned char *psess_key = NULL;
1235 unsigned char *pmach_pw = NULL;
1236 uint32 l1, l2, l3, l4, l5;
1237 int ret;
1238 struct dcinfo *pdc = NULL;
1239 char *keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
1240 SECRETS_SCHANNEL_STATE,
1241 remote_machine);
1242
1243 *ppdc = NULL;
1244
1245 if (!keystr) {
1246 return False;
1247 }
1248
1249 tdb_sc = open_schannel_session_store(mem_ctx);
1250 if (!tdb_sc) {
1251 TALLOC_FREE(keystr);
1252 return False;
1253 }
1254
1255 value = tdb_fetch_bystring(tdb_sc, keystr);
1256 if (!value.dptr) {
1257 DEBUG(0,("secrets_restore_schannel_session_info: Failed to find entry with key %s\n",
1258 keystr ));
1259 tdb_close(tdb_sc);
1260 return False;
1261 }
1262
1263 pdc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
1264
1265 /* Retrieve the record. */
1266 ret = tdb_unpack(value.dptr, value.dsize, "dBBBBBfff",
1267 &pdc->sequence,
1268 &l1, &pseed_chal,
1269 &l2, &pclnt_chal,
1270 &l3, &psrv_chal,
1271 &l4, &psess_key,
1272 &l5, &pmach_pw,
1273 &pdc->mach_acct,
1274 &pdc->remote_machine,
1275 &pdc->domain);
1276
1277 if (ret == -1 || l1 != 8 || l2 != 8 || l3 != 8 || l4 != 16 || l5 != 16) {
1278 /* Bad record - delete it. */
1279 tdb_delete_bystring(tdb_sc, keystr);
1280 tdb_close(tdb_sc);
1281 TALLOC_FREE(keystr);
1282 TALLOC_FREE(pdc);
1283 SAFE_FREE(pseed_chal);
1284 SAFE_FREE(pclnt_chal);
1285 SAFE_FREE(psrv_chal);
1286 SAFE_FREE(psess_key);
1287 SAFE_FREE(pmach_pw);
1288 SAFE_FREE(value.dptr);
1289 return False;
1290 }
1291
1292 tdb_close(tdb_sc);
1293
1294 memcpy(pdc->seed_chal.data, pseed_chal, 8);
1295 memcpy(pdc->clnt_chal.data, pclnt_chal, 8);
1296 memcpy(pdc->srv_chal.data, psrv_chal, 8);
1297 memcpy(pdc->sess_key, psess_key, 16);
1298 memcpy(pdc->mach_pw, pmach_pw, 16);
1299
1300 /* We know these are true so didn't bother to store them. */
1301 pdc->challenge_sent = True;
1302 pdc->authenticated = True;
1303
1304 DEBUG(3,("secrets_restore_schannel_session_info: restored schannel info key %s\n",
1305 keystr ));
1306
1307 SAFE_FREE(pseed_chal);
1308 SAFE_FREE(pclnt_chal);
1309 SAFE_FREE(psrv_chal);
1310 SAFE_FREE(psess_key);
1311 SAFE_FREE(pmach_pw);
1312
1313 TALLOC_FREE(keystr);
1314 SAFE_FREE(value.dptr);
1315
1316 *ppdc = pdc;
1317
1318 return True;
1319}
1320
1321bool secrets_store_generic(const char *owner, const char *key, const char *secret)
1322{
1323 char *tdbkey = NULL;
1324 bool ret;
1325
1326 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1327 DEBUG(0, ("asprintf failed!\n"));
1328 return False;
1329 }
1330
1331 ret = secrets_store(tdbkey, secret, strlen(secret)+1);
1332
1333 SAFE_FREE(tdbkey);
1334 return ret;
1335}
1336
1337/*******************************************************************
1338 Find the ldap password.
1339******************************************************************/
1340
1341char *secrets_fetch_generic(const char *owner, const char *key)
1342{
1343 char *secret = NULL;
1344 char *tdbkey = NULL;
1345
1346 if (( ! owner) || ( ! key)) {
1347 DEBUG(1, ("Invalid Paramters"));
1348 return NULL;
1349 }
1350
1351 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1352 DEBUG(0, ("Out of memory!\n"));
1353 return NULL;
1354 }
1355
1356 secret = (char *)secrets_fetch(tdbkey, NULL);
1357 SAFE_FREE(tdbkey);
1358
1359 return secret;
1360}
1361
Note: See TracBrowser for help on using the repository browser.