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