smbd: Protect ea-reading on symlinks
[Samba.git] / source3 / winbindd / winbindd_irpc.c
blobf66d797da5ef3ef4da382299b96571334453f852
1 /*
2 Unix SMB/CIFS implementation.
3 async implementation of commands submitted over IRPC
4 Copyright (C) Volker Lendecke 2009
5 Copyright (C) Guenther Deschner 2009
6 Copyright (C) Andrew Bartlett 2014
7 Copyright (C) Andrew Tridgell 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.h"
25 #include "librpc/gen_ndr/ndr_winbind_c.h"
26 #include "source4/lib/messaging/irpc.h"
27 #include "librpc/gen_ndr/ndr_winbind.h"
28 #include "librpc/gen_ndr/ndr_lsa.h"
29 #include "librpc/gen_ndr/ndr_lsa_c.h"
30 #include "libcli/security/dom_sid.h"
31 #include "passdb/lookup_sid.h" /* only for LOOKUP_NAME_NO_NSS flag */
32 #include "librpc/gen_ndr/ndr_irpc.h"
33 #include "librpc/gen_ndr/ndr_netlogon.h"
34 #include "lib/global_contexts.h"
35 #include "lib/param/param.h"
36 #include "messages.h"
38 struct imessaging_context *winbind_imessaging_context(void)
40 static struct imessaging_context *msg = NULL;
41 struct messaging_context *msg_ctx;
42 struct server_id myself;
43 struct loadparm_context *lp_ctx;
45 if (msg != NULL) {
46 return msg;
49 msg_ctx = global_messaging_context();
50 if (msg_ctx == NULL) {
51 smb_panic("global_messaging_context failed\n");
53 myself = messaging_server_id(msg_ctx);
55 lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
56 if (lp_ctx == NULL) {
57 smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
61 * Note we MUST use the NULL context here, not the autofree context,
62 * to avoid side effects in forked children exiting.
64 msg = imessaging_init(NULL, lp_ctx, myself, global_event_context());
65 talloc_unlink(NULL, lp_ctx);
67 if (msg == NULL) {
68 smb_panic("Could not init winbindd's messaging context.\n");
70 return msg;
73 struct wb_irpc_forward_state {
74 struct irpc_message *msg;
75 const char *opname;
76 struct dcesrv_call_state *dce_call;
80 called when the forwarded rpc request is finished
82 static void wb_irpc_forward_callback(struct tevent_req *subreq)
84 struct wb_irpc_forward_state *st =
85 tevent_req_callback_data(subreq,
86 struct wb_irpc_forward_state);
87 const char *opname = st->opname;
88 NTSTATUS status;
90 status = dcerpc_binding_handle_call_recv(subreq);
91 TALLOC_FREE(subreq);
92 if (!NT_STATUS_IS_OK(status)) {
93 DEBUG(0,("RPC callback failed for %s - %s\n",
94 opname, nt_errstr(status)));
95 irpc_send_reply(st->msg, status);
96 return;
99 irpc_send_reply(st->msg, status);
105 * Forward a RPC call using IRPC to another task
108 static NTSTATUS wb_irpc_forward_rpc_call(struct irpc_message *msg, TALLOC_CTX *mem_ctx,
109 struct tevent_context *ev,
110 void *r, uint32_t callid,
111 const char *opname,
112 struct winbindd_domain *domain,
113 uint32_t timeout)
115 struct wb_irpc_forward_state *st;
116 struct dcerpc_binding_handle *binding_handle;
117 struct tevent_req *subreq;
119 st = talloc(mem_ctx, struct wb_irpc_forward_state);
120 if (st == NULL) {
121 return NT_STATUS_NO_MEMORY;
124 st->msg = msg;
125 st->opname = opname;
127 binding_handle = dom_child_handle(domain);
128 if (binding_handle == NULL) {
129 DEBUG(0,("%s: Failed to forward request to winbind handler for %s\n",
130 opname, domain->name));
131 return NT_STATUS_UNSUCCESSFUL;
134 /* reset timeout for the handle */
135 dcerpc_binding_handle_set_timeout(binding_handle, timeout);
137 /* forward the call */
138 subreq = dcerpc_binding_handle_call_send(st, ev,
139 binding_handle,
140 NULL, &ndr_table_winbind,
141 callid,
142 msg, r);
143 if (subreq == NULL) {
144 DEBUG(0,("%s: Failed to forward request to winbind handler for %s\n",
145 opname, domain->name));
146 return NT_STATUS_UNSUCCESSFUL;
149 /* mark the request as replied async */
150 msg->defer_reply = true;
152 /* setup the callback */
153 tevent_req_set_callback(subreq, wb_irpc_forward_callback, st);
154 return NT_STATUS_OK;
157 static NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *msg,
158 struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
160 struct winbindd_domain *domain = find_our_domain();
161 if (domain == NULL) {
162 return NT_STATUS_NO_SUCH_DOMAIN;
165 DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords called\n"));
167 return wb_irpc_forward_rpc_call(msg, msg,
168 global_event_context(),
169 req, NDR_WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
170 "winbind_DsrUpdateReadOnlyServerDnsRecords",
171 domain, IRPC_CALL_TIMEOUT);
174 static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg,
175 struct winbind_SamLogon *req)
177 struct winbindd_domain *domain;
178 struct netr_IdentityInfo *identity_info;
179 const char *target_domain_name = NULL;
180 const char *account_name = NULL;
183 * Make sure we start with authoritative=true,
184 * it will only set to false if we don't know the
185 * domain.
187 req->out.authoritative = true;
189 switch (req->in.logon_level) {
190 case NetlogonInteractiveInformation:
191 case NetlogonServiceInformation:
192 case NetlogonInteractiveTransitiveInformation:
193 case NetlogonServiceTransitiveInformation:
194 if (req->in.logon.password == NULL) {
195 return NT_STATUS_REQUEST_NOT_ACCEPTED;
197 identity_info = &req->in.logon.password->identity_info;
198 break;
200 case NetlogonNetworkInformation:
201 case NetlogonNetworkTransitiveInformation:
202 if (req->in.logon.network == NULL) {
203 return NT_STATUS_REQUEST_NOT_ACCEPTED;
206 identity_info = &req->in.logon.network->identity_info;
207 break;
209 case NetlogonGenericInformation:
210 if (req->in.logon.generic == NULL) {
211 return NT_STATUS_REQUEST_NOT_ACCEPTED;
214 identity_info = &req->in.logon.generic->identity_info;
215 break;
217 default:
218 return NT_STATUS_REQUEST_NOT_ACCEPTED;
221 target_domain_name = identity_info->domain_name.string;
222 if (target_domain_name == NULL) {
223 target_domain_name = "";
226 account_name = identity_info->account_name.string;
227 if (account_name == NULL) {
228 account_name = "";
231 if (IS_DC && target_domain_name[0] == '\0') {
232 const char *p = NULL;
234 p = strchr_m(account_name, '@');
235 if (p != NULL) {
236 target_domain_name = p + 1;
240 if (IS_DC && target_domain_name[0] == '\0') {
241 DBG_ERR("target_domain[%s] account[%s]\n",
242 target_domain_name, account_name);
243 return NT_STATUS_REQUEST_NOT_ACCEPTED;
246 domain = find_auth_domain(0, target_domain_name);
247 if (domain == NULL) {
248 DBG_INFO("target_domain[%s] for account[%s] not known\n",
249 target_domain_name, account_name);
250 req->out.result = NT_STATUS_NO_SUCH_USER;
251 req->out.authoritative = 0;
252 return NT_STATUS_OK;
255 DEBUG(5, ("wb_irpc_SamLogon called\n"));
257 return wb_irpc_forward_rpc_call(msg, msg,
258 global_event_context(),
259 req, NDR_WINBIND_SAMLOGON,
260 "winbind_SamLogon",
261 domain, IRPC_CALL_TIMEOUT);
264 static NTSTATUS wb_irpc_LogonControl(struct irpc_message *msg,
265 struct winbind_LogonControl *req)
267 TALLOC_CTX *frame = talloc_stackframe();
268 char *domain_name = NULL;
269 struct winbindd_domain *domain = NULL;
271 DEBUG(5, ("wb_irpc_LogonControl called\n"));
273 switch (req->in.function_code) {
274 case NETLOGON_CONTROL_REDISCOVER:
275 case NETLOGON_CONTROL_TC_QUERY:
276 case NETLOGON_CONTROL_CHANGE_PASSWORD:
277 case NETLOGON_CONTROL_TC_VERIFY:
278 if (req->in.data->domain == NULL) {
279 TALLOC_FREE(frame);
280 return NT_STATUS_INVALID_PARAMETER;
283 domain_name = talloc_strdup(frame, req->in.data->domain);
284 if (domain_name == NULL) {
285 req->out.result = WERR_NOT_ENOUGH_MEMORY;
286 TALLOC_FREE(frame);
287 return NT_STATUS_OK;
290 break;
291 default:
292 TALLOC_FREE(frame);
293 return NT_STATUS_NOT_IMPLEMENTED;
296 if (req->in.function_code == NETLOGON_CONTROL_REDISCOVER) {
297 char *p = NULL;
300 * NETLOGON_CONTROL_REDISCOVER
301 * gets an optional \dcname appended to the domain name
303 p = strchr_m(domain_name, '\\');
304 if (p != NULL) {
305 *p = '\0';
309 domain = find_domain_from_name_noinit(domain_name);
310 if (domain == NULL) {
311 req->out.result = WERR_NO_SUCH_DOMAIN;
312 TALLOC_FREE(frame);
313 return NT_STATUS_OK;
316 TALLOC_FREE(frame);
317 return wb_irpc_forward_rpc_call(msg, msg,
318 global_event_context(),
319 req, NDR_WINBIND_LOGONCONTROL,
320 "winbind_LogonControl",
321 domain, 45 /* timeout */);
324 static NTSTATUS wb_irpc_GetForestTrustInformation(struct irpc_message *msg,
325 struct winbind_GetForestTrustInformation *req)
327 struct winbindd_domain *domain = NULL;
329 if (req->in.trusted_domain_name == NULL) {
330 req->out.result = WERR_NO_SUCH_DOMAIN;
331 return NT_STATUS_OK;
334 domain = find_trust_from_name_noinit(req->in.trusted_domain_name);
335 if (domain == NULL) {
336 req->out.result = WERR_NO_SUCH_DOMAIN;
337 return NT_STATUS_OK;
341 * checking for domain->internal and domain->primary
342 * makes sure we only do some work when running as DC.
345 if (domain->internal) {
346 req->out.result = WERR_NO_SUCH_DOMAIN;
347 return NT_STATUS_OK;
350 if (domain->primary) {
351 req->out.result = WERR_NO_SUCH_DOMAIN;
352 return NT_STATUS_OK;
355 DEBUG(5, ("wb_irpc_GetForestTrustInformation called\n"));
357 return wb_irpc_forward_rpc_call(msg, msg,
358 global_event_context(),
359 req, NDR_WINBIND_GETFORESTTRUSTINFORMATION,
360 "winbind_GetForestTrustInformation",
361 domain, 45 /* timeout */);
364 static NTSTATUS wb_irpc_SendToSam(struct irpc_message *msg,
365 struct winbind_SendToSam *req)
367 /* TODO make sure that it is RWDC */
368 struct winbindd_domain *domain = find_our_domain();
369 if (domain == NULL) {
370 return NT_STATUS_NO_SUCH_DOMAIN;
373 DEBUG(5, ("wb_irpc_SendToSam called\n"));
375 return wb_irpc_forward_rpc_call(msg, msg,
376 global_event_context(),
377 req, NDR_WINBIND_SENDTOSAM,
378 "winbind_SendToSam",
379 domain, IRPC_CALL_TIMEOUT);
382 struct wb_irpc_lsa_LookupSids3_state {
383 struct irpc_message *msg;
384 struct lsa_LookupSids3 *req;
387 static void wb_irpc_lsa_LookupSids3_done(struct tevent_req *subreq);
389 static NTSTATUS wb_irpc_lsa_LookupSids3_call(struct irpc_message *msg,
390 struct lsa_LookupSids3 *req)
392 struct wb_irpc_lsa_LookupSids3_state *state = NULL;
393 struct tevent_req *subreq = NULL;
394 struct dom_sid *sids = NULL;
395 uint32_t i;
397 state = talloc_zero(msg, struct wb_irpc_lsa_LookupSids3_state);
398 if (state == NULL) {
399 return NT_STATUS_NO_MEMORY;
402 state->msg = msg;
403 state->req = req;
405 state->req->out.domains = talloc_zero(state->msg,
406 struct lsa_RefDomainList *);
407 if (state->req->out.domains == NULL) {
408 return NT_STATUS_NO_MEMORY;
410 state->req->out.names = talloc_zero(state->msg,
411 struct lsa_TransNameArray2);
412 if (state->req->out.names == NULL) {
413 return NT_STATUS_NO_MEMORY;
415 state->req->out.count = talloc_zero(state->msg, uint32_t);
416 if (state->req->out.count == NULL) {
417 return NT_STATUS_NO_MEMORY;
420 state->req->out.names->names = talloc_zero_array(state->msg,
421 struct lsa_TranslatedName2,
422 req->in.sids->num_sids);
423 if (state->req->out.names->names == NULL) {
424 return NT_STATUS_NO_MEMORY;
427 sids = talloc_zero_array(state, struct dom_sid,
428 req->in.sids->num_sids);
429 if (sids == NULL) {
430 return NT_STATUS_NO_MEMORY;
433 for (i = 0; i < req->in.sids->num_sids; i++) {
434 if (req->in.sids->sids[i].sid == NULL) {
435 return NT_STATUS_REQUEST_NOT_ACCEPTED;
438 sids[i] = *req->in.sids->sids[i].sid;
441 subreq = wb_lookupsids_send(msg,
442 global_event_context(),
443 sids, req->in.sids->num_sids);
444 if (subreq == NULL) {
445 return NT_STATUS_NO_MEMORY;
447 tevent_req_set_callback(subreq, wb_irpc_lsa_LookupSids3_done, state);
448 msg->defer_reply = true;
450 return NT_STATUS_OK;
453 static void wb_irpc_lsa_LookupSids3_done(struct tevent_req *subreq)
455 struct wb_irpc_lsa_LookupSids3_state *state =
456 tevent_req_callback_data(subreq,
457 struct wb_irpc_lsa_LookupSids3_state);
458 struct lsa_RefDomainList *domains = NULL;
459 struct lsa_TransNameArray *names = NULL;
460 NTSTATUS status;
461 uint32_t i;
463 status = wb_lookupsids_recv(subreq, state->msg,
464 &domains, &names);
465 TALLOC_FREE(subreq);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(0,("RPC callback failed for %s - %s\n",
468 __func__, nt_errstr(status)));
469 irpc_send_reply(state->msg, status);
470 return;
473 if (names->count > state->req->in.sids->num_sids) {
474 status = NT_STATUS_INTERNAL_ERROR;
475 DEBUG(0,("RPC callback failed for %s - %s\n",
476 __func__, nt_errstr(status)));
477 irpc_send_reply(state->msg, status);
478 return;
481 *state->req->out.domains = domains;
482 for (i = 0; i < names->count; i++) {
483 struct lsa_TranslatedName2 *n2 =
484 &state->req->out.names->names[i];
486 n2->sid_type = names->names[i].sid_type;
487 n2->name = names->names[i].name;
488 n2->sid_index = names->names[i].sid_index;
489 n2->unknown = 0;
491 if (n2->sid_type != SID_NAME_UNKNOWN) {
492 (*state->req->out.count)++;
495 state->req->out.names->count = names->count;
497 if (*state->req->out.count == 0) {
498 state->req->out.result = NT_STATUS_NONE_MAPPED;
499 } else if (*state->req->out.count != names->count) {
500 state->req->out.result = NT_STATUS_SOME_NOT_MAPPED;
501 } else {
502 state->req->out.result = NT_STATUS_OK;
505 irpc_send_reply(state->msg, NT_STATUS_OK);
506 return;
509 struct wb_irpc_lsa_LookupNames4_name {
510 void *state;
511 uint32_t idx;
512 const char *namespace;
513 const char *domain;
514 char *name;
515 struct dom_sid sid;
516 enum lsa_SidType type;
517 struct dom_sid *authority_sid;
520 struct wb_irpc_lsa_LookupNames4_state {
521 struct irpc_message *msg;
522 struct lsa_LookupNames4 *req;
523 struct wb_irpc_lsa_LookupNames4_name *names;
524 uint32_t num_pending;
525 uint32_t num_domain_sids;
526 struct dom_sid *domain_sids;
529 static void wb_irpc_lsa_LookupNames4_done(struct tevent_req *subreq);
531 static NTSTATUS wb_irpc_lsa_LookupNames4_call(struct irpc_message *msg,
532 struct lsa_LookupNames4 *req)
534 struct wb_irpc_lsa_LookupNames4_state *state = NULL;
535 struct tevent_req *subreq = NULL;
536 uint32_t i;
539 state = talloc_zero(msg, struct wb_irpc_lsa_LookupNames4_state);
540 if (state == NULL) {
541 return NT_STATUS_NO_MEMORY;
544 state->msg = msg;
545 state->req = req;
547 state->req->out.domains = talloc_zero(state->msg,
548 struct lsa_RefDomainList *);
549 if (state->req->out.domains == NULL) {
550 return NT_STATUS_NO_MEMORY;
552 state->req->out.sids = talloc_zero(state->msg,
553 struct lsa_TransSidArray3);
554 if (state->req->out.sids == NULL) {
555 return NT_STATUS_NO_MEMORY;
557 state->req->out.count = talloc_zero(state->msg, uint32_t);
558 if (state->req->out.count == NULL) {
559 return NT_STATUS_NO_MEMORY;
562 state->req->out.sids->sids = talloc_zero_array(state->msg,
563 struct lsa_TranslatedSid3,
564 req->in.num_names);
565 if (state->req->out.sids->sids == NULL) {
566 return NT_STATUS_NO_MEMORY;
569 state->names = talloc_zero_array(state,
570 struct wb_irpc_lsa_LookupNames4_name,
571 req->in.num_names);
572 if (state->names == NULL) {
573 return NT_STATUS_NO_MEMORY;
576 for (i = 0; i < req->in.num_names; i++) {
577 struct wb_irpc_lsa_LookupNames4_name *nstate =
578 &state->names[i];
579 char *p = NULL;
581 if (req->in.names[i].string == NULL) {
582 DBG_ERR("%s: name[%s] NT_STATUS_REQUEST_NOT_ACCEPTED.\n",
583 __location__, req->in.names[i].string);
584 return NT_STATUS_REQUEST_NOT_ACCEPTED;
586 nstate->state = state;
587 nstate->idx = i;
588 nstate->name = talloc_strdup(state->names,
589 req->in.names[i].string);
590 if (nstate->name == NULL) {
591 return NT_STATUS_NO_MEMORY;
593 nstate->type = SID_NAME_UNKNOWN;
595 /* cope with the name being a fully qualified name */
596 p = strchr(nstate->name, '\\');
597 if (p != NULL) {
598 *p = 0;
599 nstate->domain = nstate->name;
600 nstate->namespace = nstate->domain;
601 nstate->name = p+1;
602 } else if ((p = strchr(nstate->name, '@')) != NULL) {
603 /* upn */
604 nstate->domain = "";
605 nstate->namespace = p + 1;
606 } else {
608 * TODO: select the domain based on
609 * req->in.level and req->in.client_revision
611 * For now we don't allow this.
613 DBG_ERR("%s: name[%s] NT_STATUS_REQUEST_NOT_ACCEPTED.\n",
614 __location__, nstate->name);
615 return NT_STATUS_REQUEST_NOT_ACCEPTED;
618 subreq = wb_lookupname_send(msg,
619 global_event_context(),
620 nstate->namespace,
621 nstate->domain,
622 nstate->name,
623 LOOKUP_NAME_NO_NSS);
624 if (subreq == NULL) {
625 return NT_STATUS_NO_MEMORY;
627 tevent_req_set_callback(subreq,
628 wb_irpc_lsa_LookupNames4_done,
629 nstate);
630 state->num_pending++;
633 msg->defer_reply = true;
635 return NT_STATUS_OK;
638 static void wb_irpc_lsa_LookupNames4_domains_done(struct tevent_req *subreq);
640 static void wb_irpc_lsa_LookupNames4_done(struct tevent_req *subreq)
642 struct wb_irpc_lsa_LookupNames4_name *nstate =
643 (struct wb_irpc_lsa_LookupNames4_name *)
644 tevent_req_callback_data_void(subreq);
645 struct wb_irpc_lsa_LookupNames4_state *state =
646 talloc_get_type_abort(nstate->state,
647 struct wb_irpc_lsa_LookupNames4_state);
648 struct dom_sid_buf buf;
649 NTSTATUS status;
651 SMB_ASSERT(state->num_pending > 0);
652 state->num_pending--;
653 status = wb_lookupname_recv(subreq, &nstate->sid, &nstate->type);
654 TALLOC_FREE(subreq);
655 if (!NT_STATUS_IS_OK(status)) {
656 DEBUG(0,("RPC callback failed for %s - %s\n",
657 __func__, nt_errstr(status)));
658 irpc_send_reply(state->msg, status);
659 return;
662 status = dom_sid_split_rid(state, &nstate->sid,
663 &nstate->authority_sid, NULL);
664 if (!NT_STATUS_IS_OK(status)) {
665 DBG_ERR("dom_sid_split_rid(%s) failed - %s\n",
666 dom_sid_str_buf(&nstate->sid, &buf),
667 nt_errstr(status));
668 irpc_send_reply(state->msg, status);
669 return;
672 status = add_sid_to_array_unique(state,
673 nstate->authority_sid,
674 &state->domain_sids,
675 &state->num_domain_sids);
676 if (!NT_STATUS_IS_OK(status)) {
677 DBG_ERR("add_sid_to_array_unique(%s) failed - %s\n",
678 dom_sid_str_buf(nstate->authority_sid, &buf),
679 nt_errstr(status));
680 irpc_send_reply(state->msg, status);
681 return;
684 if (state->num_pending > 0) {
686 * wait for more...
688 return;
692 * Now resolve all domains back to a name
693 * to get a good lsa_RefDomainList
695 subreq = wb_lookupsids_send(state,
696 global_event_context(),
697 state->domain_sids,
698 state->num_domain_sids);
699 if (subreq == NULL) {
700 status = NT_STATUS_NO_MEMORY;
701 DBG_ERR("wb_lookupsids_send - %s\n",
702 nt_errstr(status));
703 irpc_send_reply(state->msg, status);
704 return;
706 tevent_req_set_callback(subreq,
707 wb_irpc_lsa_LookupNames4_domains_done,
708 state);
710 return;
713 static void wb_irpc_lsa_LookupNames4_domains_done(struct tevent_req *subreq)
715 struct wb_irpc_lsa_LookupNames4_state *state =
716 tevent_req_callback_data(subreq,
717 struct wb_irpc_lsa_LookupNames4_state);
718 struct lsa_RefDomainList *domains = NULL;
719 struct lsa_TransNameArray *names = NULL;
720 NTSTATUS status;
721 uint32_t i;
723 status = wb_lookupsids_recv(subreq, state->msg,
724 &domains, &names);
725 TALLOC_FREE(subreq);
726 if (!NT_STATUS_IS_OK(status)) {
727 DEBUG(0,("RPC callback failed for %s - %s\n",
728 __func__, nt_errstr(status)));
729 irpc_send_reply(state->msg, status);
730 return;
733 *state->req->out.domains = domains;
734 for (i = 0; i < state->req->in.num_names; i++) {
735 struct wb_irpc_lsa_LookupNames4_name *nstate =
736 &state->names[i];
737 struct lsa_TranslatedSid3 *s3 =
738 &state->req->out.sids->sids[i];
739 uint32_t di;
741 s3->sid_type = nstate->type;
742 if (s3->sid_type != SID_NAME_UNKNOWN) {
743 s3->sid = &nstate->sid;
744 } else {
745 s3->sid = NULL;
747 s3->sid_index = UINT32_MAX;
748 for (di = 0; di < domains->count; di++) {
749 bool match;
751 if (domains->domains[di].sid == NULL) {
752 continue;
755 match = dom_sid_equal(nstate->authority_sid,
756 domains->domains[di].sid);
757 if (match) {
758 s3->sid_index = di;
759 break;
762 if (s3->sid_type != SID_NAME_UNKNOWN) {
763 (*state->req->out.count)++;
766 state->req->out.sids->count = state->req->in.num_names;
768 if (*state->req->out.count == 0) {
769 state->req->out.result = NT_STATUS_NONE_MAPPED;
770 } else if (*state->req->out.count != state->req->in.num_names) {
771 state->req->out.result = NT_STATUS_SOME_NOT_MAPPED;
772 } else {
773 state->req->out.result = NT_STATUS_OK;
776 irpc_send_reply(state->msg, NT_STATUS_OK);
777 return;
780 struct wb_irpc_GetDCName_state {
781 struct irpc_message *msg;
782 struct wbint_DsGetDcName *req;
785 static void wb_irpc_GetDCName_done(struct tevent_req *subreq);
787 static NTSTATUS wb_irpc_GetDCName(struct irpc_message *msg,
788 struct wbint_DsGetDcName *req)
791 struct tevent_req *subreq = NULL;
792 struct wb_irpc_GetDCName_state *state = NULL;
794 state = talloc_zero(msg, struct wb_irpc_GetDCName_state);
795 if (state == NULL) {
796 return NT_STATUS_NO_MEMORY;
799 state->msg = msg;
800 state->req = req;
802 subreq = wb_dsgetdcname_send(msg,
803 global_event_context(),
804 req->in.domain_name,
805 req->in.domain_guid,
806 req->in.site_name,
807 req->in.flags);
808 if (subreq == NULL) {
809 return NT_STATUS_NO_MEMORY;
812 tevent_req_set_callback(subreq,
813 wb_irpc_GetDCName_done,
814 state);
816 msg->defer_reply = true;
818 return NT_STATUS_OK;
821 static void wb_irpc_GetDCName_done(struct tevent_req *subreq)
823 struct wb_irpc_GetDCName_state *state = tevent_req_callback_data(
824 subreq, struct wb_irpc_GetDCName_state);
825 NTSTATUS status;
827 status = wb_dsgetdcname_recv(subreq, state->msg,
828 state->req->out.dc_info);
829 TALLOC_FREE(subreq);
830 if (!NT_STATUS_IS_OK(status)) {
831 DBG_INFO("RPC callback failed for %s - %s\n", "DSGETDCNAME",
832 nt_errstr(status));
835 state->req->out.result = status;
837 irpc_send_reply(state->msg, NT_STATUS_OK);
840 NTSTATUS wb_irpc_register(void)
842 NTSTATUS status;
844 status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
845 wb_irpc_DsrUpdateReadOnlyServerDnsRecords, NULL);
846 if (!NT_STATUS_IS_OK(status)) {
847 return status;
849 status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_SAMLOGON,
850 wb_irpc_SamLogon, NULL);
851 if (!NT_STATUS_IS_OK(status)) {
852 return status;
854 status = IRPC_REGISTER(winbind_imessaging_context(), winbind,
855 WINBIND_LOGONCONTROL,
856 wb_irpc_LogonControl, NULL);
857 if (!NT_STATUS_IS_OK(status)) {
858 return status;
860 status = IRPC_REGISTER(winbind_imessaging_context(), winbind,
861 WINBIND_GETFORESTTRUSTINFORMATION,
862 wb_irpc_GetForestTrustInformation, NULL);
863 if (!NT_STATUS_IS_OK(status)) {
864 return status;
866 status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_SENDTOSAM,
867 wb_irpc_SendToSam, NULL);
868 if (!NT_STATUS_IS_OK(status)) {
869 return status;
871 status = IRPC_REGISTER(winbind_imessaging_context(),
872 lsarpc, LSA_LOOKUPSIDS3,
873 wb_irpc_lsa_LookupSids3_call, NULL);
874 if (!NT_STATUS_IS_OK(status)) {
875 return status;
877 status = IRPC_REGISTER(winbind_imessaging_context(),
878 lsarpc, LSA_LOOKUPNAMES4,
879 wb_irpc_lsa_LookupNames4_call, NULL);
880 if (!NT_STATUS_IS_OK(status)) {
881 return status;
883 status = IRPC_REGISTER(winbind_imessaging_context(),
884 winbind, WBINT_DSGETDCNAME,
885 wb_irpc_GetDCName, NULL);
886 if (!NT_STATUS_IS_OK(status)) {
887 return status;
890 return NT_STATUS_OK;