s3-winbind: Added a common rpc_enum_local_groups function.
[samba.git] / source3 / winbindd / winbindd_rpc.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
30 #include "librpc/gen_ndr/cli_samr.h"
31 #include "librpc/gen_ndr/srv_samr.h"
32 #include "librpc/gen_ndr/cli_lsa.h"
33 #include "librpc/gen_ndr/srv_lsa.h"
34 #include "rpc_client/cli_samr.h"
35 #include "rpc_client/cli_lsarpc.h"
36
37 /* Query display info for a domain */
38 NTSTATUS rpc_query_user_list(TALLOC_CTX *mem_ctx,
39                              struct rpc_pipe_client *samr_pipe,
40                              struct policy_handle *samr_policy,
41                              const struct dom_sid *domain_sid,
42                              uint32_t *pnum_info,
43                              struct wbint_userinfo **pinfo)
44 {
45         struct wbint_userinfo *info = NULL;
46         uint32_t num_info = 0;
47         uint32_t loop_count = 0;
48         uint32_t start_idx = 0;
49         uint32_t i = 0;
50         NTSTATUS status;
51
52         *pnum_info = 0;
53
54         do {
55                 uint32_t j;
56                 uint32_t num_dom_users;
57                 uint32_t max_entries, max_size;
58                 uint32_t total_size, returned_size;
59                 union samr_DispInfo disp_info;
60
61                 get_query_dispinfo_params(loop_count,
62                                           &max_entries,
63                                           &max_size);
64
65                 status = rpccli_samr_QueryDisplayInfo(samr_pipe,
66                                                       mem_ctx,
67                                                       samr_policy,
68                                                       1, /* level */
69                                                       start_idx,
70                                                       max_entries,
71                                                       max_size,
72                                                       &total_size,
73                                                       &returned_size,
74                                                       &disp_info);
75                 if (!NT_STATUS_IS_OK(status)) {
76                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
77                                 return status;
78                         }
79                 }
80
81                 /* increment required start query values */
82                 start_idx += disp_info.info1.count;
83                 loop_count++;
84                 num_dom_users = disp_info.info1.count;
85
86                 num_info += num_dom_users;
87
88                 info = TALLOC_REALLOC_ARRAY(mem_ctx,
89                                             info,
90                                             struct wbint_userinfo,
91                                             num_info);
92                 if (info == NULL) {
93                         return NT_STATUS_NO_MEMORY;
94                 }
95
96                 for (j = 0; j < num_dom_users; i++, j++) {
97                         uint32_t rid = disp_info.info1.entries[j].rid;
98                         struct samr_DispEntryGeneral *src;
99                         struct wbint_userinfo *dst;
100
101                         src = &(disp_info.info1.entries[j]);
102                         dst = &(info[i]);
103
104                         dst->acct_name = talloc_strdup(info,
105                                                        src->account_name.string);
106                         if (dst->acct_name == NULL) {
107                                 return NT_STATUS_NO_MEMORY;
108                         }
109
110                         dst->full_name = talloc_strdup(info, src->full_name.string);
111                         if (dst->full_name == NULL) {
112                                 return NT_STATUS_NO_MEMORY;
113                         }
114
115                         dst->homedir = NULL;
116                         dst->shell = NULL;
117
118                         sid_compose(&dst->user_sid, domain_sid, rid);
119
120                         /* For the moment we set the primary group for
121                            every user to be the Domain Users group.
122                            There are serious problems with determining
123                            the actual primary group for large domains.
124                            This should really be made into a 'winbind
125                            force group' smb.conf parameter or
126                            something like that. */
127                         sid_compose(&dst->group_sid, domain_sid,
128                                     DOMAIN_RID_USERS);
129                 }
130         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
131
132         *pnum_info = num_info;
133         *pinfo = info;
134
135         return NT_STATUS_OK;
136 }
137
138 /* List all domain groups */
139 NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
140                              struct rpc_pipe_client *samr_pipe,
141                              struct policy_handle *samr_policy,
142                              uint32_t *pnum_info,
143                              struct acct_info **pinfo)
144 {
145         struct acct_info *info = NULL;
146         uint32_t start = 0;
147         uint32_t num_info = 0;
148         NTSTATUS status;
149
150         *pnum_info = 0;
151
152         do {
153                 struct samr_SamArray *sam_array = NULL;
154                 uint32_t count = 0;
155                 uint32_t g;
156
157                 /* start is updated by this call. */
158                 status = rpccli_samr_EnumDomainGroups(samr_pipe,
159                                                       mem_ctx,
160                                                       samr_policy,
161                                                       &start,
162                                                       &sam_array,
163                                                       0xFFFF, /* buffer size? */
164                                                       &count);
165                 if (!NT_STATUS_IS_OK(status)) {
166                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
167                                 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
168                                          nt_errstr(status)));
169                                 return status;
170                         }
171                 }
172
173                 info = TALLOC_REALLOC_ARRAY(mem_ctx,
174                                             info,
175                                             struct acct_info,
176                                             num_info + count);
177                 if (info == NULL) {
178                         return NT_STATUS_NO_MEMORY;
179                 }
180
181                 for (g = 0; g < count; g++) {
182                         fstrcpy(info[num_info + g].acct_name,
183                                 sam_array->entries[g].name.string);
184
185                         info[num_info + g].rid = sam_array->entries[g].idx;
186                 }
187
188                 num_info += count;
189         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
190
191         *pnum_info = num_info;
192         *pinfo = info;
193
194         return NT_STATUS_OK;
195 }
196
197 NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
198                                struct rpc_pipe_client *samr_pipe,
199                                struct policy_handle *samr_policy,
200                                uint32_t *pnum_info,
201                                struct acct_info **pinfo)
202 {
203         struct acct_info *info = NULL;
204         uint32_t num_info = 0;
205         NTSTATUS status;
206
207         *pnum_info = 0;
208
209         do {
210                 struct samr_SamArray *sam_array = NULL;
211                 uint32_t count = 0;
212                 uint32_t start = num_info;
213                 uint32_t g;
214
215                 status = rpccli_samr_EnumDomainAliases(samr_pipe,
216                                                        mem_ctx,
217                                                        samr_policy,
218                                                        &start,
219                                                        &sam_array,
220                                                        0xFFFF, /* buffer size? */
221                                                        &count);
222                 if (!NT_STATUS_IS_OK(status)) {
223                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
224                                 return status;
225                         }
226                 }
227
228                 info = TALLOC_REALLOC_ARRAY(mem_ctx,
229                                             info,
230                                             struct acct_info,
231                                             num_info + count);
232                 if (info == NULL) {
233                         return  NT_STATUS_NO_MEMORY;
234                 }
235
236                 for (g = 0; g < count; g++) {
237                         fstrcpy(info[num_info + g].acct_name,
238                                 sam_array->entries[g].name.string);
239                         info[num_info + g].rid = sam_array->entries[g].idx;
240                 }
241
242                 num_info += count;
243         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
244
245         *pnum_info = num_info;
246         *pinfo = info;
247
248         return NT_STATUS_OK;
249 }