Fix bug #6557 - Do not work VFS full_audit
[samba.git] / source / smbd / service.c
index 0b851f1e481b71a3b743474ae65fedcd8c561d05..8c9d75d1e9d1c763b188b787cefe93ef4558776f 100644 (file)
@@ -55,6 +55,10 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
        const char *s = connectpath;
         bool start_of_name_component = true;
 
+       if (connectpath == NULL || connectpath[0] == '\0') {
+               return false;
+       }
+
        destname = SMB_STRDUP(connectpath);
        if (!destname) {
                return false;
@@ -235,6 +239,10 @@ static int load_registry_service(const char *servicename)
                return -1;
        }
 
+       if ((servicename == NULL) || (*servicename == '\0')) {
+               return -1;
+       }
+
        if (strequal(servicename, GLOBAL_NAME)) {
                return -2;
        }
@@ -282,6 +290,10 @@ static int load_registry_service(const char *servicename)
                TALLOC_FREE(value);
        }
 
+       if (!service_ok(res)) {
+               res = -1;
+       }
+
  error:
 
        TALLOC_FREE(key);
@@ -323,7 +335,7 @@ int add_home_service(const char *service, const char *username, const char *home
 {
        int iHomeService;
 
-       if (!service || !homedir)
+       if (!service || !homedir || homedir[0] == '\0')
                return -1;
 
        if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
@@ -708,7 +720,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        fstring dev;
        int ret;
        char addr[INET6_ADDRSTRLEN];
-       bool on_err_call_dis_hook = false;
        NTSTATUS status;
 
        fstrcpy(dev, pdev);
@@ -732,7 +743,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                &conn->server_info);
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("create_connection_server_info failed: %s\n",
+               DEBUG(1, ("create_connection_server_info failed: %s\n",
                          nt_errstr(status)));
                *pstatus = status;
                conn_free(conn);
@@ -830,6 +841,14 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                        *pstatus = status;
                        return NULL;
                }
+
+               /*
+                * We need to cache this gid, to use within
+                * change_to_user() separately from the conn->server_info
+                * struct. We only use conn->server_info directly if
+                * "force_user" was set.
+                */
+               conn->force_group_gid = conn->server_info->utok.gid;
        }
 
        conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
@@ -901,25 +920,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                return NULL;
        }
 
-       /*
-        * If widelinks are disallowed we need to canonicalise the connect
-        * path here to ensure we don't have any symlinks in the
-        * connectpath. We will be checking all paths on this connection are
-        * below this directory. We must do this after the VFS init as we
-        * depend on the realpath() pointer in the vfs table. JRA.
-        */
-       if (!lp_widelinks(snum)) {
-               if (!canonicalize_connect_path(conn)) {
-                       DEBUG(0, ("canonicalize_connect_path failed "
-                       "for service %s, path %s\n",
-                               lp_servicename(snum),
-                               conn->connectpath));
-                       conn_free(conn);
-                       *pstatus = NT_STATUS_BAD_NETWORK_NAME;
-                       return NULL;
-               }
-       }
-
        if ((!conn->printer) && (!conn->ipc)) {
                conn->notify_ctx = notify_init(conn, server_id_self(),
                                               smbd_messaging_context(),
@@ -927,7 +927,11 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                                               conn);
        }
 
-/* ROOT Activities: */ 
+/* ROOT Activities: */
+       /* explicitly check widelinks here so that we can correctly warn
+        * in the logs. */
+       widelinks_warning(snum);
+
        /*
         * Enforce the max connections parameter.
         */
@@ -953,6 +957,30 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                return NULL;
        }  
 
+       /* Invoke VFS make connection hook - must be the first
+          VFS operation we do. */
+
+       if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
+                           conn->server_info->unix_name) < 0) {
+               DEBUG(0,("make_connection: VFS make connection failed!\n"));
+               yield_connection(conn, lp_servicename(snum));
+               conn_free(conn);
+               *pstatus = NT_STATUS_UNSUCCESSFUL;
+               return NULL;
+       }
+
+       /*
+        * Fix compatibility issue pointed out by Volker.
+        * We pass the conn->connectpath to the preexec
+        * scripts as a parameter, so attempt to canonicalize
+        * it here before calling the preexec scripts.
+        * We ignore errors here, as it is possible that
+        * the conn->connectpath doesn't exist yet and
+        * the preexec scripts will create them.
+        */
+
+       (void)canonicalize_connect_path(conn);
+
        /* Preexecs are done here as they might make the dir we are to ChDir
         * to below */
        /* execute any "root preexec = " line */
@@ -971,6 +999,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                if (ret != 0 && lp_rootpreexec_close(snum)) {
                        DEBUG(1,("root preexec gave %d - failing "
                                 "connection\n", ret));
+                       SMB_VFS_DISCONNECT(conn);
                        yield_connection(conn, lp_servicename(snum));
                        conn_free(conn);
                        *pstatus = NT_STATUS_ACCESS_DENIED;
@@ -982,6 +1011,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        if (!change_to_user(conn, conn->vuid)) {
                /* No point continuing if they fail the basic checks */
                DEBUG(0,("Can't become connected user!\n"));
+               SMB_VFS_DISCONNECT(conn);
                yield_connection(conn, lp_servicename(snum));
                conn_free(conn);
                *pstatus = NT_STATUS_LOGON_FAILURE;
@@ -1014,6 +1044,24 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                }
        }
 
+       /*
+        * If widelinks are disallowed we need to canonicalise the connect
+        * path here to ensure we don't have any symlinks in the
+        * connectpath. We will be checking all paths on this connection are
+        * below this directory. We must do this after the VFS init as we
+        * depend on the realpath() pointer in the vfs table. JRA.
+        */
+       if (!lp_widelinks(snum)) {
+               if (!canonicalize_connect_path(conn)) {
+                       DEBUG(0, ("canonicalize_connect_path failed "
+                       "for service %s, path %s\n",
+                               lp_servicename(snum),
+                               conn->connectpath));
+                       *pstatus = NT_STATUS_BAD_NETWORK_NAME;
+                       goto err_root_exit;
+               }
+       }
+
 #ifdef WITH_FAKE_KASERVER
        if (lp_afs_share(snum)) {
                afs_login(conn);
@@ -1029,19 +1077,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                                lp_aio_write_behind(snum));
        }
        
-       /* Invoke VFS make connection hook - do this before the VFS_STAT call
-          to allow any filesystems needing user credentials to initialize
-          themselves. */
-
-       if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
-                           conn->server_info->unix_name) < 0) {
-               DEBUG(0,("make_connection: VFS make connection failed!\n"));
-               *pstatus = NT_STATUS_UNSUCCESSFUL;
-               goto err_root_exit;
-       }
-
-       /* Any error exit after here needs to call the disconnect hook. */
-       on_err_call_dis_hook = true;
 
        /* win2000 does not check the permissions on the directory
           during the tree connect, instead relying on permission
@@ -1114,10 +1149,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
   err_root_exit:
 
        change_to_root_user();
-       if (on_err_call_dis_hook) {
-               /* Call VFS disconnect hook */
-               SMB_VFS_DISCONNECT(conn);
-       }
+       /* Call VFS disconnect hook */
+       SMB_VFS_DISCONNECT(conn);
        yield_connection(conn, lp_servicename(snum));
        conn_free(conn);
        return NULL;