s3:winbind: Add async QueryGroupList
[ira/wip.git] / source3 / winbindd / winbindd_dual_srv.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    In-Child server implementation of the routines defined in wbint.idl
5
6    Copyright (C) Volker Lendecke 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "winbindd/winbindd.h"
24 #include "winbindd/winbindd_proto.h"
25 #include "librpc/gen_ndr/srv_wbint.h"
26
27 void _wbint_Ping(pipes_struct *p, struct wbint_Ping *r)
28 {
29         *r->out.out_data = r->in.in_data;
30 }
31
32 NTSTATUS _wbint_LookupSid(pipes_struct *p, struct wbint_LookupSid *r)
33 {
34         struct winbindd_domain *domain = wb_child_domain();
35         char *dom_name;
36         char *name;
37         enum lsa_SidType type;
38         NTSTATUS status;
39
40         if (domain == NULL) {
41                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
42         }
43
44         status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
45                                               &dom_name, &name, &type);
46         if (!NT_STATUS_IS_OK(status)) {
47                 return status;
48         }
49
50         *r->out.domain = dom_name;
51         *r->out.name = name;
52         *r->out.type = type;
53         return NT_STATUS_OK;
54 }
55
56 NTSTATUS _wbint_LookupName(pipes_struct *p, struct wbint_LookupName *r)
57 {
58         struct winbindd_domain *domain = wb_child_domain();
59
60         if (domain == NULL) {
61                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
62         }
63
64         return domain->methods->name_to_sid(
65                 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
66                 r->out.sid, r->out.type);
67 }
68
69 NTSTATUS _wbint_Sid2Uid(pipes_struct *p, struct wbint_Sid2Uid *r)
70 {
71         uid_t uid;
72         NTSTATUS status;
73
74         status = idmap_sid_to_uid(r->in.dom_name ? r->in.dom_name : "",
75                                   r->in.sid, &uid);
76         if (!NT_STATUS_IS_OK(status)) {
77                 return status;
78         }
79         *r->out.uid = uid;
80         return NT_STATUS_OK;
81 }
82
83 NTSTATUS _wbint_Sid2Gid(pipes_struct *p, struct wbint_Sid2Gid *r)
84 {
85         gid_t gid;
86         NTSTATUS status;
87
88         status = idmap_sid_to_gid(r->in.dom_name ? r->in.dom_name : "",
89                                   r->in.sid, &gid);
90         if (!NT_STATUS_IS_OK(status)) {
91                 return status;
92         }
93         *r->out.gid = gid;
94         return NT_STATUS_OK;
95 }
96
97 NTSTATUS _wbint_Uid2Sid(pipes_struct *p, struct wbint_Uid2Sid *r)
98 {
99         return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
100                                 r->out.sid, r->in.uid);
101 }
102
103 NTSTATUS _wbint_Gid2Sid(pipes_struct *p, struct wbint_Gid2Sid *r)
104 {
105         return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
106                                 r->out.sid, r->in.gid);
107 }
108
109 NTSTATUS _wbint_QueryUser(pipes_struct *p, struct wbint_QueryUser *r)
110 {
111         struct winbindd_domain *domain = wb_child_domain();
112
113         if (domain == NULL) {
114                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
115         }
116
117         return domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
118                                            r->out.info);
119 }
120
121 NTSTATUS _wbint_LookupUserAliases(pipes_struct *p,
122                                   struct wbint_LookupUserAliases *r)
123 {
124         struct winbindd_domain *domain = wb_child_domain();
125
126         if (domain == NULL) {
127                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
128         }
129
130         return domain->methods->lookup_useraliases(
131                 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
132                 &r->out.rids->num_rids, &r->out.rids->rids);
133 }
134
135 NTSTATUS _wbint_LookupUserGroups(pipes_struct *p,
136                                  struct wbint_LookupUserGroups *r)
137 {
138         struct winbindd_domain *domain = wb_child_domain();
139
140         if (domain == NULL) {
141                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
142         }
143
144         return domain->methods->lookup_usergroups(
145                 domain, p->mem_ctx, r->in.sid,
146                 &r->out.sids->num_sids, &r->out.sids->sids);
147 }
148
149 NTSTATUS _wbint_QuerySequenceNumber(pipes_struct *p,
150                                     struct wbint_QuerySequenceNumber *r)
151 {
152         struct winbindd_domain *domain = wb_child_domain();
153
154         if (domain == NULL) {
155                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
156         }
157
158         return domain->methods->sequence_number(domain, r->out.sequence);
159 }
160
161 NTSTATUS _wbint_LookupGroupMembers(pipes_struct *p,
162                                    struct wbint_LookupGroupMembers *r)
163 {
164         struct winbindd_domain *domain = wb_child_domain();
165         uint32_t i, num_names;
166         struct dom_sid *sid_mem;
167         char **names;
168         uint32_t *name_types;
169         NTSTATUS status;
170
171         if (domain == NULL) {
172                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
173         }
174
175         status = domain->methods->lookup_groupmem(
176                 domain, p->mem_ctx, r->in.sid, r->in.type,
177                 &num_names, &sid_mem, &names, &name_types);
178         if (!NT_STATUS_IS_OK(status)) {
179                 return status;
180         }
181
182         r->out.members->num_principals = num_names;
183         r->out.members->principals = talloc_array(
184                 r->out.members, struct wbint_Principal, num_names);
185         if (r->out.members->principals == NULL) {
186                 return NT_STATUS_NO_MEMORY;
187         }
188
189         for (i=0; i<num_names; i++) {
190                 struct wbint_Principal *m = &r->out.members->principals[i];
191                 sid_copy(&m->sid, &sid_mem[i]);
192                 m->name = talloc_move(r->out.members->principals, &names[i]);
193                 m->type = (enum lsa_SidType)name_types[i];
194         }
195
196         return NT_STATUS_OK;
197 }
198
199 NTSTATUS _wbint_QueryUserList(pipes_struct *p, struct wbint_QueryUserList *r)
200 {
201         struct winbindd_domain *domain = wb_child_domain();
202
203         if (domain == NULL) {
204                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
205         }
206
207         return domain->methods->query_user_list(
208                 domain, p->mem_ctx, &r->out.users->num_userinfos,
209                 &r->out.users->userinfos);
210 }
211
212 NTSTATUS _wbint_QueryGroupList(pipes_struct *p, struct wbint_QueryGroupList *r)
213 {
214         struct winbindd_domain *domain = wb_child_domain();
215         uint32_t i, num_groups;
216         struct acct_info *groups;
217         struct wbint_Principal *result;
218         NTSTATUS status;
219
220         if (domain == NULL) {
221                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
222         }
223
224         status = domain->methods->enum_dom_groups(domain, talloc_tos(),
225                                                   &num_groups, &groups);
226         if (!NT_STATUS_IS_OK(status)) {
227                 return status;
228         }
229
230         result = talloc_array(r->out.groups, struct wbint_Principal,
231                               num_groups);
232         if (result == NULL) {
233                 return NT_STATUS_NO_MEMORY;
234         }
235
236         for (i=0; i<num_groups; i++) {
237                 sid_compose(&result[i].sid, &domain->sid, groups[i].rid);
238                 result[i].type = SID_NAME_DOM_GRP;
239                 result[i].name = talloc_strdup(result, groups[i].acct_name);
240                 if (result[i].name == NULL) {
241                         TALLOC_FREE(result);
242                         TALLOC_FREE(groups);
243                         return NT_STATUS_NO_MEMORY;
244                 }
245         }
246
247         r->out.groups->num_principals = num_groups;
248         r->out.groups->principals = result;
249         return NT_STATUS_OK;
250 }
251
252 NTSTATUS _wbint_DsGetDcName(pipes_struct *p, struct wbint_DsGetDcName *r)
253 {
254         struct winbindd_domain *domain = wb_child_domain();
255         struct rpc_pipe_client *netlogon_pipe;
256         struct netr_DsRGetDCNameInfo *dc_info;
257         NTSTATUS status;
258         WERROR werr;
259         unsigned int orig_timeout;
260
261         if (domain == NULL) {
262                 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
263                                    r->in.domain_name, r->in.domain_guid,
264                                    r->in.site_name ? r->in.site_name : "",
265                                    r->in.flags,
266                                    r->out.dc_info);
267         }
268
269         status = cm_connect_netlogon(domain, &netlogon_pipe);
270
271         if (!NT_STATUS_IS_OK(status)) {
272                 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
273                 return status;
274         }
275
276         /* This call can take a long time - allow the server to time out.
277            35 seconds should do it. */
278
279         orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
280
281         if (domain->active_directory) {
282                 status = rpccli_netr_DsRGetDCName(
283                         netlogon_pipe, p->mem_ctx, domain->dcname,
284                         r->in.domain_name, NULL, r->in.domain_guid,
285                         r->in.flags, r->out.dc_info, &werr);
286                 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
287                         goto done;
288                 }
289         }
290
291         /*
292          * Fallback to less capable methods
293          */
294
295         dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
296         if (dc_info == NULL) {
297                 status = NT_STATUS_NO_MEMORY;
298                 goto done;
299         }
300
301         if (r->in.flags & DS_PDC_REQUIRED) {
302                 status = rpccli_netr_GetDcName(
303                         netlogon_pipe, p->mem_ctx, domain->dcname,
304                         r->in.domain_name, &dc_info->dc_unc, &werr);
305         } else {
306                 status = rpccli_netr_GetAnyDCName(
307                         netlogon_pipe, p->mem_ctx, domain->dcname,
308                         r->in.domain_name, &dc_info->dc_unc, &werr);
309         }
310
311         if (!NT_STATUS_IS_OK(status)) {
312                 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
313                            nt_errstr(status)));
314                 goto done;
315         }
316         if (!W_ERROR_IS_OK(werr)) {
317                 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
318                            win_errstr(werr)));
319                 status = werror_to_ntstatus(werr);
320                 goto done;
321         }
322
323         *r->out.dc_info = dc_info;
324         status = NT_STATUS_OK;
325
326 done:
327         /* And restore our original timeout. */
328         rpccli_set_timeout(netlogon_pipe, orig_timeout);
329
330         return status;
331 }
332
333 NTSTATUS _wbint_LookupRids(pipes_struct *p, struct wbint_LookupRids *r)
334 {
335         struct winbindd_domain *domain = wb_child_domain();
336         char *domain_name;
337         char **names;
338         enum lsa_SidType *types;
339         struct wbint_Principal *result;
340         NTSTATUS status;
341         int i;
342
343         if (domain == NULL) {
344                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
345         }
346
347         status = domain->methods->rids_to_names(
348                 domain, talloc_tos(), &domain->sid, r->in.rids->rids,
349                 r->in.rids->num_rids, &domain_name, &names, &types);
350         if (!NT_STATUS_IS_OK(status)) {
351                 return status;
352         }
353
354         result = talloc_array(p->mem_ctx, struct wbint_Principal,
355                               r->in.rids->num_rids);
356         if (result == NULL) {
357                 return NT_STATUS_NO_MEMORY;
358         }
359
360         for (i=0; i<r->in.rids->num_rids; i++) {
361                 sid_compose(&result[i].sid, &domain->sid, r->in.rids->rids[i]);
362                 result[i].type = types[i];
363                 result[i].name = talloc_move(result, &names[i]);
364         }
365         TALLOC_FREE(types);
366         TALLOC_FREE(names);
367
368         r->out.names->num_principals = r->in.rids->num_rids;
369         r->out.names->principals = result;
370         return NT_STATUS_OK;
371 }