smbd: Add conn_using_smb2()
[samba.git] / source3 / smbd / conn.c
index d8dc1c27d427a27fccc1c6c45331cf581cbc2757..b7a745a951e85f2731ba25373ae4b915714b5df8 100644 (file)
 #include "smbd/globals.h"
 #include "lib/util/bitmap.h"
 
+static void conn_free_internal(connection_struct *conn);
+
+/****************************************************************************
+ * Remove a conn struct from conn->sconn->connections
+ * if not already done.
+****************************************************************************/
+
+static int conn_struct_destructor(connection_struct *conn)
+{
+        if (conn->sconn != NULL) {
+               DLIST_REMOVE(conn->sconn->connections, conn);
+               SMB_ASSERT(conn->sconn->num_connections > 0);
+               conn->sconn->num_connections--;
+               conn->sconn = NULL;
+       }
+       conn_free_internal(conn);
+       return 0;
+}
+
 /****************************************************************************
  Return the number of open connections.
 ****************************************************************************/
@@ -51,31 +70,95 @@ bool conn_snum_used(struct smbd_server_connection *sconn,
        return false;
 }
 
+enum protocol_types conn_protocol(struct smbd_server_connection *sconn)
+{
+       if ((sconn != NULL) &&
+           (sconn->client != NULL) &&
+           (sconn->client->connections != NULL)) {
+               return sconn->client->connections->protocol;
+       }
+       /*
+        * Default to what source3/lib/util.c has as default for the
+        * static Protocol variable to not change behaviour.
+        */
+       return PROTOCOL_COREPLUS;
+}
+
+bool conn_using_smb2(struct smbd_server_connection *sconn)
+{
+       enum protocol_types proto = conn_protocol(sconn);
+       return (proto >= PROTOCOL_SMB2_02);
+}
+
 /****************************************************************************
  Find first available connection slot, starting from a random position.
- The randomisation stops problems with the server dieing and clients
+ The randomisation stops problems with the server dying and clients
  thinking the server is still available.
 ****************************************************************************/
 
 connection_struct *conn_new(struct smbd_server_connection *sconn)
 {
-       connection_struct *conn;
+       connection_struct *conn = NULL;
 
-       if (!(conn=talloc_zero(NULL, connection_struct)) ||
-           !(conn->params = talloc(conn, struct share_params)) ||
-           !(conn->vuid_cache = talloc_zero(conn, struct vuid_cache)) ||
-           !(conn->connectpath = talloc_strdup(conn, "")) ||
-           !(conn->origpath = talloc_strdup(conn, ""))) {
-               DEBUG(0,("TALLOC_ZERO() failed!\n"));
+       conn = talloc_zero(NULL, connection_struct);
+       if (conn == NULL) {
+               DBG_ERR("talloc_zero failed\n");
+               return NULL;
+       }
+       conn->params = talloc(conn, struct share_params);
+       if (conn->params == NULL) {
+               DBG_ERR("talloc_zero failed\n");
+               TALLOC_FREE(conn);
+               return NULL;
+       }
+       conn->vuid_cache = talloc_zero(conn, struct vuid_cache);
+       if (conn->vuid_cache == NULL) {
+               DBG_ERR("talloc_zero failed\n");
+               TALLOC_FREE(conn);
+               return NULL;
+       }
+       conn->connectpath = talloc_strdup(conn, "");
+       if (conn->connectpath == NULL) {
+               DBG_ERR("talloc_zero failed\n");
+               TALLOC_FREE(conn);
+               return NULL;
+       }
+       conn->cwd_fsp = talloc_zero(conn, struct files_struct);
+       if (conn->cwd_fsp == NULL) {
+               DBG_ERR("talloc_zero failed\n");
+               TALLOC_FREE(conn);
+               return NULL;
+       }
+       conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp,
+                                                     ".",
+                                                     NULL,
+                                                     NULL,
+                                                     0,
+                                                     0);
+       if (conn->cwd_fsp->fsp_name == NULL) {
+               TALLOC_FREE(conn);
+               return NULL;
+       }
+       conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp);
+       if (conn->cwd_fsp->fh == NULL) {
+               DBG_ERR("talloc_zero failed\n");
                TALLOC_FREE(conn);
                return NULL;
        }
        conn->sconn = sconn;
        conn->force_group_gid = (gid_t)-1;
+       fsp_set_fd(conn->cwd_fsp, -1);
+       conn->cwd_fsp->fnum = FNUM_FIELD_INVALID;
+       conn->cwd_fsp->conn = conn;
 
        DLIST_ADD(sconn->connections, conn);
        sconn->num_connections++;
 
+       /*
+        * Catches the case where someone forgets to call
+        * conn_free().
+        */
+       talloc_set_destructor(conn, conn_struct_destructor);
        return conn;
 }
 
@@ -94,14 +177,6 @@ static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
 
                if (ent->vuid == vuid) {
                        ent->vuid = UID_FIELD_INVALID;
-
-                       conn->user_ev_ctx = NULL;
-
-                       if (conn->user_vfs_evg == ent->user_vfs_evg) {
-                               conn->user_vfs_evg = NULL;
-                       }
-                       TALLOC_FREE(ent->user_vfs_evg);
-
                        /*
                         * We need to keep conn->session_info around
                         * if it's equal to ent->session_info as a SMBulogoff
@@ -125,7 +200,6 @@ static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
                        } else {
                                TALLOC_FREE(ent->session_info);
                        }
-
                        ent->read_only = False;
                        ent->share_access = 0;
                }
@@ -182,7 +256,6 @@ static void conn_free_internal(connection_struct *conn)
        free_namearray(conn->aio_write_behind_list);
 
        ZERO_STRUCTP(conn);
-       talloc_destroy(conn);
 }
 
 /****************************************************************************
@@ -191,14 +264,24 @@ static void conn_free_internal(connection_struct *conn)
 
 void conn_free(connection_struct *conn)
 {
-       if (conn->sconn == NULL) {
-               conn_free_internal(conn);
-               return;
-       }
+       TALLOC_FREE(conn);
+}
 
-       DLIST_REMOVE(conn->sconn->connections, conn);
-       SMB_ASSERT(conn->sconn->num_connections > 0);
-       conn->sconn->num_connections--;
+/*
+ * Correctly initialize a share with case options.
+ */
+void conn_setup_case_options(connection_struct *conn)
+{
+       int snum = conn->params->service;
+
+       if (lp_case_sensitive(snum) == Auto) {
+               /* We will be setting this per packet. Set to be case
+               * insensitive for now. */
+               conn->case_sensitive = false;
+       } else {
+               conn->case_sensitive = (bool)lp_case_sensitive(snum);
+       }
 
-       conn_free_internal(conn);
+       conn->case_preserve = lp_preserve_case(snum);
+       conn->short_case_preserve = lp_short_preserve_case(snum);
 }