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