Skip to content

Instantly share code, notes, and snippets.

@hu55a1n1
Created December 23, 2017 12:36
Show Gist options
  • Save hu55a1n1/7d40e4ff17d8f65bf35f6146d3e55e27 to your computer and use it in GitHub Desktop.
Save hu55a1n1/7d40e4ff17d8f65bf35f6146d3e55e27 to your computer and use it in GitHub Desktop.
CLI tool for automatic discovery and bulk provisioning of Grandstream IP phones
<?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