1bba0ff718441a86b77182dbc0ebd52729ce66ad
[samba.git] / source / libnet / userman.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Rafal Szczesniak 2005
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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22   a composite functions for user management operations (add/del/chg)
23 */
24
25 #include "includes.h"
26 #include "libcli/raw/libcliraw.h"
27 #include "libcli/composite/composite.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
29 #include "libnet/composite.h"
30
31 /*
32  * Composite user add function
33  */
34
35 static void useradd_handler(struct rpc_request*);
36
37 enum useradd_stage { USERADD_CREATE };
38
39 struct useradd_state {
40         enum useradd_stage       stage;
41         struct dcerpc_pipe       *pipe;
42         struct rpc_request       *req;
43         struct policy_handle     domain_handle;
44         struct samr_CreateUser   createuser;
45         struct policy_handle     user_handle;
46         uint32_t                 user_rid;
47 };
48
49
50 /**
51  * Stage 1 (and the only one for now): Create user account.
52  */
53 static NTSTATUS useradd_create(struct composite_context *c,
54                                struct useradd_state *s)
55 {
56         c->status = dcerpc_ndr_request_recv(s->req);
57         NT_STATUS_NOT_OK_RETURN(c->status);
58         
59         c->state = SMBCLI_REQUEST_DONE;
60         return NT_STATUS_OK;
61 }
62
63
64 /**
65  * Event handler for asynchronous request. Handles transition through
66  * intermediate stages of the call.
67  *
68  * @param req rpc call context
69  */
70 static void useradd_handler(struct rpc_request *req)
71 {
72         struct composite_context *c = req->async.private;
73         struct useradd_state *s = talloc_get_type(c->private, struct useradd_state);
74         
75         switch (s->stage) {
76         case USERADD_CREATE:
77                 c->status = useradd_create(c, s);
78                 break;
79         }
80
81         if (!NT_STATUS_IS_OK(c->status)) {
82                 c->state = SMBCLI_REQUEST_ERROR;
83         }
84
85         if (c->state >= SMBCLI_REQUEST_DONE &&
86             c->async.fn) {
87                 c->async.fn(c);
88         }
89 }
90
91
92 /**
93  * Sends asynchronous useradd request
94  *
95  * @param p dce/rpc call pipe 
96  * @param io arguments and results of the call
97  */
98
99 struct composite_context *rpc_composite_useradd_send(struct dcerpc_pipe *p,
100                                                      struct rpc_composite_useradd *io)
101 {
102         struct composite_context *c;
103         struct useradd_state *s;
104         
105         c = talloc_zero(p, struct composite_context);
106         if (c == NULL) goto failure;
107         
108         s = talloc_zero(c, struct useradd_state);
109         if (s == NULL) goto failure;
110         
111         s->domain_handle = io->in.domain_handle;
112         s->pipe          = p;
113         
114         c->state     = SMBCLI_REQUEST_SEND;
115         c->private   = s;
116         c->event_ctx = dcerpc_event_context(p);
117
118         /* preparing parameters to send rpc request */
119         s->createuser.in.domain_handle         = &io->in.domain_handle;
120         s->createuser.in.account_name          = talloc_zero(c, struct samr_String);
121         s->createuser.in.account_name->string  = talloc_strdup(c, io->in.username);
122         s->createuser.out.user_handle          = &s->user_handle;
123         s->createuser.out.rid                  = &s->user_rid;
124
125         /* send request */
126         s->req = dcerpc_samr_CreateUser_send(p, c, &s->createuser);
127
128         /* callback handler */
129         s->req->async.callback = useradd_handler;
130         s->req->async.private  = c;
131         s->stage = USERADD_CREATE;
132
133         return c;
134         
135 failure:
136         talloc_free(c);
137         return NULL;
138 }
139
140
141 /**
142  * Waits for and receives result of asynchronous useradd call
143  * 
144  * @param c composite context returned by asynchronous useradd call
145  * @param mem_ctx memory context of the call
146  * @param io pointer to results (and arguments) of the call
147  * @return nt status code of execution
148  */
149
150 NTSTATUS rpc_composite_useradd_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
151                                     struct rpc_composite_useradd *io)
152 {
153         NTSTATUS status;
154         struct useradd_state *s;
155         
156         status = composite_wait(c);
157         
158         if (NT_STATUS_IS_OK(status) && io) {
159                 /* get and return result of the call */
160                 s = talloc_get_type(c->private, struct useradd_state);
161                 io->out.user_handle = s->user_handle;
162         }
163
164         talloc_free(c);
165         return status;
166 }
167
168
169 /**
170  * Synchronous version of useradd call
171  *
172  * @param pipe dce/rpc call pipe
173  * @param mem_ctx memory context for the call
174  * @param io arguments and results of the call
175  * @return nt status code of execution
176  */
177
178 NTSTATUS rpc_composite_useradd(struct dcerpc_pipe *pipe,
179                                TALLOC_CTX *mem_ctx,
180                                struct rpc_composite_useradd *io)
181 {
182         struct composite_context *c = rpc_composite_useradd_send(pipe, io);
183         return rpc_composite_useradd_recv(c, mem_ctx, io);
184 }
185
186
187 /*
188  * Composite user delete function
189  */
190
191 static void userdel_handler(struct rpc_request*);
192
193 enum userdel_stage { USERDEL_LOOKUP, USERDEL_OPEN, USERDEL_DELETE };
194
195 struct userdel_state {
196         enum userdel_stage        stage;
197         struct dcerpc_pipe        *pipe;
198         struct rpc_request        *req;
199         struct policy_handle      domain_handle;
200         struct policy_handle      user_handle;
201         struct samr_LookupNames   lookupname;
202         struct samr_OpenUser      openuser;
203         struct samr_DeleteUser    deleteuser;
204 };
205
206
207 /**
208  * Stage 1: Lookup the user name and resolve it to rid
209  */
210 static NTSTATUS userdel_lookup(struct composite_context *c,
211                                struct userdel_state *s)
212 {
213         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
214
215         c->status = dcerpc_ndr_request_recv(s->req);
216         NT_STATUS_NOT_OK_RETURN(c->status);
217         
218         if (!s->lookupname.out.rids.count) {
219                 /* TODO: no such user */
220                 status = NT_STATUS_NO_SUCH_USER;
221
222         } else if (!s->lookupname.out.rids.count > 1) {
223                 /* TODO: ambiguous username */
224                 status = NT_STATUS_INVALID_ACCOUNT_NAME;
225         }
226         
227         s->openuser.in.domain_handle = &s->domain_handle;
228         s->openuser.in.rid           = s->lookupname.out.rids.ids[0];
229         s->openuser.in.access_mask   = SEC_FLAG_MAXIMUM_ALLOWED;
230         s->openuser.out.user_handle  = &s->user_handle;
231
232         s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser);
233         
234         s->req->async.callback = userdel_handler;
235         s->req->async.private  = c;
236         s->stage = USERDEL_OPEN;
237         
238         return NT_STATUS_OK;
239 failure:
240         talloc_free(c);
241         return status;
242 }
243
244
245 /**
246  * Stage 2: Open user account.
247  */
248 static NTSTATUS userdel_open(struct composite_context *c,
249                              struct userdel_state *s)
250 {
251         c->status = dcerpc_ndr_request_recv(s->req);
252         NT_STATUS_NOT_OK_RETURN(c->status);
253         
254         s->deleteuser.in.user_handle   = &s->user_handle;
255         s->deleteuser.out.user_handle  = &s->user_handle;
256         
257         s->req = dcerpc_samr_DeleteUser_send(s->pipe, c, &s->deleteuser);
258         
259         s->req->async.callback = userdel_handler;
260         s->req->async.private  = c;
261         s->stage = USERDEL_DELETE;
262         
263         return NT_STATUS_OK;
264 }
265
266
267 /**
268  * Stage 3: Delete user account
269  */
270 static NTSTATUS userdel_delete(struct composite_context *c,
271                                struct userdel_state *s)
272 {
273         c->status = dcerpc_ndr_request_recv(s->req);
274         NT_STATUS_NOT_OK_RETURN(c->status);
275         
276         c->state = SMBCLI_REQUEST_DONE;
277
278         return NT_STATUS_OK;
279 }
280
281
282 /**
283  * Event handler for asynchronous request. Handles transition through
284  * intermediate stages of the call.
285  *
286  * @param req rpc call context
287  */
288 static void userdel_handler(struct rpc_request *req)
289 {
290         struct composite_context *c = req->async.private;
291         struct userdel_state *s = talloc_get_type(c->private, struct userdel_state);
292         
293         switch (s->stage) {
294         case USERDEL_LOOKUP:
295                 c->status = userdel_lookup(c, s);
296                 break;
297         case USERDEL_OPEN:
298                 c->status = userdel_open(c, s);
299                 break;
300         case USERDEL_DELETE:
301                 c->status = userdel_delete(c, s);
302                 break;
303         }
304
305         if (!NT_STATUS_IS_OK(c->status)) {
306                 c->state = SMBCLI_REQUEST_ERROR;
307         }
308
309         if (c->state >= SMBCLI_REQUEST_DONE &&
310             c->async.fn) {
311                 c->async.fn(c);
312         }
313 }
314
315
316 /**
317  * Sends asynchronous userdel request
318  *
319  * @param p dce/rpc call pipe
320  * @param io arguments and results of the call
321  */
322
323 struct composite_context *rpc_composite_userdel_send(struct dcerpc_pipe *p,
324                                                      struct rpc_composite_userdel *io)
325 {
326         struct composite_context *c;
327         struct userdel_state *s;
328         
329         c = talloc_zero(p, struct composite_context);
330         if (c == NULL) goto failure;
331
332         s = talloc_zero(c, struct userdel_state);
333         if (s == NULL) goto failure;
334
335         c->state      = SMBCLI_REQUEST_SEND;
336         c->private    = s;
337         c->event_ctx  = dcerpc_event_context(p);
338
339         s->pipe          = p;
340         s->domain_handle = io->in.domain_handle;
341         
342         /* preparing parameters to send rpc request */
343         s->lookupname.in.domain_handle = &io->in.domain_handle;
344         s->lookupname.in.num_names     = 1;
345         s->lookupname.in.names         = talloc_zero(s, struct samr_String);
346         s->lookupname.in.names->string = io->in.username;
347
348         /* send the request */
349         s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname);
350
351         /* callback handler */
352         s->req->async.callback = userdel_handler;
353         s->req->async.private  = c;
354         s->stage = USERDEL_LOOKUP;
355
356         return c;
357
358 failure:
359         talloc_free(c);
360         return NULL;
361 }
362
363
364 /**
365  * Waits for and receives results of asynchronous userdel call
366  *
367  * @param c composite context returned by asynchronous userdel call
368  * @param mem_ctx memory context of the call
369  * @param io pointer to results (and arguments) of the call
370  * @return nt status code of execution
371  */
372
373 NTSTATUS rpc_composite_userdel_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
374                                     struct rpc_composite_userdel *io)
375 {
376         NTSTATUS status;
377         struct userdel_state *s;
378         
379         status = composite_wait(c);
380
381         if (NT_STATUS_IS_OK(status) && io) {
382                 s  = talloc_get_type(c->private, struct userdel_state);
383                 io->out.user_handle = s->user_handle;
384         }
385
386         talloc_free(c);
387         return status;
388 }
389
390
391 /**
392  * Synchronous version of userdel call
393  *
394  * @param pipe dce/rpc call pipe
395  * @param mem_ctx memory context for the call
396  * @param io arguments and results of the call
397  * @return nt status code of execution
398  */
399
400 NTSTATUS rpc_composite_userdel(struct dcerpc_pipe *pipe,
401                                TALLOC_CTX *mem_ctx,
402                                struct rpc_composite_userdel *io)
403 {
404         struct composite_context *c = rpc_composite_userdel_send(pipe, io);
405         return rpc_composite_userdel_recv(c, mem_ctx, io);
406 }