From a86d89f5ca8d71febd764b20e939010901be4974 Mon Sep 17 00:00:00 2001
From: Frank Karlitschek <karlitschek@kde.org>
Date: Sat, 21 Apr 2012 22:47:56 +0200
Subject: [PATCH] Add a static code checker for evil patterns in apps. Disabled
 by default for now. We will check for private api calls here later once the
 public api is in place

---
 config/config.sample.php |  1 +
 lib/installer.php        | 59 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/config/config.sample.php b/config/config.sample.php
index 9f6d674fc0..0900937c69 100755
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -24,6 +24,7 @@ $CONFIG = array(
 "mail_smtpauth" => "false",
 "mail_smtpname" => "",
 "mail_smtppassword" => "",
+"appcodechecker" => "",
 // "datadirectory" => ""
 );
 ?>
diff --git a/lib/installer.php b/lib/installer.php
index 6edf4ce1b7..d559227381 100644
--- a/lib/installer.php
+++ b/lib/installer.php
@@ -47,6 +47,7 @@ class OC_Installer{
 	 * This function works as follows
 	 *   -# fetching the file
 	 *   -# unzipping it
+	 *   -# check the code
 	 *   -# installing the database at appinfo/database.xml
 	 *   -# including appinfo/install.php
 	 *   -# setting the installed version
@@ -91,6 +92,7 @@ class OC_Installer{
 		
 		//extract the archive in a temporary folder
 		$extractDir=OC_Helper::tmpFolder();
+		OC_Helper::rmdirr($extractDir);
 		mkdir($extractDir);
 		if($archive=OC_Archive::open($path)){
 			$archive->extract($extractDir);
@@ -102,7 +104,7 @@ class OC_Installer{
 			}
 			return false;
 		}
-		
+	
 		//load the info.xml file of the app
 		if(!is_file($extractDir.'/appinfo/info.xml')){
 			//try to find it in a subdir
@@ -125,6 +127,12 @@ class OC_Installer{
 		}
 		$info=OC_App::getAppInfo($extractDir.'/appinfo/info.xml',true);
 		$basedir=OC::$APPSROOT.'/apps/'.$info['id'];
+
+                // check the code for not allowed calls
+                if(!OC_Installer::checkCode($info['id'],$extractDir)){
+			OC_Helper::rmdirr($extractDir);
+                        return false;
+		}
 		
 		//check if an app with the same id is already installed
 		if(self::isInstalled( $info['id'] )){
@@ -151,8 +159,8 @@ class OC_Installer{
 		}
 		
 		//copy the app to the correct place
-		if(!mkdir($basedir)){
-			OC_Log::write('core','Can\'t create app folder ('.$basedir.')',OC_Log::ERROR);
+		if(@!mkdir($basedir)){
+			OC_Log::write('core','Can\'t create app folder. Please fix permissions. ('.$basedir.')',OC_Log::ERROR);
 			OC_Helper::rmdirr($extractDir);
 			if($data['source']=='http'){
 				unlink($path);
@@ -300,4 +308,49 @@ class OC_Installer{
 		OC_Appconfig::setValue($app,'installed_version',OC_App::getAppVersion($app));
 		return $info;
 	}
+
+
+        /**
+         * check the code of an app with some static code checks
+         * @param string $folder the folder of the app to check
+         * @returns true for app is o.k. and false for app is not o.k.
+         */
+        public static function checkCode($appname,$folder){
+
+		$blacklist=array(
+			'fopen(',
+			'eval('
+			// more evil pattern will go here later
+			// will will also check if an app is using private api once the public api is in place
+
+		);
+
+		// is the code checker enabled?
+		if(OC_Config::getValue('appcodechecker', false)){   
+
+			// check if grep is installed
+			$grep = exec('which grep');
+			if($grep=='') {
+				OC_Log::write('core','grep not installed. So checking the code of the app "'.$appname.'" was not possible',OC_Log::ERROR);
+				return true;
+			}
+
+			// iterate the bad patterns
+			foreach($blacklist as $bl) {
+				$cmd = 'grep -ri '.escapeshellarg($bl).' '.$folder.'';
+				$result = exec($cmd);
+				// bad pattern found
+				if($result<>'') {
+					OC_Log::write('core','App "'.$appname.'" is using a not allowed call "'.$bl.'". Installation refused.',OC_Log::ERROR);
+					return false;
+				}
+			}
+			return true;
+			
+		}else{
+          		return true;
+		}
+        }
+
+
 }
-- 
GitLab