r3971: fix compiler warnings
[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    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /* the Samba secrets database stores any generated, private information
23    such as the local SID and machine trust password */
24
25 #include "includes.h"
26 #include "secrets.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_PASSDB
30
31 static struct tdb_wrap *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 = getpid();
44         if (tdb) {
45                 tdb_change_int32_atomic(tdb->tdb, "INFO/random_seed", new_seed, 1);
46         }
47 }
48
49 /* close the secrets database */
50 void secrets_shutdown(void)
51 {
52         talloc_free(tdb);
53 }
54
55 /* open up the secrets database */
56 BOOL secrets_init(void)
57 {
58         pstring fname;
59         uint8_t dummy;
60
61         if (tdb)
62                 return True;
63
64         pstrcpy(fname, lp_private_dir());
65         pstrcat(fname,"/secrets.tdb");
66
67         tdb = tdb_wrap_open(NULL, fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
68
69         if (!tdb) {
70                 DEBUG(0,("Failed to open %s\n", fname));
71                 return False;
72         }
73
74         /**
75          * Set a reseed function for the crypto random generator 
76          * 
77          * This avoids a problem where systems without /dev/urandom
78          * could send the same challenge to multiple clients
79          */
80         set_rand_reseed_callback(get_rand_seed);
81
82         /* Ensure that the reseed is done now, while we are root, etc */
83         generate_random_buffer(&dummy, sizeof(dummy));
84
85         return True;
86 }
87
88 /* read a entry from the secrets database - the caller must free the result
89    if size is non-null then the size of the entry is put in there
90  */
91 static void *secrets_fetch(const char *key, size_t *size)
92 {
93         TDB_DATA kbuf, dbuf;
94         secrets_init();
95         if (!tdb)
96                 return NULL;
97         kbuf.dptr = strdup(key);
98         kbuf.dsize = strlen(key);
99         dbuf = tdb_fetch(tdb->tdb, kbuf);
100         if (size)
101                 *size = dbuf.dsize;
102         free(kbuf.dptr);
103         return dbuf.dptr;
104 }
105
106 /************************************************************************
107  Routine to fetch the plaintext machine account password for a realm
108 the password is assumed to be a null terminated ascii string
109 ************************************************************************/
110 char *secrets_fetch_machine_password(const char *domain)
111 {
112         char *key;
113         char *ret;
114         asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
115         strupper(key);
116         ret = (char *)secrets_fetch(key, NULL);
117         free(key);
118         return ret;
119 }
120
121
122
123 /*******************************************************************************
124  Lock the secrets tdb based on a string - this is used as a primitive form of mutex
125  between smbd instances.
126 *******************************************************************************/
127
128 BOOL secrets_named_mutex(const char *name, uint_t timeout, size_t *p_ref_count)
129 {
130         size_t ref_count = *p_ref_count;
131         int ret = 0;
132
133         secrets_init();
134         if (!tdb)
135                 return False;
136
137         if (ref_count == 0) {
138                 ret = tdb_lock_bystring(tdb->tdb, name, timeout);
139                 if (ret == 0)
140                         DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name ));
141         }
142
143         if (ret == 0) {
144                 *p_ref_count = ++ref_count;
145                 DEBUG(10,("secrets_named_mutex: ref_count for mutex %s = %u\n", name, (uint_t)ref_count ));
146         }
147         return (ret == 0);
148 }
149
150 /*******************************************************************************
151  Unlock a named mutex.
152 *******************************************************************************/
153
154 void secrets_named_mutex_release(const char *name, size_t *p_ref_count)
155 {
156         size_t ref_count = *p_ref_count;
157
158         SMB_ASSERT(ref_count != 0);
159
160         secrets_init();
161         if (!tdb)
162                 return;
163
164         if (ref_count == 1) {
165                 tdb_unlock_bystring(tdb->tdb, name);
166                 DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
167         }
168
169         *p_ref_count = --ref_count;
170         DEBUG(10,("secrets_named_mutex_release: ref_count for mutex %s = %u\n", name, (uint_t)ref_count ));
171 }
172