Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : Manage connections_struct structures 4 : Copyright (C) Andrew Tridgell 1998 5 : Copyright (C) Alexander Bokovoy 2002 6 : Copyright (C) Jeremy Allison 2010 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 "smbd/smbd.h" 24 : #include "smbd/globals.h" 25 : #include "lib/util/bitmap.h" 26 : 27 : static void conn_free_internal(connection_struct *conn); 28 : 29 : /**************************************************************************** 30 : * Remove a conn struct from conn->sconn->connections 31 : * if not already done. 32 : ****************************************************************************/ 33 : 34 57313 : static int conn_struct_destructor(connection_struct *conn) 35 : { 36 57313 : if (conn->sconn != NULL) { 37 57313 : DLIST_REMOVE(conn->sconn->connections, conn); 38 57313 : SMB_ASSERT(conn->sconn->num_connections > 0); 39 57313 : conn->sconn->num_connections--; 40 57313 : conn->sconn = NULL; 41 : } 42 57313 : conn_free_internal(conn); 43 57313 : return 0; 44 : } 45 : 46 : /**************************************************************************** 47 : Return the number of open connections. 48 : ****************************************************************************/ 49 : 50 9864 : int conn_num_open(struct smbd_server_connection *sconn) 51 : { 52 9864 : return sconn->num_connections; 53 : } 54 : 55 : /**************************************************************************** 56 : Check if a snum is in use. 57 : ****************************************************************************/ 58 : 59 108044 : bool conn_snum_used(struct smbd_server_connection *sconn, 60 : int snum) 61 : { 62 0 : struct connection_struct *conn; 63 : 64 166735 : for (conn=sconn->connections; conn; conn=conn->next) { 65 59376 : if (conn->params->service == snum) { 66 685 : return true; 67 : } 68 : } 69 : 70 107359 : return false; 71 : } 72 : 73 4018919 : enum protocol_types conn_protocol(struct smbd_server_connection *sconn) 74 : { 75 4018919 : if ((sconn != NULL) && 76 4018919 : (sconn->client != NULL) && 77 4018865 : (sconn->client->connections != NULL)) { 78 4018865 : return sconn->client->connections->protocol; 79 : } 80 : /* 81 : * Default to what source3/lib/util.c has as default for the 82 : * static Protocol variable to not change behaviour. 83 : */ 84 54 : return PROTOCOL_COREPLUS; 85 : } 86 : 87 2793840 : bool conn_using_smb2(struct smbd_server_connection *sconn) 88 : { 89 2793840 : enum protocol_types proto = conn_protocol(sconn); 90 2793840 : return (proto >= PROTOCOL_SMB2_02); 91 : } 92 : 93 : /**************************************************************************** 94 : Find first available connection slot, starting from a random position. 95 : The randomisation stops problems with the server dying and clients 96 : thinking the server is still available. 97 : ****************************************************************************/ 98 : 99 57339 : connection_struct *conn_new(struct smbd_server_connection *sconn) 100 : { 101 57339 : connection_struct *conn = NULL; 102 : 103 57339 : conn = talloc_zero(NULL, connection_struct); 104 57339 : if (conn == NULL) { 105 0 : DBG_ERR("talloc_zero failed\n"); 106 0 : return NULL; 107 : } 108 57339 : conn->params = talloc(conn, struct share_params); 109 57339 : if (conn->params == NULL) { 110 0 : DBG_ERR("talloc_zero failed\n"); 111 0 : TALLOC_FREE(conn); 112 0 : return NULL; 113 : } 114 57339 : conn->vuid_cache = talloc_zero(conn, struct vuid_cache); 115 57339 : if (conn->vuid_cache == NULL) { 116 0 : DBG_ERR("talloc_zero failed\n"); 117 0 : TALLOC_FREE(conn); 118 0 : return NULL; 119 : } 120 57339 : conn->connectpath = talloc_strdup(conn, ""); 121 57339 : if (conn->connectpath == NULL) { 122 0 : DBG_ERR("talloc_zero failed\n"); 123 0 : TALLOC_FREE(conn); 124 0 : return NULL; 125 : } 126 57339 : conn->cwd_fsp = talloc_zero(conn, struct files_struct); 127 57339 : if (conn->cwd_fsp == NULL) { 128 0 : DBG_ERR("talloc_zero failed\n"); 129 0 : TALLOC_FREE(conn); 130 0 : return NULL; 131 : } 132 57339 : conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp, 133 : ".", 134 : NULL, 135 : NULL, 136 : 0, 137 : 0); 138 57339 : if (conn->cwd_fsp->fsp_name == NULL) { 139 0 : TALLOC_FREE(conn); 140 0 : return NULL; 141 : } 142 57339 : conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp); 143 57339 : if (conn->cwd_fsp->fh == NULL) { 144 0 : DBG_ERR("talloc_zero failed\n"); 145 0 : TALLOC_FREE(conn); 146 0 : return NULL; 147 : } 148 57339 : conn->sconn = sconn; 149 57339 : conn->force_group_gid = (gid_t)-1; 150 57339 : fsp_set_fd(conn->cwd_fsp, -1); 151 57339 : conn->cwd_fsp->fnum = FNUM_FIELD_INVALID; 152 57339 : conn->cwd_fsp->conn = conn; 153 : 154 57339 : DLIST_ADD(sconn->connections, conn); 155 57339 : sconn->num_connections++; 156 : 157 : /* 158 : * Catches the case where someone forgets to call 159 : * conn_free(). 160 : */ 161 57339 : talloc_set_destructor(conn, conn_struct_destructor); 162 57339 : return conn; 163 : } 164 : 165 : /**************************************************************************** 166 : Clear a vuid out of the connection's vuid cache 167 : ****************************************************************************/ 168 : 169 276 : static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid) 170 : { 171 34 : int i; 172 : 173 9108 : for (i=0; i<VUID_CACHE_SIZE; i++) { 174 1088 : struct vuid_cache_entry *ent; 175 : 176 8832 : ent = &conn->vuid_cache->array[i]; 177 : 178 8832 : if (ent->vuid == vuid) { 179 190 : ent->vuid = UID_FIELD_INVALID; 180 : /* 181 : * We need to keep conn->session_info around 182 : * if it's equal to ent->session_info as a SMBulogoff 183 : * is often followed by a SMBtdis (with an invalid 184 : * vuid). The debug code (or regular code in 185 : * vfs_full_audit) wants to refer to the 186 : * conn->session_info pointer to print debug 187 : * statements. Theoretically this is a bug, 188 : * as once the vuid is gone the session_info 189 : * on the conn struct isn't valid any more, 190 : * but there's enough code that assumes 191 : * conn->session_info is never null that 192 : * it's easier to hold onto the old pointer 193 : * until we get a new sessionsetupX. 194 : * As everything is hung off the 195 : * conn pointer as a talloc context we're not 196 : * leaking memory here. See bug #6315. JRA. 197 : */ 198 190 : if (conn->session_info == ent->session_info) { 199 190 : ent->session_info = NULL; 200 : } else { 201 0 : TALLOC_FREE(ent->session_info); 202 : } 203 190 : ent->read_only = False; 204 190 : ent->share_access = 0; 205 : } 206 : } 207 276 : } 208 : 209 : /**************************************************************************** 210 : Clear a vuid out of the validity cache, and as the 'owner' of a connection. 211 : 212 : Called from invalidate_vuid() 213 : ****************************************************************************/ 214 : 215 29387 : void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint64_t vuid) 216 : { 217 782 : connection_struct *conn; 218 : 219 29663 : for (conn=sconn->connections; conn;conn=conn->next) { 220 276 : if (conn->vuid == vuid) { 221 190 : conn->vuid = UID_FIELD_INVALID; 222 : } 223 276 : conn_clear_vuid_cache(conn, vuid); 224 : } 225 29387 : } 226 : 227 : /**************************************************************************** 228 : Free a conn structure - internal part. 229 : ****************************************************************************/ 230 : 231 57313 : static void conn_free_internal(connection_struct *conn) 232 : { 233 57313 : vfs_handle_struct *handle = NULL, *thandle = NULL; 234 57313 : struct trans_state *state = NULL; 235 : 236 : /* Free vfs_connection_struct */ 237 57313 : handle = conn->vfs_handles; 238 425393 : while(handle) { 239 368080 : thandle = handle->next; 240 368080 : DLIST_REMOVE(conn->vfs_handles, handle); 241 368080 : if (handle->free_data) 242 54064 : handle->free_data(&handle->data); 243 362951 : handle = thandle; 244 : } 245 : 246 : /* Free any pending transactions stored on this conn. */ 247 57313 : for (state = conn->pending_trans; state; state = state->next) { 248 : /* state->setup is a talloc child of state. */ 249 0 : SAFE_FREE(state->param); 250 0 : SAFE_FREE(state->data); 251 : } 252 : 253 57313 : free_namearray(conn->veto_list); 254 57313 : free_namearray(conn->hide_list); 255 57313 : free_namearray(conn->veto_oplock_list); 256 57313 : free_namearray(conn->aio_write_behind_list); 257 : 258 57313 : ZERO_STRUCTP(conn); 259 57313 : } 260 : 261 : /**************************************************************************** 262 : Free a conn structure. 263 : ****************************************************************************/ 264 : 265 57313 : void conn_free(connection_struct *conn) 266 : { 267 57313 : TALLOC_FREE(conn); 268 57313 : } 269 : 270 : /* 271 : * Correctly initialize a share with case options. 272 : */ 273 57267 : void conn_setup_case_options(connection_struct *conn) 274 : { 275 57267 : int snum = conn->params->service; 276 : 277 57267 : if (lp_case_sensitive(snum) == Auto) { 278 : /* We will be setting this per packet. Set to be case 279 : * insensitive for now. */ 280 57157 : conn->case_sensitive = false; 281 : } else { 282 110 : conn->case_sensitive = (bool)lp_case_sensitive(snum); 283 : } 284 : 285 57267 : conn->case_preserve = lp_preserve_case(snum); 286 57267 : conn->short_case_preserve = lp_short_preserve_case(snum); 287 57267 : }