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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_WINBIND
31 /* Query display info for a domain. This returns enough information plus a
32 bit extra to give an overview of domain users for the User Manager
34 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
37 WINBIND_USERINFO
**info
)
39 /* We don't have users */
45 /* list all domain groups */
46 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
49 struct acct_info
**info
)
51 /* We don't have domain groups */
57 /* List all domain groups */
59 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
62 struct acct_info
**info
)
64 struct pdb_search
*search
;
65 struct samr_displayentry
*aliases
;
67 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
69 search
= pdb_search_aliases(&domain
->sid
);
70 if (search
== NULL
) goto done
;
72 *num_entries
= pdb_search_entries(search
, 0, 0xffffffff, &aliases
);
73 if (*num_entries
== 0) goto done
;
75 *info
= TALLOC_ARRAY(mem_ctx
, struct acct_info
, *num_entries
);
77 result
= NT_STATUS_NO_MEMORY
;
81 for (i
=0; i
<*num_entries
; i
++) {
82 fstrcpy((*info
)[i
].acct_name
, aliases
[i
].account_name
);
83 fstrcpy((*info
)[i
].acct_desc
, aliases
[i
].description
);
84 (*info
)[i
].rid
= aliases
[i
].rid
;
87 result
= NT_STATUS_OK
;
89 pdb_search_destroy(search
);
93 /* convert a single name to a sid in a domain */
94 static NTSTATUS
name_to_sid(struct winbindd_domain
*domain
,
96 enum winbindd_cmd original_cmd
,
97 const char *domain_name
,
100 enum lsa_SidType
*type
)
102 uint32 flags
= LOOKUP_NAME_ALL
;
104 switch ( original_cmd
) {
105 case WINBINDD_LOOKUPNAME
:
106 /* This call is ok */
109 /* Avoid any NSS calls in the lookup_name by default */
110 flags
|= LOOKUP_NAME_EXPLICIT
;
111 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
115 DEBUG(10, ("Finding name %s\n", name
));
117 if ( !lookup_name( mem_ctx
, name
, flags
, NULL
, NULL
, sid
, type
) ) {
118 return NT_STATUS_NONE_MAPPED
;
125 convert a domain SID to a user or group name
127 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
132 enum lsa_SidType
*type
)
134 const char *dom
, *nam
;
136 DEBUG(10, ("Converting SID %s\n", sid_string_static(sid
)));
139 if (!sid_check_is_in_builtin(sid
) &&
140 !sid_check_is_in_our_domain(sid
) &&
141 !sid_check_is_in_unix_users(sid
) &&
142 !sid_check_is_unix_users(sid
) &&
143 !sid_check_is_in_unix_groups(sid
) &&
144 !sid_check_is_unix_groups(sid
) )
146 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
147 "passdb backend\n", sid_string_static(sid
)));
148 return NT_STATUS_NONE_MAPPED
;
151 if (!lookup_sid(mem_ctx
, sid
, &dom
, &nam
, type
)) {
152 return NT_STATUS_NONE_MAPPED
;
155 *domain_name
= talloc_strdup(mem_ctx
, dom
);
156 *name
= talloc_strdup(mem_ctx
, nam
);
161 static NTSTATUS
rids_to_names(struct winbindd_domain
*domain
,
168 enum lsa_SidType
**types
)
170 return NT_STATUS_UNSUCCESSFUL
;
173 /* Lookup user information from a rid or username. */
174 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
176 const DOM_SID
*user_sid
,
177 WINBIND_USERINFO
*user_info
)
179 return NT_STATUS_NO_SUCH_USER
;
182 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
183 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
185 const DOM_SID
*user_sid
,
186 uint32
*num_groups
, DOM_SID
**user_gids
)
189 DOM_SID
*groups
= NULL
;
194 if ( (user
= samu_new(mem_ctx
)) == NULL
) {
195 return NT_STATUS_NO_MEMORY
;
198 if ( !pdb_getsampwsid( user
, user_sid
) ) {
199 return NT_STATUS_NO_SUCH_USER
;
202 result
= pdb_enum_group_memberships( mem_ctx
, user
, &groups
, &gids
, &ngroups
);
206 *num_groups
= (uint32
)ngroups
;
212 static NTSTATUS
lookup_useraliases(struct winbindd_domain
*domain
,
214 uint32 num_sids
, const DOM_SID
*sids
,
215 uint32
*p_num_aliases
, uint32
**rids
)
218 size_t num_aliases
= 0;
220 result
= pdb_enum_alias_memberships(mem_ctx
, &domain
->sid
,
221 sids
, num_sids
, rids
, &num_aliases
);
223 *p_num_aliases
= num_aliases
;
227 /* Lookup group membership given a rid. */
228 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
230 const DOM_SID
*group_sid
, uint32
*num_names
,
231 DOM_SID
**sid_mem
, char ***names
,
234 size_t i
, num_members
, num_mapped
;
237 const DOM_SID
**sids
;
238 struct lsa_dom_info
*lsa_domains
;
239 struct lsa_name_info
*lsa_names
;
242 if (!sid_check_is_in_our_domain(group_sid
)) {
243 /* There's no groups, only aliases in BUILTIN */
244 return NT_STATUS_NO_SUCH_GROUP
;
247 if (!(tmp_ctx
= talloc_init("lookup_groupmem"))) {
248 return NT_STATUS_NO_MEMORY
;
251 result
= pdb_enum_group_members(tmp_ctx
, group_sid
, &rids
,
253 if (!NT_STATUS_IS_OK(result
)) {
254 TALLOC_FREE(tmp_ctx
);
258 if (num_members
== 0) {
263 TALLOC_FREE(tmp_ctx
);
267 *sid_mem
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, num_members
);
268 *names
= TALLOC_ARRAY(mem_ctx
, char *, num_members
);
269 *name_types
= TALLOC_ARRAY(mem_ctx
, uint32
, num_members
);
270 sids
= TALLOC_ARRAY(tmp_ctx
, const DOM_SID
*, num_members
);
272 if (((*sid_mem
) == NULL
) || ((*names
) == NULL
) ||
273 ((*name_types
) == NULL
) || (sids
== NULL
)) {
274 TALLOC_FREE(tmp_ctx
);
275 return NT_STATUS_NO_MEMORY
;
279 * Prepare an array of sid pointers for the lookup_sids calling
283 for (i
=0; i
<num_members
; i
++) {
284 DOM_SID
*sid
= &((*sid_mem
)[i
]);
285 if (!sid_compose(sid
, &domain
->sid
, rids
[i
])) {
286 TALLOC_FREE(tmp_ctx
);
287 return NT_STATUS_INTERNAL_ERROR
;
292 result
= lookup_sids(tmp_ctx
, num_members
, sids
, 1,
293 &lsa_domains
, &lsa_names
);
294 if (!NT_STATUS_IS_OK(result
)) {
295 TALLOC_FREE(tmp_ctx
);
300 for (i
=0; i
<num_members
; i
++) {
301 if (lsa_names
[i
].type
!= SID_NAME_USER
) {
302 DEBUG(2, ("Got %s as group member -- ignoring\n",
303 sid_type_lookup(lsa_names
[i
].type
)));
306 if (!((*names
)[i
] = talloc_strdup((*names
),
307 lsa_names
[i
].name
))) {
308 TALLOC_FREE(tmp_ctx
);
309 return NT_STATUS_NO_MEMORY
;
312 (*name_types
)[i
] = lsa_names
[i
].type
;
317 *num_names
= num_mapped
;
319 TALLOC_FREE(tmp_ctx
);
323 /* find the sequence number for a domain */
324 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
329 result
= pdb_get_seq_num(&seq_num
);
334 *seq
= (int) seq_num
;
339 static NTSTATUS
lockout_policy(struct winbindd_domain
*domain
,
341 SAM_UNK_INFO_12
*policy
)
343 /* actually we have that */
344 return NT_STATUS_NOT_IMPLEMENTED
;
347 static NTSTATUS
password_policy(struct winbindd_domain
*domain
,
349 SAM_UNK_INFO_1
*policy
)
351 uint32 min_pass_len
,pass_hist
,password_properties
;
352 time_t u_expire
, u_min_age
;
353 NTTIME nt_expire
, nt_min_age
;
354 uint32 account_policy_temp
;
356 if ((policy
= TALLOC_ZERO_P(mem_ctx
, SAM_UNK_INFO_1
)) == NULL
) {
357 return NT_STATUS_NO_MEMORY
;
360 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN
, &account_policy_temp
)) {
361 return NT_STATUS_ACCESS_DENIED
;
363 min_pass_len
= account_policy_temp
;
365 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY
, &account_policy_temp
)) {
366 return NT_STATUS_ACCESS_DENIED
;
368 pass_hist
= account_policy_temp
;
370 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS
, &account_policy_temp
)) {
371 return NT_STATUS_ACCESS_DENIED
;
373 password_properties
= account_policy_temp
;
375 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE
, &account_policy_temp
)) {
376 return NT_STATUS_ACCESS_DENIED
;
378 u_expire
= account_policy_temp
;
380 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE
, &account_policy_temp
)) {
381 return NT_STATUS_ACCESS_DENIED
;
383 u_min_age
= account_policy_temp
;
385 unix_to_nt_time_abs(&nt_expire
, u_expire
);
386 unix_to_nt_time_abs(&nt_min_age
, u_min_age
);
388 init_unk_info1(policy
, (uint16
)min_pass_len
, (uint16
)pass_hist
,
389 password_properties
, nt_expire
, nt_min_age
);
394 /* get a list of trusted domains */
395 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
403 struct trustdom_info
**domains
;
412 if (!(tmp_ctx
= talloc_init("trusted_domains"))) {
413 return NT_STATUS_NO_MEMORY
;
416 nt_status
= pdb_enum_trusteddoms(tmp_ctx
, num_domains
, &domains
);
417 if (!NT_STATUS_IS_OK(nt_status
)) {
418 TALLOC_FREE(tmp_ctx
);
423 *names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
424 *alt_names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
425 *dom_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
427 if ((*alt_names
== NULL
) || (*names
== NULL
) || (*dom_sids
== NULL
)) {
428 TALLOC_FREE(tmp_ctx
);
429 return NT_STATUS_NO_MEMORY
;
437 for (i
=0; i
<*num_domains
; i
++) {
438 (*alt_names
)[i
] = NULL
;
439 if (!((*names
)[i
] = talloc_strdup((*names
),
440 domains
[i
]->name
))) {
441 TALLOC_FREE(tmp_ctx
);
442 return NT_STATUS_NO_MEMORY
;
444 sid_copy(&(*dom_sids
)[i
], &domains
[i
]->sid
);
447 TALLOC_FREE(tmp_ctx
);
451 /* the rpc backend methods are exposed via this structure */
452 struct winbindd_methods passdb_methods
= {