source: vendor/3.5.0/source3/winbindd/winbindd_passdb.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 17.9 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Winbind rpc backend functions
5
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Simo Sorce 2003
8 Copyright (C) Volker Lendecke 2004
9 Copyright (C) Jeremy Allison 2008
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "includes.h"
26#include "winbindd.h"
27
28#undef DBGC_CLASS
29#define DBGC_CLASS DBGC_WINBIND
30
31static NTSTATUS enum_groups_internal(struct winbindd_domain *domain,
32 TALLOC_CTX *mem_ctx,
33 uint32 *num_entries,
34 struct acct_info **info,
35 enum lsa_SidType sidtype)
36{
37 struct pdb_search *search;
38 struct samr_displayentry *entries;
39 int i;
40 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41
42 if (sidtype == SID_NAME_ALIAS) {
43 search = pdb_search_aliases(talloc_tos(), &domain->sid);
44 } else {
45 search = pdb_search_groups(talloc_tos());
46 }
47
48 if (search == NULL) goto done;
49
50 *num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries);
51 if (*num_entries == 0) {
52 /* Zero entries isn't an error */
53 result = NT_STATUS_OK;
54 goto done;
55 }
56
57 *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
58 if (*info == NULL) {
59 result = NT_STATUS_NO_MEMORY;
60 goto done;
61 }
62
63 for (i=0; i<*num_entries; i++) {
64 fstrcpy((*info)[i].acct_name, entries[i].account_name);
65 fstrcpy((*info)[i].acct_desc, entries[i].description);
66 (*info)[i].rid = entries[i].rid;
67 }
68
69 result = NT_STATUS_OK;
70 done:
71 TALLOC_FREE(search);
72 return result;
73}
74
75/* List all local groups (aliases) */
76static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
77 TALLOC_CTX *mem_ctx,
78 uint32 *num_entries,
79 struct acct_info **info)
80{
81 return enum_groups_internal(domain,
82 mem_ctx,
83 num_entries,
84 info,
85 SID_NAME_ALIAS);
86}
87
88/* convert a single name to a sid in a domain */
89static NTSTATUS name_to_sid(struct winbindd_domain *domain,
90 TALLOC_CTX *mem_ctx,
91 const char *domain_name,
92 const char *name,
93 uint32_t flags,
94 DOM_SID *sid,
95 enum lsa_SidType *type)
96{
97 const char *fullname;
98
99 flags |= LOOKUP_NAME_ALL;
100
101 if (domain_name && domain_name[0] && strchr_m(name, '\\') == NULL) {
102 fullname = talloc_asprintf(mem_ctx, "%s\\%s",
103 domain_name, name);
104 if (fullname == NULL) {
105 return NT_STATUS_NO_MEMORY;
106 }
107 } else {
108 fullname = name;
109 }
110
111 DEBUG(10, ("Finding fullname %s\n", fullname));
112
113 if ( !lookup_name( mem_ctx, fullname, flags, NULL, NULL, sid, type ) ) {
114 return NT_STATUS_NONE_MAPPED;
115 }
116
117 DEBUG(10, ("name_to_sid for %s returned %s (%s)\n",
118 fullname,
119 sid_string_dbg(sid),
120 sid_type_lookup((uint32)*type)));
121
122 return NT_STATUS_OK;
123}
124
125/*
126 convert a domain SID to a user or group name
127*/
128static NTSTATUS sid_to_name(struct winbindd_domain *domain,
129 TALLOC_CTX *mem_ctx,
130 const DOM_SID *sid,
131 char **domain_name,
132 char **name,
133 enum lsa_SidType *type)
134{
135 const char *dom, *nam;
136
137 DEBUG(10, ("Converting SID %s\n", sid_string_dbg(sid)));
138
139 /* Paranoia check */
140 if (!sid_check_is_in_builtin(sid) &&
141 !sid_check_is_in_our_domain(sid) &&
142 !sid_check_is_in_unix_users(sid) &&
143 !sid_check_is_unix_users(sid) &&
144 !sid_check_is_in_unix_groups(sid) &&
145 !sid_check_is_unix_groups(sid) &&
146 !sid_check_is_in_wellknown_domain(sid))
147 {
148 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
149 "passdb backend\n", sid_string_dbg(sid)));
150 return NT_STATUS_NONE_MAPPED;
151 }
152
153 if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
154 return NT_STATUS_NONE_MAPPED;
155 }
156
157 *domain_name = talloc_strdup(mem_ctx, dom);
158 *name = talloc_strdup(mem_ctx, nam);
159
160 return NT_STATUS_OK;
161}
162
163static NTSTATUS rids_to_names(struct winbindd_domain *domain,
164 TALLOC_CTX *mem_ctx,
165 const DOM_SID *sid,
166 uint32 *rids,
167 size_t num_rids,
168 char **domain_name,
169 char ***names,
170 enum lsa_SidType **types)
171{
172 size_t i;
173 bool have_mapped;
174 bool have_unmapped;
175
176 *domain_name = NULL;
177 *names = NULL;
178 *types = NULL;
179
180 if (!num_rids) {
181 return NT_STATUS_OK;
182 }
183
184 /* Paranoia check */
185 if (!sid_check_is_in_builtin(sid) &&
186 !sid_check_is_in_our_domain(sid) &&
187 !sid_check_is_in_unix_users(sid) &&
188 !sid_check_is_unix_users(sid) &&
189 !sid_check_is_in_unix_groups(sid) &&
190 !sid_check_is_unix_groups(sid) &&
191 !sid_check_is_in_wellknown_domain(sid))
192 {
193 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
194 "passdb backend\n", sid_string_dbg(sid)));
195 return NT_STATUS_NONE_MAPPED;
196 }
197
198 *names = TALLOC_ARRAY(mem_ctx, char *, num_rids);
199 *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
200
201 if ((*names == NULL) || (*types == NULL)) {
202 return NT_STATUS_NO_MEMORY;
203 }
204
205 have_mapped = have_unmapped = false;
206
207 for (i=0; i<num_rids; i++) {
208 DOM_SID lsid;
209 const char *dom = NULL, *nam = NULL;
210 enum lsa_SidType type = SID_NAME_UNKNOWN;
211
212 if (!sid_compose(&lsid, sid, rids[i])) {
213 return NT_STATUS_INTERNAL_ERROR;
214 }
215
216 if (!lookup_sid(mem_ctx, &lsid, &dom, &nam, &type)) {
217 have_unmapped = true;
218 (*types)[i] = SID_NAME_UNKNOWN;
219 (*names)[i] = talloc_strdup(mem_ctx, "");
220 } else {
221 have_mapped = true;
222 (*types)[i] = type;
223 (*names)[i] = CONST_DISCARD(char *, nam);
224 }
225
226 if (*domain_name == NULL) {
227 *domain_name = CONST_DISCARD(char *, dom);
228 } else {
229 char *dname = CONST_DISCARD(char *, dom);
230 TALLOC_FREE(dname);
231 }
232 }
233
234 if (!have_mapped) {
235 return NT_STATUS_NONE_MAPPED;
236 }
237 if (!have_unmapped) {
238 return NT_STATUS_OK;
239 }
240 return STATUS_SOME_UNMAPPED;
241}
242
243/* Lookup groups a user is a member of. I wish Unix had a call like this! */
244static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
245 TALLOC_CTX *mem_ctx,
246 const DOM_SID *user_sid,
247 uint32 *num_groups, DOM_SID **user_gids)
248{
249 NTSTATUS result;
250 DOM_SID *groups = NULL;
251 gid_t *gids = NULL;
252 size_t ngroups = 0;
253 struct samu *user;
254
255 if ( (user = samu_new(mem_ctx)) == NULL ) {
256 return NT_STATUS_NO_MEMORY;
257 }
258
259 if ( !pdb_getsampwsid( user, user_sid ) ) {
260 TALLOC_FREE( user );
261 return NT_STATUS_NO_SUCH_USER;
262 }
263
264 result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
265
266 TALLOC_FREE( user );
267
268 *num_groups = (uint32)ngroups;
269 *user_gids = groups;
270
271 return result;
272}
273
274static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
275 TALLOC_CTX *mem_ctx,
276 uint32 num_sids, const DOM_SID *sids,
277 uint32 *p_num_aliases, uint32 **rids)
278{
279 NTSTATUS result;
280 size_t num_aliases = 0;
281
282 result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
283 sids, num_sids, rids, &num_aliases);
284
285 *p_num_aliases = num_aliases;
286 return result;
287}
288
289/* find the sequence number for a domain */
290static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
291{
292 bool result;
293 time_t seq_num;
294
295 result = pdb_get_seq_num(&seq_num);
296 if (!result) {
297 *seq = 1;
298 }
299
300 *seq = (int) seq_num;
301 /* *seq = 1; */
302 return NT_STATUS_OK;
303}
304
305static NTSTATUS lockout_policy(struct winbindd_domain *domain,
306 TALLOC_CTX *mem_ctx,
307 struct samr_DomInfo12 *policy)
308{
309 /* actually we have that */
310 return NT_STATUS_NOT_IMPLEMENTED;
311}
312
313static NTSTATUS password_policy(struct winbindd_domain *domain,
314 TALLOC_CTX *mem_ctx,
315 struct samr_DomInfo1 *policy)
316{
317 struct samr_DomInfo1 *p;
318 time_t u_expire, u_min_age;
319 uint32 account_policy_temp;
320
321 if ((p = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) {
322 return NT_STATUS_NO_MEMORY;
323 }
324
325 if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN,
326 &account_policy_temp)) {
327 return NT_STATUS_ACCESS_DENIED;
328 }
329 p->min_password_length = account_policy_temp;
330
331 if (!pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY,
332 &account_policy_temp)) {
333 return NT_STATUS_ACCESS_DENIED;
334 }
335 p->password_history_length = account_policy_temp;
336
337 if (!pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS,
338 &p->password_properties)) {
339 return NT_STATUS_ACCESS_DENIED;
340 }
341
342 if (!pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp)) {
343 return NT_STATUS_ACCESS_DENIED;
344 }
345 u_expire = account_policy_temp;
346
347 if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp)) {
348 return NT_STATUS_ACCESS_DENIED;
349 }
350 u_min_age = account_policy_temp;
351
352 unix_to_nt_time_abs((NTTIME *)&p->max_password_age, u_expire);
353 unix_to_nt_time_abs((NTTIME *)&p->min_password_age, u_min_age);
354
355 policy = p;
356
357 return NT_STATUS_OK;
358}
359
360/*********************************************************************
361 BUILTIN specific functions.
362*********************************************************************/
363
364/* list all domain groups */
365static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
366 TALLOC_CTX *mem_ctx,
367 uint32 *num_entries,
368 struct acct_info **info)
369{
370 /* BUILTIN doesn't have domain groups */
371 *num_entries = 0;
372 *info = NULL;
373 return NT_STATUS_OK;
374}
375
376/* Query display info for a domain. This returns enough information plus a
377 bit extra to give an overview of domain users for the User Manager
378 application. */
379static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
380 TALLOC_CTX *mem_ctx,
381 uint32 *num_entries,
382 struct wbint_userinfo **info)
383{
384 /* We don't have users */
385 *num_entries = 0;
386 *info = NULL;
387 return NT_STATUS_OK;
388}
389
390/* Lookup user information from a rid or username. */
391static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
392 TALLOC_CTX *mem_ctx,
393 const DOM_SID *user_sid,
394 struct wbint_userinfo *user_info)
395{
396 return NT_STATUS_NO_SUCH_USER;
397}
398
399/* get a list of trusted domains - builtin domain */
400static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
401 TALLOC_CTX *mem_ctx,
402 struct netr_DomainTrustList *trusts)
403{
404 ZERO_STRUCTP(trusts);
405 return NT_STATUS_OK;
406}
407
408/*********************************************************************
409 SAM specific functions.
410*********************************************************************/
411
412/* list all domain groups */
413static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
414 TALLOC_CTX *mem_ctx,
415 uint32 *num_entries,
416 struct acct_info **info)
417{
418 return enum_groups_internal(domain,
419 mem_ctx,
420 num_entries,
421 info,
422 SID_NAME_DOM_GRP);
423}
424
425static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
426 TALLOC_CTX *mem_ctx,
427 uint32 *num_entries,
428 struct wbint_userinfo **info)
429{
430 struct pdb_search *ps = pdb_search_users(talloc_tos(), ACB_NORMAL);
431 struct samr_displayentry *entries = NULL;
432 uint32 i;
433
434 *num_entries = 0;
435 *info = NULL;
436
437 if (!ps) {
438 return NT_STATUS_NO_MEMORY;
439 }
440
441 *num_entries = pdb_search_entries(ps, 0, 0xffffffff, &entries);
442
443 DEBUG(10, ("sam_query_user_list: found %d users\n",
444 (int)*num_entries));
445
446 *info = TALLOC_ZERO_ARRAY(mem_ctx, struct wbint_userinfo, *num_entries);
447 if (!(*info)) {
448 TALLOC_FREE(ps);
449 return NT_STATUS_NO_MEMORY;
450 }
451
452 for (i = 0; i < *num_entries; i++) {
453 struct samr_displayentry *e = &entries[i];
454
455 (*info)[i].acct_name = talloc_strdup(mem_ctx, e->account_name );
456 (*info)[i].full_name = talloc_strdup(mem_ctx, e->fullname );
457 (*info)[i].homedir = NULL;
458 (*info)[i].shell = NULL;
459 sid_compose(&(*info)[i].user_sid, &domain->sid, e->rid);
460
461 /* For the moment we set the primary group for
462 every user to be the Domain Users group.
463 There are serious problems with determining
464 the actual primary group for large domains.
465 This should really be made into a 'winbind
466 force group' smb.conf parameter or
467 something like that. */
468
469 sid_compose(&(*info)[i].group_sid, &domain->sid,
470 DOMAIN_GROUP_RID_USERS);
471 }
472
473 TALLOC_FREE(ps);
474 return NT_STATUS_OK;
475}
476
477/* Lookup user information from a rid or username. */
478static NTSTATUS sam_query_user(struct winbindd_domain *domain,
479 TALLOC_CTX *mem_ctx,
480 const DOM_SID *user_sid,
481 struct wbint_userinfo *user_info)
482{
483 struct samu *sampass = NULL;
484
485 ZERO_STRUCTP(user_info);
486
487 if (!sid_check_is_in_our_domain(user_sid)) {
488 return NT_STATUS_NO_SUCH_USER;
489 }
490
491 DEBUG(10,("sam_query_user: getting samu info for sid %s\n",
492 sid_string_dbg(user_sid) ));
493
494 if (!(sampass = samu_new(mem_ctx))) {
495 return NT_STATUS_NO_MEMORY;
496 }
497
498 if (!pdb_getsampwsid(sampass, user_sid)) {
499 TALLOC_FREE(sampass);
500 return NT_STATUS_NO_SUCH_USER;
501 }
502
503 if (pdb_get_group_sid(sampass) == NULL) {
504 TALLOC_FREE(sampass);
505 return NT_STATUS_NO_SUCH_GROUP;
506 }
507
508 DEBUG(10,("sam_query_user: group sid %s\n",
509 sid_string_dbg(sampass->group_sid) ));
510
511 sid_copy(&user_info->user_sid, user_sid);
512 sid_copy(&user_info->group_sid, sampass->group_sid);
513
514 user_info->acct_name = talloc_strdup(mem_ctx, sampass->username ?
515 sampass->username : "");
516 user_info->full_name = talloc_strdup(mem_ctx, sampass->full_name ?
517 sampass->full_name : "");
518 user_info->homedir = talloc_strdup(mem_ctx, sampass->home_dir ?
519 sampass->home_dir : "");
520 if (sampass->unix_pw && sampass->unix_pw->pw_shell) {
521 user_info->shell = talloc_strdup(mem_ctx, sampass->unix_pw->pw_shell);
522 } else {
523 user_info->shell = talloc_strdup(mem_ctx, "");
524 }
525 user_info->primary_gid = sampass->unix_pw ? sampass->unix_pw->pw_gid : (gid_t)-1;
526
527 TALLOC_FREE(sampass);
528 return NT_STATUS_OK;
529}
530
531/* Lookup group membership given a rid. */
532static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
533 TALLOC_CTX *mem_ctx,
534 const DOM_SID *group_sid,
535 enum lsa_SidType type,
536 uint32 *num_names,
537 DOM_SID **sid_mem, char ***names,
538 uint32 **name_types)
539{
540 size_t i, num_members, num_mapped;
541 NTSTATUS result;
542 const DOM_SID **sids;
543 struct lsa_dom_info *lsa_domains;
544 struct lsa_name_info *lsa_names;
545 TALLOC_CTX *tmp_ctx;
546
547 DEBUG(10,("passdb: lookup_groupmem (sam) %s sid=%s\n", domain->name,
548 sid_string_dbg(group_sid)));
549
550 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
551 /* There's no groups, only aliases in BUILTIN */
552 return NT_STATUS_NO_SUCH_GROUP;
553 }
554
555 if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
556 return NT_STATUS_NO_MEMORY;
557 }
558
559 if (type == SID_NAME_DOM_GRP) {
560 uint32 *rids;
561
562 result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
563 &num_members);
564 if (!NT_STATUS_IS_OK(result)) {
565 TALLOC_FREE(tmp_ctx);
566 return result;
567 }
568 *sid_mem = talloc_array(mem_ctx, struct dom_sid, num_members);
569 if (*sid_mem == NULL) {
570 TALLOC_FREE(tmp_ctx);
571 return NT_STATUS_NO_MEMORY;
572 }
573 for (i=0; i<num_members; i++) {
574 sid_compose(&((*sid_mem)[i]), &domain->sid, rids[i]);
575 }
576 TALLOC_FREE(rids);
577 } else {
578 result = pdb_enum_aliasmem(group_sid, mem_ctx, sid_mem,
579 &num_members);
580 if (!NT_STATUS_IS_OK(result)) {
581 TALLOC_FREE(tmp_ctx);
582 return result;
583 }
584 }
585
586 if (num_members == 0) {
587 *num_names = 0;
588 *sid_mem = NULL;
589 *names = NULL;
590 *name_types = NULL;
591 TALLOC_FREE(tmp_ctx);
592 return NT_STATUS_OK;
593 }
594
595 *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
596 *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
597 sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
598
599 if (((*names) == NULL) || ((*name_types) == NULL) || (sids == NULL)) {
600 TALLOC_FREE(tmp_ctx);
601 return NT_STATUS_NO_MEMORY;
602 }
603
604 /*
605 * Prepare an array of sid pointers for the lookup_sids calling
606 * convention.
607 */
608
609 for (i=0; i<num_members; i++) {
610 sids[i] = &((*sid_mem)[i]);
611 }
612
613 result = lookup_sids(tmp_ctx, num_members, sids, 1,
614 &lsa_domains, &lsa_names);
615 if (!NT_STATUS_IS_OK(result)) {
616 TALLOC_FREE(tmp_ctx);
617 return result;
618 }
619
620 num_mapped = 0;
621 for (i=0; i<num_members; i++) {
622 if (lsa_names[i].type != SID_NAME_USER) {
623 DEBUG(2, ("Got %s as group member -- ignoring\n",
624 sid_type_lookup(lsa_names[i].type)));
625 continue;
626 }
627 if (!((*names)[num_mapped] = talloc_strdup((*names),
628 lsa_names[i].name))) {
629 TALLOC_FREE(tmp_ctx);
630 return NT_STATUS_NO_MEMORY;
631 }
632
633 (*name_types)[num_mapped] = lsa_names[i].type;
634
635 num_mapped += 1;
636 }
637
638 *num_names = num_mapped;
639
640 TALLOC_FREE(tmp_ctx);
641 return NT_STATUS_OK;
642}
643
644/* get a list of trusted domains */
645static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
646 TALLOC_CTX *mem_ctx,
647 struct netr_DomainTrustList *trusts)
648{
649 NTSTATUS nt_status;
650 struct trustdom_info **domains;
651 int i;
652
653 nt_status = pdb_enum_trusteddoms(talloc_tos(), &trusts->count,
654 &domains);
655 if (!NT_STATUS_IS_OK(nt_status)) {
656 return nt_status;
657 }
658
659 if (trusts->count == 0) {
660 trusts->array = NULL;
661 return NT_STATUS_OK;
662 }
663
664 trusts->array = talloc_zero_array(
665 mem_ctx, struct netr_DomainTrust, trusts->count);
666 if (trusts->array == NULL) {
667 return NT_STATUS_NO_MEMORY;
668 }
669
670 for (i=0; i<trusts->count; i++) {
671 struct dom_sid *sid;
672
673 trusts->array[i].netbios_name = talloc_move(
674 trusts->array, &domains[i]->name);
675 trusts->array[i].dns_name = NULL;
676
677 sid = talloc(trusts->array, struct dom_sid);
678 if (sid == NULL) {
679 return NT_STATUS_NO_MEMORY;
680 }
681 sid_copy(sid, &domains[i]->sid);
682 trusts->array[i].sid = sid;
683 }
684 return NT_STATUS_OK;
685}
686
687/* the rpc backend methods are exposed via this structure */
688struct winbindd_methods builtin_passdb_methods = {
689 false,
690 builtin_query_user_list,
691 builtin_enum_dom_groups,
692 enum_local_groups,
693 name_to_sid,
694 sid_to_name,
695 rids_to_names,
696 builtin_query_user,
697 lookup_usergroups,
698 lookup_useraliases,
699 sam_lookup_groupmem,
700 sequence_number,
701 lockout_policy,
702 password_policy,
703 builtin_trusted_domains,
704};
705
706/* the rpc backend methods are exposed via this structure */
707struct winbindd_methods sam_passdb_methods = {
708 false,
709 sam_query_user_list,
710 sam_enum_dom_groups,
711 enum_local_groups,
712 name_to_sid,
713 sid_to_name,
714 rids_to_names,
715 sam_query_user,
716 lookup_usergroups,
717 lookup_useraliases,
718 sam_lookup_groupmem,
719 sequence_number,
720 lockout_policy,
721 password_policy,
722 sam_trusted_domains,
723};
Note: See TracBrowser for help on using the repository browser.