s3-libsmb: finally remove cli_read_old()
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_dual_srv.c
bloba52951e5607a25031f22c896330c0c02e0285d97
1 /*
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/>.
23 #include "includes.h"
24 #include "winbindd/winbindd.h"
25 #include "winbindd/winbindd_proto.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "ntdomain.h"
28 #include "librpc/gen_ndr/srv_wbint.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "idmap.h"
31 #include "../libcli/security/security.h"
33 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
35 *r->out.out_data = r->in.in_data;
38 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
40 struct winbindd_domain *domain = wb_child_domain();
41 char *dom_name;
42 char *name;
43 enum lsa_SidType type;
44 NTSTATUS status;
46 if (domain == NULL) {
47 return NT_STATUS_REQUEST_NOT_ACCEPTED;
50 status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
51 &dom_name, &name, &type);
52 if (!NT_STATUS_IS_OK(status)) {
53 return status;
56 *r->out.domain = dom_name;
57 *r->out.name = name;
58 *r->out.type = type;
59 return NT_STATUS_OK;
62 NTSTATUS _wbint_LookupSids(struct pipes_struct *p, struct wbint_LookupSids *r)
64 struct winbindd_domain *domain = wb_child_domain();
66 if (domain == NULL) {
67 return NT_STATUS_REQUEST_NOT_ACCEPTED;
71 * This breaks the winbindd_domain->methods abstraction: This
72 * is only called for remote domains, and both winbindd_msrpc
73 * and winbindd_ad call into lsa_lookupsids anyway. Caching is
74 * done at the wbint RPC layer.
76 return rpc_lookup_sids(p->mem_ctx, domain, r->in.sids,
77 &r->out.domains, &r->out.names);
80 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
82 struct winbindd_domain *domain = wb_child_domain();
84 if (domain == NULL) {
85 return NT_STATUS_REQUEST_NOT_ACCEPTED;
88 return domain->methods->name_to_sid(
89 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
90 r->out.sid, r->out.type);
93 NTSTATUS _wbint_Sid2Uid(struct pipes_struct *p, struct wbint_Sid2Uid *r)
95 uid_t uid;
96 NTSTATUS status;
98 status = idmap_sid_to_uid(r->in.dom_name ? r->in.dom_name : "",
99 r->in.sid, &uid);
100 if (!NT_STATUS_IS_OK(status)) {
101 return status;
103 *r->out.uid = uid;
104 return NT_STATUS_OK;
107 NTSTATUS _wbint_Sid2Gid(struct pipes_struct *p, struct wbint_Sid2Gid *r)
109 gid_t gid;
110 NTSTATUS status;
112 status = idmap_sid_to_gid(r->in.dom_name ? r->in.dom_name : "",
113 r->in.sid, &gid);
114 if (!NT_STATUS_IS_OK(status)) {
115 return status;
117 *r->out.gid = gid;
118 return NT_STATUS_OK;
121 NTSTATUS _wbint_Sids2UnixIDs(struct pipes_struct *p,
122 struct wbint_Sids2UnixIDs *r)
124 uint32_t i, j;
125 struct id_map *ids = NULL;
126 struct id_map **id_ptrs = NULL;
127 struct dom_sid *sids = NULL;
128 uint32_t *id_idx = NULL;
129 NTSTATUS status = NT_STATUS_NO_MEMORY;
131 for (i=0; i<r->in.domains->count; i++) {
132 struct lsa_DomainInfo *d = &r->in.domains->domains[i];
133 struct idmap_domain *dom;
134 uint32_t num_ids;
136 dom = idmap_find_domain(d->name.string);
137 if (dom == NULL) {
138 DEBUG(10, ("idmap domain %s not found\n",
139 d->name.string));
140 continue;
143 num_ids = 0;
145 for (j=0; j<r->in.ids->num_ids; j++) {
146 if (r->in.ids->ids[j].domain_index == i) {
147 num_ids += 1;
151 ids = talloc_realloc(talloc_tos(), ids,
152 struct id_map, num_ids);
153 if (ids == NULL) {
154 goto nomem;
156 id_ptrs = talloc_realloc(talloc_tos(), id_ptrs,
157 struct id_map *, num_ids+1);
158 if (id_ptrs == NULL) {
159 goto nomem;
161 id_idx = talloc_realloc(talloc_tos(), id_idx,
162 uint32_t, num_ids);
163 if (id_idx == NULL) {
164 goto nomem;
166 sids = talloc_realloc(talloc_tos(), sids,
167 struct dom_sid, num_ids);
168 if (sids == NULL) {
169 goto nomem;
172 num_ids = 0;
174 for (j=0; j<r->in.ids->num_ids; j++) {
175 struct wbint_TransID *id = &r->in.ids->ids[j];
177 if (id->domain_index != i) {
178 continue;
180 id_idx[num_ids] = j;
181 id_ptrs[num_ids] = &ids[num_ids];
183 ids[num_ids].sid = &sids[num_ids];
184 sid_compose(ids[num_ids].sid, d->sid, id->rid);
185 ids[num_ids].xid.type = id->type;
186 ids[num_ids].status = ID_UNKNOWN;
187 num_ids += 1;
189 id_ptrs[num_ids] = NULL;
191 status = dom->methods->sids_to_unixids(dom, id_ptrs);
192 DEBUG(10, ("sids_to_unixids returned %s\n",
193 nt_errstr(status)));
195 for (j=0; j<num_ids; j++) {
196 struct wbint_TransID *id = &r->in.ids->ids[id_idx[j]];
198 if (ids[j].status != ID_MAPPED) {
199 continue;
201 id->unix_id = ids[j].xid.id;
204 status = NT_STATUS_OK;
205 nomem:
206 TALLOC_FREE(ids);
207 TALLOC_FREE(id_ptrs);
208 TALLOC_FREE(id_idx);
209 TALLOC_FREE(sids);
210 return status;
213 NTSTATUS _wbint_Uid2Sid(struct pipes_struct *p, struct wbint_Uid2Sid *r)
215 return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
216 r->out.sid, r->in.uid);
219 NTSTATUS _wbint_Gid2Sid(struct pipes_struct *p, struct wbint_Gid2Sid *r)
221 return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
222 r->out.sid, r->in.gid);
225 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
227 struct unixid xid;
228 NTSTATUS status;
230 status = idmap_allocate_uid(&xid);
231 if (!NT_STATUS_IS_OK(status)) {
232 return status;
234 *r->out.uid = xid.id;
235 return NT_STATUS_OK;
238 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
240 struct unixid xid;
241 NTSTATUS status;
243 status = idmap_allocate_gid(&xid);
244 if (!NT_STATUS_IS_OK(status)) {
245 return status;
247 *r->out.gid = xid.id;
248 return NT_STATUS_OK;
251 NTSTATUS _wbint_QueryUser(struct pipes_struct *p, struct wbint_QueryUser *r)
253 struct winbindd_domain *domain = wb_child_domain();
255 if (domain == NULL) {
256 return NT_STATUS_REQUEST_NOT_ACCEPTED;
259 return domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
260 r->out.info);
263 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
264 struct wbint_LookupUserAliases *r)
266 struct winbindd_domain *domain = wb_child_domain();
268 if (domain == NULL) {
269 return NT_STATUS_REQUEST_NOT_ACCEPTED;
272 return domain->methods->lookup_useraliases(
273 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
274 &r->out.rids->num_rids, &r->out.rids->rids);
277 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
278 struct wbint_LookupUserGroups *r)
280 struct winbindd_domain *domain = wb_child_domain();
282 if (domain == NULL) {
283 return NT_STATUS_REQUEST_NOT_ACCEPTED;
286 return domain->methods->lookup_usergroups(
287 domain, p->mem_ctx, r->in.sid,
288 &r->out.sids->num_sids, &r->out.sids->sids);
291 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
292 struct wbint_QuerySequenceNumber *r)
294 struct winbindd_domain *domain = wb_child_domain();
296 if (domain == NULL) {
297 return NT_STATUS_REQUEST_NOT_ACCEPTED;
300 return domain->methods->sequence_number(domain, r->out.sequence);
303 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
304 struct wbint_LookupGroupMembers *r)
306 struct winbindd_domain *domain = wb_child_domain();
307 uint32_t i, num_names;
308 struct dom_sid *sid_mem;
309 char **names;
310 uint32_t *name_types;
311 NTSTATUS status;
313 if (domain == NULL) {
314 return NT_STATUS_REQUEST_NOT_ACCEPTED;
317 status = domain->methods->lookup_groupmem(
318 domain, p->mem_ctx, r->in.sid, r->in.type,
319 &num_names, &sid_mem, &names, &name_types);
320 if (!NT_STATUS_IS_OK(status)) {
321 return status;
324 r->out.members->num_principals = num_names;
325 r->out.members->principals = talloc_array(
326 r->out.members, struct wbint_Principal, num_names);
327 if (r->out.members->principals == NULL) {
328 return NT_STATUS_NO_MEMORY;
331 for (i=0; i<num_names; i++) {
332 struct wbint_Principal *m = &r->out.members->principals[i];
333 sid_copy(&m->sid, &sid_mem[i]);
334 m->name = talloc_move(r->out.members->principals, &names[i]);
335 m->type = (enum lsa_SidType)name_types[i];
338 return NT_STATUS_OK;
341 NTSTATUS _wbint_QueryUserList(struct pipes_struct *p,
342 struct wbint_QueryUserList *r)
344 struct winbindd_domain *domain = wb_child_domain();
346 if (domain == NULL) {
347 return NT_STATUS_REQUEST_NOT_ACCEPTED;
350 return domain->methods->query_user_list(
351 domain, p->mem_ctx, &r->out.users->num_userinfos,
352 &r->out.users->userinfos);
355 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
356 struct wbint_QueryGroupList *r)
358 struct winbindd_domain *domain = wb_child_domain();
359 uint32_t i, num_groups;
360 struct wb_acct_info *groups;
361 struct wbint_Principal *result;
362 NTSTATUS status;
364 if (domain == NULL) {
365 return NT_STATUS_REQUEST_NOT_ACCEPTED;
368 status = domain->methods->enum_dom_groups(domain, talloc_tos(),
369 &num_groups, &groups);
370 if (!NT_STATUS_IS_OK(status)) {
371 return status;
374 result = talloc_array(r->out.groups, struct wbint_Principal,
375 num_groups);
376 if (result == NULL) {
377 return NT_STATUS_NO_MEMORY;
380 for (i=0; i<num_groups; i++) {
381 sid_compose(&result[i].sid, &domain->sid, groups[i].rid);
382 result[i].type = SID_NAME_DOM_GRP;
383 result[i].name = talloc_strdup(result, groups[i].acct_name);
384 if (result[i].name == NULL) {
385 TALLOC_FREE(result);
386 TALLOC_FREE(groups);
387 return NT_STATUS_NO_MEMORY;
391 r->out.groups->num_principals = num_groups;
392 r->out.groups->principals = result;
394 TALLOC_FREE(groups);
395 return NT_STATUS_OK;
398 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
400 struct winbindd_domain *domain = wb_child_domain();
401 struct rpc_pipe_client *netlogon_pipe;
402 struct netr_DsRGetDCNameInfo *dc_info;
403 NTSTATUS status;
404 WERROR werr;
405 unsigned int orig_timeout;
406 struct dcerpc_binding_handle *b;
408 if (domain == NULL) {
409 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
410 r->in.domain_name, r->in.domain_guid,
411 r->in.site_name ? r->in.site_name : "",
412 r->in.flags,
413 r->out.dc_info);
416 status = cm_connect_netlogon(domain, &netlogon_pipe);
418 if (!NT_STATUS_IS_OK(status)) {
419 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
420 return status;
423 b = netlogon_pipe->binding_handle;
425 /* This call can take a long time - allow the server to time out.
426 35 seconds should do it. */
428 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
430 if (domain->active_directory) {
431 status = dcerpc_netr_DsRGetDCName(b,
432 p->mem_ctx, domain->dcname,
433 r->in.domain_name, NULL, r->in.domain_guid,
434 r->in.flags, r->out.dc_info, &werr);
435 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
436 goto done;
441 * Fallback to less capable methods
444 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
445 if (dc_info == NULL) {
446 status = NT_STATUS_NO_MEMORY;
447 goto done;
450 if (r->in.flags & DS_PDC_REQUIRED) {
451 status = dcerpc_netr_GetDcName(b,
452 p->mem_ctx, domain->dcname,
453 r->in.domain_name, &dc_info->dc_unc, &werr);
454 } else {
455 status = dcerpc_netr_GetAnyDCName(b,
456 p->mem_ctx, domain->dcname,
457 r->in.domain_name, &dc_info->dc_unc, &werr);
460 if (!NT_STATUS_IS_OK(status)) {
461 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
462 nt_errstr(status)));
463 goto done;
465 if (!W_ERROR_IS_OK(werr)) {
466 DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
467 win_errstr(werr)));
468 status = werror_to_ntstatus(werr);
469 goto done;
472 *r->out.dc_info = dc_info;
473 status = NT_STATUS_OK;
475 done:
476 /* And restore our original timeout. */
477 rpccli_set_timeout(netlogon_pipe, orig_timeout);
479 return status;
482 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
484 struct winbindd_domain *domain = wb_child_domain();
485 char *domain_name;
486 char **names;
487 enum lsa_SidType *types;
488 struct wbint_Principal *result;
489 NTSTATUS status;
490 int i;
492 if (domain == NULL) {
493 return NT_STATUS_REQUEST_NOT_ACCEPTED;
496 status = domain->methods->rids_to_names(
497 domain, talloc_tos(), r->in.domain_sid, r->in.rids->rids,
498 r->in.rids->num_rids, &domain_name, &names, &types);
499 if (!NT_STATUS_IS_OK(status)) {
500 return status;
503 *r->out.domain_name = talloc_move(r->out.domain_name, &domain_name);
505 result = talloc_array(p->mem_ctx, struct wbint_Principal,
506 r->in.rids->num_rids);
507 if (result == NULL) {
508 return NT_STATUS_NO_MEMORY;
511 for (i=0; i<r->in.rids->num_rids; i++) {
512 sid_compose(&result[i].sid, r->in.domain_sid,
513 r->in.rids->rids[i]);
514 result[i].type = types[i];
515 result[i].name = talloc_move(result, &names[i]);
517 TALLOC_FREE(types);
518 TALLOC_FREE(names);
520 r->out.names->num_principals = r->in.rids->num_rids;
521 r->out.names->principals = result;
522 return NT_STATUS_OK;
525 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
526 struct wbint_CheckMachineAccount *r)
528 struct winbindd_domain *domain;
529 int num_retries = 0;
530 NTSTATUS status;
532 domain = wb_child_domain();
533 if (domain == NULL) {
534 return NT_STATUS_REQUEST_NOT_ACCEPTED;
537 again:
538 invalidate_cm_connection(&domain->conn);
541 struct rpc_pipe_client *netlogon_pipe;
542 status = cm_connect_netlogon(domain, &netlogon_pipe);
545 /* There is a race condition between fetching the trust account
546 password and the periodic machine password change. So it's
547 possible that the trust account password has been changed on us.
548 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
550 #define MAX_RETRIES 3
552 if ((num_retries < MAX_RETRIES)
553 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
554 num_retries++;
555 goto again;
558 if (!NT_STATUS_IS_OK(status)) {
559 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
560 goto done;
563 /* Pass back result code - zero for success, other values for
564 specific failures. */
566 DEBUG(3,("domain %s secret is %s\n", domain->name,
567 NT_STATUS_IS_OK(status) ? "good" : "bad"));
569 done:
570 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
571 ("Checking the trust account password for domain %s returned %s\n",
572 domain->name, nt_errstr(status)));
574 return status;
577 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
578 struct wbint_ChangeMachineAccount *r)
580 struct winbindd_domain *domain;
581 int num_retries = 0;
582 NTSTATUS status;
583 struct rpc_pipe_client *netlogon_pipe;
584 TALLOC_CTX *tmp_ctx;
586 again:
587 domain = wb_child_domain();
588 if (domain == NULL) {
589 return NT_STATUS_REQUEST_NOT_ACCEPTED;
592 invalidate_cm_connection(&domain->conn);
595 status = cm_connect_netlogon(domain, &netlogon_pipe);
598 /* There is a race condition between fetching the trust account
599 password and the periodic machine password change. So it's
600 possible that the trust account password has been changed on us.
601 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
603 #define MAX_RETRIES 3
605 if ((num_retries < MAX_RETRIES)
606 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
607 num_retries++;
608 goto again;
611 if (!NT_STATUS_IS_OK(status)) {
612 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
613 goto done;
616 tmp_ctx = talloc_new(p->mem_ctx);
618 status = trust_pw_find_change_and_store_it(netlogon_pipe,
619 tmp_ctx,
620 domain->name);
621 talloc_destroy(tmp_ctx);
623 /* Pass back result code - zero for success, other values for
624 specific failures. */
626 DEBUG(3,("domain %s secret %s\n", domain->name,
627 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
629 done:
630 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
631 ("Changing the trust account password for domain %s returned %s\n",
632 domain->name, nt_errstr(status)));
634 return status;
637 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
639 NTSTATUS status;
640 struct winbindd_domain *domain;
641 struct rpc_pipe_client *netlogon_pipe;
642 union netr_CONTROL_QUERY_INFORMATION info;
643 WERROR werr;
644 fstring logon_server;
645 struct dcerpc_binding_handle *b;
647 domain = wb_child_domain();
648 if (domain == NULL) {
649 return NT_STATUS_REQUEST_NOT_ACCEPTED;
652 status = cm_connect_netlogon(domain, &netlogon_pipe);
653 if (!NT_STATUS_IS_OK(status)) {
654 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
655 return status;
658 b = netlogon_pipe->binding_handle;
660 fstr_sprintf(logon_server, "\\\\%s", domain->dcname);
663 * This provokes a WERR_NOT_SUPPORTED error message. This is
664 * documented in the wspp docs. I could not get a successful
665 * call to work, but the main point here is testing that the
666 * netlogon pipe works.
668 status = dcerpc_netr_LogonControl(b, p->mem_ctx,
669 logon_server, NETLOGON_CONTROL_QUERY,
670 2, &info, &werr);
672 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
673 DEBUG(2, ("dcerpc_netr_LogonControl timed out\n"));
674 invalidate_cm_connection(&domain->conn);
675 return status;
678 if (!NT_STATUS_IS_OK(status)) {
679 DEBUG(2, ("dcerpc_netr_LogonControl failed: %s\n",
680 nt_errstr(status)));
681 return status;
684 if (!W_ERROR_EQUAL(werr, WERR_NOT_SUPPORTED)) {
685 DEBUG(2, ("dcerpc_netr_LogonControl returned %s, expected "
686 "WERR_NOT_SUPPORTED\n",
687 win_errstr(werr)));
688 return werror_to_ntstatus(werr);
691 DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
692 return NT_STATUS_OK;