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.
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.
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.
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/>.
25 #include "system/filesys.h"
26 #include "librpc/gen_ndr/ndr_krb5pac.h"
27 #include "../libcli/security/security.h"
30 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
32 static TDB_CONTEXT
*netsamlogon_tdb
= NULL
;
34 /***********************************************************************
36 ***********************************************************************/
38 bool netsamlogon_cache_init(void)
40 bool first_try
= true;
41 const char *path
= NULL
;
43 struct tdb_context
*tdb
;
45 if (netsamlogon_tdb
) {
49 path
= cache_path(NETSAMLOGON_TDB
);
51 tdb
= tdb_open_log(path
, 0, TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
,
52 O_RDWR
| O_CREAT
, 0600);
54 DEBUG(0,("tdb_open_log('%s') - failed\n", path
));
58 ret
= tdb_check(tdb
, NULL
, NULL
);
61 DEBUG(0,("tdb_check('%s') - failed\n", path
));
65 netsamlogon_tdb
= tdb
;
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);
81 DEBUG(0,("tdb_open_log(%s) with CLEAR_IF_FIRST - failed\n", path
));
87 /***********************************************************************
88 Shutdown samlogon_cache database
89 ***********************************************************************/
91 bool netsamlogon_cache_shutdown(void)
93 if (netsamlogon_tdb
) {
94 return (tdb_close(netsamlogon_tdb
) == 0);
100 /***********************************************************************
101 Clear cache getpwnam and getgroups entries from the winbindd cache
102 ***********************************************************************/
104 void netsamlogon_clear_cached_user(const struct dom_sid
*user_sid
)
108 if (!netsamlogon_cache_init()) {
109 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
115 /* Prepare key as DOMAIN-SID/USER-RID string */
116 sid_to_fstring(keystr
, user_sid
);
118 DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr
));
120 tdb_delete_bystring(netsamlogon_tdb
, keystr
);
123 /***********************************************************************
124 Store a netr_SamInfo3 structure in a tdb for later user
125 username should be in UTF-8 format
126 ***********************************************************************/
128 bool netsamlogon_cache_store(const char *username
, struct netr_SamInfo3
*info3
)
133 struct dom_sid user_sid
;
134 time_t t
= time(NULL
);
137 enum ndr_err_code ndr_err
;
138 struct netsamlogoncache_entry r
;
144 if (!netsamlogon_cache_init()) {
145 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
150 sid_compose(&user_sid
, info3
->base
.domain_sid
, info3
->base
.rid
);
152 /* Prepare key as DOMAIN-SID/USER-RID string */
153 sid_to_fstring(keystr
, &user_sid
);
155 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr
));
159 if (!(mem_ctx
= TALLOC_P( NULL
, int))) {
160 DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
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 */
167 if (!info3
->base
.account_name
.string
) {
168 info3
->base
.account_name
.string
= talloc_strdup(info3
, username
);
174 if (DEBUGLEVEL
>= 10) {
175 NDR_PRINT_DEBUG(netsamlogoncache_entry
, &r
);
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
);
186 data
.dsize
= blob
.length
;
187 data
.dptr
= blob
.data
;
189 if (tdb_store_bystring(netsamlogon_tdb
, keystr
, data
, TDB_REPLACE
) != -1) {
193 TALLOC_FREE(mem_ctx
);
198 /***********************************************************************
199 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
200 free the user_info struct (malloc()'d memory)
201 ***********************************************************************/
203 struct netr_SamInfo3
*netsamlogon_cache_get(TALLOC_CTX
*mem_ctx
, const struct dom_sid
*user_sid
)
205 struct netr_SamInfo3
*info3
= NULL
;
208 enum ndr_err_code ndr_err
;
210 struct netsamlogoncache_entry r
;
212 if (!netsamlogon_cache_init()) {
213 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
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
);
227 info3
= TALLOC_ZERO_P(mem_ctx
, struct netr_SamInfo3
);
232 blob
= data_blob_const(data
.dptr
, data
.dsize
);
234 ndr_err
= ndr_pull_struct_blob(&blob
, mem_ctx
, &r
,
235 (ndr_pull_flags_fn_t
)ndr_pull_netsamlogoncache_entry
);
237 if (DEBUGLEVEL
>= 10) {
238 NDR_PRINT_DEBUG(netsamlogoncache_entry
, &r
);
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
);
248 info3
= (struct netr_SamInfo3
*)talloc_memdup(mem_ctx
, &r
.info3
,
252 SAFE_FREE(data
.dptr
);
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.
261 time_t now
= time(NULL
);
264 /* is the entry expired? */
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
);
276 bool netsamlogon_cache_have(const struct dom_sid
*user_sid
)
278 TALLOC_CTX
*mem_ctx
= talloc_init("netsamlogon_cache_have");
279 struct netr_SamInfo3
*info3
= NULL
;
285 info3
= netsamlogon_cache_get(mem_ctx
, user_sid
);
287 result
= (info3
!= NULL
);
289 talloc_destroy(mem_ctx
);