2022-10-05 10:51:18 +07:00
|
|
|
<?php
|
2023-10-12 15:01:49 +07:00
|
|
|
|
2023-10-12 14:33:37 +07:00
|
|
|
/**
|
|
|
|
* Radius Class
|
|
|
|
* based https://gist.github.com/nasirhafeez/6669b24aab0bda545f60f9da5ed14f25
|
|
|
|
*/
|
2023-10-03 15:46:55 +07:00
|
|
|
class Radius
|
|
|
|
{
|
2022-10-05 10:51:18 +07:00
|
|
|
|
2023-10-12 15:01:49 +07:00
|
|
|
public static function getClient()
|
|
|
|
{
|
|
|
|
global $config;
|
|
|
|
return (empty($config['radius_client'])) ? shell_exec('which radclient') : $config['radius_client'];
|
|
|
|
}
|
|
|
|
|
2023-10-03 15:46:55 +07:00
|
|
|
public static function getTableNas()
|
|
|
|
{
|
2023-08-28 08:45:35 +07:00
|
|
|
return ORM::for_table('nas', 'radius');
|
|
|
|
}
|
|
|
|
|
2023-10-03 15:46:55 +07:00
|
|
|
public static function getTableCustomer()
|
|
|
|
{
|
2023-08-28 08:45:35 +07:00
|
|
|
return ORM::for_table('radcheck', 'radius');
|
|
|
|
}
|
|
|
|
|
2023-10-03 15:46:55 +07:00
|
|
|
public static function getTablePackage()
|
|
|
|
{
|
2023-08-28 08:45:35 +07:00
|
|
|
return ORM::for_table('radgroupreply', 'radius');
|
|
|
|
}
|
|
|
|
|
2023-10-03 15:46:55 +07:00
|
|
|
public static function getTableUserPackage()
|
|
|
|
{
|
2023-08-28 08:45:35 +07:00
|
|
|
return ORM::for_table('radusergroup', 'radius');
|
|
|
|
}
|
|
|
|
|
2023-10-04 14:00:04 +07:00
|
|
|
public static function nasList($search = null)
|
|
|
|
{
|
|
|
|
if ($search == null) {
|
2023-10-03 15:46:55 +07:00
|
|
|
return ORM::for_table('nas', 'radius')->find_many();
|
2023-10-04 14:00:04 +07:00
|
|
|
} else {
|
2023-10-03 15:46:55 +07:00
|
|
|
return ORM::for_table('nas', 'radius')
|
|
|
|
->where_like('nasname', $search)
|
|
|
|
->where_like('shortname', $search)
|
|
|
|
->where_like('description', $search)
|
|
|
|
->find_many();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function nasAdd($name, $ip, $ports, $secret, $description = "", $type = 'other', $server = null, $community = null)
|
|
|
|
{
|
2023-10-03 15:03:47 +07:00
|
|
|
$n = Radius::getTableNas()->create();
|
2023-08-28 08:45:35 +07:00
|
|
|
$n->nasname = $ip;
|
|
|
|
$n->shortname = $name;
|
|
|
|
$n->type = $type;
|
|
|
|
$n->ports = $ports;
|
|
|
|
$n->secret = $secret;
|
|
|
|
$n->description = $description;
|
|
|
|
$n->server = $server;
|
|
|
|
$n->community = $community;
|
|
|
|
$n->save();
|
|
|
|
return $n->id();
|
|
|
|
}
|
2023-10-03 15:03:47 +07:00
|
|
|
|
2023-10-03 15:46:55 +07:00
|
|
|
public static function nasUpdate($id, $name, $ip, $ports, $secret, $description = "", $type = 'other', $server = null, $community = null)
|
|
|
|
{
|
2023-10-03 15:03:47 +07:00
|
|
|
$n = Radius::getTableNas()->find_one($id);
|
2023-10-03 15:46:55 +07:00
|
|
|
if (empty($n)) {
|
2023-08-28 08:45:35 +07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$n->nasname = $ip;
|
|
|
|
$n->shortname = $name;
|
|
|
|
$n->type = $type;
|
|
|
|
$n->ports = $ports;
|
|
|
|
$n->secret = $secret;
|
|
|
|
$n->description = $description;
|
|
|
|
$n->server = $server;
|
|
|
|
$n->community = $community;
|
2023-10-03 15:03:47 +07:00
|
|
|
return $n->save();
|
2023-08-28 08:45:35 +07:00
|
|
|
}
|
|
|
|
|
2023-10-12 13:32:45 +07:00
|
|
|
public static function planUpSert($plan_id, $rate, $pool = null)
|
2023-10-03 15:46:55 +07:00
|
|
|
{
|
|
|
|
$rates = explode('/', $rate);
|
2023-10-12 13:32:45 +07:00
|
|
|
Radius::upsertPackage($plan_id, 'Ascend-Data-Rate', $rates[1], ':=');
|
|
|
|
Radius::upsertPackage($plan_id, 'Ascend-Xmit-Rate', $rates[0], ':=');
|
|
|
|
if ($pool != null) {
|
|
|
|
Radius::upsertPackage($plan_id, 'Framed-Pool', $pool, ':=');
|
2023-10-03 15:46:55 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 13:32:45 +07:00
|
|
|
public static function planDelete($plan_id)
|
2023-10-03 15:46:55 +07:00
|
|
|
{
|
2023-10-04 15:41:48 +07:00
|
|
|
// Delete Plan
|
2023-10-12 13:32:45 +07:00
|
|
|
Radius::getTablePackage()->where_equal('plan_id', "plan_" . $plan_id)->delete_many();
|
2023-10-04 16:11:55 +07:00
|
|
|
// Reset User Plan
|
2023-10-12 13:32:45 +07:00
|
|
|
$c = Radius::getTableUserPackage()->where_equal('groupname', "plan_" . $plan_id)->findMany();
|
2023-10-04 16:11:55 +07:00
|
|
|
if ($c) {
|
2023-10-12 13:32:45 +07:00
|
|
|
foreach ($c as $u) {
|
2023-10-04 16:11:55 +07:00
|
|
|
$u->groupname = '';
|
|
|
|
$u->save();
|
|
|
|
}
|
|
|
|
}
|
2023-10-04 15:41:48 +07:00
|
|
|
}
|
|
|
|
|
2023-10-12 13:32:45 +07:00
|
|
|
|
|
|
|
public static function customerChangeUsername($from, $to)
|
|
|
|
{
|
2023-10-04 14:16:39 +07:00
|
|
|
$c = Radius::getTableCustomer()->where_equal('username', $from)->findMany();
|
|
|
|
if ($c) {
|
2023-10-12 13:32:45 +07:00
|
|
|
foreach ($c as $u) {
|
2023-10-04 14:16:39 +07:00
|
|
|
$u->username = $to;
|
|
|
|
$u->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$c = Radius::getTableUserPackage()->where_equal('username', $from)->findMany();
|
|
|
|
if ($c) {
|
2023-10-12 13:32:45 +07:00
|
|
|
foreach ($c as $u) {
|
2023-10-04 14:16:39 +07:00
|
|
|
$u->username = $to;
|
|
|
|
$u->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-12 13:32:45 +07:00
|
|
|
public static function customerDeactivate($username)
|
|
|
|
{
|
2023-10-04 14:16:39 +07:00
|
|
|
global $radius_pass;
|
2023-10-04 16:11:55 +07:00
|
|
|
$r = Radius::getTableCustomer()->where_equal('username', $username)->whereEqual('attribute', 'Cleartext-Password')->findOne();
|
2023-10-12 13:32:45 +07:00
|
|
|
if ($r) {
|
2023-10-04 14:16:39 +07:00
|
|
|
// no need to delete, because it will make ID got higher
|
|
|
|
// we just change the password
|
2023-10-12 13:32:45 +07:00
|
|
|
$r->value = md5(time() . $username . $radius_pass);
|
2023-10-04 14:16:39 +07:00
|
|
|
$r->save();
|
2023-10-12 15:47:45 +07:00
|
|
|
return Radius::disconnectCustomer($username);
|
2023-10-04 14:16:39 +07:00
|
|
|
}
|
2023-10-12 15:47:45 +07:00
|
|
|
return '';
|
2023-10-04 14:16:39 +07:00
|
|
|
}
|
2023-10-04 14:00:04 +07:00
|
|
|
|
2023-10-12 13:32:45 +07:00
|
|
|
public static function customerDelete($username)
|
|
|
|
{
|
2023-10-04 15:41:48 +07:00
|
|
|
Radius::getTableCustomer()->where_equal('username', $username)->delete_many();
|
|
|
|
Radius::getTableUserPackage()->where_equal('username', $username)->delete_many();
|
|
|
|
}
|
|
|
|
|
2023-10-04 14:00:04 +07:00
|
|
|
/**
|
|
|
|
* When add a plan to Customer, use this
|
|
|
|
*/
|
2023-10-12 14:33:37 +07:00
|
|
|
public static function customerAddPlan($customer, $plan, $expired = null)
|
2023-10-12 13:32:45 +07:00
|
|
|
{
|
|
|
|
if (Radius::customerUpsert($customer, $plan)) {
|
2023-10-04 14:00:04 +07:00
|
|
|
$p = Radius::getTableUserPackage()->where_equal('username', $customer['username'])->findOne();
|
|
|
|
if ($p) {
|
|
|
|
// if exists
|
2023-10-12 13:32:45 +07:00
|
|
|
$p->groupname = "plan_" . $plan['id'];
|
2023-10-12 14:33:37 +07:00
|
|
|
$p->save();
|
2023-10-12 13:32:45 +07:00
|
|
|
} else {
|
2023-10-04 14:00:04 +07:00
|
|
|
$p = Radius::getTableUserPackage()->create();
|
|
|
|
$p->username = $customer['username'];
|
2023-10-12 13:32:45 +07:00
|
|
|
$p->groupname = "plan_" . $plan['id'];
|
2023-10-04 14:00:04 +07:00
|
|
|
$p->priority = 1;
|
2023-10-12 14:33:37 +07:00
|
|
|
$p->save();
|
2023-10-04 14:00:04 +07:00
|
|
|
}
|
2023-10-12 15:47:45 +07:00
|
|
|
if ($plan['type'] == 'Hotspot' && $plan['typebp'] == "Limited") {
|
2023-10-12 14:33:37 +07:00
|
|
|
if ($plan['limit_type'] == "Time_Limit") {
|
|
|
|
if ($plan['time_unit'] == 'Hrs')
|
|
|
|
$timelimit = $plan['time_limit'] * 60 * 60;
|
|
|
|
else
|
|
|
|
$timelimit = $plan['time_limit'] * 60;
|
|
|
|
Radius::upsertCustomer($customer['username'], 'Expire-After', $timelimit);
|
|
|
|
} else if ($plan['limit_type'] == "Data_Limit") {
|
|
|
|
if ($plan['data_unit'] == 'GB')
|
|
|
|
$datalimit = $plan['data_limit'] . "000000000";
|
|
|
|
else
|
|
|
|
$datalimit = $plan['data_limit'] . "000000";
|
2023-10-12 15:01:49 +07:00
|
|
|
Radius::upsertCustomer($customer['username'], 'Max-Volume', $datalimit);
|
2023-10-12 14:33:37 +07:00
|
|
|
} else if ($plan['limit_type'] == "Both_Limit") {
|
|
|
|
if ($plan['time_unit'] == 'Hrs')
|
|
|
|
$timelimit = $plan['time_limit'] * 60 * 60;
|
|
|
|
else
|
|
|
|
$timelimit = $plan['time_limit'] . ":00";
|
|
|
|
if ($plan['data_unit'] == 'GB')
|
|
|
|
$datalimit = $plan['data_limit'] . "000000000";
|
|
|
|
else
|
|
|
|
$datalimit = $plan['data_limit'] . "000000";
|
2023-10-12 15:01:49 +07:00
|
|
|
Radius::upsertCustomer($customer['username'], 'Max-Volume', $datalimit);
|
|
|
|
Radius::upsertCustomer($customer['username'], 'Expire-After', $timelimit);
|
2023-10-12 14:33:37 +07:00
|
|
|
}
|
2023-10-12 15:01:49 +07:00
|
|
|
} else {
|
2023-10-12 15:47:45 +07:00
|
|
|
$r = Radius::getTableCustomer()->where_equal('username', $customer['username'])->whereEqual('attribute', 'Max-Volume')->findOne();
|
|
|
|
if($r) $r->delete();
|
|
|
|
$r = Radius::getTableCustomer()->where_equal('username', $customer['username'])->whereEqual('attribute', 'Expire-After')->findOne();
|
|
|
|
if($r) $r->delete();
|
2023-10-12 14:33:37 +07:00
|
|
|
}
|
|
|
|
// expired user
|
2023-10-12 15:01:49 +07:00
|
|
|
if ($expired != null) {
|
2023-10-12 14:33:37 +07:00
|
|
|
Radius::upsertCustomer($customer['username'], 'expiration', date('d M Y H:i:s', strtotime($expired)));
|
2023-10-12 15:01:49 +07:00
|
|
|
} else {
|
2023-10-12 15:47:45 +07:00
|
|
|
$r = Radius::getTableCustomer()->where_equal('username', $customer['username'])->whereEqual('attribute', 'expiration')->findOne();
|
|
|
|
if($r) $r->delete();
|
2023-10-12 13:42:52 +07:00
|
|
|
}
|
2023-10-12 14:33:37 +07:00
|
|
|
return true;
|
2023-10-04 14:00:04 +07:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-10-12 13:32:45 +07:00
|
|
|
public static function customerUpsert($customer, $plan)
|
2023-10-04 14:00:04 +07:00
|
|
|
{
|
2023-10-12 13:32:45 +07:00
|
|
|
if ($plan['type'] == 'PPPOE') {
|
|
|
|
Radius::upsertCustomer($customer['username'], 'Cleartext-Password', (empty($customer['pppoe_password'])) ? $customer['password'] : $customer['pppoe_password']);
|
2023-10-04 14:00:04 +07:00
|
|
|
} else {
|
2023-10-12 13:32:45 +07:00
|
|
|
Radius::upsertCustomer($customer['username'], 'Cleartext-Password', $customer['password']);
|
2023-10-04 14:00:04 +07:00
|
|
|
}
|
2023-10-12 13:42:52 +07:00
|
|
|
Radius::upsertCustomer($customer['username'], 'Simultaneous-Use', ($plan['type'] == 'PPPOE') ? 1 : $plan['shared_users']);
|
2023-10-12 15:47:45 +07:00
|
|
|
return true;
|
2023-10-04 14:00:04 +07:00
|
|
|
}
|
2023-10-12 13:32:45 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* To insert or update existing plan
|
|
|
|
*/
|
|
|
|
private static function upsertPackage($plan_id, $attr, $value, $op = ':=')
|
|
|
|
{
|
|
|
|
$r = Radius::getTablePackage()->where_equal('plan_id', $plan_id)->whereEqual('attribute', $attr)->find_one();
|
|
|
|
if (!$r) {
|
|
|
|
$r = Radius::getTablePackage()->create();
|
|
|
|
$r->groupname = "plan_" . $plan_id;
|
|
|
|
$r->plan_id = $plan_id;
|
|
|
|
}
|
|
|
|
$r->attribute = $attr;
|
|
|
|
$r->op = $op;
|
|
|
|
$r->value = $value;
|
|
|
|
return $r->save();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* To insert or update existing customer
|
|
|
|
*/
|
|
|
|
private static function upsertCustomer($username, $attr, $value, $op = ':=')
|
|
|
|
{
|
|
|
|
$r = Radius::getTableCustomer()->where_equal('username', $username)->whereEqual('attribute', $attr)->find_one();
|
|
|
|
if (!$r) {
|
|
|
|
$r = Radius::getTableCustomer()->create();
|
|
|
|
$r->username = $username;
|
|
|
|
}
|
|
|
|
$r->attribute = $attr;
|
|
|
|
$r->op = $op;
|
|
|
|
$r->value = $value;
|
|
|
|
return $r->save();
|
|
|
|
}
|
2023-10-12 15:01:49 +07:00
|
|
|
|
|
|
|
public static function disconnectCustomer($username){
|
|
|
|
$nas = Radius::getTableNas()->findMany();
|
|
|
|
$count = count($nas)*15;
|
|
|
|
set_time_limit($count);
|
2023-10-12 15:47:45 +07:00
|
|
|
$result = [];
|
2023-10-12 15:01:49 +07:00
|
|
|
foreach ($nas as $n){
|
|
|
|
$port = 3799;
|
|
|
|
if(!empty($n['ports'])){
|
|
|
|
$port = $n['ports'];
|
|
|
|
}
|
2023-10-12 15:47:45 +07:00
|
|
|
$result[] = $n['nasname'].': '.shell_exec("echo 'User-Name = $username' | ".Radius::getClient()." ".trim($n['nasname']).":$port disconnect '".$n['secret']."'");
|
2023-10-12 15:01:49 +07:00
|
|
|
}
|
2023-10-12 15:47:45 +07:00
|
|
|
return $result;
|
2023-10-12 15:01:49 +07:00
|
|
|
}
|
2022-10-05 10:51:18 +07:00
|
|
|
}
|