RIP BOOL. Convert BOOL -> bool. I found a few interesting
[bbaumbach/samba-autobuild/.git] / source3 / libsmb / samlogon_cache.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Net_sam_logon info3 helpers
4    Copyright (C) Alexander Bokovoy              2002.
5    Copyright (C) Andrew Bartlett                2002.
6    Copyright (C) Gerald Carter                  2003.
7    Copyright (C) Tim Potter                     2003.
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24
25 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
26
27 static TDB_CONTEXT *netsamlogon_tdb = NULL;
28
29 /***********************************************************************
30  open the tdb
31  ***********************************************************************/
32  
33 bool netsamlogon_cache_init(void)
34 {
35         if (!netsamlogon_tdb) {
36                 netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0,
37                                                    TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
38         }
39
40         return (netsamlogon_tdb != NULL);
41 }
42
43
44 /***********************************************************************
45  Shutdown samlogon_cache database
46 ***********************************************************************/
47
48 bool netsamlogon_cache_shutdown(void)
49 {
50         if(netsamlogon_tdb)
51                 return (tdb_close(netsamlogon_tdb) == 0);
52                 
53         return True;
54 }
55
56 /***********************************************************************
57  Clear cache getpwnam and getgroups entries from the winbindd cache
58 ***********************************************************************/
59 void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user)
60 {
61         bool got_tdb = False;
62         DOM_SID sid;
63         fstring key_str, sid_string;
64
65         /* We may need to call this function from smbd which will not have
66            winbindd_cache.tdb open.  Open the tdb if a NULL is passed. */
67
68         if (!tdb) {
69                 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 
70                                    WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
71                                    TDB_DEFAULT, O_RDWR, 0600);
72                 if (!tdb) {
73                         DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n"));
74                         return;
75                 }
76                 got_tdb = True;
77         }
78
79         sid_copy(&sid, &user->dom_sid.sid);
80         sid_append_rid(&sid, user->user_rid);
81
82         /* Clear U/SID cache entry */
83
84         fstr_sprintf(key_str, "U/%s", sid_to_string(sid_string, &sid));
85
86         DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str));
87
88         tdb_delete(tdb, string_tdb_data(key_str));
89
90         /* Clear UG/SID cache entry */
91
92         fstr_sprintf(key_str, "UG/%s", sid_to_string(sid_string, &sid));
93
94         DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str));
95
96         tdb_delete(tdb, string_tdb_data(key_str));
97
98         if (got_tdb)
99                 tdb_close(tdb);
100 }
101
102 /***********************************************************************
103  Store a NET_USER_INFO_3 structure in a tdb for later user 
104  username should be in UTF-8 format
105 ***********************************************************************/
106
107 bool netsamlogon_cache_store( const char *username, NET_USER_INFO_3 *user )
108 {
109         TDB_DATA        data;
110         fstring         keystr;
111         prs_struct      ps;
112         bool            result = False;
113         DOM_SID         user_sid;
114         time_t          t = time(NULL);
115         TALLOC_CTX      *mem_ctx;
116         
117
118         if (!netsamlogon_cache_init()) {
119                 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB));
120                 return False;
121         }
122
123         sid_copy( &user_sid, &user->dom_sid.sid );
124         sid_append_rid( &user_sid, user->user_rid );
125
126         /* Prepare key as DOMAIN-SID/USER-RID string */
127         slprintf(keystr, sizeof(keystr), "%s", sid_string_static(&user_sid));
128
129         DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
130         
131         /* only Samba fills in the username, not sure why NT doesn't */
132         /* so we fill it in since winbindd_getpwnam() makes use of it */
133         
134         if ( !user->uni_user_name.buffer ) {
135                 init_unistr2( &user->uni_user_name, username, UNI_STR_TERMINATE );
136                 init_uni_hdr( &user->hdr_user_name, &user->uni_user_name );
137         }
138                 
139         /* Prepare data */
140         
141         if ( !(mem_ctx = TALLOC_P( NULL, int )) ) {
142                 DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
143                 return False;
144         }
145
146         prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
147         
148         {
149                 uint32 ts = (uint32)t;
150                 if ( !prs_uint32( "timestamp", &ps, 0, &ts ) )
151                         return False;
152         }
153         
154         if ( net_io_user_info3("", user, &ps, 0, 3, 0) ) 
155         {
156                 data.dsize = prs_offset( &ps );
157                 data.dptr = (uint8 *)prs_data_p( &ps );
158
159                 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1)
160                         result = True;
161                 
162                 prs_mem_free( &ps );
163         }
164
165         TALLOC_FREE( mem_ctx );
166                 
167         return result;
168 }
169
170 /***********************************************************************
171  Retrieves a NET_USER_INFO_3 structure from a tdb.  Caller must 
172  free the user_info struct (malloc()'d memory)
173 ***********************************************************************/
174
175 NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
176 {
177         NET_USER_INFO_3 *user = NULL;
178         TDB_DATA        data;
179         prs_struct      ps;
180         fstring         keystr;
181         uint32          t;
182         
183         if (!netsamlogon_cache_init()) {
184                 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n", NETSAMLOGON_TDB));
185                 return False;
186         }
187
188         /* Prepare key as DOMAIN-SID/USER-RID string */
189         slprintf(keystr, sizeof(keystr), "%s", sid_string_static(user_sid));
190         DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
191         data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
192         
193         if ( data.dptr ) {
194
195                 user = TALLOC_ZERO_P(mem_ctx, NET_USER_INFO_3);
196                 if (user == NULL) {
197                         return NULL;
198                 }
199
200                 prs_init( &ps, 0, mem_ctx, UNMARSHALL );
201                 prs_give_memory( &ps, (char *)data.dptr, data.dsize, True );
202                 
203                 if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) {
204                         prs_mem_free( &ps );
205                         TALLOC_FREE(user);
206                         return False;
207                 }
208                 
209                 if ( !net_io_user_info3("", user, &ps, 0, 3, 0) ) {
210                         TALLOC_FREE( user );
211                 }
212                         
213                 prs_mem_free( &ps );
214
215 #if 0   /* The netsamlogon cache needs to hang around.  Something about 
216            this feels wrong, but it is the only way we can get all of the
217            groups.  The old universal groups cache didn't expire either.
218            --jerry */
219         {
220                 time_t          now = time(NULL);
221                 uint32          time_diff;
222            
223                 /* is the entry expired? */
224                 time_diff = now - t;
225                 
226                 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
227                         DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
228                         tdb_delete( netsamlogon_tdb, key );
229                         TALLOC_FREE( user );
230                 }
231 #endif
232         }
233         
234         return user;
235 }
236
237 bool netsamlogon_cache_have(const DOM_SID *user_sid)
238 {
239         TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
240         NET_USER_INFO_3 *user = NULL;
241         bool result;
242
243         if (!mem_ctx)
244                 return False;
245
246         user = netsamlogon_cache_get(mem_ctx, user_sid);
247
248         result = (user != NULL);
249
250         talloc_destroy(mem_ctx);
251
252         return result;
253 }