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