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
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_WINBIND
43
44 /*
45 * The other end of this won't go away easily, so we can trust it
46 *
47 * It is either a long-lived process with the same lifetime as
48 * winbindd or a part of this process
49 */
50 struct winbind_internal_pipes {
51 struct rpc_pipe_client *samr_pipe;
52 struct policy_handle samr_domain_hnd;
53 struct rpc_pipe_client *lsa_pipe;
54 struct policy_handle lsa_hnd;
55 };
56
57
open_internal_samr_conn(TALLOC_CTX * mem_ctx,struct winbindd_domain * domain,struct rpc_pipe_client ** samr_pipe,struct policy_handle * samr_domain_hnd)58 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
59 struct winbindd_domain *domain,
60 struct rpc_pipe_client **samr_pipe,
61 struct policy_handle *samr_domain_hnd)
62 {
63 NTSTATUS status, result;
64 struct policy_handle samr_connect_hnd;
65 struct dcerpc_binding_handle *b;
66
67 status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
68 if (!NT_STATUS_IS_OK(status)) {
69 return status;
70 }
71
72 b = (*samr_pipe)->binding_handle;
73
74 status = dcerpc_samr_Connect2(b, mem_ctx,
75 (*samr_pipe)->desthost,
76 SEC_FLAG_MAXIMUM_ALLOWED,
77 &samr_connect_hnd,
78 &result);
79 if (!NT_STATUS_IS_OK(status)) {
80 return status;
81 }
82 if (!NT_STATUS_IS_OK(result)) {
83 return result;
84 }
85
86 status = dcerpc_samr_OpenDomain(b, mem_ctx,
87 &samr_connect_hnd,
88 SEC_FLAG_MAXIMUM_ALLOWED,
89 &domain->sid,
90 samr_domain_hnd,
91 &result);
92 if (!NT_STATUS_IS_OK(status)) {
93 return status;
94 }
95
96 return result;
97 }
98
open_internal_lsa_conn(TALLOC_CTX * mem_ctx,struct rpc_pipe_client ** lsa_pipe,struct policy_handle * lsa_hnd)99 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
100 struct rpc_pipe_client **lsa_pipe,
101 struct policy_handle *lsa_hnd)
102 {
103 NTSTATUS status;
104
105 status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
106 if (!NT_STATUS_IS_OK(status)) {
107 return status;
108 }
109
110 status = rpccli_lsa_open_policy((*lsa_pipe),
111 mem_ctx,
112 true,
113 SEC_FLAG_MAXIMUM_ALLOWED,
114 lsa_hnd);
115
116 return status;
117 }
118
119
open_cached_internal_pipe_conn(struct winbindd_domain * domain,struct rpc_pipe_client ** samr_pipe,struct policy_handle * samr_domain_hnd,struct rpc_pipe_client ** lsa_pipe,struct policy_handle * lsa_hnd)120 static NTSTATUS open_cached_internal_pipe_conn(
121 struct winbindd_domain *domain,
122 struct rpc_pipe_client **samr_pipe,
123 struct policy_handle *samr_domain_hnd,
124 struct rpc_pipe_client **lsa_pipe,
125 struct policy_handle *lsa_hnd)
126 {
127 struct winbind_internal_pipes *internal_pipes = NULL;
128
129 if (domain->private_data == NULL) {
130 TALLOC_CTX *frame = talloc_stackframe();
131 NTSTATUS status;
132
133 internal_pipes = talloc_zero(frame,
134 struct winbind_internal_pipes);
135
136 status = open_internal_samr_conn(
137 internal_pipes,
138 domain,
139 &internal_pipes->samr_pipe,
140 &internal_pipes->samr_domain_hnd);
141 if (!NT_STATUS_IS_OK(status)) {
142 TALLOC_FREE(frame);
143 return status;
144 }
145
146 status = open_internal_lsa_conn(internal_pipes,
147 &internal_pipes->lsa_pipe,
148 &internal_pipes->lsa_hnd);
149
150 if (!NT_STATUS_IS_OK(status)) {
151 TALLOC_FREE(frame);
152 return status;
153 }
154
155 domain->private_data = talloc_move(domain, &internal_pipes);
156
157 TALLOC_FREE(frame);
158
159 }
160
161 internal_pipes = talloc_get_type_abort(
162 domain->private_data, struct winbind_internal_pipes);
163
164 if (samr_domain_hnd) {
165 *samr_domain_hnd = internal_pipes->samr_domain_hnd;
166 }
167
168 if (samr_pipe) {
169 *samr_pipe = internal_pipes->samr_pipe;
170 }
171
172 if (lsa_hnd) {
173 *lsa_hnd = internal_pipes->lsa_hnd;
174 }
175
176 if (lsa_pipe) {
177 *lsa_pipe = internal_pipes->lsa_pipe;
178 }
179
180 return NT_STATUS_OK;
181 }
182
reset_connection_on_error(struct winbindd_domain * domain,struct rpc_pipe_client * p,NTSTATUS status)183 static bool reset_connection_on_error(struct winbindd_domain *domain,
184 struct rpc_pipe_client *p,
185 NTSTATUS status)
186 {
187 struct winbind_internal_pipes *internal_pipes = NULL;
188
189 internal_pipes = talloc_get_type_abort(
190 domain->private_data, struct winbind_internal_pipes);
191
192 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
193 NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
194 {
195 TALLOC_FREE(internal_pipes);
196 domain->private_data = NULL;
197 return true;
198 }
199
200 if (!rpccli_is_connected(p)) {
201 TALLOC_FREE(internal_pipes);
202 domain->private_data = NULL;
203 return true;
204 }
205
206 return false;
207 }
208
209 /*********************************************************************
210 SAM specific functions.
211 *********************************************************************/
212
213 /* List all domain groups */
sam_enum_dom_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * pnum_info,struct wb_acct_info ** pinfo)214 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
215 TALLOC_CTX *mem_ctx,
216 uint32_t *pnum_info,
217 struct wb_acct_info **pinfo)
218 {
219 struct rpc_pipe_client *samr_pipe;
220 struct policy_handle dom_pol = { 0 };
221 struct wb_acct_info *info = NULL;
222 uint32_t num_info = 0;
223 TALLOC_CTX *tmp_ctx;
224 NTSTATUS status;
225 bool retry = false;
226
227 DEBUG(3,("sam_enum_dom_groups\n"));
228
229 if (pnum_info) {
230 *pnum_info = 0;
231 }
232
233 tmp_ctx = talloc_stackframe();
234 if (tmp_ctx == NULL) {
235 return NT_STATUS_NO_MEMORY;
236 }
237
238 again:
239 status = open_cached_internal_pipe_conn(domain,
240 &samr_pipe,
241 &dom_pol,
242 NULL,
243 NULL);
244 if (!NT_STATUS_IS_OK(status)) {
245 TALLOC_FREE(tmp_ctx);
246 return status;
247 }
248
249 status = rpc_enum_dom_groups(tmp_ctx,
250 samr_pipe,
251 &dom_pol,
252 &num_info,
253 &info);
254
255 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
256 retry = true;
257 goto again;
258 }
259
260 if (!NT_STATUS_IS_OK(status)) {
261 TALLOC_FREE(tmp_ctx);
262 return status;
263 }
264
265 if (pnum_info) {
266 *pnum_info = num_info;
267 }
268
269 if (pinfo) {
270 *pinfo = talloc_move(mem_ctx, &info);
271 }
272
273 TALLOC_FREE(tmp_ctx);
274 return status;
275 }
276
277 /* Query display info for a domain */
sam_query_user_list(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t ** prids)278 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
279 TALLOC_CTX *mem_ctx,
280 uint32_t **prids)
281 {
282 struct rpc_pipe_client *samr_pipe = NULL;
283 struct policy_handle dom_pol = { 0 };
284 uint32_t *rids = NULL;
285 TALLOC_CTX *tmp_ctx;
286 NTSTATUS status;
287 bool retry = false;
288
289 DEBUG(3,("samr_query_user_list\n"));
290
291 tmp_ctx = talloc_stackframe();
292 if (tmp_ctx == NULL) {
293 return NT_STATUS_NO_MEMORY;
294 }
295
296 again:
297 status = open_cached_internal_pipe_conn(domain,
298 &samr_pipe,
299 &dom_pol,
300 NULL,
301 NULL);
302 if (!NT_STATUS_IS_OK(status)) {
303 goto done;
304 }
305
306 status = rpc_query_user_list(tmp_ctx,
307 samr_pipe,
308 &dom_pol,
309 &domain->sid,
310 &rids);
311 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
312 retry = true;
313 goto again;
314 }
315
316 if (!NT_STATUS_IS_OK(status)) {
317 goto done;
318 }
319
320 if (prids != NULL) {
321 *prids = talloc_move(mem_ctx, &rids);
322 }
323
324 done:
325 TALLOC_FREE(rids);
326 TALLOC_FREE(tmp_ctx);
327 return status;
328 }
329
330 /* get a list of trusted domains - builtin domain */
sam_trusted_domains(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct netr_DomainTrustList * ptrust_list)331 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
332 TALLOC_CTX *mem_ctx,
333 struct netr_DomainTrustList *ptrust_list)
334 {
335 struct rpc_pipe_client *lsa_pipe;
336 struct policy_handle lsa_policy = { 0 };
337 struct netr_DomainTrust *trusts = NULL;
338 uint32_t num_trusts = 0;
339 TALLOC_CTX *tmp_ctx;
340 NTSTATUS status;
341 bool retry = false;
342
343 DEBUG(3,("samr: trusted domains\n"));
344
345 if (ptrust_list) {
346 ZERO_STRUCTP(ptrust_list);
347 }
348
349 tmp_ctx = talloc_stackframe();
350 if (tmp_ctx == NULL) {
351 return NT_STATUS_NO_MEMORY;
352 }
353
354 again:
355 status = open_cached_internal_pipe_conn(domain,
356 NULL,
357 NULL,
358 &lsa_pipe,
359 &lsa_policy);
360 if (!NT_STATUS_IS_OK(status)) {
361 goto done;
362 }
363
364 status = rpc_trusted_domains(tmp_ctx,
365 lsa_pipe,
366 &lsa_policy,
367 &num_trusts,
368 &trusts);
369
370 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
371 retry = true;
372 goto again;
373 }
374
375 if (!NT_STATUS_IS_OK(status)) {
376 goto done;
377 }
378
379 if (ptrust_list) {
380 ptrust_list->count = num_trusts;
381 ptrust_list->array = talloc_move(mem_ctx, &trusts);
382 }
383
384 done:
385 TALLOC_FREE(tmp_ctx);
386 return status;
387 }
388
389 /* Lookup group membership given a rid. */
sam_lookup_groupmem(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * group_sid,enum lsa_SidType type,uint32_t * pnum_names,struct dom_sid ** psid_mem,char *** pnames,uint32_t ** pname_types)390 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
391 TALLOC_CTX *mem_ctx,
392 const struct dom_sid *group_sid,
393 enum lsa_SidType type,
394 uint32_t *pnum_names,
395 struct dom_sid **psid_mem,
396 char ***pnames,
397 uint32_t **pname_types)
398 {
399 struct rpc_pipe_client *samr_pipe;
400 struct policy_handle dom_pol = { 0 };
401
402 uint32_t num_names = 0;
403 struct dom_sid *sid_mem = NULL;
404 char **names = NULL;
405 uint32_t *name_types = NULL;
406
407 TALLOC_CTX *tmp_ctx;
408 NTSTATUS status;
409 bool retry = false;
410
411 DEBUG(3,("sam_lookup_groupmem\n"));
412
413 /* Paranoia check */
414 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
415 /* There's no groups, only aliases in BUILTIN */
416 return NT_STATUS_NO_SUCH_GROUP;
417 }
418
419 if (pnum_names) {
420 *pnum_names = 0;
421 }
422
423 tmp_ctx = talloc_stackframe();
424 if (tmp_ctx == NULL) {
425 return NT_STATUS_NO_MEMORY;
426 }
427
428 again:
429 status = open_cached_internal_pipe_conn(domain,
430 &samr_pipe,
431 &dom_pol,
432 NULL,
433 NULL);
434 if (!NT_STATUS_IS_OK(status)) {
435 goto done;
436 }
437
438 status = rpc_lookup_groupmem(tmp_ctx,
439 samr_pipe,
440 &dom_pol,
441 domain->name,
442 &domain->sid,
443 group_sid,
444 type,
445 &num_names,
446 &sid_mem,
447 &names,
448 &name_types);
449
450 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
451 retry = true;
452 goto again;
453 }
454
455 if (pnum_names) {
456 *pnum_names = num_names;
457 }
458
459 if (pnames) {
460 *pnames = talloc_move(mem_ctx, &names);
461 }
462
463 if (pname_types) {
464 *pname_types = talloc_move(mem_ctx, &name_types);
465 }
466
467 if (psid_mem) {
468 *psid_mem = talloc_move(mem_ctx, &sid_mem);
469 }
470
471 done:
472 TALLOC_FREE(tmp_ctx);
473 return status;
474 }
475
476 /*********************************************************************
477 BUILTIN specific functions.
478 *********************************************************************/
479
480 /* List all domain groups */
builtin_enum_dom_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * num_entries,struct wb_acct_info ** info)481 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
482 TALLOC_CTX *mem_ctx,
483 uint32_t *num_entries,
484 struct wb_acct_info **info)
485 {
486 /* BUILTIN doesn't have domain groups */
487 *num_entries = 0;
488 *info = NULL;
489 return NT_STATUS_OK;
490 }
491
492 /* Query display info for a domain */
builtin_query_user_list(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t ** rids)493 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
494 TALLOC_CTX *mem_ctx,
495 uint32_t **rids)
496 {
497 /* We don't have users */
498 *rids = NULL;
499 return NT_STATUS_OK;
500 }
501
502 /* get a list of trusted domains - builtin domain */
builtin_trusted_domains(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct netr_DomainTrustList * trusts)503 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
504 TALLOC_CTX *mem_ctx,
505 struct netr_DomainTrustList *trusts)
506 {
507 ZERO_STRUCTP(trusts);
508 return NT_STATUS_OK;
509 }
510
511 /*********************************************************************
512 COMMON functions.
513 *********************************************************************/
514
515 /* List all local groups (aliases) */
sam_enum_local_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * pnum_info,struct wb_acct_info ** pinfo)516 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
517 TALLOC_CTX *mem_ctx,
518 uint32_t *pnum_info,
519 struct wb_acct_info **pinfo)
520 {
521 struct rpc_pipe_client *samr_pipe;
522 struct policy_handle dom_pol = { 0 };
523 struct wb_acct_info *info = NULL;
524 uint32_t num_info = 0;
525 TALLOC_CTX *tmp_ctx;
526 NTSTATUS status;
527 bool retry = false;
528
529 DEBUG(3,("samr: enum local groups\n"));
530
531 if (pnum_info) {
532 *pnum_info = 0;
533 }
534
535 tmp_ctx = talloc_stackframe();
536 if (tmp_ctx == NULL) {
537 return NT_STATUS_NO_MEMORY;
538 }
539
540 again:
541 status = open_cached_internal_pipe_conn(domain,
542 &samr_pipe,
543 &dom_pol,
544 NULL,
545 NULL);
546 if (!NT_STATUS_IS_OK(status)) {
547 goto done;
548 }
549
550 status = rpc_enum_local_groups(mem_ctx,
551 samr_pipe,
552 &dom_pol,
553 &num_info,
554
555 &info);
556 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
557 retry = true;
558 goto again;
559 }
560
561 if (!NT_STATUS_IS_OK(status)) {
562 goto done;
563 }
564
565 if (pnum_info) {
566 *pnum_info = num_info;
567 }
568
569 if (pinfo) {
570 *pinfo = talloc_move(mem_ctx, &info);
571 }
572
573 done:
574 TALLOC_FREE(tmp_ctx);
575 return status;
576 }
577
578 /* convert a single name to a sid in a domain */
sam_name_to_sid(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * domain_name,const char * name,uint32_t flags,const char ** pdom_name,struct dom_sid * psid,enum lsa_SidType * ptype)579 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
580 TALLOC_CTX *mem_ctx,
581 const char *domain_name,
582 const char *name,
583 uint32_t flags,
584 const char **pdom_name,
585 struct dom_sid *psid,
586 enum lsa_SidType *ptype)
587 {
588 struct rpc_pipe_client *lsa_pipe;
589 struct policy_handle lsa_policy = { 0 };
590 struct dom_sid sid;
591 const char *dom_name;
592 enum lsa_SidType type;
593 TALLOC_CTX *tmp_ctx;
594 NTSTATUS status;
595 bool retry = false;
596
597 DEBUG(3,("sam_name_to_sid\n"));
598
599 tmp_ctx = talloc_stackframe();
600 if (tmp_ctx == NULL) {
601 return NT_STATUS_NO_MEMORY;
602 }
603
604 again:
605 status = open_cached_internal_pipe_conn(domain,
606 NULL,
607 NULL,
608 &lsa_pipe,
609 &lsa_policy);
610 if (!NT_STATUS_IS_OK(status)) {
611 goto done;
612 }
613
614 status = rpc_name_to_sid(tmp_ctx,
615 lsa_pipe,
616 &lsa_policy,
617 domain_name,
618 name,
619 flags,
620 &dom_name,
621 &sid,
622 &type);
623
624 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
625 retry = true;
626 goto again;
627 }
628
629 if (!NT_STATUS_IS_OK(status)) {
630 goto done;
631 }
632
633 if (pdom_name != NULL) {
634 *pdom_name = talloc_strdup(mem_ctx, dom_name);
635 if (*pdom_name == NULL) {
636 status = NT_STATUS_NO_MEMORY;
637 goto done;
638 }
639 }
640
641 if (psid) {
642 sid_copy(psid, &sid);
643 }
644 if (ptype) {
645 *ptype = type;
646 }
647
648 done:
649 TALLOC_FREE(tmp_ctx);
650 return status;
651 }
652
653 /* convert a domain SID to a user or group name */
sam_sid_to_name(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,char ** pdomain_name,char ** pname,enum lsa_SidType * ptype)654 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
655 TALLOC_CTX *mem_ctx,
656 const struct dom_sid *sid,
657 char **pdomain_name,
658 char **pname,
659 enum lsa_SidType *ptype)
660 {
661 struct rpc_pipe_client *lsa_pipe;
662 struct policy_handle lsa_policy = { 0 };
663 char *domain_name = NULL;
664 char *name = NULL;
665 enum lsa_SidType type;
666 TALLOC_CTX *tmp_ctx;
667 NTSTATUS status;
668 bool retry = false;
669
670 DEBUG(3,("sam_sid_to_name\n"));
671
672 /* Paranoia check */
673 if (!sid_check_is_in_builtin(sid) &&
674 !sid_check_is_builtin(sid) &&
675 !sid_check_is_in_our_sam(sid) &&
676 !sid_check_is_our_sam(sid) &&
677 !sid_check_is_in_unix_users(sid) &&
678 !sid_check_is_unix_users(sid) &&
679 !sid_check_is_in_unix_groups(sid) &&
680 !sid_check_is_unix_groups(sid) &&
681 !sid_check_is_in_wellknown_domain(sid)) {
682 struct dom_sid_buf buf;
683 DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
684 "lookup SID %s\n",
685 dom_sid_str_buf(sid, &buf)));
686 return NT_STATUS_NONE_MAPPED;
687 }
688
689 tmp_ctx = talloc_stackframe();
690 if (tmp_ctx == NULL) {
691 return NT_STATUS_NO_MEMORY;
692 }
693
694 again:
695 status = open_cached_internal_pipe_conn(domain,
696 NULL,
697 NULL,
698 &lsa_pipe,
699 &lsa_policy);
700 if (!NT_STATUS_IS_OK(status)) {
701 goto done;
702 }
703
704 status = rpc_sid_to_name(tmp_ctx,
705 lsa_pipe,
706 &lsa_policy,
707 domain,
708 sid,
709 &domain_name,
710 &name,
711 &type);
712
713 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
714 retry = true;
715 goto again;
716 }
717
718 if (ptype) {
719 *ptype = type;
720 }
721
722 if (pname) {
723 *pname = talloc_move(mem_ctx, &name);
724 }
725
726 if (pdomain_name) {
727 *pdomain_name = talloc_move(mem_ctx, &domain_name);
728 }
729
730 done:
731
732 TALLOC_FREE(tmp_ctx);
733 return status;
734 }
735
sam_rids_to_names(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * domain_sid,uint32_t * rids,size_t num_rids,char ** pdomain_name,char *** pnames,enum lsa_SidType ** ptypes)736 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
737 TALLOC_CTX *mem_ctx,
738 const struct dom_sid *domain_sid,
739 uint32_t *rids,
740 size_t num_rids,
741 char **pdomain_name,
742 char ***pnames,
743 enum lsa_SidType **ptypes)
744 {
745 struct rpc_pipe_client *lsa_pipe;
746 struct policy_handle lsa_policy = { 0 };
747 enum lsa_SidType *types = NULL;
748 char *domain_name = NULL;
749 char **names = NULL;
750 TALLOC_CTX *tmp_ctx;
751 NTSTATUS status;
752 bool retry = false;
753
754 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
755
756 /* Paranoia check */
757 if (!sid_check_is_builtin(domain_sid) &&
758 !sid_check_is_our_sam(domain_sid) &&
759 !sid_check_is_unix_users(domain_sid) &&
760 !sid_check_is_unix_groups(domain_sid) &&
761 !sid_check_is_in_wellknown_domain(domain_sid)) {
762 struct dom_sid_buf buf;
763 DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
764 "lookup SID %s\n",
765 dom_sid_str_buf(domain_sid, &buf)));
766 return NT_STATUS_NONE_MAPPED;
767 }
768
769 tmp_ctx = talloc_stackframe();
770 if (tmp_ctx == NULL) {
771 return NT_STATUS_NO_MEMORY;
772 }
773
774 again:
775 status = open_cached_internal_pipe_conn(domain,
776 NULL,
777 NULL,
778 &lsa_pipe,
779 &lsa_policy);
780 if (!NT_STATUS_IS_OK(status)) {
781 goto done;
782 }
783
784 status = rpc_rids_to_names(tmp_ctx,
785 lsa_pipe,
786 &lsa_policy,
787 domain,
788 domain_sid,
789 rids,
790 num_rids,
791 &domain_name,
792 &names,
793 &types);
794
795 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
796 retry = true;
797 goto again;
798 }
799
800 if (!NT_STATUS_IS_OK(status)) {
801 goto done;
802 }
803
804 if (pdomain_name) {
805 *pdomain_name = talloc_move(mem_ctx, &domain_name);
806 }
807
808 if (ptypes) {
809 *ptypes = talloc_move(mem_ctx, &types);
810 }
811
812 if (pnames) {
813 *pnames = talloc_move(mem_ctx, &names);
814 }
815
816 done:
817 TALLOC_FREE(tmp_ctx);
818 return status;
819 }
820
sam_lockout_policy(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct samr_DomInfo12 * lockout_policy)821 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
822 TALLOC_CTX *mem_ctx,
823 struct samr_DomInfo12 *lockout_policy)
824 {
825 struct rpc_pipe_client *samr_pipe;
826 struct policy_handle dom_pol = { 0 };
827 union samr_DomainInfo *info = NULL;
828 TALLOC_CTX *tmp_ctx;
829 NTSTATUS status, result;
830 struct dcerpc_binding_handle *b = NULL;
831 bool retry = false;
832
833 DEBUG(3,("sam_lockout_policy\n"));
834
835 tmp_ctx = talloc_stackframe();
836 if (tmp_ctx == NULL) {
837 return NT_STATUS_NO_MEMORY;
838 }
839
840 again:
841 status = open_cached_internal_pipe_conn(domain,
842 &samr_pipe,
843 &dom_pol,
844 NULL,
845 NULL);
846 if (!NT_STATUS_IS_OK(status)) {
847 goto error;
848 }
849
850 b = samr_pipe->binding_handle;
851
852 status = dcerpc_samr_QueryDomainInfo(b,
853 mem_ctx,
854 &dom_pol,
855 DomainLockoutInformation,
856 &info,
857 &result);
858
859 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
860 retry = true;
861 goto again;
862 }
863
864 if (!NT_STATUS_IS_OK(status)) {
865 goto error;
866 }
867 if (!NT_STATUS_IS_OK(result)) {
868 status = result;
869 goto error;
870 }
871
872 *lockout_policy = info->info12;
873
874 error:
875 TALLOC_FREE(tmp_ctx);
876 return status;
877 }
878
sam_password_policy(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct samr_DomInfo1 * passwd_policy)879 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
880 TALLOC_CTX *mem_ctx,
881 struct samr_DomInfo1 *passwd_policy)
882 {
883 struct rpc_pipe_client *samr_pipe;
884 struct policy_handle dom_pol = { 0 };
885 union samr_DomainInfo *info = NULL;
886 TALLOC_CTX *tmp_ctx;
887 NTSTATUS status, result;
888 struct dcerpc_binding_handle *b = NULL;
889 bool retry = false;
890
891 DEBUG(3,("sam_password_policy\n"));
892
893 tmp_ctx = talloc_stackframe();
894 if (tmp_ctx == NULL) {
895 return NT_STATUS_NO_MEMORY;
896 }
897
898 again:
899 status = open_cached_internal_pipe_conn(domain,
900 &samr_pipe,
901 &dom_pol,
902 NULL,
903 NULL);
904 if (!NT_STATUS_IS_OK(status)) {
905 goto error;
906 }
907
908 b = samr_pipe->binding_handle;
909
910 status = dcerpc_samr_QueryDomainInfo(b,
911 mem_ctx,
912 &dom_pol,
913 DomainPasswordInformation,
914 &info,
915 &result);
916
917 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
918 retry = true;
919 goto again;
920 }
921
922 if (!NT_STATUS_IS_OK(status)) {
923 goto error;
924 }
925 if (!NT_STATUS_IS_OK(result)) {
926 status = result;
927 goto error;
928 }
929
930 *passwd_policy = info->info1;
931
932 error:
933 TALLOC_FREE(tmp_ctx);
934 return status;
935 }
936
937 /* Lookup groups a user is a member of. */
sam_lookup_usergroups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * user_sid,uint32_t * pnum_groups,struct dom_sid ** puser_grpsids)938 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
939 TALLOC_CTX *mem_ctx,
940 const struct dom_sid *user_sid,
941 uint32_t *pnum_groups,
942 struct dom_sid **puser_grpsids)
943 {
944 struct rpc_pipe_client *samr_pipe;
945 struct policy_handle dom_pol;
946 struct dom_sid *user_grpsids = NULL;
947 uint32_t num_groups = 0;
948 TALLOC_CTX *tmp_ctx;
949 NTSTATUS status;
950 bool retry = false;
951
952 DEBUG(3,("sam_lookup_usergroups\n"));
953
954 ZERO_STRUCT(dom_pol);
955
956 if (pnum_groups) {
957 *pnum_groups = 0;
958 }
959
960 tmp_ctx = talloc_stackframe();
961 if (tmp_ctx == NULL) {
962 return NT_STATUS_NO_MEMORY;
963 }
964
965 again:
966 status = open_cached_internal_pipe_conn(domain,
967 &samr_pipe,
968 &dom_pol,
969 NULL,
970 NULL);
971 if (!NT_STATUS_IS_OK(status)) {
972 goto done;
973 }
974
975 status = rpc_lookup_usergroups(tmp_ctx,
976 samr_pipe,
977 &dom_pol,
978 &domain->sid,
979 user_sid,
980 &num_groups,
981 &user_grpsids);
982
983 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
984 retry = true;
985 goto again;
986 }
987
988 if (!NT_STATUS_IS_OK(status)) {
989 goto done;
990 }
991
992 if (pnum_groups) {
993 *pnum_groups = num_groups;
994 }
995
996 if (puser_grpsids) {
997 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
998 }
999
1000 done:
1001
1002 TALLOC_FREE(tmp_ctx);
1003 return status;
1004 }
1005
sam_lookup_useraliases(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t num_sids,const struct dom_sid * sids,uint32_t * pnum_aliases,uint32_t ** palias_rids)1006 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1007 TALLOC_CTX *mem_ctx,
1008 uint32_t num_sids,
1009 const struct dom_sid *sids,
1010 uint32_t *pnum_aliases,
1011 uint32_t **palias_rids)
1012 {
1013 struct rpc_pipe_client *samr_pipe;
1014 struct policy_handle dom_pol = { 0 };
1015 uint32_t num_aliases = 0;
1016 uint32_t *alias_rids = NULL;
1017 TALLOC_CTX *tmp_ctx;
1018 NTSTATUS status;
1019 bool retry = false;
1020
1021 DEBUG(3,("sam_lookup_useraliases\n"));
1022
1023 if (pnum_aliases) {
1024 *pnum_aliases = 0;
1025 }
1026
1027 tmp_ctx = talloc_stackframe();
1028 if (tmp_ctx == NULL) {
1029 return NT_STATUS_NO_MEMORY;
1030 }
1031
1032 again:
1033 status = open_cached_internal_pipe_conn(domain,
1034 &samr_pipe,
1035 &dom_pol,
1036 NULL,
1037 NULL);
1038 if (!NT_STATUS_IS_OK(status)) {
1039 goto done;
1040 }
1041
1042 status = rpc_lookup_useraliases(tmp_ctx,
1043 samr_pipe,
1044 &dom_pol,
1045 num_sids,
1046 sids,
1047 &num_aliases,
1048 &alias_rids);
1049
1050 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1051 retry = true;
1052 goto again;
1053 }
1054
1055 if (!NT_STATUS_IS_OK(status)) {
1056 goto done;
1057 }
1058
1059 if (pnum_aliases) {
1060 *pnum_aliases = num_aliases;
1061 }
1062
1063 if (palias_rids) {
1064 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1065 }
1066
1067 done:
1068
1069 TALLOC_FREE(tmp_ctx);
1070 return status;
1071 }
1072
1073 /* find the sequence number for a domain */
sam_sequence_number(struct winbindd_domain * domain,uint32_t * pseq)1074 static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
1075 uint32_t *pseq)
1076 {
1077 struct rpc_pipe_client *samr_pipe;
1078 struct policy_handle dom_pol = { 0 };
1079 uint32_t seq = DOM_SEQUENCE_NONE;
1080 TALLOC_CTX *tmp_ctx;
1081 NTSTATUS status;
1082 bool retry = false;
1083
1084 DEBUG(3,("samr: sequence number\n"));
1085
1086 if (pseq) {
1087 *pseq = DOM_SEQUENCE_NONE;
1088 }
1089
1090 tmp_ctx = talloc_stackframe();
1091 if (tmp_ctx == NULL) {
1092 return NT_STATUS_NO_MEMORY;
1093 }
1094
1095 again:
1096 status = open_cached_internal_pipe_conn(domain,
1097 &samr_pipe,
1098 &dom_pol,
1099 NULL,
1100 NULL);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 goto done;
1103 }
1104
1105 status = rpc_sequence_number(tmp_ctx,
1106 samr_pipe,
1107 &dom_pol,
1108 domain->name,
1109 &seq);
1110
1111 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1112 retry = true;
1113 goto again;
1114 }
1115
1116 if (!NT_STATUS_IS_OK(status)) {
1117 goto done;
1118 }
1119
1120 if (pseq) {
1121 *pseq = seq;
1122 }
1123
1124 done:
1125 TALLOC_FREE(tmp_ctx);
1126 return status;
1127 }
1128
1129 /* the rpc backend methods are exposed via this structure */
1130 struct winbindd_methods builtin_passdb_methods = {
1131 .consistent = false,
1132
1133 .query_user_list = builtin_query_user_list,
1134 .enum_dom_groups = builtin_enum_dom_groups,
1135 .enum_local_groups = sam_enum_local_groups,
1136 .name_to_sid = sam_name_to_sid,
1137 .sid_to_name = sam_sid_to_name,
1138 .rids_to_names = sam_rids_to_names,
1139 .lookup_usergroups = sam_lookup_usergroups,
1140 .lookup_useraliases = sam_lookup_useraliases,
1141 .lookup_groupmem = sam_lookup_groupmem,
1142 .sequence_number = sam_sequence_number,
1143 .lockout_policy = sam_lockout_policy,
1144 .password_policy = sam_password_policy,
1145 .trusted_domains = builtin_trusted_domains
1146 };
1147
1148 /* the rpc backend methods are exposed via this structure */
1149 struct winbindd_methods sam_passdb_methods = {
1150 .consistent = false,
1151
1152 .query_user_list = sam_query_user_list,
1153 .enum_dom_groups = sam_enum_dom_groups,
1154 .enum_local_groups = sam_enum_local_groups,
1155 .name_to_sid = sam_name_to_sid,
1156 .sid_to_name = sam_sid_to_name,
1157 .rids_to_names = sam_rids_to_names,
1158 .lookup_usergroups = sam_lookup_usergroups,
1159 .lookup_useraliases = sam_lookup_useraliases,
1160 .lookup_groupmem = sam_lookup_groupmem,
1161 .sequence_number = sam_sequence_number,
1162 .lockout_policy = sam_lockout_policy,
1163 .password_policy = sam_password_policy,
1164 .trusted_domains = sam_trusted_domains
1165 };
1166