source: branches/samba-3.3.x/source/passdb/secrets.c@ 491

Last change on this file since 491 was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

File size: 33.1 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(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 SAFE_FREE(pass);
403 return False;
404 }
405
406 if (pass_last_set_time) {
407 *pass_last_set_time = pass->mod_time;
408 }
409 memcpy(ret_pwd, pass->hash, 16);
410
411 if (channel) {
412 *channel = get_default_sec_channel();
413 }
414
415 /* Test if machine password has expired and needs to be changed */
416 if (lp_machine_password_timeout()) {
417 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
418 (time_t)lp_machine_password_timeout())) {
419 global_machine_password_needs_changing = True;
420 }
421 }
422
423 SAFE_FREE(pass);
424 return True;
425}
426
427/************************************************************************
428 Routine to get the trust account password for a domain.
429 The user of this function must have locked the trust password file using
430 the above secrets_lock_trust_account_password().
431************************************************************************/
432
433bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
434 time_t *pass_last_set_time,
435 uint32 *channel)
436{
437 char *plaintext;
438
439 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
440 channel);
441 if (plaintext) {
442 DEBUG(4,("Using cleartext machine password\n"));
443 E_md4hash(plaintext, ret_pwd);
444 SAFE_FREE(plaintext);
445 return True;
446 }
447
448 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
449 pass_last_set_time,
450 channel);
451}
452
453/**
454 * Pack SID passed by pointer
455 *
456 * @param pack_buf pointer to buffer which is to be filled with packed data
457 * @param bufsize size of packing buffer
458 * @param sid pointer to sid to be packed
459 *
460 * @return length of the packed representation of the whole structure
461 **/
462static size_t tdb_sid_pack(uint8 *pack_buf, int bufsize, DOM_SID* sid)
463{
464 int idx;
465 size_t len = 0;
466 uint8 *p = pack_buf;
467 int remaining_space = pack_buf ? bufsize : 0;
468
469 if (!sid) {
470 return -1;
471 }
472
473 len += tdb_pack(p, remaining_space, "bb", sid->sid_rev_num,
474 sid->num_auths);
475 if (pack_buf) {
476 p = pack_buf + len;
477 remaining_space = bufsize - len;
478 }
479
480 for (idx = 0; idx < 6; idx++) {
481 len += tdb_pack(p, remaining_space, "b",
482 sid->id_auth[idx]);
483 if (pack_buf) {
484 p = pack_buf + len;
485 remaining_space = bufsize - len;
486 }
487 }
488
489 for (idx = 0; idx < MAXSUBAUTHS; idx++) {
490 len += tdb_pack(p, remaining_space, "d",
491 sid->sub_auths[idx]);
492 if (pack_buf) {
493 p = pack_buf + len;
494 remaining_space = bufsize - len;
495 }
496 }
497
498 return len;
499}
500
501/**
502 * Unpack SID into a pointer
503 *
504 * @param pack_buf pointer to buffer with packed representation
505 * @param bufsize size of the buffer
506 * @param sid pointer to sid structure to be filled with unpacked data
507 *
508 * @return size of structure unpacked from buffer
509 **/
510static size_t tdb_sid_unpack(uint8 *pack_buf, int bufsize, DOM_SID* sid)
511{
512 int idx, len = 0;
513
514 if (!sid || !pack_buf) return -1;
515
516 len += tdb_unpack(pack_buf + len, bufsize - len, "bb",
517 &sid->sid_rev_num, &sid->num_auths);
518
519 for (idx = 0; idx < 6; idx++) {
520 len += tdb_unpack(pack_buf + len, bufsize - len, "b",
521 &sid->id_auth[idx]);
522 }
523
524 for (idx = 0; idx < MAXSUBAUTHS; idx++) {
525 len += tdb_unpack(pack_buf + len, bufsize - len, "d",
526 &sid->sub_auths[idx]);
527 }
528
529 return len;
530}
531
532/**
533 * Pack TRUSTED_DOM_PASS passed by pointer
534 *
535 * @param pack_buf pointer to buffer which is to be filled with packed data
536 * @param bufsize size of the buffer
537 * @param pass pointer to trusted domain password to be packed
538 *
539 * @return length of the packed representation of the whole structure
540 **/
541static size_t tdb_trusted_dom_pass_pack(uint8 *pack_buf, int bufsize,
542 TRUSTED_DOM_PASS* pass)
543{
544 int idx, len = 0;
545 uint8 *p = pack_buf;
546 int remaining_space = pack_buf ? bufsize : 0;
547
548 if (!pass) {
549 return -1;
550 }
551
552 /* packing unicode domain name and password */
553 len += tdb_pack(p, remaining_space, "d",
554 pass->uni_name_len);
555 if (pack_buf) {
556 p = pack_buf + len;
557 remaining_space = bufsize - len;
558 }
559
560 for (idx = 0; idx < 32; idx++) {
561 len += tdb_pack(p, remaining_space, "w",
562 pass->uni_name[idx]);
563 if (pack_buf) {
564 p = pack_buf + len;
565 remaining_space = bufsize - len;
566 }
567 }
568
569 len += tdb_pack(p, remaining_space, "dPd", pass->pass_len,
570 pass->pass, pass->mod_time);
571 if (pack_buf) {
572 p = pack_buf + len;
573 remaining_space = bufsize - len;
574 }
575
576 /* packing SID structure */
577 len += tdb_sid_pack(p, remaining_space, &pass->domain_sid);
578 if (pack_buf) {
579 p = pack_buf + len;
580 remaining_space = bufsize - len;
581 }
582
583 return len;
584}
585
586
587/**
588 * Unpack TRUSTED_DOM_PASS passed by pointer
589 *
590 * @param pack_buf pointer to buffer with packed representation
591 * @param bufsize size of the buffer
592 * @param pass pointer to trusted domain password to be filled with unpacked data
593 *
594 * @return size of structure unpacked from buffer
595 **/
596static size_t tdb_trusted_dom_pass_unpack(uint8 *pack_buf, int bufsize,
597 TRUSTED_DOM_PASS* pass)
598{
599 int idx, len = 0;
600 char *passp = NULL;
601
602 if (!pack_buf || !pass) return -1;
603
604 /* unpack unicode domain name and plaintext password */
605 len += tdb_unpack(pack_buf, bufsize - len, "d", &pass->uni_name_len);
606
607 for (idx = 0; idx < 32; idx++)
608 len += tdb_unpack(pack_buf + len, bufsize - len, "w",
609 &pass->uni_name[idx]);
610
611 len += tdb_unpack(pack_buf + len, bufsize - len, "dPd",
612 &pass->pass_len, &passp, &pass->mod_time);
613 if (passp) {
614 fstrcpy(pass->pass, passp);
615 }
616 SAFE_FREE(passp);
617
618 /* unpack domain sid */
619 len += tdb_sid_unpack(pack_buf + len, bufsize - len,
620 &pass->domain_sid);
621
622 return len;
623}
624
625/************************************************************************
626 Routine to get account password to trusted domain
627************************************************************************/
628
629bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
630 DOM_SID *sid, time_t *pass_last_set_time)
631{
632 struct trusted_dom_pass pass;
633 size_t size = 0;
634
635 /* unpacking structures */
636 uint8 *pass_buf;
637 int pass_len = 0;
638
639 ZERO_STRUCT(pass);
640
641 /* fetching trusted domain password structure */
642 if (!(pass_buf = (uint8 *)secrets_fetch(trustdom_keystr(domain),
643 &size))) {
644 DEBUG(5, ("secrets_fetch failed!\n"));
645 return False;
646 }
647
648 /* unpack trusted domain password */
649 pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass);
650 SAFE_FREE(pass_buf);
651
652 if (pass_len != size) {
653 DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
654 return False;
655 }
656
657 /* the trust's password */
658 if (pwd) {
659 *pwd = SMB_STRDUP(pass.pass);
660 if (!*pwd) {
661 return False;
662 }
663 }
664
665 /* last change time */
666 if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
667
668 /* domain sid */
669 if (sid != NULL) sid_copy(sid, &pass.domain_sid);
670
671 return True;
672}
673
674/**
675 * Routine to store the password for trusted domain
676 *
677 * @param domain remote domain name
678 * @param pwd plain text password of trust relationship
679 * @param sid remote domain sid
680 *
681 * @return true if succeeded
682 **/
683
684bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
685 const DOM_SID *sid)
686{
687 smb_ucs2_t *uni_dom_name;
688 bool ret;
689 size_t converted_size;
690
691 /* packing structures */
692 uint8 *pass_buf = NULL;
693 int pass_len = 0;
694
695 struct trusted_dom_pass pass;
696 ZERO_STRUCT(pass);
697
698 if (!push_ucs2_allocate(&uni_dom_name, domain, &converted_size)) {
699 DEBUG(0, ("Could not convert domain name %s to unicode\n",
700 domain));
701 return False;
702 }
703
704 strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
705 pass.uni_name_len = strlen_w(uni_dom_name)+1;
706 SAFE_FREE(uni_dom_name);
707
708 /* last change time */
709 pass.mod_time = time(NULL);
710
711 /* password of the trust */
712 pass.pass_len = strlen(pwd);
713 fstrcpy(pass.pass, pwd);
714
715 /* domain sid */
716 sid_copy(&pass.domain_sid, sid);
717
718 /* Calculate the length. */
719 pass_len = tdb_trusted_dom_pass_pack(NULL, 0, &pass);
720 pass_buf = SMB_MALLOC_ARRAY(uint8, pass_len);
721 if (!pass_buf) {
722 return false;
723 }
724 pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_len, &pass);
725 ret = secrets_store(trustdom_keystr(domain), (void *)pass_buf,
726 pass_len);
727 SAFE_FREE(pass_buf);
728 return ret;
729}
730
731/************************************************************************
732 Routine to delete the plaintext machine account password
733************************************************************************/
734
735bool secrets_delete_machine_password(const char *domain)
736{
737 return secrets_delete(machine_password_keystr(domain));
738}
739
740/************************************************************************
741 Routine to delete the plaintext machine account password, sec channel type and
742 last change time from secrets database
743************************************************************************/
744
745bool secrets_delete_machine_password_ex(const char *domain)
746{
747 if (!secrets_delete(machine_password_keystr(domain))) {
748 return false;
749 }
750 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
751 return false;
752 }
753 return secrets_delete(machine_last_change_time_keystr(domain));
754}
755
756/************************************************************************
757 Routine to delete the domain sid
758************************************************************************/
759
760bool secrets_delete_domain_sid(const char *domain)
761{
762 return secrets_delete(domain_sid_keystr(domain));
763}
764
765/************************************************************************
766 Routine to set the plaintext machine account password for a realm
767the password is assumed to be a null terminated ascii string
768************************************************************************/
769
770bool secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
771{
772 bool ret;
773 uint32 last_change_time;
774 uint32 sec_channel_type;
775
776 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
777 if (!ret)
778 return ret;
779
780 SIVAL(&last_change_time, 0, time(NULL));
781 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
782
783 SIVAL(&sec_channel_type, 0, sec_channel);
784 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
785
786 return ret;
787}
788
789/************************************************************************
790 Routine to fetch the plaintext machine account password for a realm
791 the password is assumed to be a null terminated ascii string.
792************************************************************************/
793
794char *secrets_fetch_machine_password(const char *domain,
795 time_t *pass_last_set_time,
796 uint32 *channel)
797{
798 char *ret;
799 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
800
801 if (pass_last_set_time) {
802 size_t size;
803 uint32 *last_set_time;
804 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
805 if (last_set_time) {
806 *pass_last_set_time = IVAL(last_set_time,0);
807 SAFE_FREE(last_set_time);
808 } else {
809 *pass_last_set_time = 0;
810 }
811 }
812
813 if (channel) {
814 size_t size;
815 uint32 *channel_type;
816 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
817 if (channel_type) {
818 *channel = IVAL(channel_type,0);
819 SAFE_FREE(channel_type);
820 } else {
821 *channel = get_default_sec_channel();
822 }
823 }
824
825 return ret;
826}
827
828/************************************************************************
829 Routine to delete the password for trusted domain
830************************************************************************/
831
832bool trusted_domain_password_delete(const char *domain)
833{
834 return secrets_delete(trustdom_keystr(domain));
835}
836
837bool secrets_store_ldap_pw(const char* dn, char* pw)
838{
839 char *key = NULL;
840 bool ret;
841
842 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
843 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
844 return False;
845 }
846
847 ret = secrets_store(key, pw, strlen(pw)+1);
848
849 SAFE_FREE(key);
850 return ret;
851}
852
853/*******************************************************************
854 Find the ldap password.
855******************************************************************/
856
857bool fetch_ldap_pw(char **dn, char** pw)
858{
859 char *key = NULL;
860 size_t size = 0;
861
862 *dn = smb_xstrdup(lp_ldap_admin_dn());
863
864 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
865 SAFE_FREE(*dn);
866 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
867 }
868
869 *pw=(char *)secrets_fetch(key, &size);
870 SAFE_FREE(key);
871
872 if (!size) {
873 /* Upgrade 2.2 style entry */
874 char *p;
875 char* old_style_key = SMB_STRDUP(*dn);
876 char *data;
877 fstring old_style_pw;
878
879 if (!old_style_key) {
880 DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
881 return False;
882 }
883
884 for (p=old_style_key; *p; p++)
885 if (*p == ',') *p = '/';
886
887 data=(char *)secrets_fetch(old_style_key, &size);
888 if ((data == NULL) || (size < sizeof(old_style_pw))) {
889 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
890 SAFE_FREE(old_style_key);
891 SAFE_FREE(*dn);
892 SAFE_FREE(data);
893 return False;
894 }
895
896 size = MIN(size, sizeof(fstring)-1);
897 strncpy(old_style_pw, data, size);
898 old_style_pw[size] = 0;
899
900 SAFE_FREE(data);
901
902 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
903 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
904 SAFE_FREE(old_style_key);
905 SAFE_FREE(*dn);
906 return False;
907 }
908 if (!secrets_delete(old_style_key)) {
909 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
910 }
911
912 SAFE_FREE(old_style_key);
913
914 *pw = smb_xstrdup(old_style_pw);
915 }
916
917 return True;
918}
919
920/**
921 * Get trusted domains info from secrets.tdb.
922 **/
923
924struct list_trusted_domains_state {
925 uint32 num_domains;
926 struct trustdom_info **domains;
927};
928
929static int list_trusted_domain(struct db_record *rec, void *private_data)
930{
931 const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
932 size_t converted_size, packed_size = 0;
933 struct trusted_dom_pass pass;
934 struct trustdom_info *dom_info;
935
936 struct list_trusted_domains_state *state =
937 (struct list_trusted_domains_state *)private_data;
938
939 if ((rec->key.dsize < prefix_len)
940 || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
941 prefix_len) != 0)) {
942 return 0;
943 }
944
945 packed_size = tdb_trusted_dom_pass_unpack(
946 rec->value.dptr, rec->value.dsize, &pass);
947
948 if (rec->value.dsize != packed_size) {
949 DEBUG(2, ("Secrets record is invalid!\n"));
950 return 0;
951 }
952
953 if (pass.domain_sid.num_auths != 4) {
954 DEBUG(0, ("SID %s is not a domain sid, has %d "
955 "auths instead of 4\n",
956 sid_string_dbg(&pass.domain_sid),
957 pass.domain_sid.num_auths));
958 return 0;
959 }
960
961 if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
962 DEBUG(0, ("talloc failed\n"));
963 return 0;
964 }
965
966 if (!pull_ucs2_talloc(dom_info, &dom_info->name, pass.uni_name,
967 &converted_size)) {
968 DEBUG(2, ("pull_ucs2_talloc failed\n"));
969 TALLOC_FREE(dom_info);
970 return 0;
971 }
972
973 sid_copy(&dom_info->sid, &pass.domain_sid);
974
975 ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
976 &state->domains, &state->num_domains);
977
978 if (state->domains == NULL) {
979 state->num_domains = 0;
980 return -1;
981 }
982 return 0;
983}
984
985NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
986 struct trustdom_info ***domains)
987{
988 struct list_trusted_domains_state state;
989
990 secrets_init();
991
992 if (db_ctx == NULL) {
993 return NT_STATUS_ACCESS_DENIED;
994 }
995
996 state.num_domains = 0;
997
998 /*
999 * Make sure that a talloc context for the trustdom_info structs
1000 * exists
1001 */
1002
1003 if (!(state.domains = TALLOC_ARRAY(
1004 mem_ctx, struct trustdom_info *, 1))) {
1005 return NT_STATUS_NO_MEMORY;
1006 }
1007
1008 db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
1009
1010 *num_domains = state.num_domains;
1011 *domains = state.domains;
1012 return NT_STATUS_OK;
1013}
1014
1015/*******************************************************************************
1016 Store a complete AFS keyfile into secrets.tdb.
1017*******************************************************************************/
1018
1019bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
1020{
1021 fstring key;
1022
1023 if ((cell == NULL) || (keyfile == NULL))
1024 return False;
1025
1026 if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
1027 return False;
1028
1029 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
1030 return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
1031}
1032
1033/*******************************************************************************
1034 Fetch the current (highest) AFS key from secrets.tdb
1035*******************************************************************************/
1036bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
1037{
1038 fstring key;
1039 struct afs_keyfile *keyfile;
1040 size_t size = 0;
1041 uint32 i;
1042
1043 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
1044
1045 keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
1046
1047 if (keyfile == NULL)
1048 return False;
1049
1050 if (size != sizeof(struct afs_keyfile)) {
1051 SAFE_FREE(keyfile);
1052 return False;
1053 }
1054
1055 i = ntohl(keyfile->nkeys);
1056
1057 if (i > SECRETS_AFS_MAXKEYS) {
1058 SAFE_FREE(keyfile);
1059 return False;
1060 }
1061
1062 *result = keyfile->entry[i-1];
1063
1064 result->kvno = ntohl(result->kvno);
1065
1066 SAFE_FREE(keyfile);
1067
1068 return True;
1069}
1070
1071/******************************************************************************
1072 When kerberos is not available, choose between anonymous or
1073 authenticated connections.
1074
1075 We need to use an authenticated connection if DCs have the
1076 RestrictAnonymous registry entry set > 0, or the "Additional
1077 restrictions for anonymous connections" set in the win2k Local
1078 Security Policy.
1079
1080 Caller to free() result in domain, username, password
1081*******************************************************************************/
1082void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
1083{
1084 *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
1085 *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
1086 *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
1087
1088 if (*username && **username) {
1089
1090 if (!*domain || !**domain)
1091 *domain = smb_xstrdup(lp_workgroup());
1092
1093 if (!*password || !**password)
1094 *password = smb_xstrdup("");
1095
1096 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
1097 *domain, *username));
1098
1099 } else {
1100 DEBUG(3, ("IPC$ connections done anonymously\n"));
1101 *username = smb_xstrdup("");
1102 *domain = smb_xstrdup("");
1103 *password = smb_xstrdup("");
1104 }
1105}
1106
1107/******************************************************************************
1108 Open or create the schannel session store tdb.
1109*******************************************************************************/
1110
1111static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
1112{
1113 TDB_DATA vers;
1114 uint32 ver;
1115 TDB_CONTEXT *tdb_sc = NULL;
1116 char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", lp_private_dir());
1117
1118 if (!fname) {
1119 return NULL;
1120 }
1121
1122 tdb_sc = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
1123
1124 if (!tdb_sc) {
1125 DEBUG(0,("open_schannel_session_store: Failed to open %s\n", fname));
1126 TALLOC_FREE(fname);
1127 return NULL;
1128 }
1129
1130 vers = tdb_fetch_bystring(tdb_sc, "SCHANNEL_STORE_VERSION");
1131 if (vers.dptr == NULL) {
1132 /* First opener, no version. */
1133 SIVAL(&ver,0,1);
1134 vers.dptr = (uint8 *)&ver;
1135 vers.dsize = 4;
1136 tdb_store_bystring(tdb_sc, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE);
1137 vers.dptr = NULL;
1138 } else if (vers.dsize == 4) {
1139 ver = IVAL(vers.dptr,0);
1140 if (ver != 1) {
1141 tdb_close(tdb_sc);
1142 tdb_sc = NULL;
1143 DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
1144 (int)ver, fname ));
1145 }
1146 } else {
1147 tdb_close(tdb_sc);
1148 tdb_sc = NULL;
1149 DEBUG(0,("open_schannel_session_store: wrong version number size %d in %s\n",
1150 (int)vers.dsize, fname ));
1151 }
1152
1153 SAFE_FREE(vers.dptr);
1154 TALLOC_FREE(fname);
1155
1156 return tdb_sc;
1157}
1158
1159/******************************************************************************
1160 Store the schannel state after an AUTH2 call.
1161 Note we must be root here.
1162*******************************************************************************/
1163
1164bool secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx,
1165 const char *remote_machine,
1166 const struct dcinfo *pdc)
1167{
1168 TDB_CONTEXT *tdb_sc = NULL;
1169 TDB_DATA value;
1170 bool ret;
1171 char *keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
1172 SECRETS_SCHANNEL_STATE,
1173 remote_machine);
1174 if (!keystr) {
1175 return False;
1176 }
1177
1178 /* Work out how large the record is. */
1179 value.dsize = tdb_pack(NULL, 0, "dBBBBBfff",
1180 pdc->sequence,
1181 8, pdc->seed_chal.data,
1182 8, pdc->clnt_chal.data,
1183 8, pdc->srv_chal.data,
1184 16, pdc->sess_key,
1185 16, pdc->mach_pw,
1186 pdc->mach_acct,
1187 pdc->remote_machine,
1188 pdc->domain);
1189
1190 value.dptr = TALLOC_ARRAY(mem_ctx, uint8, value.dsize);
1191 if (!value.dptr) {
1192 TALLOC_FREE(keystr);
1193 return False;
1194 }
1195
1196 value.dsize = tdb_pack(value.dptr, value.dsize, "dBBBBBfff",
1197 pdc->sequence,
1198 8, pdc->seed_chal.data,
1199 8, pdc->clnt_chal.data,
1200 8, pdc->srv_chal.data,
1201 16, pdc->sess_key,
1202 16, pdc->mach_pw,
1203 pdc->mach_acct,
1204 pdc->remote_machine,
1205 pdc->domain);
1206
1207 tdb_sc = open_schannel_session_store(mem_ctx);
1208 if (!tdb_sc) {
1209 TALLOC_FREE(keystr);
1210 TALLOC_FREE(value.dptr);
1211 return False;
1212 }
1213
1214 ret = (tdb_store_bystring(tdb_sc, keystr, value, TDB_REPLACE) == 0 ? True : False);
1215
1216 DEBUG(3,("secrets_store_schannel_session_info: stored schannel info with key %s\n",
1217 keystr ));
1218
1219 tdb_close(tdb_sc);
1220 TALLOC_FREE(keystr);
1221 TALLOC_FREE(value.dptr);
1222 return ret;
1223}
1224
1225/******************************************************************************
1226 Restore the schannel state on a client reconnect.
1227 Note we must be root here.
1228*******************************************************************************/
1229
1230bool secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
1231 const char *remote_machine,
1232 struct dcinfo **ppdc)
1233{
1234 TDB_CONTEXT *tdb_sc = NULL;
1235 TDB_DATA value;
1236 unsigned char *pseed_chal = NULL;
1237 unsigned char *pclnt_chal = NULL;
1238 unsigned char *psrv_chal = NULL;
1239 unsigned char *psess_key = NULL;
1240 unsigned char *pmach_pw = NULL;
1241 uint32 l1, l2, l3, l4, l5;
1242 int ret;
1243 struct dcinfo *pdc = NULL;
1244 char *keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
1245 SECRETS_SCHANNEL_STATE,
1246 remote_machine);
1247
1248 *ppdc = NULL;
1249
1250 if (!keystr) {
1251 return False;
1252 }
1253
1254 tdb_sc = open_schannel_session_store(mem_ctx);
1255 if (!tdb_sc) {
1256 TALLOC_FREE(keystr);
1257 return False;
1258 }
1259
1260 value = tdb_fetch_bystring(tdb_sc, keystr);
1261 if (!value.dptr) {
1262 DEBUG(0,("secrets_restore_schannel_session_info: Failed to find entry with key %s\n",
1263 keystr ));
1264 tdb_close(tdb_sc);
1265 return False;
1266 }
1267
1268 pdc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
1269
1270 /* Retrieve the record. */
1271 ret = tdb_unpack(value.dptr, value.dsize, "dBBBBBfff",
1272 &pdc->sequence,
1273 &l1, &pseed_chal,
1274 &l2, &pclnt_chal,
1275 &l3, &psrv_chal,
1276 &l4, &psess_key,
1277 &l5, &pmach_pw,
1278 &pdc->mach_acct,
1279 &pdc->remote_machine,
1280 &pdc->domain);
1281
1282 if (ret == -1 || l1 != 8 || l2 != 8 || l3 != 8 || l4 != 16 || l5 != 16) {
1283 /* Bad record - delete it. */
1284 tdb_delete_bystring(tdb_sc, keystr);
1285 tdb_close(tdb_sc);
1286 TALLOC_FREE(keystr);
1287 TALLOC_FREE(pdc);
1288 SAFE_FREE(pseed_chal);
1289 SAFE_FREE(pclnt_chal);
1290 SAFE_FREE(psrv_chal);
1291 SAFE_FREE(psess_key);
1292 SAFE_FREE(pmach_pw);
1293 SAFE_FREE(value.dptr);
1294 return False;
1295 }
1296
1297 tdb_close(tdb_sc);
1298
1299 memcpy(pdc->seed_chal.data, pseed_chal, 8);
1300 memcpy(pdc->clnt_chal.data, pclnt_chal, 8);
1301 memcpy(pdc->srv_chal.data, psrv_chal, 8);
1302 memcpy(pdc->sess_key, psess_key, 16);
1303 memcpy(pdc->mach_pw, pmach_pw, 16);
1304
1305 /* We know these are true so didn't bother to store them. */
1306 pdc->challenge_sent = True;
1307 pdc->authenticated = True;
1308
1309 DEBUG(3,("secrets_restore_schannel_session_info: restored schannel info key %s\n",
1310 keystr ));
1311
1312 SAFE_FREE(pseed_chal);
1313 SAFE_FREE(pclnt_chal);
1314 SAFE_FREE(psrv_chal);
1315 SAFE_FREE(psess_key);
1316 SAFE_FREE(pmach_pw);
1317
1318 TALLOC_FREE(keystr);
1319 SAFE_FREE(value.dptr);
1320
1321 *ppdc = pdc;
1322
1323 return True;
1324}
1325
1326bool secrets_store_generic(const char *owner, const char *key, const char *secret)
1327{
1328 char *tdbkey = NULL;
1329 bool ret;
1330
1331 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1332 DEBUG(0, ("asprintf failed!\n"));
1333 return False;
1334 }
1335
1336 ret = secrets_store(tdbkey, secret, strlen(secret)+1);
1337
1338 SAFE_FREE(tdbkey);
1339 return ret;
1340}
1341
1342/*******************************************************************
1343 Find the ldap password.
1344******************************************************************/
1345
1346char *secrets_fetch_generic(const char *owner, const char *key)
1347{
1348 char *secret = NULL;
1349 char *tdbkey = NULL;
1350
1351 if (( ! owner) || ( ! key)) {
1352 DEBUG(1, ("Invalid Paramters"));
1353 return NULL;
1354 }
1355
1356 if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
1357 DEBUG(0, ("Out of memory!\n"));
1358 return NULL;
1359 }
1360
1361 secret = (char *)secrets_fetch(tdbkey, NULL);
1362 SAFE_FREE(tdbkey);
1363
1364 return secret;
1365}
1366
Note: See TracBrowser for help on using the repository browser.