Revert "winbindd: implement winbind_LogonSamLogon"
[metze/samba/wip.git] / source3 / winbindd / winbindd_irpc.c
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
8
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.
13
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.
18
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/>.
21 */
22
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
35 struct wb_irpc_forward_state {
36         struct irpc_message *msg;
37         const char *opname;
38         struct dcesrv_call_state *dce_call;
39 };
40
41 /*
42   called when the forwarded rpc request is finished
43  */
44 static void wb_irpc_forward_callback(struct tevent_req *subreq)
45 {
46         struct wb_irpc_forward_state *st =
47                 tevent_req_callback_data(subreq,
48                 struct wb_irpc_forward_state);
49         const char *opname = st->opname;
50         NTSTATUS status;
51
52         status = dcerpc_binding_handle_call_recv(subreq);
53         TALLOC_FREE(subreq);
54         if (!NT_STATUS_IS_OK(status)) {
55                 DEBUG(0,("RPC callback failed for %s - %s\n",
56                          opname, nt_errstr(status)));
57                 irpc_send_reply(st->msg, status);
58                 return;
59         }
60
61         irpc_send_reply(st->msg, status);
62 }
63
64
65
66 /**
67  * Forward a RPC call using IRPC to another task
68  */
69
70 static NTSTATUS wb_irpc_forward_rpc_call(struct irpc_message *msg, TALLOC_CTX *mem_ctx,
71                                          struct tevent_context *ev,
72                                          void *r, uint32_t callid,
73                                          const char *opname,
74                                          struct winbindd_domain *domain,
75                                          uint32_t timeout)
76 {
77         struct wb_irpc_forward_state *st;
78         struct dcerpc_binding_handle *binding_handle;
79         struct tevent_req *subreq;
80
81         st = talloc(mem_ctx, struct wb_irpc_forward_state);
82         if (st == NULL) {
83                 return NT_STATUS_NO_MEMORY;
84         }
85
86         st->msg = msg;
87         st->opname   = opname;
88
89         binding_handle =  dom_child_handle(domain);
90         if (binding_handle == NULL) {
91                 DEBUG(0,("%s: Failed to forward request to winbind handler for %s\n",
92                          opname, domain->name));
93                 return NT_STATUS_UNSUCCESSFUL;
94         }
95
96         /* reset timeout for the handle */
97         dcerpc_binding_handle_set_timeout(binding_handle, timeout);
98
99         /* forward the call */
100         subreq = dcerpc_binding_handle_call_send(st, ev,
101                                                  binding_handle,
102                                                  NULL, &ndr_table_winbind,
103                                                  callid,
104                                                  msg, r);
105         if (subreq == NULL) {
106                 DEBUG(0,("%s: Failed to forward request to winbind handler for %s\n",
107                          opname, domain->name));
108                 return NT_STATUS_UNSUCCESSFUL;
109         }
110
111         /* mark the request as replied async */
112         msg->defer_reply = true;
113
114         /* setup the callback */
115         tevent_req_set_callback(subreq, wb_irpc_forward_callback, st);
116         return NT_STATUS_OK;
117 }
118
119 static NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *msg,
120                                                    struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
121 {
122         struct winbindd_domain *domain = find_our_domain();
123         if (domain == NULL) {
124                 return NT_STATUS_NO_SUCH_DOMAIN;
125         }
126
127         DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords called\n"));
128
129         return wb_irpc_forward_rpc_call(msg, msg,
130                                         global_event_context(),
131                                         req, NDR_WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
132                                         "winbind_DsrUpdateReadOnlyServerDnsRecords",
133                                         domain, IRPC_CALL_TIMEOUT);
134 }
135
136 static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg,
137                                  struct winbind_SamLogon *req)
138 {
139         struct winbindd_domain *domain;
140         struct netr_IdentityInfo *identity_info;
141         const char *target_domain_name = NULL;
142         const char *account_name = NULL;
143
144         switch (req->in.logon_level) {
145         case NetlogonInteractiveInformation:
146         case NetlogonServiceInformation:
147         case NetlogonInteractiveTransitiveInformation:
148         case NetlogonServiceTransitiveInformation:
149                 if (req->in.logon.password == NULL) {
150                         return NT_STATUS_REQUEST_NOT_ACCEPTED;
151                 }
152                 identity_info = &req->in.logon.password->identity_info;
153                 break;
154
155         case NetlogonNetworkInformation:
156         case NetlogonNetworkTransitiveInformation:
157                 if (req->in.logon.network == NULL) {
158                         return NT_STATUS_REQUEST_NOT_ACCEPTED;
159                 }
160
161                 identity_info = &req->in.logon.network->identity_info;
162                 break;
163
164         case NetlogonGenericInformation:
165                 if (req->in.logon.generic == NULL) {
166                         return NT_STATUS_REQUEST_NOT_ACCEPTED;
167                 }
168
169                 identity_info = &req->in.logon.generic->identity_info;
170                 break;
171
172         default:
173                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
174         }
175
176         target_domain_name = identity_info->domain_name.string;
177         if (target_domain_name == NULL) {
178                 target_domain_name = "";
179         }
180
181         account_name = identity_info->account_name.string;
182         if (account_name == NULL) {
183                 account_name = "";
184         }
185
186         if (IS_DC && target_domain_name[0] == '\0') {
187                 const char *p = NULL;
188
189                 p = strchr_m(account_name, '@');
190                 if (p != NULL) {
191                         target_domain_name = p + 1;
192                 }
193         }
194
195         if (IS_DC && target_domain_name[0] == '\0') {
196                 DBG_ERR("target_domain[%s] account[%s]\n",
197                         target_domain_name, account_name);
198                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
199         }
200
201         domain = find_auth_domain(0, target_domain_name);
202         if (domain == NULL) {
203                 DBG_INFO("target_domain[%s] for account[%s] not known\n",
204                         target_domain_name, account_name);
205                 req->out.result = NT_STATUS_NO_SUCH_USER;
206                 req->out.authoritative = 0;
207                 return NT_STATUS_OK;
208         }
209
210         DEBUG(5, ("wb_irpc_SamLogon called\n"));
211
212         return wb_irpc_forward_rpc_call(msg, msg,
213                                         global_event_context(),
214                                         req, NDR_WINBIND_SAMLOGON,
215                                         "winbind_SamLogon",
216                                         domain, IRPC_CALL_TIMEOUT);
217 }
218
219 static NTSTATUS wb_irpc_LogonControl(struct irpc_message *msg,
220                                      struct winbind_LogonControl *req)
221 {
222         TALLOC_CTX *frame = talloc_stackframe();
223         char *domain_name = NULL;
224         struct winbindd_domain *domain = NULL;
225
226         DEBUG(5, ("wb_irpc_LogonControl called\n"));
227
228         switch (req->in.function_code) {
229         case NETLOGON_CONTROL_REDISCOVER:
230         case NETLOGON_CONTROL_TC_QUERY:
231         case NETLOGON_CONTROL_CHANGE_PASSWORD:
232         case NETLOGON_CONTROL_TC_VERIFY:
233                 if (req->in.data->domain == NULL) {
234                         TALLOC_FREE(frame);
235                         return NT_STATUS_INVALID_PARAMETER;
236                 }
237
238                 domain_name = talloc_strdup(frame, req->in.data->domain);
239                 if (domain_name == NULL) {
240                         req->out.result = WERR_NOT_ENOUGH_MEMORY;
241                         TALLOC_FREE(frame);
242                         return NT_STATUS_OK;
243                 }
244
245                 break;
246         default:
247                 TALLOC_FREE(frame);
248                 return NT_STATUS_NOT_IMPLEMENTED;
249         }
250
251         if (req->in.function_code == NETLOGON_CONTROL_REDISCOVER) {
252                 char *p = NULL;
253
254                 /*
255                  * NETLOGON_CONTROL_REDISCOVER
256                  * get's an optional \dcname appended to the domain name
257                  */
258                 p = strchr_m(domain_name, '\\');
259                 if (p != NULL) {
260                         *p = '\0';
261                 }
262         }
263
264         domain = find_domain_from_name_noinit(domain_name);
265         if (domain == NULL) {
266                 req->out.result = WERR_NO_SUCH_DOMAIN;
267                 TALLOC_FREE(frame);
268                 return NT_STATUS_OK;
269         }
270
271         TALLOC_FREE(frame);
272         return wb_irpc_forward_rpc_call(msg, msg,
273                                         global_event_context(),
274                                         req, NDR_WINBIND_LOGONCONTROL,
275                                         "winbind_LogonControl",
276                                         domain, 45 /* timeout */);
277 }
278
279 static NTSTATUS wb_irpc_GetForestTrustInformation(struct irpc_message *msg,
280                                      struct winbind_GetForestTrustInformation *req)
281 {
282         struct winbindd_domain *domain = NULL;
283
284         if (req->in.trusted_domain_name == NULL) {
285                 req->out.result = WERR_NO_SUCH_DOMAIN;
286                 return NT_STATUS_OK;
287         }
288
289         domain = find_trust_from_name_noinit(req->in.trusted_domain_name);
290         if (domain == NULL) {
291                 req->out.result = WERR_NO_SUCH_DOMAIN;
292                 return NT_STATUS_OK;
293         }
294
295         /*
296          * checking for domain->internal and domain->primary
297          * makes sure we only do some work when running as DC.
298          */
299
300         if (domain->internal) {
301                 req->out.result = WERR_NO_SUCH_DOMAIN;
302                 return NT_STATUS_OK;
303         }
304
305         if (domain->primary) {
306                 req->out.result = WERR_NO_SUCH_DOMAIN;
307                 return NT_STATUS_OK;
308         }
309
310         DEBUG(5, ("wb_irpc_GetForestTrustInformation called\n"));
311
312         return wb_irpc_forward_rpc_call(msg, msg,
313                                         global_event_context(),
314                                         req, NDR_WINBIND_GETFORESTTRUSTINFORMATION,
315                                         "winbind_GetForestTrustInformation",
316                                         domain, 45 /* timeout */);
317 }
318
319 static NTSTATUS wb_irpc_SendToSam(struct irpc_message *msg,
320                                   struct winbind_SendToSam *req)
321 {
322         /* TODO make sure that it is RWDC */
323         struct winbindd_domain *domain = find_our_domain();
324         if (domain == NULL) {
325                 return NT_STATUS_NO_SUCH_DOMAIN;
326         }
327
328         DEBUG(5, ("wb_irpc_SendToSam called\n"));
329
330         return wb_irpc_forward_rpc_call(msg, msg,
331                                         global_event_context(),
332                                         req, NDR_WINBIND_SENDTOSAM,
333                                         "winbind_SendToSam",
334                                         domain, IRPC_CALL_TIMEOUT);
335 }
336
337 struct wb_irpc_lsa_LookupSids3_state {
338         struct irpc_message *msg;
339         struct lsa_LookupSids3 *req;
340 };
341
342 static void wb_irpc_lsa_LookupSids3_done(struct tevent_req *subreq);
343
344 static NTSTATUS wb_irpc_lsa_LookupSids3_call(struct irpc_message *msg,
345                                              struct lsa_LookupSids3 *req)
346 {
347         struct wb_irpc_lsa_LookupSids3_state *state = NULL;
348         struct tevent_req *subreq = NULL;
349         struct dom_sid *sids = NULL;
350         uint32_t i;
351
352         state = talloc_zero(msg, struct wb_irpc_lsa_LookupSids3_state);
353         if (state == NULL) {
354                 return NT_STATUS_NO_MEMORY;
355         }
356
357         state->msg = msg;
358         state->req = req;
359
360         state->req->out.domains = talloc_zero(state->msg,
361                                         struct lsa_RefDomainList *);
362         if (state->req->out.domains == NULL) {
363                 return NT_STATUS_NO_MEMORY;
364         }
365         state->req->out.names = talloc_zero(state->msg,
366                                             struct lsa_TransNameArray2);
367         if (state->req->out.names == NULL) {
368                 return NT_STATUS_NO_MEMORY;
369         }
370         state->req->out.count = talloc_zero(state->msg, uint32_t);
371         if (state->req->out.count == NULL) {
372                 return NT_STATUS_NO_MEMORY;
373         }
374
375         state->req->out.names->names = talloc_zero_array(state->msg,
376                                                 struct lsa_TranslatedName2,
377                                                 req->in.sids->num_sids);
378         if (state->req->out.names->names == NULL) {
379                 return NT_STATUS_NO_MEMORY;
380         }
381
382         sids = talloc_zero_array(state, struct dom_sid,
383                                  req->in.sids->num_sids);
384         if (sids == NULL) {
385                 return NT_STATUS_NO_MEMORY;
386         }
387
388         for (i = 0; i < req->in.sids->num_sids; i++) {
389                 if (req->in.sids->sids[i].sid == NULL) {
390                         return NT_STATUS_REQUEST_NOT_ACCEPTED;
391                 }
392
393                 sids[i] = *req->in.sids->sids[i].sid;
394         }
395
396         subreq = wb_lookupsids_send(msg,
397                                     global_event_context(),
398                                     sids, req->in.sids->num_sids);
399         if (subreq == NULL) {
400                 return NT_STATUS_NO_MEMORY;
401         }
402         tevent_req_set_callback(subreq, wb_irpc_lsa_LookupSids3_done, state);
403         msg->defer_reply = true;
404
405         return NT_STATUS_OK;
406 }
407
408 static void wb_irpc_lsa_LookupSids3_done(struct tevent_req *subreq)
409 {
410         struct wb_irpc_lsa_LookupSids3_state *state =
411                 tevent_req_callback_data(subreq,
412                 struct wb_irpc_lsa_LookupSids3_state);
413         struct lsa_RefDomainList *domains = NULL;
414         struct lsa_TransNameArray *names = NULL;
415         NTSTATUS status;
416         uint32_t i;
417
418         status = wb_lookupsids_recv(subreq, state->msg,
419                                     &domains, &names);
420         TALLOC_FREE(subreq);
421         if (!NT_STATUS_IS_OK(status)) {
422                 DEBUG(0,("RPC callback failed for %s - %s\n",
423                          __func__, nt_errstr(status)));
424                 irpc_send_reply(state->msg, status);
425                 return;
426         }
427
428         if (names->count > state->req->in.sids->num_sids) {
429                 status = NT_STATUS_INTERNAL_ERROR;
430                 DEBUG(0,("RPC callback failed for %s - %s\n",
431                          __func__, nt_errstr(status)));
432                 irpc_send_reply(state->msg, status);
433                 return;
434         }
435
436         *state->req->out.domains = domains;
437         for (i = 0; i < names->count; i++) {
438                 struct lsa_TranslatedName2 *n2 =
439                         &state->req->out.names->names[i];
440
441                 n2->sid_type = names->names[i].sid_type;
442                 n2->name = names->names[i].name;
443                 n2->sid_index = names->names[i].sid_index;
444                 n2->unknown = 0;
445
446                 if (n2->sid_type != SID_NAME_UNKNOWN) {
447                         (*state->req->out.count)++;
448                 }
449         }
450         state->req->out.names->count = names->count;
451
452         if (*state->req->out.count == 0) {
453                 state->req->out.result = NT_STATUS_NONE_MAPPED;
454         } else if (*state->req->out.count != names->count) {
455                 state->req->out.result = NT_STATUS_SOME_NOT_MAPPED;
456         } else {
457                 state->req->out.result = NT_STATUS_OK;
458         }
459
460         irpc_send_reply(state->msg, NT_STATUS_OK);
461         return;
462 }
463
464 struct wb_irpc_lsa_LookupNames4_name {
465         void *state;
466         uint32_t idx;
467         const char *namespace;
468         const char *domain;
469         char *name;
470         struct dom_sid sid;
471         enum lsa_SidType type;
472         struct dom_sid *authority_sid;
473 };
474
475 struct wb_irpc_lsa_LookupNames4_state {
476         struct irpc_message *msg;
477         struct lsa_LookupNames4 *req;
478         struct wb_irpc_lsa_LookupNames4_name *names;
479         uint32_t num_pending;
480         uint32_t num_domain_sids;
481         struct dom_sid *domain_sids;
482 };
483
484 static void wb_irpc_lsa_LookupNames4_done(struct tevent_req *subreq);
485
486 static NTSTATUS wb_irpc_lsa_LookupNames4_call(struct irpc_message *msg,
487                                               struct lsa_LookupNames4 *req)
488 {
489         struct wb_irpc_lsa_LookupNames4_state *state = NULL;
490         struct tevent_req *subreq = NULL;
491         uint32_t i;
492
493
494         state = talloc_zero(msg, struct wb_irpc_lsa_LookupNames4_state);
495         if (state == NULL) {
496                 return NT_STATUS_NO_MEMORY;
497         }
498
499         state->msg = msg;
500         state->req = req;
501
502         state->req->out.domains = talloc_zero(state->msg,
503                                         struct lsa_RefDomainList *);
504         if (state->req->out.domains == NULL) {
505                 return NT_STATUS_NO_MEMORY;
506         }
507         state->req->out.sids = talloc_zero(state->msg,
508                                            struct lsa_TransSidArray3);
509         if (state->req->out.sids == NULL) {
510                 return NT_STATUS_NO_MEMORY;
511         }
512         state->req->out.count = talloc_zero(state->msg, uint32_t);
513         if (state->req->out.count == NULL) {
514                 return NT_STATUS_NO_MEMORY;
515         }
516
517         state->req->out.sids->sids = talloc_zero_array(state->msg,
518                                                 struct lsa_TranslatedSid3,
519                                                 req->in.num_names);
520         if (state->req->out.sids->sids == NULL) {
521                 return NT_STATUS_NO_MEMORY;
522         }
523
524         state->names = talloc_zero_array(state,
525                                          struct wb_irpc_lsa_LookupNames4_name,
526                                          req->in.num_names);
527         if (state->names == NULL) {
528                 return NT_STATUS_NO_MEMORY;
529         }
530
531         for (i = 0; i < req->in.num_names; i++) {
532                 struct wb_irpc_lsa_LookupNames4_name *nstate =
533                         &state->names[i];
534                 char *p = NULL;
535
536                 if (req->in.names[i].string == NULL) {
537                         DBG_ERR("%s: name[%s] NT_STATUS_REQUEST_NOT_ACCEPTED.\n",
538                                 __location__, req->in.names[i].string);
539                         return NT_STATUS_REQUEST_NOT_ACCEPTED;
540                 }
541                 nstate->state = state;
542                 nstate->idx = i;
543                 nstate->name = talloc_strdup(state->names,
544                                              req->in.names[i].string);
545                 if (nstate->name == NULL) {
546                         return NT_STATUS_NO_MEMORY;
547                 }
548                 nstate->type = SID_NAME_UNKNOWN;
549
550                 /* cope with the name being a fully qualified name */
551                 p = strchr(nstate->name, '\\');
552                 if (p != NULL) {
553                         *p = 0;
554                         nstate->domain = nstate->name;
555                         nstate->namespace = nstate->domain;
556                         nstate->name = p+1;
557                 } else if ((p = strchr(nstate->name, '@')) != NULL) {
558                         /* upn */
559                         nstate->domain = "";
560                         nstate->namespace = p + 1;
561                 } else {
562                         /*
563                          * TODO: select the domain based on
564                          * req->in.level and req->in.client_revision
565                          *
566                          * For now we don't allow this.
567                          */
568                         DBG_ERR("%s: name[%s] NT_STATUS_REQUEST_NOT_ACCEPTED.\n",
569                                 __location__, nstate->name);
570                         return NT_STATUS_REQUEST_NOT_ACCEPTED;
571                 }
572
573                 subreq = wb_lookupname_send(msg,
574                                             global_event_context(),
575                                             nstate->namespace,
576                                             nstate->domain,
577                                             nstate->name,
578                                             LOOKUP_NAME_NO_NSS);
579                 if (subreq == NULL) {
580                         return NT_STATUS_NO_MEMORY;
581                 }
582                 tevent_req_set_callback(subreq,
583                                         wb_irpc_lsa_LookupNames4_done,
584                                         nstate);
585                 state->num_pending++;
586         }
587
588         msg->defer_reply = true;
589
590         return NT_STATUS_OK;
591 }
592
593 static void wb_irpc_lsa_LookupNames4_domains_done(struct tevent_req *subreq);
594
595 static void wb_irpc_lsa_LookupNames4_done(struct tevent_req *subreq)
596 {
597         struct wb_irpc_lsa_LookupNames4_name *nstate =
598                 (struct wb_irpc_lsa_LookupNames4_name *)
599                 tevent_req_callback_data_void(subreq);
600         struct wb_irpc_lsa_LookupNames4_state *state =
601                 talloc_get_type_abort(nstate->state,
602                 struct wb_irpc_lsa_LookupNames4_state);
603         struct dom_sid_buf buf;
604         NTSTATUS status;
605
606         SMB_ASSERT(state->num_pending > 0);
607         state->num_pending--;
608         status = wb_lookupname_recv(subreq, &nstate->sid, &nstate->type);
609         TALLOC_FREE(subreq);
610         if (!NT_STATUS_IS_OK(status)) {
611                 DEBUG(0,("RPC callback failed for %s - %s\n",
612                          __func__, nt_errstr(status)));
613                 irpc_send_reply(state->msg, status);
614                 return;
615         }
616
617         status = dom_sid_split_rid(state, &nstate->sid,
618                                    &nstate->authority_sid, NULL);
619         if (!NT_STATUS_IS_OK(status)) {
620                 DBG_ERR("dom_sid_split_rid(%s) failed - %s\n",
621                         dom_sid_str_buf(&nstate->sid, &buf),
622                         nt_errstr(status));
623                 irpc_send_reply(state->msg, status);
624                 return;
625         }
626
627         status = add_sid_to_array_unique(state,
628                                          nstate->authority_sid,
629                                          &state->domain_sids,
630                                          &state->num_domain_sids);
631         if (!NT_STATUS_IS_OK(status)) {
632                 DBG_ERR("add_sid_to_array_unique(%s) failed - %s\n",
633                         dom_sid_str_buf(nstate->authority_sid, &buf),
634                         nt_errstr(status));
635                 irpc_send_reply(state->msg, status);
636                 return;
637         }
638
639         if (state->num_pending > 0) {
640                 /*
641                  * wait for more...
642                  */
643                 return;
644         }
645
646         /*
647          * Now resolve all domains back to a name
648          * to get a good lsa_RefDomainList
649          */
650         subreq = wb_lookupsids_send(state,
651                                     global_event_context(),
652                                     state->domain_sids,
653                                     state->num_domain_sids);
654         if (subreq == NULL) {
655                 status = NT_STATUS_NO_MEMORY;
656                 DBG_ERR("wb_lookupsids_send - %s\n",
657                         nt_errstr(status));
658                 irpc_send_reply(state->msg, status);
659                 return;
660         }
661         tevent_req_set_callback(subreq,
662                                 wb_irpc_lsa_LookupNames4_domains_done,
663                                 state);
664
665         return;
666 }
667
668 static void wb_irpc_lsa_LookupNames4_domains_done(struct tevent_req *subreq)
669 {
670         struct wb_irpc_lsa_LookupNames4_state *state =
671                 tevent_req_callback_data(subreq,
672                 struct wb_irpc_lsa_LookupNames4_state);
673         struct lsa_RefDomainList *domains = NULL;
674         struct lsa_TransNameArray *names = NULL;
675         NTSTATUS status;
676         uint32_t i;
677
678         status = wb_lookupsids_recv(subreq, state->msg,
679                                     &domains, &names);
680         TALLOC_FREE(subreq);
681         if (!NT_STATUS_IS_OK(status)) {
682                 DEBUG(0,("RPC callback failed for %s - %s\n",
683                          __func__, nt_errstr(status)));
684                 irpc_send_reply(state->msg, status);
685                 return;
686         }
687
688         *state->req->out.domains = domains;
689         for (i = 0; i < state->req->in.num_names; i++) {
690                 struct wb_irpc_lsa_LookupNames4_name *nstate =
691                         &state->names[i];
692                 struct lsa_TranslatedSid3 *s3 =
693                         &state->req->out.sids->sids[i];
694                 uint32_t di;
695
696                 s3->sid_type = nstate->type;
697                 if (s3->sid_type != SID_NAME_UNKNOWN) {
698                         s3->sid = &nstate->sid;
699                 } else {
700                         s3->sid = NULL;
701                 }
702                 s3->sid_index = UINT32_MAX;
703                 for (di = 0; di < domains->count; di++) {
704                         bool match;
705
706                         if (domains->domains[di].sid == NULL) {
707                                 continue;
708                         }
709
710                         match = dom_sid_equal(nstate->authority_sid,
711                                               domains->domains[di].sid);
712                         if (match) {
713                                 s3->sid_index = di;
714                                 break;
715                         }
716                 }
717                 if (s3->sid_type != SID_NAME_UNKNOWN) {
718                         (*state->req->out.count)++;
719                 }
720         }
721         state->req->out.sids->count = state->req->in.num_names;
722
723         if (*state->req->out.count == 0) {
724                 state->req->out.result = NT_STATUS_NONE_MAPPED;
725         } else if (*state->req->out.count != state->req->in.num_names) {
726                 state->req->out.result = NT_STATUS_SOME_NOT_MAPPED;
727         } else {
728                 state->req->out.result = NT_STATUS_OK;
729         }
730
731         irpc_send_reply(state->msg, NT_STATUS_OK);
732         return;
733 }
734
735 struct wb_irpc_GetDCName_state {
736         struct irpc_message *msg;
737         struct wbint_DsGetDcName *req;
738 };
739
740 static void wb_irpc_GetDCName_done(struct tevent_req *subreq);
741
742 static NTSTATUS wb_irpc_GetDCName(struct irpc_message *msg,
743                                   struct wbint_DsGetDcName *req)
744 {
745
746         struct tevent_req *subreq = NULL;
747         struct wb_irpc_GetDCName_state *state = NULL;
748
749         state = talloc_zero(msg, struct wb_irpc_GetDCName_state);
750         if (state == NULL) {
751                 return NT_STATUS_NO_MEMORY;
752         }
753
754         state->msg = msg;
755         state->req = req;
756
757         subreq = wb_dsgetdcname_send(msg,
758                                      global_event_context(),
759                                      req->in.domain_name,
760                                      req->in.domain_guid,
761                                      req->in.site_name,
762                                      req->in.flags);
763         if (subreq == NULL) {
764                 return NT_STATUS_NO_MEMORY;
765         }
766
767         tevent_req_set_callback(subreq,
768                                 wb_irpc_GetDCName_done,
769                                 state);
770
771         msg->defer_reply = true;
772
773         return NT_STATUS_OK;
774 }
775
776 static void wb_irpc_GetDCName_done(struct tevent_req *subreq)
777 {
778         struct wb_irpc_GetDCName_state *state = tevent_req_callback_data(
779                 subreq, struct wb_irpc_GetDCName_state);
780         NTSTATUS status;
781
782         status = wb_dsgetdcname_recv(subreq, state->msg,
783                                      state->req->out.dc_info);
784         TALLOC_FREE(subreq);
785         if (!NT_STATUS_IS_OK(status)) {
786                 DBG_INFO("RPC callback failed for %s - %s\n", "DSGETDCNAME",
787                          nt_errstr(status));
788         }
789
790         state->req->out.result = status;
791
792         irpc_send_reply(state->msg, NT_STATUS_OK);
793 }
794
795 NTSTATUS wb_irpc_register(void)
796 {
797         NTSTATUS status;
798
799         status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
800                                wb_irpc_DsrUpdateReadOnlyServerDnsRecords, NULL);
801         if (!NT_STATUS_IS_OK(status)) {
802                 return status;
803         }
804         status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_SAMLOGON,
805                                wb_irpc_SamLogon, NULL);
806         if (!NT_STATUS_IS_OK(status)) {
807                 return status;
808         }
809         status = IRPC_REGISTER(winbind_imessaging_context(), winbind,
810                                WINBIND_LOGONCONTROL,
811                                wb_irpc_LogonControl, NULL);
812         if (!NT_STATUS_IS_OK(status)) {
813                 return status;
814         }
815         status = IRPC_REGISTER(winbind_imessaging_context(), winbind,
816                                WINBIND_GETFORESTTRUSTINFORMATION,
817                                wb_irpc_GetForestTrustInformation, NULL);
818         if (!NT_STATUS_IS_OK(status)) {
819                 return status;
820         }
821         status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_SENDTOSAM,
822                                wb_irpc_SendToSam, NULL);
823         if (!NT_STATUS_IS_OK(status)) {
824                 return status;
825         }
826         status = IRPC_REGISTER(winbind_imessaging_context(),
827                                lsarpc, LSA_LOOKUPSIDS3,
828                                wb_irpc_lsa_LookupSids3_call, NULL);
829         if (!NT_STATUS_IS_OK(status)) {
830                 return status;
831         }
832         status = IRPC_REGISTER(winbind_imessaging_context(),
833                                lsarpc, LSA_LOOKUPNAMES4,
834                                wb_irpc_lsa_LookupNames4_call, NULL);
835         if (!NT_STATUS_IS_OK(status)) {
836                 return status;
837         }
838         status = IRPC_REGISTER(winbind_imessaging_context(),
839                                winbind, WBINT_DSGETDCNAME,
840                                wb_irpc_GetDCName, NULL);
841         if (!NT_STATUS_IS_OK(status)) {
842                 return status;
843         }
844
845         return NT_STATUS_OK;
846 }