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_dbg(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
) &&
144 !sid_check_is_in_wellknown_domain(sid
))
146 DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
147 "passdb backend\n", sid_string_dbg(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 struct samr_DomInfo12
*policy
)
343 /* actually we have that */
344 return NT_STATUS_NOT_IMPLEMENTED
;
347 static NTSTATUS
password_policy(struct winbindd_domain
*domain
,
349 struct samr_DomInfo1
*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
, struct samr_DomInfo1
)) == 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_samr_DomInfo1(policy
,
389 (uint16
)min_pass_len
,
398 /* get a list of trusted domains */
399 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
407 struct trustdom_info
**domains
;
416 if (!(tmp_ctx
= talloc_init("trusted_domains"))) {
417 return NT_STATUS_NO_MEMORY
;
420 nt_status
= pdb_enum_trusteddoms(tmp_ctx
, num_domains
, &domains
);
421 if (!NT_STATUS_IS_OK(nt_status
)) {
422 TALLOC_FREE(tmp_ctx
);
427 *names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
428 *alt_names
= TALLOC_ARRAY(mem_ctx
, char *, *num_domains
);
429 *dom_sids
= TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
431 if ((*alt_names
== NULL
) || (*names
== NULL
) || (*dom_sids
== NULL
)) {
432 TALLOC_FREE(tmp_ctx
);
433 return NT_STATUS_NO_MEMORY
;
441 for (i
=0; i
<*num_domains
; i
++) {
442 (*alt_names
)[i
] = NULL
;
443 if (!((*names
)[i
] = talloc_strdup((*names
),
444 domains
[i
]->name
))) {
445 TALLOC_FREE(tmp_ctx
);
446 return NT_STATUS_NO_MEMORY
;
448 sid_copy(&(*dom_sids
)[i
], &domains
[i
]->sid
);
451 TALLOC_FREE(tmp_ctx
);
455 /* the rpc backend methods are exposed via this structure */
456 struct winbindd_methods passdb_methods
= {