Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Winbind rpc backend functions
5 : *
6 : * Copyright (c) 2000-2003 Tim Potter
7 : * Copyright (c) 2001 Andrew Tridgell
8 : * Copyright (c) 2005 Volker Lendecke
9 : * Copyright (c) 2008 Guenther Deschner (pidl conversion)
10 : * Copyright (c) 2010 Andreas Schneider <asn@samba.org>
11 : *
12 : * This program is free software; you can redistribute it and/or modify
13 : * it under the terms of the GNU General Public License as published by
14 : * the Free Software Foundation; either version 3 of the License, or
15 : * (at your option) any later version.
16 : *
17 : * This program is distributed in the hope that it will be useful,
18 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : * GNU General Public License for more details.
21 : *
22 : * You should have received a copy of the GNU General Public License
23 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : */
25 :
26 : #include "includes.h"
27 : #include "winbindd.h"
28 : #include "winbindd_rpc.h"
29 : #include "lib/util_unixsids.h"
30 : #include "rpc_client/rpc_client.h"
31 : #include "rpc_client/cli_pipe.h"
32 : #include "../librpc/gen_ndr/ndr_samr_c.h"
33 : #include "rpc_client/cli_samr.h"
34 : #include "../librpc/gen_ndr/ndr_lsa_c.h"
35 : #include "rpc_client/cli_lsarpc.h"
36 : #include "rpc_server/rpc_ncacn_np.h"
37 : #include "../libcli/security/security.h"
38 : #include "passdb/machine_sid.h"
39 : #include "auth.h"
40 : #include "source3/lib/global_contexts.h"
41 :
42 : #undef DBGC_CLASS
43 : #define DBGC_CLASS DBGC_WINBIND
44 :
45 : /*
46 : * The other end of this won't go away easily, so we can trust it
47 : *
48 : * It is either a long-lived process with the same lifetime as
49 : * winbindd or a part of this process
50 : */
51 : struct winbind_internal_pipes {
52 : struct tevent_timer *shutdown_timer;
53 : struct rpc_pipe_client *samr_pipe;
54 : struct policy_handle samr_domain_hnd;
55 : struct rpc_pipe_client *lsa_pipe;
56 : struct policy_handle lsa_hnd;
57 : };
58 :
59 :
60 0 : NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
61 : struct winbindd_domain *domain,
62 : struct rpc_pipe_client **samr_pipe,
63 : struct policy_handle *samr_domain_hnd)
64 : {
65 0 : NTSTATUS status, result;
66 0 : struct policy_handle samr_connect_hnd;
67 0 : struct dcerpc_binding_handle *b;
68 :
69 0 : status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
70 0 : if (!NT_STATUS_IS_OK(status)) {
71 0 : DBG_ERR("Could not connect to %s pipe: %s\n",
72 : ndr_table_samr.name, nt_errstr(status));
73 0 : return status;
74 : }
75 :
76 0 : b = (*samr_pipe)->binding_handle;
77 :
78 0 : status = dcerpc_samr_Connect2(b, mem_ctx,
79 0 : (*samr_pipe)->desthost,
80 : SEC_FLAG_MAXIMUM_ALLOWED,
81 : &samr_connect_hnd,
82 : &result);
83 0 : if (!NT_STATUS_IS_OK(status)) {
84 0 : return status;
85 : }
86 0 : if (!NT_STATUS_IS_OK(result)) {
87 0 : return result;
88 : }
89 :
90 0 : status = dcerpc_samr_OpenDomain(b, mem_ctx,
91 : &samr_connect_hnd,
92 : SEC_FLAG_MAXIMUM_ALLOWED,
93 : &domain->sid,
94 : samr_domain_hnd,
95 : &result);
96 0 : if (!NT_STATUS_IS_OK(status)) {
97 0 : return status;
98 : }
99 :
100 0 : return result;
101 : }
102 :
103 0 : NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
104 : struct rpc_pipe_client **lsa_pipe,
105 : struct policy_handle *lsa_hnd)
106 : {
107 0 : NTSTATUS status;
108 :
109 0 : status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
110 0 : if (!NT_STATUS_IS_OK(status)) {
111 0 : DBG_ERR("Could not connect to %s pipe: %s\n",
112 : ndr_table_lsarpc.name, nt_errstr(status));
113 0 : return status;
114 : }
115 :
116 0 : status = rpccli_lsa_open_policy((*lsa_pipe),
117 : mem_ctx,
118 : true,
119 : SEC_FLAG_MAXIMUM_ALLOWED,
120 : lsa_hnd);
121 :
122 0 : return status;
123 : }
124 :
125 0 : static void cached_internal_pipe_close(
126 : struct tevent_context *ev,
127 : struct tevent_timer *te,
128 : struct timeval current_time,
129 : void *private_data)
130 : {
131 0 : struct winbindd_domain *domain = talloc_get_type_abort(
132 : private_data, struct winbindd_domain);
133 : /*
134 : * Freeing samr_pipes closes the cached pipes.
135 : *
136 : * We can do a hard close because at the time of this commit
137 : * we only use synchronous calls to external pipes. So we can't
138 : * have any outstanding requests. Also, we don't set
139 : * dcerpc_binding_handle_set_sync_ev in winbind, so we don't
140 : * get nested event loops. Once we start to get async in
141 : * winbind children, we need to check for outstanding calls
142 : */
143 0 : TALLOC_FREE(domain->backend_data.samr_pipes);
144 0 : }
145 :
146 0 : static NTSTATUS open_cached_internal_pipe_conn(
147 : struct winbindd_domain *domain,
148 : struct rpc_pipe_client **samr_pipe,
149 : struct policy_handle *samr_domain_hnd,
150 : struct rpc_pipe_client **lsa_pipe,
151 : struct policy_handle *lsa_hnd)
152 : {
153 0 : struct winbind_internal_pipes *internal_pipes =
154 : domain->backend_data.samr_pipes;
155 :
156 0 : if (internal_pipes == NULL) {
157 0 : TALLOC_CTX *frame = talloc_stackframe();
158 0 : NTSTATUS status;
159 :
160 0 : internal_pipes = talloc_zero(frame,
161 : struct winbind_internal_pipes);
162 :
163 0 : status = open_internal_samr_conn(
164 : internal_pipes,
165 : domain,
166 : &internal_pipes->samr_pipe,
167 : &internal_pipes->samr_domain_hnd);
168 0 : if (!NT_STATUS_IS_OK(status)) {
169 0 : TALLOC_FREE(frame);
170 0 : return status;
171 : }
172 :
173 0 : status = open_internal_lsa_conn(internal_pipes,
174 : &internal_pipes->lsa_pipe,
175 : &internal_pipes->lsa_hnd);
176 :
177 0 : if (!NT_STATUS_IS_OK(status)) {
178 0 : TALLOC_FREE(frame);
179 0 : return status;
180 : }
181 :
182 0 : internal_pipes->shutdown_timer = tevent_add_timer(
183 : global_event_context(),
184 : internal_pipes,
185 : timeval_current_ofs(5, 0),
186 : cached_internal_pipe_close,
187 : domain);
188 0 : if (internal_pipes->shutdown_timer == NULL) {
189 0 : TALLOC_FREE(frame);
190 0 : return NT_STATUS_NO_MEMORY;
191 : }
192 :
193 0 : domain->backend_data.samr_pipes =
194 0 : talloc_steal(domain, internal_pipes);
195 :
196 0 : TALLOC_FREE(frame);
197 : }
198 :
199 0 : if (samr_domain_hnd) {
200 0 : *samr_domain_hnd = internal_pipes->samr_domain_hnd;
201 : }
202 :
203 0 : if (samr_pipe) {
204 0 : *samr_pipe = internal_pipes->samr_pipe;
205 : }
206 :
207 0 : if (lsa_hnd) {
208 0 : *lsa_hnd = internal_pipes->lsa_hnd;
209 : }
210 :
211 0 : if (lsa_pipe) {
212 0 : *lsa_pipe = internal_pipes->lsa_pipe;
213 : }
214 :
215 0 : tevent_update_timer(
216 : internal_pipes->shutdown_timer,
217 : timeval_current_ofs(5, 0));
218 :
219 0 : return NT_STATUS_OK;
220 : }
221 :
222 0 : static bool reset_connection_on_error(struct winbindd_domain *domain,
223 : struct rpc_pipe_client *p,
224 : NTSTATUS status)
225 : {
226 0 : struct dcerpc_binding_handle *b = p->binding_handle;
227 :
228 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
229 0 : NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
230 : {
231 0 : TALLOC_FREE(domain->backend_data.samr_pipes);
232 0 : return true;
233 : }
234 :
235 0 : if (!dcerpc_binding_handle_is_connected(b)) {
236 0 : TALLOC_FREE(domain->backend_data.samr_pipes);
237 0 : return true;
238 : }
239 :
240 0 : return false;
241 : }
242 :
243 : /*********************************************************************
244 : SAM specific functions.
245 : *********************************************************************/
246 :
247 : /* List all domain groups */
248 0 : static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
249 : TALLOC_CTX *mem_ctx,
250 : uint32_t *pnum_info,
251 : struct wb_acct_info **pinfo)
252 : {
253 0 : struct rpc_pipe_client *samr_pipe;
254 0 : struct policy_handle dom_pol = { 0 };
255 0 : struct wb_acct_info *info = NULL;
256 0 : uint32_t num_info = 0;
257 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
258 0 : NTSTATUS status;
259 0 : bool retry = false;
260 :
261 0 : DEBUG(3,("sam_enum_dom_groups\n"));
262 :
263 0 : if (pnum_info) {
264 0 : *pnum_info = 0;
265 : }
266 :
267 0 : again:
268 0 : status = open_cached_internal_pipe_conn(domain,
269 : &samr_pipe,
270 : &dom_pol,
271 : NULL,
272 : NULL);
273 0 : if (!NT_STATUS_IS_OK(status)) {
274 0 : TALLOC_FREE(tmp_ctx);
275 0 : return status;
276 : }
277 :
278 0 : status = rpc_enum_dom_groups(tmp_ctx,
279 : samr_pipe,
280 : &dom_pol,
281 : &num_info,
282 : &info);
283 :
284 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
285 0 : retry = true;
286 0 : goto again;
287 : }
288 :
289 0 : if (!NT_STATUS_IS_OK(status)) {
290 0 : TALLOC_FREE(tmp_ctx);
291 0 : return status;
292 : }
293 :
294 0 : if (pnum_info) {
295 0 : *pnum_info = num_info;
296 : }
297 :
298 0 : if (pinfo) {
299 0 : *pinfo = talloc_move(mem_ctx, &info);
300 : }
301 :
302 0 : TALLOC_FREE(tmp_ctx);
303 0 : return status;
304 : }
305 :
306 : /* Query display info for a domain */
307 0 : static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
308 : TALLOC_CTX *mem_ctx,
309 : uint32_t **prids)
310 : {
311 0 : struct rpc_pipe_client *samr_pipe = NULL;
312 0 : struct policy_handle dom_pol = { 0 };
313 0 : uint32_t *rids = NULL;
314 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
315 0 : NTSTATUS status;
316 0 : bool retry = false;
317 :
318 0 : DEBUG(3,("samr_query_user_list\n"));
319 :
320 0 : again:
321 0 : status = open_cached_internal_pipe_conn(domain,
322 : &samr_pipe,
323 : &dom_pol,
324 : NULL,
325 : NULL);
326 0 : if (!NT_STATUS_IS_OK(status)) {
327 0 : goto done;
328 : }
329 :
330 0 : status = rpc_query_user_list(tmp_ctx,
331 : samr_pipe,
332 : &dom_pol,
333 0 : &domain->sid,
334 : &rids);
335 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
336 0 : retry = true;
337 0 : goto again;
338 : }
339 :
340 0 : if (!NT_STATUS_IS_OK(status)) {
341 0 : goto done;
342 : }
343 :
344 0 : if (prids != NULL) {
345 0 : *prids = talloc_move(mem_ctx, &rids);
346 : }
347 :
348 0 : done:
349 0 : TALLOC_FREE(rids);
350 0 : TALLOC_FREE(tmp_ctx);
351 0 : return status;
352 : }
353 :
354 : /* get a list of trusted domains - builtin domain */
355 0 : static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
356 : TALLOC_CTX *mem_ctx,
357 : struct netr_DomainTrustList *ptrust_list)
358 : {
359 0 : struct rpc_pipe_client *lsa_pipe;
360 0 : struct policy_handle lsa_policy = { 0 };
361 0 : struct netr_DomainTrust *trusts = NULL;
362 0 : uint32_t num_trusts = 0;
363 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
364 0 : NTSTATUS status;
365 0 : bool retry = false;
366 :
367 0 : DEBUG(3,("samr: trusted domains\n"));
368 :
369 0 : if (ptrust_list) {
370 0 : ZERO_STRUCTP(ptrust_list);
371 : }
372 :
373 0 : again:
374 0 : status = open_cached_internal_pipe_conn(domain,
375 : NULL,
376 : NULL,
377 : &lsa_pipe,
378 : &lsa_policy);
379 0 : if (!NT_STATUS_IS_OK(status)) {
380 0 : goto done;
381 : }
382 :
383 0 : status = rpc_trusted_domains(tmp_ctx,
384 : lsa_pipe,
385 : &lsa_policy,
386 : &num_trusts,
387 : &trusts);
388 :
389 0 : if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
390 0 : retry = true;
391 0 : goto again;
392 : }
393 :
394 0 : if (!NT_STATUS_IS_OK(status)) {
395 0 : goto done;
396 : }
397 :
398 0 : if (ptrust_list) {
399 0 : ptrust_list->count = num_trusts;
400 0 : ptrust_list->array = talloc_move(mem_ctx, &trusts);
401 : }
402 :
403 0 : done:
404 0 : TALLOC_FREE(tmp_ctx);
405 0 : return status;
406 : }
407 :
408 : /* Lookup group membership given a rid. */
409 0 : static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
410 : TALLOC_CTX *mem_ctx,
411 : const struct dom_sid *group_sid,
412 : enum lsa_SidType type,
413 : uint32_t *pnum_names,
414 : struct dom_sid **psid_mem,
415 : char ***pnames,
416 : uint32_t **pname_types)
417 : {
418 0 : struct rpc_pipe_client *samr_pipe;
419 0 : struct policy_handle dom_pol = { 0 };
420 :
421 0 : uint32_t num_names = 0;
422 0 : struct dom_sid *sid_mem = NULL;
423 0 : char **names = NULL;
424 0 : uint32_t *name_types = NULL;
425 :
426 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
427 0 : NTSTATUS status;
428 0 : bool retry = false;
429 :
430 0 : DEBUG(3,("sam_lookup_groupmem\n"));
431 :
432 : /* Paranoia check */
433 0 : if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
434 : /* There's no groups, only aliases in BUILTIN */
435 0 : status = NT_STATUS_NO_SUCH_GROUP;
436 0 : goto done;
437 : }
438 :
439 0 : if (pnum_names) {
440 0 : *pnum_names = 0;
441 : }
442 :
443 0 : again:
444 0 : status = open_cached_internal_pipe_conn(domain,
445 : &samr_pipe,
446 : &dom_pol,
447 : NULL,
448 : NULL);
449 0 : if (!NT_STATUS_IS_OK(status)) {
450 0 : goto done;
451 : }
452 :
453 0 : status = rpc_lookup_groupmem(tmp_ctx,
454 : samr_pipe,
455 : &dom_pol,
456 0 : domain->name,
457 0 : &domain->sid,
458 : group_sid,
459 : type,
460 : &num_names,
461 : &sid_mem,
462 : &names,
463 : &name_types);
464 :
465 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
466 0 : retry = true;
467 0 : goto again;
468 : }
469 :
470 0 : if (pnum_names) {
471 0 : *pnum_names = num_names;
472 : }
473 :
474 0 : if (pnames) {
475 0 : *pnames = talloc_move(mem_ctx, &names);
476 : }
477 :
478 0 : if (pname_types) {
479 0 : *pname_types = talloc_move(mem_ctx, &name_types);
480 : }
481 :
482 0 : if (psid_mem) {
483 0 : *psid_mem = talloc_move(mem_ctx, &sid_mem);
484 : }
485 :
486 0 : done:
487 0 : TALLOC_FREE(tmp_ctx);
488 0 : return status;
489 : }
490 :
491 : /* Lookup alias membership */
492 0 : static NTSTATUS sam_lookup_aliasmem(struct winbindd_domain *domain,
493 : TALLOC_CTX *mem_ctx,
494 : const struct dom_sid *group_sid,
495 : enum lsa_SidType type,
496 : uint32_t *pnum_sids,
497 : struct dom_sid **psid_mem)
498 : {
499 0 : struct rpc_pipe_client *samr_pipe;
500 0 : struct policy_handle dom_pol = {0};
501 :
502 0 : uint32_t num_sids = 0;
503 0 : struct dom_sid *sid_mem = NULL;
504 :
505 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
506 0 : NTSTATUS status;
507 0 : bool retry = false;
508 :
509 0 : DBG_INFO("sam_lookup_aliasmem\n");
510 :
511 : /* Paranoia check */
512 0 : if (type != SID_NAME_ALIAS) {
513 0 : status = NT_STATUS_NO_SUCH_ALIAS;
514 0 : goto done;
515 : }
516 :
517 0 : if (pnum_sids) {
518 0 : *pnum_sids = 0;
519 : }
520 :
521 0 : again:
522 0 : status = open_cached_internal_pipe_conn(domain,
523 : &samr_pipe,
524 : &dom_pol,
525 : NULL,
526 : NULL);
527 0 : if (!NT_STATUS_IS_OK(status)) {
528 0 : goto done;
529 : }
530 :
531 0 : status = rpc_lookup_aliasmem(tmp_ctx,
532 : samr_pipe,
533 : &dom_pol,
534 0 : &domain->sid,
535 : group_sid,
536 : type,
537 : &num_sids,
538 : &sid_mem);
539 :
540 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
541 0 : retry = true;
542 0 : goto again;
543 : }
544 :
545 0 : if (pnum_sids) {
546 0 : *pnum_sids = num_sids;
547 : }
548 :
549 0 : if (psid_mem) {
550 0 : *psid_mem = talloc_move(mem_ctx, &sid_mem);
551 : }
552 :
553 0 : done:
554 0 : TALLOC_FREE(tmp_ctx);
555 0 : return status;
556 : }
557 :
558 : /*********************************************************************
559 : BUILTIN specific functions.
560 : *********************************************************************/
561 :
562 : /* List all domain groups */
563 0 : static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
564 : TALLOC_CTX *mem_ctx,
565 : uint32_t *num_entries,
566 : struct wb_acct_info **info)
567 : {
568 : /* BUILTIN doesn't have domain groups */
569 0 : *num_entries = 0;
570 0 : *info = NULL;
571 0 : return NT_STATUS_OK;
572 : }
573 :
574 : /* Query display info for a domain */
575 0 : static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
576 : TALLOC_CTX *mem_ctx,
577 : uint32_t **rids)
578 : {
579 : /* We don't have users */
580 0 : *rids = NULL;
581 0 : return NT_STATUS_OK;
582 : }
583 :
584 : /* get a list of trusted domains - builtin domain */
585 0 : static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
586 : TALLOC_CTX *mem_ctx,
587 : struct netr_DomainTrustList *trusts)
588 : {
589 0 : ZERO_STRUCTP(trusts);
590 0 : return NT_STATUS_OK;
591 : }
592 :
593 : /*********************************************************************
594 : COMMON functions.
595 : *********************************************************************/
596 :
597 : /* List all local groups (aliases) */
598 0 : static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
599 : TALLOC_CTX *mem_ctx,
600 : uint32_t *pnum_info,
601 : struct wb_acct_info **pinfo)
602 : {
603 0 : struct rpc_pipe_client *samr_pipe;
604 0 : struct policy_handle dom_pol = { 0 };
605 0 : struct wb_acct_info *info = NULL;
606 0 : uint32_t num_info = 0;
607 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
608 0 : NTSTATUS status;
609 0 : bool retry = false;
610 :
611 0 : DEBUG(3,("samr: enum local groups\n"));
612 :
613 0 : if (pnum_info) {
614 0 : *pnum_info = 0;
615 : }
616 :
617 0 : again:
618 0 : status = open_cached_internal_pipe_conn(domain,
619 : &samr_pipe,
620 : &dom_pol,
621 : NULL,
622 : NULL);
623 0 : if (!NT_STATUS_IS_OK(status)) {
624 0 : goto done;
625 : }
626 :
627 0 : status = rpc_enum_local_groups(mem_ctx,
628 : samr_pipe,
629 : &dom_pol,
630 : &num_info,
631 :
632 : &info);
633 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
634 0 : retry = true;
635 0 : goto again;
636 : }
637 :
638 0 : if (!NT_STATUS_IS_OK(status)) {
639 0 : goto done;
640 : }
641 :
642 0 : if (pnum_info) {
643 0 : *pnum_info = num_info;
644 : }
645 :
646 0 : if (pinfo) {
647 0 : *pinfo = talloc_move(mem_ctx, &info);
648 : }
649 :
650 0 : done:
651 0 : TALLOC_FREE(tmp_ctx);
652 0 : return status;
653 : }
654 :
655 : /* convert a single name to a sid in a domain */
656 0 : static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
657 : TALLOC_CTX *mem_ctx,
658 : const char *domain_name,
659 : const char *name,
660 : uint32_t flags,
661 : const char **pdom_name,
662 : struct dom_sid *psid,
663 : enum lsa_SidType *ptype)
664 : {
665 0 : struct rpc_pipe_client *samr_pipe = NULL;
666 0 : struct dcerpc_binding_handle *h = NULL;
667 0 : struct policy_handle dom_pol = { .handle_type = 0, };
668 0 : struct dom_sid sid;
669 0 : const char *dom_name = domain_name;
670 0 : struct lsa_String lsa_name = { .string = name };
671 0 : struct samr_Ids rids = { .count = 0 };
672 0 : struct samr_Ids types = { .count = 0 };
673 0 : enum lsa_SidType type;
674 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
675 0 : NTSTATUS status = NT_STATUS_NONE_MAPPED;
676 0 : NTSTATUS result;
677 0 : bool retry = false;
678 0 : bool ok;
679 :
680 0 : DBG_NOTICE("%s\\%s\n", domain_name, name);
681 :
682 0 : if (strequal(domain_name, unix_users_domain_name())) {
683 0 : struct passwd *pwd = NULL;
684 :
685 0 : if (name[0] == '\0') {
686 0 : sid_copy(&sid, &global_sid_Unix_Users);
687 0 : type = SID_NAME_DOMAIN;
688 0 : goto done;
689 : }
690 :
691 0 : pwd = Get_Pwnam_alloc(tmp_ctx, name);
692 0 : if (pwd == NULL) {
693 0 : goto fail;
694 : }
695 0 : ok = sid_compose(&sid, &global_sid_Unix_Users, pwd->pw_uid);
696 0 : if (!ok) {
697 0 : status = NT_STATUS_INTERNAL_ERROR;
698 0 : goto fail;
699 : }
700 0 : type = SID_NAME_USER;
701 0 : goto done;
702 : }
703 :
704 0 : if (strequal(domain_name, unix_groups_domain_name())) {
705 0 : struct group *grp = NULL;
706 :
707 0 : if (name[0] == '\0') {
708 0 : sid_copy(&sid, &global_sid_Unix_Groups);
709 0 : type = SID_NAME_DOMAIN;
710 0 : goto done;
711 : }
712 :
713 0 : grp = getgrnam(name);
714 0 : if (grp == NULL) {
715 0 : goto fail;
716 : }
717 0 : ok = sid_compose(&sid, &global_sid_Unix_Groups, grp->gr_gid);
718 0 : if (!ok) {
719 0 : status = NT_STATUS_INTERNAL_ERROR;
720 0 : goto fail;
721 : }
722 0 : type = SID_NAME_DOM_GRP;
723 0 : goto done;
724 : }
725 :
726 0 : if (name[0] == '\0') {
727 0 : sid_copy(&sid, &domain->sid);
728 0 : type = SID_NAME_DOMAIN;
729 0 : goto done;
730 : }
731 :
732 0 : ok = lookup_wellknown_name(tmp_ctx, name, &sid, &dom_name);
733 0 : if (ok) {
734 0 : type = SID_NAME_WKN_GRP;
735 0 : goto done;
736 : }
737 :
738 : {
739 0 : char *normalized = NULL;
740 0 : NTSTATUS nstatus = normalize_name_unmap(
741 : tmp_ctx, name, &normalized);
742 0 : if (NT_STATUS_IS_OK(nstatus) ||
743 0 : NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
744 0 : lsa_name.string = normalized;
745 : }
746 : }
747 :
748 0 : again:
749 0 : status = open_cached_internal_pipe_conn(
750 : domain, &samr_pipe, &dom_pol, NULL, NULL);
751 0 : if (!NT_STATUS_IS_OK(status)) {
752 0 : goto fail;
753 : }
754 0 : h = samr_pipe->binding_handle;
755 :
756 0 : status = dcerpc_samr_LookupNames(
757 : h, tmp_ctx, &dom_pol, 1, &lsa_name, &rids, &types, &result);
758 :
759 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
760 0 : retry = true;
761 0 : goto again;
762 : }
763 :
764 0 : if (!NT_STATUS_IS_OK(status)) {
765 0 : DBG_DEBUG("dcerpc_samr_LookupNames returned %s\n",
766 : nt_errstr(status));
767 0 : goto fail;
768 : }
769 0 : if (!NT_STATUS_IS_OK(result)) {
770 0 : DBG_DEBUG("dcerpc_samr_LookupNames resulted in %s\n",
771 : nt_errstr(status));
772 0 : status = result;
773 0 : goto fail;
774 : }
775 :
776 0 : sid_compose(&sid, &domain->sid, rids.ids[0]);
777 0 : type = types.ids[0];
778 :
779 0 : done:
780 0 : if (pdom_name != NULL) {
781 0 : *pdom_name = talloc_strdup(mem_ctx, dom_name);
782 0 : if (*pdom_name == NULL) {
783 0 : status = NT_STATUS_NO_MEMORY;
784 0 : goto fail;
785 : }
786 : }
787 :
788 0 : if (psid) {
789 0 : sid_copy(psid, &sid);
790 : }
791 0 : if (ptype) {
792 0 : *ptype = type;
793 : }
794 :
795 0 : status = NT_STATUS_OK;
796 0 : fail:
797 0 : TALLOC_FREE(tmp_ctx);
798 0 : return status;
799 : }
800 :
801 : /* convert a domain SID to a user or group name */
802 0 : static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
803 : TALLOC_CTX *mem_ctx,
804 : const struct dom_sid *sid,
805 : char **pdomain_name,
806 : char **pname,
807 : enum lsa_SidType *ptype)
808 : {
809 0 : struct rpc_pipe_client *samr_pipe = NULL;
810 0 : struct dcerpc_binding_handle *h = NULL;
811 0 : struct policy_handle dom_pol = { .handle_type = 0, };
812 0 : const char *domain_name = "";
813 0 : const char *name = "";
814 0 : enum lsa_SidType type = SID_NAME_USE_NONE;
815 0 : struct lsa_Strings names = { .count = 0, };
816 0 : struct samr_Ids types = { .count = 0 };
817 0 : struct dom_sid domain_sid;
818 0 : uint32_t rid;
819 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
820 0 : NTSTATUS status = NT_STATUS_NONE_MAPPED;
821 0 : NTSTATUS result;
822 0 : bool retry = false;
823 0 : bool ok;
824 :
825 0 : DEBUG(3,("sam_sid_to_name\n"));
826 :
827 0 : if (sid_check_is_unix_users(sid)) {
828 0 : domain_name = unix_users_domain_name();
829 0 : type = SID_NAME_DOMAIN;
830 0 : goto done;
831 : }
832 0 : if (sid_check_is_in_unix_users(sid)) {
833 0 : struct passwd *pwd = NULL;
834 :
835 0 : ok = sid_peek_rid(sid, &rid);
836 0 : if (!ok) {
837 0 : goto fail;
838 : }
839 0 : pwd = getpwuid(rid);
840 0 : if (pwd == NULL) {
841 0 : goto fail;
842 : }
843 :
844 0 : domain_name = unix_users_domain_name();
845 0 : name = talloc_strdup(tmp_ctx, pwd->pw_name);
846 0 : if (name == NULL) {
847 0 : status = NT_STATUS_NO_MEMORY;
848 0 : goto fail;
849 : }
850 0 : type = SID_NAME_USER;
851 0 : goto done;
852 : }
853 :
854 0 : if (sid_check_is_unix_groups(sid)) {
855 0 : domain_name = unix_groups_domain_name();
856 0 : type = SID_NAME_DOMAIN;
857 0 : goto done;
858 : }
859 0 : if (sid_check_is_in_unix_groups(sid)) {
860 0 : struct group *grp = NULL;
861 :
862 0 : ok = sid_peek_rid(sid, &rid);
863 0 : if (!ok) {
864 0 : goto fail;
865 : }
866 0 : grp = getgrgid(rid);
867 0 : if (grp == NULL) {
868 0 : goto fail;
869 : }
870 :
871 0 : domain_name = unix_groups_domain_name();
872 0 : name = talloc_strdup(tmp_ctx, grp->gr_name);
873 0 : if (name == NULL) {
874 0 : status = NT_STATUS_NO_MEMORY;
875 0 : goto fail;
876 : }
877 0 : type = SID_NAME_DOM_GRP;
878 0 : goto done;
879 : }
880 :
881 0 : ok = lookup_wellknown_sid(tmp_ctx, sid, &domain_name, &name);
882 0 : if (ok) {
883 0 : type = SID_NAME_WKN_GRP;
884 0 : goto done;
885 : }
886 :
887 0 : if (dom_sid_equal(sid, &domain->sid)) {
888 0 : domain_name = domain->name;
889 0 : type = SID_NAME_DOMAIN;
890 0 : goto done;
891 : }
892 :
893 0 : sid_copy(&domain_sid, sid);
894 0 : ok = sid_split_rid(&domain_sid, &rid);
895 0 : if (!ok) {
896 0 : goto fail;
897 : }
898 :
899 0 : if (!dom_sid_equal(&domain_sid, &domain->sid)) {
900 0 : goto fail;
901 : }
902 :
903 0 : again:
904 0 : status = open_cached_internal_pipe_conn(
905 : domain, &samr_pipe, &dom_pol, NULL, NULL);
906 0 : if (!NT_STATUS_IS_OK(status)) {
907 0 : goto fail;
908 : }
909 0 : h = samr_pipe->binding_handle;
910 :
911 0 : status = dcerpc_samr_LookupRids(
912 : h, tmp_ctx, &dom_pol, 1, &rid, &names, &types, &result);
913 :
914 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
915 0 : retry = true;
916 0 : goto again;
917 : }
918 :
919 0 : if (!NT_STATUS_IS_OK(status)) {
920 0 : DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
921 : nt_errstr(status));
922 0 : goto fail;
923 : }
924 0 : if (!NT_STATUS_IS_OK(result)) {
925 0 : DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
926 : nt_errstr(result));
927 0 : status = result;
928 0 : goto fail;
929 : }
930 :
931 0 : domain_name = domain->name;
932 0 : name = names.names[0].string;
933 0 : type = types.ids[0];
934 :
935 0 : if (name != NULL) {
936 0 : char *normalized = NULL;
937 0 : NTSTATUS nstatus = normalize_name_map(
938 : tmp_ctx, domain_name, name, &normalized);
939 0 : if (NT_STATUS_IS_OK(nstatus) ||
940 0 : NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
941 0 : name = normalized;
942 : }
943 : }
944 :
945 0 : done:
946 0 : if (ptype) {
947 0 : *ptype = type;
948 : }
949 :
950 0 : if (pname) {
951 0 : *pname = talloc_strdup(mem_ctx, name);
952 0 : if (*pname == NULL) {
953 0 : status = NT_STATUS_NO_MEMORY;
954 0 : goto fail;
955 : }
956 : }
957 :
958 0 : if (pdomain_name) {
959 0 : *pdomain_name = talloc_strdup(mem_ctx, domain_name);
960 0 : if (*pdomain_name == NULL) {
961 0 : status = NT_STATUS_NO_MEMORY;
962 0 : goto fail;
963 : }
964 : }
965 :
966 0 : status = NT_STATUS_OK;
967 0 : fail:
968 0 : TALLOC_FREE(tmp_ctx);
969 0 : return status;
970 : }
971 :
972 0 : static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
973 : TALLOC_CTX *mem_ctx,
974 : const struct dom_sid *domain_sid,
975 : uint32_t *rids,
976 : size_t num_rids,
977 : char **pdomain_name,
978 : char ***pnames,
979 : enum lsa_SidType **ptypes)
980 : {
981 0 : struct rpc_pipe_client *samr_pipe = NULL;
982 0 : struct dcerpc_binding_handle *h = NULL;
983 0 : struct policy_handle dom_pol = { .handle_type = 0, };
984 0 : enum lsa_SidType *types = NULL;
985 0 : char **names = NULL;
986 0 : const char *domain_name = NULL;
987 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
988 0 : NTSTATUS status = NT_STATUS_NO_MEMORY;
989 0 : NTSTATUS result;
990 0 : bool retry = false;
991 0 : uint32_t i;
992 :
993 0 : DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
994 :
995 0 : types = talloc_array(tmp_ctx, enum lsa_SidType, num_rids);
996 0 : if (types == NULL) {
997 0 : goto fail;
998 : }
999 :
1000 0 : names = talloc_array(tmp_ctx, char *, num_rids);
1001 0 : if (names == NULL) {
1002 0 : goto fail;
1003 : }
1004 :
1005 0 : if (sid_check_is_unix_users(domain_sid)) {
1006 0 : domain_name = unix_users_domain_name();
1007 0 : domain_sid = &global_sid_Unix_Users;
1008 : }
1009 0 : if (sid_check_is_unix_groups(domain_sid)) {
1010 0 : domain_name = unix_groups_domain_name();
1011 0 : domain_sid = &global_sid_Unix_Groups;
1012 : }
1013 :
1014 : /* Here we're only interested in the domain name being set */
1015 0 : sid_check_is_wellknown_domain(domain_sid, &domain_name);
1016 :
1017 0 : if (domain_name != NULL) {
1018 0 : uint32_t num_mapped = 0;
1019 :
1020 : /*
1021 : * Do unix users/groups and wkn in a loop. There is no
1022 : * getpwuids() call & friends anyway
1023 : */
1024 :
1025 0 : for (i=0; i<num_rids; i++) {
1026 0 : struct dom_sid sid;
1027 0 : char *name = NULL;
1028 :
1029 0 : sid_compose(&sid, domain_sid, rids[i]);
1030 :
1031 0 : types[i] = SID_NAME_UNKNOWN;
1032 0 : names[i] = NULL;
1033 :
1034 0 : status = sam_sid_to_name(
1035 : domain,
1036 : tmp_ctx,
1037 : &sid,
1038 : NULL,
1039 : &name,
1040 0 : &types[i]);
1041 0 : if (NT_STATUS_IS_OK(status)) {
1042 0 : names[i] = talloc_move(names, &name);
1043 0 : num_mapped += 1;
1044 : }
1045 : }
1046 :
1047 0 : status = NT_STATUS_NONE_MAPPED;
1048 0 : if (num_mapped > 0) {
1049 0 : status = (num_mapped == num_rids) ?
1050 0 : NT_STATUS_OK : STATUS_SOME_UNMAPPED;
1051 : }
1052 0 : goto done;
1053 : }
1054 :
1055 0 : domain_name = domain->name;
1056 :
1057 0 : again:
1058 0 : status = open_cached_internal_pipe_conn(
1059 : domain, &samr_pipe, &dom_pol, NULL, NULL);
1060 0 : if (!NT_STATUS_IS_OK(status)) {
1061 0 : goto done;
1062 : }
1063 0 : h = samr_pipe->binding_handle;
1064 :
1065 : /*
1066 : * Magic number 1000 comes from samr.idl
1067 : */
1068 :
1069 0 : for (i = 0; i < num_rids; i += 1000) {
1070 0 : uint32_t num_lookup_rids = MIN(num_rids - i, 1000);
1071 0 : struct lsa_Strings lsa_names = {
1072 : .count = 0,
1073 : };
1074 0 : struct samr_Ids samr_types = {
1075 : .count = 0,
1076 : };
1077 0 : uint32_t j;
1078 :
1079 0 : status = dcerpc_samr_LookupRids(h,
1080 : tmp_ctx,
1081 : &dom_pol,
1082 : num_lookup_rids,
1083 0 : &rids[i],
1084 : &lsa_names,
1085 : &samr_types,
1086 : &result);
1087 :
1088 0 : if (!retry &&
1089 0 : reset_connection_on_error(domain, samr_pipe, status)) {
1090 0 : retry = true;
1091 0 : goto again;
1092 : }
1093 :
1094 0 : if (!NT_STATUS_IS_OK(status)) {
1095 0 : DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
1096 : nt_errstr(status));
1097 0 : goto fail;
1098 : }
1099 0 : if (!NT_STATUS_IS_OK(result) &&
1100 0 : !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
1101 0 : DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
1102 : nt_errstr(result));
1103 0 : status = result;
1104 0 : goto fail;
1105 : }
1106 :
1107 0 : for (j = 0; j < num_lookup_rids; j++) {
1108 0 : uint32_t dst = i + j;
1109 :
1110 0 : types[dst] = samr_types.ids[j];
1111 0 : names[dst] = talloc_move(
1112 : names,
1113 : discard_const_p(char *,
1114 : &lsa_names.names[j].string));
1115 0 : if (names[dst] != NULL) {
1116 0 : char *normalized = NULL;
1117 0 : NTSTATUS nstatus =
1118 0 : normalize_name_map(names,
1119 : domain_name,
1120 0 : names[dst],
1121 : &normalized);
1122 0 : if (NT_STATUS_IS_OK(nstatus) ||
1123 0 : NT_STATUS_EQUAL(nstatus,
1124 : NT_STATUS_FILE_RENAMED)) {
1125 0 : names[dst] = normalized;
1126 : }
1127 : }
1128 : }
1129 :
1130 0 : TALLOC_FREE(samr_types.ids);
1131 0 : TALLOC_FREE(lsa_names.names);
1132 : }
1133 :
1134 0 : done:
1135 0 : if (pdomain_name) {
1136 0 : *pdomain_name = talloc_strdup(mem_ctx, domain_name);
1137 0 : if (*pdomain_name == NULL) {
1138 0 : status = NT_STATUS_NO_MEMORY;
1139 0 : goto fail;
1140 : }
1141 : }
1142 :
1143 0 : if (ptypes) {
1144 0 : *ptypes = talloc_move(mem_ctx, &types);
1145 : }
1146 :
1147 0 : if (pnames) {
1148 0 : *pnames = talloc_move(mem_ctx, &names);
1149 : }
1150 :
1151 0 : fail:
1152 0 : TALLOC_FREE(tmp_ctx);
1153 0 : return status;
1154 : }
1155 :
1156 0 : static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
1157 : TALLOC_CTX *mem_ctx,
1158 : struct samr_DomInfo12 *lockout_policy)
1159 : {
1160 0 : struct rpc_pipe_client *samr_pipe;
1161 0 : struct policy_handle dom_pol = { 0 };
1162 0 : union samr_DomainInfo *info = NULL;
1163 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1164 0 : NTSTATUS status, result;
1165 0 : struct dcerpc_binding_handle *b = NULL;
1166 0 : bool retry = false;
1167 :
1168 0 : DEBUG(3,("sam_lockout_policy\n"));
1169 :
1170 0 : again:
1171 0 : status = open_cached_internal_pipe_conn(domain,
1172 : &samr_pipe,
1173 : &dom_pol,
1174 : NULL,
1175 : NULL);
1176 0 : if (!NT_STATUS_IS_OK(status)) {
1177 0 : goto error;
1178 : }
1179 :
1180 0 : b = samr_pipe->binding_handle;
1181 :
1182 0 : status = dcerpc_samr_QueryDomainInfo(b,
1183 : mem_ctx,
1184 : &dom_pol,
1185 : DomainLockoutInformation,
1186 : &info,
1187 : &result);
1188 :
1189 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1190 0 : retry = true;
1191 0 : goto again;
1192 : }
1193 :
1194 0 : if (!NT_STATUS_IS_OK(status)) {
1195 0 : goto error;
1196 : }
1197 0 : if (!NT_STATUS_IS_OK(result)) {
1198 0 : status = result;
1199 0 : goto error;
1200 : }
1201 :
1202 0 : *lockout_policy = info->info12;
1203 :
1204 0 : error:
1205 0 : TALLOC_FREE(tmp_ctx);
1206 0 : return status;
1207 : }
1208 :
1209 0 : static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
1210 : TALLOC_CTX *mem_ctx,
1211 : struct samr_DomInfo1 *passwd_policy)
1212 : {
1213 0 : struct rpc_pipe_client *samr_pipe;
1214 0 : struct policy_handle dom_pol = { 0 };
1215 0 : union samr_DomainInfo *info = NULL;
1216 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1217 0 : NTSTATUS status, result;
1218 0 : struct dcerpc_binding_handle *b = NULL;
1219 0 : bool retry = false;
1220 :
1221 0 : DEBUG(3,("sam_password_policy\n"));
1222 :
1223 0 : again:
1224 0 : status = open_cached_internal_pipe_conn(domain,
1225 : &samr_pipe,
1226 : &dom_pol,
1227 : NULL,
1228 : NULL);
1229 0 : if (!NT_STATUS_IS_OK(status)) {
1230 0 : goto error;
1231 : }
1232 :
1233 0 : b = samr_pipe->binding_handle;
1234 :
1235 0 : status = dcerpc_samr_QueryDomainInfo(b,
1236 : mem_ctx,
1237 : &dom_pol,
1238 : DomainPasswordInformation,
1239 : &info,
1240 : &result);
1241 :
1242 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1243 0 : retry = true;
1244 0 : goto again;
1245 : }
1246 :
1247 0 : if (!NT_STATUS_IS_OK(status)) {
1248 0 : goto error;
1249 : }
1250 0 : if (!NT_STATUS_IS_OK(result)) {
1251 0 : status = result;
1252 0 : goto error;
1253 : }
1254 :
1255 0 : *passwd_policy = info->info1;
1256 :
1257 0 : error:
1258 0 : TALLOC_FREE(tmp_ctx);
1259 0 : return status;
1260 : }
1261 :
1262 : /* Lookup groups a user is a member of. */
1263 0 : static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
1264 : TALLOC_CTX *mem_ctx,
1265 : const struct dom_sid *user_sid,
1266 : uint32_t *pnum_groups,
1267 : struct dom_sid **puser_grpsids)
1268 : {
1269 0 : struct rpc_pipe_client *samr_pipe;
1270 0 : struct policy_handle dom_pol;
1271 0 : struct dom_sid *user_grpsids = NULL;
1272 0 : uint32_t num_groups = 0;
1273 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1274 0 : NTSTATUS status;
1275 0 : bool retry = false;
1276 :
1277 0 : DEBUG(3,("sam_lookup_usergroups\n"));
1278 :
1279 0 : ZERO_STRUCT(dom_pol);
1280 :
1281 0 : if (pnum_groups) {
1282 0 : *pnum_groups = 0;
1283 : }
1284 :
1285 0 : again:
1286 0 : status = open_cached_internal_pipe_conn(domain,
1287 : &samr_pipe,
1288 : &dom_pol,
1289 : NULL,
1290 : NULL);
1291 0 : if (!NT_STATUS_IS_OK(status)) {
1292 0 : goto done;
1293 : }
1294 :
1295 0 : status = rpc_lookup_usergroups(tmp_ctx,
1296 : samr_pipe,
1297 : &dom_pol,
1298 0 : &domain->sid,
1299 : user_sid,
1300 : &num_groups,
1301 : &user_grpsids);
1302 :
1303 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1304 0 : retry = true;
1305 0 : goto again;
1306 : }
1307 :
1308 0 : if (!NT_STATUS_IS_OK(status)) {
1309 0 : goto done;
1310 : }
1311 :
1312 0 : if (pnum_groups) {
1313 0 : *pnum_groups = num_groups;
1314 : }
1315 :
1316 0 : if (puser_grpsids) {
1317 0 : *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
1318 : }
1319 :
1320 0 : done:
1321 :
1322 0 : TALLOC_FREE(tmp_ctx);
1323 0 : return status;
1324 : }
1325 :
1326 0 : static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1327 : TALLOC_CTX *mem_ctx,
1328 : uint32_t num_sids,
1329 : const struct dom_sid *sids,
1330 : uint32_t *pnum_aliases,
1331 : uint32_t **palias_rids)
1332 : {
1333 0 : struct rpc_pipe_client *samr_pipe;
1334 0 : struct policy_handle dom_pol = { 0 };
1335 0 : uint32_t num_aliases = 0;
1336 0 : uint32_t *alias_rids = NULL;
1337 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1338 0 : NTSTATUS status;
1339 0 : bool retry = false;
1340 :
1341 0 : DEBUG(3,("sam_lookup_useraliases\n"));
1342 :
1343 0 : if (pnum_aliases) {
1344 0 : *pnum_aliases = 0;
1345 : }
1346 :
1347 0 : again:
1348 0 : status = open_cached_internal_pipe_conn(domain,
1349 : &samr_pipe,
1350 : &dom_pol,
1351 : NULL,
1352 : NULL);
1353 0 : if (!NT_STATUS_IS_OK(status)) {
1354 0 : goto done;
1355 : }
1356 :
1357 0 : status = rpc_lookup_useraliases(tmp_ctx,
1358 : samr_pipe,
1359 : &dom_pol,
1360 : num_sids,
1361 : sids,
1362 : &num_aliases,
1363 : &alias_rids);
1364 :
1365 0 : if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1366 0 : retry = true;
1367 0 : goto again;
1368 : }
1369 :
1370 0 : if (!NT_STATUS_IS_OK(status)) {
1371 0 : goto done;
1372 : }
1373 :
1374 0 : if (pnum_aliases) {
1375 0 : *pnum_aliases = num_aliases;
1376 : }
1377 :
1378 0 : if (palias_rids) {
1379 0 : *palias_rids = talloc_move(mem_ctx, &alias_rids);
1380 : }
1381 :
1382 0 : done:
1383 :
1384 0 : TALLOC_FREE(tmp_ctx);
1385 0 : return status;
1386 : }
1387 :
1388 : /* the rpc backend methods are exposed via this structure */
1389 : struct winbindd_methods builtin_passdb_methods = {
1390 : .consistent = false,
1391 :
1392 : .query_user_list = builtin_query_user_list,
1393 : .enum_dom_groups = builtin_enum_dom_groups,
1394 : .enum_local_groups = sam_enum_local_groups,
1395 : .name_to_sid = sam_name_to_sid,
1396 : .sid_to_name = sam_sid_to_name,
1397 : .rids_to_names = sam_rids_to_names,
1398 : .lookup_usergroups = sam_lookup_usergroups,
1399 : .lookup_useraliases = sam_lookup_useraliases,
1400 : .lookup_groupmem = sam_lookup_groupmem,
1401 : .lookup_aliasmem = sam_lookup_aliasmem,
1402 : .lockout_policy = sam_lockout_policy,
1403 : .password_policy = sam_password_policy,
1404 : .trusted_domains = builtin_trusted_domains
1405 : };
1406 :
1407 : /* the rpc backend methods are exposed via this structure */
1408 : struct winbindd_methods sam_passdb_methods = {
1409 : .consistent = false,
1410 :
1411 : .query_user_list = sam_query_user_list,
1412 : .enum_dom_groups = sam_enum_dom_groups,
1413 : .enum_local_groups = sam_enum_local_groups,
1414 : .name_to_sid = sam_name_to_sid,
1415 : .sid_to_name = sam_sid_to_name,
1416 : .rids_to_names = sam_rids_to_names,
1417 : .lookup_usergroups = sam_lookup_usergroups,
1418 : .lookup_useraliases = sam_lookup_useraliases,
1419 : .lookup_groupmem = sam_lookup_groupmem,
1420 : .lookup_aliasmem = sam_lookup_aliasmem,
1421 : .lockout_policy = sam_lockout_policy,
1422 : .password_policy = sam_password_policy,
1423 : .trusted_domains = sam_trusted_domains
1424 : };
|