r16168: Make the example match the actual function.
[Samba/aatanasov.git] / source / libnet / userinfo.c
blob9f1b97b67004b2dbeef803f5101c8582100076e1
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Rafal Szczesniak 2005
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.
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.
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.
22 a composite function for getting user information via samr pipe
25 #include "includes.h"
26 #include "libcli/composite/composite.h"
27 #include "libnet/composite.h"
28 #include "librpc/gen_ndr/security.h"
29 #include "libcli/security/security.h"
30 #include "libnet/userman.h"
31 #include "libnet/userinfo.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
34 static void userinfo_handler(struct rpc_request *req);
36 enum userinfo_stage { USERINFO_LOOKUP, USERINFO_OPENUSER, USERINFO_GETUSER, USERINFO_CLOSEUSER };
38 struct userinfo_state {
39 enum userinfo_stage stage;
40 struct dcerpc_pipe *pipe;
41 struct rpc_request *req;
42 struct policy_handle domain_handle;
43 struct policy_handle user_handle;
44 uint16_t level;
45 struct samr_LookupNames lookup;
46 struct samr_OpenUser openuser;
47 struct samr_QueryUserInfo queryuserinfo;
48 struct samr_Close samrclose;
49 union samr_UserInfo *info;
51 /* information about the progress */
52 void (*monitor_fn)(struct monitor_msg *);
56 /**
57 * Stage 1 (optional): Look for a username in SAM server.
59 static NTSTATUS userinfo_lookup(struct composite_context *c,
60 struct userinfo_state *s)
62 /* receive samr_Lookup reply */
63 c->status = dcerpc_ndr_request_recv(s->req);
64 NT_STATUS_NOT_OK_RETURN(c->status);
66 /* have we actually got name resolved
67 - we're looking for only one at the moment */
68 if (s->lookup.out.rids.count == 0) {
69 return NT_STATUS_NO_SUCH_USER;
72 /* TODO: find proper status code for more than one rid found */
74 /* prepare parameters for LookupNames */
75 s->openuser.in.domain_handle = &s->domain_handle;
76 s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
77 s->openuser.in.rid = s->lookup.out.rids.ids[0];
78 s->openuser.out.user_handle = &s->user_handle;
80 /* send request */
81 s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser);
82 if (s->req == NULL) goto failure;
84 s->req->async.callback = userinfo_handler;
85 s->req->async.private = c;
86 s->stage = USERINFO_OPENUSER;
88 return NT_STATUS_OK;
90 failure:
91 return NT_STATUS_UNSUCCESSFUL;
95 /**
96 * Stage 2: Open user policy handle.
98 static NTSTATUS userinfo_openuser(struct composite_context *c,
99 struct userinfo_state *s)
101 /* receive samr_OpenUser reply */
102 c->status = dcerpc_ndr_request_recv(s->req);
103 NT_STATUS_NOT_OK_RETURN(c->status);
105 /* prepare parameters for QueryUserInfo call */
106 s->queryuserinfo.in.user_handle = &s->user_handle;
107 s->queryuserinfo.in.level = s->level;
109 /* queue rpc call, set event handling and new state */
110 s->req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuserinfo);
111 if (s->req == NULL) goto failure;
113 s->req->async.callback = userinfo_handler;
114 s->req->async.private = c;
115 s->stage = USERINFO_GETUSER;
117 return NT_STATUS_OK;
119 failure:
120 return NT_STATUS_UNSUCCESSFUL;
125 * Stage 3: Get requested user information.
127 static NTSTATUS userinfo_getuser(struct composite_context *c,
128 struct userinfo_state *s)
130 /* receive samr_QueryUserInfo reply */
131 c->status = dcerpc_ndr_request_recv(s->req);
132 NT_STATUS_NOT_OK_RETURN(c->status);
134 s->info = talloc_steal(s, s->queryuserinfo.out.info);
136 /* prepare arguments for Close call */
137 s->samrclose.in.handle = &s->user_handle;
138 s->samrclose.out.handle = &s->user_handle;
140 /* queue rpc call, set event handling and new state */
141 s->req = dcerpc_samr_Close_send(s->pipe, c, &s->samrclose);
143 s->req->async.callback = userinfo_handler;
144 s->req->async.private = c;
145 s->stage = USERINFO_CLOSEUSER;
147 return NT_STATUS_OK;
152 * Stage 4: Close policy handle associated with opened user.
154 static NTSTATUS userinfo_closeuser(struct composite_context *c,
155 struct userinfo_state *s)
157 /* receive samr_Close reply */
158 c->status = dcerpc_ndr_request_recv(s->req);
159 NT_STATUS_NOT_OK_RETURN(c->status);
161 c->state = COMPOSITE_STATE_DONE;
163 return NT_STATUS_OK;
168 * Event handler for asynchronous request. Handles transition through
169 * intermediate stages of the call.
171 * @param req rpc call context
173 static void userinfo_handler(struct rpc_request *req)
175 struct composite_context *c = req->async.private;
176 struct userinfo_state *s = talloc_get_type(c->private_data, struct userinfo_state);
177 struct monitor_msg msg;
178 struct msg_rpc_lookup_name *msg_lookup;
179 struct msg_rpc_open_user *msg_open;
180 struct msg_rpc_query_user *msg_query;
181 struct msg_rpc_close_user *msg_close;
183 /* Stages of the call */
184 switch (s->stage) {
185 case USERINFO_LOOKUP:
186 c->status = userinfo_lookup(c, s);
188 msg.type = rpc_lookup_name;
189 msg_lookup = talloc(s, struct msg_rpc_lookup_name);
190 msg_lookup->rid = s->lookup.out.rids.ids;
191 msg_lookup->count = s->lookup.out.rids.count;
192 msg.data = (void*)msg_lookup;
193 msg.data_size = sizeof(*msg_lookup);
194 break;
196 case USERINFO_OPENUSER:
197 c->status = userinfo_openuser(c, s);
199 msg.type = rpc_open_user;
200 msg_open = talloc(s, struct msg_rpc_open_user);
201 msg_open->rid = s->openuser.in.rid;
202 msg_open->access_mask = s->openuser.in.access_mask;
203 msg.data = (void*)msg_open;
204 msg.data_size = sizeof(*msg_open);
205 break;
207 case USERINFO_GETUSER:
208 c->status = userinfo_getuser(c, s);
210 msg.type = rpc_query_user;
211 msg_query = talloc(s, struct msg_rpc_query_user);
212 msg_query->level = s->queryuserinfo.in.level;
213 msg.data = (void*)msg_query;
214 msg.data_size = sizeof(*msg_query);
215 break;
217 case USERINFO_CLOSEUSER:
218 c->status = userinfo_closeuser(c, s);
220 msg.type = rpc_close_user;
221 msg_close = talloc(s, struct msg_rpc_close_user);
222 msg_close->rid = s->openuser.in.rid;
223 msg.data = (void*)msg_close;
224 msg.data_size = sizeof(*msg_close);
225 break;
228 if (!NT_STATUS_IS_OK(c->status)) {
229 c->state = COMPOSITE_STATE_ERROR;
232 if (s->monitor_fn) {
233 s->monitor_fn(&msg);
236 if (c->state >= COMPOSITE_STATE_DONE &&
237 c->async.fn) {
238 c->async.fn(c);
244 * Sends asynchronous userinfo request
246 * @param p dce/rpc call pipe
247 * @param io arguments and results of the call
249 struct composite_context *libnet_rpc_userinfo_send(struct dcerpc_pipe *p,
250 struct libnet_rpc_userinfo *io,
251 void (*monitor)(struct monitor_msg*))
253 struct composite_context *c;
254 struct userinfo_state *s;
255 struct dom_sid *sid;
257 if (!p || !io) return NULL;
259 c = talloc_zero(p, struct composite_context);
260 if (c == NULL) goto failure;
262 s = talloc_zero(c, struct userinfo_state);
263 if (s == NULL) goto failure;
265 s->level = io->in.level;
266 s->pipe = p;
267 s->domain_handle = io->in.domain_handle;
268 s->monitor_fn = monitor;
270 c->state = COMPOSITE_STATE_IN_PROGRESS;
271 c->private_data = s;
272 c->event_ctx = dcerpc_event_context(p);
274 if (io->in.sid) {
275 sid = dom_sid_parse_talloc(s, io->in.sid);
276 if (sid == NULL) goto failure;
278 s->openuser.in.domain_handle = &s->domain_handle;
279 s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
280 s->openuser.in.rid = sid->sub_auths[sid->num_auths - 1];
281 s->openuser.out.user_handle = &s->user_handle;
283 /* send request */
284 s->req = dcerpc_samr_OpenUser_send(p, c, &s->openuser);
285 if (s->req == NULL) goto failure;
287 s->stage = USERINFO_OPENUSER;
289 } else {
290 /* preparing parameters to send rpc request */
291 s->lookup.in.domain_handle = &s->domain_handle;
292 s->lookup.in.num_names = 1;
293 s->lookup.in.names = talloc_array(s, struct lsa_String, 1);
295 if (composite_nomem(s->lookup.in.names, c)) return c;
296 s->lookup.in.names[0].string = talloc_strdup(s, io->in.username);
298 /* send request */
299 s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookup);
300 if (s->req == NULL) goto failure;
302 s->stage = USERINFO_LOOKUP;
305 /* callback handler */
306 s->req->async.callback = userinfo_handler;
307 s->req->async.private = c;
309 return c;
311 failure:
312 talloc_free(c);
313 return NULL;
318 * Waits for and receives result of asynchronous userinfo call
320 * @param c composite context returned by asynchronous userinfo call
321 * @param mem_ctx memory context of the call
322 * @param io pointer to results (and arguments) of the call
323 * @return nt status code of execution
326 NTSTATUS libnet_rpc_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
327 struct libnet_rpc_userinfo *io)
329 NTSTATUS status;
330 struct userinfo_state *s;
332 /* wait for results of sending request */
333 status = composite_wait(c);
335 if (NT_STATUS_IS_OK(status) && io) {
336 s = talloc_get_type(c->private_data, struct userinfo_state);
337 talloc_steal(mem_ctx, s->info);
338 io->out.info = *s->info;
341 /* memory context associated to composite context is no longer needed */
342 talloc_free(c);
343 return status;
348 * Synchronous version of userinfo call
350 * @param pipe dce/rpc call pipe
351 * @param mem_ctx memory context for the call
352 * @param io arguments and results of the call
353 * @return nt status code of execution
356 NTSTATUS libnet_rpc_userinfo(struct dcerpc_pipe *p,
357 TALLOC_CTX *mem_ctx,
358 struct libnet_rpc_userinfo *io)
360 struct composite_context *c = libnet_rpc_userinfo_send(p, io, NULL);
361 return libnet_rpc_userinfo_recv(c, mem_ctx, io);