Created
December 23, 2017 12:36
-
-
Save hu55a1n1/7d40e4ff17d8f65bf35f6146d3e55e27 to your computer and use it in GitHub Desktop.
CLI tool for automatic discovery and bulk provisioning of Grandstream IP phones
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function to_str($obj) { | |
ob_start(); | |
var_dump($obj); | |
return ob_get_clean(); | |
} | |
function str_btw($string, $start, $end){ | |
$string = ' ' . $string; | |
$ini = strpos($string, $start); | |
if ($ini == 0) return ''; | |
$ini += strlen($start); | |
$len = strpos($string, $end, $ini) - $ini; | |
return substr($string, $ini, $len); | |
} | |
function logtofile($string) { | |
global $logfile; | |
fwrite($logfile, $string); | |
} | |
function http_get($context, $url) { | |
curl_setopt($context, CURLOPT_CUSTOMREQUEST, 'GET'); | |
curl_setopt($context, CURLOPT_URL, $url); | |
logtofile("GET: \n" . $url . "\n"); | |
return curl_exec($context); | |
} | |
function http_post($context, $url, $data) { | |
curl_setopt($context, CURLOPT_CUSTOMREQUEST, 'POST'); | |
curl_setopt($context, CURLOPT_URL, $url); | |
curl_setopt($context, CURLOPT_POSTFIELDS, http_build_query($data)); | |
logtofile("POST: \n" . $url . "?" . http_build_query($data) . "\n"); | |
return curl_exec($context); | |
} | |
function milliseconds() { | |
$mt = explode(' ', microtime()); | |
return ((int)$mt[1]) * 1000 + ((int)round($mt[0] * 1000)); | |
} | |
function ping($domain, $timeout=2){ | |
$starttime = microtime(true); | |
$file = @fsockopen ($domain, 80, $errno, $errstr, $timeout); | |
$stoptime = microtime(true); | |
$status = 0; | |
if (!$file) $status = -1; // Site is down | |
else { | |
fclose($file); | |
$status = ($stoptime - $starttime) * 1000; | |
$status = floor($status); | |
} | |
return ($status !== -1); | |
} | |
function ip_range($start, $end) { | |
$start = ip2long($start); | |
$end = ip2long($end); | |
return array_map('long2ip', range($start, $end) ); | |
} | |
function config_gs_3240($context, $ip, $pwd, $npwd) { | |
curl_setopt($context, CURLOPT_COOKIEJAR, '/tmp/cookies.txt'); | |
curl_setopt($context, CURLOPT_COOKIEFILE, '/tmp/cookies.txt'); | |
curl_setopt($context, CURLOPT_COOKIE, 'phonecookie="4e5d67ce"; type=admin; Version="1"; Max-Age=900; needchange=1; ver=1.0.3.154; iconized_tooltipdiv=true'); | |
$content = http_get($context, 'http://' . $ip . '/manager?action=loginrealm&time=' . milliseconds()); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$realm = $body; | |
logtofile(to_str($realm)); | |
$content = http_get($context, 'http://' . $ip . '/manager?action=login&Username=admin&Secret=' . md5('admin:' . $realm . ':' . $pwd) . '&time=' . milliseconds()); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
logtofile(to_str($content)); | |
if (strpos($body, 'Response=Success') === false) { | |
echo "Error: Failed to login!\n"; | |
return; | |
} | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=status&time=' . milliseconds()); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$sip = str_btw($body, "Account_0_NO=", "\r\n"); | |
logtofile($sip); | |
if ($sip === false) { | |
echo "Error: Failed to get sip extension!\n"; | |
return; | |
} | |
usleep(2000); | |
echo "."; | |
logtofile("\n########################\n[" . $sip . "]\n########################\n"); | |
echo "\nInfo: Extension: " . $sip . "\n"; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=put&flag=1&var-0000=271&val-0000=1&var-0001=270&val-0001=' . $sip . '&var-0002=47&val-0002=' . '192.168.1.200' /* sip server */ . '&var-0003=2312&val-0003=&var-0004=35&val-0004=' . $sip . '&var-0005=36&val-0005=' . $sip . '&var-0006=33&val-0006=&var-0007=3&val-0007=' . $sip . '&var-0008=2380&val-0008=0&var-0009=63&val-0009=0&var-0010=34&val-0010=' . $sip /* password */ . '&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=needapply&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=put&flag=2&var-0000=30&val-0000=us.pool.ntp.org&var-0001=144&val-0001=1&var-0002=143&val-0002=1&var-0003=246&val-0003=MTZ%2B6MDT%2B5%2CM4.1.0%2CM11.1.0&var-0004=122&val-0004=1&var-0005=102&val-0005=1&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=savetimeset&timezone=Asia/Dubai&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=needapply&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=put&flag=0&var-0000=238&val-0000=0&var-0001=6767&val-0001=1&var-0002=212&val-0002=2&var-0003=192&val-0003=fm.grandstream.com%2Fgs&var-0004=237&val-0004=fm.grandstream.com%2Fgs&var-0005=232&val-0005=&var-0006=233&val-0006=&var-0007=234&val-0007=&var-0008=235&val-0008=&var-0009=20713&val-0009=0&var-0010=6774&val-0010=fm.grandstream.com%2Fgs&var-0011=6775&val-0011=1&var-0012=6776&val-0012=&var-0013=6777&val-0013=&var-0014=6778&val-0014=0&var-0015=22030&val-0015=0&var-0016=1407&val-0016=1&var-0017=145&val-0017=1&var-0018=1411&val-0018=1&var-0019=22053&val-0019=1&var-0020=4428&val-0020=0&var-0021=1549&val-0021=1&var-0022=22032&val-0022=0&var-0023=22033&val-0023=&var-0024=1414&val-0024=1&var-0025=194&val-0025=0&var-0026=1357&val-0026=2&var-0027=240&val-0027=0&var-0028=285&val-0028=1&var-0029=286&val-0029=1&var-0030=193&val-0030=10080&var-0031=1359&val-0031=&var-0032=6768&val-0032=&var-0033=6769&val-0033=&var-0034=1360&val-0034=&var-0035=1361&val-0035=&var-0036=40&val-0036=5060&var-0037=413&val-0037=5062&var-0038=513&val-0038=5064&var-0039=613&val-0039=5066&var-0040=1713&val-0040=5068&var-0041=1813&val-0041=5070&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=setprop&type=3&value=1&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=needapply&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=applypvalue&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=put&flag=0&var-0000=900&val-0000=0&var-0001=29605&val-0001=0&var-0002=901&val-0002=80&var-0003=2&val-0003=' . $npwd . '&var-0004=196&val-0004=123&var-0005=276&val-0005=0&var-0006=20702&val-0006=&var-0007=20701&val-0007=&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=checkpwd&Username=admin&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
} | |
function config_gs_1628($context, $ip, $pwd, $npwd) { | |
curl_setopt($context, CURLOPT_COOKIEJAR, '/tmp/cookies.txt'); | |
curl_setopt($context, CURLOPT_COOKIEFILE, '/tmp/cookies.txt'); | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/dologin', array('username' => 'admin', 'password' => $pwd)); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$body_json = json_decode($body, true); | |
if (!array_key_exists('body', $body_json) | |
|| !isset($body_json['body']['sid'])) { | |
echo "Error: Failed to login!\n"; | |
return; | |
} | |
$sid = $body_json['body']['sid']; | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
curl_setopt($context, CURLOPT_COOKIE, 'session-role=admin; session-identity=' . $sid); | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api.values.get', array('sid' => $sid, 'request' => 'vendor_fullname:Pphone_model:P271:P270:P47:P2312:P48:P2333:P2375:P35:P36:P3:P33:P2380')); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (!is_array($response) | |
|| !array_key_exists('body', $response) | |
|| !isset($response['body']['P35'])) { | |
echo "Error: Failed to get sip extension!\n"; | |
return; | |
} | |
$sip = $response['body']['P35']; | |
logtofile("\n########################\n[" . $sip . "]\n########################\n"); | |
echo "\nInfo: Extension: " . $sip . "\n"; | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api.values.post', array('sid' => $sid, 'P270' => $sip, 'P64' => 'TZR-4', 'P143' => '0', 'P1357' => '2')); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api-phone_operation', array('passcode' => $pwd, 'cmd' => 'extend')); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api-change_password', array('sid' => $sid, 'olduser' => '', 'P196' => '', ':confirmUserPwd' => '', 'oldadmin' => $pwd, 'P2' => $npwd, ':confirmAdminPwd' => $npwd)); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api-phone_operation', array('cmd' => 'extend', 'arg' => '', 'sid' => $sid)); | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
} | |
function is_gs_3240($context, $ip) { | |
curl_setopt($context, CURLOPT_COOKIEJAR, '/tmp/cookies.txt'); | |
curl_setopt($context, CURLOPT_COOKIEFILE, '/tmp/cookies.txt'); | |
curl_setopt($context, CURLOPT_COOKIE, 'phonecookie="4e5d67ce"; type=admin; Version="1"; Max-Age=900; needchange=1; ver=1.0.3.154; iconized_tooltipdiv=true'); | |
$content = http_get($context, 'http://' . $ip . '/manager?action=loginrealm&time=' . milliseconds()); | |
logtofile(to_str($content)); | |
if (curl_getinfo($context, CURLINFO_HTTP_CODE) == 200) { | |
return true; | |
} | |
return false; | |
} | |
function is_gs_1628($context, $ip, $pwd) { | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/dologin', array('username' => 'admin', 'password' => $pwd)); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (array_key_exists('body', $response) | |
&& isset($response['body']['sid'])) { | |
$sid = $response['body']['sid']; | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
curl_setopt($context, CURLOPT_COOKIE, 'session-role=admin; session-identity=' . $sid); | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api.values.get', array('sid' => $sid, 'request' => 'vendor_fullname:Pphone_model:P271:P270:P47:P2312:P48:P2333:P2375:P35:P36:P3:P33:P2380')); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (is_array($response) | |
&& array_key_exists('body', $response) | |
&& isset($response['body']['Pphone_model']) | |
&& ($response['body']['Pphone_model'] === 'GXP1628')) { | |
return true; | |
} | |
} | |
return false; | |
} | |
function is_programmed_1628($context, $ip, $npwd) { | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/dologin', array('username' => 'admin', 'password' => $npwd)); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (is_array($response) | |
&& array_key_exists('response', $response) | |
&& $response['response'] === 'success') { | |
return true; | |
} | |
return false; | |
} | |
function is_gs_2170($context, $ip, $pwd) { | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/dologin', array('username' => 'admin', 'password' => $pwd)); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (array_key_exists('body', $response) | |
&& isset($response['body']['sid'])) { | |
$sid = $response['body']['sid']; | |
logtofile(to_str($content)); | |
usleep(2000); | |
echo "."; | |
curl_setopt($context, CURLOPT_COOKIE, 'session-role=admin; session-identity=' . $sid); | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/api.values.get', array('sid' => $sid, 'request' => 'vendor_fullname:Pphone_model:P271:P270:P47:P2312:P48:P2333:P2375:P35:P36:P3:P33:P2380')); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (is_array($response) | |
&& array_key_exists('body', $response) | |
&& isset($response['body']['Pphone_model']) | |
&& ($response['body']['Pphone_model'] === 'GXP2170')) { | |
return true; | |
} | |
} | |
return false; | |
} | |
function is_programmed_2170($context, $ip, $npwd) { | |
$content = http_post($context, 'http://' . $ip . '/cgi-bin/dologin', array('username' => 'admin', 'password' => $npwd)); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$response = json_decode($body, true); | |
logtofile(to_str($content)); | |
if (is_array($response) | |
&& array_key_exists('response', $response) | |
&& $response['response'] === 'success') { | |
return true; | |
} | |
return false; | |
} | |
function is_programmed_3240($context, $ip, $npwd) { | |
$content = http_get($context, 'http://' . $ip . '/manager?action=loginrealm&time=' . milliseconds()); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
$realm = $body; | |
$content = http_get($context, 'http://' . $ip . '/manager?action=login&Username=admin&Secret=' . md5('admin:' . $realm . ':' . $npwd) . '&time=' . milliseconds()); | |
$header_size = curl_getinfo($context, CURLINFO_HEADER_SIZE); | |
$header = substr($content, 0, $header_size); | |
$body = substr($content, $header_size); | |
logtofile(to_str($content)); | |
if (strpos($body, 'Response=Success') !== false) { | |
return true; | |
} | |
return false; | |
} | |
// ====================================================== | |
// ====================================================== | |
// ====================================================== | |
// ====================================================== | |
// $ip_start = '192.168.1.2'; | |
// $ip_end = '192.168.1.100'; | |
$pwd = 'admin'; | |
$npwd = 'admin1234'; | |
$logfile = fopen("logs", "w"); | |
$ips = ip_range($ip_start, $ip_end); | |
if (!is_array($ips)) { | |
echo "Error: Invalid range!\n"; | |
exit(); | |
} | |
// ---- OR ---- | |
// Supply range manually | |
// $ips = array(); | |
foreach ($ips as $ip) { | |
$context = curl_init(); | |
curl_setopt($context, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($context, CURLOPT_TIMEOUT, 3); | |
curl_setopt($context, CURLOPT_HEADER, 1); | |
echo "Info: [" . $ip . "] --- "; | |
logtofile("\n------------------------\n[" . $ip . "]\n------------------------\n"); | |
if (ping($ip) === true) { | |
echo "[ Online ]\n"; | |
if (is_gs_1628($context, $ip, $pwd) === true) { | |
echo "Info: Model 1628\n"; | |
if (is_programmed_1628($context, $ip, $npwd) === true) { | |
echo "Warning: Device already programmed \n"; | |
goto END; | |
} else { | |
echo "Info: Configuring."; | |
config_gs_1628($context, $ip, $pwd, $npwd); | |
echo (is_programmed_1628($context, $ip, $npwd) === true) ? " Result: [ Success ]" : " Result: [ Failed ]"; | |
echo "\n"; | |
} | |
} else if (is_gs_3240($context, $ip) === true) { | |
echo "Info: Model 3240\n"; | |
if (is_programmed_3240($context, $ip, $npwd) === true) { | |
echo "Warning: Device already programmed \n"; | |
goto END; | |
} else { | |
echo "Info: Configuring."; | |
config_gs_3240($context, $ip, $pwd, $npwd); | |
echo (is_programmed_3240($context, $ip, $npwd) === true) ? " Result: [ Success ]" : " Result: [ Failed ]"; | |
echo "\n"; | |
} | |
} else if (is_gs_2170($context, $ip, $pwd) === true) { | |
echo "Info: Model 2170\n"; | |
if (is_programmed_2170($context, $ip, $npwd) === true) { | |
echo "Warning: Device already programmed \n"; | |
goto END; | |
} else { | |
echo "Info: Configuring."; | |
config_gs_1628($context, $ip, $pwd, $npwd); | |
echo (is_programmed_2170($context, $ip, $npwd) === true) ? " Result: [ Success ]" : " Result: [ Failed ]"; | |
echo "\n"; | |
} | |
} else if (is_programmed_1628($context, $ip, $npwd) === true) { | |
echo "Info: Model 1628\n"; | |
echo "Warning: Device already programmed \n"; | |
} else if (is_programmed_2170($context, $ip, $npwd) === true) { | |
echo "Info: Model 2170\n"; | |
echo "Warning: Device already programmed \n"; | |
} | |
else { | |
echo "Info: Model Unknown!\n"; | |
} | |
} else { | |
echo "[ Offline ]\n"; | |
} | |
END: | |
echo "\n"; | |
curl_close($context); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment