From 8d6eddcf1e90ee0bf9373398eafe0e0fbf97ffee Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Sat, 27 Jun 2009 06:56:41 +0000 Subject: [PATCH] Experimental: add function to encrypt sensitive data in database --- htdocs/core/conf.class.php | 5 +- .../modules/DolibarrModules.class.php | 36 +++---- htdocs/lib/admin.lib.php | 15 +-- htdocs/lib/databases/mysqli.lib.php | 101 +++++++++++++----- htdocs/master.inc.php | 4 + 5 files changed, 109 insertions(+), 52 deletions(-) diff --git a/htdocs/core/conf.class.php b/htdocs/core/conf.class.php index f2514a18a0a..e991011ec8c 100644 --- a/htdocs/core/conf.class.php +++ b/htdocs/core/conf.class.php @@ -76,6 +76,8 @@ class Conf */ function setValues($db) { + global $conf; + dol_syslog("Conf::setValues"); /* @@ -83,7 +85,8 @@ class Conf * - En constante php (TODO a virer) * - En $this->global->key=value */ - $sql = "SELECT name, value, entity"; + $sql = "SELECT ".$db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." as name"; + $sql.= ",".$db->decrypt('value',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." as value, entity"; $sql.= " FROM ".MAIN_DB_PREFIX."const"; $sql.= " WHERE entity IN (0,".$this->entity.")"; diff --git a/htdocs/includes/modules/DolibarrModules.class.php b/htdocs/includes/modules/DolibarrModules.class.php index 721805db99d..cb0456d76c0 100644 --- a/htdocs/includes/modules/DolibarrModules.class.php +++ b/htdocs/includes/modules/DolibarrModules.class.php @@ -376,14 +376,14 @@ class DolibarrModules $entity = ((isset($this->always_enabled)||isset($this->core_enabled)) ? 0 : $conf->entity); $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name = '".$this->const_name."'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = '".$this->const_name."'"; $sql.= " AND entity = ".$entity; dol_syslog("DolibarrModules::_active sql=".$sql, LOG_DEBUG); $this->db->query($sql); $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,value,visible,entity) VALUES"; - $sql.= " ('".$this->const_name."','1',0,".$entity.")"; + $sql.= " (".$this->db->encrypt("'".$this->const_name."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",".$this->db->encrypt('1',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",0,".$entity.")"; dol_syslog("DolibarrModules::_active sql=".$sql, LOG_DEBUG); if (!$this->db->query($sql)) @@ -409,7 +409,7 @@ class DolibarrModules $entity = (isset($this->core_enabled) ? 0 : $conf->entity); $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name = '".$this->const_name."'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = '".$this->const_name."'"; $sql.= " AND entity = ".$entity; dol_syslog("DolibarrModules::_unactive sql=".$sql); @@ -604,7 +604,7 @@ class DolibarrModules if ($this->style_sheet) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name = '".$this->const_name."_CSS'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = '".$this->const_name."_CSS'"; $sql.= " AND entity = ".$conf->entity; dol_syslog("DolibarrModules::delete_style_sheet sql=".$sql); @@ -630,7 +630,7 @@ class DolibarrModules $err=0; $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name like '".$this->const_name."_TABS_%'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." like '".$this->const_name."_TABS_%'"; $sql.= " AND entity = ".$conf->entity; dol_syslog("DolibarrModules::delete_tabs sql=".$sql); @@ -665,9 +665,9 @@ class DolibarrModules $sql.= ", entity"; $sql.= ")"; $sql.= " VALUES ("; - $sql.= "'".$this->const_name."_CSS'"; + $sql.= $this->db->encrypt("'".$this->const_name."_CSS'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey); $sql.= ", 'chaine'"; - $sql.= ", '".$this->style_sheet."'"; + $sql.= ", ".$this->db->encrypt("'".$this->style_sheet."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey); $sql.= ", 'Style sheet for module ".$this->name."'"; $sql.= ", '0'"; $sql.= ", ".$conf->entity; @@ -712,9 +712,9 @@ class DolibarrModules $sql.= ", entity"; $sql.= ")"; $sql.= " VALUES ("; - $sql.= "'".$this->const_name."_TABS_".$i."'"; + $sql.= $this->db->encrypt("'".$this->const_name."_TABS_".$i."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey); $sql.= ", 'chaine'"; - $sql.= ", '".$value."'"; + $sql.= ", ".$this->db->encrypt("'".$value."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey); $sql.= ", null"; $sql.= ", '0'"; $sql.= ", ".$conf->entity; @@ -755,7 +755,7 @@ class DolibarrModules $sql = "SELECT count(*)"; $sql.= " FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name ='".$name."'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = ".$name; $sql.= " AND entity = ".$conf->entity; $result=$this->db->query($sql); @@ -769,17 +769,17 @@ class DolibarrModules if (strlen($note)) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,note,visible,entity)"; - $sql.= " VALUES ('".$name."','".$type."','".$val."','".$note."','".$visible."',".$conf->entity.")"; + $sql.= " VALUES (".$this->db->encrypt("'".$name."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'".$type."',".$this->db->encrypt("'".$val."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'".$note."','".$visible."',".$conf->entity.")"; } elseif (strlen($val)) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,visible,entity)"; - $sql.= " VALUES ('".$name."','".$type."','".$val."','".$visible."',".$conf->entity.")"; + $sql.= " VALUES (".$this->db->encrypt("'".$name."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'".$type."',".$this->db->encrypt("'".$val."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'".$visible."',".$conf->entity.")"; } else { $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,visible,entity)"; - $sql.= " VALUES ('".$name."','".$type."','".$visible."',".$conf->entity.")"; + $sql.= " VALUES (".$this->db->encrypt("'".$name."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'".$type."','".$visible."',".$conf->entity.")"; } dol_syslog("DolibarrModules::insert_const sql=".$sql); @@ -812,8 +812,8 @@ class DolibarrModules //print $this->rights_class." ".sizeof($this->rights)."
"; // Test si module actif - $sql_del = "SELECT value FROM ".MAIN_DB_PREFIX."const"; - $sql_del.= " WHERE name = '".$this->const_name."'"; + $sql_del = "SELECT ".$this->db->decrypt('value',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." FROM ".MAIN_DB_PREFIX."const"; + $sql_del.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = ".$this->const_name; $sql_del.= " AND entity IN (0,".$conf->entity.")"; $resql=$this->db->query($sql_del); if ($resql) { @@ -1080,7 +1080,7 @@ class DolibarrModules $sql = "SELECT count(*)"; $sql.= " FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name ='".$name."'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = ".$name; $sql.= " AND entity = ".$conf->entity; $result=$this->db->query($sql); @@ -1091,7 +1091,7 @@ class DolibarrModules if ($row[0] == 0) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,note,visible,entity)"; - $sql.= " VALUES ('".$name."','chaine','".$dir."','Directory for module ".$this->name."','0',".$conf->entity.")"; + $sql.= " VALUES (".$this->db->encrypt("'".$name."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'chaine',".$this->db->encrypt("'".$dir."'",$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey).",'Directory for module ".$this->name."','0',".$conf->entity.")"; dol_syslog("DolibarrModules::insert_dir_output sql=".$sql); $resql=$this->db->query($sql); @@ -1117,7 +1117,7 @@ class DolibarrModules $err=0; $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; - $sql.= " WHERE name like '".$this->const_name."_DIR_%'"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." like '".$this->const_name."_DIR_%'"; $sql.= " AND entity = ".$conf->entity; dol_syslog("DolibarrModules::delete_dirs sql=".$sql); diff --git a/htdocs/lib/admin.lib.php b/htdocs/lib/admin.lib.php index 20d9126c35c..9f1cdf3abce 100644 --- a/htdocs/lib/admin.lib.php +++ b/htdocs/lib/admin.lib.php @@ -302,8 +302,8 @@ function dolibarr_del_const($db, $name, $entity=1) { global $conf; - $sql = "DELETE FROM llx_const"; - $sql.=" WHERE (name='".addslashes($name)."' OR rowid='".addslashes($name)."')"; + $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; + $sql.=" WHERE (".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = '".addslashes($name)."' OR rowid = '".addslashes($name)."')"; $sql.= " AND entity = ".$entity; dol_syslog("admin.lib::dolibarr_del_const sql=".$sql); @@ -332,9 +332,9 @@ function dolibarr_get_const($db, $name, $entity=1) global $conf; $value=''; - $sql = "SELECT value"; - $sql.= " FROM llx_const"; - $sql.= " WHERE name = '".addslashes($name)."'"; + $sql = "SELECT ".$db->decrypt('value',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." as value"; + $sql.= " FROM ".MAIN_DB_PREFIX."const"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = '".addslashes($name)."'"; $sql.= " AND entity = ".$entity; dol_syslog("admin.lib::dolibarr_get_const sql=".$sql); @@ -373,7 +373,8 @@ function dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $not $db->begin(); //dol_syslog("dolibarr_set_const name=$name, value=$value"); - $sql = "DELETE FROM llx_const WHERE name = '".addslashes($name)."'"; + $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; + $sql.= " WHERE ".$this->db->decrypt('name',$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)." = '".addslashes($name)."'"; $sql.= " AND entity = ".$entity; dol_syslog("admin.lib::dolibarr_set_const sql=".$sql, LOG_DEBUG); $resql=$db->query($sql); @@ -381,7 +382,7 @@ function dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $not if (strcmp($value,'')) // true if different. Must work for $value='0' or $value=0 { $sql = "INSERT INTO llx_const(name,value,type,visible,note,entity)"; - $sql.= " VALUES ('".$name."','".addslashes($value)."','".$type."',".$visible.",'".addslashes($note)."',".$entity.")"; + $sql.= " VALUES ('".$db->encrypt($name,$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)."','".$db->encrypt(addslashes($value),$conf->db->dolibarr_main_db_encryption,$conf->db->dolibarr_main_db_cryptkey)."','".$type."',".$visible.",'".addslashes($note)."',".$entity.")"; dol_syslog("admin.lib::dolibarr_set_const sql=".$sql, LOG_DEBUG); $resql=$db->query($sql); diff --git a/htdocs/lib/databases/mysqli.lib.php b/htdocs/lib/databases/mysqli.lib.php index bfdd7ba58ed..923d6a24b0b 100644 --- a/htdocs/lib/databases/mysqli.lib.php +++ b/htdocs/lib/databases/mysqli.lib.php @@ -72,10 +72,10 @@ class DoliDb /** - \brief Ouverture d'une connexion vers le serveur et �ventuellement une database. - \param type Type de base de donn�es (mysql ou pgsql) - \param host Addresse de la base de donn�es - \param user Nom de l'utilisateur autoris� + \brief Ouverture d'une connexion vers le serveur et eventuellement une database. + \param type Type de base de donnees (mysql ou pgsql) + \param host Addresse de la base de donnees + \param user Nom de l'utilisateur autorise \param pass Mot de passe \param name Nom de la database \param port Port of database server @@ -349,7 +349,7 @@ class DoliDb } /** - \brief Effectue une requete et renvoi le resultset de r�ponse de la base + \brief Effectue une requete et renvoi le resultset de reponse de la base \param query Contenu de la query \return resource Resultset de la reponse */ @@ -449,7 +449,7 @@ class DoliDb function affected_rows($resultset=0) { - // Si le resultset n'est pas fourni, on prend le dernier utilis� sur cette connexion + // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion if (! is_object($resultset)) { $resultset=$this->results; } // mysql necessite un link de base pour cette fonction contrairement // a pqsql qui prend un resultset @@ -458,22 +458,22 @@ class DoliDb /** - \brief Lib�re le dernier resultset utilis� sur cette connexion. + \brief Libere le dernier resultset utilise sur cette connexion. \param resultset Curseur de la requete voulue */ function free($resultset=0) { - // Si le resultset n'est pas fourni, on prend le dernier utilis� sur cette connexion + // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion if (! is_object($resultset)) { $resultset=$this->results; } - // Si resultset en est un, on libere la m�moire + // Si resultset en est un, on libere la memoire if (is_object($resultset)) mysqli_free_result($resultset); } /** - \brief D�fini les limites de la requ�te. - \param limit nombre maximum de lignes retourn�es - \param offset num�ro de la ligne � partir de laquelle recup�rer les ligne + \brief Defini les limites de la requete. + \param limit nombre maximum de lignes retournees + \param offset numero de la ligne a partir de laquelle recuperer les ligne \return string chaine exprimant la syntax sql de la limite */ function plimit($limit=0,$offset=0) @@ -486,7 +486,7 @@ class DoliDb /** - \brief D�fini le tri de la requ�te. + \brief Defini le tri de la requete. \param sortfield liste des champ de tri \param sortorder ordre du tri \return string chaine exprimant la syntax sql de l'ordre de tri @@ -704,8 +704,8 @@ class DoliDb } /** - \brief R�cup�re l'id gen�r� par le dernier INSERT. - \param tab Nom de la table concern�e par l'insert. Ne sert pas sous MySql mais requis pour compatibilit� avec Postgresql + \brief Recupere l'id genere par le dernier INSERT. + \param tab Nom de la table concernee par l'insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql \return int id */ function last_insert_id($tab) @@ -717,8 +717,57 @@ class DoliDb // Next function are not required. Only minor features use them. //-------------------------------------------------------------- + + /** + * \brief Encrypt sensitive data in database + * \param field Field name to encrypt + * \param cryptType Type of encryption (2: AES (recommended), 1: DES , 0: no encryption) + * \param cryptKey Encryption key + * \return return Field to encrypt if used + */ + function encrypt($field, $cryptType=0, $cryptKey='') + { + $return = $field; + + if ($cryptType && !empty($cryptKey)) + { + if ($cryptType == 2) + { + $return = 'AES_ENCRYPT('.$field.',\''.$cryptKey.'\')'; + } + else if ($cryptType == 1) + { + $return = 'DES_ENCRYPT('.$field.',\''.$cryptKey.'\')'; + } + } - + return $return; + } + /** + * \brief Decrypt sensitive data in database + * \param field Field name to decrypt + * \param cryptType Type of encryption (2: AES (recommended), 1: DES , 0: no encryption) + * \param cryptKey Encryption key + * \return return Field to decrypt if used + */ + function decrypt($field, $cryptType=0, $cryptKey='') + { + $return = $field; + + if ($cryptType && !empty($cryptKey)) + { + if ($cryptType == 2) + { + $return = 'AES_DECRYPT('.$field.',\''.$cryptKey.'\')'; + } + else if ($cryptType == 1) + { + $return = 'DES_DECRYPT('.$field.',\''.$cryptKey.'\')'; + } + } + + return $return; + } /** \brief Renvoie l'id de la connexion @@ -765,7 +814,7 @@ class DoliDb /** \brief Liste des tables dans une database. \param database Nom de la database - \param table Filtre sur tables � rechercher + \param table Filtre sur tables a rechercher \return array Tableau des tables de la base */ function DDLListTables($database, $table='') @@ -785,19 +834,19 @@ class DoliDb } /** - \brief Cr�e une table + \brief Cree une table \param table Nom de la table \param fields Tableau associatif [nom champ][tableau des descriptions] \param primary_key Nom du champ qui sera la clef primaire \param unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur - \param fulltext Tableau des Nom de champs qui seront index�s en fulltext - \param key Tableau des champs cl�s noms => valeur + \param fulltext Tableau des Nom de champs qui seront indexes en fulltext + \param key Tableau des champs cles noms => valeur \param type Type de la table \return int <0 si KO, >=0 si OK */ function DDLCreateTable($table,$fields,$primary_key,$type,$unique_keys="",$fulltext_keys="",$keys="") { - // cl�s recherch�es dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra + // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); $sql = "create table ".$table."("; $i=0; @@ -861,7 +910,7 @@ class DoliDb } /** - \brief d�crit une table dans une database. + \brief decrit une table dans une database. \param table Nom de la table \param field Optionnel : Nom du champ si l'on veut la desc d'un champ \return resource @@ -879,13 +928,13 @@ class DoliDb * \brief Insert a new field in table * \param table Nom de la table * \param field_name Nom du champ a inserer - * \param field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du param�tre] + * \param field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du parametre] * \param field_position Optionnel ex.: "after champtruc" * \return int <0 si KO, >0 si OK */ function DDLAddField($table,$field_name,$field_desc,$field_position="") { - // cl�s recherch�es dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra + // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); $sql= "ALTER TABLE ".$table." ADD ".$field_name." "; $sql .= $field_desc['type']; @@ -934,8 +983,8 @@ class DoliDb /** \brief Create a user \param dolibarr_main_db_host Ip serveur - \param dolibarr_main_db_user Nom user � cr�er - \param dolibarr_main_db_pass Mot de passe user � cr�er + \param dolibarr_main_db_user Nom user a creer + \param dolibarr_main_db_pass Mot de passe user a creer \param dolibarr_main_db_name Database name where user must be granted \return int <0 si KO, >=0 si OK */ diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index d63d1cd4379..d3020df6082 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -129,6 +129,10 @@ if (empty($dolibarr_main_db_prefix)) $dolibarr_main_db_prefix='llx_'; $conf->db->prefix = $dolibarr_main_db_prefix; if (empty($dolibarr_main_db_collation)) $dolibarr_main_db_collation='latin1_swedish_ci'; $conf->db->dolibarr_main_db_collation=$dolibarr_main_db_collation; +if (empty($dolibarr_main_db_encryption)) $dolibarr_main_db_encryption=0; +$conf->db->dolibarr_main_db_encryption = $dolibarr_main_db_encryption; +if (empty($dolibarr_main_db_cryptkey)) $dolibarr_main_db_cryptkey=''; // TODO la cle devra ne doit pas etre stockee sur le serveur +$conf->db->dolibarr_main_db_cryptkey = $dolibarr_main_db_cryptkey; // Identifiant autres $conf->file->main_authentication = empty($dolibarr_main_authentication)?'':$dolibarr_main_authentication; // Force https