897de42d20b3fd7f79a8400f2950378995b58ac2
[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         struct dom_sid *sid;
105         
106         c = talloc_zero(p, struct composite_context);
107         if (c == NULL) goto failure;
108         
109         s = talloc_zero(c, struct useradd_state);
110         if (s == NULL) goto failure;
111         
112         s->domain_handle = io->in.domain_handle;
113         s->pipe          = p;
114         
115         c->state     = SMBCLI_REQUEST_SEND;
116         c->private   = s;
117         c->event_ctx = dcerpc_event_context(p);
118
119         /* preparing parameters to send rpc request */
120         s->createuser.in.domain_handle         = &io->in.domain_handle;
121         s->createuser.in.account_name          = talloc_zero(c, struct samr_String);
122         s->createuser.in.account_name->string  = talloc_strdup(c, io->in.username);
123         s->createuser.out.user_handle          = &s->user_handle;
124         s->createuser.out.rid                  = &s->user_rid;
125
126         /* send request */
127         s->req = dcerpc_samr_CreateUser_send(p, c, &s->createuser);
128
129         /* callback handler */
130         s->req->async.callback = useradd_handler;
131         s->req->async.private  = c;
132         s->stage = USERADD_CREATE;
133
134         return c;
135         
136 failure:
137         talloc_free(c);
138         return NULL;
139 }
140
141
142 /**
143  * Waits for and receives result of asynchronous useradd call
144  * 
145  * @param c composite context returned by asynchronous useradd call
146  * @param mem_ctx memory context of the call
147  * @param io pointer to results (and arguments) of the call
148  * @return nt status code of execution
149  */
150
151 NTSTATUS rpc_composite_useradd_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
152                                     struct rpc_composite_useradd *io)
153 {
154         NTSTATUS status;
155         struct useradd_state *s;
156         
157         status = composite_wait(c);
158         
159         if (NT_STATUS_IS_OK(status) && io) {
160                 /* get and return result of the call */
161                 s = talloc_get_type(c->private, struct useradd_state);
162                 io->out.user_handle = s->user_handle;
163         }
164
165         talloc_free(c);
166         return status;
167 }
168
169
170 /**
171  * Synchronous version of useradd call
172  *
173  * @param pipe dce/rpc call pipe
174  * @param mem_ctx memory context for the call
175  * @param io arguments and results of the call
176  * @return nt status code of execution
177  */
178
179 NTSTATUS rpc_composite_useradd(struct dcerpc_pipe *pipe,
180                                TALLOC_CTX *mem_ctx,
181                                struct rpc_composite_useradd *io)
182 {
183         struct composite_context *c = rpc_composite_useradd_send(pipe, io);
184         return rpc_composite_useradd_recv(c, mem_ctx, io);
185 }
186
187
188 /*
189  * Composite user delete function
190  */
191
192 static void userdel_handler(struct rpc_request*);
193
194 enum userdel_stage { USERDEL_LOOKUP, USERDEL_OPEN, USERDEL_DELETE };
195
196 struct userdel_state {
197         enum userdel_stage        stage;
198         struct dcerpc_pipe        *pipe;
199         struct rpc_request        *req;
200         struct policy_handle      domain_handle;
201         struct policy_handle      user_handle;
202         struct samr_LookupNames   lookupname;
203         struct samr_OpenUser      openuser;
204         struct samr_DeleteUser    deleteuser;
205 };
206
207
208 /**
209  * Stage 1: Lookup the user name and resolve it to rid
210  */
211 static NTSTATUS userdel_lookup(struct composite_context *c,
212                                struct userdel_state *s)
213 {
214         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
215
216         c->status = dcerpc_ndr_request_recv(s->req);
217         NT_STATUS_NOT_OK_RETURN(c->status);
218         
219         if (!s->lookupname.out.rids.count) {
220                 /* TODO: no such user */
221                 status = NT_STATUS_NO_SUCH_USER;
222
223         } else if (!s->lookupname.out.rids.count > 1) {
224                 /* TODO: ambiguous username */
225                 status = NT_STATUS_INVALID_ACCOUNT_NAME;
226         }
227         
228         s->openuser.in.domain_handle = &s->domain_handle;
229         s->openuser.in.rid           = s->lookupname.out.rids.ids[0];
230         s->openuser.in.access_mask   = SEC_FLAG_MAXIMUM_ALLOWED;
231         s->openuser.out.user_handle  = &s->user_handle;
232
233         s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser);
234         
235         s->req->async.callback = userdel_handler;
236         s->req->async.private  = c;
237         s->stage = USERDEL_OPEN;
238         
239         return NT_STATUS_OK;
240 failure:
241         talloc_free(c);
242         return status;
243 }
244
245
246 /**
247  * Stage 2: Open user account.
248  */
249 static NTSTATUS userdel_open(struct composite_context *c,
250                              struct userdel_state *s)
251 {
252         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
253         
254         c->status = dcerpc_ndr_request_recv(s->req);
255         NT_STATUS_NOT_OK_RETURN(c->status);
256         
257         s->deleteuser.in.user_handle   = &s->user_handle;
258         s->deleteuser.out.user_handle  = &s->user_handle;
259         
260         s->req = dcerpc_samr_DeleteUser_send(s->pipe, c, &s->deleteuser);
261         
262         s->req->async.callback = userdel_handler;
263         s->req->async.private  = c;
264         s->stage = USERDEL_DELETE;
265         
266         return NT_STATUS_OK;
267 }
268
269
270 /**
271  * Stage 3: Delete user account
272  */
273 static NTSTATUS userdel_delete(struct composite_context *c,
274                                struct userdel_state *s)
275 {
276         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
277         
278         c->status = dcerpc_ndr_request_recv(s->req);
279         NT_STATUS_NOT_OK_RETURN(c->status);
280         
281         c->state = SMBCLI_REQUEST_DONE;
282
283         return NT_STATUS_OK;
284 }
285
286
287 /**
288  * Event handler for asynchronous request. Handles transition through
289  * intermediate stages of the call.
290  *
291  * @param req rpc call context
292  */
293 static void userdel_handler(struct rpc_request *req)
294 {
295         struct composite_context *c = req->async.private;
296         struct userdel_state *s = talloc_get_type(c->private, struct userdel_state);
297         
298         switch (s->stage) {
299         case USERDEL_LOOKUP:
300                 c->status = userdel_lookup(c, s);
301                 break;
302         case USERDEL_OPEN:
303                 c->status = userdel_open(c, s);
304                 break;
305         case USERDEL_DELETE:
306                 c->status = userdel_delete(c, s);
307                 break;
308         }
309
310         if (!NT_STATUS_IS_OK(c->status)) {
311                 c->state = SMBCLI_REQUEST_ERROR;
312         }
313
314         if (c->state >= SMBCLI_REQUEST_DONE &&
315             c->async.fn) {
316                 c->async.fn(c);
317         }
318 }
319
320
321 /**
322  * Sends asynchronous userdel request
323  *
324  * @param p dce/rpc call pipe
325  * @param io arguments and results of the call
326  */
327
328 struct composite_context *rpc_composite_userdel_send(struct dcerpc_pipe *p,
329                                                      struct rpc_composite_userdel *io)
330 {
331         struct composite_context *c;
332         struct userdel_state *s;
333         
334         c = talloc_zero(p, struct composite_context);
335         if (c == NULL) goto failure;
336
337         s = talloc_zero(c, struct userdel_state);
338         if (s == NULL) goto failure;
339
340         c->state      = SMBCLI_REQUEST_SEND;
341         c->private    = s;
342         c->event_ctx  = dcerpc_event_context(p);
343
344         s->pipe          = p;
345         s->domain_handle = io->in.domain_handle;
346         
347         /* preparing parameters to send rpc request */
348         s->lookupname.in.domain_handle = &io->in.domain_handle;
349         s->lookupname.in.num_names     = 1;
350         s->lookupname.in.names         = talloc_zero(s, struct samr_String);
351         s->lookupname.in.names->string = io->in.username;
352
353         /* send the request */
354         s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname);
355
356         /* callback handler */
357         s->req->async.callback = userdel_handler;
358         s->req->async.private  = c;
359         s->stage = USERDEL_LOOKUP;
360
361         return c;
362
363 failure:
364         talloc_free(c);
365         return NULL;
366 }
367
368
369 /**
370  * Waits for and receives results of asynchronous userdel call
371  *
372  * @param c composite context returned by asynchronous userdel call
373  * @param mem_ctx memory context of the call
374  * @param io pointer to results (and arguments) of the call
375  * @return nt status code of execution
376  */
377
378 NTSTATUS rpc_composite_userdel_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
379                                     struct rpc_composite_userdel *io)
380 {
381         NTSTATUS status;
382         struct userdel_state *s;
383         
384         status = composite_wait(c);
385
386         if (NT_STATUS_IS_OK(status) && io) {
387                 s  = talloc_get_type(c->private, struct userdel_state);
388                 io->out.user_handle = s->user_handle;
389         }
390
391         talloc_free(c);
392         return status;
393 }
394
395
396 /**
397  * Synchronous version of userdel call
398  *
399  * @param pipe dce/rpc call pipe
400  * @param mem_ctx memory context for the call
401  * @param io arguments and results of the call
402  * @return nt status code of execution
403  */
404
405 NTSTATUS rpc_composite_userdel(struct dcerpc_pipe *pipe,
406                                TALLOC_CTX *mem_ctx,
407                                struct rpc_composite_userdel *io)
408 {
409         struct composite_context *c = rpc_composite_userdel_send(pipe, io);
410         return rpc_composite_userdel_recv(c, mem_ctx, io);
411 }