Line data Source code
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. 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 "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" 32 : 33 : #undef DBGC_CLASS 34 : #define DBGC_CLASS DBGC_RPC_SRV 35 : 36 : static size_t num_handles = 0; 37 : 38 0 : bool check_open_pipes(void) 39 : { 40 0 : if (num_handles > 0) { 41 0 : return true; 42 : } 43 : 44 0 : return false; 45 : } 46 : 47 0 : size_t num_pipe_handles(void) 48 : { 49 0 : return num_handles; 50 : } 51 : 52 : /**************************************************************************** 53 : find first available policy slot. creates a policy handle for you. 54 : 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 : ****************************************************************************/ 59 : 60 : struct hnd_cnt { 61 : bool _dummy; 62 : }; 63 : 64 98705 : static int hnd_cnt_destructor(struct hnd_cnt *cnt) 65 : { 66 98705 : num_handles--; 67 98705 : return 0; 68 : } 69 : 70 98705 : void *create_policy_hnd(struct pipes_struct *p, 71 : struct policy_handle *hnd, 72 : uint8_t handle_type, 73 : void *data_ptr) 74 : { 75 98705 : struct dcesrv_handle *rpc_hnd = NULL; 76 98705 : struct hnd_cnt *cnt = NULL; 77 : 78 98705 : rpc_hnd = dcesrv_handle_create(p->dce_call, handle_type); 79 98705 : if (rpc_hnd == NULL) { 80 0 : return NULL; 81 : } 82 : 83 98705 : cnt = talloc_zero(rpc_hnd, struct hnd_cnt); 84 98705 : if (cnt == NULL) { 85 0 : TALLOC_FREE(rpc_hnd); 86 0 : return NULL; 87 : } 88 98705 : talloc_set_destructor(cnt, hnd_cnt_destructor); 89 : 90 98705 : if (data_ptr != NULL) { 91 98705 : rpc_hnd->data = talloc_move(rpc_hnd, &data_ptr); 92 : } 93 : 94 98705 : *hnd = rpc_hnd->wire_handle; 95 : 96 98705 : num_handles++; 97 : 98 98705 : return rpc_hnd; 99 : } 100 : 101 : /**************************************************************************** 102 : find policy by handle - internal version. 103 : ****************************************************************************/ 104 : 105 651700 : 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) 110 : { 111 651700 : struct dcesrv_handle *h = NULL; 112 : 113 651700 : if (data_p) { 114 555023 : *data_p = NULL; 115 : } 116 : 117 : /* 118 : * Do not pass an empty policy_handle to dcesrv_handle_lookup() or 119 : * it will create a new empty handle 120 : */ 121 651700 : if (ndr_policy_handle_empty(hnd)) { 122 50 : p->fault_state = DCERPC_FAULT_CONTEXT_MISMATCH; 123 50 : return NULL; 124 : } 125 : 126 : /* 127 : * Do not pass handle_type to avoid setting the fault_state in the 128 : * pipes_struct if the handle type does not match 129 : */ 130 651650 : h = dcesrv_handle_lookup(p->dce_call, hnd, DCESRV_HANDLE_ANY); 131 651650 : if (h == NULL) { 132 10 : p->fault_state = DCERPC_FAULT_CONTEXT_MISMATCH; 133 10 : return NULL; 134 : } 135 : 136 651640 : if (handle_type != DCESRV_HANDLE_ANY && 137 501719 : h->wire_handle.handle_type != handle_type) { 138 : /* Just return NULL, do not set a fault 139 : * state in pipes_struct */ 140 0 : return NULL; 141 : } 142 : 143 651640 : if (data_p) { 144 554963 : *data_p = h->data; 145 : } 146 : 147 651640 : return h; 148 : } 149 : 150 : /**************************************************************************** 151 : find policy by handle 152 : ****************************************************************************/ 153 : 154 555023 : void *_find_policy_by_hnd(struct pipes_struct *p, 155 : const struct policy_handle *hnd, 156 : uint8_t handle_type, 157 : NTSTATUS *pstatus) 158 : { 159 555023 : struct dcesrv_handle *rpc_hnd = NULL; 160 555023 : void *data = NULL; 161 : 162 555023 : rpc_hnd = find_policy_by_hnd_internal(p, hnd, handle_type, &data); 163 555023 : if (rpc_hnd == NULL) { 164 60 : *pstatus = NT_STATUS_INVALID_HANDLE; 165 60 : return NULL; 166 : } 167 : 168 554963 : *pstatus = NT_STATUS_OK; 169 554963 : return data; 170 : } 171 : 172 : /**************************************************************************** 173 : Close a policy. 174 : ****************************************************************************/ 175 : 176 96677 : bool close_policy_hnd(struct pipes_struct *p, 177 : struct policy_handle *hnd) 178 : { 179 96677 : struct dcesrv_handle *rpc_hnd = NULL; 180 : 181 96677 : rpc_hnd = find_policy_by_hnd_internal(p, hnd, DCESRV_HANDLE_ANY, NULL); 182 96677 : if (rpc_hnd == NULL) { 183 0 : DEBUG(3, ("Error closing policy (policy not found)\n")); 184 0 : return false; 185 : } 186 : 187 96677 : TALLOC_FREE(rpc_hnd); 188 : 189 96677 : return true; 190 : } 191 : 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 : ********************************************************************/ 199 : 200 890 : bool pipe_access_check(struct pipes_struct *p) 201 : { 202 : /* Don't let anonymous users access this RPC if restrict 203 : anonymous > 0 */ 204 : 205 890 : if (lp_restrict_anonymous() > 0) { 206 : 207 0 : struct dcesrv_call_state *dce_call = p->dce_call; 208 0 : struct dcesrv_auth *auth_state = dce_call->auth_state; 209 0 : enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; 210 0 : struct auth_session_info *session_info = NULL; 211 0 : enum security_user_level user_level; 212 : 213 0 : if (!auth_state->auth_finished) { 214 0 : return false; 215 : } 216 : 217 0 : dcesrv_call_auth_info(dce_call, &auth_type, NULL); 218 : 219 : /* schannel, so we must be ok */ 220 0 : if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { 221 0 : return True; 222 : } 223 : 224 0 : session_info = dcesrv_call_session_info(dce_call); 225 0 : user_level = security_session_user_level(session_info, NULL); 226 : 227 0 : if (user_level < SECURITY_USER) { 228 0 : return False; 229 : } 230 : } 231 : 232 890 : return True; 233 : }