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 /* Query display info for a domain. This returns enough information plus a
31 bit extra to give an overview of domain users for the User Manager
33 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
36 WINBIND_USERINFO
**info
)
38 /* We don't have users */
44 /* list all domain groups */
45 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
48 struct acct_info
**info
)
50 /* We don't have domain groups */
56 /* List all domain groups */
58 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
61 struct acct_info
**info
)
63 struct pdb_search
*search
;
64 struct samr_displayentry
*aliases
;
66 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
68 search
= pdb_search_aliases(&domain
->sid
);
69 if (search
== NULL
) goto done
;
71 *num_entries
= pdb_search_entries(search
, 0, 0xffffffff, &aliases
);
72 if (*num_entries
== 0) goto done
;
74 *info
= TALLOC_ARRAY(mem_ctx
, struct acct_info
, *num_entries
);
76 result
= NT_STATUS_NO_MEMORY
;
80 for (i
=0; i
<*num_entries
; i
++) {
81 fstrcpy((*info
)[i
].acct_name
, aliases
[i
].account_name
);
82 fstrcpy((*info
)[i
].acct_desc
, aliases
[i
].description
);
83 (*info
)[i
].rid
= aliases
[i
].rid
;
86 result
= NT_STATUS_OK
;
88 pdb_search_destroy(search
);
92 /* convert a single name to a sid in a domain */
93 static NTSTATUS
name_to_sid(struct winbindd_domain
*domain
,
95 enum winbindd_cmd original_cmd
,
96 const char *domain_name
,
99 enum lsa_SidType
*type
)
101 uint32 flags
= LOOKUP_NAME_ALL
;
103 switch ( original_cmd
) {
104 case WINBINDD_LOOKUPNAME
:
105 /* This call is ok */
108 /* Avoid any NSS calls in the lookup_name by default */
109 flags
|= LOOKUP_NAME_EXPLICIT
;
110 DEBUG(10,("winbindd_passdb: limiting name_to_sid() to explicit mappings\n"));
114 DEBUG(10, ("Finding name %s\n", name
));
116 if ( !lookup_name( mem_ctx
, name
, flags
, NULL
, NULL
, sid
, type
) ) {
117 return NT_STATUS_NONE_MAPPED
;
124 convert a domain SID to a user or group name
126 static NTSTATUS
sid_to_name(struct winbindd_domain
*domain
,
131 enum lsa_SidType
*type
)
133 const char *dom
, *nam
;
135 DEBUG(10, ("Converting SID %s\n", sid_string_static(sid
)));
138 if (!sid_check_is_in_builtin(sid
) &&
139 !sid_check_is_in_our_domain(sid
) &&
140 !sid_check_is_in_unix_users(sid
) &&
141 !sid_check_is_unix_users(sid
) &&
142 !sid_check_is_in_unix_groups(sid
) &&
143 !sid_check_is_unix_groups(sid
) )
145 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
146 "passdb backend\n", sid_string_static(sid
)));
147 return NT_STATUS_NONE_MAPPED
;
150 if (!lookup_sid(mem_ctx
, sid
, &dom
, &nam
, type
)) {
151 return NT_STATUS_NONE_MAPPED
;
154 *domain_name
= talloc_strdup(mem_ctx
, dom
);
155 *name
= talloc_strdup(mem_ctx
, nam
);
160 static NTSTATUS
rids_to_names(struct winbindd_domain
*domain
,
167 enum lsa_SidType
**types
)
169 return NT_STATUS_UNSUCCESSFUL
;
172 /* Lookup user information from a rid or username. */
173 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
175 const DOM_SID
*user_sid
,
176 WINBIND_USERINFO
*user_info
)
178 return NT_STATUS_NO_SUCH_USER
;
181 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
182 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
184 const DOM_SID
*user_sid
,
185 uint32
*num_groups
, DOM_SID
**user_gids
)
188 DOM_SID
*groups
= NULL
;
193 if ( (user
= samu_new(mem_ctx
)) == NULL
) {
194 return NT_STATUS_NO_MEMORY
;
197 if ( !pdb_getsampwsid( user
, user_sid
) ) {
198 return NT_STATUS_NO_SUCH_USER
;
201 result
= pdb_enum_group_memberships( mem_ctx
, user
, &groups
, &gids
, &ngroups
);
205 *num_groups
= (uint32
)ngroups
;
211 static NTSTATUS
lookup_useraliases(struct winbindd_domain
*domain
,
213 uint32 num_sids
, const DOM_SID
*sids
,
214 uint32
*p_num_aliases
, uint32
**rids
)
217 size_t num_aliases
= 0;
219 result
= pdb_enum_alias_memberships(mem_ctx
, &domain
->sid
,
220 sids
, num_sids
, rids
, &num_aliases
);
222 *p_num_aliases
= num_aliases
;
226 /* Lookup group membership given a rid. */
227 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
229 const DOM_SID
*group_sid
, uint32
*num_names
,
230 DOM_SID
**sid_mem
, char ***names
,
233 size_t i
, num_members
, num_mapped
;
236 const DOM_SID
**sids
;
237 struct lsa_dom_info
*lsa_domains
;
238 struct lsa_name_info
*lsa_names
;
241 if (!sid_check_is_in_our_domain(group_sid
)) {
242 /* There's no groups, only aliases in BUILTIN */
243 return NT_STATUS_NO_SUCH_GROUP
;
246 if (!(tmp_ctx
= talloc_init("lookup_groupmem"))) {
247 return NT_STATUS_NO_MEMORY
;
250 result
= pdb_enum_group_members(tmp_ctx
, group_sid
, &rids
,
252 if (!NT_STATUS_IS_OK(result
)) {
253 TALLOC_FREE(tmp_ctx
);
257 if (num_members
== 0) {
262 TALLOC_FREE(tmp_ctx
);
266 *sid_mem
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, num_members
);
267 *names
= TALLOC_ARRAY(mem_ctx
, char *, num_members
);
268 *name_types
= TALLOC_ARRAY(mem_ctx
, uint32
, num_members
);
269 sids
= TALLOC_ARRAY(tmp_ctx
, const DOM_SID
*, num_members
);
271 if (((*sid_mem
) == NULL
) || ((*names
) == NULL
) ||
272 ((*name_types
) == NULL
) || (sids
== NULL
)) {
273 TALLOC_FREE(tmp_ctx
);
274 return NT_STATUS_NO_MEMORY
;
278 * Prepare an array of sid pointers for the lookup_sids calling
282 for (i
=0; i
<num_members
; i
++) {
283 DOM_SID
*sid
= &((*sid_mem
)[i
]);
284 if (!sid_compose(sid
, &domain
->sid
, rids
[i
])) {
285 TALLOC_FREE(tmp_ctx
);
286 return NT_STATUS_INTERNAL_ERROR
;
291 result
= lookup_sids(tmp_ctx
, num_members
, sids
, 1,
292 &lsa_domains
, &lsa_names
);
293 if (!NT_STATUS_IS_OK(result
)) {
294 TALLOC_FREE(tmp_ctx
);
299 for (i
=0; i
<num_members
; i
++) {
300 if (lsa_names
[i
].type
!= SID_NAME_USER
) {
301 DEBUG(2, ("Got %s as group member -- ignoring\n",
302 sid_type_lookup(lsa_names
[i
].type
)));
305 if (!((*names
)[i
] = talloc_strdup((*names
),
306 lsa_names
[i
].name
))) {
307 TALLOC_FREE(tmp_ctx
);
308 return NT_STATUS_NO_MEMORY
;
311 (*name_types
)[i
] = lsa_names
[i
].type
;
316 *num_names
= num_mapped
;
318 TALLOC_FREE(tmp_ctx
);
322 /* find the sequence number for a domain */
323 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
328 result
= pdb_get_seq_num(&seq_num
);
333 *seq
= (int) seq_num
;
338 static NTSTATUS
lockout_policy(struct winbindd_domain
*domain
,
340 SAM_UNK_INFO_12
*policy
)
342 /* actually we have that */
343 return NT_STATUS_NOT_IMPLEMENTED
;
346 static NTSTATUS
password_policy(struct winbindd_domain
*domain
,
348 SAM_UNK_INFO_1
*policy
)
350 uint32 min_pass_len
,pass_hist
,password_properties
;
351 time_t u_expire
, u_min_age
;
352 NTTIME nt_expire
, nt_min_age
;
353 uint32 account_policy_temp
;
355 if ((policy
= TALLOC_ZERO_P(mem_ctx
, SAM_UNK_INFO_1
)) == NULL
) {
356 return NT_STATUS_NO_MEMORY
;
359 if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN
, &account_policy_temp
)) {
360 return NT_STATUS_ACCESS_DENIED
;
362 min_pass_len
= account_policy_temp
;
364 if (!pdb_get_account_policy(AP_PASSWORD_HISTORY
, &account_policy_temp
)) {
365 return NT_STATUS_ACCESS_DENIED
;
367 pass_hist
= account_policy_temp
;
369 if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS
, &account_policy_temp
)) {
370 return NT_STATUS_ACCESS_DENIED
;
372 password_properties
= account_policy_temp
;
374 if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE
, &account_policy_temp
)) {
375 return NT_STATUS_ACCESS_DENIED
;
377 u_expire
= account_policy_temp
;
379 if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE
, &account_policy_temp
)) {
380 return NT_STATUS_ACCESS_DENIED
;
382 u_min_age
= account_policy_temp
;
384 unix_to_nt_time_abs(&nt_expire
, u_expire
);
385 unix_to_nt_time_abs(&nt_min_age
, u_min_age
);
387 init_unk_info1(policy
, (uint16
)min_pass_len
, (uint16
)pass_hist
,
388 password_properties
, nt_expire
, nt_min_age
);
393 /* get a list of trusted domains */
394 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
402 struct trustdom_info
**domains
;
411 if (!(tmp_ctx
= talloc_init("trusted_domains"))) {
412 return NT_STATUS_NO_MEMORY
;
415 nt_status
= pdb_enum_trusteddoms(tmp_ctx
, num_domains
, &domains
);
416 if (!NT_STATUS_IS_OK(nt_status
)) {
417 TALLOC_FREE(tmp_ctx
);
422 *names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
423 *alt_names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
424 *dom_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
426 if ((*alt_names
== NULL
) || (*names
== NULL
) || (*dom_sids
== NULL
)) {
427 TALLOC_FREE(tmp_ctx
);
428 return NT_STATUS_NO_MEMORY
;
436 for (i
=0; i
<*num_domains
; i
++) {
437 (*alt_names
)[i
] = NULL
;
438 if (!((*names
)[i
] = talloc_strdup((*names
),
439 domains
[i
]->name
))) {
440 TALLOC_FREE(tmp_ctx
);
441 return NT_STATUS_NO_MEMORY
;
443 sid_copy(&(*dom_sids
)[i
], &domains
[i
]->sid
);
446 TALLOC_FREE(tmp_ctx
);
450 /* the rpc backend methods are exposed via this structure */
451 struct winbindd_methods passdb_methods
= {