r21187: - Convert LdbBrowse to use TreeVirtual. This adds the following capabilities
[Samba/ekacnet.git] / source4 / libnet / userinfo.c
blob57a30e59dc877c31144263f9a37f860d4e86eb4a
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 /* there could be a problem with name resolving itself */
67 NT_STATUS_NOT_OK_RETURN(s->lookup.out.result);
69 /* have we actually got name resolved
70 - we're looking for only one at the moment */
71 if (s->lookup.out.rids.count == 0) {
72 return NT_STATUS_NO_SUCH_USER;
75 /* TODO: find proper status code for more than one rid found */
77 /* prepare parameters for LookupNames */
78 s->openuser.in.domain_handle = &s->domain_handle;
79 s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
80 s->openuser.in.rid = s->lookup.out.rids.ids[0];
81 s->openuser.out.user_handle = &s->user_handle;
83 /* send request */
84 s->req = dcerpc_samr_OpenUser_send(s->pipe, c, &s->openuser);
85 if (s->req == NULL) goto failure;
87 s->req->async.callback = userinfo_handler;
88 s->req->async.private = c;
89 s->stage = USERINFO_OPENUSER;
91 return NT_STATUS_OK;
93 failure:
94 return NT_STATUS_UNSUCCESSFUL;
98 /**
99 * Stage 2: Open user policy handle.
101 static NTSTATUS userinfo_openuser(struct composite_context *c,
102 struct userinfo_state *s)
104 /* receive samr_OpenUser reply */
105 c->status = dcerpc_ndr_request_recv(s->req);
106 NT_STATUS_NOT_OK_RETURN(c->status);
108 /* prepare parameters for QueryUserInfo call */
109 s->queryuserinfo.in.user_handle = &s->user_handle;
110 s->queryuserinfo.in.level = s->level;
112 /* queue rpc call, set event handling and new state */
113 s->req = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &s->queryuserinfo);
114 if (s->req == NULL) goto failure;
116 s->req->async.callback = userinfo_handler;
117 s->req->async.private = c;
118 s->stage = USERINFO_GETUSER;
120 return NT_STATUS_OK;
122 failure:
123 return NT_STATUS_UNSUCCESSFUL;
128 * Stage 3: Get requested user information.
130 static NTSTATUS userinfo_getuser(struct composite_context *c,
131 struct userinfo_state *s)
133 /* receive samr_QueryUserInfo reply */
134 c->status = dcerpc_ndr_request_recv(s->req);
135 NT_STATUS_NOT_OK_RETURN(c->status);
137 /* check if queryuser itself went ok */
138 NT_STATUS_NOT_OK_RETURN(s->queryuserinfo.out.result);
140 s->info = talloc_steal(s, s->queryuserinfo.out.info);
142 /* prepare arguments for Close call */
143 s->samrclose.in.handle = &s->user_handle;
144 s->samrclose.out.handle = &s->user_handle;
146 /* queue rpc call, set event handling and new state */
147 s->req = dcerpc_samr_Close_send(s->pipe, c, &s->samrclose);
149 s->req->async.callback = userinfo_handler;
150 s->req->async.private = c;
151 s->stage = USERINFO_CLOSEUSER;
153 return NT_STATUS_OK;
158 * Stage 4: Close policy handle associated with opened user.
160 static NTSTATUS userinfo_closeuser(struct composite_context *c,
161 struct userinfo_state *s)
163 /* receive samr_Close reply */
164 c->status = dcerpc_ndr_request_recv(s->req);
165 NT_STATUS_NOT_OK_RETURN(c->status);
167 c->state = COMPOSITE_STATE_DONE;
169 return NT_STATUS_OK;
174 * Event handler for asynchronous request. Handles transition through
175 * intermediate stages of the call.
177 * @param req rpc call context
179 static void userinfo_handler(struct rpc_request *req)
181 struct composite_context *c = req->async.private;
182 struct userinfo_state *s = talloc_get_type(c->private_data, struct userinfo_state);
183 struct monitor_msg msg;
184 struct msg_rpc_lookup_name *msg_lookup;
185 struct msg_rpc_open_user *msg_open;
186 struct msg_rpc_query_user *msg_query;
187 struct msg_rpc_close_user *msg_close;
189 /* Stages of the call */
190 switch (s->stage) {
191 case USERINFO_LOOKUP:
192 c->status = userinfo_lookup(c, s);
194 msg.type = rpc_lookup_name;
195 msg_lookup = talloc(s, struct msg_rpc_lookup_name);
196 msg_lookup->rid = s->lookup.out.rids.ids;
197 msg_lookup->count = s->lookup.out.rids.count;
198 msg.data = (void*)msg_lookup;
199 msg.data_size = sizeof(*msg_lookup);
200 break;
202 case USERINFO_OPENUSER:
203 c->status = userinfo_openuser(c, s);
205 msg.type = rpc_open_user;
206 msg_open = talloc(s, struct msg_rpc_open_user);
207 msg_open->rid = s->openuser.in.rid;
208 msg_open->access_mask = s->openuser.in.access_mask;
209 msg.data = (void*)msg_open;
210 msg.data_size = sizeof(*msg_open);
211 break;
213 case USERINFO_GETUSER:
214 c->status = userinfo_getuser(c, s);
216 msg.type = rpc_query_user;
217 msg_query = talloc(s, struct msg_rpc_query_user);
218 msg_query->level = s->queryuserinfo.in.level;
219 msg.data = (void*)msg_query;
220 msg.data_size = sizeof(*msg_query);
221 break;
223 case USERINFO_CLOSEUSER:
224 c->status = userinfo_closeuser(c, s);
226 msg.type = rpc_close_user;
227 msg_close = talloc(s, struct msg_rpc_close_user);
228 msg_close->rid = s->openuser.in.rid;
229 msg.data = (void*)msg_close;
230 msg.data_size = sizeof(*msg_close);
231 break;
234 if (!NT_STATUS_IS_OK(c->status)) {
235 c->state = COMPOSITE_STATE_ERROR;
238 if (s->monitor_fn) {
239 s->monitor_fn(&msg);
242 if (c->state >= COMPOSITE_STATE_DONE &&
243 c->async.fn) {
244 c->async.fn(c);
250 * Sends asynchronous userinfo request
252 * @param p dce/rpc call pipe
253 * @param io arguments and results of the call
255 struct composite_context *libnet_rpc_userinfo_send(struct dcerpc_pipe *p,
256 struct libnet_rpc_userinfo *io,
257 void (*monitor)(struct monitor_msg*))
259 struct composite_context *c;
260 struct userinfo_state *s;
261 struct dom_sid *sid;
263 if (!p || !io) return NULL;
265 c = talloc_zero(p, struct composite_context);
266 if (c == NULL) goto failure;
268 s = talloc_zero(c, struct userinfo_state);
269 if (s == NULL) goto failure;
271 s->level = io->in.level;
272 s->pipe = p;
273 s->domain_handle = io->in.domain_handle;
274 s->monitor_fn = monitor;
276 c->state = COMPOSITE_STATE_IN_PROGRESS;
277 c->private_data = s;
278 c->event_ctx = dcerpc_event_context(p);
280 if (io->in.sid) {
281 sid = dom_sid_parse_talloc(s, io->in.sid);
282 if (sid == NULL) goto failure;
284 s->openuser.in.domain_handle = &s->domain_handle;
285 s->openuser.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
286 s->openuser.in.rid = sid->sub_auths[sid->num_auths - 1];
287 s->openuser.out.user_handle = &s->user_handle;
289 /* send request */
290 s->req = dcerpc_samr_OpenUser_send(p, c, &s->openuser);
291 if (s->req == NULL) goto failure;
293 s->stage = USERINFO_OPENUSER;
295 } else {
296 /* preparing parameters to send rpc request */
297 s->lookup.in.domain_handle = &s->domain_handle;
298 s->lookup.in.num_names = 1;
299 s->lookup.in.names = talloc_array(s, struct lsa_String, 1);
301 if (composite_nomem(s->lookup.in.names, c)) return c;
302 s->lookup.in.names[0].string = talloc_strdup(s, io->in.username);
304 /* send request */
305 s->req = dcerpc_samr_LookupNames_send(p, c, &s->lookup);
306 if (s->req == NULL) goto failure;
308 s->stage = USERINFO_LOOKUP;
311 /* callback handler */
312 s->req->async.callback = userinfo_handler;
313 s->req->async.private = c;
315 return c;
317 failure:
318 talloc_free(c);
319 return NULL;
324 * Waits for and receives result of asynchronous userinfo call
326 * @param c composite context returned by asynchronous userinfo call
327 * @param mem_ctx memory context of the call
328 * @param io pointer to results (and arguments) of the call
329 * @return nt status code of execution
332 NTSTATUS libnet_rpc_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
333 struct libnet_rpc_userinfo *io)
335 NTSTATUS status;
336 struct userinfo_state *s;
338 /* wait for results of sending request */
339 status = composite_wait(c);
341 if (NT_STATUS_IS_OK(status) && io) {
342 s = talloc_get_type(c->private_data, struct userinfo_state);
343 talloc_steal(mem_ctx, s->info);
344 io->out.info = *s->info;
347 /* memory context associated to composite context is no longer needed */
348 talloc_free(c);
349 return status;
354 * Synchronous version of userinfo call
356 * @param pipe dce/rpc call pipe
357 * @param mem_ctx memory context for the call
358 * @param io arguments and results of the call
359 * @return nt status code of execution
362 NTSTATUS libnet_rpc_userinfo(struct dcerpc_pipe *p,
363 TALLOC_CTX *mem_ctx,
364 struct libnet_rpc_userinfo *io)
366 struct composite_context *c = libnet_rpc_userinfo_send(p, io, NULL);
367 return libnet_rpc_userinfo_recv(c, mem_ctx, io);