getResponse() Küldés: __construct getSSLKeyPair _genSessionKey setRemoteNodeId _setRemotePublicKey getSslPublicKeyByNodeId setRemoteHost (HOST, publicKey) _setRemotePublicKey setRequestTarget (PSF) sendRequest _prepareRequest _encodeRequest($ADAT) AES::encrypt !! json, base64 - nincs AES :( _sessionKeyEncode _curlGet --> response _decodeRequest !! jelenleg csak json... _sessionKeyDecode json_decode - AES::decrypt */ function getSslKeyPair() { $q = "SELECT * FROM mayorSsl"; $r = db_query($q, array('fv'=>'getSslKeyPair','modul'=>'login','result'=>'record')); if ($r=='') { $SSLKeyPair = generateSSLKeyPair(); $secret = sha1(mt_rand(100000000000000,999999999999999)); $q = "INSERT INTO mayorSsl (privateKey,publicKey,secret) VALUES ('%s','%s','%s')"; $values = array($SSLKeyPair['privateKey'],$SSLKeyPair['publicKey'],$secret); $r = db_query($q, array('fv'=>'getSslKeyPair','modul'=>'login', 'values'=>$values)); return $SSLKeyPair; } else { return $r; } } function generateSSLKeyPair() { $SSL_KEY_PAIR=openssl_pkey_new(); // Get private key openssl_pkey_export($SSL_KEY_PAIR, $privatekey); // Get public key $publickey=openssl_pkey_get_details($SSL_KEY_PAIR); $publickey=$publickey["key"]; return array('fv'=>'geneateSslKeyPair','privateKey'=>$privatekey,'publicKey'=>$publickey); } function setNodeId($nodeId, $publicKey) { $q = "UPDATE mayorSsl SET nodeId=%u where publicKey='%s'"; $v = array($nodeId, $publicKey); return db_query($q, array('debug'=>false,'fv'=>'setNodeId','modul'=>'login', 'values'=>$v)); } function getSslPublicKey() { $SSLKeyPair = getSslKeyPair(); return $SSLKeyPair['publicKey']; } function getSslPublicKeyByNodeId($nodeId) { if (is_numeric($nodeId)) { $q = "SELECT publicKey FROM mayorKeychain WHERE valid=1 AND nodeId='%u'"; $values = array($nodeId); $result = db_query($q, array('debug'=>false,'fv'=>'getSslPublicKeyByNodeId','modul'=>'login', 'values'=>$values,'result'=>'value')); if ($result=='') return false; else return $result; } else { return false; } } function getPublicDataFromLocalKeychain($nodeId) { if (is_numeric($nodeId)) { // lekérdezés a helyi adatbázisból $q = "SELECT * FROM mayorKeychain WHERE valid=1 AND nodeId='%u'"; $values = array($nodeId); $result = db_query($q, array('debug'=>false,'fv'=>'getPublicDataFromLocalKeychain','modul'=>'login', 'values'=>$values,'result'=>'record')); if ($result=='') return false; else return $result; } elseif (is_null($nodeId)) { // Az összes eltárolt node adatának lekérdezése $q = "SELECT * FROM mayorKeychain WHERE valid=1 ORDER BY nodeTipus DESC, nev"; $result = db_query($q, array('debug'=>false,'fv'=>'getPublicDataFromLocalKeychain','modul'=>'login','result'=>'indexed')); if ($result=='') return false; else return $result; } } function addPublicDataToLocalKeychain($DATA) { // egy új rekord felvétele... $fields = array_keys($DATA); $values = array_values($DATA); $q = "INSERT INTO mayorKeychain (".implode(',', array_fill(0, count($fields), "%s")).") VALUES (".implode(',', array_fill(0, count($values), "'%s'")).")"; $v = array_merge($fields, $values); $r = db_query($q, array('debug'=>false,'func'=>'addPublicDataToLocalKeychain','modul'=>'login','values'=>$v,'result'=>'insert')); return $r; } function removeNodeFromLocalKeychain($nodeId) { $q = "DELETE FROM mayorKeychain WHERE nodeId=%u"; $v = array($nodeId); $r = db_query($q, array('debug'=>false,'func'=>'removeNodeFromLocalKeychain','modul'=>'login','values'=>$v)); return $r; } function sendPublicRequest($data) { if (defined('_DEVEL') && _DEVEL===true) $host = 'localhost'; else $host = 'www.mayor.hu'; $url = "https://$host/index.php?page=portal&sub=regisztracio&f=regisztracio&skin=ajax"; $salt_name='MS_'.sha1('portal_regisztracio_regisztracio'); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // a választ feldolgozzuk curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYSTATUS, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // a helyi gépen nekem ez kellett :( curl_setopt($ch, CURLOPT_HEADER, 0); // curl_setopt($ch, CURLOPT_TIMEOUT,60); curl_setopt($ch, CURLOPT_USERAGENT, "MaYoR-registration (php; cURL)"); curl_setopt($ch, CURLOPT_VERBOSE, true); // Cookie curl_setopt($ch, CURLOPT_COOKIE, $salt_name.'=portal_regisztracio_regisztracio'); // POST curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); $response = curl_exec($ch); $INFO = curl_getinfo($ch); // ha kell if ($INFO['http_code'] == 200) { // minden ok //dump($INFO['url']); //dump("response:",$response); } else { echo 'URL'; dump($INFO['http_code'],$response,$INFO); throw new Exception($INFO['http_code']); } curl_close($ch); return $response; } //function base64url_encode($data) { // return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); //} //function base64url_decode($data) { // return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); //} function random_str($length, $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') { $str = ''; $max = mb_strlen($keyspace, '8bit') - 1; for ($i = 0; $i < $length; ++$i) { $str .= $keyspace[random_int(0, $max)]; } return $str; } /* symmetric cryptographic module */ class AES { public function __construct() { } public function encrypt($data, $key) { $data = urlencode($data); // $return = $data; // $return = $key . $data; // $return = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA); // $return = db_query("SELECT aes_encrypt('%s','%s')",array('fv'=>'class AES','result'=>'value','modul'=>'login','values'=>array($data,$key))); if (function_exists('mcrypt_encrypt')) { $return = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_MODE_CBC,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); } else { $_SESSION['alert'][] = 'info:mcrypt függvény nem található (tipp! telepítsd a php5-mcrypt csomagot a szerverre)'; } return base64_encode($return); } public function decrypt($data,$key) { $data = base64_decode($data); // $return = $data; // $return = substr($data,strlen($key)); // $return = openssl_decrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA); // $return = db_query("SELECT aes_decrypt('%s','%s')",array('fv'=>'class AES','result'=>'value','modul'=>'login','values'=>array($data,$key))); if (function_exists('mcrypt_decrypt')) { $return = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_MODE_CBC,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); } else { $_SESSION['alert'][] = 'info:mcrypt függvény nem található (tipp! telepítsd a php5-mcrypt csomagot a szerverre)'; } return trim(urldecode($return)); } } class Interconnect { /* A: küldő, B: fogadó használja */ private $sessionKey; // egy kommunikációhoz használt session kulcs private $KP; // a saját kulcspárom private $nodeId; private $privateKey; private $publicKey; private $remotePublicKey; private $remoteNodeId; private $remoteHost; private $psf; private $myRequest; // a küldendő kérés (object) private $myResponse; // a küldendő válasz (object) private $incomingRequest; // a beérkező kérés (object) private $incomingResponse; // a beérkező válasz (object) private $status; // a művelet eredményességéek visszajelzése, hibaok kódja... private $controllerNodeId = '09862967'; // Ez van jelenleg az adatbázisban... /* Konstruktor */ public function __construct() { $this->sessionKey = $this->_genSessionKey(); $this->KP = getSSLKeyPair(); $this->nodeId = $this->KP['nodeId']; $this->privateKey = $this->KP['privateKey']; $this->publicKey = $this->KP['publicKey']; $this->status = 'ok:created'; $this->psf = 'page=rpc&f=rpc'; } /* Privát metódusok */ // private function _yconv($get) { // $get = str_replace(' ','+',$get); // hm. erre miért van szükség??? autokonverzió? // $get = str_replace('\/','/',$get); // hm. erre miért van szükség??? autokonverzió? // $get = str_replace('\\','',$get); // hm. erre miért van szükség??? autokonverzió?\"' // return $get; // } private function _curlGet($data) { $host = $this->remoteHost; $url = $this->remoteHost."/index.php?skin=rpc&".$this->psf; //dump('url',$url); $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // a választ feldolgozzuk curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYSTATUS, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // a helyi gépen nekem ez kellett :( curl_setopt($ch, CURLOPT_HEADER, 0); // curl_setopt($ch, CURLOPT_TIMEOUT,60); curl_setopt($ch, CURLOPT_USERAGENT, "MaYoR-interconnect (php; cURL)"); curl_setopt($ch, CURLOPT_VERBOSE, true); // POST $data['senderNodeId'] = $this->nodeId; curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); $response = curl_exec($ch); $INFO = curl_getinfo($ch); // ha kell if ($INFO['http_code'] == 200) { // minden ok //dump($INFO['url']); //dump($response); } else { echo 'URL'; dump($response,$INFO); throw new Exception($INFO['http_code']); } curl_close($ch); return $response; } private function _genSessionKey() { return base64_encode(pack('N6', mt_rand(), mt_rand(), mt_rand(),mt_rand(), mt_rand(), mt_rand())); //return random_str( 32 ); } private function _sessionKeyEncode() { $crypttext = ''; $res = openssl_public_encrypt($this->sessionKey, $crypttext, $this->remotePublicKey); // majd a távoli publikus kulccal return base64_encode($crypttext); } private function _sessionKeyDecode($in) { $decodedtext = ''; $res = openssl_private_decrypt(base64_decode($in), $decodedtext, $this->privateKey); // a saját privát kulccsal return $decodedtext; } private function _genHash($in) { // hash generálás return hash('sha256', $in, false); } private function _hashEncode($in) { // a mi privát kulcsunkkal... $res = openssl_private_encrypt($in, $encodedHash, $this->privateKey); // a saját privát kulccsal return base64_encode($encodedHash); } private function _hashDecode($in) { // a remotePublic-kal $res = openssl_public_decrypt(base64_decode($in), $decodedHash, $this->remotePublicKey); // majd a távoli publikus kulccal return $decodedHash; } private function _verifyHash($PACKED) { return ($this->_genHash($PACKED['details']))===($this->_hashDecode($PACKED['hashEncoded'])); } private function _packData($DATA) { // --> array(details|sessionKeyEncoded) $ADAT['details'] = AES::encrypt(json_encode($DATA),$this->sessionKey); // implicit base64_encode $ADAT['hashEncoded'] = $this->_hashEncode($this->_genHash($ADAT['details'])); $ADAT['sessionKeyEncoded'] = $this->_sessionKeyEncode(); // implicit base64_encode $ADAT['status'] = $this->status; return $ADAT; } private function _unpackData($PACKED) { // packed[details] --> object !! feltesszük, hogy már be van állítva a sessionKey, ellenőrizve van a hash! return json_decode(AES::decrypt($PACKED['details'],$this->sessionKey), true); } private function _encodeRequest($IN = array()) { // HTTP GET paraméter return urlencode(json_encode($IN)); } private function _decodeRequest($IN) { // HTTP GET paraméter return json_decode($IN, true); } private function _encodeResponse($IN=array()) { // HTTP - tartalom return json_encode($IN); } private function _decodeResponse($IN=array()) { // HTTP - tartalom return json_decode($IN, true); } /* Publikus metódusok */ public function setRequestTarget($target) { if ($target == 'controller') $this->psf='page=rpc&sub=controller&f=rpc'; else if ($target == 'naplo') $this->psf='page=rpc&sub=naplo&f=rpc'; else $this->psf='page=rpc&f=rpc'; // alap funkciók } public function getRegistrationDataByNodeId($nodeId) { // feltesszük, hogy valid $origRemoteNodeId = $this->remoteNodeId; $this->setRemoteHostByNodeId($this->controllerNodeId); $ret = $this->sendRequest(array('func'=>'getPublicDataByNodeId', 'nodeId'=>$nodeId)); $this->setRemoteHostByNodeId($origRemoteNodeId); return $ret; } public function getPublicDataByNodeId($nodeId) { if (defined('_DEVEL') && _DEVEL===true) { // A helyi gép adatait adjuk meg $ret = array('nodeId'=>$this->nodeId, 'url'=>'https://localhost','publicKey'=>$this->publicKey); } else { if ($nodeId == '') $nodeId = $this->controllerNodeId; // Adott nodeId adatainak lekérdezése a helyi adatbázisból $ret = getPublicDataFromLocalKeychain($nodeId); if ($ret === false) { $RPC = new Interconnect(); $RPC->setRequestTarget('controller'); $RPC->setRemoteHostByNodeId($this->controllerNodeId); $ret2 = $RPC->sendRequest(array('func'=>'getPublicDataByNodeId', 'nodeId'=>$nodeId)); $ret = $ret2['nodeData']; foreach (array( 'regId','dij','utemezes','egyebTamogatas','szamlazasiCim','szamlaHelyseg','szamlaIrsz','szamlaKozteruletNev', 'szamlaKozteruletJelleg','szamlaHazszam' ) as $field) { unset($ret[$field]); } if (is_array($ret)) addPublicDataToLocalKeychain($ret); /* } elseif (false) { // Adott nodeId adatainak lekérdezése a www.mayor.hu-tól (controller) Interconnect-tel $origRemoteNodeId = $this->remoteNodeId; $origPsf = $this->psf; $this->setRequestTarget('controller'); $this->setRemoteHostByNodeId($this->controllerNodeId); $ret2 = $this->sendRequest(array('func'=>'getPublicDataByNodeId', 'nodeId'=>$nodeId)); $ret = $ret2['nodeData']; foreach (array( 'regId','dij','utemezes','egyebTamogatas','szamlazasiCim','szamlaHelyseg','szamlaIrsz','szamlaKozteruletNev', 'szamlaKozteruletJelleg','szamlaHazszam' ) as $field) { unset($ret[$field]); } if (is_array($ret)) addPublicDataToLocalKeychain($ret); if ($origRemoteNodeId!='') $this->setRemoteHostByNodeId($origRemoteNodeId); $this->psf = $origPsf; */ } } return $ret; } public function setRemoteHostByNodeId($nodeId) { $rData = $this->getPublicDataByNodeId($nodeId); if (is_array($rData)) { $this->remoteHost = $rData['url']; $this->remoteNodeId = $rData['nodeId']; $this->remotePublicKey = $rData['publicKey']; $this->status = 'ok:remoteHost'; } else { $this->remoteHost = ''; // controller $this->remoteNodeId = $this->controllerNodeId; $this->remotePublicKey = $rData['publicKey']; $this->status = 'ok:remoteHostController'; } } /* A oldal */ public function sendRequest($ADAT = array()) { $PACKED = $this->_packData($ADAT); $this->myRequest = $PACKED; // $this->myRequest = $this->_encodeRequest($PACKED); $response = $this->_curlGet($this->myRequest); $decodedResponse = $this->_decodeResponse($response); if ($this->sessionKey === $this->_sessionKeyDecode($decodedResponse['sessionKeyEncoded'])) { if ($this->_verifyHash($decodedResponse)) { $this->incomingResponse = $this->_unpackData($decodedResponse); $this->status = 'ok:success response'; } else { $this->incomingResponse = false; $this->status = 'error:wrong response hash'; } } else { $this->status = 'error:wrong response sessionKey ('.($this->sessionKey).' != '.($this->_sessionKeyDecode($decodedResponse['sessionKeyEncoded'])).') response: '.$response; $this->incomingResponse = false; } return $this->incomingResponse; } /* B oldal! */ public function processRequest() { // rights.php $PACKED = $_POST; $this->sessionKey = $this->_sessionKeyDecode($PACKED['sessionKeyEncoded']); if ($this->_verifyHash($PACKED)) { $this->incomingRequest = $this->_unpackData($PACKED); openlog("MaYoR Interconnect", LOG_PID | LOG_PERROR, LOG_LOCAL0); syslog(LOG_WARNING, "Data unpacked: ".(json_encode($this->incomingRequest))." {$_SERVER['REMOTE_ADDR']} ({$_SERVER['HTTP_USER_AGENT']})"); closelog(); $this->status = 'ok:success request'; } else { $this->incomingRequest = false; $this->status = 'error:wrong request hash'; } return $this->incomingRequest; } public function setResponse($DATA) { // ez kell a pre-be $this->myResponse = $this->_encodeResponse($this->_packData($DATA)); } public function sendResponse() { // skin=rpc - csak ki kell írnunk az elküldendő adatsort - ezt a skin csinálja echo $this->myResponse; } public function getIncomingRequest() { return $this->incomingRequest; } // a pre-ben public function getPublicKey() { return $this->publicKey; } public function getSessionKey() { return $this->sessionKey; } public function getStatus() { return $this->status; } public function getRemoteNodeId() { return $this->remoteNodeId; } public function getControllerNodeId() { return $this->controllerNodeId; } public function getNodeId() { return $this->nodeId; } } ?>