Final piece of support needed to find iconv libraries on FreeBSD.
[ira/wip.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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
27
28 static TDB_CONTEXT *netsamlogon_tdb = NULL;
29
30 /***********************************************************************
31  open the tdb
32  ***********************************************************************/
33  
34 BOOL netsamlogon_cache_init(void)
35 {
36         if (!netsamlogon_tdb) {
37                 netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0,
38                                                    TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
39         }
40
41         return (netsamlogon_tdb != NULL);
42 }
43
44
45 /***********************************************************************
46  Shutdown samlogon_cache database
47 ***********************************************************************/
48
49 BOOL netsamlogon_cache_shutdown(void)
50 {
51         if(netsamlogon_tdb)
52                 return (tdb_close(netsamlogon_tdb) == 0);
53                 
54         return True;
55 }
56
57 /***********************************************************************
58  Clear cache getpwnam and getgroups entries from the winbindd cache
59 ***********************************************************************/
60 void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user)
61 {
62         fstring domain;
63         TDB_DATA key;
64         BOOL got_tdb = False;
65
66         /* We may need to call this function from smbd which will not have
67            winbindd_cache.tdb open.  Open the tdb if a NULL is passed. */
68
69         if (!tdb) {
70                 tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
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         unistr2_to_ascii(domain, &user->uni_logon_dom, sizeof(domain) - 1);
80
81         /* Clear U/DOMAIN/RID cache entry */
82
83         asprintf(&key.dptr, "U/%s/%d", domain, user->user_rid);
84         key.dsize = strlen(key.dptr) - 1; /* keys are not NULL terminated */
85
86         DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key.dptr));
87
88         tdb_delete(tdb, key);
89
90         SAFE_FREE(key.dptr);
91
92         /* Clear UG/DOMAIN/RID cache entry */
93
94         asprintf(&key.dptr, "UG/%s/%d", domain, user->user_rid);
95         key.dsize = strlen(key.dptr) - 1; /* keys are not NULL terminated */
96
97         DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key.dptr));
98
99         tdb_delete(tdb, key);
100
101         SAFE_FREE(key.dptr);
102
103         if (got_tdb)
104                 tdb_close(tdb);
105 }
106
107 /***********************************************************************
108  Store a NET_USER_INFO_3 structure in a tdb for later user 
109 ***********************************************************************/
110
111 BOOL netsamlogon_cache_store(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
112 {
113         TDB_DATA        data;
114         fstring         keystr;
115         prs_struct      ps;
116         BOOL            result = False;
117         DOM_SID         user_sid;
118         time_t          t = time(NULL);
119         
120
121         if (!netsamlogon_cache_init()) {
122                 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB));
123                 return False;
124         }
125
126         sid_copy( &user_sid, &user->dom_sid.sid );
127         sid_append_rid( &user_sid, user->user_rid );
128
129         /* Prepare key as DOMAIN-SID/USER-RID string */
130         slprintf(keystr, sizeof(keystr), "%s", sid_string_static(&user_sid));
131
132         DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
133                 
134         /* Prepare data */
135         
136         prs_init( &ps,MAX_PDU_FRAG_LEN , mem_ctx, MARSHALL);
137         
138         if ( !prs_uint32( "timestamp", &ps, 0, (uint32*)&t ) )
139                 return False;
140         
141         if ( net_io_user_info3("", user, &ps, 0, 3) ) 
142         {
143                 data.dsize = prs_offset( &ps );
144                 data.dptr = prs_data_p( &ps );
145
146                 if (tdb_store_by_string(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1)
147                         result = True;
148                 
149                 prs_mem_free( &ps );
150         }
151                 
152         return result;
153 }
154
155 /***********************************************************************
156  Retrieves a NET_USER_INFO_3 structure from a tdb.  Caller must 
157  free the user_info struct (malloc()'d memory)
158 ***********************************************************************/
159
160 NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, DOM_SID *user_sid)
161 {
162         NET_USER_INFO_3 *user = NULL;
163         TDB_DATA        data, key;
164         prs_struct      ps;
165         fstring         keystr;
166         uint32          t;
167         
168         if (!netsamlogon_cache_init()) {
169                 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB));
170                 return False;
171         }
172
173         /* Prepare key as DOMAIN-SID/USER-RID string */
174         slprintf(keystr, sizeof(keystr), "%s", sid_string_static(user_sid));
175         DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
176         key.dptr = keystr;
177         key.dsize = strlen(keystr)+1;
178         data = tdb_fetch( netsamlogon_tdb, key );
179         
180         if ( data.dptr ) {
181                 
182                 if ( (user = (NET_USER_INFO_3*)malloc(sizeof(NET_USER_INFO_3))) == NULL )
183                         return NULL;
184                         
185                 prs_init( &ps, 0, mem_ctx, UNMARSHALL );
186                 prs_give_memory( &ps, data.dptr, data.dsize, True );
187                 
188                 if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) {
189                         prs_mem_free( &ps );
190                         return False;
191                 }
192                 
193                 if ( !net_io_user_info3("", user, &ps, 0, 3) ) {
194                         SAFE_FREE( user );
195                 }
196                         
197                 prs_mem_free( &ps );
198
199 #if 0   /* The netsamlogon cache needs to hang around.  Something about 
200            this feels wrong, but it is the only way we can get all of the
201            groups.  The old universal groups cache didn't expire either.
202            --jerry */
203         {
204                 time_t          now = time(NULL);
205                 uint32          time_diff;
206            
207                 /* is the entry expired? */
208                 time_diff = now - t;
209                 
210                 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
211                         DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
212                         tdb_delete( netsamlogon_tdb, key );
213                         SAFE_FREE( user );
214                 }
215 #endif
216         }
217         
218         return user;
219 }
220
221 BOOL netsamlogon_cache_have(DOM_SID *user_sid)
222 {
223         TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
224         NET_USER_INFO_3 *user = NULL;
225         BOOL result;
226
227         if (!mem_ctx)
228                 return False;
229
230         user = netsamlogon_cache_get(mem_ctx, user_sid);
231
232         result = (user != NULL);
233
234         talloc_destroy(mem_ctx);
235         SAFE_FREE(user);
236
237         return result;
238 }