2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6 * Copyright (C) Jeremy Allison 2001.
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 "../librpc/gen_ndr/ndr_lsa.h"
24 #include "../librpc/gen_ndr/ndr_samr.h"
29 #define DBGC_CLASS DBGC_RPC_SRV
32 * Handle database - stored per pipe.
35 struct dcesrv_handle
{
36 struct dcesrv_handle
*prev
, *next
;
37 struct policy_handle wire_handle
;
38 uint32_t access_granted
;
43 struct dcesrv_handle
*handles
; /* List of pipe handles. */
44 size_t count
; /* Current number of handles. */
45 size_t pipe_ref_count
; /* Number of pipe handles referring
49 /* This is the max handles across all instances of a pipe name. */
51 #define MAX_OPEN_POLS 2048
54 /****************************************************************************
55 Hack as handles need to be persisant over lsa pipe closes so long as a samr
57 ****************************************************************************/
59 static bool is_samr_lsa_pipe(const struct ndr_syntax_id
*syntax
)
61 return (ndr_syntax_id_equal(syntax
, &ndr_table_samr
.syntax_id
)
62 || ndr_syntax_id_equal(syntax
, &ndr_table_lsarpc
.syntax_id
));
65 size_t num_pipe_handles(struct pipes_struct
*p
)
67 if (p
->pipe_handles
== NULL
) {
70 return p
->pipe_handles
->count
;
73 /****************************************************************************
74 Initialise a policy handle list on a pipe. Handle list is shared between all
75 pipes of the same name.
76 ****************************************************************************/
78 bool init_pipe_handles(struct pipes_struct
*p
, const struct ndr_syntax_id
*syntax
)
80 struct pipes_struct
*plist
;
81 struct handle_list
*hl
;
83 for (plist
= get_first_internal_pipe();
85 plist
= get_next_internal_pipe(plist
)) {
86 if (ndr_syntax_id_equal(syntax
, &plist
->syntax
)) {
89 if (is_samr_lsa_pipe(&plist
->syntax
)
90 && is_samr_lsa_pipe(syntax
)) {
92 * samr and lsa share a handle space (same process
100 hl
= plist
->pipe_handles
;
106 * First open, we have to create the handle list
108 hl
= talloc_zero(NULL
, struct handle_list
);
113 DEBUG(10,("init_pipe_handle_list: created handle list for "
115 get_pipe_name_from_syntax(talloc_tos(), syntax
)));
119 * One more pipe is using this list.
122 hl
->pipe_ref_count
++;
125 * Point this pipe at this list.
128 p
->pipe_handles
= hl
;
130 DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for "
131 "pipe %s\n", (unsigned long)p
->pipe_handles
->pipe_ref_count
,
132 get_pipe_name_from_syntax(talloc_tos(), syntax
)));
137 /****************************************************************************
138 find first available policy slot. creates a policy handle for you.
140 If "data_ptr" is given, this must be a talloc'ed object, create_policy_hnd
141 talloc_moves this into the handle. If the policy_hnd is closed,
142 data_ptr is TALLOC_FREE()'ed
143 ****************************************************************************/
145 static struct dcesrv_handle
*create_rpc_handle_internal(struct pipes_struct
*p
,
146 struct policy_handle
*hnd
, void *data_ptr
)
148 struct dcesrv_handle
*rpc_hnd
;
149 static uint32 pol_hnd_low
= 0;
150 static uint32 pol_hnd_high
= 0;
151 time_t t
= time(NULL
);
153 if (p
->pipe_handles
->count
> MAX_OPEN_POLS
) {
154 DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
155 (int)p
->pipe_handles
->count
));
159 rpc_hnd
= talloc_zero(p
->pipe_handles
, struct dcesrv_handle
);
161 DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
165 if (data_ptr
!= NULL
) {
166 rpc_hnd
->data
= talloc_move(rpc_hnd
, &data_ptr
);
170 if (pol_hnd_low
== 0) {
174 /* first bit must be null */
175 SIVAL(&rpc_hnd
->wire_handle
.handle_type
, 0 , 0);
177 /* second bit is incrementing */
178 SIVAL(&rpc_hnd
->wire_handle
.uuid
.time_low
, 0 , pol_hnd_low
);
179 SSVAL(&rpc_hnd
->wire_handle
.uuid
.time_mid
, 0 , pol_hnd_high
);
180 SSVAL(&rpc_hnd
->wire_handle
.uuid
.time_hi_and_version
, 0, (pol_hnd_high
>> 16));
182 /* split the current time into two 16 bit values */
184 /* something random */
185 SSVAL(rpc_hnd
->wire_handle
.uuid
.clock_seq
, 0, (t
>> 16));
186 /* something random */
187 SSVAL(rpc_hnd
->wire_handle
.uuid
.node
, 0, t
);
188 /* something more random */
189 SIVAL(rpc_hnd
->wire_handle
.uuid
.node
, 2, sys_getpid());
191 DLIST_ADD(p
->pipe_handles
->handles
, rpc_hnd
);
192 p
->pipe_handles
->count
++;
194 *hnd
= rpc_hnd
->wire_handle
;
196 DEBUG(4, ("Opened policy hnd[%d] ", (int)p
->pipe_handles
->count
));
197 dump_data(4, (uint8_t *)hnd
, sizeof(*hnd
));
202 bool create_policy_hnd(struct pipes_struct
*p
, struct policy_handle
*hnd
,
205 struct dcesrv_handle
*rpc_hnd
;
207 rpc_hnd
= create_rpc_handle_internal(p
, hnd
, data_ptr
);
208 if (rpc_hnd
== NULL
) {
214 /****************************************************************************
215 find policy by handle - internal version.
216 ****************************************************************************/
218 static struct dcesrv_handle
*find_policy_by_hnd_internal(struct pipes_struct
*p
,
219 const struct policy_handle
*hnd
, void **data_p
)
221 struct dcesrv_handle
*h
;
229 for (h
= p
->pipe_handles
->handles
; h
!= NULL
; h
= h
->next
) {
230 if (memcmp(&h
->wire_handle
, hnd
, sizeof(*hnd
)) == 0) {
231 DEBUG(4,("Found policy hnd[%u] ", count
));
232 dump_data(4, (uint8
*)hnd
, sizeof(*hnd
));
241 DEBUG(4,("Policy not found: "));
242 dump_data(4, (uint8_t *)hnd
, sizeof(*hnd
));
244 p
->bad_handle_fault_state
= true;
249 /****************************************************************************
250 find policy by handle
251 ****************************************************************************/
253 bool find_policy_by_hnd(struct pipes_struct
*p
, const struct policy_handle
*hnd
,
256 struct dcesrv_handle
*rpc_hnd
;
258 rpc_hnd
= find_policy_by_hnd_internal(p
, hnd
, data_p
);
259 if (rpc_hnd
== NULL
) {
265 /****************************************************************************
267 ****************************************************************************/
269 bool close_policy_hnd(struct pipes_struct
*p
, struct policy_handle
*hnd
)
271 struct dcesrv_handle
*rpc_hnd
;
273 rpc_hnd
= find_policy_by_hnd_internal(p
, hnd
, NULL
);
275 if (rpc_hnd
== NULL
) {
276 DEBUG(3, ("Error closing policy (policy not found)\n"));
280 DEBUG(3,("Closed policy\n"));
282 p
->pipe_handles
->count
--;
284 DLIST_REMOVE(p
->pipe_handles
->handles
, rpc_hnd
);
285 TALLOC_FREE(rpc_hnd
);
290 /****************************************************************************
291 Close a pipe - free the handle set if it was the last pipe reference.
292 ****************************************************************************/
294 void close_policy_by_pipe(struct pipes_struct
*p
)
296 p
->pipe_handles
->pipe_ref_count
--;
298 if (p
->pipe_handles
->pipe_ref_count
== 0) {
300 * Last pipe open on this list - free the list.
302 TALLOC_FREE(p
->pipe_handles
);
304 DEBUG(10,("close_policy_by_pipe: deleted handle list for "
306 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
)));
310 /*******************************************************************
311 Shall we allow access to this rpc? Currently this function
312 implements the 'restrict anonymous' setting by denying access to
313 anonymous users if the restrict anonymous level is > 0. Further work
314 will be checking a security descriptor to determine whether a user
315 token has enough access to access the pipe.
316 ********************************************************************/
318 bool pipe_access_check(struct pipes_struct
*p
)
320 /* Don't let anonymous users access this RPC if restrict
323 if (lp_restrict_anonymous() > 0) {
325 /* schannel, so we must be ok */
327 (p
->auth
.auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
)) {
331 if (p
->session_info
->guest
) {
339 void *_policy_handle_create(struct pipes_struct
*p
, struct policy_handle
*hnd
,
340 uint32_t access_granted
, size_t data_size
,
341 const char *type
, NTSTATUS
*pstatus
)
343 struct dcesrv_handle
*rpc_hnd
;
346 if (p
->pipe_handles
->count
> MAX_OPEN_POLS
) {
347 DEBUG(0, ("policy_handle_create: ERROR: too many handles (%d) "
348 "on pipe %s.\n", (int)p
->pipe_handles
->count
,
349 get_pipe_name_from_syntax(talloc_tos(), &p
->syntax
)));
350 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
354 data
= talloc_size(talloc_tos(), data_size
);
356 *pstatus
= NT_STATUS_NO_MEMORY
;
359 talloc_set_name_const(data
, type
);
361 rpc_hnd
= create_rpc_handle_internal(p
, hnd
, data
);
362 if (rpc_hnd
== NULL
) {
364 *pstatus
= NT_STATUS_NO_MEMORY
;
367 rpc_hnd
->access_granted
= access_granted
;
368 *pstatus
= NT_STATUS_OK
;
372 void *_policy_handle_find(struct pipes_struct
*p
,
373 const struct policy_handle
*hnd
,
374 uint32_t access_required
,
375 uint32_t *paccess_granted
,
376 const char *name
, const char *location
,
379 struct dcesrv_handle
*rpc_hnd
;
382 rpc_hnd
= find_policy_by_hnd_internal(p
, hnd
, &data
);
383 if (rpc_hnd
== NULL
) {
384 *pstatus
= NT_STATUS_INVALID_HANDLE
;
387 if (strcmp(name
, talloc_get_name(data
)) != 0) {
388 DEBUG(10, ("expected %s, got %s\n", name
,
389 talloc_get_name(data
)));
390 *pstatus
= NT_STATUS_INVALID_HANDLE
;
393 if ((access_required
& rpc_hnd
->access_granted
) != access_required
) {
394 if (geteuid() == sec_initial_uid()) {
395 DEBUG(4, ("%s: ACCESS should be DENIED (granted: "
396 "%#010x; required: %#010x)\n", location
,
397 rpc_hnd
->access_granted
, access_required
));
398 DEBUGADD(4,("but overwritten by euid == 0\n"));
401 DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: "
402 "%#010x)\n", location
, rpc_hnd
->access_granted
,
404 *pstatus
= NT_STATUS_ACCESS_DENIED
;
409 DEBUG(10, ("found handle of type %s\n", talloc_get_name(data
)));
410 if (paccess_granted
!= NULL
) {
411 *paccess_granted
= rpc_hnd
->access_granted
;
413 *pstatus
= NT_STATUS_OK
;