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