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

Last change on this file since 77 was 77, checked in by Paul Smedley, 18 years ago

Update trunk to 3.2.0pre1

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