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
26 #include "libcli/raw/libcliraw.h"
27 #include "libcli/composite/composite.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
30 enum userinfo_stage { USERINFO_OPENUSER, USERINFO_GETUSER, USERINFO_CLOSEUSER };
32 struct rpc_composite_userinfo {
34 struct policy_handle domain_handle;
39 union samr_UserInfo info;
43 struct userinfo_state {
44 enum userinfo_stage stage;
45 struct dcerpc_pipe *pipe;
46 struct rpc_composite_userinfo io;
49 static void userinfo_handler(struct rpc_request *req);
52 static NTSTATUS userinfo_openuser(struct composite_context *c,
53 struct rpc_composite_userinfo *io)
55 struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
56 struct rpc_request *req = s->pipe->conn->pending;
57 struct samr_OpenUser *rep;
58 struct samr_QueryUserInfo r;
60 /* receive samr_OpenUser reply */
61 c->status = dcerpc_ndr_request_recv(req);
62 NT_STATUS_NOT_OK_RETURN(c->status);
63 rep = (struct samr_OpenUser*)req->ndr.struct_ptr;
65 /* prepare parameters for QueryUserInfo call */
66 r.in.user_handle = talloc_zero(c, struct policy_handle);
67 memcpy((void*)r.in.user_handle, (void*)rep->out.user_handle, sizeof(struct policy_handle));
68 r.in.level = io->in.level;
70 /* queue rpc call, set event handling and new state */
71 s->pipe->conn->pending = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &r);
73 s->pipe->conn->pending->async.callback = userinfo_handler;
74 s->pipe->conn->pending->async.private = c;
75 s->stage = USERINFO_GETUSER;
77 return rep->out.result;
81 static NTSTATUS userinfo_getuser(struct composite_context *c,
82 struct rpc_composite_userinfo *io)
84 struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
85 struct rpc_request *req = s->pipe->conn->pending;
86 struct samr_QueryUserInfo *rep;
89 /* receive samr_QueryUserInfo reply */
90 c->status = dcerpc_ndr_request_recv(req);
91 NT_STATUS_NOT_OK_RETURN(c->status);
92 rep = (struct samr_QueryUserInfo*)req->ndr.struct_ptr;
94 /* prepare arguments for Close call */
95 r.in.handle = talloc_zero(c, struct policy_handle);
96 memcpy((void*)r.in.handle, (void*)rep->in.user_handle, sizeof(struct policy_handle));
98 /* queue rpc call, set event handling and new state */
99 s->pipe->conn->pending = dcerpc_samr_Close_send(s->pipe, c, &r);
101 s->pipe->conn->pending->async.callback = userinfo_handler;
102 s->pipe->conn->pending->async.private = c;
103 s->stage = USERINFO_CLOSEUSER;
105 /* copying result of composite call */
106 memcpy((void*)&io->out.info, (void*)rep->out.info, sizeof(union samr_UserInfo));
108 return rep->out.result;
112 static NTSTATUS userinfo_closeuser(struct composite_context *c,
113 struct rpc_composite_userinfo *io)
115 struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
116 struct rpc_request *req = s->pipe->conn->pending;
117 struct samr_Close *rep;
119 /* receive samr_Close reply */
120 c->status = dcerpc_ndr_request_recv(req);
121 NT_STATUS_NOT_OK_RETURN(c->status);
122 rep = (struct samr_Close*)req->ndr.struct_ptr;
125 return rep->out.result;
129 static void userinfo_handler(struct rpc_request *req)
131 struct composite_context *c = req->async.private;
132 struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
135 case USERINFO_OPENUSER:
136 c->status = userinfo_openuser(c, &s->io);
139 case USERINFO_GETUSER:
140 c->status = userinfo_getuser(c, &s->io);
143 case USERINFO_CLOSEUSER:
144 c->status = userinfo_closeuser(c, &s->io);
148 if (!NT_STATUS_IS_OK(c->status)) {
149 /* this should be some error state instead */
150 c->state = RPC_REQUEST_DONE;
153 if (c->state >= RPC_REQUEST_DONE &&
160 struct composite_context* rpc_composite_userinfo_send(struct dcerpc_pipe *p,
161 struct rpc_composite_userinfo *io)
164 /* dom_sid_parse_talloc call */
165 struct composite_context *c;
166 struct userinfo_state *s;
167 struct samr_OpenUser *r;
170 c = talloc_zero(p, struct composite_context);
171 if (c == NULL) goto failure;
173 s = talloc_zero(c, struct userinfo_state);
174 if (s == NULL) goto failure;
176 /* copying input parameters */
177 memcpy((void*)&s->io.in.domain_handle, (void*)&io->in.domain_handle, sizeof(struct policy_handle));
178 s->io.in.sid = talloc_strdup(p, io->in.sid);
179 s->io.in.level = io->in.level;
180 sid = dom_sid_parse_talloc(c, s->io.in.sid);
183 c->event_ctx = dcerpc_event_context(p);
185 /* preparing parameters to send rpc request */
186 r = talloc_zero(p, struct samr_OpenUser);
187 r->in.domain_handle = &s->io.in.domain_handle;
188 r->in.access_mask = 0;
189 r->in.rid = sid->sub_auths[sid->num_auths - 1];
192 s->pipe->conn->pending = dcerpc_samr_OpenUser_send(p, c, r);
194 /* callback handler */
195 s->pipe->conn->pending->async.callback = userinfo_handler;
196 s->pipe->conn->pending->async.private = c;
197 s->stage = USERINFO_OPENUSER;
206 NTSTATUS rpc_composite_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
209 struct userinfo_state *s;
211 status = composite_wait(c);
213 if (NT_STATUS_IS_OK(status)) {
214 s = talloc_get_type(c->private, struct userinfo_state);
215 talloc_steal(mem_ctx, &s->io.out.info);
223 NTSTATUS rpc_composite_userinfo(struct dcerpc_pipe *pipe,
225 struct rpc_composite_userinfo *io)
227 struct composite_context *c = rpc_composite_userinfo_send(pipe, io);
228 return rpc_composite_userinfo_recv(c, mem_ctx);