6724206b2ebe7e302fe68ecc2c25bc57e5309d9b
[ira/wip.git] / source4 / 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 struct composite_context *rpc_composite_useradd_send(struct dcerpc_pipe *p,
99                                                      struct rpc_composite_useradd *io)
100 {
101         struct composite_context *c;
102         struct useradd_state *s;
103         struct dom_sid *sid;
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 userinfo 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 del 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 static NTSTATUS userdel_lookup(struct composite_context *c,
208                                struct userdel_state *s)
209 {
210         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
211
212         c->status = dcerpc_ndr_request_recv(s->req);
213         NT_STATUS_NOT_OK_RETURN(c->status);
214         
215         if (!s->lookupname.out.rids.count) {
216                 /* TODO: no such user */
217                 status = NT_STATUS_NO_SUCH_USER;
218
219         } else if (!s->lookupname.out.rids.count > 1) {
220                 /* TODO: ambiguous username */
221                 status = NT_STATUS_INVALID_ACCOUNT_NAME;
222         }
223         
224         s->openuser.in.domain_handle = &s->domain_handle;
225         s->openuser.in.rid           = s->lookupname.out.rids.ids[0];
226         s->openuser.in.access_mask   = SEC_FLAG_MAXIMUM_ALLOWED;
227         s->openuser.out.user_handle  = &s->user_handle;
228
229         s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser);
230         
231         s->req->async.callback = userdel_handler;
232         s->req->async.private  = c;
233         s->stage = USERDEL_OPEN;
234         
235         return NT_STATUS_OK;
236 failure:
237         talloc_free(c);
238         return status;
239 }
240
241
242 static NTSTATUS userdel_open(struct composite_context *c,
243                              struct userdel_state *s)
244 {
245         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
246         
247         c->status = dcerpc_ndr_request_recv(s->req);
248         NT_STATUS_NOT_OK_RETURN(c->status);
249         
250         s->deleteuser.in.user_handle   = &s->user_handle;
251         s->deleteuser.out.user_handle  = &s->user_handle;
252         
253         s->req = dcerpc_samr_DeleteUser_send(s->pipe, c, &s->deleteuser);
254         
255         s->req->async.callback = userdel_handler;
256         s->req->async.private  = c;
257         s->stage = USERDEL_DELETE;
258         
259         return NT_STATUS_OK;
260 }
261
262
263 static NTSTATUS userdel_delete(struct composite_context *c,
264                                struct userdel_state *s)
265 {
266         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
267         
268         c->status = dcerpc_ndr_request_recv(s->req);
269         NT_STATUS_NOT_OK_RETURN(c->status);
270         
271         c->state = SMBCLI_REQUEST_DONE;
272
273         return NT_STATUS_OK;
274 }
275
276
277 static void userdel_handler(struct rpc_request *req)
278 {
279         struct composite_context *c = req->async.private;
280         struct userdel_state *s = talloc_get_type(c->private, struct userdel_state);
281         
282         switch (s->stage) {
283         case USERDEL_LOOKUP:
284                 c->status = userdel_lookup(c, s);
285                 break;
286         case USERDEL_OPEN:
287                 c->status = userdel_open(c, s);
288                 break;
289         case USERDEL_DELETE:
290                 c->status = userdel_delete(c, s);
291                 break;
292         }
293
294         if (!NT_STATUS_IS_OK(c->status)) {
295                 c->state = SMBCLI_REQUEST_ERROR;
296         }
297
298         if (c->state >= SMBCLI_REQUEST_DONE &&
299             c->async.fn) {
300                 c->async.fn(c);
301         }
302 }
303
304
305 struct composite_context *rpc_composite_userdel_send(struct dcerpc_pipe *p,
306                                                      struct rpc_composite_userdel *io)
307 {
308         struct composite_context *c;
309         struct userdel_state *s;
310         
311         c = talloc_zero(p, struct composite_context);
312         if (c == NULL) goto failure;
313
314         s = talloc_zero(c, struct userdel_state);
315         if (s == NULL) goto failure;
316
317         s->pipe = p;
318         c->state      = SMBCLI_REQUEST_SEND;
319         c->private    = s;
320         c->event_ctx  = dcerpc_event_context(p);
321
322         s->lookupname.in.domain_handle = &io->in.domain_handle;
323         s->lookupname.in.num_names     = 1;
324         s->lookupname.in.names         = talloc_zero(s, struct samr_String);
325         s->lookupname.in.names->string = io->in.username;
326
327         s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookupname);
328         
329         s->req->async.callback = userdel_handler;
330         s->req->async.private  = c;
331         s->stage = USERDEL_LOOKUP;
332
333         return c;
334
335 failure:
336         talloc_free(c);
337         return NULL;
338 }
339
340
341 NTSTATUS rpc_composite_userdel_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
342                                     struct rpc_composite_userdel *io)
343 {
344         NTSTATUS status;
345         struct userdel_state *s;
346         
347         status = composite_wait(c);
348
349         if (NT_STATUS_IS_OK(status) && io) {
350                 s  = talloc_get_type(c->private, struct userdel_state);
351                 io->out.user_handle = s->user_handle;
352         }
353
354         talloc_free(c);
355         return status;
356 }
357
358
359 NTSTATUS rpc_composite_userdel(struct dcerpc_pipe *pipe,
360                                TALLOC_CTX *mem_ctx,
361                                struct rpc_composite_userdel *io)
362 {
363         struct composite_context *c = rpc_composite_userdel_send(pipe, io);
364         return rpc_composite_userdel_recv(c, mem_ctx, io);
365 }