s3-winbind: Implemented samr backend function sam_enum_dom_groups.
[kai/samba-autobuild/.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         /* TODO FIXME */
390         return NT_STATUS_NOT_IMPLEMENTED;
391 }
392
393 /* get a list of trusted domains - builtin domain */
394 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
395                                     TALLOC_CTX *mem_ctx,
396                                     struct netr_DomainTrustList *trusts)
397 {
398         /* TODO FIXME */
399         return NT_STATUS_NOT_IMPLEMENTED;
400 }
401
402 /* Lookup group membership given a rid.   */
403 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
404                                     TALLOC_CTX *mem_ctx,
405                                     const struct dom_sid *group_sid,
406                                     enum lsa_SidType type,
407                                     uint32_t *num_names,
408                                     struct dom_sid **sid_mem,
409                                     char ***names,
410                                     uint32_t **name_types)
411 {
412         /* TODO FIXME */
413         return NT_STATUS_NOT_IMPLEMENTED;
414 }
415
416 /*********************************************************************
417  BUILTIN specific functions.
418 *********************************************************************/
419
420 /* List all domain groups */
421 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
422                                 TALLOC_CTX *mem_ctx,
423                                 uint32 *num_entries,
424                                 struct acct_info **info)
425 {
426         /* BUILTIN doesn't have domain groups */
427         *num_entries = 0;
428         *info = NULL;
429         return NT_STATUS_OK;
430 }
431
432 /* Query display info for a domain */
433 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
434                                 TALLOC_CTX *mem_ctx,
435                                 uint32 *num_entries,
436                                 struct wbint_userinfo **info)
437 {
438         /* We don't have users */
439         *num_entries = 0;
440         *info = NULL;
441         return NT_STATUS_OK;
442 }
443
444 /* Lookup user information from a rid or username. */
445 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
446                                 TALLOC_CTX *mem_ctx,
447                                 const struct dom_sid *user_sid,
448                                 struct wbint_userinfo *user_info)
449 {
450         return NT_STATUS_NO_SUCH_USER;
451 }
452
453 /* get a list of trusted domains - builtin domain */
454 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
455                                         TALLOC_CTX *mem_ctx,
456                                         struct netr_DomainTrustList *trusts)
457 {
458         ZERO_STRUCTP(trusts);
459         return NT_STATUS_OK;
460 }
461
462 /*********************************************************************
463  COMMON functions.
464 *********************************************************************/
465
466 /* List all local groups (aliases) */
467 static NTSTATUS common_enum_local_groups(struct winbindd_domain *domain,
468                                          TALLOC_CTX *mem_ctx,
469                                          uint32_t *num_entries,
470                                          struct acct_info **info)
471 {
472         /* TODO FIXME */
473         return NT_STATUS_NOT_IMPLEMENTED;
474 }
475
476 /* convert a single name to a sid in a domain */
477 static NTSTATUS common_name_to_sid(struct winbindd_domain *domain,
478                                    TALLOC_CTX *mem_ctx,
479                                    const char *domain_name,
480                                    const char *name,
481                                    uint32_t flags,
482                                    struct dom_sid *sid,
483                                    enum lsa_SidType *type)
484 {
485         /* TODO FIXME */
486         return NT_STATUS_NOT_IMPLEMENTED;
487 }
488
489 /* convert a domain SID to a user or group name */
490 static NTSTATUS common_sid_to_name(struct winbindd_domain *domain,
491                                    TALLOC_CTX *mem_ctx,
492                                    const struct dom_sid *sid,
493                                    char **domain_name,
494                                    char **name,
495                                    enum lsa_SidType *type)
496 {
497         /* TODO FIXME */
498         return NT_STATUS_NOT_IMPLEMENTED;
499 }
500
501 static NTSTATUS common_rids_to_names(struct winbindd_domain *domain,
502                                      TALLOC_CTX *mem_ctx,
503                                      const struct dom_sid *sid,
504                                      uint32 *rids,
505                                      size_t num_rids,
506                                      char **domain_name,
507                                      char ***names,
508                                      enum lsa_SidType **types)
509 {
510         /* TODO FIXME */
511         return NT_STATUS_NOT_IMPLEMENTED;
512 }
513
514 static NTSTATUS common_lockout_policy(struct winbindd_domain *domain,
515                                       TALLOC_CTX *mem_ctx,
516                                       struct samr_DomInfo12 *policy)
517 {
518         /* TODO FIXME */
519         return NT_STATUS_NOT_IMPLEMENTED;
520 }
521
522 static NTSTATUS common_password_policy(struct winbindd_domain *domain,
523                                        TALLOC_CTX *mem_ctx,
524                                        struct samr_DomInfo1 *policy)
525 {
526         /* TODO FIXME */
527         return NT_STATUS_NOT_IMPLEMENTED;
528 }
529
530 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
531 static NTSTATUS common_lookup_usergroups(struct winbindd_domain *domain,
532                                          TALLOC_CTX *mem_ctx,
533                                          const struct dom_sid *user_sid,
534                                          uint32_t *num_groups,
535                                          struct dom_sid **user_gids)
536 {
537         /* TODO FIXME */
538         return NT_STATUS_NOT_IMPLEMENTED;
539 }
540
541 static NTSTATUS common_lookup_useraliases(struct winbindd_domain *domain,
542                                           TALLOC_CTX *mem_ctx,
543                                           uint32_t num_sids,
544                                           const struct dom_sid *sids,
545                                           uint32_t *p_num_aliases,
546                                           uint32_t **rids)
547 {
548         /* TODO FIXME */
549         return NT_STATUS_NOT_IMPLEMENTED;
550 }
551
552 /* find the sequence number for a domain */
553 static NTSTATUS common_sequence_number(struct winbindd_domain *domain,
554                                        uint32_t *seq)
555 {
556         /* TODO FIXME */
557         return NT_STATUS_NOT_IMPLEMENTED;
558 }
559
560 #if 0
561 /* the rpc backend methods are exposed via this structure */
562 struct winbindd_methods builtin_passdb_methods = {
563         .consistent            = false,
564
565         .query_user_list       = builtin_query_user_list,
566         .enum_dom_groups       = builtin_enum_dom_groups,
567         .enum_local_groups     = common_enum_local_groups,
568         .name_to_sid           = common_name_to_sid,
569         .sid_to_name           = common_sid_to_name,
570         .rids_to_names         = common_rids_to_names,
571         .query_user            = builtin_query_user,
572         .lookup_usergroups     = common_lookup_usergroups,
573         .lookup_useraliases    = common_lookup_useraliases,
574         .lookup_groupmem       = sam_lookup_groupmem,
575         .sequence_number       = common_sequence_number,
576         .lockout_policy        = common_lockout_policy,
577         .password_policy       = common_password_policy,
578         .trusted_domains       = builtin_trusted_domains
579 };
580
581 /* the rpc backend methods are exposed via this structure */
582 struct winbindd_methods sam_passdb_methods = {
583         .consistent            = false,
584
585         .query_user_list       = sam_query_user_list,
586         .enum_dom_groups       = sam_enum_dom_groups,
587         .enum_local_groups     = common_enum_local_groups,
588         .name_to_sid           = common_name_to_sid,
589         .sid_to_name           = common_sid_to_name,
590         .rids_to_names         = common_rids_to_names,
591         .query_user            = sam_query_user,
592         .lookup_usergroups     = common_lookup_usergroups,
593         .lookup_useraliases    = common_lookup_useraliases,
594         .lookup_groupmem       = sam_lookup_groupmem,
595         .sequence_number       = common_sequence_number,
596         .lockout_policy        = common_lockout_policy,
597         .password_policy       = common_password_policy,
598         .trusted_domains       = sam_trusted_domains
599 };
600 #endif