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