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.
26 #define DBGC_CLASS DBGC_WINBIND
28 struct winbind_cache
{
29 struct winbindd_methods
*backend
;
35 uint32 sequence_number
;
40 #define WINBINDD_MAX_CACHE_SIZE (50*1024*1024)
42 static struct winbind_cache
*wcache
;
45 void wcache_flush_cache(void)
47 extern BOOL opt_nocache
;
51 tdb_close(wcache
->tdb
);
54 if (opt_nocache
) return;
56 wcache
->tdb
= tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
57 TDB_CLEAR_IF_FIRST
, O_RDWR
|O_CREAT
, 0600);
60 DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
64 void winbindd_check_cache_size(time_t t
)
66 static time_t last_check_time
;
69 if (last_check_time
== (time_t)0)
72 if (t
- last_check_time
< 60 && t
- last_check_time
> 0)
75 if (wcache
== NULL
|| wcache
->tdb
== NULL
) {
76 DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n"));
80 if (fstat(wcache
->tdb
->fd
, &st
) == -1) {
81 DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno
) ));
85 if (st
.st_size
> WINBINDD_MAX_CACHE_SIZE
) {
86 DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n",
87 (unsigned long)st
.st_size
,
88 (unsigned long)WINBINDD_MAX_CACHE_SIZE
));
93 /* get the winbind_cache structure */
94 static struct winbind_cache
*get_cache(struct winbindd_domain
*domain
)
96 extern struct winbindd_methods msrpc_methods
;
97 struct winbind_cache
*ret
= wcache
;
101 ret
= smb_xmalloc(sizeof(*ret
));
103 switch (lp_security()) { /* winbind pdc disabled until ready
104 if (!strcmp(domain->name, lp_workgroup()) && (lp_security() == SEC_USER)) {
105 extern struct winbindd_methods passdb_methods;
106 ret->backend = &passdb_methods;
108 } else switch (lp_security()) { */
111 extern struct winbindd_methods ads_methods
;
112 ret
->backend
= &ads_methods
;
117 ret
->backend
= &msrpc_methods
;
121 wcache_flush_cache();
127 free a centry structure
129 static void centry_free(struct cache_entry
*centry
)
132 SAFE_FREE(centry
->data
);
138 pull a uint32 from a cache entry
140 static uint32
centry_uint32(struct cache_entry
*centry
)
143 if (centry
->len
- centry
->ofs
< 4) {
144 DEBUG(0,("centry corruption? needed 4 bytes, have %d\n",
145 centry
->len
- centry
->ofs
));
146 smb_panic("centry_uint32");
148 ret
= IVAL(centry
->data
, centry
->ofs
);
154 pull a uint8 from a cache entry
156 static uint8
centry_uint8(struct cache_entry
*centry
)
159 if (centry
->len
- centry
->ofs
< 1) {
160 DEBUG(0,("centry corruption? needed 1 bytes, have %d\n",
161 centry
->len
- centry
->ofs
));
162 smb_panic("centry_uint32");
164 ret
= CVAL(centry
->data
, centry
->ofs
);
169 /* pull a string from a cache entry, using the supplied
172 static char *centry_string(struct cache_entry
*centry
, TALLOC_CTX
*mem_ctx
)
177 len
= centry_uint8(centry
);
180 /* a deliberate NULL string */
184 if (centry
->len
- centry
->ofs
< len
) {
185 DEBUG(0,("centry corruption? needed %d bytes, have %d\n",
186 len
, centry
->len
- centry
->ofs
));
187 smb_panic("centry_string");
190 ret
= talloc(mem_ctx
, len
+1);
192 smb_panic("centry_string out of memory\n");
194 memcpy(ret
,centry
->data
+ centry
->ofs
, len
);
200 /* pull a string from a cache entry, using the supplied
203 static DOM_SID
*centry_sid(struct cache_entry
*centry
, TALLOC_CTX
*mem_ctx
)
207 sid
= talloc(mem_ctx
, sizeof(*sid
));
208 if (!sid
) return NULL
;
210 sid_string
= centry_string(centry
, mem_ctx
);
211 if (!string_to_sid(sid
, sid_string
)) {
217 /* the server is considered down if it can't give us a sequence number */
218 static BOOL
wcache_server_down(struct winbindd_domain
*domain
)
220 if (!wcache
->tdb
) return False
;
221 return (domain
->sequence_number
== DOM_SEQUENCE_NONE
);
226 refresh the domain sequence number. If force is True
227 then always refresh it, no matter how recently we fetched it
229 static void refresh_sequence_number(struct winbindd_domain
*domain
, BOOL force
)
233 unsigned cache_time
= lp_winbind_cache_time();
235 /* trying to reconnect is expensive, don't do it too often */
236 if (domain
->sequence_number
== DOM_SEQUENCE_NONE
) {
240 time_diff
= time(NULL
) - domain
->last_seq_check
;
242 /* see if we have to refetch the domain sequence number */
243 if (!force
&& (time_diff
< cache_time
)) {
247 status
= wcache
->backend
->sequence_number(domain
, &domain
->sequence_number
);
249 if (!NT_STATUS_IS_OK(status
)) {
250 domain
->sequence_number
= DOM_SEQUENCE_NONE
;
253 domain
->last_seq_check
= time(NULL
);
257 decide if a cache entry has expired
259 static BOOL
centry_expired(struct winbindd_domain
*domain
, struct cache_entry
*centry
)
261 /* if the server is OK and our cache entry came from when it was down then
262 the entry is invalid */
263 if (domain
->sequence_number
!= DOM_SEQUENCE_NONE
&&
264 centry
->sequence_number
== DOM_SEQUENCE_NONE
) {
268 /* if the server is down or the cache entry is not older than the
269 current sequence number then it is OK */
270 if (wcache_server_down(domain
) ||
271 centry
->sequence_number
== domain
->sequence_number
) {
280 fetch an entry from the cache, with a varargs key. auto-fetch the sequence
281 number and return status
283 static struct cache_entry
*wcache_fetch(struct winbind_cache
*cache
,
284 struct winbindd_domain
*domain
,
285 const char *format
, ...) PRINTF_ATTRIBUTE(3,4);
286 static struct cache_entry
*wcache_fetch(struct winbind_cache
*cache
,
287 struct winbindd_domain
*domain
,
288 const char *format
, ...)
293 struct cache_entry
*centry
;
296 refresh_sequence_number(domain
, False
);
298 va_start(ap
, format
);
299 smb_xvasprintf(&kstr
, format
, ap
);
303 key
.dsize
= strlen(kstr
);
304 data
= tdb_fetch(wcache
->tdb
, key
);
311 centry
= smb_xmalloc(sizeof(*centry
));
312 centry
->data
= data
.dptr
;
313 centry
->len
= data
.dsize
;
316 if (centry
->len
< 8) {
317 /* huh? corrupt cache? */
322 centry
->status
= NT_STATUS(centry_uint32(centry
));
323 centry
->sequence_number
= centry_uint32(centry
);
325 if (centry_expired(domain
, centry
)) {
326 extern BOOL opt_dual_daemon
;
328 if (opt_dual_daemon
) {
329 extern BOOL background_process
;
330 background_process
= True
;
341 make sure we have at least len bytes available in a centry
343 static void centry_expand(struct cache_entry
*centry
, uint32 len
)
346 if (centry
->len
- centry
->ofs
>= len
) return;
348 p
= realloc(centry
->data
, centry
->len
);
350 DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry
->len
));
351 smb_panic("out of memory in centry_expand");
357 push a uint32 into a centry
359 static void centry_put_uint32(struct cache_entry
*centry
, uint32 v
)
361 centry_expand(centry
, 4);
362 SIVAL(centry
->data
, centry
->ofs
, v
);
367 push a uint8 into a centry
369 static void centry_put_uint8(struct cache_entry
*centry
, uint8 v
)
371 centry_expand(centry
, 1);
372 SCVAL(centry
->data
, centry
->ofs
, v
);
377 push a string into a centry
379 static void centry_put_string(struct cache_entry
*centry
, const char *s
)
384 /* null strings are marked as len 0xFFFF */
385 centry_put_uint8(centry
, 0xFF);
390 /* can't handle more than 254 char strings. Truncating is probably best */
391 if (len
> 254) len
= 254;
392 centry_put_uint8(centry
, len
);
393 centry_expand(centry
, len
);
394 memcpy(centry
->data
+ centry
->ofs
, s
, len
);
398 static void centry_put_sid(struct cache_entry
*centry
, const DOM_SID
*sid
)
401 centry_put_string(centry
, sid_to_string(sid_string
, sid
));
405 start a centry for output. When finished, call centry_end()
407 struct cache_entry
*centry_start(struct winbindd_domain
*domain
, NTSTATUS status
)
409 struct cache_entry
*centry
;
411 if (!wcache
->tdb
) return NULL
;
413 centry
= smb_xmalloc(sizeof(*centry
));
415 centry
->len
= 8192; /* reasonable default */
416 centry
->data
= smb_xmalloc(centry
->len
);
418 centry
->sequence_number
= domain
->sequence_number
;
419 centry_put_uint32(centry
, NT_STATUS_V(status
));
420 centry_put_uint32(centry
, centry
->sequence_number
);
425 finish a centry and write it to the tdb
427 static void centry_end(struct cache_entry
*centry
, const char *format
, ...) PRINTF_ATTRIBUTE(2,3);
428 static void centry_end(struct cache_entry
*centry
, const char *format
, ...)
434 va_start(ap
, format
);
435 smb_xvasprintf(&kstr
, format
, ap
);
439 key
.dsize
= strlen(kstr
);
440 data
.dptr
= centry
->data
;
441 data
.dsize
= centry
->ofs
;
443 tdb_store(wcache
->tdb
, key
, data
, TDB_REPLACE
);
447 static void wcache_save_name_to_sid(struct winbindd_domain
*domain
,
449 const char *name
, DOM_SID
*sid
,
450 enum SID_NAME_USE type
)
452 struct cache_entry
*centry
;
456 centry
= centry_start(domain
, status
);
458 centry_put_sid(centry
, sid
);
459 fstrcpy(uname
, name
);
461 centry_end(centry
, "NS/%s", sid_to_string(sid_string
, sid
));
465 static void wcache_save_sid_to_name(struct winbindd_domain
*domain
, NTSTATUS status
,
466 DOM_SID
*sid
, const char *name
, enum SID_NAME_USE type
)
468 struct cache_entry
*centry
;
471 centry
= centry_start(domain
, status
);
473 if (NT_STATUS_IS_OK(status
)) {
474 centry_put_uint32(centry
, type
);
475 centry_put_string(centry
, name
);
477 centry_end(centry
, "SN/%s", sid_to_string(sid_string
, sid
));
482 static void wcache_save_user(struct winbindd_domain
*domain
, NTSTATUS status
, WINBIND_USERINFO
*info
)
484 struct cache_entry
*centry
;
487 centry
= centry_start(domain
, status
);
489 centry_put_string(centry
, info
->acct_name
);
490 centry_put_string(centry
, info
->full_name
);
491 centry_put_sid(centry
, info
->user_sid
);
492 centry_put_sid(centry
, info
->group_sid
);
493 centry_end(centry
, "U/%s", sid_to_string(sid_string
, info
->user_sid
));
498 /* Query display info. This is the basic user list fn */
499 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
502 WINBIND_USERINFO
**info
)
504 struct winbind_cache
*cache
= get_cache(domain
);
505 struct cache_entry
*centry
= NULL
;
509 if (!cache
->tdb
) goto do_query
;
511 centry
= wcache_fetch(cache
, domain
, "UL/%s", domain
->name
);
512 if (!centry
) goto do_query
;
514 *num_entries
= centry_uint32(centry
);
516 if (*num_entries
== 0) goto do_cached
;
518 (*info
) = talloc(mem_ctx
, sizeof(**info
) * (*num_entries
));
519 if (! (*info
)) smb_panic("query_user_list out of memory");
520 for (i
=0; i
<(*num_entries
); i
++) {
521 (*info
)[i
].acct_name
= centry_string(centry
, mem_ctx
);
522 (*info
)[i
].full_name
= centry_string(centry
, mem_ctx
);
523 (*info
)[i
].user_sid
= centry_sid(centry
, mem_ctx
);
524 (*info
)[i
].group_sid
= centry_sid(centry
, mem_ctx
);
528 status
= centry
->status
;
536 if (wcache_server_down(domain
)) {
537 return NT_STATUS_SERVER_DISABLED
;
540 status
= cache
->backend
->query_user_list(domain
, mem_ctx
, num_entries
, info
);
543 refresh_sequence_number(domain
, True
);
544 centry
= centry_start(domain
, status
);
545 if (!centry
) goto skip_save
;
546 centry_put_uint32(centry
, *num_entries
);
547 for (i
=0; i
<(*num_entries
); i
++) {
548 centry_put_string(centry
, (*info
)[i
].acct_name
);
549 centry_put_string(centry
, (*info
)[i
].full_name
);
550 centry_put_sid(centry
, (*info
)[i
].user_sid
);
551 centry_put_sid(centry
, (*info
)[i
].group_sid
);
552 if (cache
->backend
->consistent
) {
553 /* when the backend is consistent we can pre-prime some mappings */
554 wcache_save_name_to_sid(domain
, NT_STATUS_OK
,
555 (*info
)[i
].acct_name
,
558 wcache_save_sid_to_name(domain
, NT_STATUS_OK
,
560 (*info
)[i
].acct_name
,
562 wcache_save_user(domain
, NT_STATUS_OK
, &(*info
)[i
]);
565 centry_end(centry
, "UL/%s", domain
->name
);
572 /* list all domain groups */
573 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
576 struct acct_info
**info
)
578 struct winbind_cache
*cache
= get_cache(domain
);
579 struct cache_entry
*centry
= NULL
;
583 if (!cache
->tdb
) goto do_query
;
585 centry
= wcache_fetch(cache
, domain
, "GL/%s/domain", domain
->name
);
586 if (!centry
) goto do_query
;
588 *num_entries
= centry_uint32(centry
);
590 if (*num_entries
== 0) goto do_cached
;
592 (*info
) = talloc(mem_ctx
, sizeof(**info
) * (*num_entries
));
593 if (! (*info
)) smb_panic("enum_dom_groups out of memory");
594 for (i
=0; i
<(*num_entries
); i
++) {
595 fstrcpy((*info
)[i
].acct_name
, centry_string(centry
, mem_ctx
));
596 fstrcpy((*info
)[i
].acct_desc
, centry_string(centry
, mem_ctx
));
597 (*info
)[i
].rid
= centry_uint32(centry
);
601 status
= centry
->status
;
609 if (wcache_server_down(domain
)) {
610 return NT_STATUS_SERVER_DISABLED
;
613 status
= cache
->backend
->enum_dom_groups(domain
, mem_ctx
, num_entries
, info
);
616 refresh_sequence_number(domain
, True
);
617 centry
= centry_start(domain
, status
);
618 if (!centry
) goto skip_save
;
619 centry_put_uint32(centry
, *num_entries
);
620 for (i
=0; i
<(*num_entries
); i
++) {
621 centry_put_string(centry
, (*info
)[i
].acct_name
);
622 centry_put_string(centry
, (*info
)[i
].acct_desc
);
623 centry_put_uint32(centry
, (*info
)[i
].rid
);
625 centry_end(centry
, "GL/%s/domain", domain
->name
);
632 /* list all domain groups */
633 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
636 struct acct_info
**info
)
638 struct winbind_cache
*cache
= get_cache(domain
);
639 struct cache_entry
*centry
= NULL
;
643 if (!cache
->tdb
) goto do_query
;
645 centry
= wcache_fetch(cache
, domain
, "GL/%s/local", domain
->name
);
646 if (!centry
) goto do_query
;
648 *num_entries
= centry_uint32(centry
);
650 if (*num_entries
== 0) goto do_cached
;
652 (*info
) = talloc(mem_ctx
, sizeof(**info
) * (*num_entries
));
653 if (! (*info
)) smb_panic("enum_dom_groups out of memory");
654 for (i
=0; i
<(*num_entries
); i
++) {
655 fstrcpy((*info
)[i
].acct_name
, centry_string(centry
, mem_ctx
));
656 fstrcpy((*info
)[i
].acct_desc
, centry_string(centry
, mem_ctx
));
657 (*info
)[i
].rid
= centry_uint32(centry
);
662 /* If we are returning cached data and the domain controller
663 is down then we don't know whether the data is up to date
664 or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to
667 if (wcache_server_down(domain
)) {
668 DEBUG(10, ("query_user_list: returning cached user list and server was down\n"));
669 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
671 status
= centry
->status
;
680 if (wcache_server_down(domain
)) {
681 return NT_STATUS_SERVER_DISABLED
;
684 status
= cache
->backend
->enum_local_groups(domain
, mem_ctx
, num_entries
, info
);
687 refresh_sequence_number(domain
, True
);
688 centry
= centry_start(domain
, status
);
689 if (!centry
) goto skip_save
;
690 centry_put_uint32(centry
, *num_entries
);
691 for (i
=0; i
<(*num_entries
); i
++) {
692 centry_put_string(centry
, (*info
)[i
].acct_name
);
693 centry_put_string(centry
, (*info
)[i
].acct_desc
);
694 centry_put_uint32(centry
, (*info
)[i
].rid
);
696 centry_end(centry
, "GL/%s/local", domain
->name
);
703 /* convert a single name to a sid in a domain */
704 static NTSTATUS
name_to_sid(struct winbindd_domain
*domain
,
708 enum SID_NAME_USE
*type
)
710 struct winbind_cache
*cache
= get_cache(domain
);
711 struct cache_entry
*centry
= NULL
;
716 if (!cache
->tdb
) goto do_query
;
718 fstrcpy(uname
, name
);
720 centry
= wcache_fetch(cache
, domain
, "NS/%s/%s", domain
->name
, uname
);
721 if (!centry
) goto do_query
;
722 *type
= centry_uint32(centry
);
723 sid2
= centry_sid(centry
, mem_ctx
);
730 status
= centry
->status
;
737 if (wcache_server_down(domain
)) {
738 return NT_STATUS_SERVER_DISABLED
;
740 status
= cache
->backend
->name_to_sid(domain
, mem_ctx
, name
, sid
, type
);
743 wcache_save_name_to_sid(domain
, status
, name
, sid
, *type
);
745 /* We can't save the sid to name mapping as we don't know the
746 correct case of the name without looking it up */
751 /* convert a sid to a user or group name. The sid is guaranteed to be in the domain
753 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
757 enum SID_NAME_USE
*type
)
759 struct winbind_cache
*cache
= get_cache(domain
);
760 struct cache_entry
*centry
= NULL
;
764 if (!cache
->tdb
) goto do_query
;
766 centry
= wcache_fetch(cache
, domain
, "SN/%s", sid_to_string(sid_string
, sid
));
767 if (!centry
) goto do_query
;
768 if (NT_STATUS_IS_OK(centry
->status
)) {
769 *type
= centry_uint32(centry
);
770 *name
= centry_string(centry
, mem_ctx
);
772 status
= centry
->status
;
779 if (wcache_server_down(domain
)) {
780 return NT_STATUS_SERVER_DISABLED
;
782 status
= cache
->backend
->sid_to_name(domain
, mem_ctx
, sid
, name
, type
);
785 refresh_sequence_number(domain
, True
);
786 wcache_save_sid_to_name(domain
, status
, sid
, *name
, *type
);
787 wcache_save_name_to_sid(domain
, status
, *name
, sid
, *type
);
793 /* Lookup user information from a rid */
794 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
797 WINBIND_USERINFO
*info
)
799 struct winbind_cache
*cache
= get_cache(domain
);
800 struct cache_entry
*centry
= NULL
;
804 if (!cache
->tdb
) goto do_query
;
806 centry
= wcache_fetch(cache
, domain
, "U/%s", sid_to_string(sid_string
, user_sid
));
807 if (!centry
) goto do_query
;
809 info
->acct_name
= centry_string(centry
, mem_ctx
);
810 info
->full_name
= centry_string(centry
, mem_ctx
);
811 info
->user_sid
= centry_sid(centry
, mem_ctx
);
812 info
->group_sid
= centry_sid(centry
, mem_ctx
);
813 status
= centry
->status
;
820 if (wcache_server_down(domain
)) {
821 return NT_STATUS_SERVER_DISABLED
;
824 status
= cache
->backend
->query_user(domain
, mem_ctx
, user_sid
, info
);
827 refresh_sequence_number(domain
, True
);
828 wcache_save_user(domain
, status
, info
);
834 /* Lookup groups a user is a member of. */
835 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
838 uint32
*num_groups
, DOM_SID
***user_gids
)
840 struct winbind_cache
*cache
= get_cache(domain
);
841 struct cache_entry
*centry
= NULL
;
846 if (!cache
->tdb
) goto do_query
;
848 centry
= wcache_fetch(cache
, domain
, "UG/%s", sid_to_string(sid_string
, user_sid
));
849 if (!centry
) goto do_query
;
851 *num_groups
= centry_uint32(centry
);
853 if (*num_groups
== 0) goto do_cached
;
855 (*user_gids
) = talloc(mem_ctx
, sizeof(**user_gids
) * (*num_groups
));
856 if (! (*user_gids
)) smb_panic("lookup_usergroups out of memory");
857 for (i
=0; i
<(*num_groups
); i
++) {
858 (*user_gids
)[i
] = centry_sid(centry
, mem_ctx
);
862 status
= centry
->status
;
870 if (wcache_server_down(domain
)) {
871 return NT_STATUS_SERVER_DISABLED
;
873 status
= cache
->backend
->lookup_usergroups(domain
, mem_ctx
, user_sid
, num_groups
, user_gids
);
876 refresh_sequence_number(domain
, True
);
877 centry
= centry_start(domain
, status
);
878 if (!centry
) goto skip_save
;
879 centry_put_uint32(centry
, *num_groups
);
880 for (i
=0; i
<(*num_groups
); i
++) {
881 centry_put_sid(centry
, (*user_gids
)[i
]);
883 centry_end(centry
, "UG/%s", sid_to_string(sid_string
, user_sid
));
891 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
893 DOM_SID
*group_sid
, uint32
*num_names
,
894 DOM_SID
***sid_mem
, char ***names
,
897 struct winbind_cache
*cache
= get_cache(domain
);
898 struct cache_entry
*centry
= NULL
;
903 if (!cache
->tdb
) goto do_query
;
905 centry
= wcache_fetch(cache
, domain
, "GM/%s", sid_to_string(sid_string
, group_sid
));
906 if (!centry
) goto do_query
;
908 *num_names
= centry_uint32(centry
);
910 if (*num_names
== 0) goto do_cached
;
912 (*sid_mem
) = talloc(mem_ctx
, sizeof(**sid_mem
) * (*num_names
));
913 (*names
) = talloc(mem_ctx
, sizeof(**names
) * (*num_names
));
914 (*name_types
) = talloc(mem_ctx
, sizeof(**name_types
) * (*num_names
));
916 if (! (*sid_mem
) || ! (*names
) || ! (*name_types
)) {
917 smb_panic("lookup_groupmem out of memory");
920 for (i
=0; i
<(*num_names
); i
++) {
921 (*sid_mem
)[i
] = centry_sid(centry
, mem_ctx
);
922 (*names
)[i
] = centry_string(centry
, mem_ctx
);
923 (*name_types
)[i
] = centry_uint32(centry
);
927 status
= centry
->status
;
935 (*name_types
) = NULL
;
938 if (wcache_server_down(domain
)) {
939 return NT_STATUS_SERVER_DISABLED
;
941 status
= cache
->backend
->lookup_groupmem(domain
, mem_ctx
, group_sid
, num_names
,
942 sid_mem
, names
, name_types
);
945 refresh_sequence_number(domain
, True
);
946 centry
= centry_start(domain
, status
);
947 if (!centry
) goto skip_save
;
948 centry_put_uint32(centry
, *num_names
);
949 for (i
=0; i
<(*num_names
); i
++) {
950 centry_put_sid(centry
, (*sid_mem
)[i
]);
951 centry_put_string(centry
, (*names
)[i
]);
952 centry_put_uint32(centry
, (*name_types
)[i
]);
954 centry_end(centry
, "GM/%s", sid_to_string(sid_string
, group_sid
));
961 /* find the sequence number for a domain */
962 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
964 refresh_sequence_number(domain
, False
);
966 *seq
= domain
->sequence_number
;
971 /* enumerate trusted domains */
972 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
979 struct winbind_cache
*cache
= get_cache(domain
);
981 /* we don't cache this call */
982 return cache
->backend
->trusted_domains(domain
, mem_ctx
, num_domains
,
983 names
, alt_names
, dom_sids
);
986 /* find the domain sid */
987 static NTSTATUS
domain_sid(struct winbindd_domain
*domain
, DOM_SID
*sid
)
989 struct winbind_cache
*cache
= get_cache(domain
);
991 /* we don't cache this call */
992 return cache
->backend
->domain_sid(domain
, sid
);
995 /* find the alternate names for the domain, if any */
996 static NTSTATUS
alternate_name(struct winbindd_domain
*domain
)
998 struct winbind_cache
*cache
= get_cache(domain
);
1000 /* we don't cache this call */
1001 return cache
->backend
->alternate_name(domain
);
1004 /* the ADS backend methods are exposed via this structure */
1005 struct winbindd_methods cache_methods
= {