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)
committerKarolin Seeger <kseeger@samba.org>
Thu, 10 Dec 2015 10:10:54 +0000 (11:10 +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 118f6c90b2b126e5aeb0d793fcc7e1ec5585c181..edf4ee15df8a9ba632ae0beefb90cb4ab0cd9daa 100644 (file)
@@ -976,6 +976,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;
+       bool matched;
 
        DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
                        fname,
@@ -1070,7 +1071,10 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
        }
 
        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",
@@ -1210,6 +1214,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
        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) {
@@ -1220,8 +1225,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                }
 
                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));