mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 05:58:58 +01:00
Refactored AuthorizationHandler and written DataCenter class
This commit is contained in:
parent
246579d645
commit
f331931365
@ -31,6 +31,7 @@ src/danog/MadelineProto/
|
||||
TLMethod - Represents a TL method
|
||||
API - Wrapper class that istantiates the MTProto class, sets the error handler, and provides a wrapper for calling mtproto methods directly as class submethods
|
||||
Connection - Handles tcp/udp/http connections and wrapping payloads generated by MTProtoTools/MessageHandler into the right message according to the protocol
|
||||
DataCenter - Handles mtproto datacenters
|
||||
DebugTools - Various debugging tools
|
||||
Exception - Handles exceptions in the main namespace
|
||||
MTProto - Extends MTProtoTools, handles initial connection, generation of authorization keys, istantiation of classes
|
||||
|
@ -12,7 +12,7 @@ If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
class API
|
||||
class API extends Tools
|
||||
{
|
||||
public $session;
|
||||
|
||||
|
71
src/danog/MadelineProto/DataCenter.php
Normal file
71
src/danog/MadelineProto/DataCenter.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright 2016 Daniil Gentili
|
||||
(https://daniil.it)
|
||||
This file is part of MadelineProto.
|
||||
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License along with the MadelineProto.
|
||||
If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
/**
|
||||
* Manages all of the mtproto stuff.
|
||||
*/
|
||||
class DataCenter extends Tools
|
||||
{
|
||||
public function __construct($dclist, $settings) {
|
||||
$this->dclist = $dclist;
|
||||
$this->settings = $settings;
|
||||
if (isset($this->settings["all"])) {
|
||||
foreach ($this->range(1, 6) as $n) {
|
||||
$this->settings[$n] = $this->settings["all"];
|
||||
}
|
||||
unset($this->settings["all"]);
|
||||
}
|
||||
foreach ($this->range(1, 6) as $n) {
|
||||
if (!isset($this->settings[$n])) {
|
||||
$this->settings[$n] = [
|
||||
'protocol' => 'tcp_full',
|
||||
'port' => '443',
|
||||
'test_mode' => true
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->connect(2);
|
||||
}
|
||||
public function connnect($dc_number, $settings = []) {
|
||||
if ($settings == []) {
|
||||
$settings = $this->settings[$dc_number];
|
||||
}
|
||||
$address = $settings["test_mode"] ? $this->dclist["test"][$dc_number] : $this->dclist["main"][$dc_number];
|
||||
if ($settings["protocol"] == "https") {
|
||||
$subdomain = $this->dclist["ssl_subdomains"][$dc_number] . ($settings["upload"] ? '-1' : '');
|
||||
$path = $settings["test_mode"] ? 'apiw_test1' : 'apiw1';
|
||||
$address = 'https://' . $subdomain . '.web.telegram.org/' . $path;
|
||||
}
|
||||
$this->sockets[$dc_number] = new Connection($address, $settings["port"], $settings["protocol"]);
|
||||
$this->curdc = $dc_number;
|
||||
}
|
||||
public function send_message($message, $dc_number = -1) {
|
||||
if ($dc_number == -1) {
|
||||
$dc_number = $this->curdc;
|
||||
}
|
||||
return $this->sockets[$dc_number]->send_message($message);
|
||||
}
|
||||
public function read_message($dc_number = -1) {
|
||||
if ($dc_number == -1) {
|
||||
$dc_number = $this->curdc;
|
||||
}
|
||||
return $this->sockets[$dc_number]->read_message();
|
||||
}
|
||||
|
||||
public function __destroy() {
|
||||
foreach ($this->sockets as $n => $socket) {
|
||||
unset($this->sockets[$n]);
|
||||
}
|
||||
}
|
||||
}
|
@ -38,12 +38,30 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----',
|
||||
],
|
||||
'connection' => [
|
||||
'dc_list' => [
|
||||
2 => [
|
||||
'ip_address' => '149.154.167.50',
|
||||
'port' => '443',
|
||||
'protocol' => 'tcp_full',
|
||||
],
|
||||
'ssl_subdomains' => [
|
||||
1 => 'pluto',
|
||||
2 => 'venus',
|
||||
3 => 'aurora',
|
||||
4 => 'vesta',
|
||||
5 => 'flora'
|
||||
],
|
||||
'test' => [
|
||||
1 => '149.154.175.10',
|
||||
2 => '149.154.167.40',
|
||||
3 => '149.154.175.117'
|
||||
],
|
||||
'main' => [
|
||||
1 => '149.154.175.50',
|
||||
2 => '149.154.167.51',
|
||||
3 => '149.154.175.100',
|
||||
4 => '149.154.167.91',
|
||||
5 => '149.154.171.5'
|
||||
]
|
||||
],
|
||||
'connection_settings' => [
|
||||
'all' => [
|
||||
'protocol' => 'tcp_full',
|
||||
'test_mode' => true
|
||||
],
|
||||
],
|
||||
'app_info' => [
|
||||
@ -85,7 +103,8 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
$this->settings = $settings;
|
||||
|
||||
// Connect to servers
|
||||
$this->sock = new Connection($this->settings['connection']['ip_address'], $this->settings['connection']['port'], $this->settings['connection']['protocol']);
|
||||
$this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
|
||||
var_dump($this->connection);
|
||||
|
||||
// Load rsa key
|
||||
$this->key = new RSA($settings['authorization']['rsa_key']);
|
||||
|
@ -22,7 +22,7 @@ class AuthKeyHandler extends AckHandler
|
||||
{
|
||||
public function create_auth_key($expires_in = -1)
|
||||
{
|
||||
foreach (\danog\MadelineProto\Tools::range(0, $this->settings['max_tries']['authorization']) as $retry_id_total) {
|
||||
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id_total) {
|
||||
$this->log->log('Handshake: Requesting pq');
|
||||
|
||||
/**
|
||||
@ -51,7 +51,7 @@ class AuthKeyHandler extends AckHandler
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Compare the equal of nonce client and nonce server
|
||||
* Check if the client's nonce and the server's nonce are the same
|
||||
*/
|
||||
if ($ResPQ['nonce'] !== $nonce) {
|
||||
throw new Exception('Handshake: wrong nonce');
|
||||
@ -94,7 +94,7 @@ class AuthKeyHandler extends AckHandler
|
||||
throw new Exception("Handshake: couldn't compute p and q.");
|
||||
}
|
||||
|
||||
$this->log->log(sprintf('Factorization %s = %s * %s', $pq, $p, $q));
|
||||
$this->log->log('Handshake: Factorization '.$pq.' = '.$p.' * '.$q);
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
@ -138,7 +138,7 @@ class AuthKeyHandler extends AckHandler
|
||||
$to_encrypt = $sha_digest.$data.$random_bytes;
|
||||
$encrypted_data = $this->key->encrypt($to_encrypt);
|
||||
|
||||
$this->log->log('Starting Diffie Hellman key exchange');
|
||||
$this->log->log('Handshake: Starting Diffie Hellman key exchange');
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Starting Diffie Hellman key exchange, Server authentication
|
||||
@ -172,7 +172,7 @@ class AuthKeyHandler extends AckHandler
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Compare the equal of nonce client and nonce server
|
||||
* Check if the client's nonce and the server's nonce are the same
|
||||
*/
|
||||
if ($nonce != $server_dh_params['nonce']) {
|
||||
throw new Exception('Handshake: wrong nonce.');
|
||||
@ -180,7 +180,7 @@ class AuthKeyHandler extends AckHandler
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Compare the equal of server_nonce and new server_nonce
|
||||
* Check if server_nonce and new server_nonce are the same
|
||||
*/
|
||||
if ($server_nonce != $server_dh_params['server_nonce']) {
|
||||
throw new Exception('Handshake: wrong server nonce.');
|
||||
@ -224,13 +224,13 @@ class AuthKeyHandler extends AckHandler
|
||||
* int $server_time
|
||||
* ]
|
||||
*/
|
||||
$server_DH_inner_data = $this->tl->deserialize(\danog\MadelineProto\Tools::fopen_and_write('php://memory', 'rw+b', $answer));
|
||||
$server_DH_inner_data = $this->tl->deserialize($this->fopen_and_write('php://memory', 'rw+b', $answer));
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Do some checks
|
||||
*/
|
||||
$server_DH_inner_data_length = $this->tl->get_length(\danog\MadelineProto\Tools::fopen_and_write('php://memory', 'rw+b', $answer));
|
||||
$server_DH_inner_data_length = $this->tl->get_length($this->fopen_and_write('php://memory', 'rw+b', $answer));
|
||||
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
|
||||
throw new Exception('Handshake: answer_hash mismatch.');
|
||||
}
|
||||
@ -252,9 +252,9 @@ class AuthKeyHandler extends AckHandler
|
||||
* Time delta
|
||||
*/
|
||||
$server_time = $server_DH_inner_data['server_time'];
|
||||
$this->timedelta = ($server_time - time());
|
||||
$this->timedelta = $server_time - time();
|
||||
|
||||
$this->log->log(sprintf('Server-client time delta = %.1f s', $this->timedelta));
|
||||
$this->log->log(sprintf('Handshake: Server-client time delta = %.1f s', $this->timedelta));
|
||||
|
||||
|
||||
/*
|
||||
@ -310,7 +310,7 @@ class AuthKeyHandler extends AckHandler
|
||||
throw new Exception('Handshake: g_a is invalid (1 < g_a < dh_prime - 1 is false).');
|
||||
}
|
||||
|
||||
foreach (\danog\MadelineProto\Tools::range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
|
||||
foreach ($this->range(0, $this->settings['max_tries']['authorization']) as $retry_id) {
|
||||
$b = new \phpseclib\Math\BigInteger(\phpseclib\Crypt\Random::string(256), 256);
|
||||
$g_b = $g->powMod($b, $dh_prime);
|
||||
|
||||
@ -352,7 +352,7 @@ class AuthKeyHandler extends AckHandler
|
||||
* encrypt client_DH_inner_data
|
||||
*/
|
||||
$data_with_sha = sha1($data, true).$data;
|
||||
$data_with_sha_padded = $data_with_sha.\phpseclib\Crypt\Random::string(\danog\MadelineProto\Tools::posmod(-strlen($data_with_sha), 16));
|
||||
$data_with_sha_padded = $data_with_sha.\phpseclib\Crypt\Random::string($this->posmod(-strlen($data_with_sha), 16));
|
||||
$encrypted_data = $this->ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
|
||||
|
||||
/*
|
||||
@ -395,7 +395,7 @@ class AuthKeyHandler extends AckHandler
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Compare the equal of nonce client and nonce server
|
||||
* Check if the client's nonce and the server's nonce are the same
|
||||
*/
|
||||
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
|
||||
throw new Exception('Handshake: wrong nonce.');
|
||||
@ -403,7 +403,7 @@ class AuthKeyHandler extends AckHandler
|
||||
|
||||
/*
|
||||
* ***********************************************************************
|
||||
* Compare the equal of server_nonce and new server_nonce
|
||||
* Check if server_nonce and new server_nonce are the same
|
||||
*/
|
||||
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
|
||||
throw new Exception('Handshake: wrong server nonce');
|
||||
@ -413,41 +413,43 @@ class AuthKeyHandler extends AckHandler
|
||||
* ***********************************************************************
|
||||
* Check Set_client_DH_params_answer type
|
||||
*/
|
||||
if ($Set_client_DH_params_answer['_'] == 'dh_gen_ok') {
|
||||
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
||||
throw new Exception('Handshake: wrong new_nonce_hash1');
|
||||
}
|
||||
switch ($Set_client_DH_params_answer['_']) {
|
||||
case 'dh_gen_ok':
|
||||
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
||||
throw new Exception('Handshake: wrong new_nonce_hash1');
|
||||
}
|
||||
|
||||
$this->log->log('Diffie Hellman key exchange processed successfully');
|
||||
$this->log->log('Diffie Hellman key exchange processed successfully');
|
||||
|
||||
$res_authorization['server_salt'] = $this->struct->unpack('<q', substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0))[0];
|
||||
$res_authorization['auth_key'] = $auth_key_str;
|
||||
$res_authorization['id'] = substr($auth_key_sha, -8);
|
||||
$res_authorization['server_salt'] = $this->struct->unpack('<q', substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0))[0];
|
||||
$res_authorization['auth_key'] = $auth_key_str;
|
||||
$res_authorization['id'] = substr($auth_key_sha, -8);
|
||||
|
||||
if ($expires_in < 0) { //check if permanent authorization
|
||||
$res_authorization['expires_in'] = $expires_in;
|
||||
}
|
||||
if ($expires_in < 0) { //check if permanent authorization
|
||||
$res_authorization['expires_in'] = $expires_in;
|
||||
}
|
||||
|
||||
$this->log->log('Auth key generated');
|
||||
$this->timedelta = 0;
|
||||
$this->log->log('Auth key generated');
|
||||
$this->timedelta = 0;
|
||||
return $res_authorization;
|
||||
case 'dh_gen_retry':
|
||||
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
||||
throw new Exception('Handshake: wrong new_nonce_hash_2');
|
||||
}
|
||||
|
||||
return $res_authorization;
|
||||
} elseif ($Set_client_DH_params_answer['_'] == 'dh_gen_retry') {
|
||||
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
||||
throw new Exception('Handshake: wrong new_nonce_hash_2');
|
||||
}
|
||||
//repeat foreach
|
||||
$this->log->log('Handshake: Retrying Auth');
|
||||
break;
|
||||
case 'dh_gen_fail':
|
||||
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
|
||||
throw new Exception('Handshake: wrong new_nonce_hash_3');
|
||||
}
|
||||
|
||||
//repeat foreach
|
||||
$this->log->log('Retrying Auth');
|
||||
} elseif ($Set_client_DH_params_answer['_'] == 'dh_gen_fail') {
|
||||
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
|
||||
throw new Exception('Handshake: wrong new_nonce_hash_3');
|
||||
}
|
||||
|
||||
$this->log->log('Auth Failed');
|
||||
break;
|
||||
} else {
|
||||
throw new Exception('Response Error');
|
||||
$this->log->log('Handshake: Auth Failed');
|
||||
break 2;
|
||||
default:
|
||||
throw new Exception('Response Error');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ class CallHandler extends AuthKeyHandler
|
||||
$server_answer = $this->wait_for_response($int_message_id);
|
||||
} catch (Exception $e) {
|
||||
$this->log->log('An error occurred while calling method '.$method.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().$e->getTraceAsString().'. Recreating connection and retrying to call method...');
|
||||
unset($this->sock);
|
||||
$this->sock = new \danog\MadelineProto\Connection($this->settings['connection']['ip_address'], $this->settings['connection']['port'], $this->settings['connection']['protocol']);
|
||||
unset($this->connection);
|
||||
$this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
|
||||
continue;
|
||||
}
|
||||
if ($server_answer == null) {
|
||||
@ -73,9 +73,9 @@ class CallHandler extends AuthKeyHandler
|
||||
$this->outgoing_messages[$int_message_id]['content'] = ['object' => $object, 'args' => $args];
|
||||
// $server_answer = $this->wait_for_response($int_message_id);
|
||||
} catch (Exception $e) {
|
||||
$this->log->log('An error occurred while calling object '.$object.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().'. Recreating connection and retrying to call object...');
|
||||
unset($this->sock);
|
||||
$this->sock = new \danog\MadelineProto\Connection($this->settings['connection']['ip_address'], $this->settings['connection']['port'], $this->settings['connection']['protocol']);
|
||||
$this->log->log('An error occurred while calling object '.$object.': '.$e->getMessage().' in '.$e->getFile().':'.$e->getLine().'. Recreating connection and retrying to call object...');
|
||||
unset($this->connection);
|
||||
$this->connection = new DataCenter($this->settings['connection'], $this->settings['connection_settings']);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -38,17 +38,17 @@ class MessageHandler extends Crypt
|
||||
$message = $this->settings['authorization']['temp_auth_key']['id'].$message_key.$this->ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
||||
$this->outgoing_messages[$int_message_id]['seq_no'] = $seq_no;
|
||||
}
|
||||
$this->sock->send_message($message);
|
||||
$this->connection->send_message($message);
|
||||
|
||||
return $int_message_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reading socket and receiving message from server. Check the CRC32.
|
||||
* Reading connectionet and receiving message from server. Check the CRC32.
|
||||
*/
|
||||
public function recv_message()
|
||||
{
|
||||
$payload = $this->sock->read_message();
|
||||
$payload = $this->connection->read_message();
|
||||
if (fstat($payload)['size'] == 4) {
|
||||
throw new Exception('Server response error: '.abs($this->struct->unpack('<i', fread($payload, 4))[0]));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user