2 Unix SMB/CIFS implementation.
4 In-Child server implementation of the routines defined in wbint.idl
6 Copyright (C) Volker Lendecke 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "winbindd/winbindd.h"
24 #include "winbindd/winbindd_proto.h"
25 #include "librpc/gen_ndr/srv_wbint.h"
27 void _wbint_Ping(pipes_struct
*p
, struct wbint_Ping
*r
)
29 *r
->out
.out_data
= r
->in
.in_data
;
32 NTSTATUS
_wbint_LookupSid(pipes_struct
*p
, struct wbint_LookupSid
*r
)
34 struct winbindd_domain
*domain
= wb_child_domain();
37 enum lsa_SidType type
;
41 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
44 status
= domain
->methods
->sid_to_name(domain
, p
->mem_ctx
, r
->in
.sid
,
45 &dom_name
, &name
, &type
);
46 if (!NT_STATUS_IS_OK(status
)) {
50 *r
->out
.domain
= dom_name
;
56 NTSTATUS
_wbint_LookupName(pipes_struct
*p
, struct wbint_LookupName
*r
)
58 struct winbindd_domain
*domain
= wb_child_domain();
61 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
64 return domain
->methods
->name_to_sid(
65 domain
, p
->mem_ctx
, r
->in
.domain
, r
->in
.name
, r
->in
.flags
,
66 r
->out
.sid
, r
->out
.type
);
69 NTSTATUS
_wbint_Sid2Uid(pipes_struct
*p
, struct wbint_Sid2Uid
*r
)
74 status
= idmap_sid_to_uid(r
->in
.dom_name
? r
->in
.dom_name
: "",
76 if (!NT_STATUS_IS_OK(status
)) {
83 NTSTATUS
_wbint_Sid2Gid(pipes_struct
*p
, struct wbint_Sid2Gid
*r
)
88 status
= idmap_sid_to_gid(r
->in
.dom_name
? r
->in
.dom_name
: "",
90 if (!NT_STATUS_IS_OK(status
)) {
97 NTSTATUS
_wbint_Uid2Sid(pipes_struct
*p
, struct wbint_Uid2Sid
*r
)
99 return idmap_uid_to_sid(r
->in
.dom_name
? r
->in
.dom_name
: "",
100 r
->out
.sid
, r
->in
.uid
);
103 NTSTATUS
_wbint_Gid2Sid(pipes_struct
*p
, struct wbint_Gid2Sid
*r
)
105 return idmap_gid_to_sid(r
->in
.dom_name
? r
->in
.dom_name
: "",
106 r
->out
.sid
, r
->in
.gid
);
109 NTSTATUS
_wbint_AllocateUid(pipes_struct
*p
, struct wbint_AllocateUid
*r
)
114 status
= idmap_allocate_uid(&xid
);
115 if (!NT_STATUS_IS_OK(status
)) {
118 *r
->out
.uid
= xid
.id
;
122 NTSTATUS
_wbint_AllocateGid(pipes_struct
*p
, struct wbint_AllocateGid
*r
)
127 status
= idmap_allocate_gid(&xid
);
128 if (!NT_STATUS_IS_OK(status
)) {
131 *r
->out
.gid
= xid
.id
;
135 NTSTATUS
_wbint_QueryUser(pipes_struct
*p
, struct wbint_QueryUser
*r
)
137 struct winbindd_domain
*domain
= wb_child_domain();
139 if (domain
== NULL
) {
140 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
143 return domain
->methods
->query_user(domain
, p
->mem_ctx
, r
->in
.sid
,
147 NTSTATUS
_wbint_LookupUserAliases(pipes_struct
*p
,
148 struct wbint_LookupUserAliases
*r
)
150 struct winbindd_domain
*domain
= wb_child_domain();
152 if (domain
== NULL
) {
153 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
156 return domain
->methods
->lookup_useraliases(
157 domain
, p
->mem_ctx
, r
->in
.sids
->num_sids
, r
->in
.sids
->sids
,
158 &r
->out
.rids
->num_rids
, &r
->out
.rids
->rids
);
161 NTSTATUS
_wbint_LookupUserGroups(pipes_struct
*p
,
162 struct wbint_LookupUserGroups
*r
)
164 struct winbindd_domain
*domain
= wb_child_domain();
166 if (domain
== NULL
) {
167 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
170 return domain
->methods
->lookup_usergroups(
171 domain
, p
->mem_ctx
, r
->in
.sid
,
172 &r
->out
.sids
->num_sids
, &r
->out
.sids
->sids
);
175 NTSTATUS
_wbint_QuerySequenceNumber(pipes_struct
*p
,
176 struct wbint_QuerySequenceNumber
*r
)
178 struct winbindd_domain
*domain
= wb_child_domain();
180 if (domain
== NULL
) {
181 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
184 return domain
->methods
->sequence_number(domain
, r
->out
.sequence
);
187 NTSTATUS
_wbint_LookupGroupMembers(pipes_struct
*p
,
188 struct wbint_LookupGroupMembers
*r
)
190 struct winbindd_domain
*domain
= wb_child_domain();
191 uint32_t i
, num_names
;
192 struct dom_sid
*sid_mem
;
194 uint32_t *name_types
;
197 if (domain
== NULL
) {
198 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
201 status
= domain
->methods
->lookup_groupmem(
202 domain
, p
->mem_ctx
, r
->in
.sid
, r
->in
.type
,
203 &num_names
, &sid_mem
, &names
, &name_types
);
204 if (!NT_STATUS_IS_OK(status
)) {
208 r
->out
.members
->num_principals
= num_names
;
209 r
->out
.members
->principals
= talloc_array(
210 r
->out
.members
, struct wbint_Principal
, num_names
);
211 if (r
->out
.members
->principals
== NULL
) {
212 return NT_STATUS_NO_MEMORY
;
215 for (i
=0; i
<num_names
; i
++) {
216 struct wbint_Principal
*m
= &r
->out
.members
->principals
[i
];
217 sid_copy(&m
->sid
, &sid_mem
[i
]);
218 m
->name
= talloc_move(r
->out
.members
->principals
, &names
[i
]);
219 m
->type
= (enum lsa_SidType
)name_types
[i
];
225 NTSTATUS
_wbint_QueryUserList(pipes_struct
*p
, struct wbint_QueryUserList
*r
)
227 struct winbindd_domain
*domain
= wb_child_domain();
229 if (domain
== NULL
) {
230 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
233 return domain
->methods
->query_user_list(
234 domain
, p
->mem_ctx
, &r
->out
.users
->num_userinfos
,
235 &r
->out
.users
->userinfos
);
238 NTSTATUS
_wbint_QueryGroupList(pipes_struct
*p
, struct wbint_QueryGroupList
*r
)
240 struct winbindd_domain
*domain
= wb_child_domain();
241 uint32_t i
, num_groups
;
242 struct acct_info
*groups
;
243 struct wbint_Principal
*result
;
246 if (domain
== NULL
) {
247 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
250 status
= domain
->methods
->enum_dom_groups(domain
, talloc_tos(),
251 &num_groups
, &groups
);
252 if (!NT_STATUS_IS_OK(status
)) {
256 result
= talloc_array(r
->out
.groups
, struct wbint_Principal
,
258 if (result
== NULL
) {
259 return NT_STATUS_NO_MEMORY
;
262 for (i
=0; i
<num_groups
; i
++) {
263 sid_compose(&result
[i
].sid
, &domain
->sid
, groups
[i
].rid
);
264 result
[i
].type
= SID_NAME_DOM_GRP
;
265 result
[i
].name
= talloc_strdup(result
, groups
[i
].acct_name
);
266 if (result
[i
].name
== NULL
) {
269 return NT_STATUS_NO_MEMORY
;
273 r
->out
.groups
->num_principals
= num_groups
;
274 r
->out
.groups
->principals
= result
;
278 NTSTATUS
_wbint_DsGetDcName(pipes_struct
*p
, struct wbint_DsGetDcName
*r
)
280 struct winbindd_domain
*domain
= wb_child_domain();
281 struct rpc_pipe_client
*netlogon_pipe
;
282 struct netr_DsRGetDCNameInfo
*dc_info
;
285 unsigned int orig_timeout
;
287 if (domain
== NULL
) {
288 return dsgetdcname(p
->mem_ctx
, winbind_messaging_context(),
289 r
->in
.domain_name
, r
->in
.domain_guid
,
290 r
->in
.site_name
? r
->in
.site_name
: "",
295 status
= cm_connect_netlogon(domain
, &netlogon_pipe
);
297 if (!NT_STATUS_IS_OK(status
)) {
298 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
302 /* This call can take a long time - allow the server to time out.
303 35 seconds should do it. */
305 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
307 if (domain
->active_directory
) {
308 status
= rpccli_netr_DsRGetDCName(
309 netlogon_pipe
, p
->mem_ctx
, domain
->dcname
,
310 r
->in
.domain_name
, NULL
, r
->in
.domain_guid
,
311 r
->in
.flags
, r
->out
.dc_info
, &werr
);
312 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(werr
)) {
318 * Fallback to less capable methods
321 dc_info
= talloc_zero(r
->out
.dc_info
, struct netr_DsRGetDCNameInfo
);
322 if (dc_info
== NULL
) {
323 status
= NT_STATUS_NO_MEMORY
;
327 if (r
->in
.flags
& DS_PDC_REQUIRED
) {
328 status
= rpccli_netr_GetDcName(
329 netlogon_pipe
, p
->mem_ctx
, domain
->dcname
,
330 r
->in
.domain_name
, &dc_info
->dc_unc
, &werr
);
332 status
= rpccli_netr_GetAnyDCName(
333 netlogon_pipe
, p
->mem_ctx
, domain
->dcname
,
334 r
->in
.domain_name
, &dc_info
->dc_unc
, &werr
);
337 if (!NT_STATUS_IS_OK(status
)) {
338 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
342 if (!W_ERROR_IS_OK(werr
)) {
343 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
345 status
= werror_to_ntstatus(werr
);
349 *r
->out
.dc_info
= dc_info
;
350 status
= NT_STATUS_OK
;
353 /* And restore our original timeout. */
354 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
359 NTSTATUS
_wbint_LookupRids(pipes_struct
*p
, struct wbint_LookupRids
*r
)
361 struct winbindd_domain
*domain
= wb_child_domain();
364 enum lsa_SidType
*types
;
365 struct wbint_Principal
*result
;
369 if (domain
== NULL
) {
370 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
373 status
= domain
->methods
->rids_to_names(
374 domain
, talloc_tos(), &domain
->sid
, r
->in
.rids
->rids
,
375 r
->in
.rids
->num_rids
, &domain_name
, &names
, &types
);
376 if (!NT_STATUS_IS_OK(status
)) {
380 result
= talloc_array(p
->mem_ctx
, struct wbint_Principal
,
381 r
->in
.rids
->num_rids
);
382 if (result
== NULL
) {
383 return NT_STATUS_NO_MEMORY
;
386 for (i
=0; i
<r
->in
.rids
->num_rids
; i
++) {
387 sid_compose(&result
[i
].sid
, &domain
->sid
, r
->in
.rids
->rids
[i
]);
388 result
[i
].type
= types
[i
];
389 result
[i
].name
= talloc_move(result
, &names
[i
]);
394 r
->out
.names
->num_principals
= r
->in
.rids
->num_rids
;
395 r
->out
.names
->principals
= result
;
399 NTSTATUS
_wbint_CheckMachineAccount(pipes_struct
*p
,
400 struct wbint_CheckMachineAccount
*r
)
402 struct winbindd_domain
*domain
;
407 domain
= wb_child_domain();
408 if (domain
== NULL
) {
409 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
412 invalidate_cm_connection(&domain
->conn
);
415 struct rpc_pipe_client
*netlogon_pipe
;
416 status
= cm_connect_netlogon(domain
, &netlogon_pipe
);
419 /* There is a race condition between fetching the trust account
420 password and the periodic machine password change. So it's
421 possible that the trust account password has been changed on us.
422 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
424 #define MAX_RETRIES 3
426 if ((num_retries
< MAX_RETRIES
)
427 && NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
432 if (!NT_STATUS_IS_OK(status
)) {
433 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
437 /* Pass back result code - zero for success, other values for
438 specific failures. */
440 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(status
) ?
444 DEBUG(NT_STATUS_IS_OK(status
) ? 5 : 2,
445 ("Checking the trust account password returned %s\n",