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 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
130 "passdb backend\n", sid_string_static(sid
)));
131 return NT_STATUS_NONE_MAPPED
;
134 if (!lookup_sid(mem_ctx
, sid
, &dom
, &nam
, type
)) {
135 return NT_STATUS_NONE_MAPPED
;
138 *domain_name
= talloc_strdup(mem_ctx
, dom
);
139 *name
= talloc_strdup(mem_ctx
, nam
);
144 static NTSTATUS
rids_to_names(struct winbindd_domain
*domain
,
151 enum lsa_SidType
**types
)
153 return NT_STATUS_UNSUCCESSFUL
;
156 /* Lookup user information from a rid or username. */
157 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
159 const DOM_SID
*user_sid
,
160 WINBIND_USERINFO
*user_info
)
162 return NT_STATUS_NO_SUCH_USER
;
165 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
166 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
168 const DOM_SID
*user_sid
,
169 uint32
*num_groups
, DOM_SID
**user_gids
)
172 DOM_SID
*groups
= NULL
;
177 if ( (user
= samu_new(mem_ctx
)) == NULL
) {
178 return NT_STATUS_NO_MEMORY
;
181 if ( !pdb_getsampwsid( user
, user_sid
) ) {
182 return NT_STATUS_NO_SUCH_USER
;
185 result
= pdb_enum_group_memberships( mem_ctx
, user
, &groups
, &gids
, &ngroups
);
189 *num_groups
= (uint32
)ngroups
;
195 static NTSTATUS
lookup_useraliases(struct winbindd_domain
*domain
,
197 uint32 num_sids
, const DOM_SID
*sids
,
198 uint32
*p_num_aliases
, uint32
**rids
)
201 size_t num_aliases
= 0;
203 result
= pdb_enum_alias_memberships(mem_ctx
, &domain
->sid
,
204 sids
, num_sids
, rids
, &num_aliases
);
206 *p_num_aliases
= num_aliases
;
210 /* Lookup group membership given a rid. */
211 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
213 const DOM_SID
*group_sid
, uint32
*num_names
,
214 DOM_SID
**sid_mem
, char ***names
,
217 size_t i
, num_members
, num_mapped
;
220 const DOM_SID
**sids
;
221 struct lsa_dom_info
*lsa_domains
;
222 struct lsa_name_info
*lsa_names
;
225 if (!sid_check_is_in_our_domain(group_sid
)) {
226 /* There's no groups, only aliases in BUILTIN */
227 return NT_STATUS_NO_SUCH_GROUP
;
230 if (!(tmp_ctx
= talloc_init("lookup_groupmem"))) {
231 return NT_STATUS_NO_MEMORY
;
234 result
= pdb_enum_group_members(tmp_ctx
, group_sid
, &rids
,
236 if (!NT_STATUS_IS_OK(result
)) {
237 TALLOC_FREE(tmp_ctx
);
241 if (num_members
== 0) {
246 TALLOC_FREE(tmp_ctx
);
250 *sid_mem
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, num_members
);
251 *names
= TALLOC_ARRAY(mem_ctx
, char *, num_members
);
252 *name_types
= TALLOC_ARRAY(mem_ctx
, uint32
, num_members
);
253 sids
= TALLOC_ARRAY(tmp_ctx
, const DOM_SID
*, num_members
);
255 if (((*sid_mem
) == NULL
) || ((*names
) == NULL
) ||
256 ((*name_types
) == NULL
) || (sids
== NULL
)) {
257 TALLOC_FREE(tmp_ctx
);
258 return NT_STATUS_NO_MEMORY
;
262 * Prepare an array of sid pointers for the lookup_sids calling
266 for (i
=0; i
<num_members
; i
++) {
267 DOM_SID
*sid
= &((*sid_mem
)[i
]);
268 if (!sid_compose(sid
, &domain
->sid
, rids
[i
])) {
269 TALLOC_FREE(tmp_ctx
);
270 return NT_STATUS_INTERNAL_ERROR
;
275 result
= lookup_sids(tmp_ctx
, num_members
, sids
, 1,
276 &lsa_domains
, &lsa_names
);
277 if (!NT_STATUS_IS_OK(result
)) {
278 TALLOC_FREE(tmp_ctx
);
283 for (i
=0; i
<num_members
; i
++) {
284 if (lsa_names
[i
].type
!= SID_NAME_USER
) {
285 DEBUG(2, ("Got %s as group member -- ignoring\n",
286 sid_type_lookup(lsa_names
[i
].type
)));
289 if (!((*names
)[i
] = talloc_strdup((*names
),
290 lsa_names
[i
].name
))) {
291 TALLOC_FREE(tmp_ctx
);
292 return NT_STATUS_NO_MEMORY
;
295 (*name_types
)[i
] = lsa_names
[i
].type
;
300 *num_names
= num_mapped
;
302 TALLOC_FREE(tmp_ctx
);
306 /* find the sequence number for a domain */
307 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
312 result
= pdb_get_seq_num(&seq_num
);
317 *seq
= (int) seq_num
;
322 static NTSTATUS
lockout_policy(struct winbindd_domain
*domain
,
324 SAM_UNK_INFO_12
*policy
)
326 /* actually we have that */
327 return NT_STATUS_NOT_IMPLEMENTED
;
330 static NTSTATUS
password_policy(struct winbindd_domain
*domain
,
332 SAM_UNK_INFO_1
*policy
)
334 uint32 min_pass_len
,pass_hist
,password_properties
;
335 time_t u_expire
, u_min_age
;
336 NTTIME nt_expire
, nt_min_age
;
337 uint32 account_policy_temp
;
339 if ((policy
= TALLOC_ZERO_P(mem_ctx
, SAM_UNK_INFO_1
)) == NULL
) {
340 return NT_STATUS_NO_MEMORY
;
343 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN
, &account_policy_temp
)) {
344 return NT_STATUS_ACCESS_DENIED
;
346 min_pass_len
= account_policy_temp
;
348 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY
, &account_policy_temp
)) {
349 return NT_STATUS_ACCESS_DENIED
;
351 pass_hist
= account_policy_temp
;
353 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS
, &account_policy_temp
)) {
354 return NT_STATUS_ACCESS_DENIED
;
356 password_properties
= account_policy_temp
;
358 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE
, &account_policy_temp
)) {
359 return NT_STATUS_ACCESS_DENIED
;
361 u_expire
= account_policy_temp
;
363 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE
, &account_policy_temp
)) {
364 return NT_STATUS_ACCESS_DENIED
;
366 u_min_age
= account_policy_temp
;
368 unix_to_nt_time_abs(&nt_expire
, u_expire
);
369 unix_to_nt_time_abs(&nt_min_age
, u_min_age
);
371 init_unk_info1(policy
, (uint16
)min_pass_len
, (uint16
)pass_hist
,
372 password_properties
, nt_expire
, nt_min_age
);
377 /* get a list of trusted domains */
378 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
386 struct trustdom_info
**domains
;
395 if (!(tmp_ctx
= talloc_init("trusted_domains"))) {
396 return NT_STATUS_NO_MEMORY
;
399 nt_status
= secrets_trusted_domains(tmp_ctx
, num_domains
,
401 if (!NT_STATUS_IS_OK(nt_status
)) {
402 TALLOC_FREE(tmp_ctx
);
407 *names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
408 *alt_names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
409 *dom_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
411 if ((*alt_names
== NULL
) || (*names
== NULL
) || (*dom_sids
== NULL
)) {
412 TALLOC_FREE(tmp_ctx
);
413 return NT_STATUS_NO_MEMORY
;
421 for (i
=0; i
<*num_domains
; i
++) {
422 (*alt_names
)[i
] = NULL
;
423 if (!((*names
)[i
] = talloc_strdup((*names
),
424 domains
[i
]->name
))) {
425 TALLOC_FREE(tmp_ctx
);
426 return NT_STATUS_NO_MEMORY
;
428 sid_copy(&(*dom_sids
)[i
], &domains
[i
]->sid
);
431 TALLOC_FREE(tmp_ctx
);
435 /* the rpc backend methods are exposed via this structure */
436 struct winbindd_methods passdb_methods
= {