diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index 7839cf14efc..d54b5771514 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -113,15 +113,15 @@ class DolibarrApiAccess implements iAuthenticate $sql = "SELECT u.login, u.datec, u.api_key, "; $sql .= " u.tms as date_modification, u.entity"; $sql .= " FROM ".MAIN_DB_PREFIX."user as u"; - $sql .= " WHERE u.api_key = '".$this->db->escape($api_key)."'"; - // TODO Check if 2 users has same API key. + $sql .= " WHERE u.api_key = '".$this->db->escape($api_key)."' OR u.api_key = '".$this->db->escape(dolEncrypt($api_key, '', '', 'dolibarr'))."'"; $result = $this->db->query($sql); if ($result) { - if ($this->db->num_rows($result)) { + $nbrows = $this->db->num_rows($result); + if ($nbrows == 1) { $obj = $this->db->fetch_object($result); $login = $obj->login; - $stored_key = $obj->api_key; + $stored_key = dolDecrypt($obj->api_key); $userentity = $obj->entity; if (!defined("DOLENTITY") && $conf->entity != ($obj->entity ? $obj->entity : 1)) { // If API was not forced with HTTP_DOLENTITY, and user is on another entity, so we reset entity to entity of user @@ -130,6 +130,8 @@ class DolibarrApiAccess implements iAuthenticate dol_syslog("Entity was not set on http header with HTTP_DOLAPIENTITY (recommanded for performance purpose), so we switch now on entity of user (".$conf->entity.") and we have to reload configuration.", LOG_WARNING); $conf->setValues($this->db); } + } elseif ($nbrows > 1) { + throw new RestException(503, 'Error when fetching user api_key : More than 1 user with this apikey'); } } else { throw new RestException(503, 'Error when fetching user api_key :'.$this->db->error_msg); diff --git a/htdocs/api/class/api_login.class.php b/htdocs/api/class/api_login.class.php index d5362f4ac56..bf4f7ffd318 100644 --- a/htdocs/api/class/api_login.class.php +++ b/htdocs/api/class/api_login.class.php @@ -18,6 +18,7 @@ use Luracast\Restler\RestException; +require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; /** @@ -149,7 +150,7 @@ class Login // We store API token into database $sql = "UPDATE ".MAIN_DB_PREFIX."user"; - $sql .= " SET api_key = '".$this->db->escape($token)."'"; + $sql .= " SET api_key = '".$this->db->escape(dolEncrypt($token, '', '', 'dolibarr'))."'"; $sql .= " WHERE login = '".$this->db->escape($login)."'"; dol_syslog(get_class($this)."::login", LOG_DEBUG); // No log diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 5a610090be2..7ee9f7ce9b5 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -113,10 +113,11 @@ function dolGetRandomBytes($length) * @param string $chain string to encode * @param string $key If '', we use $dolibarr_main_instance_unique_id * @param string $ciphering Default ciphering algorithm + * @param string $forceseed To force the seed * @return string encoded string * @see dolDecrypt(), dol_hash() */ -function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR") +function dolEncrypt($chain, $key = '', $ciphering = 'AES-256-CTR', $forceseed = '') { global $dolibarr_main_instance_unique_id; global $dolibarr_disable_dolcrypt_for_debug; @@ -134,6 +135,9 @@ function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR") if (empty($key)) { $key = $dolibarr_main_instance_unique_id; } + if (empty($ciphering)) { + $ciphering = 'AES-256-CTR'; + } $newchain = $chain; @@ -145,7 +149,11 @@ function dolEncrypt($chain, $key = '', $ciphering = "AES-256-CTR") if ($ivlen === false || $ivlen < 1 || $ivlen > 32) { $ivlen = 16; } - $ivseed = dolGetRandomBytes($ivlen); + if (empty($forceseed)) { + $ivseed = dolGetRandomBytes($ivlen); + } else { + $ivseed = dol_trunc(md5($forceseed), $ivlen, 'right', 'UTF-8', 1); + } $newchain = openssl_encrypt($chain, $ciphering, $key, 0, $ivseed); return 'dolcrypt:'.$ciphering.':'.$ivseed.':'.$newchain; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 46b4b12a25e..5bea5b9f754 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -35,9 +35,11 @@ * \ingroup core */ +require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; + /** * Class to manage Dolibarr users */ @@ -526,7 +528,7 @@ class User extends CommonObject $this->pass_indatabase_crypted = $obj->pass_crypted; $this->pass = $obj->pass; $this->pass_temp = $obj->pass_temp; - $this->api_key = $obj->api_key; + $this->api_key = dolDecrypt($obj->api_key); $this->address = $obj->address; $this->zip = $obj->zip; @@ -1977,7 +1979,7 @@ class User extends CommonObject $sql .= ", national_registration_number = '".$this->db->escape($this->national_registration_number)."'"; $sql .= ", employee = ".(int) $this->employee; $sql .= ", login = '".$this->db->escape($this->login)."'"; - $sql .= ", api_key = ".($this->api_key ? "'".$this->db->escape($this->api_key)."'" : "null"); + $sql .= ", api_key = ".($this->api_key ? "'".$this->db->escape(dolEncrypt($this->api_key, '', '', 'dolibarr'))."'" : "null"); $sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman' $sql .= ", birth=".(strval($this->birth) != '' ? "'".$this->db->idate($this->birth, 'tzserver')."'" : 'null'); if (!empty($user->admin)) { diff --git a/htdocs/user/list.php b/htdocs/user/list.php index a269a93fb7b..19022cceccf 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -1127,10 +1127,13 @@ while ($i < $imaxinloop) { } } if (!empty($arrayfields['u.api_key']['checked'])) { - print '