s3-libsmbclient: Fix crash bug in SMBC_parse_path().
[ira/wip.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         return True;
52 }
53
54
55 /**
56  * Shutdown trustdom name caching system. Calls gencache
57  * shutdown function.
58  *
59  * @return true upon successful cache close or
60  *         false if it failed
61  **/
62
63 bool trustdom_cache_shutdown(void)
64 {
65         return True;
66 }
67
68
69 /**
70  * Form up trustdom name key. It is based only
71  * on domain name now.
72  *
73  * @param name trusted domain name
74  * @return cache key for use in gencache mechanism
75  **/
76
77 static char* trustdom_cache_key(const char* name)
78 {
79         char* keystr = NULL;
80         asprintf_strupper_m(&keystr, TDOMKEY_FMT, name);
81
82         return keystr;
83 }
84
85
86 /**
87  * Store trusted domain in gencache as the domain name (key)
88  * and trusted domain's SID (value)
89  *
90  * @param name trusted domain name
91  * @param alt_name alternative trusted domain name (used in ADS domains)
92  * @param sid trusted domain's SID
93  * @param timeout cache entry expiration time
94  * @return true upon successful value storing or
95  *         false if store attempt failed
96  **/
97  
98 bool trustdom_cache_store(char* name, char* alt_name, const DOM_SID *sid,
99                           time_t timeout)
100 {
101         char *key, *alt_key;
102         fstring sid_string;
103         bool ret;
104
105         DEBUG(5, ("trustdom_store: storing SID %s of domain %s\n",
106                   sid_string_dbg(sid), name));
107
108         key = trustdom_cache_key(name);
109         alt_key = alt_name ? trustdom_cache_key(alt_name) : NULL;
110
111         /* Generate string representation domain SID */
112         sid_to_fstring(sid_string, sid);
113
114         /*
115          * try to put the names in the cache
116          */
117         if (alt_key) {
118                 ret = gencache_set(alt_key, sid_string, timeout);
119                 if ( ret ) {
120                         ret = gencache_set(key, sid_string, timeout);
121                 }
122                 SAFE_FREE(alt_key);
123                 SAFE_FREE(key);
124                 return ret;
125         }
126
127         ret = gencache_set(key, sid_string, timeout);
128         SAFE_FREE(key);
129         return ret;
130 }
131
132
133 /**
134  * Fetch trusted domain's SID from the gencache.
135  * This routine can also be used to check whether given
136  * domain is currently trusted one.
137  *
138  * @param name trusted domain name
139  * @param sid trusted domain's SID to be returned
140  * @return true if entry is found or
141  *         false if has expired/doesn't exist
142  **/
143
144 bool trustdom_cache_fetch(const char* name, DOM_SID* sid)
145 {
146         char *key = NULL, *value = NULL;
147         time_t timeout;
148
149         /* exit now if null pointers were passed as they're required further */
150         if (!sid)
151                 return False;
152
153         /* prepare a key and get the value */
154         key = trustdom_cache_key(name);
155         if (!key)
156                 return False;
157
158         if (!gencache_get(key, &value, &timeout)) {
159                 DEBUG(5, ("no entry for trusted domain %s found.\n", name));
160                 SAFE_FREE(key);
161                 return False;
162         } else {
163                 SAFE_FREE(key);
164                 DEBUG(5, ("trusted domain %s found (%s)\n", name, value));
165         }
166
167         /* convert sid string representation into DOM_SID structure */
168         if(! string_to_sid(sid, value)) {
169                 sid = NULL;
170                 SAFE_FREE(value);
171                 return False;
172         }
173
174         SAFE_FREE(value);
175         return True;
176 }
177
178
179 /*******************************************************************
180  fetch the timestamp from the last update 
181 *******************************************************************/
182
183 uint32 trustdom_cache_fetch_timestamp( void )
184 {
185         char *value = NULL;
186         time_t timeout;
187         uint32 timestamp;
188
189         if (!gencache_get(TDOMTSKEY, &value, &timeout)) {
190                 DEBUG(5, ("no timestamp for trusted domain cache located.\n"));
191                 SAFE_FREE(value);
192                 return 0;
193         } 
194
195         timestamp = atoi(value);
196
197         SAFE_FREE(value);
198         return timestamp;
199 }
200
201 /*******************************************************************
202  store the timestamp from the last update 
203 *******************************************************************/
204
205 bool trustdom_cache_store_timestamp( uint32 t, time_t timeout )
206 {
207         fstring value;
208
209         fstr_sprintf(value, "%d", t );
210
211         if (!gencache_set(TDOMTSKEY, value, timeout)) {
212                 DEBUG(5, ("failed to set timestamp for trustdom_cache\n"));
213                 return False;
214         } 
215
216         return True;
217 }
218
219
220 /**
221  * Delete single trustdom entry. Look at the
222  * gencache_iterate definition.
223  *
224  **/
225
226 static void flush_trustdom_name(const char* key, const char *value, time_t timeout, void* dptr)
227 {
228         gencache_del(key);
229         DEBUG(5, ("Deleting entry %s\n", key));
230 }
231
232
233 /**
234  * Flush all the trusted domains entries from the cache.
235  **/
236
237 void trustdom_cache_flush(void)
238 {
239         /* 
240          * iterate through each TDOM cache's entry and flush it
241          * by flush_trustdom_name function
242          */
243         gencache_iterate(flush_trustdom_name, NULL, trustdom_cache_key("*"));
244         DEBUG(5, ("Trusted domains cache flushed\n"));
245 }
246
247 /********************************************************************
248  update the trustdom_cache if needed 
249 ********************************************************************/
250 #define TRUSTDOM_UPDATE_INTERVAL        600
251
252 void update_trustdom_cache( void )
253 {
254         char **domain_names;
255         DOM_SID *dom_sids;
256         uint32 num_domains;
257         uint32 last_check;
258         int time_diff;
259         TALLOC_CTX *mem_ctx = NULL;
260         time_t now = time(NULL);
261         int i;
262
263         /* get the timestamp.  We have to initialise it if the last timestamp == 0 */   
264         if ( (last_check = trustdom_cache_fetch_timestamp()) == 0 ) 
265                 trustdom_cache_store_timestamp(0, now+TRUSTDOM_UPDATE_INTERVAL);
266
267         time_diff = (int) (now - last_check);
268
269         if ( (time_diff > 0) && (time_diff < TRUSTDOM_UPDATE_INTERVAL) ) {
270                 DEBUG(10,("update_trustdom_cache: not time to update trustdom_cache yet\n"));
271                 return;
272         }
273
274         /* note that we don't lock the timestamp. This prevents this
275            smbd from blocking all other smbd daemons while we
276            enumerate the trusted domains */
277         trustdom_cache_store_timestamp(now, now+TRUSTDOM_UPDATE_INTERVAL);
278
279         if ( !(mem_ctx = talloc_init("update_trustdom_cache")) ) {
280                 DEBUG(0,("update_trustdom_cache: talloc_init() failed!\n"));
281                 goto done;
282         }
283
284         /* get the domains and store them */
285
286         if ( enumerate_domain_trusts(mem_ctx, lp_workgroup(), &domain_names, 
287                 &num_domains, &dom_sids)) {
288                 for ( i=0; i<num_domains; i++ ) {
289                         trustdom_cache_store( domain_names[i], NULL, &dom_sids[i], 
290                                 now+TRUSTDOM_UPDATE_INTERVAL);
291                 }               
292         } else {
293                 /* we failed to fetch the list of trusted domains - restore the old
294                    timestamp */
295                 trustdom_cache_store_timestamp(last_check, 
296                                                last_check+TRUSTDOM_UPDATE_INTERVAL);
297         }
298
299 done:   
300         talloc_destroy( mem_ctx );
301
302         return;
303 }