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