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 57139 : static int conn_struct_destructor(connection_struct *conn) 35 : { 36 57139 : if (conn->sconn != NULL) { 37 57139 : DLIST_REMOVE(conn->sconn->connections, conn); 38 57139 : SMB_ASSERT(conn->sconn->num_connections > 0); 39 57139 : conn->sconn->num_connections--; 40 57139 : conn->sconn = NULL; 41 : } 42 57139 : conn_free_internal(conn); 43 57139 : return 0; 44 : } 45 : 46 : /**************************************************************************** 47 : Return the number of open connections. 48 : ****************************************************************************/ 49 : 50 9888 : int conn_num_open(struct smbd_server_connection *sconn) 51 : { 52 9888 : return sconn->num_connections; 53 : } 54 : 55 : /**************************************************************************** 56 : Check if a snum is in use. 57 : ****************************************************************************/ 58 : 59 115710 : bool conn_snum_used(struct smbd_server_connection *sconn, 60 : int snum) 61 : { 62 0 : struct connection_struct *conn; 63 : 64 181997 : for (conn=sconn->connections; conn; conn=conn->next) { 65 67042 : if (conn->params->service == snum) { 66 755 : return true; 67 : } 68 : } 69 : 70 114955 : 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 57165 : connection_struct *conn_new(struct smbd_server_connection *sconn) 80 : { 81 57165 : connection_struct *conn = NULL; 82 : 83 57165 : conn = talloc_zero(NULL, connection_struct); 84 57165 : if (conn == NULL) { 85 0 : DBG_ERR("talloc_zero failed\n"); 86 0 : return NULL; 87 : } 88 57165 : conn->params = talloc(conn, struct share_params); 89 57165 : if (conn->params == NULL) { 90 0 : DBG_ERR("talloc_zero failed\n"); 91 0 : TALLOC_FREE(conn); 92 0 : return NULL; 93 : } 94 57165 : conn->vuid_cache = talloc_zero(conn, struct vuid_cache); 95 57165 : if (conn->vuid_cache == NULL) { 96 0 : DBG_ERR("talloc_zero failed\n"); 97 0 : TALLOC_FREE(conn); 98 0 : return NULL; 99 : } 100 57165 : conn->connectpath = talloc_strdup(conn, ""); 101 57165 : if (conn->connectpath == NULL) { 102 0 : DBG_ERR("talloc_zero failed\n"); 103 0 : TALLOC_FREE(conn); 104 0 : return NULL; 105 : } 106 57165 : conn->cwd_fsp = talloc_zero(conn, struct files_struct); 107 57165 : if (conn->cwd_fsp == NULL) { 108 0 : DBG_ERR("talloc_zero failed\n"); 109 0 : TALLOC_FREE(conn); 110 0 : return NULL; 111 : } 112 57165 : conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp, 113 : ".", 114 : NULL, 115 : NULL, 116 : 0, 117 : 0); 118 57165 : if (conn->cwd_fsp->fsp_name == NULL) { 119 0 : TALLOC_FREE(conn); 120 0 : return NULL; 121 : } 122 57165 : conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp); 123 57165 : 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 57165 : conn->sconn = sconn; 129 57165 : conn->force_group_gid = (gid_t)-1; 130 57165 : fsp_set_fd(conn->cwd_fsp, -1); 131 57165 : conn->cwd_fsp->fnum = FNUM_FIELD_INVALID; 132 57165 : conn->cwd_fsp->conn = conn; 133 : 134 57165 : DLIST_ADD(sconn->connections, conn); 135 57165 : sconn->num_connections++; 136 : 137 : /* 138 : * Catches the case where someone forgets to call 139 : * conn_free(). 140 : */ 141 57165 : talloc_set_destructor(conn, conn_struct_destructor); 142 57165 : 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 29212 : void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint64_t vuid) 196 : { 197 782 : connection_struct *conn; 198 : 199 29488 : 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 29212 : } 206 : 207 : /**************************************************************************** 208 : Free a conn structure - internal part. 209 : ****************************************************************************/ 210 : 211 57139 : static void conn_free_internal(connection_struct *conn) 212 : { 213 57139 : vfs_handle_struct *handle = NULL, *thandle = NULL; 214 57139 : struct trans_state *state = NULL; 215 : 216 : /* Free vfs_connection_struct */ 217 57139 : handle = conn->vfs_handles; 218 424180 : while(handle) { 219 367041 : thandle = handle->next; 220 367041 : DLIST_REMOVE(conn->vfs_handles, handle); 221 367041 : if (handle->free_data) 222 53890 : handle->free_data(&handle->data); 223 361912 : handle = thandle; 224 : } 225 : 226 : /* Free any pending transactions stored on this conn. */ 227 57139 : 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 57139 : free_namearray(conn->veto_list); 234 57139 : free_namearray(conn->hide_list); 235 57139 : free_namearray(conn->veto_oplock_list); 236 57139 : free_namearray(conn->aio_write_behind_list); 237 : 238 57139 : ZERO_STRUCTP(conn); 239 57139 : } 240 : 241 : /**************************************************************************** 242 : Free a conn structure. 243 : ****************************************************************************/ 244 : 245 57139 : void conn_free(connection_struct *conn) 246 : { 247 57139 : TALLOC_FREE(conn); 248 57139 : } 249 : 250 : /* 251 : * Correctly initialize a share with case options. 252 : */ 253 57093 : void conn_setup_case_options(connection_struct *conn) 254 : { 255 57093 : int snum = conn->params->service; 256 : 257 57093 : if (lp_case_sensitive(snum) == Auto) { 258 : /* We will be setting this per packet. Set to be case 259 : * insensitive for now. */ 260 56983 : conn->case_sensitive = false; 261 : } else { 262 110 : conn->case_sensitive = (bool)lp_case_sensitive(snum); 263 : } 264 : 265 57093 : conn->case_preserve = lp_preserve_case(snum); 266 57093 : conn->short_case_preserve = lp_short_preserve_case(snum); 267 57093 : }