From 5a76e66f9c80b0f0378bc250b03da3a3872a8e48 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 17 Jul 2016 10:27:59 +0200 Subject: [PATCH] =?UTF-8?q?Gestion=20du=20'hashChain'=20cyclique=20fonctio?= =?UTF-8?q?nnel=20au=20niveau=20du=20module=20'machineDefault/sync'=20et?= =?UTF-8?q?=20du=20repo=20'machine/getByToken'=20+=20Tests=20des=20donn?= =?UTF-8?q?=C3=A9es=20de=20la=20synchronisation=20et=20r=C3=A9vision=20des?= =?UTF-8?q?=20=C3=A9tapes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/modules.json | 5 +- manager/ModuleRequest.php | 1 - manager/module/machineDefault.php | 28 ++- manager/repo/machine.php | 9 +- test/client/api.manifest.json | 35 ++++ test/client/api.php | 225 ++++++++++++++++++++++ test/client/background.php | 86 +++++++++ test/{client.php => client/interface.php} | 33 +++- test/clientBackground.php | 27 --- test/testHashChain.php | 10 +- 10 files changed, 419 insertions(+), 40 deletions(-) create mode 100644 test/client/api.manifest.json create mode 100644 test/client/api.php create mode 100644 test/client/background.php rename test/{client.php => client/interface.php} (82%) delete mode 100644 test/clientBackground.php diff --git a/config/modules.json b/config/modules.json index d7cc72c..a188c9d 100755 --- a/config/modules.json +++ b/config/modules.json @@ -228,8 +228,9 @@ "description": "Synchronisation d'une machine.", "permissions": ["warehouse"], "parameters": { - "token": { "description": "Code d'accès évolutif dynamique.", "type": "hash" }, - "data": { "description": "Données (dépendent des modules).", "type": "array" } + "token": { "description": "Code d'accès évolutif dynamique.", "type": "hash" }, + "data": { "description": "Données (dépendent des modules).", "type": "array" }, + "renew": { "description": "Nouveau code d'accès.", "type": "hash", "optional": true } }, "output": { "data": { "description": "Données (dépendent des modules).", "type": "array" } diff --git a/manager/ModuleRequest.php b/manager/ModuleRequest.php index baec0d7..7799f67 100755 --- a/manager/ModuleRequest.php +++ b/manager/ModuleRequest.php @@ -33,7 +33,6 @@ * * @path Chemin de delegation ("module/methode") * @param Tableau associatif contenant les parametres utiles au traitement - * @token Token d'acces a l'api (OPTIONNEL) * * @return status Retourne si oui ou non tout s'est bien passe * diff --git a/manager/module/machineDefault.php b/manager/module/machineDefault.php index b0385f1..3004e48 100755 --- a/manager/module/machineDefault.php +++ b/manager/module/machineDefault.php @@ -357,6 +357,7 @@ * * @token Token de synchronisation de la machine * @data Données de la synchronisation + * @renew Renouvellement du token de synchronisation de la machine (opt.) * * @return data Données de retour de synchronisation * @@ -364,10 +365,33 @@ public static function sync($params){ extract($params); - $checkToken = new Repo('machine/checkToken', [ $_SESSION['WAREHOUSE']['id'], $token ]); + /* [0] Vérification du token + =========================================================*/ + $checkToken = new Repo('machine/checkToken', [ $_SESSION['WAREHOUSE']['id'], $token, $renew ]); + + // Si token incorrect, on envoie une erreur + if( $checkToken->answer() !== true ) + return [ 'ModuleError' => ManagerError::TokenError ]; + + + + /* [1] Initialisation des variables + =========================================================*/ + $data = ['a', 'b']; + + + + /* [2] Données à reçues + =========================================================*/ + + + + /* [3] Données à envoyer + =========================================================*/ + return [ - 'tokenResult' => $checkToken->answer() + 'data' => $data ]; diff --git a/manager/repo/machine.php b/manager/repo/machine.php index 61c45fb..4b3d272 100755 --- a/manager/repo/machine.php +++ b/manager/repo/machine.php @@ -3,6 +3,7 @@ namespace manager\repo; use \manager\Database; use \manager\sessionManager; + use \manager\Checker; use \manager\repo\cluster as clusterRepo; class machine extends parentRepo{ @@ -352,12 +353,14 @@ /* VERIFIE MET A JOUR LE TOKEN DE SYNCHRONISATION * - * @token Nouveau token de synchronisation + * @id_warehouse UID de l'entrepot + * @token Token de synchronisation + * @newToken Nouveau token de synchronisation (optionnel, uniquement quand on arrive à la fin du cycle de la hashChain) * * @return status VRAI si le token est correct, sinon FALSE * */ - public static function checkToken($id_warehouse, $token){ + public static function checkToken($id_warehouse, $token, $newToken=null){ /* [1] On vérifie le token =========================================================*/ $hash = sessionManager::secure_hash($token); @@ -375,7 +378,7 @@ SET token = :token WHERE id_machine = :id_machine"); $updateToken->execute([ - ':token' => $token, + ':token' => Checker::run('hash', $newToken) ? $newToken : $token, ':id_machine' => $byToken[0]['id_machine'] ]); diff --git a/test/client/api.manifest.json b/test/client/api.manifest.json new file mode 100644 index 0000000..e5fd34d --- /dev/null +++ b/test/client/api.manifest.json @@ -0,0 +1,35 @@ +{ + "name": "xdrm_api", + "version": "0.1", + "description": "API du serveur de centralisation des accès.", + + "requests": { + + "sync": { + "url": "stefproject/api/machineDefault/sync", + "method": "POST", + "headers": { "Authorization": "Digest @warehouse" }, + "postdata": { + "token": "@token", + "data": "@data" + }, + "description": "Synchronisation des données de la machine avec le serveur." + }, + + "sync-renew": { + "url": "stefproject/api/machineDefault/sync", + "method": "POST", + "headers": { "Authorization": "Digest @warehouse" }, + "postdata": { + "token": "@token", + "data": "@data", + "renew": "@renew" + }, + "description": "Synchronisation des données de la machine avec le serveur. Remise à 0 du token" + } + + } + + + +} diff --git a/test/client/api.php b/test/client/api.php new file mode 100644 index 0000000..a98a3fb --- /dev/null +++ b/test/client/api.php @@ -0,0 +1,225 @@ + Description du retour + * + */ + class api{ + + // Fichier de configuration par defaut + private $config_path = 'api.manifest.json'; + public $error; + + // liste des methodes + public static $METHODS = array( + 'POST' => array( CURLOPT_POST, true ), + 'GET' => array( CURLOPT_HTTPGET, true ), + 'PUT' => array( CURLOPT_CUSTOMREQUEST, 'PUT' ), + 'DELETE' => array( CURLOPT_CUSTOMREQUEST, 'DELETE' ) + ); + + /*************/ + /* ATTRIBUTS */ + /*************/ + private $manifest = null; // Contiendra le tableau correspondant au JSON + private $requests = array(); // Contiendra la liste des requetes de l'api et leurs parametres + + private $name; + private $description; + private $version; + + + /* CONSTRUCTEUR DU CLIENT DE L'API + * + * @config Chemin du fichier de configuration de l'api + * + */ + public function __construct($config=null){ + /* [0] Gestion du fichier de config si donne en param + =========================================================*/ + if( $config !== null ) $this->config_path = $config; + + /* [1] On recupere le contenu du fichier de config + =========================================================*/ + $manifest = json_decode( file_get_contents($this->config_path), true ); + + // Si erreur de parsage ou de fichier, on retourne une erreur + if( $manifest === null ){ + $this->error = ManagerError::ParsingFailed; + return; + } + + + /* [2] On repartie et classe les donnees + =========================================================*/ + /* (1) Informations generales */ + $name = $manifest['name']; + $description = $manifest['description']; + $version = $manifest['version']; + + /* (2) Liste des requetes */ + $this->requests = $manifest['requests']; + } + + + + + + /* ENVOI ET CONSTRUCTION D'UNE REQUETE + * + * @request_name Nom de la requete en question + * @parameters Liste des parametres de la requete + * + * @return response Reponse HTTP au format norme ou FAUX si une erreur occure + * + */ + public function send($request_name, $parameters=array()){ + /* [1] On construit la requete avec les parametres + =========================================================*/ + $build = $this->build($request_name, $parameters); + + // Si la construction a echoue, on retourne une erreur + if( $build === false ) return false; + + + /* [2] Header et pre-data de la requete + =========================================================*/ + /* (1) On definit l'URL */ + $curl = curl_init($build['url']); + + // permet de recupere le resultat au lieu de l'afficher + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + + + /* (2) On definit la methode */ + $method_arguments = self::$METHODS[ $build['method'] ]; + + curl_setopt($curl, $method_arguments[0], $method_arguments[1]); + + + /* (3) On definit les headers */ + $headers = array(); + + // On construit le header au bon format : 'name: value' + foreach($build['headers'] as $name=>$value) + array_push($headers, $name.': '.$value); + + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + + + /* (4) On definit les donnees POST si on est pas en get */ + if( $build['method'] != 'GET' ){ + $postdata = ''; + + // On formatte les donnees au format 'key=value&key=value' + foreach($build['postdata'] as $key=>$value) + $postdata .= $key.'='.$value.'&'; + rtrim($postdata); // on supprime le '&' a la fin s'il y a + + // On envoie les donnees + curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata); + } + + + /* [4] Execution de la requete et recup de la response + =========================================================*/ + $response = curl_exec($curl); + curl_close($curl); + + + /* [5] On retourne la reponse + =========================================================*/ + return $response; + } + + + + + + + + + + /* CONSTRUCTION D'UNE REQUETE + * + * @request_name Nom de la requete + * @parameters Liste des parametres de la requete + * + * @return filledRequest Renvoie la requete avec les bons parametres + * + */ + private function build($request_name, $parameters=array()){ + /* [0] Gestion des INPUTS + =========================================================*/ + // On retourne une erreur si la requete n'existe pas + if( !isset($this->requests[$request_name]) ) return false; + + // On enregistre une copie de la requete + $request = $this->requests[$request_name]; + + + /* [1] Gestion de la methode + =========================================================*/ + // Si la methode n'est pas prise en compte, on retourne une erreur + if( !isset( self::$METHODS[$request['method']] ) ) return false; + + + + + /* [2] Remplacement des parametres (valeurs globales) + =========================================================*/ + /* (1) Remplacement dans l'URL */ + $request['url'] = $this->fillParameters($request['url'], $parameters); + + /* (2) Remplacement dans les headers */ + foreach($request['headers'] as $name=>$value) + $request['headers'][$name] = $this->fillParameters($value, $parameters); + + /* (2) Remplacement dans les postdata */ + foreach($request['postdata'] as $name=>$value) + $request['postdata'][$name] = $this->fillParameters($value, $parameters); + + + /* [3] Retour de la requete construite + =========================================================*/ + return $request; + } + + + + + /* REMPLACE LES PARAMETRES DANS UNE CHAINE + * + * @before Chaine a etudier et dans laquelle remplacer les parametres + * @parameters Liste des parametres a remplacer (prefixes d'un '@') + * + * @return after Chaine contenant les parametres de la liste @parameters + * + */ + private function fillParameters($before, $parameters){ + // On initialise la valeur de retour + $after = $before; + + /* [1] On remplace les parametres prefixes par '@' + =========================================================*/ + foreach($parameters as $name=>$value){ + $position = strpos($after, $name); + + // Si on a trouve, on remplace le nom de variable par la valeur + if( $position !== false ) + $after = substr($after, 0, $position) . $value . substr($after, $position+strlen($name) ); + + } + + /* [2] On retourne la nouvelle chaine + =========================================================*/ + return $after; + } + + } + + +?> diff --git a/test/client/background.php b/test/client/background.php new file mode 100644 index 0000000..f8d05c6 --- /dev/null +++ b/test/client/background.php @@ -0,0 +1,86 @@ + json_decode( $_POST['code'], true ), + 'action' => json_decode( $_POST['action'], true ) + ]); + + $data = ''; + + foreach($_SESSION['history'] as $h=>$entry) + $data .= "".$entry['code']." - ".$entry['action']."
"; + + + echo json_encode( [ + 'ModuleError' => 0, + 'data' => $data + ] ); + + } + + + /* [2] Gestion de la synchronisation + =========================================================*/ + if( isset($_POST['sync']) ){ + + $api = new api(); + + /* (1) On effectue la synchro */ + $token = sessionManager::secure_hash( $_COOKIE['mac_password'], $_COOKIE['mac_count'] ); + + + // Renouvellement du TOKEN + if( $_COOKIE['mac_count'] == 1 ){ + + + $response = $api->send('sync-renew', [ + '@warehouse' => '643405e1004845c2291c244faab192e3ad493b9dec147c8030475794b0f2fa23', + '@token' => $token, + '@data' => json_encode( $_SESSION['history'] ), + '@renew' => sessionManager::secure_hash( $_COOKIE['mac_password'], 10) + ]); + + $_COOKIE['mac_count'] = 9; + setcookie('mac_count', $_COOKIE['mac_count'], time()+3600*24*365, '/'); + + }else{ + + $response = $api->send('sync', [ + '@warehouse' => '643405e1004845c2291c244faab192e3ad493b9dec147c8030475794b0f2fa23', + '@token' => $token, + '@data' => json_encode( $_SESSION['history'] ) + ]); + + $_COOKIE['mac_count']--; + setcookie('mac_count', $_COOKIE['mac_count'], time()+3600*24*365, '/'); + } + + + $parsedResponse = json_decode( $response, true ); + + $toReturn = [ + 'response' => $parsedResponse, + 'pwd' => $_COOKIE['mac_password'], + 'count' => $_COOKIE['mac_count'], + 'token' => $token, + 'status' => $parsedResponse['ModuleError'], + 'data' => ($parsedResponse['ModuleError']==0) ? $parsedResponse['data'] : 'void' + ]; + + echo json_encode($toReturn); + } +?> diff --git a/test/client.php b/test/client/interface.php similarity index 82% rename from test/client.php rename to test/client/interface.php index 93c79df..80fe77d 100644 --- a/test/client.php +++ b/test/client/interface.php @@ -1,9 +1,18 @@ - @@ -30,6 +39,12 @@



+ + +
+ +


+





@@ -45,12 +60,13 @@ var bUnlock = document.querySelector('input[data-name="unlock"]'); var bSync = document.querySelector('input[data-name="sync"]'); + var cBox = document.querySelector('#cookie-box'); var sBox = document.querySelector('#status-box'); var hBox = document.querySelector('#history-box'); var FD = new FormDeflater(document.body, ['input'], ['data-name']); - var selfApi = new APIClass('/test/clientBackground.php'); + var selfApi = new APIClass('/test/client/background.php'); var remoteApi = new APIClass('/api/'); var state = false; @@ -148,6 +164,15 @@ /* (5) Gestion de la synchro */ bSync.addEventListener('click', function(e){ + var req = { + 'sync' : null, + }; + + selfApi.send(req, function(res){ + cBox.innerHTML = res.pwd+'
'+res.count; + console.log(res); + }); + }, false); diff --git a/test/clientBackground.php b/test/clientBackground.php deleted file mode 100644 index 2716390..0000000 --- a/test/clientBackground.php +++ /dev/null @@ -1,27 +0,0 @@ -$entry) - $data .= "".$entry[0]." - ".$entry[1]."
"; - - - echo json_encode( [ - 'ModuleError' => 0, - 'data' => $data - ] ); - - } -?> diff --git a/test/testHashChain.php b/test/testHashChain.php index 113348d..90101c0 100644 --- a/test/testHashChain.php +++ b/test/testHashChain.php @@ -7,8 +7,16 @@ $hash = 'password'; + $times = 10000; - var_dump( sessionManager::secure_hash($hash, 1000) ); + $start = microtime(true); + $hashed = sessionManager::secure_hash($hash, $times); + $stop = microtime(true); + + var_dump( $hashed ); + $elapsed = ($stop-$start)/1000; + var_dump('time: '. $elapsed . ' ms'); + var_dump('hash/sec: '. $elapsed/$times . ' ms');