From ed0f9c079bbefd3ee241f01cb4d3b3e7039e2d95 Mon Sep 17 00:00:00 2001 From: William Kibirango Date: Sat, 30 Sep 2017 12:16:41 +0300 Subject: [PATCH] added files --- configure_hotspot.php | 209 ++++++++++++++++++++ disabler.php | 8 + general_settings.php | 241 +++++++++++++++++++++++ hotspots.php | 210 ++++++++++++++++++++ imgback.jpg | Bin 0 -> 65514 bytes index.php | 10 + login.php | 145 ++++++++++++++ logout.php | 5 + make_vouchers.php | 97 ++++++++++ menu.php | 17 ++ remove_router.php | 28 +++ routeros_api.class.php | 425 +++++++++++++++++++++++++++++++++++++++++ routers.php | 251 ++++++++++++++++++++++++ script.js | 2 + setup_one_hotspot.php | 112 +++++++++++ tutorial.php | 119 ++++++++++++ upload_Logo.php | 85 +++++++++ upload_logo.php | 106 ++++++++++ vouchers.php | 176 +++++++++++++++++ 19 files changed, 2246 insertions(+) create mode 100755 configure_hotspot.php create mode 100755 disabler.php create mode 100755 general_settings.php create mode 100755 hotspots.php create mode 100755 imgback.jpg create mode 100755 index.php create mode 100755 login.php create mode 100755 logout.php create mode 100755 make_vouchers.php create mode 100755 menu.php create mode 100755 remove_router.php create mode 100755 routeros_api.class.php create mode 100755 routers.php create mode 100755 script.js create mode 100755 setup_one_hotspot.php create mode 100755 tutorial.php create mode 100755 upload_Logo.php create mode 100755 upload_logo.php create mode 100755 vouchers.php diff --git a/configure_hotspot.php b/configure_hotspot.php new file mode 100755 index 0000000..55bd3c4 --- /dev/null +++ b/configure_hotspot.php @@ -0,0 +1,209 @@ + 251) { + $final_num_users = 251; + } else if ($num_users < 10) { + $final_num_users = 10; + } else { + $final_num_users = $num_users; + } + return $final_num_users; +}*/ + +function checkOctet($octet) { + $final_octet = 0; + if ($octet > 255) { + $final_octet = 255; + } else if ($octet < 0) { + $final_octet = 0; + } else { + $final_octet = $octet; + } + return $final_octet; +} + +function multiexplode ($delimiters, $string) { + $ready = str_replace($delimiters, $delimiters[0], $string); + $launch = explode($delimiters[0], $ready); + return $launch; +} + +function genPool($oct1, $oct2, $oct3, $oct4, $mask) { + $oct = 3; + $du = 24; + $dl = 16; + $first_host = ""; + $last_host = ""; + + $pool = ""; + #find the octet we are working in + if ($mask >= 16 and $mask <= 24) { + $oct = 3; + $du = 24; + $dl = 16; + } else if ($mask >= 24 and $mask < 32) { + $oct = 4; + $du = 32; + $dl = 24; + } + #get the subnet increment + $inc = 2 ** ($du - $mask); + + #get the number of hosts + $hosts = (2 ** (32 - $mask)) - 2; + + #validate network address and get the pool range + if ($oct == 3 and ($oct3 % $inc == 0)) { + $serv = "$oct1.$oct2.$oct3.1"; + $first_host = "$oct1.$oct2.$oct3.2"; + $last_host = "$oct1.$oct2." . ($oct3 + ($inc - 1)) . ".254"; + } else if ($oct == 4 and ($oct4 % $inc == 0)) { + $serv = "$oct1.$oct2.$oct3." . ($oct4 + 1); + $first_host = "$oct1.$oct2.$oct3." . ($oct4 + 2); + $last_host = "$oct1.$oct2.$oct3." . (($oct4 + $inc) - 2); + } +# else { +# echo "bad network\n"; +# exit; +# } + + #output results + return array("pool" => "$first_host-$last_host", "server" => $serv); +} + +function setup($router_addr, $username, $password) { + $API = new RouterosAPI(); + $API->debug = true; + $poolName = randomString() . randomString() . randomString(); + $dhcpName = randomString() . randomString() . randomString(); + $profName = randomString() . randomString() . randomString(); + + $net = $_POST["hs_net"]; + $octs = multiexplode(array(".", "/"), $net); + $mask = $octs[4]; + + $pool_array = genPool($octs[0], $octs[1], $octs[2], $octs[3], $mask); + $serv = $pool_array["server"]; + $pool = $pool_array["pool"]; + + if ($API->connect($router_addr, $username, $password)) { + + $API->write("/interface/wireless/set", false); + $API->write("=.id=*6", false); + $API->write("=ssid=" . $_POST["hs_ssid"], false); + $API->write("=mode=ap-bridge", false); + $API->write("=wireless-protocol=802.11", false); + $API->write("=disabled=no"); + $READ = $API->read(false); +/* + $API->write("/interface/bridge/add", false); + $API->write("=name=bridge-hotspot", false); + $API->write("=arp=enabled", false); + $API->write("protocol-mode=stp", false); + $API->write("=disabled=no"); + $READ = $API->read(false); + + $API->write("/interface/bridge/port/add", false); + $API->write("=interface=wlan1", false); + $API->write("=bridge=bridge-hotspot"); + $READ = $API->read(false); +*/ + $API->write("/ip/address/add", false); + $API->write("=address=$serv/$mask", false); + $API->write("=interface=wlan1"); + $READ = $API->read(false); + + $API->write("/ip/pool/add", false); + $API->write("=name=" . $poolName, false); + $API->write("=ranges=$pool"); + $READ = $API->read(false); + + $API->write("/ip/dhcp-server/add", false); + $API->write("=name=" . $dhcpName, false); + $API->write("=interface=wlan1", false); + $API->write("=address-pool=" . $poolName, false); + $API->write("=lease-time=3d", false); + $API->write("=disabled=no"); + $READ = $API->read(false); + + $API->write("/ip/dhcp-server/network/add", false); + $API->write("=address=$net", false); + $API->write("=gateway=$serv"); + $READ = $API->read(false); + + $API->write("/routing/ospf/network/add", false); + $API->write("=network=$net", false); + $API->write("=area=backbone"); + $READ = $API->read(false); + + $API->write("/ip/hotspot/profile/add", false); + $API->write("=name=" . $profName, false); + $API->write("=dns-name=" . $_POST["hs_dns"], false); + $API->write("=hotspot-address=$serv", false); + $API->write("=use-radius=yes", false); + $API->write("=radius-accounting=yes", false); + $API->write("=login-by=http-pap"); + $READ = $API->read(false); + + $API->write("/ip/hotspot/add", false); + $API->write("=profile=" . $profName, false); + $API->write("=name=" . $_POST["hs_ssid"], false); + $API->write("=address-pool=" . $poolName, false); + $API->write("=interface=wlan1", false); + $API->write("=addresses-per-mac=1", false); + $API->write("=disabled=no"); + $READ = $API->read(false); + +// $API->write("/ip/firewall/nat/set", false); +// $API->write("=.id=*1", false); +// $API->write("=src-address=$net"); +// $READ = $API->read(false); + + $conn = new mysqli("localhost", "mgt", "admin_mgt", "manager_db"); + if ($conn->connect_error) { + die("Connection failed: " . $conn->connect_error); + } + $sql = "select * from radlogin where id = 1"; + $result = $conn->query($sql); + $row = $result->fetch_assoc(); + + $API->write("/radius/add", false); + $API->write("=address=" . $row["radaddress"], false); + $API->write("=secret=" . $row["radsecret"], false); + $API->write("=service=hotspot", false); + $API->write("=disabled=no"); + $READ = $API->read(false); + + $API->write("/radius/incoming/set", false); + $API->write("=accept=yes"); + $READ = $API->read(false); + + $conn->close(); + } +} + +function randomString() { + $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $randString = ''; + for ($i = 0; $i < 10; $i++) { + $randString = $characters[rand(0, strlen($characters))]; + } + return $randString; +} + +function checkOctet_bool($octet) { + $octet_ok = TRUE; + if ($octet > 255 or $octet < 0) { + $octet_ok = FALSE; + } else { + $octet = TRUE; + } + return $octet_ok; +} + +?> + diff --git a/disabler.php b/disabler.php new file mode 100755 index 0000000..9a992f3 --- /dev/null +++ b/disabler.php @@ -0,0 +1,8 @@ + + + diff --git a/general_settings.php b/general_settings.php new file mode 100755 index 0000000..05b9c1a --- /dev/null +++ b/general_settings.php @@ -0,0 +1,241 @@ + + + + + + + + +

+connect_error) { + die("Connection failed: " . $conn_1->connect_error); + } + + $sql_1 = "update login set username=\"$new_username\",". + " password=\"$new_password\" where id = 1"; + $sql_2 = "select * from login where id = 1"; + $sql_3 = "update radlogin set radaddress=\"$new_radaddr\",". + " radsecret=\"$new_radsecret\" where id = 1"; + + #get the old credentials + $result = $conn_1->query($sql_2); + $row = $result->fetch_assoc(); + $db_username = $row["username"]; + $db_password = $row["password"]; + + #validate the user with the credentials + if ($old_username === $db_username and $old_password === $db_password) { + if ($conn_1->query($sql_1) === FALSE) { + die("Query \"$sql_1\" failed!"); + } else { + #change the credentials of the routers + $conn_2 = new mysqli($servername, "radius", "radpass", "radius"); + if ($conn_2->connect_error) { + die("Connection failed: " . $conn_2->connect_error); + } + $sql_4 = "select nasname from nas"; + $result_2 = $conn_2->query($sql_4); + if ($result_2->num_rows > 0) { + $API = new RouterosAPI(); + $API->debug = true; # hope this doesn't mess stuff up + while ($row = $result_2->fetch_assoc()) { + if ($API->connect($row["nasname"], $old_username, $old_password)) { + $API->write("/user/set", false); + $API->write("=.id=*1", false); + $API->write("=name=$new_username", false); + $API->write("=password=$new_password"); + $READ = $API->read(false); + } + } + $msg_1 = "

+ + Credentials saved +


"; + } else { + $msg_1 = "

+ + Credentials saved + + but no routers added +


"; + } + $conn_2->close(); + } + if ($conn_1->query($sql_3) === FALSE) { + die("Query \"$sql_3\" failed!"); + } else { + $msg_2 = "

+ RADIUS settings saved


"; + } + } + + $conn_1->close(); + +} +?> +

+ +

GENERAL SETTINGS

+
+
+
+RADIUS + +

+ +

+
+ +
+ADMIN + +

+ +

+
+ +
+CONFIRM YOUR IDENTITY + +

+ +

+

+
+ + +
+
+CUSTOM LOGO + +

+

+
+ + +
+ + + + + + diff --git a/hotspots.php b/hotspots.php new file mode 100755 index 0000000..bd3a967 --- /dev/null +++ b/hotspots.php @@ -0,0 +1,210 @@ + + + + + + + + +

+= 22 and $octs[4] <= 29 + and checkOctet_bool($octs[0]) and checkOctet_bool($octs[1]) + and checkOctet_bool($octs[2]) and checkOctet_bool($octs[3])) { + $servername = "localhost"; + $username = "radius"; + $password = "radpass"; + $dbname = "radius"; + + $conn_1 = new mysqli($servername, $username, $password, $dbname); + $conn_2 = new mysqli($servername, "mgt", "admin_mgt", "manager_db"); + if ($conn_1->connect_error or $conn_2->connection_error) { + die("Connection failed: " . $conn_1->connect_error . " " + .$conn_2->connection_error); + } + + $sql_1 = "select nasname from nas"; + $result = $conn_1->query($sql_1); + + $sql_2 = "select * from login where id = 1"; + $login = ($conn_2->query($sql_2))->fetch_assoc(); + + if ($result->num_rows > 0) { + while($row = $result->fetch_assoc()) { + setup($row["nasname"], $login["username"], $login["password"]); + } + } + $conn_1->close(); + $conn_2->close(); + } else { + //$msg = "

+ // Invalid subnet mask or network

"; + } +} +?> +

+ +
+

HOTSPOTS

+
+
+SETTINGS FOR ALL HOTSPOTS + +

+ + +

+ +

+ +
+ + +
+
+SETTINGS FOR ONE HOTSPOT + +

+ + + +

+ +

+ +

+ +
+ + +
+ +HOTSPOT CREATED WITH THE FOLLOWING SETTINGS"; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + echo "
HOTSPOT NAMEHOTSPOT ADDRESS
" . $_POST["hs_ssid"] . "" . $_POST["hs_net"] . "
"; + + echo ' + + + + + diff --git a/imgback.jpg b/imgback.jpg new file mode 100755 index 0000000000000000000000000000000000000000..b47813b83ee776d3577cc93b0a4ff0cd06afccde GIT binary patch literal 65514 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

9;n9Q{`;!K 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

LrNnF+CHtfglMy; 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 +require 'voucher.php'; +Congratulation! You have logged into password protected page. Click here to Logout. diff --git a/login.php b/login.php new file mode 100755 index 0000000..ae96489 --- /dev/null +++ b/login.php @@ -0,0 +1,145 @@ + + + + + + '123456','username1' => 'password1','username2' => 'password2'); + $username = "mgt"; + $password = "admin_mgt"; + $server = "localhost"; + $db = "manager_db"; + + $conn = new mysqli($server, $username, $password, $db); + + if ($conn->connect_error) { + die("Connection failed: " . $conn->conncet_error); + } + + $sql_1 = "select * from login where id = 1"; + $result = $conn->query($sql_1); + $row = $result->fetch_assoc(); + $db_username = $row["username"]; + $db_password = $row["password"]; + + /* Check and assign submitted Username and Password to new variable */ + $Username = isset($_POST['Username']) ? $_POST['Username'] : ''; + $Password = isset($_POST['Password']) ? $_POST['Password'] : ''; + + /* Check Username and Password existence in defined array */ + if ($Username === $db_username & $Password === $db_password){ + /* Success: Set session variables and redirect to Protected page */ + + $_SESSION['UserData']['Username']=$db_password; + + header("location:routers.php"); + + exit; + } else { + /*Unsuccessful attempt: Set error message */ + $msg="Invalid Login Details"; + } + } +?> + +Company Logo + +

WELCOME TO NETFACE

+

Your configurations partner

+
+
+
+LOGIN DETAILS + + + + + + + + + + + + + + + + + + + +
Username
Password
+
+ +
+
+ + + diff --git a/logout.php b/logout.php new file mode 100755 index 0000000..a94e6b6 --- /dev/null +++ b/logout.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/make_vouchers.php b/make_vouchers.php new file mode 100755 index 0000000..3a0cc7e --- /dev/null +++ b/make_vouchers.php @@ -0,0 +1,97 @@ +connect_error) { + die("Connection failed: " . $conn->connect_error); + } + + #make vouchers + for ($x = 0; $x < $num_vouchers; $x++) { + $randu = substr(md5(microtime()), rand(0, 26), 5); + $voucher_login = $voucher_prefix . "--" . $randu; + $randpw = substr(md5(microtime()), rand(0, 26), 5); + $voucher_pw = $randpw; + + $sql_1 = "insert into radcheck (username, attribute, op, value) values " . + "(\"$voucher_login\", \"MD5-Password\", \":=\"," . + " MD5(\"$voucher_pw\"))"; + if ($conn->query($sql_1) == FALSE) { + echo "Error :" . $sql_1 . "\n" . $conn->error . "\n"; + } + + $vouchers_str = $vouchers_str . + "Username: " . $voucher_login . "\nPassword: " + . $voucher_pw . "\n\n"; + + $sql_2 = "insert into radusergroup (username, groupname, priority)" . + " values (\"$voucher_login\", \"$group_name\", \"1\")"; + if ($conn->query($sql_2) == FALSE) { + echo "Error :" . $sql_2 . "\n" . $conn->error . "\n"; + } + + } + + $sql_groupcheck = "select attribute from radgroupcheck " . + "where groupname = \"$group_name\""; + $sql_groupreply = "select attribute from radgroupreply " . + "where groupname = \"$group_name\""; + $result_1 = $conn->query($sql_groupcheck); + $result_2 = $conn->query($sql_groupreply); + + if ($result_1->num_rows == 0 && $result_2->num_rows == 0) { + #create group attributes + + #in radgroupcheck + $sql_3 = "insert into radgroupcheck (groupname, attribute, op, value)" . + " values (\"$group_name\", \"Max-All-Session\"," . + " \":=\", \"$time_limit\")"; + if ($conn->query($sql_3) == FALSE) { + echo "Error :" . $sql_3 . "\n" . $conn->error . "\n"; + } + + #in radgroupreply + $sql_4 = "insert into radgroupreply (groupname, attribute, op, value)" . + " values (\"$group_name\", \"Session-Timeout\"," . + " \":=\", \"$time_limit\"), " . + "(\"$group_name\", \"Framed-Compression\"," . + " \":=\", \"Van-Jacobsen-TCP-IP\"), " . + "(\"$group_name\", \"Framed-Protocol\"," . + " \":=\", \"PPP\"), " . + "(\"$group_name\", \"Framed-MTU\"," . + " \":=\", \"1500\"), " . + "(\"$group_name\", \"Service-Type\"," . + " \":=\", \"Login-User\")"; + if ($conn->query($sql_4) == FALSE) { + echo "Error :" . $sql_4 . "\n" . $conn->error . "\n"; + } + } + + $conn->close(); + + #write file + echo "$vouchers_str"; +} + +?> diff --git a/menu.php b/menu.php new file mode 100755 index 0000000..44018bc --- /dev/null +++ b/menu.php @@ -0,0 +1,17 @@ + + + + + '; +?> + + diff --git a/remove_router.php b/remove_router.php new file mode 100755 index 0000000..32b6be1 --- /dev/null +++ b/remove_router.php @@ -0,0 +1,28 @@ +connect_error) { + die("Connection failed: " . $conn->connect_error); + } + + $sql_1 = "delete from nas where nasname = \"$addr\""; + if ($conn->query($sql_1) == FALSE) { + echo "Error: " . $sql_1 . "\h" . $conn->error . "\n"; + } else { + header("Location: routers.php"); + //echo "Router removed!"; + } + + $conn->close(); +} +?> + + diff --git a/routeros_api.class.php b/routeros_api.class.php new file mode 100755 index 0000000..f1e5153 --- /dev/null +++ b/routeros_api.class.php @@ -0,0 +1,425 @@ +debug) { + echo $text . "\n"; + } + } + + + /** + * + * + * @param string $length + * + * @return void + */ + public function encodeLength($length) + { + if ($length < 0x80) { + $length = chr($length); + } elseif ($length < 0x4000) { + $length |= 0x8000; + $length = chr(($length >> 8) & 0xFF) . chr($length & 0xFF); + } elseif ($length < 0x200000) { + $length |= 0xC00000; + $length = chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); + } elseif ($length < 0x10000000) { + $length |= 0xE0000000; + $length = chr(($length >> 24) & 0xFF) . chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); + } elseif ($length >= 0x10000000) { + $length = chr(0xF0) . chr(($length >> 24) & 0xFF) . chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); + } + + return $length; + } + + + /** + * Login to RouterOS + * + * @param string $ip Hostname (IP or domain) of the RouterOS server + * @param string $login The RouterOS username + * @param string $password The RouterOS password + * + * @return boolean If we are connected or not + */ + public function connect($ip, $login, $password) + { + for ($ATTEMPT = 1; $ATTEMPT <= $this->attempts; $ATTEMPT++) { + $this->connected = false; + $PROTOCOL = ($this->ssl ? 'ssl://' : '' ); + $context = stream_context_create(array('ssl' => array('ciphers' => 'ADH:ALL', 'verify_peer' => false, 'verify_peer_name' => false))); + $this->debug('Connection attempt #' . $ATTEMPT . ' to ' . $PROTOCOL . $ip . ':' . $this->port . '...'); + $this->socket = @stream_socket_client($PROTOCOL . $ip.':'. $this->port, $this->error_no, $this->error_str, $this->timeout, STREAM_CLIENT_CONNECT,$context); + if ($this->socket) { + socket_set_timeout($this->socket, $this->timeout); + $this->write('/login'); + $RESPONSE = $this->read(false); + if (isset($RESPONSE[0]) && $RESPONSE[0] == '!done') { + $MATCHES = array(); + if (preg_match_all('/[^=]+/i', $RESPONSE[1], $MATCHES)) { + if ($MATCHES[0][0] == 'ret' && strlen($MATCHES[0][1]) == 32) { + $this->write('/login', false); + $this->write('=name=' . $login, false); + $this->write('=response=00' . md5(chr(0) . $password . pack('H*', $MATCHES[0][1]))); + $RESPONSE = $this->read(false); + if (isset($RESPONSE[0]) && $RESPONSE[0] == '!done') { + $this->connected = true; + break; + } + } + } + } + fclose($this->socket); + } + sleep($this->delay); + } + + if ($this->connected) { + $this->debug('Connected...'); + } else { + $this->debug('Error...'); + } + return $this->connected; + } + + + /** + * Disconnect from RouterOS + * + * @return void + */ + public function disconnect() + { + // let's make sure this socket is still valid. it may have been closed by something else + if( is_resource($this->socket) ) { + fclose($this->socket); + } + $this->connected = false; + $this->debug('Disconnected...'); + } + + + /** + * Parse response from Router OS + * + * @param array $response Response data + * + * @return array Array with parsed data + */ + public function parseResponse($response) + { + if (is_array($response)) { + $PARSED = array(); + $CURRENT = null; + $singlevalue = null; + foreach ($response as $x) { + if (in_array($x, array('!fatal','!re','!trap'))) { + if ($x == '!re') { + $CURRENT =& $PARSED[]; + } else { + $CURRENT =& $PARSED[$x][]; + } + } elseif ($x != '!done') { + $MATCHES = array(); + if (preg_match_all('/[^=]+/i', $x, $MATCHES)) { + if ($MATCHES[0][0] == 'ret') { + $singlevalue = $MATCHES[0][1]; + } + $CURRENT[$MATCHES[0][0]] = (isset($MATCHES[0][1]) ? $MATCHES[0][1] : ''); + } + } + } + + if (empty($PARSED) && !is_null($singlevalue)) { + $PARSED = $singlevalue; + } + + return $PARSED; + } else { + return array(); + } + } + + + /** + * Parse response from Router OS + * + * @param array $response Response data + * + * @return array Array with parsed data + */ + public function parseResponse4Smarty($response) + { + if (is_array($response)) { + $PARSED = array(); + $CURRENT = null; + $singlevalue = null; + foreach ($response as $x) { + if (in_array($x, array('!fatal','!re','!trap'))) { + if ($x == '!re') { + $CURRENT =& $PARSED[]; + } else { + $CURRENT =& $PARSED[$x][]; + } + } elseif ($x != '!done') { + $MATCHES = array(); + if (preg_match_all('/[^=]+/i', $x, $MATCHES)) { + if ($MATCHES[0][0] == 'ret') { + $singlevalue = $MATCHES[0][1]; + } + $CURRENT[$MATCHES[0][0]] = (isset($MATCHES[0][1]) ? $MATCHES[0][1] : ''); + } + } + } + foreach ($PARSED as $key => $value) { + $PARSED[$key] = $this->arrayChangeKeyName($value); + } + return $PARSED; + if (empty($PARSED) && !is_null($singlevalue)) { + $PARSED = $singlevalue; + } + } else { + return array(); + } + } + + + /** + * Change "-" and "/" from array key to "_" + * + * @param array $array Input array + * + * @return array Array with changed key names + */ + public function arrayChangeKeyName(&$array) + { + if (is_array($array)) { + foreach ($array as $k => $v) { + $tmp = str_replace("-", "_", $k); + $tmp = str_replace("/", "_", $tmp); + if ($tmp) { + $array_new[$tmp] = $v; + } else { + $array_new[$k] = $v; + } + } + return $array_new; + } else { + return $array; + } + } + + + /** + * Read data from Router OS + * + * @param boolean $parse Parse the data? default: true + * + * @return array Array with parsed or unparsed data + */ + public function read($parse = true) + { + $RESPONSE = array(); + $receiveddone = false; + while (true) { + // Read the first byte of input which gives us some or all of the length + // of the remaining reply. + $BYTE = ord(fread($this->socket, 1)); + $LENGTH = 0; + // If the first bit is set then we need to remove the first four bits, shift left 8 + // and then read another byte in. + // We repeat this for the second and third bits. + // If the fourth bit is set, we need to remove anything left in the first byte + // and then read in yet another byte. + if ($BYTE & 128) { + if (($BYTE & 192) == 128) { + $LENGTH = (($BYTE & 63) << 8) + ord(fread($this->socket, 1)); + } else { + if (($BYTE & 224) == 192) { + $LENGTH = (($BYTE & 31) << 8) + ord(fread($this->socket, 1)); + $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); + } else { + if (($BYTE & 240) == 224) { + $LENGTH = (($BYTE & 15) << 8) + ord(fread($this->socket, 1)); + $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); + $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); + } else { + $LENGTH = ord(fread($this->socket, 1)); + $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); + $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); + $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); + } + } + } + } else { + $LENGTH = $BYTE; + } + + $_ = ""; + + // If we have got more characters to read, read them in. + if ($LENGTH > 0) { + $_ = ""; + $retlen = 0; + while ($retlen < $LENGTH) { + $toread = $LENGTH - $retlen; + $_ .= fread($this->socket, $toread); + $retlen = strlen($_); + } + $RESPONSE[] = $_; + $this->debug('>>> [' . $retlen . '/' . $LENGTH . '] bytes read.'); + } + + // If we get a !done, make a note of it. + if ($_ == "!done") { + $receiveddone = true; + } + + $STATUS = socket_get_status($this->socket); + if ($LENGTH > 0) { + $this->debug('>>> [' . $LENGTH . ', ' . $STATUS['unread_bytes'] . ']' . $_); + } + + if ((!$this->connected && !$STATUS['unread_bytes']) || ($this->connected && !$STATUS['unread_bytes'] && $receiveddone)) { + break; + } + } + + if ($parse) { + $RESPONSE = $this->parseResponse($RESPONSE); + } + + return $RESPONSE; + } + + + /** + * Write (send) data to Router OS + * + * @param string $command A string with the command to send + * @param mixed $param2 If we set an integer, the command will send this data as a "tag" + * If we set it to boolean true, the funcion will send the comand and finish + * If we set it to boolean false, the funcion will send the comand and wait for next command + * Default: true + * + * @return boolean Return false if no command especified + */ + public function write($command, $param2 = true) + { + if ($command) { + $data = explode("\n", $command); + foreach ($data as $com) { + $com = trim($com); + fwrite($this->socket, $this->encodeLength(strlen($com)) . $com); + $this->debug('<<< [' . strlen($com) . '] ' . $com); + } + + if (gettype($param2) == 'integer') { + fwrite($this->socket, $this->encodeLength(strlen('.tag=' . $param2)) . '.tag=' . $param2 . chr(0)); + $this->debug('<<< [' . strlen('.tag=' . $param2) . '] .tag=' . $param2); + } elseif (gettype($param2) == 'boolean') { + fwrite($this->socket, ($param2 ? chr(0) : '')); + } + + return true; + } else { + return false; + } + } + + + /** + * Write (send) data to Router OS + * + * @param string $com A string with the command to send + * @param array $arr An array with arguments or queries + * + * @return array Array with parsed + */ + public function comm($com, $arr = array()) + { + $count = count($arr); + $this->write($com, !$arr); + $i = 0; + if ($this->isIterable($arr)) { + foreach ($arr as $k => $v) { + switch ($k[0]) { + case "?": + $el = "$k=$v"; + break; + case "~": + $el = "$k~$v"; + break; + default: + $el = "=$k=$v"; + break; + } + + $last = ($i++ == $count - 1); + $this->write($el, $last); + } + } + + return $this->read(); + } + + /** + * Standard destructor + * + * @return void + */ + public function __destruct() + { + $this->disconnect(); + } +} diff --git a/routers.php b/routers.php new file mode 100755 index 0000000..085be09 --- /dev/null +++ b/routers.php @@ -0,0 +1,251 @@ + + + + + + + + + + +

+connect_error or $conn_2->connect_error) { + die("Connection failed: " . $conn_1->connect_error . " " + . $conn_2->connect_error); + } + + $sql_1 = "select radsecret from radlogin where id = 1"; + $result = $conn_1->query($sql_1); + $row = $result->fetch_assoc(); + $secret = $row["radsecret"]; + $sql_2 = "insert into nas (nasname, secret, shortname) values " . + "(\"$addr\", \"$secret\", \"$name\")"; + + if ($conn_2->query($sql_2) == FALSE) { + $msg = "

Error adding router

"; + } else { + $msg = "

Router added

"; + } + + $conn_1->close(); + $conn_2->close(); +} +?> +

+ + +

ROUTERS

+
+
+
+ADD ROUTER + +

+ +

+ +
+ +
+
+
+
+
+REMOVE ROUTER + +

+ +
+ +
+connect_error) { + die("Connection failed: " . $conn->connect_error); + } + $sql_2 = "select * from login where id = 1"; + $result = $conn_1->query($sql_2); + $row = $result->fetch_assoc(); + $login_result = ftp_login($conn_id, $row["username"], $row["password"]); + if (ftp_put($conn_id, $trg_file_path, + "/var/www/html/init/" . $login_file, FTP_ASCII)) { + echo "

+ Successfully uploaded your login page to router

"; + } else { + echo "

+ There was a problem while uploading your login page to router +

"; + } + $conn_1->close(); + ftp_close($conn_id); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $addr = $_POST["router_addr"]; + if(isset($msg)) {echo $msg;} + uploadMikLoginPage($addr, "login.html"); +} + $servername = "localhost"; + $username = "radius"; + $password = "radpass"; + $dbname = "radius"; + + + $conn = new mysqli($servername, $username, $password, $dbname); + + if ($conn->connect_error) { + die("Connection failed: " . $conn->connect_error); + } + + $sql_2 = "select nasname, shortname from nas"; + $result = $conn->query($sql_2); + + echo "

ROUTERS ADDED

"; + + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + if ($result->num_rows > 0) { + while($row = $result->fetch_assoc()) { + echo ""; + echo ""; + echo ""; + echo ""; + } + } else { + echo ""; + echo ""; + echo ""; + echo ""; + } + + echo "
ROUTER NAMEROUTER ADDRESS
" . $row["shortname"] . "" . $row["nasname"] . "
--- ---
"; + + $conn->close(); + +?> + + + + diff --git a/script.js b/script.js new file mode 100755 index 0000000..4eb0c60 --- /dev/null +++ b/script.js @@ -0,0 +1,2 @@ +document.getElementById("form").innerHTML = ""; +document.getElementById("script").innerHTML = ""; diff --git a/setup_one_hotspot.php b/setup_one_hotspot.php new file mode 100755 index 0000000..d83f4b1 --- /dev/null +++ b/setup_one_hotspot.php @@ -0,0 +1,112 @@ +; + + + + + + + + +

+= 22 and $octs[4] <= 29 + and checkOctet_bool($octs[0]) and checkOctet_bool($octs[1]) + and checkOctet_bool($octs[2]) and checkOctet_bool($octs[3])) { + $conn = new mysqli("localhost", "mgt", "admin_mgt", "manager_db"); + if ($conn->connection_error) { + die("Connection failed: " . $conn->connection_error); + } + $result = $conn->query("select * from login where id = 1"); + $row = $result->fetch_assoc(); + setup($_POST["router_addr"], $row["username"], $row["password"]); + $conn->close(); + } else { + $msg = "

+ Invalid subnet mask or network

"; + } +} +?> +

+ + + + + +HOTSPOT CREATED WITH THE FOLLOWING SETTINGS"; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + echo "
HOTSPOT NAMEHOTSPOT ADDRESS
" . $_POST["hs_ssid"] . "" . $_POST["hs_net"]. "
"; + + echo ' + + + + + diff --git a/tutorial.php b/tutorial.php new file mode 100755 index 0000000..bcc4db9 --- /dev/null +++ b/tutorial.php @@ -0,0 +1,119 @@ + + + + + + + + +

+ +

TUTORIAL

+

HOW TO SETUP A HOTSPOT

+

+

STEP 1: ADD A MIKROTIK ROUTER TO THIS WEB INTERFACE

+

Click "Routers" on the menu above. Go to the "ADD ROUTER" section. +

Type in the IP address of the router you want to add, + for example 10.10.1.1.

+

Next, type in the Name of that router. + This could be anything you want, for example "Conference Hall Hotspot".

+

Lastly, type in the RADIUS secret. This is a secret password which + your router uses for authentication from the RADIUS server. Without it, + your router will not be able to provide internet to your users. + We recommend setting a secure password.

+

Click ADD when done. + You will see your added router at the bottom of that page.

+

+ + + + diff --git a/upload_Logo.php b/upload_Logo.php new file mode 100755 index 0000000..784d054 --- /dev/null +++ b/upload_Logo.php @@ -0,0 +1,85 @@ +connect_error) { + die("Connection failed: " . $conn->connect_error); + } + $sql = "select * from login where id = 1"; + $result = $conn->query($sql); + $row = $result->fetch_assoc(); + $login_result = ftp_login($conn_id, $row["username"], $row["password"]); + if (ftp_put($conn_id, $trg_file_path, + "/var/www/html/logo/" . $logo_file, FTP_BINARY)) { + echo "Successfully uploaded your logo to router " . $router_addr . "\n\n"; + } else { + echo "There was a problem uploading your logo to router " . $router_addr . + "\n\n"; + } + $conn->close(); + ftp_close($conn_id); +} + +if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $target_dir = "logo/"; + $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); + $uploadOk = 1; + $imageFileType = pathinfo($target_file,PATHINFO_EXTENSION); + // Check if image file is a actual image or fake image + if(isset($_POST["submit"])) { + $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]); + if($check !== false) { + echo "File is an image - " . $check["mime"] . "."; + $uploadOk = 1; + } else { + echo "File is not an image."; + $uploadOk = 0; + } + } + // Check if file already exists + if (file_exists($target_file)) { + echo "Sorry, the logo already exists."; + $uploadOk = 0; + } + // Check file size + $KiB = 1024; + if ($_FILES["fileToUpload"]["size"] > (500 * $KiB)) { + echo "Sorry, your file is too large."; + $uploadOk = 0; + } + // Allow only PNG file format + if($imageFileType != "png") { + echo "Sorry, only PNG files are allowed."; + $uploadOk = 0; + } + // Check if $uploadOk is set to 0 by an error + if ($uploadOk == 0) { + echo "Sorry, your logo was not uploaded."; + // if everything is ok, try to upload file + } else { + if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], + $target_file)) { + rename($target_file, $target_dir . "company_logo.png"); + $conn = new mysqli("localhost", "radius", "radpass", "radius"); + if ($conn->connect_error) { + die("Connection failed: " . $conn->connect_error); + } + $sql_1 = "select nasname from nas"; + $result = $conn->query($sql_1); + if ($result->num_rows > 0) { + while($row = $result->fetch_assoc()) { + uploadMikLogo($row["nasname"], "company_logo.png"); + } + } + echo "Successfully uploaded your logo to Web UI.\n\n"; + $conn->close(); + header("Location: general_settings.php"); + } else { + echo "There was an problem while uploading your logo to Web UI.\n\n"; + } + } + +} +?> + diff --git a/upload_logo.php b/upload_logo.php new file mode 100755 index 0000000..8ac9799 --- /dev/null +++ b/upload_logo.php @@ -0,0 +1,106 @@ + + + + + + + + +

+ +

UPLOAD CUSTOM LOGO

+
+Select image to upload (PNG format only): +

+

+
+ + (500 * $KiB)) { + echo "Sorry, your file is too large."; + $uploadOk = 0; + } + // Allow only PNG file format + if($imageFileType != "png") { + echo "Sorry, only PNG files are allowed."; + $uploadOk = 0; + } + // Check if $uploadOk is set to 0 by an error + if ($uploadOk == 0) { + echo "Sorry, your logo was not uploaded."; + // if everything is ok, try to upload file + } else { + if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], + $target_file)) { + rename($target_file, $target_dir . "company_logo.png"); + $conn = new mysqli("localhost", "radius", "radpass", "radius"); + if ($conn->connect_error) { + die("Connection failed: " . $conn->connect_error); + } + $sql_1 = "select nasname from nas"; + $result = $conn->query($sql_1); + if ($result->num_rows > 0) { + while($row = $result->fetch_assoc()) { + uploadMikLogo($row["nasname"], "company_logo.png"); + } + } + echo "Successfully uploaded your logo to Web UI."; + $conn->close(); + } else { + echo "There was an problem while uploading your logo to Web UI."; + } + } + +} +?> + + diff --git a/vouchers.php b/vouchers.php new file mode 100755 index 0000000..346c67b --- /dev/null +++ b/vouchers.php @@ -0,0 +1,176 @@ + + + + + + + + +

+ +

VOUCHERS

+
+
+
+MAKE NEW VOUCHERS + +

+ +

+ +

+ +
+ + +
+
+
+FLUSH OLD VOUCHERS +

+
+ +
+connect_error) { + die("Connection failed: " . $conn->connect_error); + } + + $sql_1 = "drop table radcheck"; + $sql_2 = "drop table radusergroup"; + + if ($conn->query($sql_1) == FALSE & $conn->query($sql_2) == FALSE) { + die("Query \"$sql_1\" or \"$sql_2\" failed!"); + } else { + $sql_3 = "CREATE TABLE radcheck ( + id int(11) unsigned NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '==', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY username (username(32)) + )"; + $sql_4 = "CREATE TABLE radusergroup ( + username varchar(64) NOT NULL default '', + groupname varchar(64) NOT NULL default '', + priority int(11) NOT NULL default '1', + KEY username (username(32)) + )"; + if ($conn->query($sql_3) == FALSE & $conn->query($sql_4) == FALSE) { + die("Query \"$sql_3\" or \"$sql_4\" failed!"); + } else { + echo "

+ Vouchers flushed! +



"; + } + } + + $conn->close(); + +} +?> + + + +