Fix encryption of api_key

This commit is contained in:
Laurent Destailleur 2023-03-13 12:48:25 +01:00
parent 80678cfcb9
commit d369a640de
5 changed files with 28 additions and 12 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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)) {

View File

@ -1127,10 +1127,13 @@ while ($i < $imaxinloop) {
}
}
if (!empty($arrayfields['u.api_key']['checked'])) {
print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($obj->api_key).'">';
if ($obj->api_key) {
$api_key = dolDecrypt($obj->api_key);
print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($api_key).'">';
if ($api_key) {
if ($canreadsecretapi) {
print dol_escape_htmltag($obj->api_key);
print '<span class="opacitymedium">';
print showValueWithClipboardCPButton($object->api_key, 1, dol_trunc($api_key, 3)); // TODO Add an option to also reveal the hash, not only copy paste
print '</span>';
} else {
print '<span class="opacitymedium">'.$langs->trans("Hidden").'</span>';
}