CVE-2022-29528: Deserialization of Untrusted Data (CWE-502)
value: An issue was discovered in MISP before 2.4.158. PHAR deserialization can occur.
CWE description: The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.
CVSS v3 base score: 9.8
Published: 2022-04-20T23:15Z
Repository: https://github.com/MISP/MISP
Language: PHP
Files changed: app/Model/AppModel.php, app/Model/Feed.php, app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php
Commit date: 2022-04-17 18:25:51 +0200
Commit message: fix: [security] Sanitise paths for several file interactions

- remove :// anywhere we don't expect a protocol to be supplied
- remove phar:// in certauth plugin's fetcher

- as reported by Dawid Czarnecki of Zigrin Security

Diff: diff --git a/app/Model/AppModel.php b/app/Model/AppModel.php
index 8edcea224e3c..1e01e44018de 100644
--- a/app/Model/AppModel.php
+++ b/app/Model/AppModel.php
@@ -2586,10 +2586,11 @@ class AppModel extends Model
     {
         if (!$this->loadedKafkaPubTool) {
             App::uses('KafkaPubTool', 'Tools');
             $kafkaPubTool = new KafkaPubTool();
             $rdkafkaIni = Configure::read('Plugin.Kafka_rdkafka_config');
+            $rdkafkaIni = mb_ereg_replace("/\:\/\//", '', $rdkafkaIni);
             $kafkaConf = array();
             if (!empty($rdkafkaIni)) {
                 $kafkaConf = parse_ini_file($rdkafkaIni);
             }
             $brokers = Configure::read('Plugin.Kafka_brokers');
diff --git a/app/Model/Feed.php b/app/Model/Feed.php
index f85c038ae2dd..d09cd877921b 100644
--- a/app/Model/Feed.php
+++ b/app/Model/Feed.php
@@ -124,16 +124,17 @@ class Feed extends AppModel
     }
 
     public function urlOrExistingFilepath($fields)
     {
         if ($this->isFeedLocal($this->data)) {
+            $path = mb_ereg_replace("/\:\/\//", '', $this->data['Feed']['url']);
             if ($this->data['Feed']['source_format'] == 'misp') {
-                if (!is_dir($this->data['Feed']['url'])) {
+                if (!is_dir($path)) {
                     return 'For MISP type local feeds, please specify the containing directory.';
                 }
             } else {
-                if (!file_exists($this->data['Feed']['url'])) {
+                if (!file_exists($path)) {
                     return 'Invalid path or file not found. Make sure that the path points to an existing file that is readable and watch out for typos.';
                 }
             }
         } else {
             if (!filter_var($this->data['Feed']['url'], FILTER_VALIDATE_URL)) {
@@ -1927,10 +1928,11 @@ class Feed extends AppModel
      * @throws Exception
      */
     private function feedGetUri($feed, $uri, HttpSocket $HttpSocket = null)
     {
         if ($this->isFeedLocal($feed)) {
+            $uri = mb_ereg_replace("/\:\/\//", '', $uri);
             if (file_exists($uri)) {
                 return FileAccessTool::readFromFile($uri);
             } else {
                 throw new Exception("Local file '$uri' doesn't exists.");
             }
diff --git a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php
index 521ffc8dbc76..c91fd85d7dde 100644
--- a/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php
+++ b/app/Plugin/CertAuth/Controller/Component/Auth/CertificateAuthenticate.php
@@ -19,276 +19,277 @@
 App::uses('AuthComponent', 'Controller/Component');
 App::uses('BaseAuthenticate', 'Controller/Component/Auth');
 
 class CertificateAuthenticate extends BaseAuthenticate
 {
-	/**
-	 * Holds the certificate issuer information (available at SSL_CLIENT_I_DN)
-	 *
-	 * @var array
-	 */
-	protected static $ca;
+    /**
+     * Holds the certificate issuer information (available at SSL_CLIENT_I_DN)
+     *
+     * @var array
+     */
+    protected static $ca;
 
-	/**
-	 * Holds the certificate user information (available at SSL_CLIENT_S_DN)
-	 *
-	 * @var array
-	 */
-	protected static $client;
+    /**
+     * Holds the certificate user information (available at SSL_CLIENT_S_DN)
+     *
+     * @var array
+     */
+    protected static $client;
 
-	/**
-	 * Holds the user information
-	 *
-	 * @var array
-	 */
-	protected static $user;
+    /**
+     * Holds the user information
+     *
+     * @var array
+     */
+    protected static $user;
 
-	/**
-	 * Class constructor.
-	 *
-	 * This should only be called once per request, so it doesn't need to store values in
-	 * the instance. Simply checks if the certificate is valid (against configured valid issuers)
-	 * and returns the user information encoded.
-	 */
-	public function __construct()
-	{
-		self::$ca = self::$client = false;
+    /**
+     * Class constructor.
+     *
+     * This should only be called once per request, so it doesn't need to store values in
+     * the instance. Simply checks if the certificate is valid (against configured valid issuers)
+     * and returns the user information encoded.
+     */
+    public function __construct()
+    {
+        self::$ca = self::$client = false;
 
-		if (isset($_SERVER['SSL_CLIENT_I_DN'])) {
-			$CA = self::parse($_SERVER['SSL_CLIENT_I_DN'], Configure::read('CertAuth.mapCa'));
-			// only valid CAs, if this was configured
-			if ($ca=Configure::read('CertAuth.ca')) {
-				$k = Configure::read('CertAuth.caId');
-				if (!$k) $k = 'CN';
-				$id = (isset($CA[$k]))?($CA[$k]):(false);
+        if (isset($_SERVER['SSL_CLIENT_I_DN'])) {
+            $CA = self::parse($_SERVER['SSL_CLIENT_I_DN'], Configure::read('CertAuth.mapCa'));
+            // only valid CAs, if this was configured
+            if ($ca=Configure::read('CertAuth.ca')) {
+                $k = Configure::read('CertAuth.caId');
+                if (!$k) $k = 'CN';
+                $id = (isset($CA[$k]))?($CA[$k]):(false);
 
-				if (!$id) {
-					$CA = false;
-				} else if (is_array($ca)) {
-					if (!in_array($id, $ca)) $CA = false;
-				} else if ($ca!=$id) {
-					$CA = false;
-				}
-				unset($id, $k);
-			}
-			self::$ca = $CA;
-			unset($CA, $ca);
-		}
+                if (!$id) {
+                    $CA = false;
+                } else if (is_array($ca)) {
+                    if (!in_array($id, $ca)) $CA = false;
+                } else if ($ca!=$id) {
+                    $CA = false;
+                }
+                unset($id, $k);
+            }
+            self::$ca = $CA;
+            unset($CA, $ca);
+        }
 
-		if (self::$ca) {
-			$map = Configure::read('CertAuth.map');
-			if(isset($_SERVER['SSL_CLIENT_S_DN'])) {
-				self::$client = self::parse($_SERVER['SSL_CLIENT_S_DN'], $map);
-			} else {
-				self::$client = array();
-			}
-			foreach($map as $n=>$d) {
-				if(isset($_SERVER[$n])) {
-					self::$client[$d] = $_SERVER[$n];
-				}
-				unset($map[$n], $n, $d);
-			}
-			unset($map);
-			if(!self::$client) {
-				self::$client = false;
-			}
-		}
-	}
+        if (self::$ca) {
+            $map = Configure::read('CertAuth.map');
+            if(isset($_SERVER['SSL_CLIENT_S_DN'])) {
+                self::$client = self::parse($_SERVER['SSL_CLIENT_S_DN'], $map);
+            } else {
+                self::$client = array();
+            }
+            foreach($map as $n=>$d) {
+                if(isset($_SERVER[$n])) {
+                    self::$client[$d] = $_SERVER[$n];
+                }
+                unset($map[$n], $n, $d);
+            }
+            unset($map);
+            if(!self::$client) {
+                self::$client = false;
+            }
+        }
+    }
 
-	/**
-	 * Parse certificate extensions
-	 *
-	 * @TODO    this should properly address the RFC
-	 * @param   string            $s    text to be parsed
-	 * @param   (optional) array  $map  array of mapping extension to User fields
-	 * @return  array             parsed values
-	 */
-	private static function parse($s, $map=null)
-	{
-		$r=array();
-		if (preg_match_all('#(^/?|\/|\,)([a-zA-Z]+)\=([^\/\,]+)#', $s, $m)) {
-			foreach ($m[2] as $i=>$k) {
-				if ($map) {
-					if (isset($map[$k])) {
-						$k = $map[$k];
-					} else {
-						$k = null;
-					}
-				}
-				if ($k) {
-					$v = $m[3][$i];
-					$r[$k] = $v;
-				}
-				unset($m[0][$i], $m[1][$i], $m[2][$i], $m[3][$i], $k, $v, $i);
-			}
-		}
-		return $r;
-	}
+    /**
+     * Parse certificate extensions
+     *
+     * @TODO    this should properly address the RFC
+     * @param   string            $s    text to be parsed
+     * @param   (optional) array  $map  array of mapping extension to User fields
+     * @return  array             parsed values
+     */
+    private static function parse($s, $map=null)
+    {
+        $r=array();
+        if (preg_match_all('#(^/?|\/|\,)([a-zA-Z]+)\=([^\/\,]+)#', $s, $m)) {
+            foreach ($m[2] as $i=>$k) {
+                if ($map) {
+                    if (isset($map[$k])) {
+                        $k = $map[$k];
+                    } else {
+                        $k = null;
+                    }
+                }
+                if ($k) {
+                    $v = $m[3][$i];
+                    $r[$k] = $v;
+                }
+                unset($m[0][$i], $m[1][$i], $m[2][$i], $m[3][$i], $k, $v, $i);
+            }
+        }
+        return $r;
+    }
 
-	// to enable stateless authentication
-	public function getUser(CakeRequest $request)
-	{
-		if (empty(self::$user)) {
-			if (self::$client) {
-				self::$user = self::$client;
-				// If $sync is true, allow the creation of the user from the certificate
-				$sync = Configure::read('CertAuth.syncUser');
-				$url = Configure::read('CertAuth.restApi.url');
-				if ($sync && $url) {
-					if (!self::getRestUser()) return false;
-				}
+    // to enable stateless authentication
+    public function getUser(CakeRequest $request)
+    {
+        if (empty(self::$user)) {
+            if (self::$client) {
+                self::$user = self::$client;
+                // If $sync is true, allow the creation of the user from the certificate
+                $sync = Configure::read('CertAuth.syncUser');
+                $url = Configure::read('CertAuth.restApi.url');
+                if ($sync && $url) {
+                    if (!self::getRestUser()) return false;
+                }
 
-				// find and fill user with model
-				$userModelKey = empty(Configure::read('CertAuth.userModelKey')) ? 'email' : Configure::read('CertAuth.userModelKey');
-				$userDefaults = Configure::read('CertAuth.userDefaults');
-				$this->User = ClassRegistry::init('User');
-				if (!empty(self::$user[$userModelKey])) {
-					$existingUser = $this->User->find('first', array(
-						'conditions' => array($userModelKey => self::$user[$userModelKey]),
-						'recursive' => false
-					));
-				}
-				if ($existingUser) {
-					if ($sync) {
-						if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
-							self::$user['org_id'] = $this->User->Organisation->createOrgFromName(self::$user['org'], $existingUser['User']['id'], true);
-							// reset user defaults in case it's a different org_id
-							if (self::$user['org_id'] && $existingUser['User']['org_id'] != self::$user['org_id']) {
-								if ($userDefaults && is_array($userDefaults)) {
-									self::$user = array_merge($userDefaults + self::$user);
-								}
-							}
-							unset(self::$user['org']);
-						}
-						$write = array();
-						foreach (self::$user as $k => $v) {
-							if (isset($existingUser['User'][$k]) && trim($existingUser['User'][$k]) != trim($v)) {
-								$write[] = $k;
-								$existingUser['User'][$k] = trim($v);
-							}
-						}
-						if (!empty($write) && !$this->User->save($existingUser['User'], true, $write)) {
-							CakeLog::write('alert', 'Could not update model at database with RestAPI data.');
-						}
-					}
-					self::$user = $this->User->getAuthUser($existingUser['User']['id']);
-					if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
-				} else if ($sync && !empty(self::$user)) {
-					$org = isset(self::$client['org']) ? self::$client['org'] : null;
-					if ($org == null) return false;
-					if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
-						self::$user['org_id'] = $this->User->Organisation->createOrgFromName($org, 0, true);
-						unset(self::$user['org']);
-					}
-					if ($userDefaults && is_array($userDefaults)) {
-						self::$user = array_merge(self::$user, $userDefaults);
-					}
-					$this->User->create();
-					if ($this->User->save(self::$user)) {
-						$id = $this->User->id;
-						self::$user = $this->User->getAuthUser($id);
-						if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
-					} else {
-						CakeLog::write('alert', 'Could not insert model at database from RestAPI data. Reason: ' . json_encode($this->User->validationErrors));
-					}
-				} else {
-					// No match -- User doesn't exist !!!
-					self::$user = false;
-				}
-			}
-		}
-		return self::$user;
-	}
+                // find and fill user with model
+                $userModelKey = empty(Configure::read('CertAuth.userModelKey')) ? 'email' : Configure::read('CertAuth.userModelKey');
+                $userDefaults = Configure::read('CertAuth.userDefaults');
+                $this->User = ClassRegistry::init('User');
+                if (!empty(self::$user[$userModelKey])) {
+                    $existingUser = $this->User->find('first', array(
+                        'conditions' => array($userModelKey => self::$user[$userModelKey]),
+                        'recursive' => false
+                    ));
+                }
+                if ($existingUser) {
+                    if ($sync) {
+                        if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
+                            self::$user['org_id'] = $this->User->Organisation->createOrgFromName(self::$user['org'], $existingUser['User']['id'], true);
+                            // reset user defaults in case it's a different org_id
+                            if (self::$user['org_id'] && $existingUser['User']['org_id'] != self::$user['org_id']) {
+                                if ($userDefaults && is_array($userDefaults)) {
+                                    self::$user = array_merge($userDefaults + self::$user);
+                                }
+                            }
+                            unset(self::$user['org']);
+                        }
+                        $write = array();
+                        foreach (self::$user as $k => $v) {
+                            if (isset($existingUser['User'][$k]) && trim($existingUser['User'][$k]) != trim($v)) {
+                                $write[] = $k;
+                                $existingUser['User'][$k] = trim($v);
+                            }
+                        }
+                        if (!empty($write) && !$this->User->save($existingUser['User'], true, $write)) {
+                            CakeLog::write('alert', 'Could not update model at database with RestAPI data.');
+                        }
+                    }
+                    self::$user = $this->User->getAuthUser($existingUser['User']['id']);
+                    if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
+                } else if ($sync && !empty(self::$user)) {
+                    $org = isset(self::$client['org']) ? self::$client['org'] : null;
+                    if ($org == null) return false;
+                    if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
+                        self::$user['org_id'] = $this->User->Organisation->createOrgFromName($org, 0, true);
+                        unset(self::$user['org']);
+                    }
+                    if ($userDefaults && is_array($userDefaults)) {
+                        self::$user = array_merge(self::$user, $userDefaults);
+                    }
+                    $this->User->create();
+                    if ($this->User->save(self::$user)) {
+                        $id = $this->User->id;
+                        self::$user = $this->User->getAuthUser($id);
+                        if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
+                    } else {
+                        CakeLog::write('alert', 'Could not insert model at database from RestAPI data. Reason: ' . json_encode($this->User->validationErrors));
+                    }
+                } else {
+                    // No match -- User doesn't exist !!!
+                    self::$user = false;
+                }
+            }
+        }
+        return self::$user;
+    }
 
-	// to enable stateless authentication
-	public function authenticate(CakeRequest $request, CakeResponse $response)
-	{
-		return self::getUser($request);
-	}
+    // to enable stateless authentication
+    public function authenticate(CakeRequest $request, CakeResponse $response)
+    {
+        return self::getUser($request);
+    }
 
-	/**
-	 * Fetches user information from external REST API
-	 *
-	 * Valid options (should be configured under CertAuth.restApi):
-	 *
-	 * @param   (optional) array  $options  API configuration
-	 *  url     (string) Where to fetch information from
-	 *  headers (array)  list of additional headers to be used, reserved for authentication tokens
-	 *  params  (array)  mapping of additional params to be included at the url, uses $user values
-	 *  map     (array)  mapping of the return values to be added to the self::$user
-	 * @return  array    updated user object
-	 */
-	public function getRestUser($options=null, $user=null)
-	{
-		if (is_null($options)) {
-			$options = Configure::read('CertAuth.restApi');
-		}
-		if (!is_null($user)) {
-			self::$user = $user;
-		}
+    /**
+     * Fetches user information from external REST API
+     *
+     * Valid options (should be configured under CertAuth.restApi):
+     *
+     * @param   (optional) array  $options  API configuration
+     *  url     (string) Where to fetch information from
+     *  headers (array)  list of additional headers to be used, reserved for authentication tokens
+     *  params  (array)  mapping of additional params to be included at the url, uses $user values
+     *  map     (array)  mapping of the return values to be added to the self::$user
+     * @return  array    updated user object
+     */
+    public function getRestUser($options=null, $user=null)
+    {
+        if (is_null($options)) {
+            $options = Configure::read('CertAuth.restApi');
+        }
+        if (!is_null($user)) {
+            self::$user = $user;
+        }
 
-		if (!isset($options['url'])) {
-			return null;
-		}
+        if (!isset($options['url'])) {
+            return null;
+        }
 
-		// Create a stream
-		$req = array(
-			'http'=>array(
-				'method'=>'GET',
-				'header'=>"Accept: application/json\r\n"
-			),
-		);
-		if (isset($options['headers'])) {
-			foreach ($options['headers'] as $k=>$v) {
-				if (is_int($k)) {
-					$req['header'] .= "{$v}\r\n";
-				} else {
-					$req['header'] .= "{$k}: {$v}\r\n";
-				}
-				unset($k, $v);
-			}
-		}
+        // Create a stream
+        $req = array(
+            'http'=>array(
+                'method'=>'GET',
+                'header'=>"Accept: application/json\r\n"
+            ),
+        );
+        if (isset($options['headers'])) {
+            foreach ($options['headers'] as $k=>$v) {
+                if (is_int($k)) {
+                    $req['header'] .= "{$v}\r\n";
+                } else {
+                    $req['header'] .= "{$k}: {$v}\r\n";
+                }
+                unset($k, $v);
+            }
+        }
 
-		$url = $options['url'];
-		if (isset($options['param'])) {
-			foreach ($options['param'] as $k=>$v) {
-				if (isset(self::$user[$v])) {
-					$url .= ((strpos($url, '?'))?('&'):('?'))
-						. $k . '=' . urlencode(self::$user[$v]);
-				}
-				unset($k, $v);
-			}
-		}
-		$ctx = stream_context_create($req);
-		$a   = file_get_contents($url, false, $ctx);
-		if (!$a) return null;
+        $url = $options['url'];
+        if (isset($options['param'])) {
+            foreach ($options['param'] as $k=>$v) {
+                if (isset(self::$user[$v])) {
+                    $url .= ((strpos($url, '?'))?('&'):('?'))
+                        . $k . '=' . urlencode(self::$user[$v]);
+                }
+                unset($k, $v);
+            }
+        }
+        $ctx = stream_context_create($req);
+        $url = mb_ereg_replace("/phar\:\/\//i", '', $url);
+        $a   = file_get_contents($url, false, $ctx);
+        if (!$a) return null;
 
-		$A = json_decode($a, true);
-		if (!isset($A['data'][0])) {
-			self::$user = false;
-		} else if (isset($options['map'])) {
-			foreach ($options['map'] as $k=>$v) {
-				if (isset($A['data'][0][$k])) {
-					self::$user[$v] = $A['data'][0][$k];
-				}
-				unset($k, $v);
-			}
-		}
+        $A = json_decode($a, true);
+        if (!isset($A['data'][0])) {
+            self::$user = false;
+        } else if (isset($options['map'])) {
+            foreach ($options['map'] as $k=>$v) {
+                if (isset($A['data'][0][$k])) {
+                    self::$user[$v] = $A['data'][0][$k];
+                }
+                unset($k, $v);
+            }
+        }
 
-		return self::$user;
-	}
+        return self::$user;
+    }
 
-	protected static $instance;
+    protected static $instance;
 
-	public static function ca()
-	{
-		if (is_null(self::$ca)) new CertificateAuthenticate();
-		return self::$ca;
-	}
+    public static function ca()
+    {
+        if (is_null(self::$ca)) new CertificateAuthenticate();
+        return self::$ca;
+    }
 
-	public static function client()
-	{
-		if (is_null(self::$client)) new CertificateAuthenticate();
-		return self::$client;
-	}
+    public static function client()
+    {
+        if (is_null(self::$client)) new CertificateAuthenticate();
+        return self::$client;
+    }
 
 }

Vulnerable code:                 if (!is_dir($this->data['Feed']['url'])) {
                if (!file_exists($this->data['Feed']['url'])) {
	/**
	 * Holds the certificate issuer information (available at SSL_CLIENT_I_DN)
	 *
	 * @var array
	 */
	protected static $ca;
	/**
	 * Holds the certificate user information (available at SSL_CLIENT_S_DN)
	 *
	 * @var array
	 */
	protected static $client;
	/**
	 * Holds the user information
	 *
	 * @var array
	 */
	protected static $user;
	/**
	 * Class constructor.
	 *
	 * This should only be called once per request, so it doesn't need to store values in
	 * the instance. Simply checks if the certificate is valid (against configured valid issuers)
	 * and returns the user information encoded.
	 */
	public function __construct()
	{
		self::$ca = self::$client = false;
		if (isset($_SERVER['SSL_CLIENT_I_DN'])) {
			$CA = self::parse($_SERVER['SSL_CLIENT_I_DN'], Configure::read('CertAuth.mapCa'));
			// only valid CAs, if this was configured
			if ($ca=Configure::read('CertAuth.ca')) {
				$k = Configure::read('CertAuth.caId');
				if (!$k) $k = 'CN';
				$id = (isset($CA[$k]))?($CA[$k]):(false);
				if (!$id) {
					$CA = false;
				} else if (is_array($ca)) {
					if (!in_array($id, $ca)) $CA = false;
				} else if ($ca!=$id) {
					$CA = false;
				}
				unset($id, $k);
			}
			self::$ca = $CA;
			unset($CA, $ca);
		}
		if (self::$ca) {
			$map = Configure::read('CertAuth.map');
			if(isset($_SERVER['SSL_CLIENT_S_DN'])) {
				self::$client = self::parse($_SERVER['SSL_CLIENT_S_DN'], $map);
			} else {
				self::$client = array();
			}
			foreach($map as $n=>$d) {
				if(isset($_SERVER[$n])) {
					self::$client[$d] = $_SERVER[$n];
				}
				unset($map[$n], $n, $d);
			}
			unset($map);
			if(!self::$client) {
				self::$client = false;
			}
		}
	}
	/**
	 * Parse certificate extensions
	 *
	 * @TODO    this should properly address the RFC
	 * @param   string            $s    text to be parsed
	 * @param   (optional) array  $map  array of mapping extension to User fields
	 * @return  array             parsed values
	 */
	private static function parse($s, $map=null)
	{
		$r=array();
		if (preg_match_all('#(^/?|\/|\,)([a-zA-Z]+)\=([^\/\,]+)#', $s, $m)) {
			foreach ($m[2] as $i=>$k) {
				if ($map) {
					if (isset($map[$k])) {
						$k = $map[$k];
					} else {
						$k = null;
					}
				}
				if ($k) {
					$v = $m[3][$i];
					$r[$k] = $v;
				}
				unset($m[0][$i], $m[1][$i], $m[2][$i], $m[3][$i], $k, $v, $i);
			}
		}
		return $r;
	}
	// to enable stateless authentication
	public function getUser(CakeRequest $request)
	{
		if (empty(self::$user)) {
			if (self::$client) {
				self::$user = self::$client;
				// If $sync is true, allow the creation of the user from the certificate
				$sync = Configure::read('CertAuth.syncUser');
				$url = Configure::read('CertAuth.restApi.url');
				if ($sync && $url) {
					if (!self::getRestUser()) return false;
				}
				// find and fill user with model
				$userModelKey = empty(Configure::read('CertAuth.userModelKey')) ? 'email' : Configure::read('CertAuth.userModelKey');
				$userDefaults = Configure::read('CertAuth.userDefaults');
				$this->User = ClassRegistry::init('User');
				if (!empty(self::$user[$userModelKey])) {
					$existingUser = $this->User->find('first', array(
						'conditions' => array($userModelKey => self::$user[$userModelKey]),
						'recursive' => false
					));
				}
				if ($existingUser) {
					if ($sync) {
						if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
							self::$user['org_id'] = $this->User->Organisation->createOrgFromName(self::$user['org'], $existingUser['User']['id'], true);
							// reset user defaults in case it's a different org_id
							if (self::$user['org_id'] && $existingUser['User']['org_id'] != self::$user['org_id']) {
								if ($userDefaults && is_array($userDefaults)) {
									self::$user = array_merge($userDefaults + self::$user);
								}
							}
							unset(self::$user['org']);
						}
						$write = array();
						foreach (self::$user as $k => $v) {
							if (isset($existingUser['User'][$k]) && trim($existingUser['User'][$k]) != trim($v)) {
								$write[] = $k;
								$existingUser['User'][$k] = trim($v);
							}
						}
						if (!empty($write) && !$this->User->save($existingUser['User'], true, $write)) {
							CakeLog::write('alert', 'Could not update model at database with RestAPI data.');
						}
					}
					self::$user = $this->User->getAuthUser($existingUser['User']['id']);
					if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
				} else if ($sync && !empty(self::$user)) {
					$org = isset(self::$client['org']) ? self::$client['org'] : null;
					if ($org == null) return false;
					if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
						self::$user['org_id'] = $this->User->Organisation->createOrgFromName($org, 0, true);
						unset(self::$user['org']);
					}
					if ($userDefaults && is_array($userDefaults)) {
						self::$user = array_merge(self::$user, $userDefaults);
					}
					$this->User->create();
					if ($this->User->save(self::$user)) {
						$id = $this->User->id;
						self::$user = $this->User->getAuthUser($id);
						if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
					} else {
						CakeLog::write('alert', 'Could not insert model at database from RestAPI data. Reason: ' . json_encode($this->User->validationErrors));
					}
				} else {
					// No match -- User doesn't exist !!!
					self::$user = false;
				}
			}
		}
		return self::$user;
	}
	// to enable stateless authentication
	public function authenticate(CakeRequest $request, CakeResponse $response)
	{
		return self::getUser($request);
	}
	/**
	 * Fetches user information from external REST API
	 *
	 * Valid options (should be configured under CertAuth.restApi):
	 *
	 * @param   (optional) array  $options  API configuration
	 *  url     (string) Where to fetch information from
	 *  headers (array)  list of additional headers to be used, reserved for authentication tokens
	 *  params  (array)  mapping of additional params to be included at the url, uses $user values
	 *  map     (array)  mapping of the return values to be added to the self::$user
	 * @return  array    updated user object
	 */
	public function getRestUser($options=null, $user=null)
	{
		if (is_null($options)) {
			$options = Configure::read('CertAuth.restApi');
		}
		if (!is_null($user)) {
			self::$user = $user;
		}
		if (!isset($options['url'])) {
			return null;
		}
		// Create a stream
		$req = array(
			'http'=>array(
				'method'=>'GET',
				'header'=>"Accept: application/json\r\n"
			),
		);
		if (isset($options['headers'])) {
			foreach ($options['headers'] as $k=>$v) {
				if (is_int($k)) {
					$req['header'] .= "{$v}\r\n";
				} else {
					$req['header'] .= "{$k}: {$v}\r\n";
				}
				unset($k, $v);
			}
		}
		$url = $options['url'];
		if (isset($options['param'])) {
			foreach ($options['param'] as $k=>$v) {
				if (isset(self::$user[$v])) {
					$url .= ((strpos($url, '?'))?('&'):('?'))
						. $k . '=' . urlencode(self::$user[$v]);
				}
				unset($k, $v);
			}
		}
		$ctx = stream_context_create($req);
		$a   = file_get_contents($url, false, $ctx);
		if (!$a) return null;
		$A = json_decode($a, true);
		if (!isset($A['data'][0])) {
			self::$user = false;
		} else if (isset($options['map'])) {
			foreach ($options['map'] as $k=>$v) {
				if (isset($A['data'][0][$k])) {
					self::$user[$v] = $A['data'][0][$k];
				}
				unset($k, $v);
			}
		}
		return self::$user;
	}
	protected static $instance;
	public static function ca()
	{
		if (is_null(self::$ca)) new CertificateAuthenticate();
		return self::$ca;
	}
	public static function client()
	{
		if (is_null(self::$client)) new CertificateAuthenticate();
		return self::$client;
	}
Fixed code:             $rdkafkaIni = mb_ereg_replace("/\:\/\//", '', $rdkafkaIni);
            $path = mb_ereg_replace("/\:\/\//", '', $this->data['Feed']['url']);
                if (!is_dir($path)) {
                if (!file_exists($path)) {
            $uri = mb_ereg_replace("/\:\/\//", '', $uri);
    /**
     * Holds the certificate issuer information (available at SSL_CLIENT_I_DN)
     *
     * @var array
     */
    protected static $ca;
    /**
     * Holds the certificate user information (available at SSL_CLIENT_S_DN)
     *
     * @var array
     */
    protected static $client;
    /**
     * Holds the user information
     *
     * @var array
     */
    protected static $user;
    /**
     * Class constructor.
     *
     * This should only be called once per request, so it doesn't need to store values in
     * the instance. Simply checks if the certificate is valid (against configured valid issuers)
     * and returns the user information encoded.
     */
    public function __construct()
    {
        self::$ca = self::$client = false;
        if (isset($_SERVER['SSL_CLIENT_I_DN'])) {
            $CA = self::parse($_SERVER['SSL_CLIENT_I_DN'], Configure::read('CertAuth.mapCa'));
            // only valid CAs, if this was configured
            if ($ca=Configure::read('CertAuth.ca')) {
                $k = Configure::read('CertAuth.caId');
                if (!$k) $k = 'CN';
                $id = (isset($CA[$k]))?($CA[$k]):(false);
                if (!$id) {
                    $CA = false;
                } else if (is_array($ca)) {
                    if (!in_array($id, $ca)) $CA = false;
                } else if ($ca!=$id) {
                    $CA = false;
                }
                unset($id, $k);
            }
            self::$ca = $CA;
            unset($CA, $ca);
        }
        if (self::$ca) {
            $map = Configure::read('CertAuth.map');
            if(isset($_SERVER['SSL_CLIENT_S_DN'])) {
                self::$client = self::parse($_SERVER['SSL_CLIENT_S_DN'], $map);
            } else {
                self::$client = array();
            }
            foreach($map as $n=>$d) {
                if(isset($_SERVER[$n])) {
                    self::$client[$d] = $_SERVER[$n];
                }
                unset($map[$n], $n, $d);
            }
            unset($map);
            if(!self::$client) {
                self::$client = false;
            }
        }
    }
    /**
     * Parse certificate extensions
     *
     * @TODO    this should properly address the RFC
     * @param   string            $s    text to be parsed
     * @param   (optional) array  $map  array of mapping extension to User fields
     * @return  array             parsed values
     */
    private static function parse($s, $map=null)
    {
        $r=array();
        if (preg_match_all('#(^/?|\/|\,)([a-zA-Z]+)\=([^\/\,]+)#', $s, $m)) {
            foreach ($m[2] as $i=>$k) {
                if ($map) {
                    if (isset($map[$k])) {
                        $k = $map[$k];
                    } else {
                        $k = null;
                    }
                }
                if ($k) {
                    $v = $m[3][$i];
                    $r[$k] = $v;
                }
                unset($m[0][$i], $m[1][$i], $m[2][$i], $m[3][$i], $k, $v, $i);
            }
        }
        return $r;
    }
    // to enable stateless authentication
    public function getUser(CakeRequest $request)
    {
        if (empty(self::$user)) {
            if (self::$client) {
                self::$user = self::$client;
                // If $sync is true, allow the creation of the user from the certificate
                $sync = Configure::read('CertAuth.syncUser');
                $url = Configure::read('CertAuth.restApi.url');
                if ($sync && $url) {
                    if (!self::getRestUser()) return false;
                }
                // find and fill user with model
                $userModelKey = empty(Configure::read('CertAuth.userModelKey')) ? 'email' : Configure::read('CertAuth.userModelKey');
                $userDefaults = Configure::read('CertAuth.userDefaults');
                $this->User = ClassRegistry::init('User');
                if (!empty(self::$user[$userModelKey])) {
                    $existingUser = $this->User->find('first', array(
                        'conditions' => array($userModelKey => self::$user[$userModelKey]),
                        'recursive' => false
                    ));
                }
                if ($existingUser) {
                    if ($sync) {
                        if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
                            self::$user['org_id'] = $this->User->Organisation->createOrgFromName(self::$user['org'], $existingUser['User']['id'], true);
                            // reset user defaults in case it's a different org_id
                            if (self::$user['org_id'] && $existingUser['User']['org_id'] != self::$user['org_id']) {
                                if ($userDefaults && is_array($userDefaults)) {
                                    self::$user = array_merge($userDefaults + self::$user);
                                }
                            }
                            unset(self::$user['org']);
                        }
                        $write = array();
                        foreach (self::$user as $k => $v) {
                            if (isset($existingUser['User'][$k]) && trim($existingUser['User'][$k]) != trim($v)) {
                                $write[] = $k;
                                $existingUser['User'][$k] = trim($v);
                            }
                        }
                        if (!empty($write) && !$this->User->save($existingUser['User'], true, $write)) {
                            CakeLog::write('alert', 'Could not update model at database with RestAPI data.');
                        }
                    }
                    self::$user = $this->User->getAuthUser($existingUser['User']['id']);
                    if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
                } else if ($sync && !empty(self::$user)) {
                    $org = isset(self::$client['org']) ? self::$client['org'] : null;
                    if ($org == null) return false;
                    if (!isset(self::$user['org_id']) && isset(self::$user['org'])) {
                        self::$user['org_id'] = $this->User->Organisation->createOrgFromName($org, 0, true);
                        unset(self::$user['org']);
                    }
                    if ($userDefaults && is_array($userDefaults)) {
                        self::$user = array_merge(self::$user, $userDefaults);
                    }
                    $this->User->create();
                    if ($this->User->save(self::$user)) {
                        $id = $this->User->id;
                        self::$user = $this->User->getAuthUser($id);
                        if (isset(self::$user['gpgkey'])) unset(self::$user['gpgkey']);
                    } else {
                        CakeLog::write('alert', 'Could not insert model at database from RestAPI data. Reason: ' . json_encode($this->User->validationErrors));
                    }
                } else {
                    // No match -- User doesn't exist !!!
                    self::$user = false;
                }
            }
        }
        return self::$user;
    }
    // to enable stateless authentication
    public function authenticate(CakeRequest $request, CakeResponse $response)
    {
        return self::getUser($request);
    }
    /**
     * Fetches user information from external REST API
     *
     * Valid options (should be configured under CertAuth.restApi):
     *
     * @param   (optional) array  $options  API configuration
     *  url     (string) Where to fetch information from
     *  headers (array)  list of additional headers to be used, reserved for authentication tokens
     *  params  (array)  mapping of additional params to be included at the url, uses $user values
     *  map     (array)  mapping of the return values to be added to the self::$user
     * @return  array    updated user object
     */
    public function getRestUser($options=null, $user=null)
    {
        if (is_null($options)) {
            $options = Configure::read('CertAuth.restApi');
        }
        if (!is_null($user)) {
            self::$user = $user;
        }
        if (!isset($options['url'])) {
            return null;
        }
        // Create a stream
        $req = array(
            'http'=>array(
                'method'=>'GET',
                'header'=>"Accept: application/json\r\n"
            ),
        );
        if (isset($options['headers'])) {
            foreach ($options['headers'] as $k=>$v) {
                if (is_int($k)) {
                    $req['header'] .= "{$v}\r\n";
                } else {
                    $req['header'] .= "{$k}: {$v}\r\n";
                }
                unset($k, $v);
            }
        }
        $url = $options['url'];
        if (isset($options['param'])) {
            foreach ($options['param'] as $k=>$v) {
                if (isset(self::$user[$v])) {
                    $url .= ((strpos($url, '?'))?('&'):('?'))
                        . $k . '=' . urlencode(self::$user[$v]);
                }
                unset($k, $v);
            }
        }
        $ctx = stream_context_create($req);
        $url = mb_ereg_replace("/phar\:\/\//i", '', $url);
        $a   = file_get_contents($url, false, $ctx);
        if (!$a) return null;
        $A = json_decode($a, true);
        if (!isset($A['data'][0])) {
            self::$user = false;
        } else if (isset($options['map'])) {
            foreach ($options['map'] as $k=>$v) {
                if (isset($A['data'][0][$k])) {
                    self::$user[$v] = $A['data'][0][$k];
                }
                unset($k, $v);
            }
        }
        return self::$user;
    }
    protected static $instance;
    public static function ca()
    {
        if (is_null(self::$ca)) new CertificateAuthenticate();
        return self::$ca;
    }
    public static function client()
    {
        if (is_null(self::$client)) new CertificateAuthenticate();
        return self::$client;
    }