[moodle/f13/master] Multiple security fixes.

Jon Ciesla limb at fedoraproject.org
Thu Aug 19 20:38:18 UTC 2010


commit 5bd8f62e08b6e5c28f6d9b5952c7186edff227d1
Author: Jon Ciesla <limb at jcomserv.net>
Date:   Thu Aug 19 15:37:59 2010 -0500

    Multiple security fixes.

 moodle-1.9.9-htmlpurifier-4.1.1.patch |  339 +++++++++++++++++++++++++++++++++
 moodle.spec                           |   24 +++-
 2 files changed, 362 insertions(+), 1 deletions(-)
---
diff --git a/moodle-1.9.9-htmlpurifier-4.1.1.patch b/moodle-1.9.9-htmlpurifier-4.1.1.patch
new file mode 100644
index 0000000..fa88d2f
--- /dev/null
+++ b/moodle-1.9.9-htmlpurifier-4.1.1.patch
@@ -0,0 +1,339 @@
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/AttrDef/CSS/BackgroundPosition.php lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
+--- lib/htmlpurifier/HTMLPurifier.old/AttrDef/CSS/BackgroundPosition.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php	2010-05-31 22:22:39.000000000 -0500
+@@ -59,7 +59,8 @@
+         $keywords = array();
+         $keywords['h'] = false; // left, right
+         $keywords['v'] = false; // top, bottom
+-        $keywords['c'] = false; // center
++        $keywords['ch'] = false; // center (first word)
++        $keywords['cv'] = false; // center (second word)
+         $measures = array();
+ 
+         $i = 0;
+@@ -79,6 +80,13 @@
+             $lbit = ctype_lower($bit) ? $bit : strtolower($bit);
+             if (isset($lookup[$lbit])) {
+                 $status = $lookup[$lbit];
++                if ($status == 'c') {
++                    if ($i == 0) {
++                        $status = 'ch';
++                    } else {
++                        $status = 'cv';
++                    }
++                }
+                 $keywords[$status] = $lbit;
+                 $i++;
+             }
+@@ -101,20 +109,19 @@
+ 
+         if (!$i) return false; // no valid values were caught
+ 
+-
+         $ret = array();
+ 
+         // first keyword
+         if     ($keywords['h'])     $ret[] = $keywords['h'];
+-        elseif (count($measures))   $ret[] = array_shift($measures);
+-        elseif ($keywords['c']) {
+-            $ret[] = $keywords['c'];
+-            $keywords['c'] = false; // prevent re-use: center = center center
++        elseif ($keywords['ch']) {
++            $ret[] = $keywords['ch'];
++            $keywords['cv'] = false; // prevent re-use: center = center center
+         }
++        elseif (count($measures))   $ret[] = array_shift($measures);
+ 
+         if     ($keywords['v'])     $ret[] = $keywords['v'];
++        elseif ($keywords['cv'])    $ret[] = $keywords['cv'];
+         elseif (count($measures))   $ret[] = array_shift($measures);
+-        elseif ($keywords['c'])     $ret[] = $keywords['c'];
+ 
+         if (empty($ret)) return false;
+         return implode(' ', $ret);
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/AttrDef/CSS/FontFamily.php lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php
+--- lib/htmlpurifier/HTMLPurifier.old/AttrDef/CSS/FontFamily.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php	2010-05-31 22:22:39.000000000 -0500
+@@ -34,37 +34,10 @@
+                 $quote = $font[0];
+                 if ($font[$length - 1] !== $quote) continue;
+                 $font = substr($font, 1, $length - 2);
++            }
+ 
+-                $new_font = '';
+-                for ($i = 0, $c = strlen($font); $i < $c; $i++) {
+-                    if ($font[$i] === '\\') {
+-                        $i++;
+-                        if ($i >= $c) {
+-                            $new_font .= '\\';
+-                            break;
+-                        }
+-                        if (ctype_xdigit($font[$i])) {
+-                            $code = $font[$i];
+-                            for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
+-                                if (!ctype_xdigit($font[$i])) break;
+-                                $code .= $font[$i];
+-                            }
+-                            // We have to be extremely careful when adding
+-                            // new characters, to make sure we're not breaking
+-                            // the encoding.
+-                            $char = HTMLPurifier_Encoder::unichr(hexdec($code));
+-                            if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
+-                            $new_font .= $char;
+-                            if ($i < $c && trim($font[$i]) !== '') $i--;
+-                            continue;
+-                        }
+-                        if ($font[$i] === "\n") continue;
+-                    }
+-                    $new_font .= $font[$i];
+-                }
++            $font = $this->expandCSSEscape($font);
+ 
+-                $font = $new_font;
+-            }
+             // $font is a pure representation of the font name
+ 
+             if (ctype_alnum($font) && $font !== '') {
+@@ -73,12 +46,21 @@
+                 continue;
+             }
+ 
+-            // complicated font, requires quoting
++            // bugger out on whitespace.  form feed (0C) really
++            // shouldn't show up regardless
++            $font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
++
++            // These ugly transforms don't pose a security
++            // risk (as \\ and \" might).  We could try to be clever and
++            // use single-quote wrapping when there is a double quote
++            // present, but I have choosen not to implement that.
++            // (warning: this code relies on the selection of quotation
++            // mark below)
++            $font = str_replace('\\', '\\5C ', $font);
++            $font = str_replace('"',  '\\22 ', $font);
+ 
+-            // armor single quotes and new lines
+-            $font = str_replace("\\", "\\\\", $font);
+-            $font = str_replace("'", "\\'", $font);
+-            $final .= "'$font', ";
++            // complicated font, requires quoting
++            $final .= "\"$font\", "; // note that this will later get turned into &quot;
+         }
+         $final = rtrim($final, ', ');
+         if ($final === '') return false;
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/AttrDef/CSS/URI.php lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php
+--- lib/htmlpurifier/HTMLPurifier.old/AttrDef/CSS/URI.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php	2010-05-31 22:22:39.000000000 -0500
+@@ -34,20 +34,16 @@
+             $uri = substr($uri, 1, $new_length - 1);
+         }
+ 
+-        $keys   = array(  '(',   ')',   ',',   ' ',   '"',   "'");
+-        $values = array('\\(', '\\)', '\\,', '\\ ', '\\"', "\\'");
+-        $uri = str_replace($values, $keys, $uri);
++        $uri = $this->expandCSSEscape($uri);
+ 
+         $result = parent::validate($uri, $config, $context);
+ 
+         if ($result === false) return false;
+ 
+-        // escape necessary characters according to CSS spec
+-        // except for the comma, none of these should appear in the
+-        // URI at all
+-        $result = str_replace($keys, $values, $result);
++        // extra sanity check; should have been done by URI
++        $result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
+ 
+-        return "url('$result')";
++        return "url(\"$result\")";
+ 
+     }
+ 
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/AttrDef/Lang.php lib/htmlpurifier/HTMLPurifier/AttrDef/Lang.php
+--- lib/htmlpurifier/HTMLPurifier.old/AttrDef/Lang.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/AttrDef/Lang.php	2010-05-31 22:22:39.000000000 -0500
+@@ -9,10 +9,6 @@
+ 
+     public function validate($string, $config, $context) {
+ 
+-// moodle change - we use special lang strings unfortunatelly
+-        return preg_replace('/[^0-9a-zA-Z_-]/', '', $string);
+-// moodle change end
+-
+         $string = trim($string);
+         if (!$string) return false;
+ 
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/AttrDef.php lib/htmlpurifier/HTMLPurifier/AttrDef.php
+--- lib/htmlpurifier/HTMLPurifier.old/AttrDef.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/AttrDef.php	2010-05-31 22:22:39.000000000 -0500
+@@ -82,6 +82,42 @@
+         return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
+     }
+ 
++    /**
++     * Parses a possibly escaped CSS string and returns the "pure" 
++     * version of it.
++     */
++    protected function expandCSSEscape($string) {
++        // flexibly parse it
++        $ret = '';
++        for ($i = 0, $c = strlen($string); $i < $c; $i++) {
++            if ($string[$i] === '\\') {
++                $i++;
++                if ($i >= $c) {
++                    $ret .= '\\';
++                    break;
++                }
++                if (ctype_xdigit($string[$i])) {
++                    $code = $string[$i];
++                    for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
++                        if (!ctype_xdigit($string[$i])) break;
++                        $code .= $string[$i];
++                    }
++                    // We have to be extremely careful when adding
++                    // new characters, to make sure we're not breaking
++                    // the encoding.
++                    $char = HTMLPurifier_Encoder::unichr(hexdec($code));
++                    if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
++                    $ret .= $char;
++                    if ($i < $c && trim($string[$i]) !== '') $i--;
++                    continue;
++                }
++                if ($string[$i] === "\n") continue;
++            }
++            $ret .= $string[$i];
++        }
++        return $ret;
++    }
++
+ }
+ 
+ // vim: et sw=4 sts=4
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/Config.php lib/htmlpurifier/HTMLPurifier/Config.php
+--- lib/htmlpurifier/HTMLPurifier.old/Config.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/Config.php	2010-05-31 22:22:39.000000000 -0500
+@@ -20,7 +20,7 @@
+     /**
+      * HTML Purifier's version
+      */
+-    public $version = '4.1.0';
++    public $version = '4.1.1';
+ 
+     /**
+      * Bool indicator whether or not to automatically finalize
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/HTMLModule/Text.php lib/htmlpurifier/HTMLPurifier/HTMLModule/Text.php
+--- lib/htmlpurifier/HTMLPurifier.old/HTMLModule/Text.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/HTMLModule/Text.php	2010-05-31 22:22:39.000000000 -0500
+@@ -45,13 +45,6 @@
+         $this->addElement('span', 'Inline', 'Inline', 'Common');
+         $this->addElement('br',   'Inline', 'Empty',  'Core');
+ 
+-        // Moodle specific elements - start
+-        $this->addElement('nolink',  'Inline', 'Flow');
+-        $this->addElement('tex',     'Inline', 'Flow');
+-        $this->addElement('algebra', 'Inline', 'Flow');
+-        $this->addElement('lang',    'Inline', 'Flow', 'I18N');
+-        // Moodle specific elements - end
+-        
+         // Block Phrasal --------------------------------------------------
+         $this->addElement('address',     'Block', 'Inline', 'Common');
+         $this->addElement('blockquote',  'Block', 'Optional: Heading | Block | List', 'Common', array('cite' => 'URI') );
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/HTMLModule/XMLCommonAttributes.php lib/htmlpurifier/HTMLPurifier/HTMLModule/XMLCommonAttributes.php
+--- lib/htmlpurifier/HTMLPurifier.old/HTMLModule/XMLCommonAttributes.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/HTMLModule/XMLCommonAttributes.php	2010-05-31 22:22:39.000000000 -0500
+@@ -5,11 +5,9 @@
+     public $name = 'XMLCommonAttributes';
+ 
+     public $attr_collections = array(
+-/* moodle comment - xml:lang breaks our multilang
+         'Lang' => array(
+             'xml:lang' => 'LanguageCode',
+         )
+-*/
+     );
+ }
+ 
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/Language/messages/en.php lib/htmlpurifier/HTMLPurifier/Language/messages/en.php
+--- lib/htmlpurifier/HTMLPurifier.old/Language/messages/en.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/Language/messages/en.php	2010-05-31 22:22:39.000000000 -0500
+@@ -23,6 +23,7 @@
+ 'Lexer: Missing gt'            => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped',
+ 'Lexer: Missing attribute key' => 'Attribute declaration has no key',
+ 'Lexer: Missing end quote'     => 'Attribute declaration has no end quote',
++'Lexer: Extracted body'        => 'Removed document metadata tags',
+ 
+ 'Strategy_RemoveForeignElements: Tag transform'              => '<$1> element transformed into $CurrentToken.Serialized',
+ 'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1',
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/Lexer/DirectLex.php lib/htmlpurifier/HTMLPurifier/Lexer/DirectLex.php
+--- lib/htmlpurifier/HTMLPurifier.old/Lexer/DirectLex.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/Lexer/DirectLex.php	2010-05-31 22:22:39.000000000 -0500
+@@ -384,7 +384,7 @@
+                 }
+             }
+             if ($value === false) $value = '';
+-            return array($key => $value);
++            return array($key => $this->parseData($value));
+         }
+ 
+         // setup loop environment
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/Lexer.php lib/htmlpurifier/HTMLPurifier/Lexer.php
+--- lib/htmlpurifier/HTMLPurifier.old/Lexer.php	2010-06-03 19:03:47.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/Lexer.php	2010-05-31 22:22:39.000000000 -0500
+@@ -252,10 +252,8 @@
+     public function normalize($html, $config, $context) {
+ 
+         // normalize newlines to \n
+-        if ($config->get('Output.Newline')!=="\n") {
+-            $html = str_replace("\r\n", "\n", $html);
+-            $html = str_replace("\r", "\n", $html);
+-        }
++        $html = str_replace("\r\n", "\n", $html);
++        $html = str_replace("\r", "\n", $html);
+ 
+         if ($config->get('HTML.Trusted')) {
+             // escape convoluted CDATA
+@@ -267,7 +265,15 @@
+ 
+         // extract body from document if applicable
+         if ($config->get('Core.ConvertDocumentToFragment')) {
+-            $html = $this->extractBody($html);
++            $e = false;
++            if ($config->get('Core.CollectErrors')) {
++                $e =& $context->get('ErrorCollector');
++            }
++            $new_html = $this->extractBody($html);
++            if ($e && $new_html != $html) {
++                $e->send(E_WARNING, 'Lexer: Extracted body');
++            }
++            $html = $new_html;
+         }
+ 
+         // expand entities that aren't the big five
+diff -r -U3 lib/htmlpurifier/HTMLPurifier.old/Strategy/MakeWellFormed.php lib/htmlpurifier/HTMLPurifier/Strategy/MakeWellFormed.php
+--- lib/htmlpurifier/HTMLPurifier.old/Strategy/MakeWellFormed.php	2010-05-21 19:04:23.000000000 -0500
++++ lib/htmlpurifier/HTMLPurifier/Strategy/MakeWellFormed.php	2010-05-31 22:22:39.000000000 -0500
+@@ -165,6 +165,7 @@
+             $token = $tokens[$t];
+ 
+             //echo '<br>'; printTokens($tokens, $t); printTokens($this->stack);
++            //flush();
+ 
+             // quick-check: if it's not a tag, no need to process
+             if (empty($token->is_tag)) {
+@@ -221,11 +222,14 @@
+                     }
+ 
+                     if ($autoclose && $definition->info[$token->name]->wrap) {
+-                        // check if this is actually a wrap (mmm wraps!)
++                        // Check if an element can be wrapped by another 
++                        // element to make it valid in a context (for 
++                        // example, <ul><ul> needs a <li> in between)
+                         $wrapname = $definition->info[$token->name]->wrap;
+                         $wrapdef = $definition->info[$wrapname];
+                         $elements = $wrapdef->child->getAllowedElements($config);
+-                        if (isset($elements[$token->name])) {
++                        $parent_elements = $definition->info[$parent->name]->child->getAllowedElements($config);
++                        if (isset($elements[$token->name]) && isset($parent_elements[$wrapname])) {
+                             $newtoken = new HTMLPurifier_Token_Start($wrapname);
+                             $this->insertBefore($newtoken);
+                             $reprocess = true;
diff --git a/moodle.spec b/moodle.spec
index 2cf6460..6b91a84 100644
--- a/moodle.spec
+++ b/moodle.spec
@@ -8,7 +8,7 @@
 
 Name:           moodle
 Version:        1.9.9
-Release:       	1%{?dist}
+Release:       	2%{?dist}
 Summary:        A Course Management System
 
 Group:          Applications/Publishing
@@ -108,6 +108,7 @@ BuildArch:      noarch
 Patch0:		moodle-1.9.3-rce-texed.patch
 Patch1:		moodle-1.9.4-CVE-2009-1171-1.patch
 #Patch2:		moodle-1.9.4-CVE-2009-1171-2.patch
+Patch3:		moodle-1.9.9-htmlpurifier-4.1.1.patch
 
 BuildRequires:  unzip
 Requires:       php-gd vixie-cron mimetex perl(lib) php-mysql php-xmlrpc
@@ -117,6 +118,7 @@ Requires:	php-Smarty
 Requires:	php-adodb
 #Requires:	php-magpierss
 Requires:	gnu-free-sans-fonts
+Requires:	php-pear-CAS
 Requires(post): /sbin/chkconfig
 Requires(preun): /sbin/chkconfig
 Requires(preun): /sbin/service
@@ -1547,6 +1549,7 @@ sed -i 's/\r//' mod/wiki/ewiki/README.de
 %patch0 -p0
 %patch1 -p0
 #%patch2 -p0
+%patch3 -p0
 
 %build
 rm config-dist.php install.php tags filter/tex/mimetex.* filter/tex/README.mimetex
@@ -1600,6 +1603,11 @@ ln -s /usr/share/fonts/gnu-free/FreeSans.ttf $RPM_BUILD_ROOT%{moodlewebdir}/lib/
 rm -f $RPM_BUILD_ROOT%{moodlewebdir}/lang/km_utf8/fonts/default.ttf
 ln -s /usr/share/fonts/khmeros/KhmerOS_sys.ttf $RPM_BUILD_ROOT%{moodlewebdir}/lang/km_utf8/fonts/default.ttf
 
+#use system php-pear-CAS
+rm -rf $RPM_BUILD_ROOT/var/www/moodle/web/auth/cas
+ln -s /usr/share/pear/ $RPM_BUILD_ROOT/var/www/moodle/web/auth/cas
+
+
 %clean
 rm -rf $RPM_BUILD_ROOT
 
@@ -1624,6 +1632,16 @@ if [ ! -L /var/www/moodle/web/lib/adodb ]; then
   ln -s /usr/share/php/adodb/ /var/www/moodle/web/lib/adodb
 fi
 
+if [ -d /var/www/moodle/web/auth/cas -a ! -L /var/www/moodle/web/auth/cas ]; then
+  mv /var/www/moodle/web/auth.cas /var/www/moodle/web/auth/cas.rpmbak && \
+  ln -s /usr/share/pear/ /var/www/moodle/web/auth/cas
+  rm -rf /var/www/moodle/web/auth/cas.rpmbak
+fi
+if [ ! -L /var/www/moodle/web/auth/cas ]; then
+  ln -s /usr/share/pear/ /var/www/moodle/web/auth/cas
+fi
+
+
 %preun
 if [ $1 = 0 ]; then
   /sbin/service %{name} stop >/dev/null 2>&1
@@ -1773,6 +1791,10 @@ fi
 %exclude %{moodlewebdir}/COPYING.txt
 
 %changelog
+* Thu Aug 19 2010 Jon Ciesla <limb at jcomserv.net> - 1.9.9-2
+- Switch to system php-pear-CAS, BZ 577467, 620772.
+- Patching htmlpurifier, BZ 624754.
+
 * Tue Jun 22 2010 Jon Ciesla <limb at jcomserv.net> - 1.9.9-1
 - Update to 1.9.9, BZ 605810.
 


More information about the scm-commits mailing list