Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8396f7856b | ||
|
|
b18866077e | ||
|
|
a66cc09095 | ||
|
|
1cfdc45107 | ||
|
|
07e46c91ab | ||
|
|
8aee448c59 |
@@ -12,6 +12,8 @@ Not yet covered tests:
|
||||
- loginGetLocale
|
||||
- loginGetHeaderColor
|
||||
- loginGetPages
|
||||
- loginGetPageLookupList
|
||||
- loginPageAccessAllowed
|
||||
- loginGetEuid
|
||||
*/
|
||||
|
||||
|
||||
@@ -5009,8 +5009,8 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
)
|
||||
),
|
||||
($params === null ?
|
||||
$db->dbGetQueryHash($query) :
|
||||
$db->dbGetQueryHash($query, $params)
|
||||
$db->dbBuildQueryHash($query) :
|
||||
$db->dbBuildQueryHash($query, $params)
|
||||
),
|
||||
'Failed assertdbGetQueryHash '
|
||||
);
|
||||
|
||||
@@ -15,6 +15,8 @@ ob_start();
|
||||
define('USE_DATABASE', true);
|
||||
// sample config
|
||||
require 'config.php';
|
||||
// for testing encryption compare
|
||||
use OpenPGP\OpenPGP;
|
||||
// define log file id
|
||||
$LOG_FILE_ID = 'classTest-db-query-encryption';
|
||||
ob_end_flush();
|
||||
@@ -42,11 +44,15 @@ print '<div><a href="class_test.php">Class Test Master</a></div>';
|
||||
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
|
||||
|
||||
// encryption key
|
||||
$key = CreateKey::generateRandomKey();
|
||||
$key_new = CreateKey::generateRandomKey();
|
||||
print "Secret Key NEW: " . $key_new . "<br>";
|
||||
// for reproducable test results
|
||||
$key = 'e475c19b9a3c8363feb06b51f5b73f1dc9b6f20757d4ab89509bf5cc70ed30ec';
|
||||
print "Secret Key: " . $key . "<br>";
|
||||
|
||||
// test text
|
||||
$text_string = "I a some deep secret";
|
||||
$text_string = "I a some deep secret ABC";
|
||||
//
|
||||
$crypt = new SymmetricEncryption($key);
|
||||
$encrypted = $crypt->encrypt($text_string);
|
||||
@@ -105,20 +111,55 @@ $res = $db->dbReturnRowParams(
|
||||
-- in DB encryption
|
||||
pg_digest_bytea, pg_digest_text,
|
||||
pg_hmac_bytea, pg_hmac_text,
|
||||
pg_crypt_bytea, pg_crypt_text
|
||||
pg_crypt_bytea, pg_crypt_text,
|
||||
encode(pg_crypt_bytea, 'hex') AS pg_crypt_bytea_hex,
|
||||
pgp_sym_decrypt(pg_crypt_bytea, $2) AS from_pg_crypt_bytea,
|
||||
pgp_sym_decrypt(decode(pg_crypt_text, 'hex'), $2) AS from_pg_crypt_text
|
||||
FROM
|
||||
test_encryption
|
||||
WHERE
|
||||
cuuid = $1
|
||||
SQL,
|
||||
[
|
||||
$cuuid
|
||||
$cuuid, $key
|
||||
]
|
||||
);
|
||||
|
||||
print "RES: <pre>" . Support::prAr($res) . "</pre><br>";
|
||||
|
||||
// do compare
|
||||
if ($res === false) {
|
||||
echo "Failed to run query<br>";
|
||||
} else {
|
||||
if (hash_equals($string_hashed, $res['pg_digest_text'])) {
|
||||
print "libsodium and pgcrypto hash match<br>";
|
||||
}
|
||||
if (hash_equals($string_hmac, $res['pg_hmac_text'])) {
|
||||
print "libsodium and pgcrypto hash hmac match<br>";
|
||||
}
|
||||
// do compare for PHP and pgcrypto settings
|
||||
$encryptedMessage_template = <<<TEXT
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
{BASE64}
|
||||
-----END PGP MESSAGE-----
|
||||
TEXT;
|
||||
$base64_string = base64_encode(hex2bin($res['pg_crypt_text']) ?: '');
|
||||
$encryptedMessage = str_replace(
|
||||
'{BASE64}',
|
||||
$base64_string,
|
||||
$encryptedMessage_template
|
||||
);
|
||||
try {
|
||||
$literalMessage = OpenPGP::decryptMessage($encryptedMessage, passwords: [$key]);
|
||||
$decrypted = $literalMessage->getLiteralData()->getData();
|
||||
print "Pg decrypted PHP: " . $decrypted . "<br>";
|
||||
if ($decrypted == $text_string) {
|
||||
print "Decryption worked<br>";
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
print "Error decrypting message: " . $e->getMessage() . "<br>";
|
||||
}
|
||||
}
|
||||
|
||||
print "</body></html>";
|
||||
|
||||
|
||||
@@ -127,6 +127,12 @@ if (isset($login->loginGetAcl()['unit'])) {
|
||||
// IP check: 'REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'CLIENT_IP' in _SERVER
|
||||
// Agent check: 'HTTP_USER_AGENT'
|
||||
|
||||
print "<hr>";
|
||||
print "PAGE lookup:<br>";
|
||||
$file_name = 'test_edit_base.php';
|
||||
print "Access to '$file_name': " . $log->prAr($login->loginPageAccessAllowed($file_name)) . "<br>";
|
||||
$file_name = 'i_do_not_exists.php';
|
||||
print "Access to '$file_name': " . $log->prAr($login->loginPageAccessAllowed($file_name)) . "<br>";
|
||||
|
||||
echo "<hr>";
|
||||
print "SESSION: " . Support::printAr($_SESSION) . "<br>";
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"egrajp/smarty-extended": "^5.4",
|
||||
"php": ">=8.1",
|
||||
"gullevek/dotenv": "^2.0",
|
||||
"psr/log": "^2.0 || ^3.0"
|
||||
"psr/log": "^2.0 || ^3.0",
|
||||
"php-privacy/openpgp": "^2.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,7 +924,9 @@ class Login
|
||||
$mandatory_session_vars = [
|
||||
'LOGIN_USER_NAME', 'LOGIN_GROUP_NAME', 'LOGIN_EUCUID', 'LOGIN_EUCUUID',
|
||||
'LOGIN_USER_ADDITIONAL_ACL', 'LOGIN_GROUP_ADDITIONAL_ACL',
|
||||
'LOGIN_ADMIN', 'LOGIN_GROUP_ACL_LEVEL', 'LOGIN_PAGES_ACL_LEVEL', 'LOGIN_USER_ACL_LEVEL',
|
||||
'LOGIN_ADMIN', 'LOGIN_GROUP_ACL_LEVEL',
|
||||
'LOGIN_PAGES', 'LOGIN_PAGES_LOOKUP', 'LOGIN_PAGES_ACL_LEVEL',
|
||||
'LOGIN_USER_ACL_LEVEL',
|
||||
'LOGIN_UNIT', 'LOGIN_UNIT_DEFAULT_EACUID'
|
||||
];
|
||||
$force_reauth = false;
|
||||
@@ -1264,6 +1266,7 @@ class Login
|
||||
}
|
||||
$edit_page_ids = [];
|
||||
$pages = [];
|
||||
$pages_lookup = [];
|
||||
$pages_acl = [];
|
||||
// set pages access
|
||||
$q = <<<SQL
|
||||
@@ -1307,6 +1310,7 @@ class Login
|
||||
'query' => [],
|
||||
'visible' => []
|
||||
];
|
||||
$pages_lookup[$res['filename']] = $res['cuid'];
|
||||
// make reference filename -> level
|
||||
$pages_acl[$res['filename']] = $res['level'];
|
||||
} // for each page
|
||||
@@ -1367,6 +1371,7 @@ class Login
|
||||
// write back the pages data to the output array
|
||||
$this->session->setMany([
|
||||
'LOGIN_PAGES' => $pages,
|
||||
'LOGIN_PAGES_LOOKUP' => $pages_lookup,
|
||||
'LOGIN_PAGES_ACL_LEVEL' => $pages_acl,
|
||||
]);
|
||||
// load the edit_access user rights
|
||||
@@ -1526,6 +1531,8 @@ class Login
|
||||
) {
|
||||
$this->acl['page'] = $_SESSION['LOGIN_PAGES_ACL_LEVEL'][$this->page_name];
|
||||
}
|
||||
$this->acl['pages_detail'] = $_SESSION['LOGIN_PAGES'];
|
||||
$this->acl['pages_lookup_cuid'] = $_SESSION['LOGIN_PAGES_LOOKUP'];
|
||||
|
||||
$this->acl['unit_cuid'] = null;
|
||||
$this->acl['unit_name'] = null;
|
||||
@@ -2728,6 +2735,31 @@ HTML;
|
||||
return $this->session->get('LOGIN_PAGES');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current loaded list of pages the user can access
|
||||
*
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public function loginGetPageLookupList(): array
|
||||
{
|
||||
return $this->session->get('LOGIN_PAGES_LOOKUP');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access to a file in the pages list
|
||||
*
|
||||
* @param string $filename File name to check
|
||||
* @return bool True if page in list and anything other than None access, False if failed
|
||||
*/
|
||||
public function loginPageAccessAllowed(string $filename): bool
|
||||
{
|
||||
return (
|
||||
$this->session->get('LOGIN_PAGES')[
|
||||
$this->session->get('LOGIN_PAGES_LOOKUP')[$filename] ?? ''
|
||||
] ?? 0
|
||||
) != 0 ? true : false;
|
||||
}
|
||||
|
||||
// MARK: logged in uid(pk)/eucuid/eucuuid
|
||||
|
||||
/**
|
||||
|
||||
@@ -303,6 +303,8 @@ class IO
|
||||
private string $query = '';
|
||||
/** @var array<mixed> current params for query */
|
||||
private array $params = [];
|
||||
/** @var string current hash build from query and params */
|
||||
private string $query_hash = '';
|
||||
// if we do have a convert call, store the convert data in here, else it will be empty
|
||||
/** @var array{}|array{original:array{query:string,params:array<mixed>},type:''|'named'|'numbered'|'question_mark',found:int,matches:array<string>,params_lookup:array<mixed>,query:string,params:array<mixed>} */
|
||||
private array $placeholder_converted = [];
|
||||
@@ -1319,7 +1321,7 @@ class IO
|
||||
*/
|
||||
private function __dbCountQueryParams(string $query): int
|
||||
{
|
||||
return $this->db_functions->__dbCountQueryParams($query);
|
||||
return count($this->db_functions->__dbGetQueryParams($query));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1382,6 +1384,8 @@ class IO
|
||||
$this->query = $query;
|
||||
// current params
|
||||
$this->params = $params;
|
||||
// empty on new
|
||||
$this->query_hash = '';
|
||||
// no query set
|
||||
if (empty($this->query)) {
|
||||
$this->__dbError(11);
|
||||
@@ -1441,7 +1445,7 @@ class IO
|
||||
$this->returning_id = true;
|
||||
}
|
||||
// import protection, hash needed
|
||||
$query_hash = $this->dbGetQueryHash($this->query, $this->params);
|
||||
$query_hash = $this->dbBuildQueryHash($this->query, $this->params);
|
||||
// QUERY PARAMS: run query params check and rewrite
|
||||
if ($this->dbGetConvertPlaceholder() === true) {
|
||||
try {
|
||||
@@ -1475,7 +1479,8 @@ class IO
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// set query hash
|
||||
$this->query_hash = $query_hash;
|
||||
// $this->debug('DB IO', 'Q: ' . $this->query . ', RETURN: ' . $this->returning_id);
|
||||
// for DEBUG, only on first time ;)
|
||||
$this->__dbDebug(
|
||||
@@ -1959,7 +1964,7 @@ class IO
|
||||
{
|
||||
// set start array
|
||||
if ($query) {
|
||||
$array = $this->cursor_ext[$this->dbGetQueryHash($query)] ?? [];
|
||||
$array = $this->cursor_ext[$this->dbBuildQueryHash($query)] ?? [];
|
||||
} else {
|
||||
$array = $this->cursor_ext;
|
||||
}
|
||||
@@ -2361,7 +2366,7 @@ class IO
|
||||
return false;
|
||||
}
|
||||
// create hash from query ...
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
$query_hash = $this->dbBuildQueryHash($query, $params);
|
||||
// pre declare array
|
||||
if (!isset($this->cursor_ext[$query_hash])) {
|
||||
$this->cursor_ext[$query_hash] = [
|
||||
@@ -2940,7 +2945,7 @@ class IO
|
||||
public function dbCacheReset(string $query, array $params = []): bool
|
||||
{
|
||||
$this->__dbErrorReset();
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
$query_hash = $this->dbBuildQueryHash($query, $params);
|
||||
// clears cache for this query
|
||||
if (empty($this->cursor_ext[$query_hash]['query'])) {
|
||||
$this->__dbWarning(18, context: [
|
||||
@@ -2982,7 +2987,7 @@ class IO
|
||||
if ($query === null) {
|
||||
return $this->cursor_ext;
|
||||
}
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
$query_hash = $this->dbBuildQueryHash($query, $params);
|
||||
if (
|
||||
!empty($this->cursor_ext) &&
|
||||
isset($this->cursor_ext[$query_hash])
|
||||
@@ -3012,7 +3017,7 @@ class IO
|
||||
$this->__dbError(11);
|
||||
return false;
|
||||
}
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
$query_hash = $this->dbBuildQueryHash($query, $params);
|
||||
if (
|
||||
!empty($this->cursor_ext) &&
|
||||
isset($this->cursor_ext[$query_hash])
|
||||
@@ -3038,7 +3043,7 @@ class IO
|
||||
$this->__dbError(11);
|
||||
return false;
|
||||
}
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
$query_hash = $this->dbBuildQueryHash($query, $params);
|
||||
if (
|
||||
!empty($this->cursor_ext) &&
|
||||
isset($this->cursor_ext[$query_hash])
|
||||
@@ -3064,7 +3069,7 @@ class IO
|
||||
*/
|
||||
public function dbResetQueryCalled(string $query, array $params = []): void
|
||||
{
|
||||
$this->query_called[$this->dbGetQueryHash($query, $params)] = 0;
|
||||
$this->query_called[$this->dbBuildQueryHash($query, $params)] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3077,7 +3082,7 @@ class IO
|
||||
*/
|
||||
public function dbGetQueryCalled(string $query, array $params = []): int
|
||||
{
|
||||
$query_hash = $this->dbGetQueryHash($query, $params);
|
||||
$query_hash = $this->dbBuildQueryHash($query, $params);
|
||||
if (!empty($this->query_called[$query_hash])) {
|
||||
return $this->query_called[$query_hash];
|
||||
} else {
|
||||
@@ -4046,7 +4051,7 @@ class IO
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hash for query
|
||||
* Creates hash for query and parameters
|
||||
* Hash is used in all internal storage systems for return data
|
||||
*
|
||||
* @param string $query The query to create the hash from
|
||||
@@ -4054,7 +4059,7 @@ class IO
|
||||
* data to create a unique call one, optional
|
||||
* @return string Hash, as set by hash long
|
||||
*/
|
||||
public function dbGetQueryHash(string $query, array $params = []): string
|
||||
public function dbBuildQueryHash(string $query, array $params = []): string
|
||||
{
|
||||
return Hash::hashLong(
|
||||
$query . (
|
||||
@@ -4104,6 +4109,26 @@ class IO
|
||||
$this->params = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current set query hash
|
||||
*
|
||||
* @return string Current Query hash
|
||||
*/
|
||||
public function dbGetQueryHash(): string
|
||||
{
|
||||
return $this->query_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* reset query hash
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dbResetQueryHash(): void
|
||||
{
|
||||
$this->query_hash = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the placeholder convert set or empty
|
||||
*
|
||||
|
||||
@@ -379,9 +379,9 @@ interface SqlFunctions
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string $query
|
||||
* @return int
|
||||
* @return array<string>
|
||||
*/
|
||||
public function __dbCountQueryParams(string $query): int;
|
||||
public function __dbGetQueryParams(string $query): array;
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -978,7 +978,7 @@ class PgSQL implements Interface\SqlFunctions
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the all the $ params, unique list
|
||||
* Get the all the $ params, as a unique list
|
||||
*
|
||||
* @param string $query
|
||||
* @return array<string>
|
||||
@@ -1004,17 +1004,6 @@ class PgSQL implements Interface\SqlFunctions
|
||||
);
|
||||
return array_unique(array_filter($matches[ConvertPlaceholder::MATCHING_POS]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Count placeholder queries. $ only
|
||||
*
|
||||
* @param string $query
|
||||
* @return int
|
||||
*/
|
||||
public function __dbCountQueryParams(string $query): int
|
||||
{
|
||||
return count($this->__dbGetQueryParams($query));
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -1371,7 +1371,7 @@ class Generate
|
||||
) {
|
||||
$this->msg .= sprintf(
|
||||
$this->l->__('Please enter a valid (%s) input for the <b>%s</b> Field!<br>'),
|
||||
$this->dba->getTableArray()[$key]['error_example'],
|
||||
$this->dba->getTableArray()[$key]['error_example'] ?? '[MISSING]',
|
||||
$this->dba->getTableArray()[$key]['output_name']
|
||||
);
|
||||
}
|
||||
@@ -2602,7 +2602,7 @@ class Generate
|
||||
}
|
||||
}
|
||||
// add lost error ones
|
||||
$this->log->error('P: ' . $data['prefix'] . ', '
|
||||
$this->log->error('Prefix: ' . $data['prefix'] . ', '
|
||||
. Support::prAr($_POST['ERROR'][$data['prefix']] ?? []));
|
||||
if ($this->error && !empty($_POST['ERROR'][$data['prefix']])) {
|
||||
$prfx = $data['prefix']; // short
|
||||
|
||||
@@ -50,7 +50,8 @@ class EditUsers implements Interface\TableArraysInterface
|
||||
'HIDDEN_value' => $_POST['HIDDEN_password'] ?? '',
|
||||
'CONFIRM_value' => $_POST['CONFIRM_password'] ?? '',
|
||||
'output_name' => 'Password',
|
||||
'mandatory' => 1,
|
||||
// make it not mandatory to create dummy accounts that can only login via login url id
|
||||
'mandatory' => 0,
|
||||
'type' => 'password', // later has to be password for encryption in database
|
||||
'update' => [ // connected field updates, and update data
|
||||
'password_change_date' => [ // db row to update
|
||||
@@ -182,6 +183,7 @@ class EditUsers implements Interface\TableArraysInterface
|
||||
'type' => 'text',
|
||||
'error_check' => 'unique|custom',
|
||||
'error_regex' => "/^[A-Za-z0-9]+$/",
|
||||
'error_example' => "ABCdef123",
|
||||
'emptynull' => 1,'min_edit_acl' => '100',
|
||||
'min_show_acl' => '100',
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user