mirror of
https://github.com/danog/MadelineProto.git
synced 2024-12-02 14:37:48 +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
|
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
|
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
|
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
|
DebugTools - Various debugging tools
|
||||||
Exception - Handles exceptions in the main namespace
|
Exception - Handles exceptions in the main namespace
|
||||||
MTProto - Extends MTProtoTools, handles initial connection, generation of authorization keys, istantiation of classes
|
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;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
class API
|
class API extends Tools
|
||||||
{
|
{
|
||||||
public $session;
|
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-----',
|
-----END RSA PUBLIC KEY-----',
|
||||||
],
|
],
|
||||||
'connection' => [
|
'connection' => [
|
||||||
'dc_list' => [
|
'ssl_subdomains' => [
|
||||||
2 => [
|
1 => 'pluto',
|
||||||
'ip_address' => '149.154.167.50',
|
2 => 'venus',
|
||||||
'port' => '443',
|
3 => 'aurora',
|
||||||
'protocol' => 'tcp_full',
|
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' => [
|
'app_info' => [
|
||||||
@ -85,7 +103,8 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
|
|
||||||
// Connect to servers
|
// 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
|
// Load rsa key
|
||||||
$this->key = new RSA($settings['authorization']['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)
|
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');
|
$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) {
|
if ($ResPQ['nonce'] !== $nonce) {
|
||||||
throw new Exception('Handshake: wrong 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.");
|
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;
|
$to_encrypt = $sha_digest.$data.$random_bytes;
|
||||||
$encrypted_data = $this->key->encrypt($to_encrypt);
|
$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
|
* 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']) {
|
if ($nonce != $server_dh_params['nonce']) {
|
||||||
throw new Exception('Handshake: wrong 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']) {
|
if ($server_nonce != $server_dh_params['server_nonce']) {
|
||||||
throw new Exception('Handshake: wrong server nonce.');
|
throw new Exception('Handshake: wrong server nonce.');
|
||||||
@ -224,13 +224,13 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* int $server_time
|
* 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
|
* 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) {
|
if (sha1(substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
|
||||||
throw new Exception('Handshake: answer_hash mismatch.');
|
throw new Exception('Handshake: answer_hash mismatch.');
|
||||||
}
|
}
|
||||||
@ -252,9 +252,9 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* Time delta
|
* Time delta
|
||||||
*/
|
*/
|
||||||
$server_time = $server_DH_inner_data['server_time'];
|
$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).');
|
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);
|
$b = new \phpseclib\Math\BigInteger(\phpseclib\Crypt\Random::string(256), 256);
|
||||||
$g_b = $g->powMod($b, $dh_prime);
|
$g_b = $g->powMod($b, $dh_prime);
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* encrypt client_DH_inner_data
|
* encrypt client_DH_inner_data
|
||||||
*/
|
*/
|
||||||
$data_with_sha = sha1($data, true).$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);
|
$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) {
|
if ($Set_client_DH_params_answer['nonce'] != $nonce) {
|
||||||
throw new Exception('Handshake: wrong 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) {
|
if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
|
||||||
throw new Exception('Handshake: wrong server nonce');
|
throw new Exception('Handshake: wrong server nonce');
|
||||||
@ -413,7 +413,8 @@ class AuthKeyHandler extends AckHandler
|
|||||||
* ***********************************************************************
|
* ***********************************************************************
|
||||||
* Check Set_client_DH_params_answer type
|
* Check Set_client_DH_params_answer type
|
||||||
*/
|
*/
|
||||||
if ($Set_client_DH_params_answer['_'] == 'dh_gen_ok') {
|
switch ($Set_client_DH_params_answer['_']) {
|
||||||
|
case 'dh_gen_ok':
|
||||||
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
|
||||||
throw new Exception('Handshake: wrong new_nonce_hash1');
|
throw new Exception('Handshake: wrong new_nonce_hash1');
|
||||||
}
|
}
|
||||||
@ -430,24 +431,25 @@ class AuthKeyHandler extends AckHandler
|
|||||||
|
|
||||||
$this->log->log('Auth key generated');
|
$this->log->log('Auth key generated');
|
||||||
$this->timedelta = 0;
|
$this->timedelta = 0;
|
||||||
|
|
||||||
return $res_authorization;
|
return $res_authorization;
|
||||||
} elseif ($Set_client_DH_params_answer['_'] == 'dh_gen_retry') {
|
case 'dh_gen_retry':
|
||||||
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
|
||||||
throw new Exception('Handshake: wrong new_nonce_hash_2');
|
throw new Exception('Handshake: wrong new_nonce_hash_2');
|
||||||
}
|
}
|
||||||
|
|
||||||
//repeat foreach
|
//repeat foreach
|
||||||
$this->log->log('Retrying Auth');
|
$this->log->log('Handshake: Retrying Auth');
|
||||||
} elseif ($Set_client_DH_params_answer['_'] == 'dh_gen_fail') {
|
break;
|
||||||
|
case 'dh_gen_fail':
|
||||||
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
|
if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
|
||||||
throw new Exception('Handshake: wrong new_nonce_hash_3');
|
throw new Exception('Handshake: wrong new_nonce_hash_3');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->log->log('Auth Failed');
|
$this->log->log('Handshake: Auth Failed');
|
||||||
break;
|
break 2;
|
||||||
} else {
|
default:
|
||||||
throw new Exception('Response Error');
|
throw new Exception('Response Error');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,8 @@ class CallHandler extends AuthKeyHandler
|
|||||||
$server_answer = $this->wait_for_response($int_message_id);
|
$server_answer = $this->wait_for_response($int_message_id);
|
||||||
} catch (Exception $e) {
|
} 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...');
|
$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);
|
unset($this->connection);
|
||||||
$this->sock = new \danog\MadelineProto\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']);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($server_answer == null) {
|
if ($server_answer == null) {
|
||||||
@ -74,8 +74,8 @@ class CallHandler extends AuthKeyHandler
|
|||||||
// $server_answer = $this->wait_for_response($int_message_id);
|
// $server_answer = $this->wait_for_response($int_message_id);
|
||||||
} catch (Exception $e) {
|
} 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...');
|
$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);
|
unset($this->connection);
|
||||||
$this->sock = new \danog\MadelineProto\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']);
|
||||||
continue;
|
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);
|
$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->outgoing_messages[$int_message_id]['seq_no'] = $seq_no;
|
||||||
}
|
}
|
||||||
$this->sock->send_message($message);
|
$this->connection->send_message($message);
|
||||||
|
|
||||||
return $int_message_id;
|
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()
|
public function recv_message()
|
||||||
{
|
{
|
||||||
$payload = $this->sock->read_message();
|
$payload = $this->connection->read_message();
|
||||||
if (fstat($payload)['size'] == 4) {
|
if (fstat($payload)['size'] == 4) {
|
||||||
throw new Exception('Server response error: '.abs($this->struct->unpack('<i', fread($payload, 4))[0]));
|
throw new Exception('Server response error: '.abs($this->struct->unpack('<i', fread($payload, 4))[0]));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user