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