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