s3-winbind: Implemented samr backend function sam_query_user.
[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 "../librpc/gen_ndr/cli_samr.h"
29 #include "rpc_client/cli_samr.h"
30 #include "../librpc/gen_ndr/srv_samr.h"
31 #include "../librpc/gen_ndr/cli_lsa.h"
32 #include "rpc_client/cli_lsarpc.h"
33 #include "../librpc/gen_ndr/srv_lsa.h"
34
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_WINBIND
37
38 static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
39                                         struct rpc_pipe_client **samr_pipe)
40 {
41         static struct rpc_pipe_client *cli = NULL;
42         struct auth_serversupplied_info *server_info = NULL;
43         NTSTATUS status;
44
45         if (cli != NULL) {
46                 goto done;
47         }
48
49         if (server_info == NULL) {
50                 status = make_server_info_system(mem_ctx, &server_info);
51                 if (!NT_STATUS_IS_OK(status)) {
52                         DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
53                                   nt_errstr(status)));
54                         return status;
55                 }
56         }
57
58         /* create a samr connection */
59         status = rpc_pipe_open_internal(talloc_autofree_context(),
60                                         &ndr_table_samr.syntax_id,
61                                         rpc_samr_dispatch,
62                                         server_info,
63                                         &cli);
64         if (!NT_STATUS_IS_OK(status)) {
65                 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
66                           nt_errstr(status)));
67                 return status;
68         }
69
70 done:
71         if (samr_pipe) {
72                 *samr_pipe = cli;
73         }
74
75         return NT_STATUS_OK;
76 }
77
78 static NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
79                                         struct winbindd_domain *domain,
80                                         struct rpc_pipe_client **samr_pipe,
81                                         struct policy_handle *samr_domain_hnd)
82 {
83         NTSTATUS status;
84         struct policy_handle samr_connect_hnd;
85
86         status = open_internal_samr_pipe(mem_ctx, samr_pipe);
87         if (!NT_STATUS_IS_OK(status)) {
88                 return status;
89         }
90
91         status = rpccli_samr_Connect2((*samr_pipe),
92                                       mem_ctx,
93                                       (*samr_pipe)->desthost,
94                                       SEC_FLAG_MAXIMUM_ALLOWED,
95                                       &samr_connect_hnd);
96         if (!NT_STATUS_IS_OK(status)) {
97                 return status;
98         }
99
100         status = rpccli_samr_OpenDomain((*samr_pipe),
101                                         mem_ctx,
102                                         &samr_connect_hnd,
103                                         SEC_FLAG_MAXIMUM_ALLOWED,
104                                         &domain->sid,
105                                         samr_domain_hnd);
106
107         return status;
108 }
109
110 static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx,
111                                        struct rpc_pipe_client **lsa_pipe)
112 {
113         static struct rpc_pipe_client *cli = NULL;
114         struct auth_serversupplied_info *server_info = NULL;
115         NTSTATUS status;
116
117         if (cli != NULL) {
118                 goto done;
119         }
120
121         if (server_info == NULL) {
122                 status = make_server_info_system(mem_ctx, &server_info);
123                 if (!NT_STATUS_IS_OK(status)) {
124                         DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
125                                   nt_errstr(status)));
126                         return status;
127                 }
128         }
129
130         /* create a samr connection */
131         status = rpc_pipe_open_internal(talloc_autofree_context(),
132                                         &ndr_table_lsarpc.syntax_id,
133                                         rpc_lsarpc_dispatch,
134                                         server_info,
135                                         &cli);
136         if (!NT_STATUS_IS_OK(status)) {
137                 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
138                           nt_errstr(status)));
139                 return status;
140         }
141
142 done:
143         if (lsa_pipe) {
144                 *lsa_pipe = cli;
145         }
146
147         return NT_STATUS_OK;
148 }
149
150 static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
151                                        struct rpc_pipe_client **lsa_pipe,
152                                        struct policy_handle *lsa_hnd)
153 {
154         NTSTATUS status;
155
156         status = open_internal_lsa_pipe(mem_ctx, lsa_pipe);
157         if (!NT_STATUS_IS_OK(status)) {
158                 return status;
159         }
160
161         status = rpccli_lsa_open_policy((*lsa_pipe),
162                                         mem_ctx,
163                                         true,
164                                         SEC_FLAG_MAXIMUM_ALLOWED,
165                                         lsa_hnd);
166
167         return status;
168 }
169
170 /*********************************************************************
171  SAM specific functions.
172 *********************************************************************/
173
174 /* List all domain groups */
175 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
176                                     TALLOC_CTX *mem_ctx,
177                                     uint32_t *pnum_info,
178                                     struct acct_info **pinfo)
179 {
180         struct rpc_pipe_client *samr_pipe;
181         struct policy_handle dom_pol;
182         struct acct_info *info = NULL;
183         TALLOC_CTX *tmp_ctx;
184         uint32_t start = 0;
185         uint32_t num_info = 0;
186         NTSTATUS status;
187
188         DEBUG(3,("samr: query_user_list\n"));
189
190         if (pnum_info) {
191                 *pnum_info = 0;
192         }
193
194         tmp_ctx = talloc_stackframe();
195         if (tmp_ctx == NULL) {
196                 return NT_STATUS_NO_MEMORY;
197         }
198
199         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
200         if (!NT_STATUS_IS_OK(status)) {
201                 goto error;
202         }
203
204         do {
205                 struct samr_SamArray *sam_array = NULL;
206                 uint32_t count = 0;
207                 uint32_t g;
208
209                 /* start is updated by this call. */
210                 status = rpccli_samr_EnumDomainGroups(samr_pipe,
211                                                       tmp_ctx,
212                                                       &dom_pol,
213                                                       &start,
214                                                       &sam_array,
215                                                       0xFFFF, /* buffer size? */
216                                                       &count);
217                 if (!NT_STATUS_IS_OK(status)) {
218                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
219                                 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
220                                          nt_errstr(status)));
221                                 goto error;
222                         }
223                 }
224
225                 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
226                                             info,
227                                             struct acct_info,
228                                             num_info + count);
229                 if (info == NULL) {
230                         status = NT_STATUS_NO_MEMORY;
231                         goto error;
232                 }
233
234                 for (g = 0; g < count; g++) {
235                         fstrcpy(info[num_info + g].acct_name,
236                                 sam_array->entries[g].name.string);
237
238                         info[num_info + g].rid = sam_array->entries[g].idx;
239                 }
240
241                 num_info += count;
242         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
243
244         if (pnum_info) {
245                 *pnum_info = num_info;
246         }
247
248         if (pinfo) {
249                 *pinfo = talloc_move(mem_ctx, &info);
250         }
251
252 error:
253         TALLOC_FREE(tmp_ctx);
254         return status;
255 }
256
257 /* Query display info for a domain */
258 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
259                                     TALLOC_CTX *mem_ctx,
260                                     uint32_t *pnum_info,
261                                     struct wbint_userinfo **pinfo)
262 {
263         struct rpc_pipe_client *samr_pipe = NULL;
264         struct wbint_userinfo *info = NULL;
265         struct policy_handle dom_pol;
266         uint32_t num_info = 0;
267         uint32_t loop_count = 0;
268         uint32_t start_idx = 0;
269         uint32_t i = 0;
270         TALLOC_CTX *tmp_ctx;
271         NTSTATUS status;
272
273         DEBUG(3,("samr: query_user_list\n"));
274
275         if (pnum_info) {
276                 *pnum_info = 0;
277         }
278
279         tmp_ctx = talloc_stackframe();
280         if (tmp_ctx == NULL) {
281                 return NT_STATUS_NO_MEMORY;
282         }
283
284         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
285         if (!NT_STATUS_IS_OK(status)) {
286                 goto error;
287         }
288
289         do {
290                 uint32_t j;
291                 uint32_t num_dom_users;
292                 uint32_t max_entries, max_size;
293                 uint32_t total_size, returned_size;
294                 union samr_DispInfo disp_info;
295
296                 get_query_dispinfo_params(loop_count,
297                                           &max_entries,
298                                           &max_size);
299
300                 status = rpccli_samr_QueryDisplayInfo(samr_pipe,
301                                                       tmp_ctx,
302                                                       &dom_pol,
303                                                       1, /* level */
304                                                       start_idx,
305                                                       max_entries,
306                                                       max_size,
307                                                       &total_size,
308                                                       &returned_size,
309                                                       &disp_info);
310                 if (!NT_STATUS_IS_OK(status)) {
311                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
312                                 goto error;
313                         }
314                 }
315
316                 /* increment required start query values */
317                 start_idx += disp_info.info1.count;
318                 loop_count++;
319                 num_dom_users = disp_info.info1.count;
320
321                 num_info += num_dom_users;
322
323                 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
324                                             info,
325                                             struct wbint_userinfo,
326                                             num_info);
327                 if (info == NULL) {
328                         status = NT_STATUS_NO_MEMORY;
329                         goto error;
330                 }
331
332                 for (j = 0; j < num_dom_users; i++, j++) {
333                         uint32_t rid = disp_info.info1.entries[j].rid;
334                         struct samr_DispEntryGeneral *src;
335                         struct wbint_userinfo *dst;
336
337                         src = &(disp_info.info1.entries[j]);
338                         dst = &(info[i]);
339
340                         dst->acct_name = talloc_strdup(info,
341                                                        src->account_name.string);
342                         if (dst->acct_name == NULL) {
343                                 status = NT_STATUS_NO_MEMORY;
344                                 goto error;
345                         }
346
347                         dst->full_name = talloc_strdup(info, src->full_name.string);
348                         if (dst->full_name == NULL) {
349                                 status = NT_STATUS_NO_MEMORY;
350                                 goto error;
351                         }
352
353                         dst->homedir = NULL;
354                         dst->shell = NULL;
355
356                         sid_compose(&dst->user_sid, &domain->sid, rid);
357
358                         /* For the moment we set the primary group for
359                            every user to be the Domain Users group.
360                            There are serious problems with determining
361                            the actual primary group for large domains.
362                            This should really be made into a 'winbind
363                            force group' smb.conf parameter or
364                            something like that. */
365                         sid_compose(&dst->group_sid, &domain->sid,
366                                     DOMAIN_RID_USERS);
367                 }
368         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
369
370         if (pnum_info) {
371                 *pnum_info = num_info;
372         }
373
374         if (pinfo) {
375                 *pinfo = talloc_move(mem_ctx, &info);
376         }
377
378 error:
379         TALLOC_FREE(tmp_ctx);
380         return status;
381 }
382
383 /* Lookup user information from a rid or username. */
384 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
385                                TALLOC_CTX *mem_ctx,
386                                const struct dom_sid *user_sid,
387                                struct wbint_userinfo *user_info)
388 {
389         struct rpc_pipe_client *samr_pipe;
390         struct policy_handle dom_pol, user_pol;
391         union samr_UserInfo *info = NULL;
392         TALLOC_CTX *tmp_ctx;
393         uint32_t user_rid;
394         NTSTATUS status;
395
396         DEBUG(3,("samr: query_user\n"));
397
398         if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
399                 return NT_STATUS_UNSUCCESSFUL;
400         }
401
402         if (user_info) {
403                 user_info->homedir = NULL;
404                 user_info->shell = NULL;
405                 user_info->primary_gid = (gid_t) -1;
406         }
407
408         tmp_ctx = talloc_stackframe();
409         if (tmp_ctx == NULL) {
410                 return NT_STATUS_NO_MEMORY;
411         }
412
413         status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
414         if (!NT_STATUS_IS_OK(status)) {
415                 goto error;
416         }
417
418         /* Get user handle */
419         status = rpccli_samr_OpenUser(samr_pipe,
420                                       tmp_ctx,
421                                       &dom_pol,
422                                       SEC_FLAG_MAXIMUM_ALLOWED,
423                                       user_rid,
424                                       &user_pol);
425         if (!NT_STATUS_IS_OK(status)) {
426                 goto error;
427         }
428
429         /* Get user info */
430         status = rpccli_samr_QueryUserInfo(samr_pipe,
431                                            tmp_ctx,
432                                            &user_pol,
433                                            0x15,
434                                            &info);
435
436         rpccli_samr_Close(samr_pipe, tmp_ctx, &user_pol);
437
438         if (!NT_STATUS_IS_OK(status)) {
439                 goto error;
440         }
441
442         sid_compose(&user_info->user_sid, &domain->sid, user_rid);
443         sid_compose(&user_info->group_sid, &domain->sid,
444                     info->info21.primary_gid);
445
446         if (user_info) {
447                 user_info->acct_name = talloc_strdup(mem_ctx,
448                                                      info->info21.account_name.string);
449                 if (user_info->acct_name == NULL) {
450                         status = NT_STATUS_NO_MEMORY;
451                         goto error;
452                 }
453
454                 user_info->full_name = talloc_strdup(mem_ctx,
455                                                      info->info21.full_name.string);
456                 if (user_info->acct_name == NULL) {
457                         status = NT_STATUS_NO_MEMORY;
458                         goto error;
459                 }
460
461                 user_info->homedir = NULL;
462                 user_info->shell = NULL;
463                 user_info->primary_gid = (gid_t)-1;
464         }
465
466         status = NT_STATUS_OK;
467 error:
468         TALLOC_FREE(tmp_ctx);
469         return status;
470 }
471
472 /* get a list of trusted domains - builtin domain */
473 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
474                                     TALLOC_CTX *mem_ctx,
475                                     struct netr_DomainTrustList *trusts)
476 {
477         /* TODO FIXME */
478         return NT_STATUS_NOT_IMPLEMENTED;
479 }
480
481 /* Lookup group membership given a rid.   */
482 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
483                                     TALLOC_CTX *mem_ctx,
484                                     const struct dom_sid *group_sid,
485                                     enum lsa_SidType type,
486                                     uint32_t *num_names,
487                                     struct dom_sid **sid_mem,
488                                     char ***names,
489                                     uint32_t **name_types)
490 {
491         /* TODO FIXME */
492         return NT_STATUS_NOT_IMPLEMENTED;
493 }
494
495 /*********************************************************************
496  BUILTIN specific functions.
497 *********************************************************************/
498
499 /* List all domain groups */
500 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
501                                 TALLOC_CTX *mem_ctx,
502                                 uint32 *num_entries,
503                                 struct acct_info **info)
504 {
505         /* BUILTIN doesn't have domain groups */
506         *num_entries = 0;
507         *info = NULL;
508         return NT_STATUS_OK;
509 }
510
511 /* Query display info for a domain */
512 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
513                                 TALLOC_CTX *mem_ctx,
514                                 uint32 *num_entries,
515                                 struct wbint_userinfo **info)
516 {
517         /* We don't have users */
518         *num_entries = 0;
519         *info = NULL;
520         return NT_STATUS_OK;
521 }
522
523 /* Lookup user information from a rid or username. */
524 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
525                                 TALLOC_CTX *mem_ctx,
526                                 const struct dom_sid *user_sid,
527                                 struct wbint_userinfo *user_info)
528 {
529         return NT_STATUS_NO_SUCH_USER;
530 }
531
532 /* get a list of trusted domains - builtin domain */
533 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
534                                         TALLOC_CTX *mem_ctx,
535                                         struct netr_DomainTrustList *trusts)
536 {
537         ZERO_STRUCTP(trusts);
538         return NT_STATUS_OK;
539 }
540
541 /*********************************************************************
542  COMMON functions.
543 *********************************************************************/
544
545 /* List all local groups (aliases) */
546 static NTSTATUS common_enum_local_groups(struct winbindd_domain *domain,
547                                          TALLOC_CTX *mem_ctx,
548                                          uint32_t *num_entries,
549                                          struct acct_info **info)
550 {
551         /* TODO FIXME */
552         return NT_STATUS_NOT_IMPLEMENTED;
553 }
554
555 /* convert a single name to a sid in a domain */
556 static NTSTATUS common_name_to_sid(struct winbindd_domain *domain,
557                                    TALLOC_CTX *mem_ctx,
558                                    const char *domain_name,
559                                    const char *name,
560                                    uint32_t flags,
561                                    struct dom_sid *sid,
562                                    enum lsa_SidType *type)
563 {
564         /* TODO FIXME */
565         return NT_STATUS_NOT_IMPLEMENTED;
566 }
567
568 /* convert a domain SID to a user or group name */
569 static NTSTATUS common_sid_to_name(struct winbindd_domain *domain,
570                                    TALLOC_CTX *mem_ctx,
571                                    const struct dom_sid *sid,
572                                    char **domain_name,
573                                    char **name,
574                                    enum lsa_SidType *type)
575 {
576         /* TODO FIXME */
577         return NT_STATUS_NOT_IMPLEMENTED;
578 }
579
580 static NTSTATUS common_rids_to_names(struct winbindd_domain *domain,
581                                      TALLOC_CTX *mem_ctx,
582                                      const struct dom_sid *sid,
583                                      uint32 *rids,
584                                      size_t num_rids,
585                                      char **domain_name,
586                                      char ***names,
587                                      enum lsa_SidType **types)
588 {
589         /* TODO FIXME */
590         return NT_STATUS_NOT_IMPLEMENTED;
591 }
592
593 static NTSTATUS common_lockout_policy(struct winbindd_domain *domain,
594                                       TALLOC_CTX *mem_ctx,
595                                       struct samr_DomInfo12 *policy)
596 {
597         /* TODO FIXME */
598         return NT_STATUS_NOT_IMPLEMENTED;
599 }
600
601 static NTSTATUS common_password_policy(struct winbindd_domain *domain,
602                                        TALLOC_CTX *mem_ctx,
603                                        struct samr_DomInfo1 *policy)
604 {
605         /* TODO FIXME */
606         return NT_STATUS_NOT_IMPLEMENTED;
607 }
608
609 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
610 static NTSTATUS common_lookup_usergroups(struct winbindd_domain *domain,
611                                          TALLOC_CTX *mem_ctx,
612                                          const struct dom_sid *user_sid,
613                                          uint32_t *num_groups,
614                                          struct dom_sid **user_gids)
615 {
616         /* TODO FIXME */
617         return NT_STATUS_NOT_IMPLEMENTED;
618 }
619
620 static NTSTATUS common_lookup_useraliases(struct winbindd_domain *domain,
621                                           TALLOC_CTX *mem_ctx,
622                                           uint32_t num_sids,
623                                           const struct dom_sid *sids,
624                                           uint32_t *p_num_aliases,
625                                           uint32_t **rids)
626 {
627         /* TODO FIXME */
628         return NT_STATUS_NOT_IMPLEMENTED;
629 }
630
631 /* find the sequence number for a domain */
632 static NTSTATUS common_sequence_number(struct winbindd_domain *domain,
633                                        uint32_t *seq)
634 {
635         /* TODO FIXME */
636         return NT_STATUS_NOT_IMPLEMENTED;
637 }
638
639 #if 0
640 /* the rpc backend methods are exposed via this structure */
641 struct winbindd_methods builtin_passdb_methods = {
642         .consistent            = false,
643
644         .query_user_list       = builtin_query_user_list,
645         .enum_dom_groups       = builtin_enum_dom_groups,
646         .enum_local_groups     = common_enum_local_groups,
647         .name_to_sid           = common_name_to_sid,
648         .sid_to_name           = common_sid_to_name,
649         .rids_to_names         = common_rids_to_names,
650         .query_user            = builtin_query_user,
651         .lookup_usergroups     = common_lookup_usergroups,
652         .lookup_useraliases    = common_lookup_useraliases,
653         .lookup_groupmem       = sam_lookup_groupmem,
654         .sequence_number       = common_sequence_number,
655         .lockout_policy        = common_lockout_policy,
656         .password_policy       = common_password_policy,
657         .trusted_domains       = builtin_trusted_domains
658 };
659
660 /* the rpc backend methods are exposed via this structure */
661 struct winbindd_methods sam_passdb_methods = {
662         .consistent            = false,
663
664         .query_user_list       = sam_query_user_list,
665         .enum_dom_groups       = sam_enum_dom_groups,
666         .enum_local_groups     = common_enum_local_groups,
667         .name_to_sid           = common_name_to_sid,
668         .sid_to_name           = common_sid_to_name,
669         .rids_to_names         = common_rids_to_names,
670         .query_user            = sam_query_user,
671         .lookup_usergroups     = common_lookup_usergroups,
672         .lookup_useraliases    = common_lookup_useraliases,
673         .lookup_groupmem       = sam_lookup_groupmem,
674         .sequence_number       = common_sequence_number,
675         .lockout_policy        = common_lockout_policy,
676         .password_policy       = common_password_policy,
677         .trusted_domains       = sam_trusted_domains
678 };
679 #endif