Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : server side dcerpc handle code
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "lib/util/dlinklist.h"
24 : #include "rpc_server/dcerpc_server.h"
25 : #include "libcli/security/security.h"
26 : #include "librpc/gen_ndr/auth.h"
27 :
28 : /*
29 : destroy a rpc handle
30 : */
31 124712 : static int dcesrv_handle_destructor(struct dcesrv_handle *h)
32 : {
33 124712 : DLIST_REMOVE(h->assoc_group->handles, h);
34 124712 : return 0;
35 : }
36 :
37 :
38 : /*
39 : allocate a new rpc handle
40 : */
41 : _PUBLIC_
42 122609 : struct dcesrv_handle *dcesrv_handle_create(struct dcesrv_call_state *call,
43 : uint8_t handle_type)
44 : {
45 122609 : struct dcesrv_connection_context *context = call->context;
46 591 : struct auth_session_info *session_info =
47 122609 : dcesrv_call_session_info(call);
48 591 : struct dcesrv_handle *h;
49 591 : struct dom_sid *sid;
50 :
51 : /*
52 : * For simplicity, ensure we abort here for an interface that
53 : * has no handles (programmer error)
54 : */
55 122609 : SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
56 :
57 122609 : sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
58 :
59 122609 : h = talloc_zero(context->conn->assoc_group, struct dcesrv_handle);
60 122609 : if (!h) {
61 0 : return NULL;
62 : }
63 122609 : h->data = NULL;
64 122609 : sid_copy(&h->sid, sid);
65 122609 : h->min_auth_level = call->auth_state->auth_level;
66 122609 : h->assoc_group = context->conn->assoc_group;
67 122609 : h->iface = context->iface;
68 122609 : h->wire_handle.handle_type = handle_type;
69 122609 : h->wire_handle.uuid = GUID_random();
70 :
71 122609 : DLIST_ADD(context->conn->assoc_group->handles, h);
72 :
73 122609 : talloc_set_destructor(h, dcesrv_handle_destructor);
74 :
75 122609 : return h;
76 : }
77 :
78 : /**
79 : find an internal handle given a wire handle. If the wire handle is NULL then
80 : allocate a new handle
81 : */
82 :
83 : _PUBLIC_
84 762129 : struct dcesrv_handle *dcesrv_handle_lookup(struct dcesrv_call_state *call,
85 : const struct policy_handle *p,
86 : uint8_t handle_type)
87 : {
88 762129 : struct dcesrv_connection_context *context = call->context;
89 977 : struct auth_session_info *session_info =
90 762129 : dcesrv_call_session_info(call);
91 977 : struct dcesrv_handle *h;
92 977 : struct dom_sid *sid;
93 :
94 : /*
95 : * For simplicity, ensure we abort here for an interface that
96 : * has no handles (programmer error)
97 : */
98 762129 : SMB_ASSERT((context->iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) == 0);
99 :
100 762129 : sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
101 :
102 762129 : if (ndr_policy_handle_empty(p)) {
103 : /* TODO: we should probably return a NULL handle here */
104 14 : return dcesrv_handle_create(call, handle_type);
105 : }
106 :
107 762115 : if (handle_type != DCESRV_HANDLE_ANY &&
108 29973 : p->handle_type != handle_type) {
109 0 : DBG_WARNING("client gave us the wrong handle type "
110 : "(%"PRIu32" should be %"PRIu8")\n",
111 : p->handle_type,
112 : handle_type);
113 0 : return NULL;
114 : }
115 :
116 1279912 : for (h=context->conn->assoc_group->handles; h; h=h->next) {
117 2266612 : if (h->wire_handle.handle_type == p->handle_type &&
118 986916 : GUID_equal(&p->uuid, &h->wire_handle.uuid)) {
119 760951 : break;
120 : }
121 : }
122 :
123 762115 : if (h == NULL) {
124 : /* not found */
125 187 : return NULL;
126 : }
127 :
128 761899 : if (!dom_sid_equal(&h->sid, sid)) {
129 0 : struct dom_sid_buf buf1, buf2;
130 0 : DBG_ERR("Attempt to use invalid sid %s - %s\n",
131 : dom_sid_str_buf(&h->sid, &buf1),
132 : dom_sid_str_buf(sid, &buf2));
133 0 : return NULL;
134 : }
135 :
136 761899 : if (call->auth_state->auth_level < h->min_auth_level) {
137 0 : DBG_ERR("Attempt to use invalid auth_level %u < %u\n",
138 : call->auth_state->auth_level,
139 : h->min_auth_level);
140 0 : return NULL;
141 : }
142 :
143 761899 : if (h->iface != context->iface) {
144 12 : DBG_ERR("Attempt to use invalid iface\n");
145 12 : return NULL;
146 : }
147 :
148 760942 : return h;
149 : }
150 :
151 : struct dcesrv_iface_state {
152 : struct dcesrv_iface_state *prev, *next;
153 : struct dcesrv_assoc_group *assoc;
154 : const struct dcesrv_interface *iface;
155 : struct dom_sid owner;
156 : const struct dcesrv_connection *conn;
157 : const struct dcesrv_auth *auth;
158 : const struct dcesrv_connection_context *pres;
159 : uint64_t magic;
160 : void *ptr;
161 : const char *location;
162 : };
163 :
164 15092 : static int dcesrv_iface_state_destructor(struct dcesrv_iface_state *istate)
165 : {
166 15092 : DLIST_REMOVE(istate->assoc->iface_states, istate);
167 15092 : return 0;
168 : }
169 :
170 55101 : static void *dcesrv_iface_state_find(struct dcesrv_assoc_group *assoc,
171 : const struct dcesrv_interface *iface,
172 : const struct dom_sid *owner,
173 : const struct dcesrv_connection *conn,
174 : const struct dcesrv_auth *auth,
175 : const struct dcesrv_connection_context *pres,
176 : uint64_t magic,
177 : const void *ptr)
178 : {
179 55101 : struct dcesrv_iface_state *cur = NULL;
180 :
181 74073 : for (cur = assoc->iface_states; cur != NULL; cur = cur->next) {
182 4165 : bool match;
183 :
184 53251 : SMB_ASSERT(cur->assoc == assoc);
185 :
186 53251 : if (cur->ptr == ptr) {
187 0 : return cur->ptr;
188 : }
189 :
190 53251 : if (cur->iface != iface) {
191 0 : continue;
192 : }
193 :
194 53251 : match = dom_sid_equal(&cur->owner, owner);
195 53251 : if (!match) {
196 16024 : continue;
197 : }
198 :
199 37227 : if (cur->conn != conn) {
200 1385 : continue;
201 : }
202 :
203 35842 : if (cur->auth != auth) {
204 0 : continue;
205 : }
206 :
207 35842 : if (cur->pres != pres) {
208 0 : continue;
209 : }
210 :
211 35842 : if (cur->magic != magic) {
212 1563 : continue;
213 : }
214 :
215 34279 : return cur->ptr;
216 : }
217 :
218 19447 : return NULL;
219 : }
220 :
221 15074 : static NTSTATUS dcesrv_iface_state_store(struct dcesrv_assoc_group *assoc,
222 : const struct dcesrv_interface *iface,
223 : const struct dom_sid *owner,
224 : const struct dcesrv_connection *conn,
225 : const struct dcesrv_auth *auth,
226 : const struct dcesrv_connection_context *pres,
227 : uint64_t magic,
228 : TALLOC_CTX *mem_ctx,
229 : void *ptr,
230 : const char *location)
231 : {
232 15074 : struct dcesrv_iface_state *istate = NULL;
233 15074 : void *optr = NULL;
234 :
235 15074 : optr = dcesrv_iface_state_find(assoc,
236 : iface,
237 : owner,
238 : conn,
239 : auth,
240 : pres,
241 : magic,
242 : ptr);
243 15074 : if (optr != NULL) {
244 0 : return NT_STATUS_OBJECTID_EXISTS;
245 : }
246 :
247 15074 : istate = talloc_zero(ptr, struct dcesrv_iface_state);
248 15074 : if (istate == NULL) {
249 0 : return NT_STATUS_NO_MEMORY;
250 : }
251 :
252 15074 : *istate = (struct dcesrv_iface_state) {
253 : .assoc = assoc,
254 : .iface = iface,
255 15074 : .owner = *owner,
256 : .conn = conn,
257 : .auth = auth,
258 : .pres = pres,
259 : .magic = magic,
260 : .location = location,
261 : };
262 :
263 15074 : istate->ptr = talloc_steal(mem_ctx, ptr);
264 :
265 15074 : talloc_set_destructor(istate, dcesrv_iface_state_destructor);
266 :
267 15074 : DLIST_ADD_END(assoc->iface_states, istate);
268 :
269 15074 : return NT_STATUS_OK;
270 : }
271 :
272 2 : NTSTATUS _dcesrv_iface_state_store_assoc(struct dcesrv_call_state *call,
273 : uint64_t magic,
274 : void *ptr,
275 : const char *location)
276 : {
277 0 : struct auth_session_info *session_info =
278 2 : dcesrv_call_session_info(call);
279 2 : const struct dom_sid *owner =
280 2 : &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
281 0 : NTSTATUS status;
282 :
283 2 : status = dcesrv_iface_state_store(call->conn->assoc_group,
284 2 : call->context->iface,
285 : owner,
286 : NULL, /* conn */
287 : NULL, /* auth */
288 : NULL, /* pres */
289 : magic,
290 2 : call->conn->assoc_group, /* mem_ctx */
291 : ptr,
292 : location);
293 2 : if (!NT_STATUS_IS_OK(status)) {
294 0 : return status;
295 : }
296 :
297 2 : return NT_STATUS_OK;
298 : }
299 :
300 4 : void *_dcesrv_iface_state_find_assoc(struct dcesrv_call_state *call, uint64_t magic)
301 : {
302 0 : struct auth_session_info *session_info =
303 4 : dcesrv_call_session_info(call);
304 4 : const struct dom_sid *owner =
305 4 : &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
306 4 : void *ptr = NULL;
307 :
308 4 : ptr = dcesrv_iface_state_find(call->conn->assoc_group,
309 4 : call->context->iface,
310 : owner,
311 : NULL, /* conn */
312 : NULL, /* auth */
313 : NULL, /* pres */
314 : magic,
315 : NULL); /* ptr */
316 4 : if (ptr == NULL) {
317 2 : return NULL;
318 : }
319 :
320 2 : return ptr;
321 : }
322 :
323 15072 : NTSTATUS _dcesrv_iface_state_store_conn(struct dcesrv_call_state *call,
324 : uint64_t magic,
325 : void *ptr,
326 : const char *location)
327 : {
328 974 : struct auth_session_info *session_info =
329 15072 : dcesrv_call_session_info(call);
330 15072 : const struct dom_sid *owner =
331 15072 : &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
332 974 : NTSTATUS status;
333 :
334 15072 : status = dcesrv_iface_state_store(call->conn->assoc_group,
335 14098 : call->context->iface,
336 : owner,
337 14098 : call->conn,
338 15072 : call->auth_state,
339 15072 : call->context,
340 : magic,
341 15072 : call->conn, /* mem_ctx */
342 : ptr,
343 : location);
344 15072 : if (!NT_STATUS_IS_OK(status)) {
345 0 : return status;
346 : }
347 :
348 15072 : return NT_STATUS_OK;
349 : }
350 :
351 40023 : void *_dcesrv_iface_state_find_conn(struct dcesrv_call_state *call, uint64_t magic)
352 : {
353 2566 : struct auth_session_info *session_info =
354 40023 : dcesrv_call_session_info(call);
355 40023 : const struct dom_sid *owner =
356 40023 : &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
357 40023 : void *ptr = NULL;
358 :
359 42589 : ptr = dcesrv_iface_state_find(call->conn->assoc_group,
360 37457 : call->context->iface,
361 : owner,
362 40023 : call->conn,
363 40023 : call->auth_state,
364 40023 : call->context,
365 : magic,
366 : NULL); /* ptr */
367 40023 : if (ptr == NULL) {
368 5746 : return NULL;
369 : }
370 :
371 32112 : return ptr;
372 : }
|