python/samba/tests: add test cases for s3/registry init funcs
[Samba.git] / source3 / rpc_server / rpc_handles.c
blob60ee11df45715a9eb56119d464e1dd564119e1f7
1 /*
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.
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.
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/>.
22 #include "includes.h"
23 #include "system/passwd.h" /* uid_wrapper */
24 #include "../librpc/gen_ndr/ndr_lsa.h"
25 #include "../librpc/gen_ndr/ndr_samr.h"
26 #include "auth.h"
27 #include "rpc_server/rpc_pipes.h"
28 #include "../libcli/security/security.h"
29 #include "lib/tsocket/tsocket.h"
30 #include "librpc/ndr/ndr_table.h"
31 #include "librpc/rpc/dcesrv_core.h"
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 static size_t num_handles = 0;
38 bool check_open_pipes(void)
40 if (num_handles > 0) {
41 return true;
44 return false;
47 size_t num_pipe_handles(void)
49 return num_handles;
52 /****************************************************************************
53 find first available policy slot. creates a policy handle for you.
55 If "data_ptr" is given, this must be a talloc'ed object, create_policy_hnd
56 talloc_moves this into the handle. If the policy_hnd is closed,
57 data_ptr is TALLOC_FREE()'ed
58 ****************************************************************************/
60 struct hnd_cnt {
61 bool _dummy;
64 static int hnd_cnt_destructor(struct hnd_cnt *cnt)
66 num_handles--;
67 return 0;
70 bool create_policy_hnd(struct pipes_struct *p,
71 struct policy_handle *hnd,
72 uint8_t handle_type,
73 void *data_ptr)
75 struct dcesrv_handle *rpc_hnd = NULL;
76 struct hnd_cnt *cnt = NULL;
78 rpc_hnd = dcesrv_handle_create(p->dce_call, handle_type);
79 if (rpc_hnd == NULL) {
80 return false;
83 cnt = talloc_zero(rpc_hnd, struct hnd_cnt);
84 if (cnt == NULL) {
85 TALLOC_FREE(rpc_hnd);
86 return false;
88 talloc_set_destructor(cnt, hnd_cnt_destructor);
90 if (data_ptr != NULL) {
91 rpc_hnd->data = talloc_move(rpc_hnd, &data_ptr);
94 *hnd = rpc_hnd->wire_handle;
96 num_handles++;
98 return true;
101 /****************************************************************************
102 find policy by handle - internal version.
103 ****************************************************************************/
105 static struct dcesrv_handle *find_policy_by_hnd_internal(
106 struct pipes_struct *p,
107 const struct policy_handle *hnd,
108 uint8_t handle_type,
109 void **data_p)
111 struct dcesrv_handle *h = NULL;
113 if (data_p) {
114 *data_p = NULL;
118 * Do not pass an empty policy_handle to dcesrv_handle_lookup() or
119 * it will create a new empty handle
121 if (ndr_policy_handle_empty(hnd)) {
122 p->fault_state = DCERPC_FAULT_CONTEXT_MISMATCH;
123 return NULL;
127 * Do not pass handle_type to avoid setting the fault_state in the
128 * pipes_struct if the handle type does not match
130 h = dcesrv_handle_lookup(p->dce_call, hnd, DCESRV_HANDLE_ANY);
131 if (h == NULL) {
132 p->fault_state = DCERPC_FAULT_CONTEXT_MISMATCH;
133 return NULL;
136 if (handle_type != DCESRV_HANDLE_ANY &&
137 h->wire_handle.handle_type != handle_type) {
138 /* Just return NULL, do not set a fault
139 * state in pipes_struct */
140 return NULL;
143 if (data_p) {
144 *data_p = h->data;
147 return h;
150 /****************************************************************************
151 find policy by handle
152 ****************************************************************************/
154 void *_find_policy_by_hnd(struct pipes_struct *p,
155 const struct policy_handle *hnd,
156 uint8_t handle_type,
157 NTSTATUS *pstatus)
159 struct dcesrv_handle *rpc_hnd = NULL;
160 void *data = NULL;
162 rpc_hnd = find_policy_by_hnd_internal(p, hnd, handle_type, &data);
163 if (rpc_hnd == NULL) {
164 *pstatus = NT_STATUS_INVALID_HANDLE;
165 return NULL;
168 *pstatus = NT_STATUS_OK;
169 return data;
172 /****************************************************************************
173 Close a policy.
174 ****************************************************************************/
176 bool close_policy_hnd(struct pipes_struct *p,
177 struct policy_handle *hnd)
179 struct dcesrv_handle *rpc_hnd = NULL;
181 rpc_hnd = find_policy_by_hnd_internal(p, hnd, DCESRV_HANDLE_ANY, NULL);
182 if (rpc_hnd == NULL) {
183 DEBUG(3, ("Error closing policy (policy not found)\n"));
184 return false;
187 TALLOC_FREE(rpc_hnd);
189 return true;
192 /*******************************************************************
193 Shall we allow access to this rpc? Currently this function
194 implements the 'restrict anonymous' setting by denying access to
195 anonymous users if the restrict anonymous level is > 0. Further work
196 will be checking a security descriptor to determine whether a user
197 token has enough access to access the pipe.
198 ********************************************************************/
200 bool pipe_access_check(struct pipes_struct *p)
202 /* Don't let anonymous users access this RPC if restrict
203 anonymous > 0 */
205 if (lp_restrict_anonymous() > 0) {
207 struct dcesrv_call_state *dce_call = p->dce_call;
208 struct dcesrv_auth *auth_state = dce_call->auth_state;
209 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
210 struct auth_session_info *session_info = NULL;
211 enum security_user_level user_level;
213 if (!auth_state->auth_finished) {
214 return false;
217 dcesrv_call_auth_info(dce_call, &auth_type, NULL);
219 /* schannel, so we must be ok */
220 if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
221 return True;
224 session_info = dcesrv_call_session_info(dce_call);
225 user_level = security_session_user_level(session_info, NULL);
227 if (user_level < SECURITY_USER) {
228 return False;
232 return True;