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 09:23:28 +0000 (10:23 +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 9f3ba6dd905b9e432d342ee27573c9fb2bc005d0..f14ecbef9669dbf71c050a0a5363d262092963d1 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;
+       bool matched;
 
        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);
-       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",
@@ -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;
+               bool matched;
 
                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);
-               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));