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 7978 : static int conn_struct_destructor(connection_struct *conn)
35 : {
36 7978 : if (conn->sconn != NULL) {
37 7978 : DLIST_REMOVE(conn->sconn->connections, conn);
38 7978 : SMB_ASSERT(conn->sconn->num_connections > 0);
39 7978 : conn->sconn->num_connections--;
40 7978 : conn->sconn = NULL;
41 : }
42 7978 : conn_free_internal(conn);
43 7978 : return 0;
44 : }
45 :
46 : /****************************************************************************
47 : Return the number of open connections.
48 : ****************************************************************************/
49 :
50 408 : int conn_num_open(struct smbd_server_connection *sconn)
51 : {
52 408 : return sconn->num_connections;
53 : }
54 :
55 : /****************************************************************************
56 : Check if a snum is in use.
57 : ****************************************************************************/
58 :
59 20142 : bool conn_snum_used(struct smbd_server_connection *sconn,
60 : int snum)
61 : {
62 : struct connection_struct *conn;
63 :
64 20457 : for (conn=sconn->connections; conn; conn=conn->next) {
65 318 : if (conn->params->service == snum) {
66 3 : return true;
67 : }
68 : }
69 :
70 20139 : return false;
71 : }
72 :
73 : /****************************************************************************
74 : Find first available connection slot, starting from a random position.
75 : The randomisation stops problems with the server dieing and clients
76 : thinking the server is still available.
77 : ****************************************************************************/
78 :
79 7978 : connection_struct *conn_new(struct smbd_server_connection *sconn)
80 : {
81 7978 : connection_struct *conn = NULL;
82 :
83 7978 : conn = talloc_zero(NULL, connection_struct);
84 7978 : if (conn == NULL) {
85 0 : DBG_ERR("talloc_zero failed\n");
86 0 : return NULL;
87 : }
88 7978 : conn->params = talloc(conn, struct share_params);
89 7978 : if (conn->params == NULL) {
90 0 : DBG_ERR("talloc_zero failed\n");
91 0 : TALLOC_FREE(conn);
92 0 : return NULL;
93 : }
94 7978 : conn->vuid_cache = talloc_zero(conn, struct vuid_cache);
95 7978 : if (conn->vuid_cache == NULL) {
96 0 : DBG_ERR("talloc_zero failed\n");
97 0 : TALLOC_FREE(conn);
98 0 : return NULL;
99 : }
100 7978 : conn->connectpath = talloc_strdup(conn, "");
101 7978 : if (conn->connectpath == NULL) {
102 0 : DBG_ERR("talloc_zero failed\n");
103 0 : TALLOC_FREE(conn);
104 0 : return NULL;
105 : }
106 7978 : conn->cwd_fsp = talloc_zero(conn, struct files_struct);
107 7978 : if (conn->cwd_fsp == NULL) {
108 0 : DBG_ERR("talloc_zero failed\n");
109 0 : TALLOC_FREE(conn);
110 0 : return NULL;
111 : }
112 7978 : conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp,
113 : ".",
114 : NULL,
115 : NULL,
116 : 0,
117 : 0);
118 7978 : if (conn->cwd_fsp->fsp_name == NULL) {
119 0 : TALLOC_FREE(conn);
120 0 : return NULL;
121 : }
122 7978 : conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp);
123 7978 : 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 7978 : conn->sconn = sconn;
129 7978 : conn->force_group_gid = (gid_t)-1;
130 7978 : fsp_set_fd(conn->cwd_fsp, -1);
131 7978 : conn->cwd_fsp->fnum = FNUM_FIELD_INVALID;
132 7978 : conn->cwd_fsp->conn = conn;
133 :
134 7978 : DLIST_ADD(sconn->connections, conn);
135 7978 : sconn->num_connections++;
136 :
137 : /*
138 : * Catches the case where someone forgets to call
139 : * conn_free().
140 : */
141 7978 : talloc_set_destructor(conn, conn_struct_destructor);
142 7978 : return conn;
143 : }
144 :
145 : /****************************************************************************
146 : Clear a vuid out of the connection's vuid cache
147 : ****************************************************************************/
148 :
149 38 : static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
150 : {
151 : int i;
152 :
153 1254 : for (i=0; i<VUID_CACHE_SIZE; i++) {
154 : struct vuid_cache_entry *ent;
155 :
156 1216 : ent = &conn->vuid_cache->array[i];
157 :
158 1216 : if (ent->vuid == vuid) {
159 30 : 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 30 : if (conn->session_info == ent->session_info) {
179 30 : ent->session_info = NULL;
180 : } else {
181 0 : TALLOC_FREE(ent->session_info);
182 : }
183 30 : ent->read_only = False;
184 30 : ent->share_access = 0;
185 : }
186 : }
187 38 : }
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 4844 : void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint64_t vuid)
196 : {
197 : connection_struct *conn;
198 :
199 4882 : for (conn=sconn->connections; conn;conn=conn->next) {
200 38 : if (conn->vuid == vuid) {
201 30 : conn->vuid = UID_FIELD_INVALID;
202 : }
203 38 : conn_clear_vuid_cache(conn, vuid);
204 : }
205 4844 : }
206 :
207 : /****************************************************************************
208 : Free a conn structure - internal part.
209 : ****************************************************************************/
210 :
211 7978 : static void conn_free_internal(connection_struct *conn)
212 : {
213 7978 : vfs_handle_struct *handle = NULL, *thandle = NULL;
214 7978 : struct trans_state *state = NULL;
215 :
216 : /* Free vfs_connection_struct */
217 7978 : handle = conn->vfs_handles;
218 63853 : while(handle) {
219 50332 : thandle = handle->next;
220 50332 : DLIST_REMOVE(conn->vfs_handles, handle);
221 50332 : if (handle->free_data)
222 7966 : handle->free_data(&handle->data);
223 50332 : handle = thandle;
224 : }
225 :
226 : /* Free any pending transactions stored on this conn. */
227 7978 : 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 7978 : free_namearray(conn->veto_list);
234 7978 : free_namearray(conn->hide_list);
235 7978 : free_namearray(conn->veto_oplock_list);
236 7978 : free_namearray(conn->aio_write_behind_list);
237 :
238 7978 : ZERO_STRUCTP(conn);
239 7978 : }
240 :
241 : /****************************************************************************
242 : Free a conn structure.
243 : ****************************************************************************/
244 :
245 7978 : void conn_free(connection_struct *conn)
246 : {
247 7978 : TALLOC_FREE(conn);
248 7978 : }
249 :
250 : /*
251 : * Correctly initialize a share with case options.
252 : */
253 7966 : void conn_setup_case_options(connection_struct *conn)
254 : {
255 7966 : int snum = conn->params->service;
256 :
257 7966 : if (lp_case_sensitive(snum) == Auto) {
258 : /* We will be setting this per packet. Set to be case
259 : * insensitive for now. */
260 7966 : conn->case_sensitive = false;
261 : } else {
262 0 : conn->case_sensitive = (bool)lp_case_sensitive(snum);
263 : }
264 :
265 7966 : conn->case_preserve = lp_preserve_case(snum);
266 7966 : conn->short_case_preserve = lp_short_preserve_case(snum);
267 7966 : }
|