source: vendor/3.6.0/source3/libsmb/samlogon_cache.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 7.7 KB
Line 
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 Copyright (C) Guenther Deschner 2008.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "system/filesys.h"
26#include "librpc/gen_ndr/ndr_krb5pac.h"
27#include "../libcli/security/security.h"
28#include "util_tdb.h"
29
30#define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
31
32static TDB_CONTEXT *netsamlogon_tdb = NULL;
33
34/***********************************************************************
35 open the tdb
36 ***********************************************************************/
37
38bool netsamlogon_cache_init(void)
39{
40 bool first_try = true;
41 const char *path = NULL;
42 int ret;
43 struct tdb_context *tdb;
44
45 if (netsamlogon_tdb) {
46 return true;
47 }
48
49 path = cache_path(NETSAMLOGON_TDB);
50again:
51 tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
52 O_RDWR | O_CREAT, 0600);
53 if (tdb == NULL) {
54 DEBUG(0,("tdb_open_log('%s') - failed\n", path));
55 goto clear;
56 }
57
58 ret = tdb_check(tdb, NULL, NULL);
59 if (ret != 0) {
60 tdb_close(tdb);
61 DEBUG(0,("tdb_check('%s') - failed\n", path));
62 goto clear;
63 }
64
65 netsamlogon_tdb = tdb;
66 return true;
67
68clear:
69 if (!first_try) {
70 return false;
71 }
72 first_try = false;
73
74 DEBUG(0,("retry after CLEAR_IF_FIRST for '%s'\n", path));
75 tdb = tdb_open_log(path, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
76 O_RDWR | O_CREAT, 0600);
77 if (tdb) {
78 tdb_close(tdb);
79 goto again;
80 }
81 DEBUG(0,("tdb_open_log(%s) with CLEAR_IF_FIRST - failed\n", path));
82
83 return false;
84}
85
86
87/***********************************************************************
88 Shutdown samlogon_cache database
89***********************************************************************/
90
91bool netsamlogon_cache_shutdown(void)
92{
93 if (netsamlogon_tdb) {
94 return (tdb_close(netsamlogon_tdb) == 0);
95 }
96
97 return true;
98}
99
100/***********************************************************************
101 Clear cache getpwnam and getgroups entries from the winbindd cache
102***********************************************************************/
103
104void netsamlogon_clear_cached_user(const struct dom_sid *user_sid)
105{
106 fstring keystr;
107
108 if (!netsamlogon_cache_init()) {
109 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
110 "%s for write!\n",
111 NETSAMLOGON_TDB));
112 return;
113 }
114
115 /* Prepare key as DOMAIN-SID/USER-RID string */
116 sid_to_fstring(keystr, user_sid);
117
118 DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
119
120 tdb_delete_bystring(netsamlogon_tdb, keystr);
121}
122
123/***********************************************************************
124 Store a netr_SamInfo3 structure in a tdb for later user
125 username should be in UTF-8 format
126***********************************************************************/
127
128bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
129{
130 TDB_DATA data;
131 fstring keystr;
132 bool result = false;
133 struct dom_sid user_sid;
134 time_t t = time(NULL);
135 TALLOC_CTX *mem_ctx;
136 DATA_BLOB blob;
137 enum ndr_err_code ndr_err;
138 struct netsamlogoncache_entry r;
139
140 if (!info3) {
141 return false;
142 }
143
144 if (!netsamlogon_cache_init()) {
145 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
146 NETSAMLOGON_TDB));
147 return false;
148 }
149
150 sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid);
151
152 /* Prepare key as DOMAIN-SID/USER-RID string */
153 sid_to_fstring(keystr, &user_sid);
154
155 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
156
157 /* Prepare data */
158
159 if (!(mem_ctx = TALLOC_P( NULL, int))) {
160 DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
161 return false;
162 }
163
164 /* only Samba fills in the username, not sure why NT doesn't */
165 /* so we fill it in since winbindd_getpwnam() makes use of it */
166
167 if (!info3->base.account_name.string) {
168 info3->base.account_name.string = talloc_strdup(info3, username);
169 }
170
171 r.timestamp = t;
172 r.info3 = *info3;
173
174 if (DEBUGLEVEL >= 10) {
175 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
176 }
177
178 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r,
179 (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
180 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
181 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
182 TALLOC_FREE(mem_ctx);
183 return false;
184 }
185
186 data.dsize = blob.length;
187 data.dptr = blob.data;
188
189 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) {
190 result = true;
191 }
192
193 TALLOC_FREE(mem_ctx);
194
195 return result;
196}
197
198/***********************************************************************
199 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
200 free the user_info struct (malloc()'d memory)
201***********************************************************************/
202
203struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
204{
205 struct netr_SamInfo3 *info3 = NULL;
206 TDB_DATA data;
207 fstring keystr, tmp;
208 enum ndr_err_code ndr_err;
209 DATA_BLOB blob;
210 struct netsamlogoncache_entry r;
211
212 if (!netsamlogon_cache_init()) {
213 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
214 NETSAMLOGON_TDB));
215 return false;
216 }
217
218 /* Prepare key as DOMAIN-SID/USER-RID string */
219 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
220 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
221 data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
222
223 if (!data.dptr) {
224 return NULL;
225 }
226
227 info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3);
228 if (!info3) {
229 goto done;
230 }
231
232 blob = data_blob_const(data.dptr, data.dsize);
233
234 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
235 (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
236
237 if (DEBUGLEVEL >= 10) {
238 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
239 }
240
241 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
242 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
243 tdb_delete(netsamlogon_tdb, data);
244 TALLOC_FREE(info3);
245 goto done;
246 }
247
248 info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
249 sizeof(r.info3));
250
251 done:
252 SAFE_FREE(data.dptr);
253
254 return info3;
255
256#if 0 /* The netsamlogon cache needs to hang around. Something about
257 this feels wrong, but it is the only way we can get all of the
258 groups. The old universal groups cache didn't expire either.
259 --jerry */
260 {
261 time_t now = time(NULL);
262 uint32 time_diff;
263
264 /* is the entry expired? */
265 time_diff = now - t;
266
267 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
268 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
269 tdb_delete( netsamlogon_tdb, key );
270 TALLOC_FREE( user );
271 }
272 }
273#endif
274}
275
276bool netsamlogon_cache_have(const struct dom_sid *user_sid)
277{
278 TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
279 struct netr_SamInfo3 *info3 = NULL;
280 bool result;
281
282 if (!mem_ctx)
283 return False;
284
285 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
286
287 result = (info3 != NULL);
288
289 talloc_destroy(mem_ctx);
290
291 return result;
292}
Note: See TracBrowser for help on using the repository browser.