CVE-2015-5252: s3: smbd: Fix symlink verification (file access outside the share).
authorJeremy Allison <jra@samba.org>
Thu, 9 Jul 2015 17:58:11 +0000 (10:58 -0700)
committerStefan Metzmacher <metze@samba.org>
Wed, 16 Dec 2015 11:56:48 +0000 (12:56 +0100)
Ensure matching component ends in '/' or '\0'.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11395

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/smbd/vfs.c

index 0c272a7967bb09f3adec8e71f466b8ecf81bb8af..27b38d643ae7251c6340f4000de1d6706b93f67d 100644 (file)
@@ -982,6 +982,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
        struct smb_filename *smb_fname_cwd = NULL;
        struct privilege_paths *priv_paths = NULL;
        int ret;
        struct smb_filename *smb_fname_cwd = NULL;
        struct privilege_paths *priv_paths = NULL;
        int ret;
+       bool matched;
 
        DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
                        fname,
 
        DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
                        fname,
@@ -1076,7 +1077,10 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
        }
 
        rootdir_len = strlen(conn_rootdir);
        }
 
        rootdir_len = strlen(conn_rootdir);
-       if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) {
+       matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
+
+       if (!matched || (resolved_name[rootdir_len] != '/' &&
+                        resolved_name[rootdir_len] != '\0')) {
                DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
                        "attempt: %s is a symlink outside the "
                        "share path\n",
                DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
                        "attempt: %s is a symlink outside the "
                        "share path\n",
@@ -1216,6 +1220,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
        if (!allow_widelinks || !allow_symlinks) {
                const char *conn_rootdir;
                size_t rootdir_len;
        if (!allow_widelinks || !allow_symlinks) {
                const char *conn_rootdir;
                size_t rootdir_len;
+               bool matched;
 
                conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
                if (conn_rootdir == NULL) {
 
                conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
                if (conn_rootdir == NULL) {
@@ -1226,8 +1231,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                }
 
                rootdir_len = strlen(conn_rootdir);
                }
 
                rootdir_len = strlen(conn_rootdir);
-               if (strncmp(conn_rootdir, resolved_name,
-                               rootdir_len) != 0) {
+               matched = (strncmp(conn_rootdir, resolved_name,
+                               rootdir_len) == 0);
+               if (!matched || (resolved_name[rootdir_len] != '/' &&
+                                resolved_name[rootdir_len] != '\0')) {
                        DEBUG(2, ("check_reduced_name: Bad access "
                                "attempt: %s is a symlink outside the "
                                "share path\n", fname));
                        DEBUG(2, ("check_reduced_name: Bad access "
                                "attempt: %s is a symlink outside the "
                                "share path\n", fname));