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