summaryrefslogtreecommitdiff
path: root/source4/libnet/userinfo.c
blob: 88ef80c53c849ca02f4b424626fedf137e57867a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/* 
   Unix SMB/CIFS implementation.

   Copyright (C) Rafal Szczesniak 2005
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
  a composite function for getting user information via samr pipe
*/

#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
#include "librpc/gen_ndr/ndr_samr.h"

enum userinfo_stage { USERINFO_OPENUSER, USERINFO_GETUSER, USERINFO_CLOSEUSER };

struct rpc_composite_userinfo {
	struct {
		struct policy_handle domain_handle;
		const char *sid;
		uint16_t level;
	} in;
	struct {
		union samr_UserInfo info;
	} out;
};

struct userinfo_state {
	enum userinfo_stage stage;
	struct dcerpc_pipe *pipe;
	struct rpc_composite_userinfo io;
};

static void userinfo_handler(struct rpc_request *req);


static NTSTATUS userinfo_openuser(struct composite_context *c,
				  struct rpc_composite_userinfo *io)
{
	struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
	struct rpc_request *req = s->pipe->conn->pending;
	struct samr_OpenUser *rep;
	struct samr_QueryUserInfo r;

	/* receive samr_OpenUser reply */
	c->status = dcerpc_ndr_request_recv(req);
	NT_STATUS_NOT_OK_RETURN(c->status);
	rep = (struct samr_OpenUser*)req->ndr.struct_ptr;

	/* prepare parameters for QueryUserInfo call */
	r.in.user_handle = talloc_zero(c, struct policy_handle);
	memcpy((void*)r.in.user_handle, (void*)rep->out.user_handle, sizeof(struct policy_handle));
	r.in.level = io->in.level;
	
	/* queue rpc call, set event handling and new state */
	s->pipe->conn->pending = dcerpc_samr_QueryUserInfo_send(s->pipe, c, &r);
	
	s->pipe->conn->pending->async.callback = userinfo_handler;
	s->pipe->conn->pending->async.private  = c;
	s->stage = USERINFO_GETUSER;
	
	return rep->out.result;
}


static NTSTATUS userinfo_getuser(struct composite_context *c,
				 struct rpc_composite_userinfo *io)
{
	struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
	struct rpc_request *req = s->pipe->conn->pending;
	struct samr_QueryUserInfo *rep;
	struct samr_Close r;
	
	/* receive samr_QueryUserInfo reply */
	c->status = dcerpc_ndr_request_recv(req);
	NT_STATUS_NOT_OK_RETURN(c->status);
	rep = (struct samr_QueryUserInfo*)req->ndr.struct_ptr;
	
	/* prepare arguments for Close call */
	r.in.handle = talloc_zero(c, struct policy_handle);
	memcpy((void*)r.in.handle, (void*)rep->in.user_handle, sizeof(struct policy_handle));
	
	/* queue rpc call, set event handling and new state */
	s->pipe->conn->pending = dcerpc_samr_Close_send(s->pipe, c, &r);
	
	s->pipe->conn->pending->async.callback = userinfo_handler;
	s->pipe->conn->pending->async.private  = c;
	s->stage = USERINFO_CLOSEUSER;

	/* copying result of composite call */
	memcpy((void*)&io->out.info, (void*)rep->out.info, sizeof(union samr_UserInfo));

	return rep->out.result;
}


static NTSTATUS userinfo_closeuser(struct composite_context *c,
				   struct rpc_composite_userinfo *io)
{
	struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);
	struct rpc_request *req = s->pipe->conn->pending;
	struct samr_Close *rep;
	
	/* receive samr_Close reply */
	c->status = dcerpc_ndr_request_recv(req);
	NT_STATUS_NOT_OK_RETURN(c->status);
	rep = (struct samr_Close*)req->ndr.struct_ptr;

	/* return result */
	return rep->out.result;
}


static void userinfo_handler(struct rpc_request *req)
{
	struct composite_context *c = req->async.private;
	struct userinfo_state *s = talloc_get_type(c->private, struct userinfo_state);

	switch (s->stage) {
	case USERINFO_OPENUSER:
		c->status = userinfo_openuser(c, &s->io);
		break;

	case USERINFO_GETUSER:
		c->status = userinfo_getuser(c, &s->io);
		break;
		
	case USERINFO_CLOSEUSER:
		c->status = userinfo_closeuser(c, &s->io);
		break;
	}

	if (!NT_STATUS_IS_OK(c->status)) {
		/* this should be some error state instead */
		c->state = RPC_REQUEST_DONE;
	}

	if (c->state >= RPC_REQUEST_DONE &&
	    c->async.fn) {
		c->async.fn(c);
	}
}


struct composite_context* rpc_composite_userinfo_send(struct dcerpc_pipe *p,
						      struct rpc_composite_userinfo *io)
{	

	struct composite_context *c;
	struct userinfo_state *s;
	struct samr_OpenUser *r;
	struct dom_sid *sid;
	
	c = talloc_zero(p, struct composite_context);
	if (c == NULL) goto failure;
	
	s = talloc_zero(c, struct userinfo_state);
	if (s == NULL) goto failure;
	
	/* copying input parameters */
	memcpy((void*)&s->io.in.domain_handle, (void*)&io->in.domain_handle, sizeof(struct policy_handle));
	s->io.in.sid     = talloc_strdup(p, io->in.sid);
	s->io.in.level   = io->in.level;
	sid              = dom_sid_parse_talloc(c, s->io.in.sid);
	
	c->private = s;
	c->event_ctx = dcerpc_event_context(p);

	/* preparing parameters to send rpc request */
	r = talloc_zero(p, struct samr_OpenUser);
	r->in.domain_handle  = &s->io.in.domain_handle;
	r->in.access_mask    = 0;
	r->in.rid            = sid->sub_auths[sid->num_auths - 1];

	/* send request */
	s->pipe->conn->pending = dcerpc_samr_OpenUser_send(p, c, r);

	/* callback handler */
	s->pipe->conn->pending->async.callback = userinfo_handler;
	s->pipe->conn->pending->async.private  = c;
	s->stage = USERINFO_OPENUSER;

	return c;
	
failure:
	talloc_free(c);
}


NTSTATUS rpc_composite_userinfo_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
{
	NTSTATUS status;
	struct userinfo_state *s;
	
	status = composite_wait(c);
	
	if (NT_STATUS_IS_OK(status)) {
		s = talloc_get_type(c->private, struct userinfo_state);
		talloc_steal(mem_ctx, &s->io.out.info);
	}

	talloc_free(c);
	return status;
}


NTSTATUS rpc_composite_userinfo(struct dcerpc_pipe *pipe,
				TALLOC_CTX *mem_ctx,
				struct rpc_composite_userinfo *io)
{
	struct composite_context *c = rpc_composite_userinfo_send(pipe, io);
	return rpc_composite_userinfo_recv(c, mem_ctx);
}