diff --git a/config.php b/config.php index b2291c2..a00320e 100644 --- a/config.php +++ b/config.php @@ -1,6 +1,6 @@ query("SELECT * FROM servers"); -foreach ($result as $row) { - echo "id: " . $row['id'] . "\n"; - echo "host: " . $row['host'] . "\n"; - echo "type: " . $row['type'] . "\n"; - echo "-------------\n"; + + +class LicenseRegistration { + private $db = null; + private $m_request_body = ""; + private $m_input = FALSE; + + function __construct() + { + // Takes raw data from the request + $this->m_request_body = file_get_contents('php://input'); + $this->m_input = json_decode(($this->m_request_body)); + $this->db = new MeekroDB(DB_HOST, DB_USER, DB_PASS,DB_NAME); // from config file + //enable exception + $this->db->error_handler = false; + $this->db->nonsql_error_handler = false; + $this->db->throw_exception_on_error = true; + $this->db->throw_exception_on_nonsql_error = true; + + } + + + private function is_valid_input() + { + //if it's not a valid json + if ( $this->m_input != FALSE && + property_exists($this->m_input, "license") && + property_exists($this->m_input, "mid") + ){ + + if ( strlen($this->m_input->license) >= 10 && + strlen($this->m_input->mid) >=10 + ){ + return true; + } + + } + $this->record_possible_hack(); + return false; + } + + private function is_legit_code() + { + $code = $this->m_input->license; + $f = $this->db->query("SELECT * FROM volume WHERE code='$code'"); + return count($f) == 1 ; + } + + //record possible hack input + //save ip, date, request header, and invalid inputs + private function record_possible_hack() + { + $dump = new DumpHTTPRequestToString(); + $req = $dump->execute(); + $err = $this->db->insert("hack", array( + "ip" => $this->get_client_ip(), + "input" => $this->m_request_body, + "request" => $req + )); + } + + private function fresh_registration() + { + $config = $this->get_license_config(); + //inser it into database + $license = [ + 'code' => $this->m_input->license, + 'mid' => $this->m_input->mid, + 'seat' => 1, + 'quota' => $this->get_license_quota() , + 'config' => intVal($config["id"]), + 'enabled' => 1, + 'ip' => $this->get_client_ip() + ]; + + try { + $this->db->insert("register", $license); + $this->send_config($config, $license); + }catch (MeekroDBException $e){ + $this->send_error("Failed to add registration, please try again later" ); + } + } + + private function get_exact_match() + { + $code = $this->m_input->license; + $mid = $this->m_input->mid; + $match = $this->db->query("SELECT * FROM register WHERE code='$code' AND mid='$mid';"); + if (count($match) !=1 ){ + return FALSE; + }else{ + return $match[0]; + } + } + + private function get_license_by_code() + { + $code = $this->m_input->license; + $matches = $this->db->query("SELECT * FROM register WHERE code='$code';"); + if (count($matches) < 1 ){ + return FALSE; + }else{ + return $matches; + } + } + + private function quota_available($matches) + { + return count($matches) < $this->get_license_quota(); + + } + + private function allocate_seat($matches){ + $seat = $this->find_empty_seat($matches); + $config = $this->get_license_config(); + + $license = array( + 'code' => $this->m_input->license, + 'mid' => $this->m_input->mid, + 'seat' => $seat, + 'quota' => $this->get_license_quota() , + 'config' => intVal($config["id"]), + 'enabled' => 1, + 'ip' => $this->get_client_ip() + ); + try { + $this->db->insert("register",$license); + $this->send_config($config, $license); + }catch (MeekroDBException $e){ + $this->send_error("Allocate Seats $seat failed"); + } + + + } + + private function find_empty_seat($matches) + { + for ($i=1; $i <= $this->get_license_quota(); $i++) { + if ( $this->seats_occupied($matches, $i) ) + continue; + return $i; + } + } + + private function seats_occupied($matches, $seat) + { + for ($i=0; $i< count($matches); $i++){ + if ( $matches[$i]["seat"] == $seat ) + return true; + } + return false; + } + + //main routine + public function start_registration() + { + if (! $this->is_valid_input() ){ + $this->send_error("Sorry, your input is invalid"); + return; //stop everything + } + + if (! $this->is_legit_code()) { + $this->send_error("Sorry, Your license is not valid"); + return; + } + + //check mid see if a matched license code and mid already exist + $license = $this->get_exact_match(); + if ( $license != FALSE ){ //we found the match both license-code and machine-id + //get existing config + if ( $license['enabled'] == 1 ) { + $existing_config = $this->get_config_by_id($license["config"]); + $this->send_config($existing_config, $license); + }else{ + $this->send_error("Sorry, Your license is disabled"); + } + }else{ + $licenses = $this->get_license_by_code(); + + if ( $licenses == FALSE ) {//not found + $this->fresh_registration(); + }else{//we found, existing records + if ( $this->quota_available($licenses) ){ + $this->allocate_seat($licenses); + }else{ + $this->send_error("Sorry, Your license has been fully allocated"); + } + } + } + } + + private function get_config_by_id($id) + { + $f= $this->db->query("SELECT * FROM servers WHERE id=$id"); + return $f[0]; + } + + private function send_config($config, $license) + { + + $msg = "" ; + if ($license["quota"] >1){ + $msg = "Seat " . $license["seat"] . "/" . $license["quota"] . " has been allocated to you"; + + }else{ + $msg = "Single user license registered sucessfully"; + } + + $result= array( + "success" => true, + "type" => $config["type"], + "host" => $config["host"], + "port" => $config["port"], + "username" => $config["user"], + "password" => $config["pass"], + "license" => $license["code"], + "mid" => $license["mid"], + "proxyDNS" => true, + "enable" => true, + "errMsg" => $msg, + "link" => "https://hk-01.biukop.com/", + "linkText" => "Check My IP", + ); + $myJSON = json_encode($result); + echo $myJSON; + } + + private function send_error($msg){ + echo $msg; + die(); + } + + private function decode_pass($encrypt) + { + $buf = base64_decode($encrypt); + if ( substr($buf, -3, 2) != "#!" ) + return "invalid-encrypt"; + + $magic_digit = intVal(substr($buf, 2 , 1)); + $pass = substr($buf,5, -$magic_digit); + return $pass; + } + + private function encode_pass($pass) { + // prefix: "xxyxx"; Y is digit + $magic_digit = $this->rand_digit(); + $prefix = $this->build_prefix($magic_digit); + $suffix = $this->build_suffix($magic_digit); + //surffix yyyyy#!xx , max 9 + return base64_encode($prefix . $pass . $suffix); + } + + private function rand_char() { + $pool="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+:{}|<>?[]\;,./"; + $idx = rand(0, strlen($pool) -1 ); + return substr($pool, $idx, 1); + } + + private function rand_digit() { + return rand(3,9); + } + + private function build_prefix($magic_digit) + { + return $this->rand_char() . $this->rand_char() . + "$magic_digit" . + $this->rand_char() . $this->rand_char(); + } + + private function build_suffix($magic_digit) + { //$magic_digit >=3 + $suffix = ""; + for ($i=1; $i<= $magic_digit-3; $i++) { + $suffix .= $this->rand_char(); + } + $suffix .= "#!"; + $suffix .= $this->rand_char(); + return $suffix; + } + + private function get_client_ip () + { + //whether ip is from share internet + if (!empty($_SERVER['HTTP_CLIENT_IP'])) + { + $ip_address = $_SERVER['HTTP_CLIENT_IP']; + } + //whether ip is from proxy + elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) + { + $ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; + } + //whether ip is from remote address + else + { + $ip_address = $_SERVER['REMOTE_ADDR']; + } + return $ip_address; + } + + private function get_license_quota() + { + $code = $this->m_input->license; + $f = $this->db->query("SELECT * FROM volume WHERE code='$code'"); + return intVal($f[0]["max"]); + } + + private function get_license_config() + { + $code = $this->m_input->license; + $f = $this->db->query("SELECT * FROM servers WHERE code='$code'"); + return $f[0]; + } + + public function test_password() { + $encrypt = $this->encode_pass("superforex"); + $pass1 = $this->decode_pass($encrypt); + $pass = $this->decode_pass("Y2Q1ZDFzdXBlcmZvcmV4MTIjITU="); + if ($pass != $pass1){ + echo "wrong"; + } + } + + public function test_license_quota() { + $this->m_input = new stdClass(); + $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; + $six = $this->get_license_quota(); + if ($six != 6) + echo "wrong: license quota"; + } + + public function test_get_config() { + $this->m_input = new stdClass(); + $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; + $config = $this->get_license_config(); + } + + public function test_fresh_registration() { + $this->m_input = new stdClass(); + $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; + $this->m_input->mid = "AFDAFDSAFDSAFSDAFSAFSDA"; + $this->fresh_registration(); + + } + + public function test_licenses() { + $this->m_input = new stdClass(); + $this->m_input->license = "VOL-XDTG-ADQE-DQERG-QERFDA"; + $this->m_input->mid = "2-AFDAFDSAFDSAFSDAFSAFSDA"; + $this->start_registration(); + } + + public function test() { + $this->m_input = new stdClass(); + $this->m_input->license = "VOL"; + $this->m_input->mid = "2-AFD"; + $this->start_registration(); + } + } -$now = date(DATE_RFC2822); - -if ( $data->license != "VOL-XDTG-ADQE-DQERG-QERFDA" ) { - - echo "invalid license"; - file_put_contents(dirname(__FILE__) . "/fail.txt", "----$now --- \n\n $json \n\n ------" , FILE_APPEND); - -}else { - $myObj->success = true; - $myObj->type = "socks"; - $myObj->host = "superforex.vip.biukop.com.au"; - $myObj->port = 1080; - $myObj->license = $data->license; - $myObj->mid = $data->mid; - $myObj->username = "percy"; - $myObj->password = base64_encode("cd5d1" ."superforex" . "12#!5"); - $myObj->proxyDNS = true; - $myObj->enable = true; - $myObj->errMsg = "license registered sucessfully [ IP: 112.213.36.86 ] "; - $myObj->link = "https://hk-01.biukop.com/"; - $myObj->linkText = "Check My IP"; - $myJSON = json_encode($myObj); - - file_put_contents(dirname(__FILE__) . "/success.txt", "$now , license: $myObj->license , mid: $myObj->mid\n", FILE_APPEND); - echo $myJSON; +class DumpHTTPRequestToString { + public function execute() { + $data = sprintf( + "%s %s %s %s\n\nHTTP headers:\n", + $_SERVER['REQUEST_METHOD'], + $_SERVER['REQUEST_URI'], + $_SERVER['SERVER_PROTOCOL'], + $_SERVER['REMOTE_ADDR'] + ); + foreach ($this->getHeaderList() as $name => $value) { + $data .= $name . ': ' . $value . "\n"; + } + $data .= "\nRequest body:\n" . file_get_contents('php://input'); + return $data; + } + private function getHeaderList() { + $headerList = []; + foreach ($_SERVER as $name => $value) { + if (preg_match('/^HTTP_/',$name)) { + // convert HTTP_HEADER_NAME to Header-Name + $name = strtr(substr($name,5),'_',' '); + $name = ucwords(strtolower($name)); + $name = strtr($name,' ','-'); + // add to list + $headerList[$name] = $value; + } + } + return $headerList; + } } + +$bb = new LicenseRegistration(); +$bb->start_registration(); +//$bb->test(); + ?> diff --git a/myheader.txt b/myheader.txt new file mode 100644 index 0000000..8f41e57 --- /dev/null +++ b/myheader.txt @@ -0,0 +1,7 @@ +----- +Cache-Control: no-cache +Pragma: no-cache +Cookie: start_debug=1; +Content-Length: 62 +Content-Type: application/json +Host: license.biukop.com.au