Fix some nonempty blank lines
[kamenim/samba-autobuild/.git] / source3 / libsmb / trustdom_cache.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Trusted domain names cache on top of gencache.
5
6    Copyright (C) Rafal Szczesniak       2002
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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_ALL     /* there's no proper class yet */
26
27 #define TDOMKEY_FMT  "TDOM/%s"
28 #define TDOMTSKEY    "TDOMCACHE/TIMESTAMP"
29
30
31 /**
32  * @file trustdom_cache.c
33  *
34  * Implementation of trusted domain names cache useful when
35  * samba acts as domain member server. In such case, caching
36  * domain names currently trusted gives a performance gain
37  * because there's no need to query PDC each time we need
38  * list of trusted domains
39  **/
40
41 /**
42  * Initialise trustdom name caching system. Call gencache
43  * initialisation routine to perform necessary activities.
44  *
45  * @return true upon successful cache initialisation or
46  *         false if cache init failed
47  **/
48
49 bool trustdom_cache_enable(void)
50 {
51         /* Init trustdom cache by calling gencache initialisation */
52         if (!gencache_init()) {
53                 DEBUG(2, ("trustdomcache_enable: Couldn't initialise trustdom cache on top of gencache.\n"));
54                 return False;
55         }
56
57         return True;
58 }
59
60
61 /**
62  * Shutdown trustdom name caching system. Calls gencache
63  * shutdown function.
64  *
65  * @return true upon successful cache close or
66  *         false if it failed
67  **/
68
69 bool trustdom_cache_shutdown(void)
70 {
71         /* Close trustdom cache by calling gencache shutdown */
72         if (!gencache_shutdown()) {
73                 DEBUG(2, ("trustdomcache_shutdown: Couldn't shutdown trustdom cache on top of gencache.\n"));
74                 return False;
75         }
76
77         return True;
78 }
79
80
81 /**
82  * Form up trustdom name key. It is based only
83  * on domain name now.
84  *
85  * @param name trusted domain name
86  * @return cache key for use in gencache mechanism
87  **/
88
89 static char* trustdom_cache_key(const char* name)
90 {
91         char* keystr = NULL;
92         asprintf_strupper_m(&keystr, TDOMKEY_FMT, name);
93
94         return keystr;
95 }
96
97
98 /**
99  * Store trusted domain in gencache as the domain name (key)
100  * and trusted domain's SID (value)
101  *
102  * @param name trusted domain name
103  * @param alt_name alternative trusted domain name (used in ADS domains)
104  * @param sid trusted domain's SID
105  * @param timeout cache entry expiration time
106  * @return true upon successful value storing or
107  *         false if store attempt failed
108  **/
109  
110 bool trustdom_cache_store(char* name, char* alt_name, const DOM_SID *sid,
111                           time_t timeout)
112 {
113         char *key, *alt_key;
114         fstring sid_string;
115         bool ret;
116
117         /*
118          * we use gecache call to avoid annoying debug messages
119          * about initialised trustdom 
120          */
121         if (!gencache_init())
122                 return False;
123
124         DEBUG(5, ("trustdom_store: storing SID %s of domain %s\n",
125                   sid_string_dbg(sid), name));
126
127         key = trustdom_cache_key(name);
128         alt_key = alt_name ? trustdom_cache_key(alt_name) : NULL;
129
130         /* Generate string representation domain SID */
131         sid_to_fstring(sid_string, sid);
132
133         /*
134          * try to put the names in the cache
135          */
136         if (alt_key) {
137                 ret = gencache_set(alt_key, sid_string, timeout);
138                 if ( ret ) {
139                         ret = gencache_set(key, sid_string, timeout);
140                 }
141                 SAFE_FREE(alt_key);
142                 SAFE_FREE(key);
143                 return ret;
144         }
145
146         ret = gencache_set(key, sid_string, timeout);
147         SAFE_FREE(key);
148         return ret;
149 }
150
151
152 /**
153  * Fetch trusted domain's SID from the gencache.
154  * This routine can also be used to check whether given
155  * domain is currently trusted one.
156  *
157  * @param name trusted domain name
158  * @param sid trusted domain's SID to be returned
159  * @return true if entry is found or
160  *         false if has expired/doesn't exist
161  **/
162
163 bool trustdom_cache_fetch(const char* name, DOM_SID* sid)
164 {
165         char *key = NULL, *value = NULL;
166         time_t timeout;
167
168         /* init the cache */
169         if (!gencache_init())
170                 return False;
171
172         /* exit now if null pointers were passed as they're required further */
173         if (!sid)
174                 return False;
175
176         /* prepare a key and get the value */
177         key = trustdom_cache_key(name);
178         if (!key)
179                 return False;
180
181         if (!gencache_get(key, &value, &timeout)) {
182                 DEBUG(5, ("no entry for trusted domain %s found.\n", name));
183                 SAFE_FREE(key);
184                 return False;
185         } else {
186                 SAFE_FREE(key);
187                 DEBUG(5, ("trusted domain %s found (%s)\n", name, value));
188         }
189
190         /* convert sid string representation into DOM_SID structure */
191         if(! string_to_sid(sid, value)) {
192                 sid = NULL;
193                 SAFE_FREE(value);
194                 return False;
195         }
196
197         SAFE_FREE(value);
198         return True;
199 }
200
201
202 /*******************************************************************
203  fetch the timestamp from the last update 
204 *******************************************************************/
205
206 uint32 trustdom_cache_fetch_timestamp( void )
207 {
208         char *value = NULL;
209         time_t timeout;
210         uint32 timestamp;
211
212         /* init the cache */
213         if (!gencache_init()) 
214                 return False;
215
216         if (!gencache_get(TDOMTSKEY, &value, &timeout)) {
217                 DEBUG(5, ("no timestamp for trusted domain cache located.\n"));
218                 SAFE_FREE(value);
219                 return 0;
220         } 
221
222         timestamp = atoi(value);
223
224         SAFE_FREE(value);
225         return timestamp;
226 }
227
228 /*******************************************************************
229  store the timestamp from the last update 
230 *******************************************************************/
231
232 bool trustdom_cache_store_timestamp( uint32 t, time_t timeout )
233 {
234         fstring value;
235
236         /* init the cache */
237         if (!gencache_init()) 
238                 return False;
239
240         fstr_sprintf(value, "%d", t );
241
242         if (!gencache_set(TDOMTSKEY, value, timeout)) {
243                 DEBUG(5, ("failed to set timestamp for trustdom_cache\n"));
244                 return False;
245         } 
246
247         return True;
248 }
249
250
251 /**
252  * Delete single trustdom entry. Look at the
253  * gencache_iterate definition.
254  *
255  **/
256
257 static void flush_trustdom_name(const char* key, const char *value, time_t timeout, void* dptr)
258 {
259         gencache_del(key);
260         DEBUG(5, ("Deleting entry %s\n", key));
261 }
262
263
264 /**
265  * Flush all the trusted domains entries from the cache.
266  **/
267
268 void trustdom_cache_flush(void)
269 {
270         if (!gencache_init())
271                 return;
272
273         /* 
274          * iterate through each TDOM cache's entry and flush it
275          * by flush_trustdom_name function
276          */
277         gencache_iterate(flush_trustdom_name, NULL, trustdom_cache_key("*"));
278         DEBUG(5, ("Trusted domains cache flushed\n"));
279 }
280
281 /********************************************************************
282  update the trustdom_cache if needed 
283 ********************************************************************/
284 #define TRUSTDOM_UPDATE_INTERVAL        600
285
286 void update_trustdom_cache( void )
287 {
288         char **domain_names;
289         DOM_SID *dom_sids;
290         uint32 num_domains;
291         uint32 last_check;
292         int time_diff;
293         TALLOC_CTX *mem_ctx = NULL;
294         time_t now = time(NULL);
295         int i;
296
297         /* get the timestamp.  We have to initialise it if the last timestamp == 0 */   
298         if ( (last_check = trustdom_cache_fetch_timestamp()) == 0 ) 
299                 trustdom_cache_store_timestamp(0, now+TRUSTDOM_UPDATE_INTERVAL);
300
301         time_diff = (int) (now - last_check);
302
303         if ( (time_diff > 0) && (time_diff < TRUSTDOM_UPDATE_INTERVAL) ) {
304                 DEBUG(10,("update_trustdom_cache: not time to update trustdom_cache yet\n"));
305                 return;
306         }
307
308         /* note that we don't lock the timestamp. This prevents this
309            smbd from blocking all other smbd daemons while we
310            enumerate the trusted domains */
311         trustdom_cache_store_timestamp(now, now+TRUSTDOM_UPDATE_INTERVAL);
312
313         if ( !(mem_ctx = talloc_init("update_trustdom_cache")) ) {
314                 DEBUG(0,("update_trustdom_cache: talloc_init() failed!\n"));
315                 goto done;
316         }
317
318         /* get the domains and store them */
319
320         if ( enumerate_domain_trusts(mem_ctx, lp_workgroup(), &domain_names, 
321                 &num_domains, &dom_sids)) {
322                 for ( i=0; i<num_domains; i++ ) {
323                         trustdom_cache_store( domain_names[i], NULL, &dom_sids[i], 
324                                 now+TRUSTDOM_UPDATE_INTERVAL);
325                 }               
326         } else {
327                 /* we failed to fetch the list of trusted domains - restore the old
328                    timestamp */
329                 trustdom_cache_store_timestamp(last_check, 
330                                                last_check+TRUSTDOM_UPDATE_INTERVAL);
331         }
332
333 done:   
334         talloc_destroy( mem_ctx );
335
336         return;
337 }