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;
43 struct tdb_context
*tdb
;
45 if (netsamlogon_tdb
) {
49 path
= cache_path(NETSAMLOGON_TDB
);
54 tdb
= tdb_open_log(path
, 0, TDB_DEFAULT
|TDB_INCOMPATIBLE_HASH
,
55 O_RDWR
| O_CREAT
, 0600);
57 DEBUG(0,("tdb_open_log('%s') - failed\n", path
));
61 ret
= tdb_check(tdb
, NULL
, NULL
);
64 DEBUG(0,("tdb_check('%s') - failed\n", path
));
68 netsamlogon_tdb
= tdb
;
79 DEBUG(0,("retry after truncate for '%s'\n", path
));
85 /***********************************************************************
86 Shutdown samlogon_cache database
87 ***********************************************************************/
89 bool netsamlogon_cache_shutdown(void)
91 if (netsamlogon_tdb
) {
92 return (tdb_close(netsamlogon_tdb
) == 0);
98 /***********************************************************************
99 Clear cache getpwnam and getgroups entries from the winbindd cache
100 ***********************************************************************/
102 void netsamlogon_clear_cached_user(const struct dom_sid
*user_sid
)
106 if (!netsamlogon_cache_init()) {
107 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
113 /* Prepare key as DOMAIN-SID/USER-RID string */
114 sid_to_fstring(keystr
, user_sid
);
116 DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr
));
118 tdb_delete_bystring(netsamlogon_tdb
, keystr
);
121 /***********************************************************************
122 Store a netr_SamInfo3 structure in a tdb for later user
123 username should be in UTF-8 format
124 ***********************************************************************/
126 bool netsamlogon_cache_store(const char *username
, struct netr_SamInfo3
*info3
)
131 struct dom_sid user_sid
;
132 time_t t
= time(NULL
);
133 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
135 enum ndr_err_code ndr_err
;
136 struct netsamlogoncache_entry r
;
142 if (!netsamlogon_cache_init()) {
143 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
148 sid_compose(&user_sid
, info3
->base
.domain_sid
, info3
->base
.rid
);
150 /* Prepare key as DOMAIN-SID/USER-RID string */
151 sid_to_fstring(keystr
, &user_sid
);
153 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr
));
157 if (info3
->base
.full_name
.string
== NULL
) {
158 struct netr_SamInfo3
*cached_info3
;
159 const char *full_name
= NULL
;
161 cached_info3
= netsamlogon_cache_get(tmp_ctx
, &user_sid
);
162 if (cached_info3
!= NULL
) {
163 full_name
= cached_info3
->base
.full_name
.string
;
166 if (full_name
!= NULL
) {
167 info3
->base
.full_name
.string
= talloc_strdup(info3
, full_name
);
171 /* only Samba fills in the username, not sure why NT doesn't */
172 /* so we fill it in since winbindd_getpwnam() makes use of it */
174 if (!info3
->base
.account_name
.string
) {
175 info3
->base
.account_name
.string
= talloc_strdup(info3
, username
);
181 if (DEBUGLEVEL
>= 10) {
182 NDR_PRINT_DEBUG(netsamlogoncache_entry
, &r
);
185 ndr_err
= ndr_push_struct_blob(&blob
, tmp_ctx
, &r
,
186 (ndr_push_flags_fn_t
)ndr_push_netsamlogoncache_entry
);
187 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
188 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
189 TALLOC_FREE(tmp_ctx
);
193 data
.dsize
= blob
.length
;
194 data
.dptr
= blob
.data
;
196 if (tdb_store_bystring(netsamlogon_tdb
, keystr
, data
, TDB_REPLACE
) == 0) {
200 TALLOC_FREE(tmp_ctx
);
205 /***********************************************************************
206 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
207 free the user_info struct (malloc()'d memory)
208 ***********************************************************************/
210 struct netr_SamInfo3
*netsamlogon_cache_get(TALLOC_CTX
*mem_ctx
, const struct dom_sid
*user_sid
)
212 struct netr_SamInfo3
*info3
= NULL
;
215 enum ndr_err_code ndr_err
;
217 struct netsamlogoncache_entry r
;
219 if (!netsamlogon_cache_init()) {
220 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
225 /* Prepare key as DOMAIN-SID/USER-RID string */
226 slprintf(keystr
, sizeof(keystr
), "%s", sid_to_fstring(tmp
, user_sid
));
227 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr
));
228 data
= tdb_fetch_bystring( netsamlogon_tdb
, keystr
);
234 info3
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
239 blob
= data_blob_const(data
.dptr
, data
.dsize
);
241 ndr_err
= ndr_pull_struct_blob(&blob
, mem_ctx
, &r
,
242 (ndr_pull_flags_fn_t
)ndr_pull_netsamlogoncache_entry
);
244 if (DEBUGLEVEL
>= 10) {
245 NDR_PRINT_DEBUG(netsamlogoncache_entry
, &r
);
248 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
249 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
250 tdb_delete(netsamlogon_tdb
, data
);
255 info3
= (struct netr_SamInfo3
*)talloc_memdup(mem_ctx
, &r
.info3
,
259 SAFE_FREE(data
.dptr
);
263 #if 0 /* The netsamlogon cache needs to hang around. Something about
264 this feels wrong, but it is the only way we can get all of the
265 groups. The old universal groups cache didn't expire either.
268 time_t now
= time(NULL
);
271 /* is the entry expired? */
274 if ( (time_diff
< 0 ) || (time_diff
> lp_winbind_cache_time()) ) {
275 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
276 tdb_delete( netsamlogon_tdb
, key
);
283 bool netsamlogon_cache_have(const struct dom_sid
*user_sid
)
285 TALLOC_CTX
*mem_ctx
= talloc_init("netsamlogon_cache_have");
286 struct netr_SamInfo3
*info3
= NULL
;
292 info3
= netsamlogon_cache_get(mem_ctx
, user_sid
);
294 result
= (info3
!= NULL
);
296 talloc_destroy(mem_ctx
);