r10504: - seperate implementation specific stuff, from the generic composite
[kai/samba-autobuild/.git] / source4 / libnet / userinfo.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 function for getting user information via samr pipe
23 */
24
25 #include "includes.h"
26 #include "libcli/composite/composite.h"
27 #include "librpc/gen_ndr/ndr_samr.h"
28 #include "libnet/composite.h"
29 #include "libnet/userinfo.h"
30
31 static void userinfo_handler(struct rpc_request *req);
32
33 enum userinfo_stage { USERINFO_OPENUSER, USERINFO_GETUSER, USERINFO_CLOSEUSER };
34
35 struct userinfo_state {
36         enum userinfo_stage       stage;
37         struct dcerpc_pipe        *pipe;
38         struct rpc_request        *req;
39         struct policy_handle      user_handle;
40         uint16_t                  level;
41         struct samr_OpenUser      openuser;
42         struct samr_QueryUserInfo queryuserinfo;
43         struct samr_Close         samrclose;    
44         union  samr_UserInfo      *info;
45         /* information about the progress */
46         void (*monitor_fn)(struct monitor_msg *);
47 };
48
49
50 /**
51  * Stage 1: Open user policy handle in SAM server.
52  */
53 static NTSTATUS userinfo_openuser(struct composite_context *c,
54                                   struct userinfo_state *s)
55 {
56         /* receive samr_OpenUser reply */
57         c->status = dcerpc_ndr_request_recv(s->req);
58         NT_STATUS_NOT_OK_RETURN(c->status);
59
60         /* prepare parameters for QueryUserInfo call */
61         s->queryuserinfo.in.user_handle = &s->user_handle;
62         s->queryuserinfo.in.level       = s->level;
63         
64         /* queue rpc call, set event handling and new state */
65         s->req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuserinfo);
66         if (s->req == NULL) goto failure;
67         
68         s->req->async.callback = userinfo_handler;
69         s->req->async.private  = c;
70         s->stage = USERINFO_GETUSER;
71         
72         return NT_STATUS_OK;
73
74 failure:
75         return NT_STATUS_UNSUCCESSFUL;
76 }
77
78
79 /**
80  * Stage 2: Get requested user information.
81  */
82 static NTSTATUS userinfo_getuser(struct composite_context *c,
83                                  struct userinfo_state *s)
84 {
85         /* receive samr_QueryUserInfo reply */
86         c->status = dcerpc_ndr_request_recv(s->req);
87         NT_STATUS_NOT_OK_RETURN(c->status);
88
89         s->info = talloc_steal(s, s->queryuserinfo.out.info);
90         
91         /* prepare arguments for Close call */
92         s->samrclose.in.handle  = &s->user_handle;
93         s->samrclose.out.handle = &s->user_handle;
94         
95         /* queue rpc call, set event handling and new state */
96         s->req = dcerpc_samr_Close_send(s->pipe, c, &s->samrclose);
97         
98         s->req->async.callback = userinfo_handler;
99         s->req->async.private  = c;
100         s->stage = USERINFO_CLOSEUSER;
101
102         return NT_STATUS_OK;
103 }
104
105
106 /**
107  * Stage 3: Close policy handle associated with opened user.
108  */
109 static NTSTATUS userinfo_closeuser(struct composite_context *c,
110                                    struct userinfo_state *s)
111 {
112         /* receive samr_Close reply */
113         c->status = dcerpc_ndr_request_recv(s->req);
114         NT_STATUS_NOT_OK_RETURN(c->status);
115
116         c->state = COMPOSITE_STATE_DONE;
117
118         return NT_STATUS_OK;
119 }
120
121
122 /**
123  * Event handler for asynchronous request. Handles transition through
124  * intermediate stages of the call.
125  *
126  * @param req rpc call context
127  */
128 static void userinfo_handler(struct rpc_request *req)
129 {
130         struct composite_context *c = req->async.private;
131         struct userinfo_state *s = talloc_get_type(c->private_data, struct userinfo_state);
132         struct monitor_msg msg;
133         struct msg_rpc_open_user *msg_open;
134         struct msg_rpc_query_user *msg_query;
135         struct msg_rpc_close_user *msg_close;
136         
137         /* Stages of the call */
138         switch (s->stage) {
139         case USERINFO_OPENUSER:
140                 c->status = userinfo_openuser(c, s);
141
142                 msg.type = rpc_open_user;
143                 msg_open = talloc(s, struct msg_rpc_open_user);
144                 msg_open->rid = s->openuser.in.rid;
145                 msg_open->access_mask = s->openuser.in.access_mask;
146                 msg.data = (void*)msg_open;
147                 msg.data_size = sizeof(*msg_open);
148                 break;
149
150         case USERINFO_GETUSER:
151                 c->status = userinfo_getuser(c, s);
152
153                 msg.type = rpc_query_user;
154                 msg_query = talloc(s, struct msg_rpc_query_user);
155                 msg_query->level = s->queryuserinfo.in.level;
156                 msg.data = (void*)msg_query;
157                 msg.data_size = sizeof(*msg_query);
158                 break;
159                 
160         case USERINFO_CLOSEUSER:
161                 c->status = userinfo_closeuser(c, s);
162
163                 msg.type = rpc_close_user;
164                 msg_close = talloc(s, struct msg_rpc_close_user);
165                 msg_close->rid = s->openuser.in.rid;
166                 msg.data = (void*)msg_close;
167                 msg.data_size = sizeof(*msg_close);
168                 break;
169         }
170
171         if (!NT_STATUS_IS_OK(c->status)) {
172                 c->state = COMPOSITE_STATE_ERROR;
173         }
174         
175         if (s->monitor_fn) {
176                 s->monitor_fn(&msg);
177         }
178
179         if (c->state >= COMPOSITE_STATE_DONE &&
180             c->async.fn) {
181                 c->async.fn(c);
182         }
183 }
184
185
186 /**
187  * Sends asynchronous userinfo request
188  *
189  * @param p dce/rpc call pipe 
190  * @param io arguments and results of the call
191  */
192 struct composite_context *libnet_rpc_userinfo_send(struct dcerpc_pipe *p,
193                                                    struct libnet_rpc_userinfo *io,
194                                                    void (*monitor)(struct monitor_msg*))
195 {
196         struct composite_context *c;
197         struct userinfo_state *s;
198         struct dom_sid *sid;
199
200         if (!p || !io) return NULL;
201         
202         c = talloc_zero(p, struct composite_context);
203         if (c == NULL) goto failure;
204         
205         s = talloc_zero(c, struct userinfo_state);
206         if (s == NULL) goto failure;
207
208         s->level = io->in.level;
209         s->pipe  = p;
210         s->monitor_fn  = monitor;
211         
212         sid = dom_sid_parse_talloc(s, io->in.sid);
213         if (sid == NULL) goto failure;  
214         c->state       = COMPOSITE_STATE_IN_PROGRESS;
215         c->private_data= s;
216         c->event_ctx   = dcerpc_event_context(p);
217
218         /* preparing parameters to send rpc request */
219         s->openuser.in.domain_handle  = &io->in.domain_handle;
220         s->openuser.in.access_mask    = SEC_FLAG_MAXIMUM_ALLOWED;
221         s->openuser.in.rid            = sid->sub_auths[sid->num_auths - 1];
222         s->openuser.out.user_handle   = &s->user_handle;
223
224         /* send request */
225         s->req = dcerpc_samr_OpenUser_send(p, c, &s->openuser);
226
227         /* callback handler */
228         s->req->async.callback = userinfo_handler;
229         s->req->async.private  = c;
230         s->stage = USERINFO_OPENUSER;
231
232         return c;
233         
234 failure:
235         talloc_free(c);
236         return NULL;
237 }
238
239
240 /**
241  * Waits for and receives result of asynchronous userinfo call
242  * 
243  * @param c composite context returned by asynchronous userinfo call
244  * @param mem_ctx memory context of the call
245  * @param io pointer to results (and arguments) of the call
246  * @return nt status code of execution
247  */
248
249 NTSTATUS libnet_rpc_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
250                                   struct libnet_rpc_userinfo *io)
251 {
252         NTSTATUS status;
253         struct userinfo_state *s;
254         
255         /* wait for results of sending request */
256         status = composite_wait(c);
257         
258         if (NT_STATUS_IS_OK(status) && io) {
259                 s = talloc_get_type(c->private_data, struct userinfo_state);
260                 talloc_steal(mem_ctx, s->info);
261                 io->out.info = *s->info;
262         }
263         
264         /* memory context associated to composite context is no longer needed */
265         talloc_free(c);
266         return status;
267 }
268
269
270 /**
271  * Synchronous version of userinfo call
272  *
273  * @param pipe dce/rpc call pipe
274  * @param mem_ctx memory context for the call
275  * @param io arguments and results of the call
276  * @return nt status code of execution
277  */
278
279 NTSTATUS libnet_rpc_userinfo(struct dcerpc_pipe *pipe,
280                              TALLOC_CTX *mem_ctx,
281                              struct libnet_rpc_userinfo *io)
282 {
283         struct composite_context *c = libnet_rpc_userinfo_send(pipe, io, NULL);
284         return libnet_rpc_userinfo_recv(c, mem_ctx, io);
285 }