2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Simo Sorce 2003
8 Copyright (C) Volker Lendecke 2004
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/>.
28 #define DBGC_CLASS DBGC_WINBIND
30 static NTSTATUS query_user_list_dom(struct winbindd_domain *domain,
33 WINBIND_USERINFO **info)
35 struct pdb_search *search;
36 struct samr_displayentry *users;
38 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
40 search = pdb_search_users(ACB_NORMAL);
41 if (search == NULL) goto done;
43 *num_entries = pdb_search_entries(search, 0, 0xffffffff, &users);
44 if (*num_entries == 0) goto done;
46 *info = TALLOC_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries);
48 result = NT_STATUS_NO_MEMORY;
52 for (i=0; i<*num_entries; i++) {
53 (*info)[i].acct_name = talloc_strdup(mem_ctx, users[i].account_name);
54 if (!(*info)[i].acct_name) goto nomem;
55 (*info)[i].full_name = talloc_strdup(mem_ctx, users[i].fullname);
56 if (!(*info)[i].full_name) goto nomem;
57 (*info)[i].homedir = NULL;
58 (*info)[i].shell = NULL;
59 (*info)[i].primary_gid = (gid_t)-1;
61 sid_compose(&(*info)[i].user_sid, &domain->sid, users[i].rid);
63 /* For the moment we set the primary group for
64 every user to be the Domain Users group.
65 There are serious problems with determining
66 the actual primary group for large domains.
67 This should really be made into a 'winbind
68 force group' smb.conf parameter or
69 something like that. */
71 sid_compose(&(*info)[i].group_sid, &domain->sid,
72 DOMAIN_GROUP_RID_USERS);
75 result = NT_STATUS_OK;
78 result = NT_STATUS_NO_MEMORY;
80 pdb_search_destroy(search);
84 /* Query display info for a domain. This returns enough information plus a
85 bit extra to give an overview of domain users for the User Manager
87 static NTSTATUS query_user_list(struct winbindd_domain *domain,
90 WINBIND_USERINFO **info)
92 return query_user_list_dom(domain, mem_ctx, num_entries, info);
93 /* We don't have users */
99 /* list all domain groups */
100 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
103 struct acct_info **info)
105 /* We don't have domain groups */
111 /* List all domain groups */
113 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
116 struct acct_info **info)
118 struct pdb_search *search;
119 struct samr_displayentry *aliases;
121 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
123 search = pdb_search_aliases(&domain->sid);
124 if (search == NULL) goto done;
126 *num_entries = pdb_search_entries(search, 0, 0xffffffff, &aliases);
127 if (*num_entries == 0) goto done;
129 *info = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
131 result = NT_STATUS_NO_MEMORY;
135 for (i=0; i<*num_entries; i++) {
136 fstrcpy((*info)[i].acct_name, aliases[i].account_name);
137 fstrcpy((*info)[i].acct_desc, aliases[i].description);
138 (*info)[i].rid = aliases[i].rid;
141 result = NT_STATUS_OK;
143 pdb_search_destroy(search);
147 /* convert a single name to a sid in a domain */
148 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
150 enum winbindd_cmd original_cmd,
151 const char *domain_name,
154 enum lsa_SidType *type)
156 uint32 flags = LOOKUP_NAME_ALL;
158 switch ( original_cmd ) {
159 case WINBINDD_LOOKUPNAME:
160 /* This call is ok */
163 /* Avoid any NSS calls in the lookup_name by default */
164 flags |= LOOKUP_NAME_EXPLICIT;
165 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
169 DEBUG(10, ("Finding name %s\n", name));
171 if ( !lookup_name( mem_ctx, name, flags, NULL, NULL, sid, type ) ) {
172 return NT_STATUS_NONE_MAPPED;
179 convert a domain SID to a user or group name
181 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
186 enum lsa_SidType *type)
188 const char *dom, *nam;
190 DEBUG(10, ("Converting SID %s\n", sid_string_dbg(sid)));
193 if (!sid_check_is_in_builtin(sid) &&
194 !sid_check_is_in_our_domain(sid) &&
195 !sid_check_is_in_unix_users(sid) &&
196 !sid_check_is_unix_users(sid) &&
197 !sid_check_is_in_unix_groups(sid) &&
198 !sid_check_is_unix_groups(sid) &&
199 !sid_check_is_in_wellknown_domain(sid))
201 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
202 "passdb backend\n", sid_string_dbg(sid)));
203 return NT_STATUS_NONE_MAPPED;
206 if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
207 return NT_STATUS_NONE_MAPPED;
210 *domain_name = talloc_strdup(mem_ctx, dom);
211 *name = talloc_strdup(mem_ctx, nam);
216 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
223 enum lsa_SidType **types)
225 return NT_STATUS_UNSUCCESSFUL;
228 /* Lookup user information from a rid or username. */
229 static NTSTATUS query_user(struct winbindd_domain *domain,
231 const DOM_SID *user_sid,
232 WINBIND_USERINFO *user_info)
234 return NT_STATUS_NO_SUCH_USER;
237 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
238 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
240 const DOM_SID *user_sid,
241 uint32 *num_groups, DOM_SID **user_gids)
244 DOM_SID *groups = NULL;
249 if ( (user = samu_new(mem_ctx)) == NULL ) {
250 return NT_STATUS_NO_MEMORY;
253 if ( !pdb_getsampwsid( user, user_sid ) ) {
254 return NT_STATUS_NO_SUCH_USER;
257 result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
261 *num_groups = (uint32)ngroups;
267 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
269 uint32 num_sids, const DOM_SID *sids,
270 uint32 *p_num_aliases, uint32 **rids)
273 size_t num_aliases = 0;
275 result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
276 sids, num_sids, rids, &num_aliases);
278 *p_num_aliases = num_aliases;
282 /* Lookup group membership given a rid. */
283 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
285 const DOM_SID *group_sid, uint32 *num_names,
286 DOM_SID **sid_mem, char ***names,
289 size_t i, num_members, num_mapped;
292 const DOM_SID **sids;
293 struct lsa_dom_info *lsa_domains;
294 struct lsa_name_info *lsa_names;
297 if (!sid_check_is_in_our_domain(group_sid)) {
298 /* There's no groups, only aliases in BUILTIN */
299 return NT_STATUS_NO_SUCH_GROUP;
302 if (!(tmp_ctx = talloc_init("lookup_groupmem"))) {
303 return NT_STATUS_NO_MEMORY;
306 result = pdb_enum_group_members(tmp_ctx, group_sid, &rids,
308 if (!NT_STATUS_IS_OK(result)) {
309 TALLOC_FREE(tmp_ctx);
313 if (num_members == 0) {
318 TALLOC_FREE(tmp_ctx);
322 *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
323 *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
324 *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
325 sids = TALLOC_ARRAY(tmp_ctx, const DOM_SID *, num_members);
327 if (((*sid_mem) == NULL) || ((*names) == NULL) ||
328 ((*name_types) == NULL) || (sids == NULL)) {
329 TALLOC_FREE(tmp_ctx);
330 return NT_STATUS_NO_MEMORY;
334 * Prepare an array of sid pointers for the lookup_sids calling
338 for (i=0; i<num_members; i++) {
339 DOM_SID *sid = &((*sid_mem)[i]);
340 if (!sid_compose(sid, &domain->sid, rids[i])) {
341 TALLOC_FREE(tmp_ctx);
342 return NT_STATUS_INTERNAL_ERROR;
347 result = lookup_sids(tmp_ctx, num_members, sids, 1,
348 &lsa_domains, &lsa_names);
349 if (!NT_STATUS_IS_OK(result)) {
350 TALLOC_FREE(tmp_ctx);
355 for (i=0; i<num_members; i++) {
356 if (lsa_names[i].type != SID_NAME_USER) {
357 DEBUG(2, ("Got %s as group member -- ignoring\n",
358 sid_type_lookup(lsa_names[i].type)));
361 if (!((*names)[i] = talloc_strdup((*names),
362 lsa_names[i].name))) {
363 TALLOC_FREE(tmp_ctx);
364 return NT_STATUS_NO_MEMORY;
367 (*name_types)[i] = lsa_names[i].type;
372 *num_names = num_mapped;
374 TALLOC_FREE(tmp_ctx);
378 /* find the sequence number for a domain */
379 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
384 result = pdb_get_seq_num(&seq_num);
389 *seq = (int) seq_num;
394 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
396 struct samr_DomInfo12 *policy)
398 /* actually we have that */
399 return NT_STATUS_NOT_IMPLEMENTED;
402 static NTSTATUS password_policy(struct winbindd_domain *domain,
404 struct samr_DomInfo1 *policy)
406 uint32 min_pass_len,pass_hist,password_properties;
407 time_t u_expire, u_min_age;
408 NTTIME nt_expire, nt_min_age;
409 uint32 account_policy_temp;
411 if ((policy = TALLOC_ZERO_P(mem_ctx, struct samr_DomInfo1)) == NULL) {
412 return NT_STATUS_NO_MEMORY;
415 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
416 return NT_STATUS_ACCESS_DENIED;
418 min_pass_len = account_policy_temp;
420 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
421 return NT_STATUS_ACCESS_DENIED;
423 pass_hist = account_policy_temp;
425 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
426 return NT_STATUS_ACCESS_DENIED;
428 password_properties = account_policy_temp;
430 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
431 return NT_STATUS_ACCESS_DENIED;
433 u_expire = account_policy_temp;
435 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
436 return NT_STATUS_ACCESS_DENIED;
438 u_min_age = account_policy_temp;
440 unix_to_nt_time_abs(&nt_expire, u_expire);
441 unix_to_nt_time_abs(&nt_min_age, u_min_age);
443 init_samr_DomInfo1(policy,
444 (uint16)min_pass_len,
453 /* get a list of trusted domains */
454 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
462 struct trustdom_info **domains;
471 if (!(tmp_ctx = talloc_init("trusted_domains"))) {
472 return NT_STATUS_NO_MEMORY;
475 nt_status = pdb_enum_trusteddoms(tmp_ctx, num_domains, &domains);
476 if (!NT_STATUS_IS_OK(nt_status)) {
477 TALLOC_FREE(tmp_ctx);
482 *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
483 *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
484 *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
486 if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
487 TALLOC_FREE(tmp_ctx);
488 return NT_STATUS_NO_MEMORY;
496 for (i=0; i<*num_domains; i++) {
497 (*alt_names)[i] = NULL;
498 if (!((*names)[i] = talloc_strdup((*names),
499 domains[i]->name))) {
500 TALLOC_FREE(tmp_ctx);
501 return NT_STATUS_NO_MEMORY;
503 sid_copy(&(*dom_sids)[i], &domains[i]->sid);
506 TALLOC_FREE(tmp_ctx);
510 /* the rpc backend methods are exposed via this structure */
511 struct winbindd_methods passdb_methods = {