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 "libcli/composite/monitor.h"
29 #include "librpc/gen_ndr/ndr_samr.h"
30 #include "libnet/composite.h"
32 static void userinfo_handler(struct rpc_request
*req
);
34 enum userinfo_stage
{ USERINFO_OPENUSER
, USERINFO_GETUSER
, USERINFO_CLOSEUSER
};
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
;
42 struct samr_OpenUser openuser
;
43 struct samr_QueryUserInfo queryuserinfo
;
44 struct samr_Close samrclose
;
45 union samr_UserInfo
*info
;
50 * Stage 1: Open user policy handle in SAM server.
52 static NTSTATUS
userinfo_openuser(struct composite_context
*c
,
53 struct userinfo_state
*s
)
55 /* receive samr_OpenUser reply */
56 c
->status
= dcerpc_ndr_request_recv(s
->req
);
57 NT_STATUS_NOT_OK_RETURN(c
->status
);
59 /* prepare parameters for QueryUserInfo call */
60 s
->queryuserinfo
.in
.user_handle
= &s
->user_handle
;
61 s
->queryuserinfo
.in
.level
= s
->level
;
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
;
67 s
->req
->async
.callback
= userinfo_handler
;
68 s
->req
->async
.private = c
;
69 s
->stage
= USERINFO_GETUSER
;
74 return NT_STATUS_UNSUCCESSFUL
;
79 * Stage 2: Get requested user information.
81 static NTSTATUS
userinfo_getuser(struct composite_context
*c
,
82 struct userinfo_state
*s
)
84 /* receive samr_QueryUserInfo reply */
85 c
->status
= dcerpc_ndr_request_recv(s
->req
);
86 NT_STATUS_NOT_OK_RETURN(c
->status
);
88 s
->info
= talloc_steal(s
, s
->queryuserinfo
.out
.info
);
90 /* prepare arguments for Close call */
91 s
->samrclose
.in
.handle
= &s
->user_handle
;
92 s
->samrclose
.out
.handle
= &s
->user_handle
;
94 /* queue rpc call, set event handling and new state */
95 s
->req
= dcerpc_samr_Close_send(s
->pipe
, c
, &s
->samrclose
);
97 s
->req
->async
.callback
= userinfo_handler
;
98 s
->req
->async
.private = c
;
99 s
->stage
= USERINFO_CLOSEUSER
;
106 * Stage 3: Close policy handle associated with opened user.
108 static NTSTATUS
userinfo_closeuser(struct composite_context
*c
,
109 struct userinfo_state
*s
)
111 /* receive samr_Close reply */
112 c
->status
= dcerpc_ndr_request_recv(s
->req
);
113 NT_STATUS_NOT_OK_RETURN(c
->status
);
115 c
->state
= SMBCLI_REQUEST_DONE
;
122 * Event handler for asynchronous request. Handles transition through
123 * intermediate stages of the call.
125 * @param req rpc call context
127 static void userinfo_handler(struct rpc_request
*req
)
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
;
133 /* Stages of the call */
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
;
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
;
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
;
155 if (!NT_STATUS_IS_OK(c
->status
)) {
156 c
->state
= SMBCLI_REQUEST_ERROR
;
163 if (c
->state
>= SMBCLI_REQUEST_DONE
&&
171 * Sends asynchronous userinfo request
173 * @param p dce/rpc call pipe
174 * @param io arguments and results of the call
176 struct composite_context
*libnet_rpc_userinfo_send(struct dcerpc_pipe
*p
,
177 struct libnet_rpc_userinfo
*io
,
178 void (*monitor
)(struct monitor_msg
*))
180 struct composite_context
*c
;
181 struct userinfo_state
*s
;
184 c
= talloc_zero(p
, struct composite_context
);
185 if (c
== NULL
) goto failure
;
187 s
= talloc_zero(c
, struct userinfo_state
);
188 if (s
== NULL
) goto failure
;
190 s
->level
= io
->in
.level
;
193 sid
= dom_sid_parse_talloc(s
, io
->in
.sid
);
194 if (sid
== NULL
) goto failure
;
195 c
->state
= SMBCLI_REQUEST_SEND
;
197 c
->event_ctx
= dcerpc_event_context(p
);
198 c
->monitor_fn
= monitor
;
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
;
207 s
->req
= dcerpc_samr_OpenUser_send(p
, c
, &s
->openuser
);
209 /* callback handler */
210 s
->req
->async
.callback
= userinfo_handler
;
211 s
->req
->async
.private = c
;
212 s
->stage
= USERINFO_OPENUSER
;
223 * Waits for and receives result of asynchronous userinfo call
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
231 NTSTATUS
libnet_rpc_userinfo_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
,
232 struct libnet_rpc_userinfo
*io
)
235 struct userinfo_state
*s
;
237 /* wait for results of sending request */
238 status
= composite_wait(c
);
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
;
246 /* memory context associated to composite context is no longer needed */
253 * Synchronous version of userinfo call
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
261 NTSTATUS
libnet_rpc_userinfo(struct dcerpc_pipe
*pipe
,
263 struct libnet_rpc_userinfo
*io
)
265 struct composite_context
*c
= libnet_rpc_userinfo_send(pipe
, io
, NULL
);
266 return libnet_rpc_userinfo_recv(c
, mem_ctx
, io
);