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 const char *domain_name
,
99 enum lsa_SidType
*type
)
101 DEBUG(10, ("Finding name %s\n", name
));
103 if ( !lookup_name( mem_ctx
, name
, LOOKUP_NAME_ALL
,
104 NULL
, NULL
, sid
, type
) )
106 return NT_STATUS_NONE_MAPPED
;
113 convert a domain SID to a user or group name
115 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
120 enum lsa_SidType
*type
)
122 const char *dom
, *nam
;
124 DEBUG(10, ("Converting SID %s\n", sid_string_static(sid
)));
127 if (!sid_check_is_in_builtin(sid
) &&
128 !sid_check_is_in_our_domain(sid
) &&
129 !sid_check_is_in_unix_users(sid
) &&
130 !sid_check_is_unix_users(sid
) &&
131 !sid_check_is_in_unix_groups(sid
) &&
132 !sid_check_is_unix_groups(sid
) )
134 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
135 "passdb backend\n", sid_string_static(sid
)));
136 return NT_STATUS_NONE_MAPPED
;
139 if (!lookup_sid(mem_ctx
, sid
, &dom
, &nam
, type
)) {
140 return NT_STATUS_NONE_MAPPED
;
143 *domain_name
= talloc_strdup(mem_ctx
, dom
);
144 *name
= talloc_strdup(mem_ctx
, nam
);
149 static NTSTATUS
rids_to_names(struct winbindd_domain
*domain
,
156 enum lsa_SidType
**types
)
158 return NT_STATUS_UNSUCCESSFUL
;
161 /* Lookup user information from a rid or username. */
162 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
164 const DOM_SID
*user_sid
,
165 WINBIND_USERINFO
*user_info
)
167 return NT_STATUS_NO_SUCH_USER
;
170 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
171 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
173 const DOM_SID
*user_sid
,
174 uint32
*num_groups
, DOM_SID
**user_gids
)
177 DOM_SID
*groups
= NULL
;
182 if ( (user
= samu_new(mem_ctx
)) == NULL
) {
183 return NT_STATUS_NO_MEMORY
;
186 if ( !pdb_getsampwsid( user
, user_sid
) ) {
187 return NT_STATUS_NO_SUCH_USER
;
190 result
= pdb_enum_group_memberships( mem_ctx
, user
, &groups
, &gids
, &ngroups
);
194 *num_groups
= (uint32
)ngroups
;
200 static NTSTATUS
lookup_useraliases(struct winbindd_domain
*domain
,
202 uint32 num_sids
, const DOM_SID
*sids
,
203 uint32
*p_num_aliases
, uint32
**rids
)
206 size_t num_aliases
= 0;
208 result
= pdb_enum_alias_memberships(mem_ctx
, &domain
->sid
,
209 sids
, num_sids
, rids
, &num_aliases
);
211 *p_num_aliases
= num_aliases
;
215 /* Lookup group membership given a rid. */
216 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
218 const DOM_SID
*group_sid
, uint32
*num_names
,
219 DOM_SID
**sid_mem
, char ***names
,
222 size_t i
, num_members
, num_mapped
;
225 const DOM_SID
**sids
;
226 struct lsa_dom_info
*lsa_domains
;
227 struct lsa_name_info
*lsa_names
;
230 if (!sid_check_is_in_our_domain(group_sid
)) {
231 /* There's no groups, only aliases in BUILTIN */
232 return NT_STATUS_NO_SUCH_GROUP
;
235 if (!(tmp_ctx
= talloc_init("lookup_groupmem"))) {
236 return NT_STATUS_NO_MEMORY
;
239 result
= pdb_enum_group_members(tmp_ctx
, group_sid
, &rids
,
241 if (!NT_STATUS_IS_OK(result
)) {
242 TALLOC_FREE(tmp_ctx
);
246 if (num_members
== 0) {
251 TALLOC_FREE(tmp_ctx
);
255 *sid_mem
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, num_members
);
256 *names
= TALLOC_ARRAY(mem_ctx
, char *, num_members
);
257 *name_types
= TALLOC_ARRAY(mem_ctx
, uint32
, num_members
);
258 sids
= TALLOC_ARRAY(tmp_ctx
, const DOM_SID
*, num_members
);
260 if (((*sid_mem
) == NULL
) || ((*names
) == NULL
) ||
261 ((*name_types
) == NULL
) || (sids
== NULL
)) {
262 TALLOC_FREE(tmp_ctx
);
263 return NT_STATUS_NO_MEMORY
;
267 * Prepare an array of sid pointers for the lookup_sids calling
271 for (i
=0; i
<num_members
; i
++) {
272 DOM_SID
*sid
= &((*sid_mem
)[i
]);
273 if (!sid_compose(sid
, &domain
->sid
, rids
[i
])) {
274 TALLOC_FREE(tmp_ctx
);
275 return NT_STATUS_INTERNAL_ERROR
;
280 result
= lookup_sids(tmp_ctx
, num_members
, sids
, 1,
281 &lsa_domains
, &lsa_names
);
282 if (!NT_STATUS_IS_OK(result
)) {
283 TALLOC_FREE(tmp_ctx
);
288 for (i
=0; i
<num_members
; i
++) {
289 if (lsa_names
[i
].type
!= SID_NAME_USER
) {
290 DEBUG(2, ("Got %s as group member -- ignoring\n",
291 sid_type_lookup(lsa_names
[i
].type
)));
294 if (!((*names
)[i
] = talloc_strdup((*names
),
295 lsa_names
[i
].name
))) {
296 TALLOC_FREE(tmp_ctx
);
297 return NT_STATUS_NO_MEMORY
;
300 (*name_types
)[i
] = lsa_names
[i
].type
;
305 *num_names
= num_mapped
;
307 TALLOC_FREE(tmp_ctx
);
311 /* find the sequence number for a domain */
312 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
317 result
= pdb_get_seq_num(&seq_num
);
322 *seq
= (int) seq_num
;
327 static NTSTATUS
lockout_policy(struct winbindd_domain
*domain
,
329 SAM_UNK_INFO_12
*policy
)
331 /* actually we have that */
332 return NT_STATUS_NOT_IMPLEMENTED
;
335 static NTSTATUS
password_policy(struct winbindd_domain
*domain
,
337 SAM_UNK_INFO_1
*policy
)
339 uint32 min_pass_len
,pass_hist
,password_properties
;
340 time_t u_expire
, u_min_age
;
341 NTTIME nt_expire
, nt_min_age
;
342 uint32 account_policy_temp
;
344 if ((policy
= TALLOC_ZERO_P(mem_ctx
, SAM_UNK_INFO_1
)) == NULL
) {
345 return NT_STATUS_NO_MEMORY
;
348 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN
, &account_policy_temp
)) {
349 return NT_STATUS_ACCESS_DENIED
;
351 min_pass_len
= account_policy_temp
;
353 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY
, &account_policy_temp
)) {
354 return NT_STATUS_ACCESS_DENIED
;
356 pass_hist
= account_policy_temp
;
358 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS
, &account_policy_temp
)) {
359 return NT_STATUS_ACCESS_DENIED
;
361 password_properties
= account_policy_temp
;
363 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE
, &account_policy_temp
)) {
364 return NT_STATUS_ACCESS_DENIED
;
366 u_expire
= account_policy_temp
;
368 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE
, &account_policy_temp
)) {
369 return NT_STATUS_ACCESS_DENIED
;
371 u_min_age
= account_policy_temp
;
373 unix_to_nt_time_abs(&nt_expire
, u_expire
);
374 unix_to_nt_time_abs(&nt_min_age
, u_min_age
);
376 init_unk_info1(policy
, (uint16
)min_pass_len
, (uint16
)pass_hist
,
377 password_properties
, nt_expire
, nt_min_age
);
382 /* get a list of trusted domains */
383 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
391 struct trustdom_info
**domains
;
400 if (!(tmp_ctx
= talloc_init("trusted_domains"))) {
401 return NT_STATUS_NO_MEMORY
;
404 nt_status
= pdb_enum_trusteddoms(tmp_ctx
, num_domains
, &domains
);
405 if (!NT_STATUS_IS_OK(nt_status
)) {
406 TALLOC_FREE(tmp_ctx
);
411 *names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
412 *alt_names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
413 *dom_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
415 if ((*alt_names
== NULL
) || (*names
== NULL
) || (*dom_sids
== NULL
)) {
416 TALLOC_FREE(tmp_ctx
);
417 return NT_STATUS_NO_MEMORY
;
425 for (i
=0; i
<*num_domains
; i
++) {
426 (*alt_names
)[i
] = NULL
;
427 if (!((*names
)[i
] = talloc_strdup((*names
),
428 domains
[i
]->name
))) {
429 TALLOC_FREE(tmp_ctx
);
430 return NT_STATUS_NO_MEMORY
;
432 sid_copy(&(*dom_sids
)[i
], &domains
[i
]->sid
);
435 TALLOC_FREE(tmp_ctx
);
439 /* the rpc backend methods are exposed via this structure */
440 struct winbindd_methods passdb_methods
= {