mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-27 07:00:29 +01:00
206 lines
6.2 KiB
PHP
206 lines
6.2 KiB
PHP
|
<?php
|
||
|
/*
|
||
|
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
|
||
|
*
|
||
|
* Xentral (c) Xentral ERP Sorftware GmbH, Fuggerstrasse 11, D-86150 Augsburg, * Germany 2019
|
||
|
*
|
||
|
* This file is licensed under the Embedded Projects General Public License *Version 3.1.
|
||
|
*
|
||
|
* You should have received a copy of this license from your vendor and/or *along with this file; If not, please visit www.wawision.de/Lizenzhinweis
|
||
|
* to obtain the text of the corresponding license version.
|
||
|
*
|
||
|
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
|
||
|
*/
|
||
|
?>
|
||
|
<?php
|
||
|
// Nur einfache Fehler melden
|
||
|
error_reporting(E_ERROR | E_WARNING | E_PARSE);
|
||
|
|
||
|
include dirname(dirname(__DIR__)) . '/conf/main.conf.php';
|
||
|
include dirname(dirname(__DIR__)) . '/phpwf/plugins/class.mysql.php';
|
||
|
include '../lib/libextern.php';
|
||
|
|
||
|
|
||
|
$config = new Config();
|
||
|
$db = new DB($config->WFdbhost, $config->WFdbname, $config->WFdbuser, $config->WFdbpass,null,$conf->WFdbport);
|
||
|
//$erp = new erpAPI($app);
|
||
|
//$app->erp = $erp;
|
||
|
|
||
|
header('Access-Control-Allow-Origin: *');
|
||
|
$cmd = !empty($_GET['cmd']) ? $_GET['cmd'] : '';
|
||
|
$shouldLog = !empty($db->Select("SELECT `wert` FROM `konfiguration` WHERE `name` = 'adapterbox_logging_active' LIMIT 1"));
|
||
|
$deviceId = !empty($_GET['device']) ? $_GET['device'] : null;
|
||
|
$passwordHash = $_GET['auth'];
|
||
|
$realm = 'DeviceID';
|
||
|
$nonce = uniqid();
|
||
|
$ip = !empty($_SERVER['REMOTE_ADDR']) ? $db->real_escape_string($_SERVER['REMOTE_ADDR']) : '';
|
||
|
$validPass = $db->Select("SELECT `devicekey` FROM `firmendaten` WHERE `devicekey` != '' LIMIT 1");
|
||
|
if ($validPass === '') {
|
||
|
$validPass = rand() . '' . mt_rand();
|
||
|
}
|
||
|
$guard = new AuthenticationGuard($db, $validPass);
|
||
|
$digest = (string)getDigest();
|
||
|
try {
|
||
|
$authenticatedDeviceId = $guard->login($passwordHash, $deviceId, $realm, $digest);
|
||
|
} catch (Exception $e) {
|
||
|
if ($shouldLog) {
|
||
|
$db->Insert(
|
||
|
sprintf("
|
||
|
INSERT INTO `adapterbox_request_log` (`device`, `auth`, `success`, `created_at`, `validpass`, `ip`)
|
||
|
VALUES ('%s','%s', 0, NOW(),'%s','%s')",
|
||
|
$db->real_escape_string($deviceId),
|
||
|
$db->real_escape_string($passwordHash),
|
||
|
$db->real_escape_string($validPass),
|
||
|
$ip
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
requireLogin($realm, $nonce);
|
||
|
}
|
||
|
|
||
|
include 'statemachine.php';
|
||
|
RunStateMachine($db, $authenticatedDeviceId);
|
||
|
|
||
|
|
||
|
class AuthenticationGuard
|
||
|
{
|
||
|
/** @var DB */
|
||
|
private $db;
|
||
|
|
||
|
/** @var string */
|
||
|
private $key;
|
||
|
|
||
|
public function __construct(DB $db, string $key)
|
||
|
{
|
||
|
$this->db = $db;
|
||
|
$this->key = $key;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $passwordHash
|
||
|
* @param string|null $deviceId
|
||
|
* @param string $realm
|
||
|
* @param string $digest
|
||
|
*
|
||
|
* @return string
|
||
|
*
|
||
|
* @throws Exception
|
||
|
*/
|
||
|
public function login(
|
||
|
string $passwordHash,
|
||
|
?string $deviceId = null,
|
||
|
string $realm = '',
|
||
|
string $digest = ''
|
||
|
): string
|
||
|
{
|
||
|
// sometimes 000000000 is getting sent instead of the real device serial along while the original hash from the real serial
|
||
|
// thus, calculating the hash for 000.. will yield a different hash than the sent device hash
|
||
|
if (!$deviceId || $deviceId == '000000000') {
|
||
|
$deviceId = $this->loginWithoutDeviceId($passwordHash, $realm, $digest);
|
||
|
} else {
|
||
|
$hash = $this->generateHash($this->key, $deviceId);
|
||
|
|
||
|
if ($hash !== $passwordHash) {
|
||
|
throw new Exception('Wrong hash');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $deviceId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @var string $passwordHash
|
||
|
* @var string $realm
|
||
|
* @var string $digest
|
||
|
*
|
||
|
* @return string
|
||
|
* @throws Exception
|
||
|
*/
|
||
|
private function loginWithoutDeviceId(string $passwordHash, string $realm, string $digest): string
|
||
|
{
|
||
|
$devices = $this->getValidDevices();
|
||
|
foreach($devices as $deviceId) {
|
||
|
if ($passwordHash === $this->generateHash($this->key, $deviceId)) {
|
||
|
return $deviceId;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$deviceId = $this->loginWithDigest($devices, $realm, $digest);
|
||
|
if($deviceId === null) {
|
||
|
throw new Exception('Hash not valid for any device');
|
||
|
}
|
||
|
|
||
|
return $deviceId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $devices
|
||
|
* @param string $realm
|
||
|
* @param string $digest
|
||
|
*
|
||
|
* @return string|null
|
||
|
*/
|
||
|
private function loginWithDigest(array $devices, string $realm, string $digest): ?string
|
||
|
{
|
||
|
if ($digest === '') {
|
||
|
return null;
|
||
|
}
|
||
|
$digestParts = digestParse($digest);
|
||
|
if ($digestParts === false) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
foreach($devices as $deviceId) {
|
||
|
$validUser = $deviceId;
|
||
|
// Based on all the info we gathered we can figure out what the response should be
|
||
|
$A1 = md5("{$validUser}:{$realm}:{$this->key}");
|
||
|
$A2 = md5("{$_SERVER['REQUEST_METHOD']}:{$digestParts['uri']}");
|
||
|
|
||
|
$validResponse = md5("{$A1}:{$digestParts['nonce']}:{$digestParts['nc']}:{$digestParts['cnonce']}:{$digestParts['qop']}:{$A2}");
|
||
|
if ($digestParts['response'] === $validResponse) {
|
||
|
return $validUser;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/** @return array */
|
||
|
private function getValidDevices()
|
||
|
{
|
||
|
$validDevices = ['000000000'];
|
||
|
//$validDevices = array('000000000','999999999','123456789');
|
||
|
$printers = $this->db->SelectFirstCols("
|
||
|
SELECT `adapterboxseriennummer`
|
||
|
FROM `drucker`
|
||
|
WHERE `adapterboxseriennummer` != ''
|
||
|
AND `aktiv` = '1'
|
||
|
AND (`anbindung` = 'adapterbox' OR `anbindung` = 'spooler')
|
||
|
");
|
||
|
$adapterBoxes = $this->db->SelectFirstCols("
|
||
|
SELECT `seriennummer` as `adapterboxseriennummer`
|
||
|
FROM `adapterbox`
|
||
|
WHERE `seriennummer` != ''
|
||
|
");
|
||
|
|
||
|
return array_values(array_unique(array_merge($validDevices, $printers, $adapterBoxes)));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $key
|
||
|
* @param string $deviceId
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
private function generateHash($key, $deviceId)
|
||
|
{
|
||
|
$hash = '';
|
||
|
|
||
|
for ($i = 0; $i <= 200; $i++) {
|
||
|
$hash = sha1($hash . $key . $deviceId);
|
||
|
}
|
||
|
|
||
|
return $hash;
|
||
|
}
|
||
|
}
|