ba24855f3e3069a69e1f51341c7552704706d736
[samba.git] / source4 / 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/raw/libcliraw.h"
27 #include "libcli/composite/composite.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
29
30 enum userinfo_stage { USERINFO_OPENUSER, USERINFO_GETUSER, USERINFO_CLOSEUSER };
31
32 struct rpc_composite_userinfo {
33         struct {
34                 struct policy_handle domain_handle;
35                 const char *sid;
36                 uint16_t level;
37         } in;
38         struct {
39                 union samr_UserInfo info;
40         } out;
41 };
42
43 struct userinfo_state {
44         enum userinfo_stage stage;
45         struct dcerpc_pipe *pipe;
46         struct rpc_composite_userinfo io;
47 };
48
49 static void userinfo_handler(struct rpc_request *req);
50
51
52 static NTSTATUS userinfo_openuser(struct composite_context *c,
53                                   struct rpc_composite_userinfo *io)
54 {
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;
59
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;
64
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;
69         
70         /* queue rpc call, set event handling and new state */
71         s->pipe->conn->pending = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &r);
72         
73         s->pipe->conn->pending->async.callback = userinfo_handler;
74         s->pipe->conn->pending->async.private  = c;
75         s->stage = USERINFO_GETUSER;
76         
77         return rep->out.result;
78 }
79
80
81 static NTSTATUS userinfo_getuser(struct composite_context *c,
82                                  struct rpc_composite_userinfo *io)
83 {
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;
87         struct samr_Close r;
88         
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;
93         
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));
97         
98         /* queue rpc call, set event handling and new state */
99         s->pipe->conn->pending = dcerpc_samr_Close_send(s->pipe, c, &r);
100         
101         s->pipe->conn->pending->async.callback = userinfo_handler;
102         s->pipe->conn->pending->async.private  = c;
103         s->stage = USERINFO_CLOSEUSER;
104
105         /* copying result of composite call */
106         memcpy((void*)&io->out.info, (void*)rep->out.info, sizeof(union samr_UserInfo));
107
108         return rep->out.result;
109 }
110
111
112 static NTSTATUS userinfo_closeuser(struct composite_context *c,
113                                    struct rpc_composite_userinfo *io)
114 {
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;
118         
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;
123
124         /* return result */
125         return rep->out.result;
126 }
127
128
129 static void userinfo_handler(struct rpc_request *req)
130 {
131         struct composite_context *c = req->async.private;
132         struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
133
134         switch (s->stage) {
135         case USERINFO_OPENUSER:
136                 c->status = userinfo_openuser(c, &s->io);
137                 break;
138
139         case USERINFO_GETUSER:
140                 c->status = userinfo_getuser(c, &s->io);
141                 break;
142                 
143         case USERINFO_CLOSEUSER:
144                 c->status = userinfo_closeuser(c, &s->io);
145                 break;
146         }
147
148         if (!NT_STATUS_IS_OK(c->status)) {
149                 /* this should be some error state instead */
150                 c->state = RPC_REQUEST_DONE;
151         }
152
153         if (c->state >= RPC_REQUEST_DONE &&
154             c->async.fn) {
155                 c->async.fn(c);
156         }
157 }
158
159
160 struct composite_context* rpc_composite_userinfo_send(struct dcerpc_pipe *p,
161                                                       struct rpc_composite_userinfo *io)
162 {       
163
164   /* dom_sid_parse_talloc call */
165         struct composite_context *c;
166         struct userinfo_state *s;
167         struct samr_OpenUser *r;
168         struct dom_sid *sid;
169         
170         c = talloc_zero(p, struct composite_context);
171         if (c == NULL) goto failure;
172         
173         s = talloc_zero(c, struct userinfo_state);
174         if (s == NULL) goto failure;
175         
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);
181         
182         c->private = s;
183         c->event_ctx = dcerpc_event_context(p);
184
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];
190
191         /* send request */
192         s->pipe->conn->pending = dcerpc_samr_OpenUser_send(p, c, r);
193
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;
198
199         return c;
200         
201 failure:
202         talloc_free(c);
203 }
204
205
206 NTSTATUS rpc_composite_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
207 {
208         NTSTATUS status;
209         struct userinfo_state *s;
210         
211         status = composite_wait(c);
212         
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);
216         }
217
218         talloc_free(c);
219         return status;
220 }
221
222
223 NTSTATUS rpc_composite_userinfo(struct dcerpc_pipe *pipe,
224                                 TALLOC_CTX *mem_ctx,
225                                 struct rpc_composite_userinfo *io)
226 {
227         struct composite_context *c = rpc_composite_userinfo_send(pipe, io);
228         return rpc_composite_userinfo_recv(c, mem_ctx);
229 }