r10656: BIG merge from trunk. Features not copied over
[ira/wip.git] / source3 / passdb / secrets.c
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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 /* the Samba secrets database stores any generated, private information
24    such as the local SID and machine trust password */
25
26 #include "includes.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
30
31 static TDB_CONTEXT *tdb;
32
33 /* Urrrg. global.... */
34 BOOL global_machine_password_needs_changing;
35
36 /**
37  * Use a TDB to store an incrementing random seed.
38  *
39  * Initialised to the current pid, the very first time Samba starts,
40  * and incremented by one each time it is needed.  
41  * 
42  * @note Not called by systems with a working /dev/urandom.
43  */
44 static void get_rand_seed(int *new_seed) 
45 {
46         *new_seed = sys_getpid();
47         if (tdb) {
48                 tdb_change_int32_atomic(tdb, "INFO/random_seed", new_seed, 1);
49         }
50 }
51
52 /* open up the secrets database */
53 BOOL secrets_init(void)
54 {
55         pstring fname;
56         unsigned char dummy;
57
58         if (tdb)
59                 return True;
60
61         pstrcpy(fname, lp_private_dir());
62         pstrcat(fname,"/secrets.tdb");
63
64         tdb = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
65
66         if (!tdb) {
67                 DEBUG(0,("Failed to open %s\n", fname));
68                 return False;
69         }
70
71         /**
72          * Set a reseed function for the crypto random generator 
73          * 
74          * This avoids a problem where systems without /dev/urandom
75          * could send the same challenge to multiple clients
76          */
77         set_rand_reseed_callback(get_rand_seed);
78
79         /* Ensure that the reseed is done now, while we are root, etc */
80         generate_random_buffer(&dummy, sizeof(dummy));
81
82         return True;
83 }
84
85 /* read a entry from the secrets database - the caller must free the result
86    if size is non-null then the size of the entry is put in there
87  */
88 void *secrets_fetch(const char *key, size_t *size)
89 {
90         TDB_DATA dbuf;
91         secrets_init();
92         if (!tdb)
93                 return NULL;
94         dbuf = tdb_fetch(tdb, string_tdb_data(key));
95         if (size)
96                 *size = dbuf.dsize;
97         return dbuf.dptr;
98 }
99
100 /* store a secrets entry 
101  */
102 BOOL secrets_store(const char *key, const void *data, size_t size)
103 {
104         secrets_init();
105         if (!tdb)
106                 return False;
107         return tdb_store(tdb, string_tdb_data(key), make_tdb_data(data, size),
108                          TDB_REPLACE) == 0;
109 }
110
111
112 /* delete a secets database entry
113  */
114 BOOL secrets_delete(const char *key)
115 {
116         secrets_init();
117         if (!tdb)
118                 return False;
119         return tdb_delete(tdb, string_tdb_data(key)) == 0;
120 }
121
122 BOOL 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
137 BOOL secrets_fetch_domain_sid(const char *domain, DOM_SID *sid)
138 {
139         DOM_SID *dyn_sid;
140         fstring key;
141         size_t size;
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         { 
152                 SAFE_FREE(dyn_sid);
153                 return False;
154         }
155
156         *sid = *dyn_sid;
157         SAFE_FREE(dyn_sid);
158         return True;
159 }
160
161 BOOL secrets_store_domain_guid(const char *domain, struct uuid *guid)
162 {
163         fstring key;
164
165         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
166         strupper_m(key);
167         return secrets_store(key, guid, sizeof(struct uuid));
168 }
169
170 BOOL secrets_fetch_domain_guid(const char *domain, struct uuid *guid)
171 {
172         struct uuid *dyn_guid;
173         fstring key;
174         size_t size;
175         struct uuid new_guid;
176
177         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
178         strupper_m(key);
179         dyn_guid = (struct uuid *)secrets_fetch(key, &size);
180
181         if ((!dyn_guid) && (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 uuid *)secrets_fetch(key, &size);
186                 if (dyn_guid == NULL)
187                         return False;
188         }
189
190         if (size != sizeof(struct uuid))
191         { 
192                 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
193                 SAFE_FREE(dyn_guid);
194                 return False;
195         }
196
197         *guid = *dyn_guid;
198         SAFE_FREE(dyn_guid);
199         return True;
200 }
201
202 /**
203  * Form a key for fetching the machine trust account password
204  *
205  * @param domain domain name
206  *
207  * @return stored password's key
208  **/
209 const char *trust_keystr(const char *domain)
210 {
211         static fstring keystr;
212
213         slprintf(keystr,sizeof(keystr)-1,"%s/%s", 
214                  SECRETS_MACHINE_ACCT_PASS, domain);
215         strupper_m(keystr);
216
217         return keystr;
218 }
219
220 /**
221  * Form a key for fetching a trusted domain password
222  *
223  * @param domain trusted domain name
224  *
225  * @return stored password's key
226  **/
227 static char *trustdom_keystr(const char *domain)
228 {
229         static pstring keystr;
230
231         pstr_sprintf(keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain);
232         strupper_m(keystr);
233                 
234         return keystr;
235 }
236
237 /************************************************************************
238  Lock the trust password entry.
239 ************************************************************************/
240
241 BOOL secrets_lock_trust_account_password(const char *domain, BOOL dolock)
242 {
243         if (!tdb)
244                 return False;
245
246         if (dolock)
247                 return (tdb_lock_bystring(tdb, trust_keystr(domain),0) == 0);
248         else
249                 tdb_unlock_bystring(tdb, trust_keystr(domain));
250         return True;
251 }
252
253 /************************************************************************
254  Routine to get the default secure channel type for trust accounts
255 ************************************************************************/
256
257 uint32 get_default_sec_channel(void) 
258 {
259         if (lp_server_role() == ROLE_DOMAIN_BDC || 
260             lp_server_role() == ROLE_DOMAIN_PDC) {
261                 return SEC_CHAN_BDC;
262         } else {
263                 return SEC_CHAN_WKSTA;
264         }
265 }
266
267 /************************************************************************
268  Routine to get the trust account password for a domain.
269  The user of this function must have locked the trust password file using
270  the above secrets_lock_trust_account_password().
271 ************************************************************************/
272
273 BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
274                                           time_t *pass_last_set_time,
275                                           uint32 *channel)
276 {
277         struct machine_acct_pass *pass;
278         char *plaintext;
279         size_t size;
280
281         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, 
282                                                    channel);
283         if (plaintext) {
284                 DEBUG(4,("Using cleartext machine password\n"));
285                 E_md4hash(plaintext, ret_pwd);
286                 SAFE_FREE(plaintext);
287                 return True;
288         }
289
290         if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
291                 DEBUG(5, ("secrets_fetch failed!\n"));
292                 return False;
293         }
294         
295         if (size != sizeof(*pass)) {
296                 DEBUG(0, ("secrets were of incorrect size!\n"));
297                 return False;
298         }
299
300         if (pass_last_set_time) {
301                 *pass_last_set_time = pass->mod_time;
302         }
303         memcpy(ret_pwd, pass->hash, 16);
304         SAFE_FREE(pass);
305
306         if (channel) {
307                 *channel = get_default_sec_channel();
308         }
309
310         /* Test if machine password has expired and needs to be changed */
311         if (lp_machine_password_timeout()) {
312                 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
313                                 lp_machine_password_timeout())) {
314                         global_machine_password_needs_changing = True;
315                 }
316         }
317
318         return True;
319 }
320
321 /************************************************************************
322  Routine to get account password to trusted domain
323 ************************************************************************/
324
325 BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
326                                            DOM_SID *sid, time_t *pass_last_set_time)
327 {
328         struct trusted_dom_pass pass;
329         size_t size;
330         
331         /* unpacking structures */
332         char* pass_buf;
333         int pass_len = 0;
334
335         ZERO_STRUCT(pass);
336
337         /* fetching trusted domain password structure */
338         if (!(pass_buf = secrets_fetch(trustdom_keystr(domain), &size))) {
339                 DEBUG(5, ("secrets_fetch failed!\n"));
340                 return False;
341         }
342
343         /* unpack trusted domain password */
344         pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass);
345         SAFE_FREE(pass_buf);
346
347         if (pass_len != size) {
348                 DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
349                 return False;
350         }
351                         
352         /* the trust's password */      
353         if (pwd) {
354                 *pwd = SMB_STRDUP(pass.pass);
355                 if (!*pwd) {
356                         return False;
357                 }
358         }
359
360         /* last change time */
361         if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
362
363         /* domain sid */
364         sid_copy(sid, &pass.domain_sid);
365                 
366         return True;
367 }
368
369 /************************************************************************
370  Routine to set the trust account password for a domain.
371 ************************************************************************/
372
373 BOOL secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16])
374 {
375         struct machine_acct_pass pass;
376
377         pass.mod_time = time(NULL);
378         memcpy(pass.hash, new_pwd, 16);
379
380         return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass));
381 }
382
383 /**
384  * Routine to store the password for trusted domain
385  *
386  * @param domain remote domain name
387  * @param pwd plain text password of trust relationship
388  * @param sid remote domain sid
389  *
390  * @return true if succeeded
391  **/
392
393 BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_dom_name,
394                                            size_t uni_name_len, const char* pwd,
395                                            DOM_SID sid)
396 {       
397         /* packing structures */
398         pstring pass_buf;
399         int pass_len = 0;
400         int pass_buf_len = sizeof(pass_buf);
401         
402         struct trusted_dom_pass pass;
403         ZERO_STRUCT(pass);
404         
405         /* unicode domain name and its length */
406         if (!uni_dom_name)
407                 return False;
408                 
409         strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
410         pass.uni_name_len = uni_name_len;
411
412         /* last change time */
413         pass.mod_time = time(NULL);
414
415         /* password of the trust */
416         pass.pass_len = strlen(pwd);
417         fstrcpy(pass.pass, pwd);
418
419         /* domain sid */
420         sid_copy(&pass.domain_sid, &sid);
421         
422         pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_buf_len, &pass);
423
424         return secrets_store(trustdom_keystr(domain), (void *)&pass_buf, pass_len);
425 }
426
427 /************************************************************************
428  Routine to set the plaintext machine account password for a realm
429 the password is assumed to be a null terminated ascii string
430 ************************************************************************/
431
432 BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
433 {
434         char *key = NULL;
435         BOOL ret;
436         uint32 last_change_time;
437         uint32 sec_channel_type;
438
439         asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
440         if (!key) 
441                 return False;
442         strupper_m(key);
443
444         ret = secrets_store(key, pass, strlen(pass)+1);
445         SAFE_FREE(key);
446
447         if (!ret)
448                 return ret;
449         
450         asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
451         if (!key) 
452                 return False;
453         strupper_m(key);
454
455         SIVAL(&last_change_time, 0, time(NULL));
456         ret = secrets_store(key, &last_change_time, sizeof(last_change_time));
457         SAFE_FREE(key);
458
459         asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
460         if (!key) 
461                 return False;
462         strupper_m(key);
463
464         SIVAL(&sec_channel_type, 0, sec_channel);
465         ret = secrets_store(key, &sec_channel_type, sizeof(sec_channel_type));
466         SAFE_FREE(key);
467
468         return ret;
469 }
470
471 /************************************************************************
472  Routine to fetch the plaintext machine account password for a realm
473  the password is assumed to be a null terminated ascii string.
474 ************************************************************************/
475
476 char *secrets_fetch_machine_password(const char *domain, 
477                                      time_t *pass_last_set_time,
478                                      uint32 *channel)
479 {
480         char *key = NULL;
481         char *ret;
482         asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
483         strupper_m(key);
484         ret = (char *)secrets_fetch(key, NULL);
485         SAFE_FREE(key);
486         
487         if (pass_last_set_time) {
488                 size_t size;
489                 uint32 *last_set_time;
490                 asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
491                 strupper_m(key);
492                 last_set_time = secrets_fetch(key, &size);
493                 if (last_set_time) {
494                         *pass_last_set_time = IVAL(last_set_time,0);
495                         SAFE_FREE(last_set_time);
496                 } else {
497                         *pass_last_set_time = 0;
498                 }
499                 SAFE_FREE(key);
500         }
501         
502         if (channel) {
503                 size_t size;
504                 uint32 *channel_type;
505                 asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
506                 strupper_m(key);
507                 channel_type = secrets_fetch(key, &size);
508                 if (channel_type) {
509                         *channel = IVAL(channel_type,0);
510                         SAFE_FREE(channel_type);
511                 } else {
512                         *channel = get_default_sec_channel();
513                 }
514                 SAFE_FREE(key);
515         }
516         
517         return ret;
518 }
519
520 /*******************************************************************
521  Wrapper around retrieving the trust account password
522 *******************************************************************/
523                                                                                                                      
524 BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel)
525 {
526         DOM_SID sid;
527         char *pwd;
528         time_t last_set_time;
529                                                                                                                      
530         /* if we are a DC and this is not our domain, then lookup an account
531                 for the domain trust */
532                                                                                                                      
533         if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) {
534                 if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
535                                                         &last_set_time)) {
536                         DEBUG(0, ("get_trust_pw: could not fetch trust "
537                                 "account password for trusted domain %s\n",
538                                 domain));
539                         return False;
540                 }
541                                                                                                                      
542                 *channel = SEC_CHAN_DOMAIN;
543                 E_md4hash(pwd, ret_pwd);
544                 SAFE_FREE(pwd);
545
546                 return True;
547         }
548                                                                                                                      
549         /* Just get the account for the requested domain. In the future this
550          * might also cover to be member of more than one domain. */
551                                                                                                                      
552         if (secrets_fetch_trust_account_password(domain, ret_pwd,
553                                                 &last_set_time, channel))
554                 return True;
555
556         DEBUG(5, ("get_trust_pw: could not fetch trust account "
557                 "password for domain %s\n", domain));
558         return False;
559 }
560
561 /************************************************************************
562  Routine to delete the machine trust account password file for a domain.
563 ************************************************************************/
564
565 BOOL trust_password_delete(const char *domain)
566 {
567         return secrets_delete(trust_keystr(domain));
568 }
569
570 /************************************************************************
571  Routine to delete the password for trusted domain
572 ************************************************************************/
573
574 BOOL trusted_domain_password_delete(const char *domain)
575 {
576         return secrets_delete(trustdom_keystr(domain));
577 }
578
579 BOOL secrets_store_ldap_pw(const char* dn, char* pw)
580 {
581         char *key = NULL;
582         BOOL ret;
583         
584         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
585                 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
586                 return False;
587         }
588                 
589         ret = secrets_store(key, pw, strlen(pw)+1);
590         
591         SAFE_FREE(key);
592         return ret;
593 }
594
595 /*******************************************************************
596  Find the ldap password.
597 ******************************************************************/
598
599 BOOL fetch_ldap_pw(char **dn, char** pw)
600 {
601         char *key = NULL;
602         size_t size;
603         
604         *dn = smb_xstrdup(lp_ldap_admin_dn());
605         
606         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
607                 SAFE_FREE(*dn);
608                 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
609         }
610         
611         *pw=secrets_fetch(key, &size);
612         SAFE_FREE(key);
613
614         if (!size) {
615                 /* Upgrade 2.2 style entry */
616                 char *p;
617                 char* old_style_key = SMB_STRDUP(*dn);
618                 char *data;
619                 fstring old_style_pw;
620                 
621                 if (!old_style_key) {
622                         DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
623                         return False;
624                 }
625
626                 for (p=old_style_key; *p; p++)
627                         if (*p == ',') *p = '/';
628         
629                 data=secrets_fetch(old_style_key, &size);
630                 if (!size && size < sizeof(old_style_pw)) {
631                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
632                         SAFE_FREE(old_style_key);
633                         SAFE_FREE(*dn);
634                         return False;
635                 }
636
637                 size = MIN(size, sizeof(fstring)-1);
638                 strncpy(old_style_pw, data, size);
639                 old_style_pw[size] = 0;
640
641                 SAFE_FREE(data);
642
643                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
644                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
645                         SAFE_FREE(old_style_key);
646                         SAFE_FREE(*dn);
647                         return False;                   
648                 }
649                 if (!secrets_delete(old_style_key)) {
650                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
651                 }
652
653                 SAFE_FREE(old_style_key);
654
655                 *pw = smb_xstrdup(old_style_pw);                
656         }
657         
658         return True;
659 }
660
661 /**
662  * Get trusted domains info from secrets.tdb.
663  *
664  * The linked list is allocated on the supplied talloc context, caller gets to destroy
665  * when done.
666  *
667  * @param ctx Allocation context
668  * @param enum_ctx Starting index, eg. we can start fetching at third
669  *        or sixth trusted domain entry. Zero is the first index.
670  *        Value it is set to is the enum context for the next enumeration.
671  * @param num_domains Number of domain entries to fetch at one call
672  * @param domains Pointer to array of trusted domain structs to be filled up
673  *
674  * @return nt status code of rpc response
675  **/ 
676
677 NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
678                                      int *num_domains, TRUSTDOM ***domains)
679 {
680         TDB_LIST_NODE *keys, *k;
681         TRUSTDOM *dom = NULL;
682         char *pattern;
683         unsigned int start_idx;
684         uint32 idx = 0;
685         size_t size, packed_size = 0;
686         fstring dom_name;
687         char *packed_pass;
688         struct trusted_dom_pass *pass = TALLOC_ZERO_P(ctx, struct trusted_dom_pass);
689         NTSTATUS status;
690
691         if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
692         
693         if (!pass) {
694                 DEBUG(0, ("talloc_zero failed!\n"));
695                 return NT_STATUS_NO_MEMORY;
696         }
697                                 
698         *num_domains = 0;
699         start_idx = *enum_ctx;
700
701         /* generate searching pattern */
702         if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
703                 DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
704                 return NT_STATUS_NO_MEMORY;
705         }
706
707         DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", 
708                   max_num_domains, *enum_ctx));
709
710         *domains = TALLOC_ZERO_ARRAY(ctx, TRUSTDOM *, max_num_domains);
711
712         /* fetching trusted domains' data and collecting them in a list */
713         keys = tdb_search_keys(tdb, pattern);
714
715         /* 
716          * if there's no keys returned ie. no trusted domain,
717          * return "no more entries" code
718          */
719         status = NT_STATUS_NO_MORE_ENTRIES;
720
721         /* searching for keys in secrets db -- way to go ... */
722         for (k = keys; k; k = k->next) {
723                 char *secrets_key;
724                 
725                 /* important: ensure null-termination of the key string */
726                 secrets_key = SMB_STRNDUP(k->node_key.dptr, k->node_key.dsize);
727                 if (!secrets_key) {
728                         DEBUG(0, ("strndup failed!\n"));
729                         return NT_STATUS_NO_MEMORY;
730                 }
731
732                 packed_pass = secrets_fetch(secrets_key, &size);
733                 packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
734                 /* packed representation isn't needed anymore */
735                 SAFE_FREE(packed_pass);
736                 
737                 if (size != packed_size) {
738                         DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
739                         continue;
740                 }
741                 
742                 pull_ucs2_fstring(dom_name, pass->uni_name);
743                 DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
744                            idx, dom_name, sid_string_static(&pass->domain_sid)));
745
746                 SAFE_FREE(secrets_key);
747
748                 if (idx >= start_idx && idx < start_idx + max_num_domains) {
749                         dom = TALLOC_ZERO_P(ctx, TRUSTDOM);
750                         if (!dom) {
751                                 /* free returned tdb record */
752                                 return NT_STATUS_NO_MEMORY;
753                         }
754                         
755                         /* copy domain sid */
756                         SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
757                         memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
758                         
759                         /* copy unicode domain name */
760                         dom->name = TALLOC_MEMDUP(ctx, pass->uni_name,
761                                                   (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t));
762                         
763                         (*domains)[idx - start_idx] = dom;
764                         
765                         DEBUG(18, ("Secret record is in required range.\n \
766                                    start_idx = %d, max_num_domains = %d. Added to returned array.\n",
767                                    start_idx, max_num_domains));
768
769                         *enum_ctx = idx + 1;
770                         (*num_domains)++;
771                 
772                         /* set proper status code to return */
773                         if (k->next) {
774                                 /* there are yet some entries to enumerate */
775                                 status = STATUS_MORE_ENTRIES;
776                         } else {
777                                 /* this is the last entry in the whole enumeration */
778                                 status = NT_STATUS_OK;
779                         }
780                 } else {
781                         DEBUG(18, ("Secret is outside the required range.\n \
782                                    start_idx = %d, max_num_domains = %d. Not added to returned array\n",
783                                    start_idx, max_num_domains));
784                 }
785                 
786                 idx++;          
787         }
788         
789         DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains));
790
791         /* free the results of searching the keys */
792         tdb_search_list_free(keys);
793
794         return status;
795 }
796
797 /*******************************************************************************
798  Lock the secrets tdb based on a string - this is used as a primitive form of mutex
799  between smbd instances.
800 *******************************************************************************/
801
802 BOOL secrets_named_mutex(const char *name, unsigned int timeout)
803 {
804         int ret = 0;
805
806         if (!message_init())
807                 return False;
808
809         ret = tdb_lock_bystring(tdb, name, timeout);
810         if (ret == 0)
811                 DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name ));
812
813         return (ret == 0);
814 }
815
816 /*******************************************************************************
817  Unlock a named mutex.
818 *******************************************************************************/
819
820 void secrets_named_mutex_release(const char *name)
821 {
822         tdb_unlock_bystring(tdb, name);
823         DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
824 }
825
826 /*********************************************************
827  Check to see if we must talk to the PDC to avoid sam 
828  sync delays
829  ********************************************************/
830  
831 BOOL must_use_pdc( const char *domain )
832 {
833         time_t  now = time(NULL);
834         time_t  last_change_time;
835         unsigned char   passwd[16];   
836         
837         if ( !secrets_fetch_trust_account_password(domain, passwd, &last_change_time, NULL) )
838                 return False;
839                 
840         /*
841          * If the time the machine password has changed
842          * was less than about 15 minutes then we need to contact
843          * the PDC only, as we cannot be sure domain replication
844          * has yet taken place. Bug found by Gerald (way to go
845          * Gerald !). JRA.
846          */
847          
848         if ( now - last_change_time < SAM_SYNC_WINDOW )
849                 return True;
850                 
851         return False;
852
853 }
854
855 /*******************************************************************************
856  Store a complete AFS keyfile into secrets.tdb.
857 *******************************************************************************/
858
859 BOOL secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
860 {
861         fstring key;
862
863         if ((cell == NULL) || (keyfile == NULL))
864                 return False;
865
866         if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
867                 return False;
868
869         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
870         return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
871 }
872
873 /*******************************************************************************
874  Fetch the current (highest) AFS key from secrets.tdb
875 *******************************************************************************/
876 BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result)
877 {
878         fstring key;
879         struct afs_keyfile *keyfile;
880         size_t size;
881         uint32 i;
882
883         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
884
885         keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
886
887         if (keyfile == NULL)
888                 return False;
889
890         if (size != sizeof(struct afs_keyfile)) {
891                 SAFE_FREE(keyfile);
892                 return False;
893         }
894
895         i = ntohl(keyfile->nkeys);
896
897         if (i > SECRETS_AFS_MAXKEYS) {
898                 SAFE_FREE(keyfile);
899                 return False;
900         }
901
902         *result = keyfile->entry[i-1];
903
904         result->kvno = ntohl(result->kvno);
905
906         return True;
907 }
908
909 /******************************************************************************
910   When kerberos is not available, choose between anonymous or
911   authenticated connections.  
912
913   We need to use an authenticated connection if DCs have the
914   RestrictAnonymous registry entry set > 0, or the "Additional
915   restrictions for anonymous connections" set in the win2k Local
916   Security Policy.
917
918   Caller to free() result in domain, username, password
919 *******************************************************************************/
920 void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
921 {
922         *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
923         *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
924         *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
925         
926         if (*username && **username) {
927
928                 if (!*domain || !**domain)
929                         *domain = smb_xstrdup(lp_workgroup());
930                 
931                 if (!*password || !**password)
932                         *password = smb_xstrdup("");
933
934                 DEBUG(3, ("IPC$ connections done by user %s\\%s\n", 
935                           *domain, *username));
936
937         } else {
938                 DEBUG(3, ("IPC$ connections done anonymously\n"));
939                 *username = smb_xstrdup("");
940                 *domain = smb_xstrdup("");
941                 *password = smb_xstrdup("");
942         }
943 }
944