s4-rodc: s->schema need initialisation
[kai/samba.git] / source4 / libnet / groupman.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Rafal Szczesniak 2007
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21   a composite function for manipulating (add/edit/del) groups via samr pipe
22 */
23
24 #include "includes.h"
25 #include "libcli/composite/composite.h"
26 #include "libnet/libnet.h"
27 #include "librpc/gen_ndr/ndr_samr_c.h"
28
29
30 struct groupadd_state {
31         struct dcerpc_pipe *pipe;
32         struct policy_handle domain_handle;
33         struct samr_CreateDomainGroup creategroup;
34         struct policy_handle group_handle;
35         uint32_t group_rid;
36         
37         void (*monitor_fn)(struct monitor_msg*);
38 };
39
40
41 static void continue_groupadd_created(struct tevent_req *subreq);
42
43
44 struct composite_context* libnet_rpc_groupadd_send(struct dcerpc_pipe *p,
45                                                    struct libnet_rpc_groupadd *io,
46                                                    void (*monitor)(struct monitor_msg*))
47 {
48         struct composite_context *c;
49         struct groupadd_state *s;
50         struct tevent_req *subreq;
51
52         if (!p || !io) return NULL;
53
54         c = composite_create(p, dcerpc_event_context(p));
55         if (c == NULL) return NULL;
56
57         s = talloc_zero(c, struct groupadd_state);
58         if (composite_nomem(s, c)) return c;
59
60         c->private_data = s;
61
62         s->domain_handle = io->in.domain_handle;
63         s->pipe          = p;
64         s->monitor_fn    = monitor;
65
66         s->creategroup.in.domain_handle  = &s->domain_handle;
67
68         s->creategroup.in.name           = talloc_zero(c, struct lsa_String);
69         if (composite_nomem(s->creategroup.in.name, c)) return c;
70
71         s->creategroup.in.name->string   = talloc_strdup(c, io->in.groupname);
72         if (composite_nomem(s->creategroup.in.name->string, c)) return c;
73         
74         s->creategroup.in.access_mask    = 0;
75         
76         s->creategroup.out.group_handle  = &s->group_handle;
77         s->creategroup.out.rid           = &s->group_rid;
78         
79         subreq = dcerpc_samr_CreateDomainGroup_r_send(s, c->event_ctx,
80                                                       s->pipe->binding_handle,
81                                                       &s->creategroup);
82         if (composite_nomem(subreq, c)) return c;
83
84         tevent_req_set_callback(subreq, continue_groupadd_created, c);
85         return c;
86 }
87
88
89 NTSTATUS libnet_rpc_groupadd_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
90                                   struct libnet_rpc_groupadd *io)
91 {
92         NTSTATUS status;
93         struct groupadd_state *s;
94         
95         status = composite_wait(c);
96         if (NT_STATUS_IS_OK(status)) {
97                 s = talloc_get_type(c, struct groupadd_state);
98         }
99
100         return status;
101 }
102
103
104 static void continue_groupadd_created(struct tevent_req *subreq)
105 {
106         struct composite_context *c;
107         struct groupadd_state *s;
108
109         c = tevent_req_callback_data(subreq, struct composite_context);
110         s = talloc_get_type(c->private_data, struct groupadd_state);
111
112         c->status = dcerpc_samr_CreateDomainGroup_r_recv(subreq, s);
113         TALLOC_FREE(subreq);
114         if (!composite_is_ok(c)) return;
115
116         c->status = s->creategroup.out.result;
117         if (!composite_is_ok(c)) return;
118         
119         composite_done(c);
120 }
121
122
123 NTSTATUS libnet_rpc_groupadd(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
124                              struct libnet_rpc_groupadd *io)
125 {
126         struct composite_context *c;
127
128         c = libnet_rpc_groupadd_send(p, io, NULL);
129         return libnet_rpc_groupadd_recv(c, mem_ctx, io);
130 }
131
132
133 struct groupdel_state {
134         struct dcerpc_pipe             *pipe;
135         struct policy_handle           domain_handle;
136         struct policy_handle           group_handle;
137         struct samr_LookupNames        lookupname;
138         struct samr_OpenGroup          opengroup;
139         struct samr_DeleteDomainGroup  deletegroup;
140
141         /* information about the progress */
142         void (*monitor_fn)(struct monitor_msg *);
143 };
144
145
146 static void continue_groupdel_name_found(struct tevent_req *subreq);
147 static void continue_groupdel_group_opened(struct tevent_req *subreq);
148 static void continue_groupdel_deleted(struct tevent_req *subreq);
149
150
151 struct composite_context* libnet_rpc_groupdel_send(struct dcerpc_pipe *p,
152                                                    struct libnet_rpc_groupdel *io,
153                                                    void (*monitor)(struct monitor_msg*))
154 {
155         struct composite_context *c;
156         struct groupdel_state *s;
157         struct tevent_req *subreq;
158
159         /* composite context allocation and setup */
160         c = composite_create(p, dcerpc_event_context(p));
161         if (c == NULL) return NULL;
162
163         s = talloc_zero(c, struct groupdel_state);
164         if (composite_nomem(s, c)) return c;
165
166         c->private_data  = s;
167
168         /* store function parameters in the state structure */
169         s->pipe          = p;
170         s->domain_handle = io->in.domain_handle;
171         s->monitor_fn    = monitor;
172         
173         /* prepare parameters to send rpc request */
174         s->lookupname.in.domain_handle = &io->in.domain_handle;
175         s->lookupname.in.num_names     = 1;
176         s->lookupname.in.names         = talloc_zero(s, struct lsa_String);
177         s->lookupname.in.names->string = io->in.groupname;
178         s->lookupname.out.rids         = talloc_zero(s, struct samr_Ids);
179         s->lookupname.out.types        = talloc_zero(s, struct samr_Ids);
180         if (composite_nomem(s->lookupname.out.rids, c)) return c;
181         if (composite_nomem(s->lookupname.out.types, c)) return c;
182
183         /* send the request */
184         subreq = dcerpc_samr_LookupNames_r_send(s, c->event_ctx,
185                                                 p->binding_handle,
186                                                 &s->lookupname);
187         if (composite_nomem(subreq, c)) return c;
188
189         tevent_req_set_callback(subreq, continue_groupdel_name_found, c);
190         return c;
191 }
192
193
194 static void continue_groupdel_name_found(struct tevent_req *subreq)
195 {
196         struct composite_context *c;
197         struct groupdel_state *s;
198
199         c = tevent_req_callback_data(subreq, struct composite_context);
200         s = talloc_get_type(c->private_data, struct groupdel_state);
201
202         /* receive samr_LookupNames result */
203         c->status = dcerpc_samr_LookupNames_r_recv(subreq, s);
204         TALLOC_FREE(subreq);
205         if (!composite_is_ok(c)) return;
206
207         c->status = s->lookupname.out.result;
208         if (!NT_STATUS_IS_OK(c->status)) {
209                 composite_error(c, c->status);
210                 return;
211         }
212
213         /* what to do when there's no group account to delete
214            and what if there's more than one rid resolved */
215         if (!s->lookupname.out.rids->count) {
216                 c->status = NT_STATUS_NO_SUCH_GROUP;
217                 composite_error(c, c->status);
218                 return;
219
220         } else if (!s->lookupname.out.rids->count > 1) {
221                 c->status = NT_STATUS_INVALID_ACCOUNT_NAME;
222                 composite_error(c, c->status);
223                 return;
224         }
225
226         /* prepare the arguments for rpc call */
227         s->opengroup.in.domain_handle = &s->domain_handle;
228         s->opengroup.in.rid           = s->lookupname.out.rids->ids[0];
229         s->opengroup.in.access_mask   = SEC_FLAG_MAXIMUM_ALLOWED;
230         s->opengroup.out.group_handle  = &s->group_handle;
231
232         /* send rpc request */
233         subreq = dcerpc_samr_OpenGroup_r_send(s, c->event_ctx,
234                                               s->pipe->binding_handle,
235                                               &s->opengroup);
236         if (composite_nomem(subreq, c)) return;
237
238         tevent_req_set_callback(subreq, continue_groupdel_group_opened, c);
239 }
240
241
242 static void continue_groupdel_group_opened(struct tevent_req *subreq)
243 {
244         struct composite_context *c;
245         struct groupdel_state *s;
246
247         c = tevent_req_callback_data(subreq, struct composite_context);
248         s = talloc_get_type(c->private_data, struct groupdel_state);
249
250         /* receive samr_OpenGroup result */
251         c->status = dcerpc_samr_OpenGroup_r_recv(subreq, s);
252         TALLOC_FREE(subreq);
253         if (!composite_is_ok(c)) return;
254
255         c->status = s->opengroup.out.result;
256         if (!NT_STATUS_IS_OK(c->status)) {
257                 composite_error(c, c->status);
258                 return;
259         }
260         
261         /* prepare the final rpc call arguments */
262         s->deletegroup.in.group_handle   = &s->group_handle;
263         s->deletegroup.out.group_handle  = &s->group_handle;
264         
265         /* send rpc request */
266         subreq = dcerpc_samr_DeleteDomainGroup_r_send(s, c->event_ctx,
267                                                       s->pipe->binding_handle,
268                                                       &s->deletegroup);
269         if (composite_nomem(subreq, c)) return;
270
271         /* callback handler setup */
272         tevent_req_set_callback(subreq, continue_groupdel_deleted, c);
273 }
274
275
276 static void continue_groupdel_deleted(struct tevent_req *subreq)
277 {
278         struct composite_context *c;
279         struct groupdel_state *s;
280
281         c = tevent_req_callback_data(subreq, struct composite_context);
282         s = talloc_get_type(c->private_data, struct groupdel_state);
283
284         /* receive samr_DeleteGroup result */
285         c->status = dcerpc_samr_DeleteDomainGroup_r_recv(subreq, s);
286         TALLOC_FREE(subreq);
287         if (!composite_is_ok(c)) return;
288
289         /* return the actual function call status */
290         c->status = s->deletegroup.out.result;
291         if (!NT_STATUS_IS_OK(c->status)) {
292                 composite_error(c, c->status);
293                 return;
294         }
295         
296         composite_done(c);
297 }
298
299
300 NTSTATUS libnet_rpc_groupdel_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
301                                   struct libnet_rpc_groupdel *io)
302 {
303         NTSTATUS status;
304         struct groupdel_state *s;
305
306         status = composite_wait(c);
307         if (NT_STATUS_IS_OK(status) && io) {
308                 s = talloc_get_type(c->private_data, struct groupdel_state);
309                 io->out.group_handle = s->group_handle;
310         }
311
312         talloc_free(c);
313         return status;
314 }
315
316
317 NTSTATUS libnet_rpc_groupdel(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
318                              struct libnet_rpc_groupdel *io)
319 {
320         struct composite_context *c;
321
322         c = libnet_rpc_groupdel_send(p, io, NULL);
323         return libnet_rpc_groupdel_recv(c, mem_ctx, io);
324 }