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