Hello community,

here is the log from the commit of package exim for openSUSE:Factory checked in 
at 2019-07-26 12:42:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/exim (Old)
 and      /work/SRC/openSUSE:Factory/.exim.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "exim"

Fri Jul 26 12:42:36 2019 rev:52 rq:718600 version:4.92.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/exim/exim.changes        2019-06-12 
13:14:16.816817868 +0200
+++ /work/SRC/openSUSE:Factory/.exim.new.4126/exim.changes      2019-07-26 
12:42:39.673848205 +0200
@@ -0,0 +1,8 @@
+Thu Jul 25 13:43:52 UTC 2019 - alex <[email protected]>
+
+- update to exim 4.92.1
+ * CVE-2019-13917: Fixed an issue with ${sort} expansion which could 
+   allow remote attackers to execute other programs with root privileges 
+   (boo#1142207)
+
+-------------------------------------------------------------------

Old:
----
  exim-4.92.tar.bz2
  exim-4.92.tar.bz2.asc

New:
----
  exim-4.92.1.tar.bz2
  exim-4.92.1.tar.bz2.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ exim.spec ++++++
--- /var/tmp/diff_new_pack.ii7R12/_old  2019-07-26 12:42:40.873847691 +0200
+++ /var/tmp/diff_new_pack.ii7R12/_new  2019-07-26 12:42:40.873847691 +0200
@@ -72,7 +72,7 @@
 %endif
 Requires(pre):  fileutils textutils
 %endif
-Version:        4.92
+Version:        4.92.1
 Release:        0
 %if %{with_mysql}
 BuildRequires:  mysql-devel

++++++ exim-4.92.tar.bz2 -> exim-4.92.1.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/doc/ChangeLog new/exim-4.92.1/doc/ChangeLog
--- old/exim-4.92/doc/ChangeLog 2019-01-30 14:59:52.000000000 +0100
+++ new/exim-4.92.1/doc/ChangeLog       2019-07-18 20:55:56.000000000 +0200
@@ -5,6 +5,12 @@
 options, and new features, see the NewStuff file next to this ChangeLog.
 
 
+Exim version 4.92.1
+-------------------
+
+JH/31 Avoid re-expansion in ${sort } expansion. (CVE-2019-13917, 
OVE-20190718-0006)
+
+
 Exim version 4.92
 -----------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/doc/cve-2019-13917 
new/exim-4.92.1/doc/cve-2019-13917
--- old/exim-4.92/doc/cve-2019-13917    1970-01-01 01:00:00.000000000 +0100
+++ new/exim-4.92.1/doc/cve-2019-13917  2019-07-18 20:55:56.000000000 +0200
@@ -0,0 +1,46 @@
+CVE ID:     CVE-2019-13917
+OVE ID:     OVE-20190718-0006
+Date:       2019-07-18
+Credits:    Jeremy Harris
+Version(s): 4.85 up to and including 4.92
+Issue:      A local or remote attacker can execute programs with root
+            privileges - if you've an unusual configuration. See below.
+
+Conditions to be vulnerable
+===========================
+
+If your configuration uses the ${sort } expansion for items that can be
+controlled by an attacker (e.g. $local_part, $domain). The default
+config, as shipped by the Exim developers, does not contain ${sort }.
+
+Details
+=======
+
+The vulnerability is exploitable either remotely or locally and could
+be used to execute other programs with root privilege.  The ${sort }
+expansion re-evaluates its items.
+
+Mitigation
+==========
+
+Do not use ${sort } in your configuration.
+
+Fix
+===
+
+Download and build a fixed version:
+
+    Tarballs: http://ftp.exim.org/pub/exim/exim4/
+    Git:      https://github.com/Exim/exim.git
+              - tag    exim-4.92.1
+              - branch exim-4.92+fixes
+
+The tagged commit is the officially released version. The +fixes branch
+isn't officially maintained, but contains useful patches *and* the
+security fix.
+
+If you can't install the above versions, ask your package maintainer for
+a version containing the backported fix. On request and depending on our
+resources we will support you in backporting the fix.  (Please note,
+that Exim project officially doesn't support versions prior the current
+stable version.)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/doc/filter.txt 
new/exim-4.92.1/doc/filter.txt
--- old/exim-4.92/doc/filter.txt        2019-02-10 19:23:07.000000000 +0100
+++ new/exim-4.92.1/doc/filter.txt      2019-07-18 21:15:43.000000000 +0200
@@ -4,7 +4,7 @@
 
 Copyright (c) 2014 University of Cambridge
 
-Revision 4.92  10 Feb 2019 PH
+Revision 4.92.1  18 Jul 2019 PH
 
 -------------------------------------------------------------------------------
 
@@ -77,7 +77,7 @@
 
 This document describes the user interfaces to Exim's in-built mail filtering
 facilities, and is copyright (c) University of Cambridge 2014. It corresponds
-to Exim version 4.92.
+to Exim version 4.92.1.
 
 
 1.1 Introduction
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/doc/spec.txt new/exim-4.92.1/doc/spec.txt
--- old/exim-4.92/doc/spec.txt  2019-02-10 19:23:07.000000000 +0100
+++ new/exim-4.92.1/doc/spec.txt        2019-07-18 21:15:42.000000000 +0200
@@ -4,7 +4,7 @@
 
 Copyright (c) 2018 University of Cambridge
 
-Revision 4.92  10 Feb 2019 EM
+Revision 4.92.1  18 Jul 2019 EM
 
 -------------------------------------------------------------------------------
 
@@ -674,7 +674,7 @@
 1.1 Exim documentation
 ----------------------
 
-This edition of the Exim specification applies to version 4.92 of Exim.
+This edition of the Exim specification applies to version 4.92.1 of Exim.
 Substantive changes from the 4.91 edition are marked in some renditions of this
 document; this paragraph is so marked if the rendition is capable of showing a
 change indicator.
@@ -1780,7 +1780,7 @@
 
 Exim is distributed as a gzipped or bzipped tar file which, when unpacked,
 creates a directory with the name of the current release (for example,
-exim-4.92) into which the following files are placed:
+exim-4.92.1) into which the following files are placed:
 
     ACKNOWLEDGMENTS contains some acknowledgments
     CHANGES         contains a reference to where changes are documented
@@ -2390,7 +2390,7 @@
 For the utility programs, old versions are renamed by adding the suffix .O to
 their names. The Exim binary itself, however, is handled differently. It is
 installed under a name that includes the version number and the compile number,
-for example, exim-4.92-1. The script then arranges for a symbolic link called
+for example, exim-4.92.1-1. The script then arranges for a symbolic link called
 exim to point to the binary. If you are updating a previous version of Exim,
 the script takes care to ensure that the name exim is never absent from the
 directory (as seen by other processes).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/src/expand.c new/exim-4.92.1/src/expand.c
--- old/exim-4.92/src/expand.c  2019-01-30 14:59:52.000000000 +0100
+++ new/exim-4.92.1/src/expand.c        2019-07-18 20:55:56.000000000 +0200
@@ -2147,6 +2147,55 @@
 
 
 
+/************************************************/
+/*  Return offset in ops table, or -1 if not found.
+Repoint to just after the operator in the string.
+
+Argument:
+ ss    string representation of operator
+ opname        split-out operator name
+*/
+
+static int
+identify_operator(const uschar ** ss, uschar ** opname)
+{
+const uschar * s = *ss;
+uschar name[256];
+
+/* Numeric comparisons are symbolic */
+
+if (*s == '=' || *s == '>' || *s == '<')
+  {
+  int p = 0;
+  name[p++] = *s++;
+  if (*s == '=')
+    {
+    name[p++] = '=';
+    s++;
+    }
+  name[p] = 0;
+  }
+
+/* All other conditions are named */
+
+else
+  s = read_name(name, sizeof(name), s, US"_");
+*ss = s;
+
+/* If we haven't read a name, it means some non-alpha character is first. */
+
+if (!name[0])
+  {
+  expand_string_message = string_sprintf("condition name expected, "
+    "but found \"%.16s\"", s);
+  return -1;
+  }
+if (opname)
+  *opname = string_copy(name);
+
+return chop_match(name, cond_table, nelem(cond_table));
+}
+
 
 /*************************************************
 *        Read and evaluate a condition           *
@@ -2177,6 +2226,7 @@
 int i, rc, cond_type, roffset;
 int_eximarith_t num[2];
 struct stat statbuf;
+uschar * opname;
 uschar name[256];
 const uschar *sub[10];
 
@@ -2189,37 +2239,7 @@
   if (*s == '!') { testfor = !testfor; s++; } else break;
   }
 
-/* Numeric comparisons are symbolic */
-
-if (*s == '=' || *s == '>' || *s == '<')
-  {
-  int p = 0;
-  name[p++] = *s++;
-  if (*s == '=')
-    {
-    name[p++] = '=';
-    s++;
-    }
-  name[p] = 0;
-  }
-
-/* All other conditions are named */
-
-else s = read_name(name, 256, s, US"_");
-
-/* If we haven't read a name, it means some non-alpha character is first. */
-
-if (name[0] == 0)
-  {
-  expand_string_message = string_sprintf("condition name expected, "
-    "but found \"%.16s\"", s);
-  return NULL;
-  }
-
-/* Find which condition we are dealing with, and switch on it */
-
-cond_type = chop_match(name, cond_table, nelem(cond_table));
-switch(cond_type)
+switch(cond_type = identify_operator(&s, &opname))
   {
   /* def: tests for a non-empty variable, or for the existence of a header. If
   yield == NULL we are in a skipping state, and don't care about the answer. */
@@ -2538,7 +2558,7 @@
       {
       if (i == 0) goto COND_FAILED_CURLY_START;
       expand_string_message = string_sprintf("missing 2nd string in {} "
-        "after \"%s\"", name);
+        "after \"%s\"", opname);
       return NULL;
       }
     if (!(sub[i] = expand_string_internal(s+1, TRUE, &s, yield == NULL,
@@ -2553,7 +2573,7 @@
     conditions that compare numbers do not start with a letter. This just saves
     checking for them individually. */
 
-    if (!isalpha(name[0]) && yield != NULL)
+    if (!isalpha(opname[0]) && yield != NULL)
       if (sub[i][0] == 0)
         {
         num[i] = 0;
@@ -2867,7 +2887,7 @@
       uschar *save_iterate_item = iterate_item;
       int (*compare)(const uschar *, const uschar *);
 
-      DEBUG(D_expand) debug_printf_indent("condition: %s  item: %s\n", name, 
sub[0]);
+      DEBUG(D_expand) debug_printf_indent("condition: %s  item: %s\n", opname, 
sub[0]);
 
       tempcond = FALSE;
       compare = cond_type == ECOND_INLISTI
@@ -2909,14 +2929,14 @@
     if (*s != '{')                                     /* }-for-text-editors */
       {
       expand_string_message = string_sprintf("each subcondition "
-        "inside an \"%s{...}\" condition must be in its own {}", name);
+        "inside an \"%s{...}\" condition must be in its own {}", opname);
       return NULL;
       }
 
     if (!(s = eval_condition(s+1, resetok, subcondptr)))
       {
       expand_string_message = string_sprintf("%s inside \"%s{...}\" condition",
-        expand_string_message, name);
+        expand_string_message, opname);
       return NULL;
       }
     while (isspace(*s)) s++;
@@ -2926,7 +2946,7 @@
       {
       /* {-for-text-editors */
       expand_string_message = string_sprintf("missing } at end of condition "
-        "inside \"%s\" group", name);
+        "inside \"%s\" group", opname);
       return NULL;
       }
 
@@ -2958,7 +2978,7 @@
     int sep = 0;
     uschar *save_iterate_item = iterate_item;
 
-    DEBUG(D_expand) debug_printf_indent("condition: %s\n", name);
+    DEBUG(D_expand) debug_printf_indent("condition: %s\n", opname);
 
     while (isspace(*s)) s++;
     if (*s++ != '{') goto COND_FAILED_CURLY_START;     /* }-for-text-editors */
@@ -2979,7 +2999,7 @@
     if (!(s = eval_condition(sub[1], resetok, NULL)))
       {
       expand_string_message = string_sprintf("%s inside \"%s\" condition",
-        expand_string_message, name);
+        expand_string_message, opname);
       return NULL;
       }
     while (isspace(*s)) s++;
@@ -2989,7 +3009,7 @@
       {
       /* {-for-text-editors */
       expand_string_message = string_sprintf("missing } at end of condition "
-        "inside \"%s\"", name);
+        "inside \"%s\"", opname);
       return NULL;
       }
 
@@ -3001,11 +3021,11 @@
       if (!eval_condition(sub[1], resetok, &tempcond))
         {
         expand_string_message = string_sprintf("%s inside \"%s\" condition",
-          expand_string_message, name);
+          expand_string_message, opname);
         iterate_item = save_iterate_item;
         return NULL;
         }
-      DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", 
name,
+      DEBUG(D_expand) debug_printf_indent("%s: condition evaluated to %s\n", 
opname,
         tempcond? "true":"false");
 
       if (yield != NULL) *yield = (tempcond == testfor);
@@ -3098,19 +3118,20 @@
   /* Unknown condition */
 
   default:
-  expand_string_message = string_sprintf("unknown condition \"%s\"", name);
-  return NULL;
+    if (!expand_string_message || !*expand_string_message)
+      expand_string_message = string_sprintf("unknown condition \"%s\"", 
opname);
+    return NULL;
   }   /* End switch on condition type */
 
 /* Missing braces at start and end of data */
 
 COND_FAILED_CURLY_START:
-expand_string_message = string_sprintf("missing { after \"%s\"", name);
+expand_string_message = string_sprintf("missing { after \"%s\"", opname);
 return NULL;
 
 COND_FAILED_CURLY_END:
 expand_string_message = string_sprintf("missing } at end of \"%s\" condition",
-  name);
+  opname);
 return NULL;
 
 /* A condition requires code that is not compiled */
@@ -3120,7 +3141,7 @@
     !defined(SUPPORT_CRYPTEQ) || !defined(CYRUS_SASLAUTHD_SOCKET)
 COND_FAILED_NOT_COMPILED:
 expand_string_message = string_sprintf("support for \"%s\" not compiled",
-  name);
+  opname);
 return NULL;
 #endif
 }
@@ -3849,6 +3870,56 @@
 
 
 
+/************************************************/
+/* Comparison operation for sort expansion.  We need to avoid
+re-expanding the fields being compared, so need a custom routine.
+
+Arguments:
+ cond_type             Comparison operator code
+ leftarg, rightarg     Arguments for comparison
+
+Return true iff (leftarg compare rightarg)
+*/
+
+static BOOL
+sortsbefore(int cond_type, BOOL alpha_cond,
+  const uschar * leftarg, const uschar * rightarg)
+{
+int_eximarith_t l_num, r_num;
+
+if (!alpha_cond)
+  {
+  l_num = expanded_string_integer(leftarg, FALSE);
+  if (expand_string_message) return FALSE;
+  r_num = expanded_string_integer(rightarg, FALSE);
+  if (expand_string_message) return FALSE;
+
+  switch (cond_type)
+    {
+    case ECOND_NUM_G:  return l_num >  r_num;
+    case ECOND_NUM_GE: return l_num >= r_num;
+    case ECOND_NUM_L:  return l_num <  r_num;
+    case ECOND_NUM_LE: return l_num <= r_num;
+    default: break;
+    }
+  }
+else
+  switch (cond_type)
+    {
+    case ECOND_STR_LT: return Ustrcmp (leftarg, rightarg) <  0;
+    case ECOND_STR_LTI:        return strcmpic(leftarg, rightarg) <  0;
+    case ECOND_STR_LE: return Ustrcmp (leftarg, rightarg) <= 0;
+    case ECOND_STR_LEI:        return strcmpic(leftarg, rightarg) <= 0;
+    case ECOND_STR_GT: return Ustrcmp (leftarg, rightarg) >  0;
+    case ECOND_STR_GTI:        return strcmpic(leftarg, rightarg) >  0;
+    case ECOND_STR_GE: return Ustrcmp (leftarg, rightarg) >= 0;
+    case ECOND_STR_GEI:        return strcmpic(leftarg, rightarg) >= 0;
+    default: break;
+    }
+return FALSE;  /* should not happen */
+}
+
+
 /* Return pointer to dewrapped string, with enclosing specified chars removed.
 The given string is modified on return.  Leading whitespace is skipped while
 looking for the opening wrap character, then the rest is scanned for the 
trailing
@@ -3902,9 +3973,10 @@
 a copy in an allocated string.  Update the list pointer.
 
 The element may itself be an abject or array.
+Return NULL when the list is empty.
 */
 
-uschar *
+static uschar *
 json_nextinlist(const uschar ** list)
 {
 unsigned array_depth = 0, object_depth = 0;
@@ -3923,13 +3995,12 @@
     case '}': object_depth--; break;
     }
 *list = *s ? s+1 : s;
+if (item == s) return NULL;
 item = string_copyn(item, s - item);
 DEBUG(D_expand) debug_printf_indent("  json ele: '%s'\n", item);
 return US item;
 }
 
-
-
 /*************************************************
 *                 Expand string                  *
 *************************************************/
@@ -6240,9 +6311,10 @@
 
     case EITEM_SORT:
       {
+      int cond_type;
       int sep = 0;
       const uschar *srclist, *cmp, *xtract;
-      uschar *srcitem;
+      uschar * opname, * srcitem;
       const uschar *dstlist = NULL, *dstkeylist = NULL;
       uschar * tmp;
       uschar *save_iterate_item = iterate_item;
@@ -6277,6 +6349,25 @@
        goto EXPAND_FAILED_CURLY;
        }
 
+      if ((cond_type = identify_operator(&cmp, &opname)) == -1)
+       {
+       if (!expand_string_message)
+         expand_string_message = string_sprintf("unknown condition \"%s\"", s);
+       goto EXPAND_FAILED;
+       }
+      switch(cond_type)
+       {
+       case ECOND_NUM_L: case ECOND_NUM_LE:
+       case ECOND_NUM_G: case ECOND_NUM_GE:
+       case ECOND_STR_GE: case ECOND_STR_GEI: case ECOND_STR_GT: case 
ECOND_STR_GTI:
+       case ECOND_STR_LE: case ECOND_STR_LEI: case ECOND_STR_LT: case 
ECOND_STR_LTI:
+         break;
+
+       default:
+         expand_string_message = US"comparator not handled for sort";
+         goto EXPAND_FAILED;
+       }
+
       while (isspace(*s)) s++;
       if (*s++ != '{')
         {
@@ -6304,11 +6395,10 @@
       if (skipping) continue;
 
       while ((srcitem = string_nextinlist(&srclist, &sep, NULL, 0)))
-        {
-       uschar * dstitem;
+       {
+       uschar * srcfield, * dstitem;
        gstring * newlist = NULL;
        gstring * newkeylist = NULL;
-       uschar * srcfield;
 
         DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", name, 
srcitem);
 
@@ -6329,25 +6419,15 @@
        while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
          {
          uschar * dstfield;
-         uschar * expr;
-         BOOL before;
 
          /* field for comparison */
          if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
            goto sort_mismatch;
 
-         /* build and run condition string */
-         expr = string_sprintf("%s{%s}{%s}", cmp, srcfield, dstfield);
-
-         DEBUG(D_expand) debug_printf_indent("%s: cond = \"%s\"\n", name, 
expr);
-         if (!eval_condition(expr, &resetok, &before))
-           {
-           expand_string_message = string_sprintf("comparison in sort: %s",
-               expr);
-           goto EXPAND_FAILED;
-           }
+         /* String-comparator names start with a letter; numeric names do not 
*/
 
-         if (before)
+         if (sortsbefore(cond_type, isalpha(opname[0]),
+             srcfield, dstfield))
            {
            /* New-item sorts before this dst-item.  Append new-item,
            then dst-item, then remainder of dst list. */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/src/version.h new/exim-4.92.1/src/version.h
--- old/exim-4.92/src/version.h 2019-02-10 19:22:43.000000000 +0100
+++ new/exim-4.92.1/src/version.h       2019-07-18 21:15:20.000000000 +0200
@@ -1,5 +1,5 @@
 /* automatically generated file - see ../scripts/reversion */
-#define EXIM_RELEASE_VERSION "4.92"
+#define EXIM_RELEASE_VERSION "4.92.1"
 #ifdef EXIM_VARIANT_VERSION
 #define EXIM_VERSION_STR EXIM_RELEASE_VERSION "-" EXIM_VARIANT_VERSION
 #else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/exim-4.92/src/version.sh 
new/exim-4.92.1/src/version.sh
--- old/exim-4.92/src/version.sh        2019-02-10 19:22:43.000000000 +0100
+++ new/exim-4.92.1/src/version.sh      2019-07-18 21:15:20.000000000 +0200
@@ -1,3 +1,3 @@
 # automatically generated file - see ../scripts/reversion
-EXIM_RELEASE_VERSION="4.92"
+EXIM_RELEASE_VERSION="4.92.1"
 EXIM_COMPILE_NUMBER="1"



Reply via email to