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