2 Unix SMB/CIFS implementation.
4 Winbind cache backend functions
6 Copyright (C) Andrew Tridgell 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 struct winbind_cache
{
26 struct winbindd_methods
*backend
;
32 uint32 sequence_number
;
37 #define WINBINDD_MAX_CACHE_SIZE (50*1024*1024)
39 static struct winbind_cache
*wcache
;
42 void wcache_flush_cache(void)
44 extern BOOL opt_nocache
;
48 tdb_close(wcache
->tdb
);
51 if (opt_nocache
) return;
53 wcache
->tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
54 TDB_DEFAULT
, O_RDWR
| O_CREAT
| O_TRUNC
, 0600);
57 DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
61 void winbindd_check_cache_size(time_t t
)
63 static time_t last_check_time
;
66 if (last_check_time
== (time_t)0)
69 if (t
- last_check_time
< 60 && t
- last_check_time
> 0)
72 if (wcache
== NULL
|| wcache
->tdb
== NULL
) {
73 DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n"));
77 if (fstat(wcache
->tdb
->fd
, &st
) == -1) {
78 DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno
) ));
82 if (st
.st_size
> WINBINDD_MAX_CACHE_SIZE
) {
83 DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n",
84 (unsigned long)st
.st_size
,
85 (unsigned long)WINBINDD_MAX_CACHE_SIZE
));
90 /* get the winbind_cache structure */
91 static struct winbind_cache
*get_cache(struct winbindd_domain
*domain
)
93 extern struct winbindd_methods msrpc_methods
;
94 struct winbind_cache
*ret
= wcache
;
98 ret
= smb_xmalloc(sizeof(*ret
));
100 switch (lp_security()) {
103 extern struct winbindd_methods ads_methods
;
104 ret
->backend
= &ads_methods
;
109 ret
->backend
= &msrpc_methods
;
113 wcache_flush_cache();
119 free a centry structure
121 static void centry_free(struct cache_entry
*centry
)
124 SAFE_FREE(centry
->data
);
130 pull a uint32 from a cache entry
132 static uint32
centry_uint32(struct cache_entry
*centry
)
135 if (centry
->len
- centry
->ofs
< 4) {
136 DEBUG(0,("centry corruption? needed 4 bytes, have %d\n",
137 centry
->len
- centry
->ofs
));
138 smb_panic("centry_uint32");
140 ret
= IVAL(centry
->data
, centry
->ofs
);
146 pull a uint8 from a cache entry
148 static uint8
centry_uint8(struct cache_entry
*centry
)
151 if (centry
->len
- centry
->ofs
< 1) {
152 DEBUG(0,("centry corruption? needed 1 bytes, have %d\n",
153 centry
->len
- centry
->ofs
));
154 smb_panic("centry_uint32");
156 ret
= CVAL(centry
->data
, centry
->ofs
);
161 /* pull a string from a cache entry, using the supplied
164 static char *centry_string(struct cache_entry
*centry
, TALLOC_CTX
*mem_ctx
)
169 len
= centry_uint8(centry
);
172 /* a deliberate NULL string */
176 if (centry
->len
- centry
->ofs
< len
) {
177 DEBUG(0,("centry corruption? needed %d bytes, have %d\n",
178 len
, centry
->len
- centry
->ofs
));
179 smb_panic("centry_string");
182 ret
= talloc(mem_ctx
, len
+1);
184 smb_panic("centry_string out of memory\n");
186 memcpy(ret
,centry
->data
+ centry
->ofs
, len
);
192 /* the server is considered down if it can't give us a sequence number */
193 static BOOL
wcache_server_down(struct winbindd_domain
*domain
)
195 if (!wcache
->tdb
) return False
;
196 return (domain
->sequence_number
== DOM_SEQUENCE_NONE
);
201 refresh the domain sequence number. If force is True
202 then always refresh it, no matter how recently we fetched it
204 static void refresh_sequence_number(struct winbindd_domain
*domain
, BOOL force
)
209 time_diff
= time(NULL
) - domain
->last_seq_check
;
211 /* see if we have to refetch the domain sequence number */
212 if (!force
&& (time_diff
< lp_winbind_cache_time())) {
216 status
= wcache
->backend
->sequence_number(domain
, &domain
->sequence_number
);
218 if (!NT_STATUS_IS_OK(status
))
219 DEBUG(10, ("refresh_sequence_number: backend returned 0x%08x\n",
220 NT_STATUS_V(status
)));
222 /* Convert a NT_STATUS_UNSUCCESSFUL error to a
223 NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND. The former is
224 returned when we can't make an initial connection to
225 the domain controller. The latter is returned when we
226 can't fetch the sequence number on an already open
229 if (NT_STATUS_EQUAL(status
, NT_STATUS_UNSUCCESSFUL
))
230 status
= NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
232 domain
->last_status
= status
;
234 if (!NT_STATUS_IS_OK(status
))
235 domain
->sequence_number
= DOM_SEQUENCE_NONE
;
237 domain
->last_seq_check
= time(NULL
);
239 DEBUG(10, ("refresh_sequence_number: seq number is now %d\n",
240 domain
->sequence_number
));
244 decide if a cache entry has expired
246 static BOOL
centry_expired(struct winbindd_domain
*domain
, struct cache_entry
*centry
)
248 /* if the server is OK and our cache entry came from when it was down then
249 the entry is invalid */
250 if (domain
->sequence_number
!= DOM_SEQUENCE_NONE
&&
251 centry
->sequence_number
== DOM_SEQUENCE_NONE
) {
255 /* if the server is down or the cache entry is not older than the
256 current sequence number then it is OK */
257 if (wcache_server_down(domain
) ||
258 centry
->sequence_number
== domain
->sequence_number
) {
267 fetch an entry from the cache, with a varargs key. auto-fetch the sequence
268 number and return status
270 static struct cache_entry
*wcache_fetch(struct winbind_cache
*cache
,
271 struct winbindd_domain
*domain
,
272 const char *format
, ...)
277 struct cache_entry
*centry
;
280 refresh_sequence_number(domain
, False
);
282 va_start(ap
, format
);
283 smb_xvasprintf(&kstr
, format
, ap
);
287 key
.dsize
= strlen(kstr
);
288 data
= tdb_fetch(wcache
->tdb
, key
);
295 centry
= smb_xmalloc(sizeof(*centry
));
296 centry
->data
= (uchar
*)data
.dptr
;
297 centry
->len
= data
.dsize
;
300 if (centry
->len
< 8) {
301 /* huh? corrupt cache? */
306 centry
->status
= NT_STATUS(centry_uint32(centry
));
307 centry
->sequence_number
= centry_uint32(centry
);
309 if (centry_expired(domain
, centry
)) {
318 make sure we have at least len bytes available in a centry
320 static void centry_expand(struct cache_entry
*centry
, uint32 len
)
323 if (centry
->len
- centry
->ofs
>= len
) return;
325 p
= realloc(centry
->data
, centry
->len
);
327 DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry
->len
));
328 smb_panic("out of memory in centry_expand");
334 push a uint32 into a centry
336 static void centry_put_uint32(struct cache_entry
*centry
, uint32 v
)
338 centry_expand(centry
, 4);
339 SIVAL(centry
->data
, centry
->ofs
, v
);
344 push a uint8 into a centry
346 static void centry_put_uint8(struct cache_entry
*centry
, uint8 v
)
348 centry_expand(centry
, 1);
349 SCVAL(centry
->data
, centry
->ofs
, v
);
354 push a string into a centry
356 static void centry_put_string(struct cache_entry
*centry
, const char *s
)
361 /* null strings are marked as len 0xFFFF */
362 centry_put_uint8(centry
, 0xFF);
367 /* can't handle more than 254 char strings. Truncating is probably best */
368 if (len
> 254) len
= 254;
369 centry_put_uint8(centry
, len
);
370 centry_expand(centry
, len
);
371 memcpy(centry
->data
+ centry
->ofs
, s
, len
);
376 start a centry for output. When finished, call centry_end()
378 struct cache_entry
*centry_start(struct winbindd_domain
*domain
, NTSTATUS status
)
380 struct cache_entry
*centry
;
382 if (!wcache
->tdb
) return NULL
;
384 centry
= smb_xmalloc(sizeof(*centry
));
386 centry
->len
= 8192; /* reasonable default */
387 centry
->data
= smb_xmalloc(centry
->len
);
389 centry
->sequence_number
= domain
->sequence_number
;
390 centry_put_uint32(centry
, NT_STATUS_V(status
));
391 centry_put_uint32(centry
, centry
->sequence_number
);
396 finish a centry and write it to the tdb
398 static void centry_end(struct cache_entry
*centry
, const char *format
, ...)
404 va_start(ap
, format
);
405 smb_xvasprintf(&kstr
, format
, ap
);
409 key
.dsize
= strlen(kstr
);
410 data
.dptr
= (char *)centry
->data
;
411 data
.dsize
= centry
->ofs
;
413 tdb_store(wcache
->tdb
, key
, data
, TDB_REPLACE
);
417 /* form a sid from the domain plus rid */
418 static DOM_SID
*form_sid(struct winbindd_domain
*domain
, uint32 rid
)
421 sid_copy(&sid
, &domain
->sid
);
422 sid_append_rid(&sid
, rid
);
426 static void wcache_save_name_to_sid(struct winbindd_domain
*domain
, NTSTATUS status
,
427 const char *name
, DOM_SID
*sid
, enum SID_NAME_USE type
)
429 struct cache_entry
*centry
;
433 centry
= centry_start(domain
, status
);
436 centry_expand(centry
, len
);
437 centry_put_uint32(centry
, type
);
438 sid_linearize((char *)centry
->data
+ centry
->ofs
, len
, sid
);
440 fstrcpy(uname
, name
);
442 centry_end(centry
, "NS/%s/%s", domain
->name
, uname
);
446 static void wcache_save_sid_to_name(struct winbindd_domain
*domain
, NTSTATUS status
,
447 DOM_SID
*sid
, const char *name
, enum SID_NAME_USE type
, uint32 rid
)
449 struct cache_entry
*centry
;
451 centry
= centry_start(domain
, status
);
453 if (NT_STATUS_IS_OK(status
)) {
454 centry_put_uint32(centry
, type
);
455 centry_put_string(centry
, name
);
457 centry_end(centry
, "SN/%s/%d", domain
->name
, rid
);
462 static void wcache_save_user(struct winbindd_domain
*domain
, NTSTATUS status
, WINBIND_USERINFO
*info
)
464 struct cache_entry
*centry
;
466 centry
= centry_start(domain
, status
);
468 centry_put_string(centry
, info
->acct_name
);
469 centry_put_string(centry
, info
->full_name
);
470 centry_put_uint32(centry
, info
->user_rid
);
471 centry_put_uint32(centry
, info
->group_rid
);
472 centry_end(centry
, "U/%s/%d", domain
->name
, info
->user_rid
);
477 /* Query display info. This is the basic user list fn */
478 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
481 WINBIND_USERINFO
**info
)
483 struct winbind_cache
*cache
= get_cache(domain
);
484 struct cache_entry
*centry
= NULL
;
488 if (!cache
->tdb
) goto do_query
;
490 centry
= wcache_fetch(cache
, domain
, "UL/%s", domain
->name
);
491 if (!centry
) goto do_query
;
493 *num_entries
= centry_uint32(centry
);
495 if (*num_entries
== 0) goto do_cached
;
497 (*info
) = talloc(mem_ctx
, sizeof(**info
) * (*num_entries
));
498 if (! (*info
)) smb_panic("query_user_list out of memory");
499 for (i
=0; i
<(*num_entries
); i
++) {
500 (*info
)[i
].acct_name
= centry_string(centry
, mem_ctx
);
501 (*info
)[i
].full_name
= centry_string(centry
, mem_ctx
);
502 (*info
)[i
].user_rid
= centry_uint32(centry
);
503 (*info
)[i
].group_rid
= centry_uint32(centry
);
508 /* If we are returning cached data and the domain controller
509 is down then we don't know whether the data is up to date
510 or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to
513 if (wcache_server_down(domain
)) {
514 DEBUG(10, ("query_user_list: returning cached user list and server was down\n"));
515 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
517 status
= centry
->status
;
526 /* Return status value returned by seq number check */
528 if (!NT_STATUS_IS_OK(domain
->last_status
))
529 return domain
->last_status
;
531 status
= cache
->backend
->query_user_list(domain
, mem_ctx
, num_entries
, info
);
534 refresh_sequence_number(domain
, True
);
535 centry
= centry_start(domain
, status
);
536 if (!centry
) goto skip_save
;
537 centry_put_uint32(centry
, *num_entries
);
538 for (i
=0; i
<(*num_entries
); i
++) {
539 centry_put_string(centry
, (*info
)[i
].acct_name
);
540 centry_put_string(centry
, (*info
)[i
].full_name
);
541 centry_put_uint32(centry
, (*info
)[i
].user_rid
);
542 centry_put_uint32(centry
, (*info
)[i
].group_rid
);
543 if (cache
->backend
->consistent
) {
544 /* when the backend is consistent we can pre-prime some mappings */
545 wcache_save_name_to_sid(domain
, NT_STATUS_OK
,
546 (*info
)[i
].acct_name
,
547 form_sid(domain
, (*info
)[i
].user_rid
),
549 wcache_save_sid_to_name(domain
, NT_STATUS_OK
,
550 form_sid(domain
, (*info
)[i
].user_rid
),
551 (*info
)[i
].acct_name
,
552 SID_NAME_USER
, (*info
)[i
].user_rid
);
553 wcache_save_user(domain
, NT_STATUS_OK
, &(*info
)[i
]);
556 centry_end(centry
, "UL/%s", domain
->name
);
563 /* list all domain groups */
564 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
567 struct acct_info
**info
)
569 struct winbind_cache
*cache
= get_cache(domain
);
570 struct cache_entry
*centry
= NULL
;
574 if (!cache
->tdb
) goto do_query
;
576 centry
= wcache_fetch(cache
, domain
, "GL/%s", domain
->name
);
577 if (!centry
) goto do_query
;
579 *num_entries
= centry_uint32(centry
);
581 if (*num_entries
== 0) goto do_cached
;
583 (*info
) = talloc(mem_ctx
, sizeof(**info
) * (*num_entries
));
584 if (! (*info
)) smb_panic("enum_dom_groups out of memory");
585 for (i
=0; i
<(*num_entries
); i
++) {
586 fstrcpy((*info
)[i
].acct_name
, centry_string(centry
, mem_ctx
));
587 fstrcpy((*info
)[i
].acct_desc
, centry_string(centry
, mem_ctx
));
588 (*info
)[i
].rid
= centry_uint32(centry
);
593 /* If we are returning cached data and the domain controller
594 is down then we don't know whether the data is up to date
595 or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to
598 if (wcache_server_down(domain
)) {
599 DEBUG(10, ("query_user_list: returning cached user list and server was down\n"));
600 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
602 status
= centry
->status
;
611 /* Return status value returned by seq number check */
613 if (!NT_STATUS_IS_OK(domain
->last_status
))
614 return domain
->last_status
;
616 status
= cache
->backend
->enum_dom_groups(domain
, mem_ctx
, num_entries
, info
);
619 refresh_sequence_number(domain
, True
);
620 centry
= centry_start(domain
, status
);
621 if (!centry
) goto skip_save
;
622 centry_put_uint32(centry
, *num_entries
);
623 for (i
=0; i
<(*num_entries
); i
++) {
624 centry_put_string(centry
, (*info
)[i
].acct_name
);
625 centry_put_string(centry
, (*info
)[i
].acct_desc
);
626 centry_put_uint32(centry
, (*info
)[i
].rid
);
628 centry_end(centry
, "GL/%s", domain
->name
);
636 /* convert a single name to a sid in a domain */
637 static NTSTATUS
name_to_sid(struct winbindd_domain
*domain
,
640 enum SID_NAME_USE
*type
)
642 struct winbind_cache
*cache
= get_cache(domain
);
643 struct cache_entry
*centry
= NULL
;
647 if (!cache
->tdb
) goto do_query
;
649 fstrcpy(uname
, name
);
651 centry
= wcache_fetch(cache
, domain
, "NS/%s/%s", domain
->name
, uname
);
652 if (!centry
) goto do_query
;
653 *type
= centry_uint32(centry
);
654 sid_parse((char *)centry
->data
+ centry
->ofs
, centry
->len
- centry
->ofs
, sid
);
656 status
= centry
->status
;
663 /* Return status value returned by seq number check */
665 if (!NT_STATUS_IS_OK(domain
->last_status
))
666 return domain
->last_status
;
668 status
= cache
->backend
->name_to_sid(domain
, name
, sid
, type
);
671 wcache_save_name_to_sid(domain
, status
, name
, sid
, *type
);
673 /* We can't save the sid to name mapping as we don't know the
674 correct case of the name without looking it up */
679 /* convert a sid to a user or group name. The sid is guaranteed to be in the domain
681 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
685 enum SID_NAME_USE
*type
)
687 struct winbind_cache
*cache
= get_cache(domain
);
688 struct cache_entry
*centry
= NULL
;
692 sid_peek_rid(sid
, &rid
);
694 if (!cache
->tdb
) goto do_query
;
696 centry
= wcache_fetch(cache
, domain
, "SN/%s/%d", domain
->name
, rid
);
697 if (!centry
) goto do_query
;
698 if (NT_STATUS_IS_OK(centry
->status
)) {
699 *type
= centry_uint32(centry
);
700 *name
= centry_string(centry
, mem_ctx
);
702 status
= centry
->status
;
709 /* Return status value returned by seq number check */
711 if (!NT_STATUS_IS_OK(domain
->last_status
))
712 return domain
->last_status
;
714 status
= cache
->backend
->sid_to_name(domain
, mem_ctx
, sid
, name
, type
);
717 refresh_sequence_number(domain
, True
);
718 wcache_save_sid_to_name(domain
, status
, sid
, *name
, *type
, rid
);
719 wcache_save_name_to_sid(domain
, status
, *name
, sid
, *type
);
725 /* Lookup user information from a rid */
726 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
729 WINBIND_USERINFO
*info
)
731 struct winbind_cache
*cache
= get_cache(domain
);
732 struct cache_entry
*centry
= NULL
;
735 if (!cache
->tdb
) goto do_query
;
737 centry
= wcache_fetch(cache
, domain
, "U/%s/%d", domain
->name
, user_rid
);
738 if (!centry
) goto do_query
;
740 info
->acct_name
= centry_string(centry
, mem_ctx
);
741 info
->full_name
= centry_string(centry
, mem_ctx
);
742 info
->user_rid
= centry_uint32(centry
);
743 info
->group_rid
= centry_uint32(centry
);
744 status
= centry
->status
;
751 /* Return status value returned by seq number check */
753 if (!NT_STATUS_IS_OK(domain
->last_status
))
754 return domain
->last_status
;
756 status
= cache
->backend
->query_user(domain
, mem_ctx
, user_rid
, info
);
759 refresh_sequence_number(domain
, True
);
760 wcache_save_user(domain
, status
, info
);
766 /* Lookup groups a user is a member of. */
767 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
770 uint32
*num_groups
, uint32
**user_gids
)
772 struct winbind_cache
*cache
= get_cache(domain
);
773 struct cache_entry
*centry
= NULL
;
777 if (!cache
->tdb
) goto do_query
;
779 centry
= wcache_fetch(cache
, domain
, "UG/%s/%d", domain
->name
, user_rid
);
780 if (!centry
) goto do_query
;
782 *num_groups
= centry_uint32(centry
);
784 if (*num_groups
== 0) goto do_cached
;
786 (*user_gids
) = talloc(mem_ctx
, sizeof(**user_gids
) * (*num_groups
));
787 if (! (*user_gids
)) smb_panic("lookup_usergroups out of memory");
788 for (i
=0; i
<(*num_groups
); i
++) {
789 (*user_gids
)[i
] = centry_uint32(centry
);
793 status
= centry
->status
;
801 /* Return status value returned by seq number check */
803 if (!NT_STATUS_IS_OK(domain
->last_status
))
804 return domain
->last_status
;
806 status
= cache
->backend
->lookup_usergroups(domain
, mem_ctx
, user_rid
, num_groups
, user_gids
);
809 refresh_sequence_number(domain
, True
);
810 centry
= centry_start(domain
, status
);
811 if (!centry
) goto skip_save
;
812 centry_put_uint32(centry
, *num_groups
);
813 for (i
=0; i
<(*num_groups
); i
++) {
814 centry_put_uint32(centry
, (*user_gids
)[i
]);
816 centry_end(centry
, "UG/%s/%d", domain
->name
, user_rid
);
824 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
826 uint32 group_rid
, uint32
*num_names
,
827 uint32
**rid_mem
, char ***names
,
830 struct winbind_cache
*cache
= get_cache(domain
);
831 struct cache_entry
*centry
= NULL
;
835 if (!cache
->tdb
) goto do_query
;
837 centry
= wcache_fetch(cache
, domain
, "GM/%s/%d", domain
->name
, group_rid
);
838 if (!centry
) goto do_query
;
840 *num_names
= centry_uint32(centry
);
842 if (*num_names
== 0) goto do_cached
;
844 (*rid_mem
) = talloc(mem_ctx
, sizeof(**rid_mem
) * (*num_names
));
845 (*names
) = talloc(mem_ctx
, sizeof(**names
) * (*num_names
));
846 (*name_types
) = talloc(mem_ctx
, sizeof(**name_types
) * (*num_names
));
848 if (! (*rid_mem
) || ! (*names
) || ! (*name_types
)) {
849 smb_panic("lookup_groupmem out of memory");
852 for (i
=0; i
<(*num_names
); i
++) {
853 (*rid_mem
)[i
] = centry_uint32(centry
);
854 (*names
)[i
] = centry_string(centry
, mem_ctx
);
855 (*name_types
)[i
] = centry_uint32(centry
);
859 status
= centry
->status
;
867 (*name_types
) = NULL
;
869 /* Return status value returned by seq number check */
871 if (!NT_STATUS_IS_OK(domain
->last_status
))
872 return domain
->last_status
;
874 status
= cache
->backend
->lookup_groupmem(domain
, mem_ctx
, group_rid
, num_names
,
875 rid_mem
, names
, name_types
);
878 refresh_sequence_number(domain
, True
);
879 centry
= centry_start(domain
, status
);
880 if (!centry
) goto skip_save
;
881 centry_put_uint32(centry
, *num_names
);
882 for (i
=0; i
<(*num_names
); i
++) {
883 centry_put_uint32(centry
, (*rid_mem
)[i
]);
884 centry_put_string(centry
, (*names
)[i
]);
885 centry_put_uint32(centry
, (*name_types
)[i
]);
887 centry_end(centry
, "GM/%s/%d", domain
->name
, group_rid
);
894 /* find the sequence number for a domain */
895 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
897 refresh_sequence_number(domain
, False
);
899 *seq
= domain
->sequence_number
;
904 /* enumerate trusted domains */
905 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
911 struct winbind_cache
*cache
= get_cache(domain
);
913 /* we don't cache this call */
914 return cache
->backend
->trusted_domains(domain
, mem_ctx
, num_domains
,
918 /* find the domain sid */
919 static NTSTATUS
domain_sid(struct winbindd_domain
*domain
, DOM_SID
*sid
)
921 struct winbind_cache
*cache
= get_cache(domain
);
923 /* we don't cache this call */
924 return cache
->backend
->domain_sid(domain
, sid
);
927 /* the ADS backend methods are exposed via this structure */
928 struct winbindd_methods cache_methods
= {