Comment and formatting fix.
[samba.git] / source / 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, struct uuid *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(struct uuid));
139 }
140
141 BOOL secrets_fetch_domain_guid(const char *domain, struct uuid *guid)
142 {
143         struct uuid *dyn_guid;
144         fstring key;
145         size_t size;
146         struct uuid new_guid;
147
148         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
149         strupper_m(key);
150         dyn_guid = (struct uuid *)secrets_fetch(key, &size);
151
152         if ((!dyn_guid) && (lp_server_role() == ROLE_DOMAIN_PDC)) {
153                 smb_uuid_generate_random(&new_guid);
154                 if (!secrets_store_domain_guid(domain, &new_guid))
155                         return False;
156                 dyn_guid = (struct uuid *)secrets_fetch(key, &size);
157                 if (dyn_guid == NULL)
158                         return False;
159         }
160
161         if (size != sizeof(struct uuid))
162         { 
163                 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
164                 SAFE_FREE(dyn_guid);
165                 return False;
166         }
167
168         *guid = *dyn_guid;
169         SAFE_FREE(dyn_guid);
170         return True;
171 }
172
173 /**
174  * Form a key for fetching the machine trust account password
175  *
176  * @param domain domain name
177  *
178  * @return stored password's key
179  **/
180 const char *trust_keystr(const char *domain)
181 {
182         static fstring keystr;
183
184         slprintf(keystr,sizeof(keystr)-1,"%s/%s", 
185                  SECRETS_MACHINE_ACCT_PASS, domain);
186         strupper_m(keystr);
187
188         return keystr;
189 }
190
191 /**
192  * Form a key for fetching a trusted domain password
193  *
194  * @param domain trusted domain name
195  *
196  * @return stored password's key
197  **/
198 static char *trustdom_keystr(const char *domain)
199 {
200         static pstring keystr;
201
202         pstr_sprintf(keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain);
203         strupper_m(keystr);
204                 
205         return keystr;
206 }
207
208 /************************************************************************
209  Lock the trust password entry.
210 ************************************************************************/
211
212 BOOL secrets_lock_trust_account_password(const char *domain, BOOL dolock)
213 {
214         if (!tdb)
215                 return False;
216
217         if (dolock)
218                 return (tdb_lock_bystring(tdb, trust_keystr(domain),0) == 0);
219         else
220                 tdb_unlock_bystring(tdb, trust_keystr(domain));
221         return True;
222 }
223
224 /************************************************************************
225  Routine to get the default secure channel type for trust accounts
226 ************************************************************************/
227
228 uint32 get_default_sec_channel(void) 
229 {
230         if (lp_server_role() == ROLE_DOMAIN_BDC || 
231             lp_server_role() == ROLE_DOMAIN_PDC) {
232                 return SEC_CHAN_BDC;
233         } else {
234                 return SEC_CHAN_WKSTA;
235         }
236 }
237
238 /************************************************************************
239  Routine to get the trust account password for a domain.
240  The user of this function must have locked the trust password file using
241  the above secrets_lock_trust_account_password().
242 ************************************************************************/
243
244 BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
245                                           time_t *pass_last_set_time,
246                                           uint32 *channel)
247 {
248         struct machine_acct_pass *pass;
249         char *plaintext;
250         size_t size;
251
252         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, 
253                                                    channel);
254         if (plaintext) {
255                 DEBUG(4,("Using cleartext machine password\n"));
256                 E_md4hash(plaintext, ret_pwd);
257                 SAFE_FREE(plaintext);
258                 return True;
259         }
260
261         if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
262                 DEBUG(5, ("secrets_fetch failed!\n"));
263                 return False;
264         }
265         
266         if (size != sizeof(*pass)) {
267                 DEBUG(0, ("secrets were of incorrect size!\n"));
268                 return False;
269         }
270
271         if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
272         memcpy(ret_pwd, pass->hash, 16);
273         SAFE_FREE(pass);
274
275         if (channel) 
276                 *channel = get_default_sec_channel();
277
278         return True;
279 }
280
281 /************************************************************************
282  Routine to get account password to trusted domain
283 ************************************************************************/
284
285 BOOL secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
286                                            DOM_SID *sid, time_t *pass_last_set_time)
287 {
288         struct trusted_dom_pass pass;
289         size_t size;
290         
291         /* unpacking structures */
292         char* pass_buf;
293         int pass_len = 0;
294
295         ZERO_STRUCT(pass);
296
297         /* fetching trusted domain password structure */
298         if (!(pass_buf = secrets_fetch(trustdom_keystr(domain), &size))) {
299                 DEBUG(5, ("secrets_fetch failed!\n"));
300                 return False;
301         }
302
303         /* unpack trusted domain password */
304         pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass);
305         SAFE_FREE(pass_buf);
306
307         if (pass_len != size) {
308                 DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
309                 return False;
310         }
311                         
312         /* the trust's password */      
313         if (pwd) {
314                 *pwd = strdup(pass.pass);
315                 if (!*pwd) {
316                         return False;
317                 }
318         }
319
320         /* last change time */
321         if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
322
323         /* domain sid */
324         sid_copy(sid, &pass.domain_sid);
325                 
326         return True;
327 }
328
329 /************************************************************************
330  Routine to set the trust account password for a domain.
331 ************************************************************************/
332
333 BOOL secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16])
334 {
335         struct machine_acct_pass pass;
336
337         pass.mod_time = time(NULL);
338         memcpy(pass.hash, new_pwd, 16);
339
340         return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass));
341 }
342
343 /**
344  * Routine to store the password for trusted domain
345  *
346  * @param domain remote domain name
347  * @param pwd plain text password of trust relationship
348  * @param sid remote domain sid
349  *
350  * @return true if succeeded
351  **/
352
353 BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_dom_name,
354                                            size_t uni_name_len, const char* pwd,
355                                            DOM_SID sid)
356 {       
357         /* packing structures */
358         pstring pass_buf;
359         int pass_len = 0;
360         int pass_buf_len = sizeof(pass_buf);
361         
362         struct trusted_dom_pass pass;
363         ZERO_STRUCT(pass);
364         
365         /* unicode domain name and its length */
366         if (!uni_dom_name)
367                 return False;
368                 
369         strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
370         pass.uni_name_len = uni_name_len;
371
372         /* last change time */
373         pass.mod_time = time(NULL);
374
375         /* password of the trust */
376         pass.pass_len = strlen(pwd);
377         fstrcpy(pass.pass, pwd);
378
379         /* domain sid */
380         sid_copy(&pass.domain_sid, &sid);
381         
382         pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_buf_len, &pass);
383
384         return secrets_store(trustdom_keystr(domain), (void *)&pass_buf, pass_len);
385 }
386
387 /************************************************************************
388  Routine to set the plaintext machine account password for a realm
389 the password is assumed to be a null terminated ascii string
390 ************************************************************************/
391
392 BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
393 {
394         char *key = NULL;
395         BOOL ret;
396         uint32 last_change_time;
397         uint32 sec_channel_type;
398
399         asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
400         if (!key) 
401                 return False;
402         strupper_m(key);
403
404         ret = secrets_store(key, pass, strlen(pass)+1);
405         SAFE_FREE(key);
406
407         if (!ret)
408                 return ret;
409         
410         asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
411         if (!key) 
412                 return False;
413         strupper_m(key);
414
415         SIVAL(&last_change_time, 0, time(NULL));
416         ret = secrets_store(key, &last_change_time, sizeof(last_change_time));
417         SAFE_FREE(key);
418
419         asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
420         if (!key) 
421                 return False;
422         strupper_m(key);
423
424         SIVAL(&sec_channel_type, 0, sec_channel);
425         ret = secrets_store(key, &sec_channel_type, sizeof(sec_channel_type));
426         SAFE_FREE(key);
427
428         return ret;
429 }
430
431
432 /************************************************************************
433  Routine to fetch the plaintext machine account password for a realm
434 the password is assumed to be a null terminated ascii string
435 ************************************************************************/
436 char *secrets_fetch_machine_password(const char *domain, 
437                                      time_t *pass_last_set_time,
438                                      uint32 *channel)
439 {
440         char *key = NULL;
441         char *ret;
442         asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
443         strupper_m(key);
444         ret = (char *)secrets_fetch(key, NULL);
445         SAFE_FREE(key);
446         
447         if (pass_last_set_time) {
448                 size_t size;
449                 uint32 *last_set_time;
450                 asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
451                 strupper_m(key);
452                 last_set_time = secrets_fetch(key, &size);
453                 if (last_set_time) {
454                         *pass_last_set_time = IVAL(last_set_time,0);
455                         SAFE_FREE(last_set_time);
456                 } else {
457                         *pass_last_set_time = 0;
458                 }
459                 SAFE_FREE(key);
460         }
461         
462         if (channel) {
463                 size_t size;
464                 uint32 *channel_type;
465                 asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
466                 strupper_m(key);
467                 channel_type = secrets_fetch(key, &size);
468                 if (channel_type) {
469                         *channel = IVAL(channel_type,0);
470                         SAFE_FREE(channel_type);
471                 } else {
472                         *channel = get_default_sec_channel();
473                 }
474                 SAFE_FREE(key);
475         }
476         
477         return ret;
478 }
479
480
481
482 /************************************************************************
483  Routine to delete the machine trust account password file for a domain.
484 ************************************************************************/
485
486 BOOL trust_password_delete(const char *domain)
487 {
488         return secrets_delete(trust_keystr(domain));
489 }
490
491 /************************************************************************
492  Routine to delete the password for trusted domain
493 ************************************************************************/
494
495 BOOL trusted_domain_password_delete(const char *domain)
496 {
497         return secrets_delete(trustdom_keystr(domain));
498 }
499
500
501 /*******************************************************************
502  Reset the 'done' variables so after a client process is created
503  from a fork call these calls will be re-done. This should be
504  expanded if more variables need reseting.
505  ******************************************************************/
506
507 void reset_globals_after_fork(void)
508 {
509         unsigned char dummy;
510
511         secrets_init();
512
513         /*
514          * Increment the global seed value to ensure every smbd starts
515          * with a new random seed.
516          */
517
518         if (tdb) {
519                 uint32 initial_val = sys_getpid();
520                 tdb_change_int32_atomic(tdb, "INFO/random_seed", (int *)&initial_val, 1);
521                 set_rand_reseed_data((unsigned char *)&initial_val, sizeof(initial_val));
522         }
523
524         /*
525          * Re-seed the random crypto generator, so all smbd's
526          * started from the same parent won't generate the same
527          * sequence.
528          */
529         generate_random_buffer( &dummy, 1, True);
530 }
531
532 BOOL secrets_store_ldap_pw(const char* dn, char* pw)
533 {
534         char *key = NULL;
535         BOOL ret;
536         
537         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
538                 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
539                 return False;
540         }
541                 
542         ret = secrets_store(key, pw, strlen(pw)+1);
543         
544         SAFE_FREE(key);
545         return ret;
546 }
547
548
549 /**
550  * Get trusted domains info from secrets.tdb.
551  *
552  * The linked list is allocated on the supplied talloc context, caller gets to destroy
553  * when done.
554  *
555  * @param ctx Allocation context
556  * @param enum_ctx Starting index, eg. we can start fetching at third
557  *        or sixth trusted domain entry. Zero is the first index.
558  *        Value it is set to is the enum context for the next enumeration.
559  * @param num_domains Number of domain entries to fetch at one call
560  * @param domains Pointer to array of trusted domain structs to be filled up
561  *
562  * @return nt status code of rpc response
563  **/ 
564
565 NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
566                                      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