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 58656 : static int conn_struct_destructor(connection_struct *conn) 35 : { 36 58656 : if (conn->sconn != NULL) { 37 58656 : DLIST_REMOVE(conn->sconn->connections, conn); 38 58656 : SMB_ASSERT(conn->sconn->num_connections > 0); 39 58656 : conn->sconn->num_connections--; 40 58656 : conn->sconn = NULL; 41 : } 42 58656 : conn_free_internal(conn); 43 58656 : return 0; 44 : } 45 : 46 : /**************************************************************************** 47 : Return the number of open connections. 48 : ****************************************************************************/ 49 : 50 9948 : int conn_num_open(struct smbd_server_connection *sconn) 51 : { 52 9948 : return sconn->num_connections; 53 : } 54 : 55 : /**************************************************************************** 56 : Check if a snum is in use. 57 : ****************************************************************************/ 58 : 59 107956 : bool conn_snum_used(struct smbd_server_connection *sconn, 60 : int snum) 61 : { 62 0 : struct connection_struct *conn; 63 : 64 166560 : for (conn=sconn->connections; conn; conn=conn->next) { 65 59288 : if (conn->params->service == snum) { 66 684 : return true; 67 : } 68 : } 69 : 70 107272 : return false; 71 : } 72 : 73 4022965 : enum protocol_types conn_protocol(struct smbd_server_connection *sconn) 74 : { 75 4022965 : if ((sconn != NULL) && 76 4022965 : (sconn->client != NULL) && 77 4022911 : (sconn->client->connections != NULL)) { 78 4022911 : 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 2790645 : bool conn_using_smb2(struct smbd_server_connection *sconn) 88 : { 89 2790645 : enum protocol_types proto = conn_protocol(sconn); 90 2790645 : 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 58682 : connection_struct *conn_new(struct smbd_server_connection *sconn) 100 : { 101 58682 : connection_struct *conn = NULL; 102 : 103 58682 : conn = talloc_zero(NULL, connection_struct); 104 58682 : if (conn == NULL) { 105 0 : DBG_ERR("talloc_zero failed\n"); 106 0 : return NULL; 107 : } 108 58682 : conn->params = talloc(conn, struct share_params); 109 58682 : if (conn->params == NULL) { 110 0 : DBG_ERR("talloc_zero failed\n"); 111 0 : TALLOC_FREE(conn); 112 0 : return NULL; 113 : } 114 58682 : conn->vuid_cache = talloc_zero(conn, struct vuid_cache); 115 58682 : if (conn->vuid_cache == NULL) { 116 0 : DBG_ERR("talloc_zero failed\n"); 117 0 : TALLOC_FREE(conn); 118 0 : return NULL; 119 : } 120 58682 : conn->connectpath = talloc_strdup(conn, ""); 121 58682 : if (conn->connectpath == NULL) { 122 0 : DBG_ERR("talloc_zero failed\n"); 123 0 : TALLOC_FREE(conn); 124 0 : return NULL; 125 : } 126 58682 : conn->cwd_fsp = talloc_zero(conn, struct files_struct); 127 58682 : if (conn->cwd_fsp == NULL) { 128 0 : DBG_ERR("talloc_zero failed\n"); 129 0 : TALLOC_FREE(conn); 130 0 : return NULL; 131 : } 132 58682 : conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp, 133 : ".", 134 : NULL, 135 : NULL, 136 : 0, 137 : 0); 138 58682 : if (conn->cwd_fsp->fsp_name == NULL) { 139 0 : TALLOC_FREE(conn); 140 0 : return NULL; 141 : } 142 58682 : conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp); 143 58682 : 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 58682 : conn->sconn = sconn; 149 58682 : conn->force_group_gid = (gid_t)-1; 150 58682 : fsp_set_fd(conn->cwd_fsp, -1); 151 58682 : conn->cwd_fsp->fnum = FNUM_FIELD_INVALID; 152 58682 : conn->cwd_fsp->conn = conn; 153 : 154 58682 : DLIST_ADD(sconn->connections, conn); 155 58682 : sconn->num_connections++; 156 : 157 : /* 158 : * Catches the case where someone forgets to call 159 : * conn_free(). 160 : */ 161 58682 : talloc_set_destructor(conn, conn_struct_destructor); 162 58682 : return conn; 163 : } 164 : 165 : /**************************************************************************** 166 : Clear a vuid out of the connection's vuid cache 167 : ****************************************************************************/ 168 : 169 292 : static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid) 170 : { 171 38 : int i; 172 : 173 9636 : for (i=0; i<VUID_CACHE_SIZE; i++) { 174 1216 : struct vuid_cache_entry *ent; 175 : 176 9344 : ent = &conn->vuid_cache->array[i]; 177 : 178 9344 : 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 292 : } 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 29763 : void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint64_t vuid) 216 : { 217 806 : connection_struct *conn; 218 : 219 30055 : for (conn=sconn->connections; conn;conn=conn->next) { 220 292 : if (conn->vuid == vuid) { 221 190 : conn->vuid = UID_FIELD_INVALID; 222 : } 223 292 : conn_clear_vuid_cache(conn, vuid); 224 : } 225 29763 : } 226 : 227 : /**************************************************************************** 228 : Free a conn structure - internal part. 229 : ****************************************************************************/ 230 : 231 58656 : static void conn_free_internal(connection_struct *conn) 232 : { 233 58656 : vfs_handle_struct *handle = NULL, *thandle = NULL; 234 58656 : struct trans_state *state = NULL; 235 : 236 : /* Free vfs_connection_struct */ 237 58656 : handle = conn->vfs_handles; 238 436209 : while(handle) { 239 377553 : thandle = handle->next; 240 377553 : DLIST_REMOVE(conn->vfs_handles, handle); 241 377553 : if (handle->free_data) 242 55397 : handle->free_data(&handle->data); 243 372304 : handle = thandle; 244 : } 245 : 246 : /* Free any pending transactions stored on this conn. */ 247 58656 : 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 58656 : free_namearray(conn->veto_list); 254 58656 : free_namearray(conn->hide_list); 255 58656 : free_namearray(conn->veto_oplock_list); 256 58656 : free_namearray(conn->aio_write_behind_list); 257 : 258 58656 : ZERO_STRUCTP(conn); 259 58656 : } 260 : 261 : /**************************************************************************** 262 : Free a conn structure. 263 : ****************************************************************************/ 264 : 265 58656 : void conn_free(connection_struct *conn) 266 : { 267 58656 : TALLOC_FREE(conn); 268 58656 : } 269 : 270 : /* 271 : * Correctly initialize a share with case options. 272 : */ 273 58610 : void conn_setup_case_options(connection_struct *conn) 274 : { 275 58610 : int snum = conn->params->service; 276 : 277 58610 : if (lp_case_sensitive(snum) == Auto) { 278 : /* We will be setting this per packet. Set to be case 279 : * insensitive for now. */ 280 58500 : conn->case_sensitive = false; 281 : } else { 282 110 : conn->case_sensitive = (bool)lp_case_sensitive(snum); 283 : } 284 : 285 58610 : conn->case_preserve = lp_preserve_case(snum); 286 58610 : conn->short_case_preserve = lp_short_preserve_case(snum); 287 58610 : }