2 Unix SMB/CIFS implementation.
4 In-Child server implementation of the routines defined in wbint.idl
6 Copyright (C) Volker Lendecke 2009
7 Copyright (C) Guenther Deschner 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "winbindd/winbindd.h"
25 #include "winbindd/winbindd_proto.h"
26 #include "librpc/gen_ndr/srv_wbint.h"
28 void _wbint_Ping(pipes_struct *p, struct wbint_Ping *r)
30 *r->out.out_data = r->in.in_data;
33 NTSTATUS _wbint_LookupSid(pipes_struct *p, struct wbint_LookupSid *r)
35 struct winbindd_domain *domain = wb_child_domain();
38 enum lsa_SidType type;
42 return NT_STATUS_REQUEST_NOT_ACCEPTED;
45 status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
46 &dom_name, &name, &type);
47 if (!NT_STATUS_IS_OK(status)) {
51 *r->out.domain = dom_name;
57 NTSTATUS _wbint_LookupName(pipes_struct *p, struct wbint_LookupName *r)
59 struct winbindd_domain *domain = wb_child_domain();
62 return NT_STATUS_REQUEST_NOT_ACCEPTED;
65 return domain->methods->name_to_sid(
66 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
67 r->out.sid, r->out.type);
70 NTSTATUS _wbint_Sid2Uid(pipes_struct *p, struct wbint_Sid2Uid *r)
75 status = idmap_sid_to_uid(r->in.dom_name ? r->in.dom_name : "",
77 if (!NT_STATUS_IS_OK(status)) {
84 NTSTATUS _wbint_Sid2Gid(pipes_struct *p, struct wbint_Sid2Gid *r)
89 status = idmap_sid_to_gid(r->in.dom_name ? r->in.dom_name : "",
91 if (!NT_STATUS_IS_OK(status)) {
98 NTSTATUS _wbint_Uid2Sid(pipes_struct *p, struct wbint_Uid2Sid *r)
100 return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
101 r->out.sid, r->in.uid);
104 NTSTATUS _wbint_Gid2Sid(pipes_struct *p, struct wbint_Gid2Sid *r)
106 return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
107 r->out.sid, r->in.gid);
110 NTSTATUS _wbint_AllocateUid(pipes_struct *p, struct wbint_AllocateUid *r)
115 status = idmap_allocate_uid(&xid);
116 if (!NT_STATUS_IS_OK(status)) {
119 *r->out.uid = xid.id;
123 NTSTATUS _wbint_AllocateGid(pipes_struct *p, struct wbint_AllocateGid *r)
128 status = idmap_allocate_gid(&xid);
129 if (!NT_STATUS_IS_OK(status)) {
132 *r->out.gid = xid.id;
136 NTSTATUS _wbint_QueryUser(pipes_struct *p, struct wbint_QueryUser *r)
138 struct winbindd_domain *domain = wb_child_domain();
140 if (domain == NULL) {
141 return NT_STATUS_REQUEST_NOT_ACCEPTED;
144 return domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
148 NTSTATUS _wbint_LookupUserAliases(pipes_struct *p,
149 struct wbint_LookupUserAliases *r)
151 struct winbindd_domain *domain = wb_child_domain();
153 if (domain == NULL) {
154 return NT_STATUS_REQUEST_NOT_ACCEPTED;
157 return domain->methods->lookup_useraliases(
158 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
159 &r->out.rids->num_rids, &r->out.rids->rids);
162 NTSTATUS _wbint_LookupUserGroups(pipes_struct *p,
163 struct wbint_LookupUserGroups *r)
165 struct winbindd_domain *domain = wb_child_domain();
167 if (domain == NULL) {
168 return NT_STATUS_REQUEST_NOT_ACCEPTED;
171 return domain->methods->lookup_usergroups(
172 domain, p->mem_ctx, r->in.sid,
173 &r->out.sids->num_sids, &r->out.sids->sids);
176 NTSTATUS _wbint_QuerySequenceNumber(pipes_struct *p,
177 struct wbint_QuerySequenceNumber *r)
179 struct winbindd_domain *domain = wb_child_domain();
181 if (domain == NULL) {
182 return NT_STATUS_REQUEST_NOT_ACCEPTED;
185 return domain->methods->sequence_number(domain, r->out.sequence);
188 NTSTATUS _wbint_LookupGroupMembers(pipes_struct *p,
189 struct wbint_LookupGroupMembers *r)
191 struct winbindd_domain *domain = wb_child_domain();
192 uint32_t i, num_names;
193 struct dom_sid *sid_mem;
195 uint32_t *name_types;
198 if (domain == NULL) {
199 return NT_STATUS_REQUEST_NOT_ACCEPTED;
202 status = domain->methods->lookup_groupmem(
203 domain, p->mem_ctx, r->in.sid, r->in.type,
204 &num_names, &sid_mem, &names, &name_types);
205 if (!NT_STATUS_IS_OK(status)) {
209 r->out.members->num_principals = num_names;
210 r->out.members->principals = talloc_array(
211 r->out.members, struct wbint_Principal, num_names);
212 if (r->out.members->principals == NULL) {
213 return NT_STATUS_NO_MEMORY;
216 for (i=0; i<num_names; i++) {
217 struct wbint_Principal *m = &r->out.members->principals[i];
218 sid_copy(&m->sid, &sid_mem[i]);
219 m->name = talloc_move(r->out.members->principals, &names[i]);
220 m->type = (enum lsa_SidType)name_types[i];
226 NTSTATUS _wbint_QueryUserList(pipes_struct *p, struct wbint_QueryUserList *r)
228 struct winbindd_domain *domain = wb_child_domain();
230 if (domain == NULL) {
231 return NT_STATUS_REQUEST_NOT_ACCEPTED;
234 return domain->methods->query_user_list(
235 domain, p->mem_ctx, &r->out.users->num_userinfos,
236 &r->out.users->userinfos);
239 NTSTATUS _wbint_QueryGroupList(pipes_struct *p, struct wbint_QueryGroupList *r)
241 struct winbindd_domain *domain = wb_child_domain();
242 uint32_t i, num_groups;
243 struct acct_info *groups;
244 struct wbint_Principal *result;
247 if (domain == NULL) {
248 return NT_STATUS_REQUEST_NOT_ACCEPTED;
251 status = domain->methods->enum_dom_groups(domain, talloc_tos(),
252 &num_groups, &groups);
253 if (!NT_STATUS_IS_OK(status)) {
257 result = talloc_array(r->out.groups, struct wbint_Principal,
259 if (result == NULL) {
260 return NT_STATUS_NO_MEMORY;
263 for (i=0; i<num_groups; i++) {
264 sid_compose(&result[i].sid, &domain->sid, groups[i].rid);
265 result[i].type = SID_NAME_DOM_GRP;
266 result[i].name = talloc_strdup(result, groups[i].acct_name);
267 if (result[i].name == NULL) {
270 return NT_STATUS_NO_MEMORY;
274 r->out.groups->num_principals = num_groups;
275 r->out.groups->principals = result;
279 NTSTATUS _wbint_DsGetDcName(pipes_struct *p, struct wbint_DsGetDcName *r)
281 struct winbindd_domain *domain = wb_child_domain();
282 struct rpc_pipe_client *netlogon_pipe;
283 struct netr_DsRGetDCNameInfo *dc_info;
286 unsigned int orig_timeout;
288 if (domain == NULL) {
289 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
290 r->in.domain_name, r->in.domain_guid,
291 r->in.site_name ? r->in.site_name : "",
296 status = cm_connect_netlogon(domain, &netlogon_pipe);
298 if (!NT_STATUS_IS_OK(status)) {
299 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
303 /* This call can take a long time - allow the server to time out.
304 35 seconds should do it. */
306 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
308 if (domain->active_directory) {
309 status = rpccli_netr_DsRGetDCName(
310 netlogon_pipe, p->mem_ctx, domain->dcname,
311 r->in.domain_name, NULL, r->in.domain_guid,
312 r->in.flags, r->out.dc_info, &werr);
313 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
319 * Fallback to less capable methods
322 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
323 if (dc_info == NULL) {
324 status = NT_STATUS_NO_MEMORY;
328 if (r->in.flags & DS_PDC_REQUIRED) {
329 status = rpccli_netr_GetDcName(
330 netlogon_pipe, p->mem_ctx, domain->dcname,
331 r->in.domain_name, &dc_info->dc_unc, &werr);
333 status = rpccli_netr_GetAnyDCName(
334 netlogon_pipe, p->mem_ctx, domain->dcname,
335 r->in.domain_name, &dc_info->dc_unc, &werr);
338 if (!NT_STATUS_IS_OK(status)) {
339 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
343 if (!W_ERROR_IS_OK(werr)) {
344 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
346 status = werror_to_ntstatus(werr);
350 *r->out.dc_info = dc_info;
351 status = NT_STATUS_OK;
354 /* And restore our original timeout. */
355 rpccli_set_timeout(netlogon_pipe, orig_timeout);
360 NTSTATUS _wbint_LookupRids(pipes_struct *p, struct wbint_LookupRids *r)
362 struct winbindd_domain *domain = wb_child_domain();
365 enum lsa_SidType *types;
366 struct wbint_Principal *result;
370 if (domain == NULL) {
371 return NT_STATUS_REQUEST_NOT_ACCEPTED;
374 status = domain->methods->rids_to_names(
375 domain, talloc_tos(), &domain->sid, r->in.rids->rids,
376 r->in.rids->num_rids, &domain_name, &names, &types);
377 if (!NT_STATUS_IS_OK(status)) {
381 result = talloc_array(p->mem_ctx, struct wbint_Principal,
382 r->in.rids->num_rids);
383 if (result == NULL) {
384 return NT_STATUS_NO_MEMORY;
387 for (i=0; i<r->in.rids->num_rids; i++) {
388 sid_compose(&result[i].sid, &domain->sid, r->in.rids->rids[i]);
389 result[i].type = types[i];
390 result[i].name = talloc_move(result, &names[i]);
395 r->out.names->num_principals = r->in.rids->num_rids;
396 r->out.names->principals = result;
400 NTSTATUS _wbint_CheckMachineAccount(pipes_struct *p,
401 struct wbint_CheckMachineAccount *r)
403 struct winbindd_domain *domain;
408 domain = wb_child_domain();
409 if (domain == NULL) {
410 return NT_STATUS_REQUEST_NOT_ACCEPTED;
413 invalidate_cm_connection(&domain->conn);
416 struct rpc_pipe_client *netlogon_pipe;
417 status = cm_connect_netlogon(domain, &netlogon_pipe);
420 /* There is a race condition between fetching the trust account
421 password and the periodic machine password change. So it's
422 possible that the trust account password has been changed on us.
423 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
425 #define MAX_RETRIES 3
427 if ((num_retries < MAX_RETRIES)
428 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
433 if (!NT_STATUS_IS_OK(status)) {
434 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
438 /* Pass back result code - zero for success, other values for
439 specific failures. */
441 DEBUG(3,("domain %s secret is %s\n", domain->name,
442 NT_STATUS_IS_OK(status) ? "good" : "bad"));
445 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
446 ("Checking the trust account password for domain %s returned %s\n",
447 domain->name, nt_errstr(status)));
452 NTSTATUS _wbint_ChangeMachineAccount(pipes_struct *p,
453 struct wbint_ChangeMachineAccount *r)
455 struct winbindd_domain *domain;
458 struct rpc_pipe_client *netlogon_pipe;
462 domain = wb_child_domain();
463 if (domain == NULL) {
464 return NT_STATUS_REQUEST_NOT_ACCEPTED;
467 invalidate_cm_connection(&domain->conn);
470 status = cm_connect_netlogon(domain, &netlogon_pipe);
473 /* There is a race condition between fetching the trust account
474 password and the periodic machine password change. So it's
475 possible that the trust account password has been changed on us.
476 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
478 #define MAX_RETRIES 3
480 if ((num_retries < MAX_RETRIES)
481 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
486 if (!NT_STATUS_IS_OK(status)) {
487 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
491 tmp_ctx = talloc_new(p->mem_ctx);
493 status = trust_pw_find_change_and_store_it(netlogon_pipe,
496 talloc_destroy(tmp_ctx);
498 /* Pass back result code - zero for success, other values for
499 specific failures. */
501 DEBUG(3,("domain %s secret %s\n", domain->name,
502 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
505 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
506 ("Changing the trust account password for domain %s returned %s\n",
507 domain->name, nt_errstr(status)));
513 NTSTATUS _wbint_SetMapping(pipes_struct *p, struct wbint_SetMapping *r)
518 map.xid.id = r->in.id;
519 map.status = ID_MAPPED;
521 switch (r->in.type) {
522 case WBINT_ID_TYPE_UID:
523 map.xid.type = ID_TYPE_UID;
525 case WBINT_ID_TYPE_GID:
526 map.xid.type = ID_TYPE_GID;
529 return NT_STATUS_INVALID_PARAMETER;
532 return idmap_set_mapping(&map);
535 NTSTATUS _wbint_RemoveMapping(pipes_struct *p, struct wbint_RemoveMapping *r)
540 map.xid.id = r->in.id;
541 map.status = ID_MAPPED;
543 switch (r->in.type) {
544 case WBINT_ID_TYPE_UID:
545 map.xid.type = ID_TYPE_UID;
547 case WBINT_ID_TYPE_GID:
548 map.xid.type = ID_TYPE_GID;
551 return NT_STATUS_INVALID_PARAMETER;
554 return idmap_remove_mapping(&map);
557 NTSTATUS _wbint_SetHWM(pipes_struct *p, struct wbint_SetHWM *r)
565 case WBINT_ID_TYPE_UID:
566 id.type = ID_TYPE_UID;
567 status = idmap_set_uid_hwm(&id);
570 id.type = ID_TYPE_GID;
571 status = idmap_set_gid_hwm(&id);
574 status = NT_STATUS_INVALID_PARAMETER;