Changeset 111634 in spip-zone


Ignore:
Timestamp:
Sep 20, 2018, 11:09:57 AM (15 months ago)
Author:
cedric@…
Message:

Fix un gros probleme de confidentialite avec apc/apcu :

apc/apcu fournissent le moyen de lister toutes les cles en cache. Sur un serveur qui heberge plusieurs sites cela permet donc d'acceder au cache des autres sites et d'en lire le contenu, ce qui peut etre problematique. Pour eviter cela on introduit une cle de cache propre a chaque site avec laquelle les donnes sont encodees a la mise en cache et decodees a la lecture. Impact perf absolu acceptable meme si relatif non negligeable : sur une config de test la lecture passe de 0.4µs a 1.7µs et l'ecriture de 0.8µs a 2.2µs

+ simplifcation de la purge sans foreach sur apc/apcu
+ les cles de memoization du cache SPIP sont prefixees par un 'cache:' pour permettre de les reconnaitre et distinguer vis a vis d'autres utilisations de memoization

La mise a jour vers cette version du plugin redefinit un nouveau namespace et donc invalide le cache existant, meme si on utilise pas apc ou apcu (c'est pas genial mais c'est le mieux qu'on puisse faire pour ne pas provoquer de bug chez les utilisateurs d'apc/apcu)

Location:
_plugins_/memoization/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/memoization/trunk/memo/apc.inc

    r111462 r111634  
    33        define('_CACHE_NAMESPACE', $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].":");
    44
     5if (!defined('_CACHE_KEY'))
     6        define('_CACHE_KEY', '0123456789ABCDEF');
     7
    58class MCacheBackend_apc extends MCacheBackend {
    69
    710        function key_for_lock($str) {
    8                 return _CACHE_NAMESPACE.md5($str."locked");
     11                return _CACHE_NAMESPACE . 'lock:' . md5($str . "locked");
     12        }
     13
     14        function _xor($message) {
     15                $key = _CACHE_KEY;
     16                $keylen = strlen($key);
     17                $messagelen = strlen($message);
     18                for ($i = 0; $i < $messagelen; $i++) {
     19                        $message[$i] = ~($message[$i] ^ $key[$i % $keylen]);
     20                }
     21                return $message;
     22        }
     23
     24        function store_value($value) {
     25                if (is_object($value)
     26                        or is_array($value)
     27                        or is_bool($value)
     28                        or !$value) {
     29                                return array($this->_xor(serialize($value)));
     30                }
     31                return $this->_xor($value);
     32        }
     33
     34        function unstore_value($a) {
     35                if (is_null($a)) {
     36                        return $a;
     37                }
     38                // maybe_unserialize
     39                if (is_array($a)){
     40                        return @unserialize($this->_xor($a[0]));
     41                }
     42                return $this->_xor($a);
    943        }
    1044
    1145        function get($key) {
    1246                $a = apc_fetch(_CACHE_NAMESPACE.$key);
    13                 // maybe_unserialize
    14                 if (is_array($a))
    15                         return @unserialize($a[0]);
    16                 else
    17                         return $a;
     47                return $this->unstore_value($a);
    1848        }
    1949       
    2050        function set($key, $value, $ttl=null) {
    21                 // maybe_serialize
    22                 if (is_object($value) OR is_array($value))
    23                         $value = array(serialize($value));
    2451                return is_null($ttl)
    25                         ? apc_store(_CACHE_NAMESPACE.$key, $value)
    26                         : apc_store(_CACHE_NAMESPACE.$key, $value, $ttl);
     52                        ? apc_store(_CACHE_NAMESPACE.$key, $this->store_value($value))
     53                        : apc_store(_CACHE_NAMESPACE.$key, $this->store_value($value), $ttl);
    2754        }
    2855       
     
    6895
    6996        function purge() {
     97                // le cache en memoire est de toute facon invalide par la globale cache_mark et le ttl est cense nettoyer le reste
    7098                if (!class_exists('APCIterator'))
    7199                        return false;
    72100                $a = new APCIterator('user', '/^'.preg_quote(_CACHE_NAMESPACE).'/', APC_ITER_ALL, 256*256);
    73                 foreach ($a as $cache) {
    74                         apc_delete($cache['key']);
    75                 }
     101                apc_delete($a);
    76102                return true;
    77103        }
  • _plugins_/memoization/trunk/memo/apcu.inc

    r111462 r111634  
    33        define('_CACHE_NAMESPACE', $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].":");
    44
     5if (!defined('_CACHE_KEY'))
     6        define('_CACHE_KEY', '0123456789ABCDEF');
     7
    58class MCacheBackend_apcu extends MCacheBackend {
    69
    710        function key_for_lock($str) {
    8                 return _CACHE_NAMESPACE.md5($str."locked");
     11                return _CACHE_NAMESPACE . 'lock:' . md5($str . "locked");
     12        }
     13
     14        function _xor($message) {
     15                $key = _CACHE_KEY;
     16                $keylen = strlen($key);
     17                $messagelen = strlen($message);
     18                for ($i = 0; $i < $messagelen; $i++) {
     19                        $message[$i] = ~($message[$i] ^ $key[$i % $keylen]);
     20                }
     21                return $message;
     22        }
     23
     24        function store_value($value) {
     25                if (is_object($value)
     26                        or is_array($value)
     27                        or is_bool($value)
     28                        or !$value) {
     29                                return array($this->_xor(serialize($value)));
     30                }
     31                return $this->_xor($value);
     32        }
     33
     34        function unstore_value($a) {
     35                if (is_null($a)) {
     36                        return $a;
     37                }
     38                // maybe_unserialize
     39                if (is_array($a)){
     40                        return @unserialize($this->_xor($a[0]));
     41                }
     42                return $this->_xor($a);
    943        }
    1044
    1145        function get($key) {
    1246                $a = apcu_fetch(_CACHE_NAMESPACE.$key);
    13                 // maybe_unserialize
    14                 if (is_array($a))
    15                         return @unserialize($a[0]);
    16                 else
    17                         return $a;
     47                return $this->unstore_value($a);
    1848        }
    1949       
    2050        function set($key, $value, $ttl=null) {
    21                 // maybe_serialize
    22                 if (is_object($value) OR is_array($value))
    23                         $value = array(serialize($value));
    2451                return is_null($ttl)
    25                         ? apcu_store(_CACHE_NAMESPACE.$key, $value)
    26                         : apcu_store(_CACHE_NAMESPACE.$key, $value, $ttl);
     52                        ? apcu_store(_CACHE_NAMESPACE.$key, $this->store_value($value))
     53                        : apcu_store(_CACHE_NAMESPACE.$key, $this->store_value($value), $ttl);
    2754        }
    2855       
     
    6895
    6996        function purge() {
     97                // le cache en memoire est de toute facon invalide par la globale cache_mark et le ttl est cense nettoyer le reste
    7098                if (!class_exists('APCUIterator'))
    7199                        return false;
    72100                $a = new APCUIterator('/^'.preg_quote(_CACHE_NAMESPACE).'/', APC_ITER_ALL, 256*256);
    73                 foreach ($a as $cache) {
    74                         apcu_delete($cache['key']);
    75                 }
     101                apcu_delete($a);
    76102                return true;
    77103        }
  • _plugins_/memoization/trunk/memoization_options.php

    r110893 r111634  
    123123
    124124
     125if (!isset($GLOBALS['meta']['cache_key'])){
     126        include_spip("inc/securiser_action");
     127        $key = pack("H*", calculer_cle_action('memoization'));
     128        ecrire_meta('cache_key', $key, 'non');
     129        // il faut redefinir le namespace car on introduit une cle -> invalidation des caches existants
     130        if (isset($GLOBALS['meta']['cache_namespace'])) {
     131                unset($GLOBALS['meta']['cache_namespace']);
     132        }
     133}
    125134if (!isset($GLOBALS['meta']['cache_namespace'])){
    126135        include_spip('inc/acces');
    127136        ecrire_meta('cache_namespace', dechex(crc32($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SERVER_SIGNATURE"] . creer_uniqid())), 'non');
    128137}
     138
    129139if (!defined('_CACHE_NAMESPACE'))
    130140        define('_CACHE_NAMESPACE', $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].':'.$GLOBALS['meta']['cache_namespace'].':');
     141if (!defined('_CACHE_KEY'))
     142        define('_CACHE_KEY', $GLOBALS['meta']['cache_key']);
    131143
    132144global $Memoization;
  • _plugins_/memoization/trunk/paquet.xml

    r111462 r111634  
    22        prefix="Memoization"
    33        categorie="performance"
    4         version="2.0.5"
     4        version="2.1.0"
    55        etat="stable"
    66        compatibilite="[3.0.0;3.2.*]"
  • _plugins_/memoization/trunk/public/cacher.php

    r110880 r111634  
    2828
    2929        return
    30                 md5(var_export(array($contexte, $page),true).'-'.$GLOBALS['dossier_squelettes'].'-'.(isset($GLOBALS['marqueur'])?$GLOBALS['marqueur']:''))
    31                 . '-'.$indicateur;
     30                'cache:'
     31                . md5(var_export(array($contexte, $page),true).'-'.$GLOBALS['dossier_squelettes'].'-'.(isset($GLOBALS['marqueur'])?$GLOBALS['marqueur']:''))
     32                . '-' . $indicateur;
    3233}
    3334
Note: See TracChangeset for help on using the changeset viewer.