2 Unix SMB/CIFS implementation.
4 server side dcerpc handle code
6 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
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"
31 static int dcesrv_handle_destructor(struct dcesrv_handle
*h
)
33 DLIST_REMOVE(h
->assoc_group
->handles
, h
);
39 allocate a new rpc handle
42 struct dcesrv_handle
*dcesrv_handle_create(struct dcesrv_call_state
*call
,
45 struct dcesrv_connection_context
*context
= call
->context
;
46 struct auth_session_info
*session_info
=
47 dcesrv_call_session_info(call
);
48 struct dcesrv_handle
*h
;
52 * For simplicity, ensure we abort here for an interface that
53 * has no handles (programmer error)
55 SMB_ASSERT((context
->iface
->flags
& DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
) == 0);
57 sid
= &session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
59 h
= talloc_zero(context
->conn
->assoc_group
, struct dcesrv_handle
);
64 sid_copy(&h
->sid
, sid
);
65 h
->min_auth_level
= call
->auth_state
->auth_level
;
66 h
->assoc_group
= context
->conn
->assoc_group
;
67 h
->iface
= context
->iface
;
68 h
->wire_handle
.handle_type
= handle_type
;
69 h
->wire_handle
.uuid
= GUID_random();
71 DLIST_ADD(context
->conn
->assoc_group
->handles
, h
);
73 talloc_set_destructor(h
, dcesrv_handle_destructor
);
79 find an internal handle given a wire handle. If the wire handle is NULL then
84 struct dcesrv_handle
*dcesrv_handle_lookup(struct dcesrv_call_state
*call
,
85 const struct policy_handle
*p
,
88 struct dcesrv_connection_context
*context
= call
->context
;
89 struct auth_session_info
*session_info
=
90 dcesrv_call_session_info(call
);
91 struct dcesrv_handle
*h
;
95 * For simplicity, ensure we abort here for an interface that
96 * has no handles (programmer error)
98 SMB_ASSERT((context
->iface
->flags
& DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
) == 0);
100 sid
= &session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
102 if (ndr_policy_handle_empty(p
)) {
103 /* TODO: we should probably return a NULL handle here */
104 return dcesrv_handle_create(call
, handle_type
);
107 if (handle_type
!= DCESRV_HANDLE_ANY
&&
108 p
->handle_type
!= handle_type
) {
109 DBG_WARNING("client gave us the wrong handle type "
110 "(%"PRIu32
" should be %"PRIu8
")\n",
116 for (h
=context
->conn
->assoc_group
->handles
; h
; h
=h
->next
) {
117 if (h
->wire_handle
.handle_type
== p
->handle_type
&&
118 GUID_equal(&p
->uuid
, &h
->wire_handle
.uuid
)) {
128 if (!dom_sid_equal(&h
->sid
, sid
)) {
129 struct dom_sid_buf buf1
, buf2
;
130 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
));
136 if (call
->auth_state
->auth_level
< h
->min_auth_level
) {
137 DBG_ERR("Attempt to use invalid auth_level %u < %u\n",
138 call
->auth_state
->auth_level
,
143 if (h
->iface
!= context
->iface
) {
144 DBG_ERR("Attempt to use invalid iface\n");
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
;
161 const char *location
;
164 static int dcesrv_iface_state_destructor(struct dcesrv_iface_state
*istate
)
166 DLIST_REMOVE(istate
->assoc
->iface_states
, istate
);
170 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
,
179 struct dcesrv_iface_state
*cur
= NULL
;
181 for (cur
= assoc
->iface_states
; cur
!= NULL
; cur
= cur
->next
) {
184 SMB_ASSERT(cur
->assoc
== assoc
);
186 if (cur
->ptr
== ptr
) {
190 if (cur
->iface
!= iface
) {
194 match
= dom_sid_equal(&cur
->owner
, owner
);
199 if (cur
->conn
!= conn
) {
203 if (cur
->auth
!= auth
) {
207 if (cur
->pres
!= pres
) {
211 if (cur
->magic
!= magic
) {
221 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
,
230 const char *location
)
232 struct dcesrv_iface_state
*istate
= NULL
;
235 optr
= dcesrv_iface_state_find(assoc
,
244 return NT_STATUS_OBJECTID_EXISTS
;
247 istate
= talloc_zero(ptr
, struct dcesrv_iface_state
);
248 if (istate
== NULL
) {
249 return NT_STATUS_NO_MEMORY
;
252 *istate
= (struct dcesrv_iface_state
) {
260 .location
= location
,
263 istate
->ptr
= talloc_steal(mem_ctx
, ptr
);
265 talloc_set_destructor(istate
, dcesrv_iface_state_destructor
);
267 DLIST_ADD_END(assoc
->iface_states
, istate
);
272 NTSTATUS
_dcesrv_iface_state_store_assoc(struct dcesrv_call_state
*call
,
275 const char *location
)
277 struct auth_session_info
*session_info
=
278 dcesrv_call_session_info(call
);
279 const struct dom_sid
*owner
=
280 &session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
283 status
= dcesrv_iface_state_store(call
->conn
->assoc_group
,
284 call
->context
->iface
,
290 call
->conn
->assoc_group
, /* mem_ctx */
293 if (!NT_STATUS_IS_OK(status
)) {
300 void *_dcesrv_iface_state_find_assoc(struct dcesrv_call_state
*call
, uint64_t magic
)
302 struct auth_session_info
*session_info
=
303 dcesrv_call_session_info(call
);
304 const struct dom_sid
*owner
=
305 &session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
308 ptr
= dcesrv_iface_state_find(call
->conn
->assoc_group
,
309 call
->context
->iface
,
323 NTSTATUS
_dcesrv_iface_state_store_conn(struct dcesrv_call_state
*call
,
326 const char *location
)
328 struct auth_session_info
*session_info
=
329 dcesrv_call_session_info(call
);
330 const struct dom_sid
*owner
=
331 &session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
334 status
= dcesrv_iface_state_store(call
->conn
->assoc_group
,
335 call
->context
->iface
,
341 call
->conn
, /* mem_ctx */
344 if (!NT_STATUS_IS_OK(status
)) {
351 void *_dcesrv_iface_state_find_conn(struct dcesrv_call_state
*call
, uint64_t magic
)
353 struct auth_session_info
*session_info
=
354 dcesrv_call_session_info(call
);
355 const struct dom_sid
*owner
=
356 &session_info
->security_token
->sids
[PRIMARY_USER_SID_INDEX
];
359 ptr
= dcesrv_iface_state_find(call
->conn
->assoc_group
,
360 call
->context
->iface
,