The branch, v4-1-test has been updated
       via  a52afc3 VERSION: Bump version number up to 4.1.2...
       via  5e64b07 Merge tag 'samba-4.1.1' into v4-1-test
       via  32d78c8 VERSION: Disable git snapshots for the 4.1.1 release.
       via  07be799 WHATSNEW: Add release notes for Samba 4.1.1.
       via  e737fc7 CVE-2013-4476: s4:libtls: check for safe permissions of tls 
private key file (key.pem)
       via  2ca3eae CVE-2013-4476: s4:libtls: Create tls private key file 
(key.pem) with mode 0600
       via  bc067d0 CVE-2013-4476: selftest/Samba4: use umask 0077 within 
mk_keyblobs()
       via  d6988a1 CVE-2013-4476: samba-tool provision: create 
${private_dir}/tls with mode 0700
       via  7fc2f97 CVE-2013-4476: lib-util: split out file_save_mode() from 
file_save()
       via  81e5048 CVE-2013-4476: lib-util: add file_check_permissions()
       via  afe7ffd Add regression test for bug #10229 - No access check 
verification on stream files.
       via  a2c4c0e Fix bug #10229 - No access check verification on stream 
files.
      from  6207530 s4-dns: dlz_bind9: Create dns-HOSTNAME account disabled

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-1-test


- Log -----------------------------------------------------------------
commit a52afc34d992c7a201c0b35d9d8df1ba25260787
Author: Karolin Seeger <ksee...@samba.org>
Date:   Mon Nov 11 11:40:49 2013 +0100

    VERSION: Bump version number up to 4.1.2...
    
    and re-enable git snapshots.
    
    Signed-off-by: Karolin Seeger <ksee...@samba.org>

commit 5e64b0718f56181b6d70623e285f5e74096fe4af
Merge: 62075301713602612fe3eae92ce4b23e14ab8fa8 
32d78c867eb259960736121146c7152934f3e6b3
Author: Karolin Seeger <ksee...@samba.org>
Date:   Mon Nov 11 11:39:35 2013 +0100

    Merge tag 'samba-4.1.1' into v4-1-test
    
    samba: tag release samba-4.1.1

-----------------------------------------------------------------------

Summary of changes:
 VERSION                            |    2 +-
 WHATSNEW.txt                       |   73 +++++++++++++++
 lib/util/samba_util.h              |   11 ++
 lib/util/util.c                    |   44 +++++++++
 lib/util/util_file.c               |   16 ++-
 python/samba/provision/__init__.py |    2 +-
 selftest/knownfail                 |    1 +
 selftest/target/Samba4.pm          |    6 +-
 source3/smbd/open.c                |   59 ++++++++++++
 source4/lib/tls/tls.c              |   17 ++++
 source4/lib/tls/tls_tstream.c      |   16 +++
 source4/lib/tls/tlscert.c          |    2 +-
 source4/torture/raw/streams.c      |  181 ++++++++++++++++++++++++++++++++++++
 13 files changed, 421 insertions(+), 9 deletions(-)


Changeset truncated at 500 lines:

diff --git a/VERSION b/VERSION
index 9394c6f..28fdecb 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=1
-SAMBA_VERSION_RELEASE=1
+SAMBA_VERSION_RELEASE=2
 
 ########################################################
 # If a official release has a serious bug              #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 857a7ce..4c96f34 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,77 @@
                    =============================
+                   Release Notes for Samba 4.1.1
+                         November 11, 2013
+                   =============================
+
+
+This is a security release in order to address
+CVE-2013-4475 (ACLs are not checked on opening an alternate
+data stream on a file or directory) and
+CVE-2013-4476 (Private key in key.pem world readable).
+
+o  CVE-2013-4475:
+   Samba versions 3.2.0 and above (all versions of 3.2.x, 3.3.x,
+   3.4.x, 3.5.x, 3.6.x, 4.0.x and 4.1.x) do not check the underlying
+   file or directory ACL when opening an alternate data stream.
+
+   According to the SMB1 and SMB2+ protocols the ACL on an underlying
+   file or directory should control what access is allowed to alternate
+   data streams that are associated with the file or directory.
+
+   By default no version of Samba supports alternate data streams
+   on files or directories.
+
+   Samba can be configured to support alternate data streams by loading
+   either one of two virtual file system modues (VFS) vfs_streams_depot or
+   vfs_streams_xattr supplied with Samba, so this bug only affects Samba
+   servers configured this way.
+
+   To determine if your server is vulnerable, check for the strings
+   "streams_depot" or "streams_xattr" inside your smb.conf configuration
+   file.
+
+o  CVE-2013-4476:
+   In setups which provide ldap(s) and/or https services, the private
+   key for SSL/TLS encryption might be world readable. This typically
+   happens in active directory domain controller setups.
+
+
+Changes since 4.1.0:
+--------------------
+
+o   Jeremy Allison <j...@samba.org>
+    * BUGs 10234 + 10229: CVE-2013-4475: Fix access check verification on 
stream
+      files.
+
+
+o   Björn Baumbach <b...@sernet.de>
+    * BUG 10234: CVE-2013-4476: Private key in key.pem world readable.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the Samba 4.1 product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+
+                   =============================
                    Release Notes for Samba 4.1.0
                          October 11, 2013
                    =============================
diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
index 89aa9aa..243ed3e 100644
--- a/lib/util/samba_util.h
+++ b/lib/util/samba_util.h
@@ -580,6 +580,8 @@ a line
 **/
 _PUBLIC_ void file_lines_slashcont(char **lines);
 
+_PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
+                            size_t length, mode_t mode);
 /**
   save a lump of data into a file. Mostly used for debugging 
 */
@@ -623,6 +625,15 @@ _PUBLIC_ time_t file_modtime(const char *fname);
 _PUBLIC_ bool directory_exist(const char *dname);
 
 /**
+ Check file permissions.
+**/
+struct stat;
+_PUBLIC_ bool file_check_permissions(const char *fname,
+                                    uid_t uid,
+                                    mode_t file_perms,
+                                    struct stat *pst);
+
+/**
  * Try to create the specified directory if it didn't exist.
  *
  * @retval true if the directory already existed and has the right permissions 
diff --git a/lib/util/util.c b/lib/util/util.c
index f0ed7f6..3e9047c 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -122,6 +122,50 @@ _PUBLIC_ time_t file_modtime(const char *fname)
 }
 
 /**
+ Check file permissions.
+**/
+
+_PUBLIC_ bool file_check_permissions(const char *fname,
+                                    uid_t uid,
+                                    mode_t file_perms,
+                                    struct stat *pst)
+{
+       int ret;
+       struct stat st;
+
+       if (pst == NULL) {
+               pst = &st;
+       }
+
+       ZERO_STRUCTP(pst);
+
+       ret = stat(fname, pst);
+       if (ret != 0) {
+               DEBUG(0, ("stat failed on file '%s': %s\n",
+                        fname, strerror(errno)));
+               return false;
+       }
+
+       if (pst->st_uid != uid && !uwrap_enabled()) {
+               DEBUG(0, ("invalid ownership of file '%s': "
+                        "owned by uid %u, should be %u\n",
+                        fname, (unsigned int)pst->st_uid,
+                        (unsigned int)uid));
+               return false;
+       }
+
+       if ((pst->st_mode & 0777) != file_perms) {
+               DEBUG(0, ("invalid permissions on file "
+                        "'%s': has 0%o should be 0%o\n", fname,
+                        (unsigned int)(pst->st_mode & 0777),
+                        (unsigned int)file_perms));
+               return false;
+       }
+
+       return true;
+}
+
+/**
  Check if a directory exists.
 **/
 
diff --git a/lib/util/util_file.c b/lib/util/util_file.c
index e031fc5..815cc2b 100644
--- a/lib/util/util_file.c
+++ b/lib/util/util_file.c
@@ -368,13 +368,11 @@ _PUBLIC_ void file_lines_slashcont(char **lines)
        }
 }
 
-/**
-  save a lump of data into a file. Mostly used for debugging 
-*/
-_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
+_PUBLIC_ bool file_save_mode(const char *fname, const void *packet,
+                            size_t length, mode_t mode)
 {
        int fd;
-       fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+       fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, mode);
        if (fd == -1) {
                return false;
        }
@@ -386,6 +384,14 @@ _PUBLIC_ bool file_save(const char *fname, const void 
*packet, size_t length)
        return true;
 }
 
+/**
+  save a lump of data into a file. Mostly used for debugging
+*/
+_PUBLIC_ bool file_save(const char *fname, const void *packet, size_t length)
+{
+       return file_save_mode(fname, packet, length, 0644);
+}
+
 _PUBLIC_ int vfdprintf(int fd, const char *format, va_list ap)
 {
        char *p;
diff --git a/python/samba/provision/__init__.py 
b/python/samba/provision/__init__.py
index 89f029a..4af6b69 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -2024,7 +2024,7 @@ def provision(logger, session_info, credentials, 
smbconf=None,
     if not os.path.exists(paths.private_dir):
         os.mkdir(paths.private_dir)
     if not os.path.exists(os.path.join(paths.private_dir, "tls")):
-        os.mkdir(os.path.join(paths.private_dir, "tls"))
+        os.makedirs(os.path.join(paths.private_dir, "tls"), 0700)
     if not os.path.exists(paths.state_dir):
         os.mkdir(paths.state_dir)
 
diff --git a/selftest/knownfail b/selftest/knownfail
index 0c501fa..2586947 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -144,6 +144,7 @@
 ^samba4.raw.streams.*.delete
 ^samba4.raw.streams.*.createdisp
 ^samba4.raw.streams.*.sumtab
+^samba4.raw.streams.*.perms
 ^samba4.raw.acls.INHERITFLAGS
 ^samba4.raw.acls.*.create_dir
 ^samba4.raw.acls.*.create_file
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 37f7102..8a3f51d 100644
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -246,7 +246,9 @@ sub mk_keyblobs($$)
        my $admincertfile = "$tlsdir/admincert.pem";
        my $admincertupnfile = "$tlsdir/admincertupn.pem";
 
-       mkdir($tlsdir, 0777);
+       mkdir($tlsdir, 0700);
+       my $oldumask = umask;
+       umask 0077;
 
        #This is specified here to avoid draining entropy on every run
        open(DHFILE, ">$dhfile");
@@ -437,6 +439,8 @@ 
Zd7J9s//rNFNa7waklFkDaY56+QWTFtdvxfE+KoHaqt6X8u6pqi7p3M4wDKQox+9Dx8yWFyq
 Wfz/8alZ5aMezCQzXJyIaJsCLeKABosSwHcpAFmxlQ==
 -----END CERTIFICATE-----
 EOF
+
+       umask $oldumask;
 }
 
 sub provision_raw_prepare($$$$$$$$$$)
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 10b04e7..cd1bb72 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -302,6 +302,46 @@ static NTSTATUS check_parent_access(struct 
connection_struct *conn,
 }
 
 /****************************************************************************
+ Ensure when opening a base file for a stream open that we have permissions
+ to do so given the access mask on the base file.
+****************************************************************************/
+
+static NTSTATUS check_base_file_access(struct connection_struct *conn,
+                               struct smb_filename *smb_fname,
+                               uint32_t access_mask)
+{
+       NTSTATUS status;
+
+       status = smbd_calculate_access_mask(conn, smb_fname,
+                                       false,
+                                       access_mask,
+                                       &access_mask);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("smbd_calculate_access_mask "
+                       "on file %s returned %s\n",
+                       smb_fname_str_dbg(smb_fname),
+                       nt_errstr(status)));
+               return status;
+       }
+
+       if (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) {
+               uint32_t dosattrs;
+               if (!CAN_WRITE(conn)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+               dosattrs = dos_mode(conn, smb_fname);
+               if (IS_DOS_READONLY(dosattrs)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       return smbd_check_access_rights(conn,
+                                       smb_fname,
+                                       false,
+                                       access_mask);
+}
+
+/****************************************************************************
  fd support routines - attempt to do a dos_open.
 ****************************************************************************/
 
@@ -3764,6 +3804,25 @@ static NTSTATUS create_file_unixpath(connection_struct 
*conn,
                if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
                        DEBUG(10, ("Unable to stat stream: %s\n",
                                   smb_fname_str_dbg(smb_fname_base)));
+               } else {
+                       /*
+                        * https://bugzilla.samba.org/show_bug.cgi?id=10229
+                        * We need to check if the requested access mask
+                        * could be used to open the underlying file (if
+                        * it existed), as we're passing in zero for the
+                        * access mask to the base filename.
+                        */
+                       status = check_base_file_access(conn,
+                                                       smb_fname_base,
+                                                       access_mask);
+
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(10, ("Permission check "
+                                       "for base %s failed: "
+                                       "%s\n", smb_fname->base_name,
+                                       nt_errstr(status)));
+                               goto fail;
+                       }
                }
 
                /* Open the base file. */
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index db6d1eb..9a3e610 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -22,6 +22,7 @@
 */
 
 #include "includes.h"
+#include "system/filesys.h"
 #include "lib/events/events.h"
 #include "lib/socket/socket.h"
 #include "lib/tls/tls.h"
@@ -369,6 +370,7 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, 
struct loadparm_context *
 {
        struct tls_params *params;
        int ret;
+       struct stat st;
        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
        const char *keyfile = lpcfg_tls_keyfile(tmp_ctx, lp_ctx);
        const char *certfile = lpcfg_tls_certfile(tmp_ctx, lp_ctx);
@@ -399,6 +401,21 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, 
struct loadparm_context *
                talloc_free(hostname);
        }
 
+       if (file_exist(keyfile) &&
+           !file_check_permissions(keyfile, geteuid(), 0600, &st))
+       {
+               DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
+                         "owner uid %u should be %u, mode 0%o should be 0%o\n"
+                         "This is known as CVE-2013-4476.\n"
+                         "Removing all tls .pem files will cause an "
+                         "auto-regeneration with the correct permissions.\n",
+                         keyfile,
+                         (unsigned int)st.st_uid, geteuid(),
+                         (unsigned int)(st.st_mode & 0777), 0600));
+               talloc_free(tmp_ctx);
+               return NULL;
+       }
+
        ret = gnutls_global_init();
        if (ret < 0) goto init_failed;
 
diff --git a/source4/lib/tls/tls_tstream.c b/source4/lib/tls/tls_tstream.c
index 6bb68fb..2cb75ed 100644
--- a/source4/lib/tls/tls_tstream.c
+++ b/source4/lib/tls/tls_tstream.c
@@ -19,6 +19,7 @@
 
 #include "includes.h"
 #include "system/network.h"
+#include "system/filesys.h"
 #include "../util/tevent_unix.h"
 #include "../lib/tsocket/tsocket.h"
 #include "../lib/tsocket/tsocket_internal.h"
@@ -1083,6 +1084,7 @@ NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
        struct tstream_tls_params *tlsp;
 #if ENABLE_GNUTLS
        int ret;
+       struct stat st;
 
        if (!enabled || key_file == NULL || *key_file == 0) {
                tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
@@ -1110,6 +1112,20 @@ NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
                                  key_file, cert_file, ca_file);
        }
 
+       if (file_exist(key_file) &&
+           !file_check_permissions(key_file, geteuid(), 0600, &st))
+       {
+               DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
+                         "owner uid %u should be %u, mode 0%o should be 0%o\n"
+                         "This is known as CVE-2013-4476.\n"
+                         "Removing all tls .pem files will cause an "
+                         "auto-regeneration with the correct permissions.\n",
+                         key_file,
+                         (unsigned int)st.st_uid, geteuid(),
+                         (unsigned int)(st.st_mode & 0777), 0600));
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
        ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
        if (ret != GNUTLS_E_SUCCESS) {
                DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
diff --git a/source4/lib/tls/tlscert.c b/source4/lib/tls/tlscert.c
index 0c780ea..8a19e0a 100644
--- a/source4/lib/tls/tlscert.c
+++ b/source4/lib/tls/tlscert.c
@@ -152,7 +152,7 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
 
        bufsize = sizeof(buf);
        TLSCHECK(gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buf, 
&bufsize));
-       if (!file_save(keyfile, buf, bufsize)) {
+       if (!file_save_mode(keyfile, buf, bufsize, 0600)) {
                DEBUG(0,("Unable to save privatekey in %s parent dir exists 
?\n", keyfile));
                goto failed;
        }
diff --git a/source4/torture/raw/streams.c b/source4/torture/raw/streams.c
index 1611c64..61852f5 100644
--- a/source4/torture/raw/streams.c
+++ b/source4/torture/raw/streams.c
@@ -23,6 +23,8 @@
 #include "system/locale.h"
 #include "torture/torture.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/security/dom_sid.h"
+#include "libcli/security/security_descriptor.h"
 #include "system/filesys.h"
 #include "libcli/libcli.h"
 #include "torture/util.h"
@@ -1885,6 +1887,184 @@ static bool test_stream_summary_tab(struct 
torture_context *tctx,
        return ret;
 }
 
+/* Test how streams interact with base file permissions */
+/* Regression test for bug:
+   https://bugzilla.samba.org/show_bug.cgi?id=10229
+   bug #10229 - No access check verification on stream files.
+*/
+static bool test_stream_permissions(struct torture_context *tctx,
+                                          struct smbcli_state *cli)
+{
+       NTSTATUS status;
+       bool ret = true;
+       union smb_open io;
+       const char *fname = BASEDIR "\\stream_permissions.txt";
+       const char *stream = "Stream One:$DATA";
+       const char *fname_stream;
+       union smb_fileinfo finfo;
+       union smb_setfileinfo sfinfo;
+       int fnum = -1;
+       union smb_fileinfo q;
+       union smb_setfileinfo set;
+       struct security_ace ace;
+       struct security_descriptor *sd;
+
+       torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
+               "Failed to setup up test directory: " BASEDIR);
+
+       torture_comment(tctx, "(%s) testing permissions on streams\n", 
__location__);
+
+       fname_stream = talloc_asprintf(tctx, "%s:%s", fname, stream);
+
+       /* Create a file with a stream with attribute FILE_ATTRIBUTE_ARCHIVE. */
+       ret = create_file_with_stream(tctx, cli, fname_stream);
+       if (!ret) {
+               goto done;
+       }
+
+       ZERO_STRUCT(finfo);
+       finfo.generic.level = RAW_FILEINFO_BASIC_INFO;
+       finfo.generic.in.file.path = fname;
+       status = smb_raw_pathinfo(cli->tree, tctx, &finfo);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       torture_assert_int_equal_goto(tctx,
+               finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
+               FILE_ATTRIBUTE_ARCHIVE, ret, done, "attrib incorrect");
+
+       /* Change the attributes on the base file name. */


-- 
Samba Shared Repository

Reply via email to