mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-16 21:07:14 +00:00
captive: add missing UAM/ACCT/rate features
Fixes: WIFI-10665 Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
@@ -97,7 +97,8 @@ static void client_set_id(struct interface *iface, struct client *cl, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
int client_set(struct interface *iface, const void *addr, const char *id,
|
int client_set(struct interface *iface, const void *addr, const char *id,
|
||||||
int state, int dns_state, int accounting, struct blob_attr *data)
|
int state, int dns_state, int accounting, struct blob_attr *data,
|
||||||
|
const char *device, bool flush)
|
||||||
{
|
{
|
||||||
struct cache_entry *c;
|
struct cache_entry *c;
|
||||||
struct blob_attr *cur;
|
struct blob_attr *cur;
|
||||||
@@ -142,12 +143,21 @@ int client_set(struct interface *iface, const void *addr, const char *id,
|
|||||||
|
|
||||||
kvlist_set(&cl->kvdata, blobmsg_name(cur), cur);
|
kvlist_set(&cl->kvdata, blobmsg_name(cur), cur);
|
||||||
}
|
}
|
||||||
|
if (device)
|
||||||
|
cl->device = device;
|
||||||
if (state >= 0)
|
if (state >= 0)
|
||||||
cl->data.cur_class = state;
|
cl->data.cur_class = state;
|
||||||
if (dns_state >= 0)
|
if (dns_state >= 0)
|
||||||
cl->data.dns_class = dns_state;
|
cl->data.dns_class = dns_state;
|
||||||
if (accounting >= 0)
|
if (accounting >= 0)
|
||||||
cl->data.flags = accounting;
|
cl->data.flags = accounting;
|
||||||
|
if (flush) {
|
||||||
|
kvlist_free(&cl->kvdata);
|
||||||
|
cl->data.packets_ul = 0;
|
||||||
|
cl->data.packets_dl = 0;
|
||||||
|
cl->data.bytes_ul = 0;
|
||||||
|
cl->data.bytes_dl = 0;
|
||||||
|
}
|
||||||
spotfilter_bpf_set_client(iface, &cl->key, &cl->data);
|
spotfilter_bpf_set_client(iface, &cl->key, &cl->data);
|
||||||
|
|
||||||
if (new_client)
|
if (new_client)
|
||||||
|
|||||||
@@ -17,10 +17,12 @@ struct client {
|
|||||||
|
|
||||||
struct spotfilter_client_key key;
|
struct spotfilter_client_key key;
|
||||||
struct spotfilter_client_data data;
|
struct spotfilter_client_data data;
|
||||||
|
const char *device;
|
||||||
};
|
};
|
||||||
|
|
||||||
int client_set(struct interface *iface, const void *addr, const char *id,
|
int client_set(struct interface *iface, const void *addr, const char *id,
|
||||||
int state, int dns_state, int accounting, struct blob_attr *data);
|
int state, int dns_state, int accounting, struct blob_attr *data,
|
||||||
|
const char *device, bool flush);
|
||||||
void client_free(struct interface *iface, struct client *cl);
|
void client_free(struct interface *iface, struct client *cl);
|
||||||
void client_set_ipaddr(const void *mac, const void *addr, bool ipv6);
|
void client_set_ipaddr(const void *mac, const void *addr, bool ipv6);
|
||||||
void client_init_interface(struct interface *iface);
|
void client_init_interface(struct interface *iface);
|
||||||
|
|||||||
@@ -32,12 +32,6 @@ void interface_free(struct interface *iface)
|
|||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char *
|
|
||||||
device_name(struct device *dev)
|
|
||||||
{
|
|
||||||
return dev->node.avl.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
interface_check_device(struct interface *iface, struct device *dev)
|
interface_check_device(struct interface *iface, struct device *dev)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ static inline const char *interface_name(struct interface *iface)
|
|||||||
return iface->node.key;
|
return iface->node.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline const char *device_name(struct device *dev)
|
||||||
|
{
|
||||||
|
return dev->node.avl.key;
|
||||||
|
}
|
||||||
|
|
||||||
void interface_add(const char *name, struct blob_attr *config,
|
void interface_add(const char *name, struct blob_attr *config,
|
||||||
struct blob_attr *devices);
|
struct blob_attr *devices);
|
||||||
void interface_free(struct interface *iface);
|
void interface_free(struct interface *iface);
|
||||||
|
|||||||
@@ -155,14 +155,12 @@ nl80211_interface_update(struct interface *iface)
|
|||||||
struct client *cl, *tmp;
|
struct client *cl, *tmp;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
if (!iface->client_autoremove)
|
|
||||||
return;
|
|
||||||
|
|
||||||
avl_for_each_element_safe(&iface->clients, cl, node, tmp) {
|
avl_for_each_element_safe(&iface->clients, cl, node, tmp) {
|
||||||
if (cl->idle++ < iface->client_timeout)
|
if (cl->idle++ < iface->client_timeout)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
client_free(iface, cl);
|
if (iface->client_autoremove)
|
||||||
|
client_free(iface, cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
vlist_for_each_element(&iface->devices, dev, node)
|
vlist_for_each_element(&iface->devices, dev, node)
|
||||||
@@ -218,7 +216,7 @@ found:
|
|||||||
if (cl)
|
if (cl)
|
||||||
cl->idle = 0;
|
cl->idle = 0;
|
||||||
else if (iface->client_autocreate)
|
else if (iface->client_autocreate)
|
||||||
client_set(iface, addr, NULL, -1, -1, -1, NULL);
|
client_set(iface, addr, NULL, -1, -1, -1, NULL, device_name(dev), false);
|
||||||
|
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,9 +158,9 @@ int spotfilter_out(struct __sk_buff *skb)
|
|||||||
return TC_ACT_UNSPEC;
|
return TC_ACT_UNSPEC;
|
||||||
|
|
||||||
cl = bpf_map_lookup_elem(&client, eth->h_dest);
|
cl = bpf_map_lookup_elem(&client, eth->h_dest);
|
||||||
if (cl) {
|
if (cl && (cl->flags & SPOTFILTER_CLIENT_F_ACCT_DL)) {
|
||||||
if (cl->flags & SPOTFILTER_CLIENT_F_ACCT_DL)
|
cl->packets_dl++;
|
||||||
cl->bytes_dl += skb->len;
|
cl->bytes_dl += skb->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_parse_vlan(&info);
|
skb_parse_vlan(&info);
|
||||||
@@ -204,8 +204,10 @@ int spotfilter_in(struct __sk_buff *skb)
|
|||||||
cl = bpf_map_lookup_elem(&client, eth->h_source);
|
cl = bpf_map_lookup_elem(&client, eth->h_source);
|
||||||
if (cl) {
|
if (cl) {
|
||||||
cldata = *cl;
|
cldata = *cl;
|
||||||
if (cl->flags & SPOTFILTER_CLIENT_F_ACCT_UL)
|
if (cl->flags & SPOTFILTER_CLIENT_F_ACCT_UL) {
|
||||||
|
cl->packets_ul++;
|
||||||
cl->bytes_ul += skb->len;
|
cl->bytes_ul += skb->len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has_vlan = !!skb_parse_vlan(&info);
|
has_vlan = !!skb_parse_vlan(&info);
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ struct spotfilter_client_data {
|
|||||||
uint8_t dns_class;
|
uint8_t dns_class;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
|
||||||
|
uint64_t packets_ul;
|
||||||
|
uint64_t packets_dl;
|
||||||
uint64_t bytes_ul;
|
uint64_t bytes_ul;
|
||||||
uint64_t bytes_dl;
|
uint64_t bytes_dl;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ enum {
|
|||||||
CLIENT_ATTR_DNS_STATE,
|
CLIENT_ATTR_DNS_STATE,
|
||||||
CLIENT_ATTR_ACCOUNTING,
|
CLIENT_ATTR_ACCOUNTING,
|
||||||
CLIENT_ATTR_DATA,
|
CLIENT_ATTR_DATA,
|
||||||
|
CLIENT_ATTR_FLUSH,
|
||||||
__CLIENT_ATTR_MAX
|
__CLIENT_ATTR_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ static const struct blobmsg_policy client_policy[__CLIENT_ATTR_MAX] = {
|
|||||||
[CLIENT_ATTR_DNS_STATE] = { "dns_state", BLOBMSG_TYPE_INT32 },
|
[CLIENT_ATTR_DNS_STATE] = { "dns_state", BLOBMSG_TYPE_INT32 },
|
||||||
[CLIENT_ATTR_ACCOUNTING] = { "accounting", BLOBMSG_TYPE_ARRAY },
|
[CLIENT_ATTR_ACCOUNTING] = { "accounting", BLOBMSG_TYPE_ARRAY },
|
||||||
[CLIENT_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
|
[CLIENT_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
|
||||||
|
[CLIENT_ATTR_FLUSH] = { "flush", BLOBMSG_TYPE_BOOL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -176,6 +178,7 @@ client_ubus_update(struct ubus_context *ctx, struct ubus_object *obj,
|
|||||||
const char *id = NULL;
|
const char *id = NULL;
|
||||||
int state = -1, dns_state = -1;
|
int state = -1, dns_state = -1;
|
||||||
int accounting = -1;
|
int accounting = -1;
|
||||||
|
bool flush = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = client_ubus_init(msg, tb, &iface, &addr, &id, &cl);
|
ret = client_ubus_init(msg, tb, &iface, &addr, &id, &cl);
|
||||||
@@ -203,8 +206,11 @@ client_ubus_update(struct ubus_context *ctx, struct ubus_object *obj,
|
|||||||
if (!addr)
|
if (!addr)
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
return UBUS_STATUS_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
if (tb[CLIENT_ATTR_FLUSH])
|
||||||
|
flush = blobmsg_get_bool(tb[CLIENT_ATTR_FLUSH]);
|
||||||
|
|
||||||
client_set(iface, addr, id, state, dns_state, accounting,
|
client_set(iface, addr, id, state, dns_state, accounting,
|
||||||
tb[CLIENT_ATTR_DATA]);
|
tb[CLIENT_ATTR_DATA], NULL, flush);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -241,8 +247,10 @@ static void client_dump(struct interface *iface, struct client *cl)
|
|||||||
|
|
||||||
spotfilter_bpf_get_client(iface, &cl->key, &cl->data);
|
spotfilter_bpf_get_client(iface, &cl->key, &cl->data);
|
||||||
|
|
||||||
if (iface->client_autoremove)
|
if (cl->device)
|
||||||
blobmsg_add_u32(&b, "idle", cl->idle);
|
blobmsg_add_string(&b, "device", cl->device);
|
||||||
|
|
||||||
|
blobmsg_add_u32(&b, "idle", cl->idle);
|
||||||
|
|
||||||
blobmsg_add_u32(&b, "state", cl->data.cur_class);
|
blobmsg_add_u32(&b, "state", cl->data.cur_class);
|
||||||
blobmsg_add_u32(&b, "dns_state", cl->data.dns_class);
|
blobmsg_add_u32(&b, "dns_state", cl->data.dns_class);
|
||||||
@@ -281,6 +289,8 @@ static void client_dump(struct interface *iface, struct client *cl)
|
|||||||
interface_dump_action(&b, iface, cl->data.dns_class);
|
interface_dump_action(&b, iface, cl->data.dns_class);
|
||||||
blobmsg_close_table(&b, c);
|
blobmsg_close_table(&b, c);
|
||||||
|
|
||||||
|
blobmsg_add_u64(&b, "packets_ul", cl->data.packets_ul);
|
||||||
|
blobmsg_add_u64(&b, "packets_dl", cl->data.packets_dl);
|
||||||
blobmsg_add_u64(&b, "bytes_ul", cl->data.bytes_ul);
|
blobmsg_add_u64(&b, "bytes_ul", cl->data.bytes_ul);
|
||||||
blobmsg_add_u64(&b, "bytes_dl", cl->data.bytes_dl);
|
blobmsg_add_u64(&b, "bytes_dl", cl->data.bytes_dl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ endef
|
|||||||
|
|
||||||
define Package/uspot/install
|
define Package/uspot/install
|
||||||
$(INSTALL_DIR) $(1)/usr/bin/ $(1)/usr/lib/ucode
|
$(INSTALL_DIR) $(1)/usr/bin/ $(1)/usr/lib/ucode
|
||||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/radius-client $(1)/usr/bin
|
$(INSTALL_BIN) $(PKG_BUILD_DIR)/radius-client $(1)/usr/bin/radius-client
|
||||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/libuam.so $(1)/usr/lib/ucode/uam.so
|
$(INSTALL_DATA) $(PKG_BUILD_DIR)/libuam.so $(1)/usr/lib/ucode/uam.so
|
||||||
$(CP) ./files/* $(1)
|
$(CP) ./files/* $(1)
|
||||||
endef
|
endef
|
||||||
|
|||||||
@@ -1,25 +1,6 @@
|
|||||||
config uspot config
|
config uspot config
|
||||||
#option auth_mode 'uam'
|
|
||||||
#option auth_mode 'radius'
|
|
||||||
#option auth_mode 'credentials'
|
|
||||||
option auth_mode 'click-to-continue'
|
|
||||||
|
|
||||||
config radius radius
|
config radius radius
|
||||||
# option auth_server 212.24.98.232
|
|
||||||
# option auth_port 1812
|
|
||||||
# option auth_secret secret
|
|
||||||
|
|
||||||
config uam uam
|
config uam uam
|
||||||
# option port 3990
|
|
||||||
# option nasid AlmondLabs
|
|
||||||
# option nasmac 903cb3bb25e3
|
|
||||||
# option server https://customer.hotspotsystem.com/customer/hotspotlogin.php
|
|
||||||
# option secret hotsys123
|
|
||||||
|
|
||||||
#config credential
|
|
||||||
# option username abc
|
|
||||||
# option password def
|
|
||||||
|
|
||||||
#config credential
|
|
||||||
# option username 123
|
|
||||||
# option password 456
|
|
||||||
|
|||||||
13
feeds/ucentral/uspot/files/etc/init.d/uspot
Executable file
13
feeds/ucentral/uspot/files/etc/init.d/uspot
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
START=80
|
||||||
|
|
||||||
|
USE_PROCD=1
|
||||||
|
PROG=/usr/share/uspot/accounting.uc
|
||||||
|
|
||||||
|
start_service() {
|
||||||
|
procd_open_instance
|
||||||
|
procd_set_param command "$PROG"
|
||||||
|
procd_set_param respawn
|
||||||
|
procd_close_instance
|
||||||
|
}
|
||||||
53
feeds/ucentral/uspot/files/usr/bin/captive
Executable file
53
feeds/ucentral/uspot/files/usr/bin/captive
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/ucode
|
||||||
|
|
||||||
|
let ubus = require('ubus').connect();
|
||||||
|
let uci = require('uci').cursor();
|
||||||
|
|
||||||
|
function restart() {
|
||||||
|
system('/etc/init.d/spotfilter restart');
|
||||||
|
system('/etc/init.d/uhttpd restart');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ARGV[0]) {
|
||||||
|
case 'dump':
|
||||||
|
let clients = ubus.call('spotfilter', 'client_list', { interface: 'hotspot'});
|
||||||
|
printf('%.J\n', clients);
|
||||||
|
break;
|
||||||
|
case 'clients':
|
||||||
|
let clients = ubus.call('spotfilter', 'client_list', { interface: 'hotspot'});
|
||||||
|
let res = {};
|
||||||
|
let t = time();
|
||||||
|
|
||||||
|
for (let c, val in clients) {
|
||||||
|
res[c] = {
|
||||||
|
status: val.state ? 'Authenticated' : 'Garden',
|
||||||
|
idle: val.idle || 0,
|
||||||
|
time: val.data.connect ? t - val.data.connect : 0,
|
||||||
|
ip4addr: val.ip4addr || '',
|
||||||
|
ip6addr: val.ip6addr || '',
|
||||||
|
packets_ul: val.packets_ul || 0,
|
||||||
|
bytes_ul: val.bytes_ul || 0,
|
||||||
|
packets_dl: val.packets_dl || 0,
|
||||||
|
bytes_dl: val.bytes_dl || 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
printf('%.J\n', res);
|
||||||
|
break;
|
||||||
|
case 'remove':
|
||||||
|
ubus.call('spotfilter', 'client_remove', { interface: 'hotspot', address: ARGV[1] || ''});
|
||||||
|
break;
|
||||||
|
case 'restart':
|
||||||
|
restart();
|
||||||
|
break;
|
||||||
|
case 'log':
|
||||||
|
system('logread -f | grep uspot:');
|
||||||
|
break;
|
||||||
|
case 'debugon':
|
||||||
|
case 'debugoff':
|
||||||
|
uci.set('uspot', 'config', 'debug', 1);
|
||||||
|
uci.commit();
|
||||||
|
restart();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
211
feeds/ucentral/uspot/files/usr/share/uspot/accounting.uc
Executable file
211
feeds/ucentral/uspot/files/usr/share/uspot/accounting.uc
Executable file
@@ -0,0 +1,211 @@
|
|||||||
|
#!/usr/bin/ucode
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let fs = require('fs');
|
||||||
|
let uloop = require('uloop');
|
||||||
|
let ubus = require('ubus').connect();
|
||||||
|
let uci = require('uci').cursor();
|
||||||
|
let config = uci.get_all('uspot');
|
||||||
|
let clients = {};
|
||||||
|
|
||||||
|
let acct_interval = config.radius?.acct_interval || 600;
|
||||||
|
let idle_timeout = config.config.idle_timeout || 600;
|
||||||
|
let session_timeout = config.config.session_timeout || 0;
|
||||||
|
|
||||||
|
function syslog(mac, msg) {
|
||||||
|
let log = sprintf('uspot: %s %s', mac, msg);
|
||||||
|
|
||||||
|
system('logger ' + log);
|
||||||
|
warn(log + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug(mac, msg) {
|
||||||
|
if (config.config.debug)
|
||||||
|
syslog(mac, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_idle_timeout(mac) {
|
||||||
|
if (clients[mac])
|
||||||
|
return clients[mac].idle;
|
||||||
|
return idle_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_session_timeout(mac) {
|
||||||
|
if (clients[mac]?.session_timeout)
|
||||||
|
return clients[mac].session_timeout;
|
||||||
|
return session_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_init(mac, payload) {
|
||||||
|
for (let key in [ 'server', 'acct_server', 'acct_session', 'client_ip', 'called_station', 'calling_station', 'nas_ip', 'nas_id', 'username' ])
|
||||||
|
if (clients[mac].radius[key])
|
||||||
|
payload[key] = clients[mac].radius[key];
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_call(mac, payload) {
|
||||||
|
let cfg = fs.open('/tmp/acct' + mac + '.json', 'w');
|
||||||
|
cfg.write(payload);
|
||||||
|
cfg.close();
|
||||||
|
|
||||||
|
system('/usr/bin/radius-client /tmp/acct' + mac + '.json');
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_stop(mac) {
|
||||||
|
debug(mac, 'stopping accounting');
|
||||||
|
|
||||||
|
let payload = {
|
||||||
|
acct: true,
|
||||||
|
acct_type: 8,
|
||||||
|
terminate_cause: 0,
|
||||||
|
};
|
||||||
|
radius_init(mac, payload);
|
||||||
|
radius_call(mac, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_acct(mac, payload) {
|
||||||
|
let state = ubus.call('spotfilter', 'client_get', {
|
||||||
|
interface: 'hotspot',
|
||||||
|
address: mac
|
||||||
|
});
|
||||||
|
if (!state) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = radius_init(mac, payload);
|
||||||
|
payload.acct = true;
|
||||||
|
payload.session_time = time() - state.data.connect;
|
||||||
|
payload.output_octets = state.bytes_dl & 0xffffffff;
|
||||||
|
payload.input_octets = state.bytes_ul & 0xffffffff;
|
||||||
|
payload.output_gigawords = state.bytes_dl >> 32;
|
||||||
|
payload.input_gigawords = state.bytes_ul >> 32;
|
||||||
|
payload.output_packets = state.packets_dl;
|
||||||
|
payload.input_packets = state.packets_ul;
|
||||||
|
|
||||||
|
radius_call(mac, payload);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_idle_time(mac) {
|
||||||
|
let payload = {
|
||||||
|
acct_type: 2,
|
||||||
|
terminate_cause: 4,
|
||||||
|
};
|
||||||
|
radius_acct(mac, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_session_time(mac) {
|
||||||
|
let payload = {
|
||||||
|
acct_type: 2,
|
||||||
|
terminate_cause: 5,
|
||||||
|
};
|
||||||
|
radius_acct(mac, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_disconnect(mac) {
|
||||||
|
let payload = {
|
||||||
|
acct_type: 2,
|
||||||
|
terminate_cause: 1,
|
||||||
|
};
|
||||||
|
radius_acct(mac, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
function radius_interim(mac) {
|
||||||
|
let payload = {
|
||||||
|
acct_type: 3,
|
||||||
|
};
|
||||||
|
if (radius_acct(mac, payload))
|
||||||
|
debug(mac, 'iterim acct call');
|
||||||
|
else
|
||||||
|
syslog(mac, 'failed to sent interim accounting frame\n');
|
||||||
|
clients[mac].timeout.set(clients[mac].interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
function client_add(mac, state) {
|
||||||
|
if (state.state != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let interval = (state.data?.radius?.reply['Acct-Interim-Interval'] || acct_interval) * 1000;
|
||||||
|
let idle = (state.data?.radius?.reply['Idle-Timeout'] || idle_timeout);
|
||||||
|
let session = (state.data?.radius?.reply['Session-Timeout'] || session_timeout);
|
||||||
|
let accounting = (config.radius?.acct_server && config.radius?.acct_secret);
|
||||||
|
|
||||||
|
clients[mac] = {
|
||||||
|
accounting,
|
||||||
|
radius: state.data.radius.request,
|
||||||
|
interval,
|
||||||
|
idle,
|
||||||
|
};
|
||||||
|
syslog(mac, 'adding client');
|
||||||
|
if (accounting)
|
||||||
|
clients[mac].timeout = uloop.timer(interval, () => radius_interim(mac));
|
||||||
|
}
|
||||||
|
|
||||||
|
function client_remove(mac, reason) {
|
||||||
|
syslog(mac, reason);
|
||||||
|
if (clients[mac]) {
|
||||||
|
radius_stop(mac);
|
||||||
|
if (clients[mac].accounting)
|
||||||
|
clients[mac].timeout.cancel();
|
||||||
|
delete clients[mac];
|
||||||
|
}
|
||||||
|
ubus.call('spotfilter', 'client_remove', {
|
||||||
|
interface: "hotspot",
|
||||||
|
address: mac
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function client_timeout(mac) {
|
||||||
|
syslog(mac, 'session timeout');
|
||||||
|
if (clients[mac]) {
|
||||||
|
radius_stop(mac);
|
||||||
|
if (clients[mac].accounting)
|
||||||
|
clients[mac].timeout.cancel();
|
||||||
|
delete clients[mac];
|
||||||
|
}
|
||||||
|
ubus.call('spotfilter', 'client_set', {
|
||||||
|
interface: "hotspot",
|
||||||
|
state: 0,
|
||||||
|
address: mac,
|
||||||
|
accounting: [],
|
||||||
|
flush: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uloop.init();
|
||||||
|
|
||||||
|
uloop.timer(1000, function() {
|
||||||
|
let list = ubus.call('spotfilter', 'client_list', { interface: 'hotspot'});
|
||||||
|
let t = time();
|
||||||
|
|
||||||
|
for (let k, v in list)
|
||||||
|
if (!clients[k])
|
||||||
|
client_add(k, v);
|
||||||
|
|
||||||
|
for (let k, v in clients)
|
||||||
|
if (!list[k] || !list[k].state) {
|
||||||
|
radius_disconnect(k);
|
||||||
|
client_remove(k, 'disconnect event');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let k, v in list) {
|
||||||
|
if (v.idle > get_idle_timeout(k)) {
|
||||||
|
if (clients[k])
|
||||||
|
radius_idle_time(k);
|
||||||
|
client_remove(k, 'idle event');
|
||||||
|
|
||||||
|
}
|
||||||
|
let timeout = get_session_timeout(k);
|
||||||
|
if (timeout && ((t - v.data.connect) > timeout)) {
|
||||||
|
if (clients[k])
|
||||||
|
radius_session_time(k);
|
||||||
|
client_timeout(k);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set(5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
uloop.run();
|
||||||
@@ -26,6 +26,46 @@ return {
|
|||||||
header,
|
header,
|
||||||
footer,
|
footer,
|
||||||
|
|
||||||
|
// syslog helper
|
||||||
|
syslog: function(ctx, msg) {
|
||||||
|
warn('uspot: ' + ctx.env.REMOTE_ADDR + ' - ' + msg + '\n');
|
||||||
|
},
|
||||||
|
|
||||||
|
debug: function(ctx, msg) {
|
||||||
|
if (config.config.debug)
|
||||||
|
this.syslog(ctx, msg);
|
||||||
|
},
|
||||||
|
|
||||||
|
// mac re-formater
|
||||||
|
format_mac: function(mac) {
|
||||||
|
switch(config.uam.mac_format) {
|
||||||
|
case 'aabbccddeeff':
|
||||||
|
case 'AABBCCDDEEFF':
|
||||||
|
mac = replace(mac, ':', '');
|
||||||
|
break;
|
||||||
|
case 'aa-bb-cc-dd-ee-ff':
|
||||||
|
case 'AA-BB-CC-DD-EE-FF':
|
||||||
|
mac = replace(mac, ':', '-');
|
||||||
|
warn('uspot: ' + ctx.env.REMOTE_ADDR + ' - ' + msg + '\n');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(config.uam.mac_format) {
|
||||||
|
case 'aabbccddeeff':
|
||||||
|
case 'aa-bb-cc-dd-ee-ff':
|
||||||
|
case 'aa:bb:cc:dd:ee:ff':
|
||||||
|
mac = lc(mac);
|
||||||
|
break;
|
||||||
|
case 'AABBCCDDEEFF':
|
||||||
|
case 'AA:BB:CC:DD:EE:FF':
|
||||||
|
case 'AA-BB-CC-DD-EE-FF':
|
||||||
|
mac = uc(mac);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mac;
|
||||||
|
},
|
||||||
|
|
||||||
// wrapper for scraping external tools stdout
|
// wrapper for scraping external tools stdout
|
||||||
fs_popen: function(cmd) {
|
fs_popen: function(cmd) {
|
||||||
let stdout = fs.popen(cmd);
|
let stdout = fs.popen(cmd);
|
||||||
@@ -43,45 +83,79 @@ return {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// give a client access to the internet
|
// give a client access to the internet
|
||||||
allow_client: function(ctx) {
|
allow_client: function(ctx, data) {
|
||||||
|
this.syslog(ctx, 'allow client to pass traffic');
|
||||||
ctx.ubus.call('spotfilter', 'client_set', {
|
ctx.ubus.call('spotfilter', 'client_set', {
|
||||||
"interface": "hotspot",
|
"interface": "hotspot",
|
||||||
"address": replace(ctx.mac, '-', ':'),
|
"address": ctx.mac,
|
||||||
"state": 1,
|
"state": 1,
|
||||||
"dns_state": 1,
|
"dns_state": 1,
|
||||||
"accounting": [ "dl", "ul"],
|
"accounting": [ "dl", "ul"],
|
||||||
"data": {
|
"data": {
|
||||||
"connect": time()
|
... data || {},
|
||||||
|
"connect": time(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (ctx.query_string.userurl)
|
if (ctx.query_string.userurl)
|
||||||
include('redir.uc', { redir_location: ctx.query_string.userurl });
|
include('redir.uc', { redir_location: ctx.query_string.userurl });
|
||||||
else
|
else
|
||||||
include('allow.uc', ctx);
|
include('allow.uc', ctx);
|
||||||
|
//data.radius.reply['WISPr-Bandwidth-Max-Up'] = "20000000";
|
||||||
|
//data.radius.reply['WISPr-Bandwidth-Max-Down'] = "10000000";
|
||||||
|
if (data?.radius?.reply && (+data.radius.reply['WISPr-Bandwidth-Max-Up'] && +data.radius.reply['WISPr-Bandwidth-Max-Down']))
|
||||||
|
ctx.ubus.call('ratelimit', 'client_set', {
|
||||||
|
device: ctx.device,
|
||||||
|
address: ctx.mac,
|
||||||
|
rate_egress: sprintf('%s', data.radius.reply['WISPr-Bandwidth-Max-Down']),
|
||||||
|
rate_ingress: sprintf('%s', data.radius.reply['WISPr-Bandwidth-Max-Up']),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// put a client back into pre-auth state
|
||||||
|
logoff: function(ctx, data) {
|
||||||
|
this.syslog(ctx, 'logging client off');
|
||||||
|
ctx.ubus.call('spotfilter', 'client_set', {
|
||||||
|
interface: 'hotspot',
|
||||||
|
address: ctx.mac,
|
||||||
|
state: 0,
|
||||||
|
dns_state: 1,
|
||||||
|
accounting: [],
|
||||||
|
flush: true,
|
||||||
|
});
|
||||||
|
include('logoff.uc', ctx);
|
||||||
},
|
},
|
||||||
|
|
||||||
// generate the default radius auth payload
|
// generate the default radius auth payload
|
||||||
radius_init: function(ctx) {
|
radius_init: function(ctx, acct_session) {
|
||||||
|
let math = require('math');
|
||||||
|
if (!acct_session) {
|
||||||
|
acct_session = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < 16; i++)
|
||||||
|
acct_session += sprintf('%d', math.rand() % 10);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
server: sprintf('%s:%s:%s', this.config.radius.auth_server, this.config.radius.auth_port, this.config.radius.auth_secret),
|
server: sprintf('%s:%s:%s', this.config.radius.auth_server, this.config.radius.auth_port, this.config.radius.auth_secret),
|
||||||
acct_session: "0123456789",
|
acct_server: sprintf('%s:%s:%s', this.config.radius.acct_server, this.config.radius.acct_port, this.config.radius.acct_secret),
|
||||||
|
acct_session,
|
||||||
client_ip: ctx.env.REMOTE_ADDR,
|
client_ip: ctx.env.REMOTE_ADDR,
|
||||||
called_station: ctx.mac,
|
called_station: this.config.uam.nasmac,
|
||||||
calling_station: this.config.uam.nasmac,
|
calling_station: this.format_mac(ctx.mac),
|
||||||
nas_ip: ctx.env.SERVER_ADDR,
|
nas_ip: ctx.env.SERVER_ADDR,
|
||||||
nas_id: this.config.uam.nasid
|
nas_id: this.config.uam.nasid
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
radius_call: function(ctx, payload) {
|
radius_call: function(ctx, payload) {
|
||||||
let cfg = fs.open('/tmp/' + ctx.mac + '.json', 'w');
|
let cfg = fs.open('/tmp/auth' + ctx.mac + '.json', 'w');
|
||||||
cfg.write(payload);
|
cfg.write(payload);
|
||||||
cfg.close();
|
cfg.close();
|
||||||
|
|
||||||
return this.fs_popen('/usr/bin/radius-client /tmp/' + ctx.mac + '.json');
|
return this.fs_popen('/usr/bin/radius-client /tmp/auth' + ctx.mac + '.json');
|
||||||
},
|
},
|
||||||
|
|
||||||
handle_request: function(env) {
|
handle_request: function(env, uam) {
|
||||||
let mac;
|
let mac;
|
||||||
let form_data = {};
|
let form_data = {};
|
||||||
let query_string = {};
|
let query_string = {};
|
||||||
@@ -91,25 +165,39 @@ return {
|
|||||||
// lookup the peers MAC
|
// lookup the peers MAC
|
||||||
let macs = this.rtnl.request(this.rtnl.const.RTM_GETNEIGH, this.rtnl.const.NLM_F_DUMP, { });
|
let macs = this.rtnl.request(this.rtnl.const.RTM_GETNEIGH, this.rtnl.const.NLM_F_DUMP, { });
|
||||||
for (let m in macs)
|
for (let m in macs)
|
||||||
if (m.dst == env.REMOTE_HOST)
|
if (m.dst == env.REMOTE_HOST && m.lladdr)
|
||||||
ctx.mac = replace(m.lladdr, ':', '-');
|
ctx.mac = m.lladdr;
|
||||||
|
|
||||||
// if the MAC lookup failed, go to the error page
|
// if the MAC lookup failed, go to the error page
|
||||||
if (!ctx.mac) {
|
if (!ctx.mac) {
|
||||||
|
this.syslog(ctx, 'failed to look up mac');
|
||||||
include('error.uc', ctx);
|
include('error.uc', ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ctx.format_mac = this.format_mac(ctx.mac);
|
||||||
|
|
||||||
// check if a client is already connected
|
// check if a client is already connected
|
||||||
ctx.ubus = ubus.connect();
|
ctx.ubus = ubus.connect();
|
||||||
let connected = ctx.ubus.call('spotfilter', 'client_get', {
|
let connected = ctx.ubus.call('spotfilter', 'client_get', {
|
||||||
'interface': 'hotspot',
|
interface: 'hotspot',
|
||||||
'address': ctx.mac
|
address: ctx.mac,
|
||||||
});
|
});
|
||||||
if (connected?.state) {
|
if (!uam && connected?.state) {
|
||||||
include('connected.uc', ctx);
|
include('connected.uc', ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (!connected.data.ssid) {
|
||||||
|
let hapd = ctx.ubus.call('hostapd.' + connected.device, 'get_status');
|
||||||
|
ctx.ubus.call('spotfilter', 'client_set', {
|
||||||
|
interface: 'hotspot',
|
||||||
|
address: ctx.mac,
|
||||||
|
data: {
|
||||||
|
ssid: hapd.ssid || 'unknown'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ctx.device = connected.device;
|
||||||
|
ctx.ssid = connected.data.ssid;
|
||||||
|
|
||||||
// split QUERY_STRING
|
// split QUERY_STRING
|
||||||
if (env.QUERY_STRING)
|
if (env.QUERY_STRING)
|
||||||
|
|||||||
@@ -1,14 +1,4 @@
|
|||||||
Status: 200 OK
|
Status: 302 Found
|
||||||
|
Location: http://{{env.SERVER_ADDR}}/hotspot/?redir={{env.headers.host}}
|
||||||
Content-Type: text/html
|
Content-Type: text/html
|
||||||
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
|
||||||
<meta http-equiv="refresh" content="0; URL=http://{{env.SERVER_ADDR}}/hotspot/?redir={{env.headers.host}}" />
|
|
||||||
</head>
|
|
||||||
<body style="background-color: white">
|
|
||||||
<a style="color: black; font-family: arial, helvetica, sans-serif;" href="http://{{env.SERVER_ADDR}}/hotspot">HotSpot Login</a>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
let uci = require('uci').cursor();
|
||||||
|
let config = uci.get_all('uspot');
|
||||||
|
|
||||||
global.handle_request = function(env) {
|
global.handle_request = function(env) {
|
||||||
|
if (env.REMOTE_ADDR && config.config.debug)
|
||||||
|
warn('uspot: ' + env.REMOTE_ADDR + ' - CPD redirect\n');
|
||||||
include('cpd.uc', { env });
|
include('cpd.uc', { env });
|
||||||
};
|
};
|
||||||
%}
|
%}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ function auth_client(ctx) {
|
|||||||
let password;
|
let password;
|
||||||
let payload = portal.radius_init(ctx);
|
let payload = portal.radius_init(ctx);
|
||||||
|
|
||||||
|
payload.logoff_url = sprintf('http://%s:3990/logoff', ctx.env.SERVER_ADDR);
|
||||||
if (ctx.query_string.username && ctx.query_string.response) {
|
if (ctx.query_string.username && ctx.query_string.response) {
|
||||||
let challenge = uam.md5(portal.config.uam.challenge, ctx.mac);
|
let challenge = uam.md5(portal.config.uam.challenge, ctx.format_mac);
|
||||||
|
|
||||||
payload.type = 'uam-chap-auth';
|
|
||||||
payload.username = ctx.query_string.username;
|
payload.username = ctx.query_string.username;
|
||||||
payload.chap_password = ctx.query_string.response;
|
payload.chap_password = ctx.query_string.response;
|
||||||
if (portal.config.uam.secret)
|
if (portal.config.uam.secret)
|
||||||
@@ -23,24 +23,44 @@ function auth_client(ctx) {
|
|||||||
else
|
else
|
||||||
payload.chap_challenge = challenge;
|
payload.chap_challenge = challenge;
|
||||||
} else if (ctx.query_string.username && ctx.query_string.password) {
|
} else if (ctx.query_string.username && ctx.query_string.password) {
|
||||||
payload.type = 'uam-auth';
|
payload.username = ctx.query_string.username;
|
||||||
payload.username = ctx.mac;
|
payload.password = uam.password(uam.md5(portal.config.uam.challenge, ctx.format_mac), ctx.query_string.password, portal.config.uam.uam_secret);
|
||||||
payload.password = uam.password(uam.md5(portal.config.uam.challenge, ctx.mac), ctx.query_string.password, portal.config.uam.uam_secret);
|
} else
|
||||||
}
|
include('error.uc', ctx);
|
||||||
|
|
||||||
let reply = portal.radius_call(ctx, payload);
|
let radius = portal.radius_call(ctx, payload);
|
||||||
if (reply['access-accept']) {
|
if (radius['access-accept']) {
|
||||||
portal.allow_client(ctx);
|
portal.allow_client(ctx, { radius: { reply: radius.reply, request: payload } } );
|
||||||
return;
|
|
||||||
}
|
payload = portal.radius_init(ctx, payload.acct_session);
|
||||||
|
payload.acct = true;
|
||||||
|
payload.username = ctx.query_string.username;
|
||||||
|
payload.acct_type = 1;
|
||||||
|
portal.radius_call(ctx, payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
include('error.uc', ctx);
|
include('error.uc', ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
global.handle_request = function(env) {
|
// disconnect client
|
||||||
let ctx = portal.handle_request(env);
|
function deauth_client(ctx) {
|
||||||
|
portal.logoff(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx)
|
global.handle_request = function(env) {
|
||||||
|
let ctx = portal.handle_request(env, true);
|
||||||
|
|
||||||
|
switch (split(ctx.env.REQUEST_URI, '?')[0] || '') {
|
||||||
|
case '/logon':
|
||||||
auth_client(ctx);
|
auth_client(ctx);
|
||||||
|
break;
|
||||||
|
case '/logoff':
|
||||||
|
deauth_client(ctx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
include('error.uc', ctx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ let portal = require('common');
|
|||||||
|
|
||||||
// delegate an initial connection to the correct handler
|
// delegate an initial connection to the correct handler
|
||||||
function request_start(ctx) {
|
function request_start(ctx) {
|
||||||
|
portal.debug(ctx, 'start ' + (portal.config?.config?.auth_mode || '') + ' flow');
|
||||||
switch (portal.config?.config?.auth_mode) {
|
switch (portal.config?.config?.auth_mode) {
|
||||||
case 'click-to-continue':
|
case 'click-to-continue':
|
||||||
include('click.uc', ctx);
|
include('click.uc', ctx);
|
||||||
@@ -22,12 +23,14 @@ function request_start(ctx) {
|
|||||||
'?res=notyet' +
|
'?res=notyet' +
|
||||||
'&uamip=' + ctx.env.SERVER_ADDR +
|
'&uamip=' + ctx.env.SERVER_ADDR +
|
||||||
'&uamport=' + portal.config.uam.uam_port +
|
'&uamport=' + portal.config.uam.uam_port +
|
||||||
'&challenge=' + portal.uam.md5(portal.config.uam.challenge, ctx.mac) +
|
'&challenge=' + portal.uam.md5(portal.config.uam.challenge, ctx.format_mac) +
|
||||||
'&mac=' + replace(ctx.mac, ':', '-') +
|
'&mac=' + ctx.format_mac +
|
||||||
'&ip=' + ctx.env.REMOTE_ADDR +
|
'&ip=' + ctx.env.REMOTE_ADDR +
|
||||||
'&called=' + portal.config.uam.nasmac +
|
'&called=' + portal.config.uam.nasmac +
|
||||||
'&nasid=' + portal.config.uam.nasid;
|
'&nasid=' + portal.config.uam.nasid +
|
||||||
ctx.redir_location += '&md=' + portal.uam.md5(ctx.uam_location, portal.config.uam.uam_secret);
|
'&ssid=' + ctx.ssid;
|
||||||
|
if (portal.config.uam.uam_secret)
|
||||||
|
ctx.redir_location += '&md=' + portal.uam.md5(ctx.redir_location, portal.config.uam.uam_secret);
|
||||||
include('redir.uc', ctx);
|
include('redir.uc', ctx);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
@@ -46,6 +49,7 @@ function request_click(ctx) {
|
|||||||
|
|
||||||
// check if a username and password was provided
|
// check if a username and password was provided
|
||||||
if (ctx.form_data.accept_terms != 'clicked') {
|
if (ctx.form_data.accept_terms != 'clicked') {
|
||||||
|
portal.debug(ctx, 'user did not accept conditions');
|
||||||
request_start({ ...ctx, error: 1 });
|
request_start({ ...ctx, error: 1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -62,6 +66,7 @@ function request_credentials(ctx) {
|
|||||||
|
|
||||||
// check if a username and password was provided
|
// check if a username and password was provided
|
||||||
if (!ctx.form_data.username || !ctx.form_data.password) {
|
if (!ctx.form_data.username || !ctx.form_data.password) {
|
||||||
|
portal.debug(ctx, 'missing credentials\n');
|
||||||
request_start({ ...ctx, error: 1 });
|
request_start({ ...ctx, error: 1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -76,11 +81,12 @@ function request_credentials(ctx) {
|
|||||||
ctx.form_data.password != cred.password)
|
ctx.form_data.password != cred.password)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
portal.allow_client(ctx);
|
portal.allow_client(ctx, { username: ctx.form_data.username });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auth failed
|
// auth failed
|
||||||
|
portal.debug(ctx, 'invalid credentials\n');
|
||||||
request_start({ ...ctx, error: 1 });
|
request_start({ ...ctx, error: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,23 +100,25 @@ function request_radius(ctx) {
|
|||||||
|
|
||||||
// check if a username and password was provided
|
// check if a username and password was provided
|
||||||
if (!ctx.form_data.username || !ctx.form_data.password) {
|
if (!ctx.form_data.username || !ctx.form_data.password) {
|
||||||
|
portal.debug(ctx, 'missing credentials\n');
|
||||||
request_start({ ...ctx, error: 1 });
|
request_start({ ...ctx, error: 1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger the radius auth
|
// trigger the radius auth
|
||||||
let payload = radius_init(ctx);
|
let payload = portal.radius_init(ctx);
|
||||||
payload.type = 'auth';
|
payload.type = 'auth';
|
||||||
payload.username = ctx.form_data.username;
|
payload.username = ctx.form_data.username;
|
||||||
payload.password = ctx.form_data.password;
|
payload.password = ctx.form_data.password;
|
||||||
|
|
||||||
let reply = portal.radius_call(ctx, payload);
|
let radius = portal.radius_call(ctx, payload);
|
||||||
if (reply['access-accept']) {
|
if (radius['access-accept']) {
|
||||||
portal.allow_client(ctx);
|
portal.allow_client(ctx, { username: ctx.form_data.username, radius: { reply: radius.reply, request: payload } } );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auth failed
|
// auth failed
|
||||||
|
portal.debug(ctx, 'invalid credentials\n');
|
||||||
request_start({ ...ctx, error: 1 });
|
request_start({ ...ctx, error: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
feeds/ucentral/uspot/files/usr/share/uspot/logoff.uc
Normal file
4
feeds/ucentral/uspot/files/usr/share/uspot/logoff.uc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Status: 200 OK
|
||||||
|
Content-Type: text/html
|
||||||
|
|
||||||
|
<h1> You are now logged-off </h1>
|
||||||
@@ -9,8 +9,10 @@
|
|||||||
#include <libubox/blobmsg_json.h>
|
#include <libubox/blobmsg_json.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RADIUS_TYPE,
|
RADIUS_ACCT,
|
||||||
RADIUS_SERVER,
|
RADIUS_SERVER,
|
||||||
|
RADIUS_ACCT_SERVER,
|
||||||
|
RADIUS_ACCT_TYPE,
|
||||||
RADIUS_USERNAME,
|
RADIUS_USERNAME,
|
||||||
RADIUS_PASSWORD,
|
RADIUS_PASSWORD,
|
||||||
RADIUS_CHAP_PASSWORD,
|
RADIUS_CHAP_PASSWORD,
|
||||||
@@ -21,12 +23,23 @@ enum {
|
|||||||
RADIUS_CALLING_STATION,
|
RADIUS_CALLING_STATION,
|
||||||
RADIUS_NAS_IP,
|
RADIUS_NAS_IP,
|
||||||
RADIUS_NAS_ID,
|
RADIUS_NAS_ID,
|
||||||
|
RADIUS_TERMINATE_CAUSE,
|
||||||
|
RADIUS_SESSION_TIME,
|
||||||
|
RADIUS_INPUT_OCTETS,
|
||||||
|
RADIUS_OUTPUT_OCTETS,
|
||||||
|
RADIUS_INPUT_GIGAWORDS,
|
||||||
|
RADIUS_OUTPUT_GIGAWORDS,
|
||||||
|
RADIUS_INPUT_PACKETS,
|
||||||
|
RADIUS_OUTPUT_PACKETS,
|
||||||
|
RADIUS_LOGOFF_URL,
|
||||||
__RADIUS_MAX,
|
__RADIUS_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct blobmsg_policy radius_policy[__RADIUS_MAX] = {
|
static const struct blobmsg_policy radius_policy[__RADIUS_MAX] = {
|
||||||
[RADIUS_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_ACCT] = { .name = "acct", .type = BLOBMSG_TYPE_BOOL },
|
||||||
[RADIUS_SERVER] = { .name = "server", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_SERVER] = { .name = "server", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[RADIUS_ACCT_SERVER] = { .name = "acct_server", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[RADIUS_ACCT_TYPE] = { .name = "acct_type", .type = BLOBMSG_TYPE_INT32 },
|
||||||
[RADIUS_USERNAME] = { .name = "username", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_USERNAME] = { .name = "username", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RADIUS_PASSWORD] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_PASSWORD] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RADIUS_CHAP_PASSWORD] = { .name = "chap_password", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_CHAP_PASSWORD] = { .name = "chap_password", .type = BLOBMSG_TYPE_STRING },
|
||||||
@@ -37,23 +50,17 @@ static const struct blobmsg_policy radius_policy[__RADIUS_MAX] = {
|
|||||||
[RADIUS_CALLING_STATION] = { .name = "calling_station", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_CALLING_STATION] = { .name = "calling_station", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RADIUS_NAS_IP] = { .name = "nas_ip", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_NAS_IP] = { .name = "nas_ip", .type = BLOBMSG_TYPE_STRING },
|
||||||
[RADIUS_NAS_ID] = { .name = "nas_id", .type = BLOBMSG_TYPE_STRING },
|
[RADIUS_NAS_ID] = { .name = "nas_id", .type = BLOBMSG_TYPE_STRING },
|
||||||
|
[RADIUS_TERMINATE_CAUSE] = { .name = "terminate_cause", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_SESSION_TIME] = { .name = "session_time", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_INPUT_OCTETS] = { .name = "input_octets", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_OUTPUT_OCTETS] = { .name = "output_octets", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_INPUT_GIGAWORDS] = { .name = "input_gigawords", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_OUTPUT_GIGAWORDS] = { .name = "output_gigawords", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_INPUT_PACKETS] = { .name = "input_packets", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_OUTPUT_PACKETS] = { .name = "output_packets", .type = BLOBMSG_TYPE_INT32 },
|
||||||
|
[RADIUS_LOGOFF_URL] = { .name = "logoff_url", .type = BLOBMSG_TYPE_STRING },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct config {
|
|
||||||
char *type;
|
|
||||||
char *server;
|
|
||||||
char *username;
|
|
||||||
char *password;
|
|
||||||
char chap_password[17];
|
|
||||||
char chap_challenge[16];
|
|
||||||
char *acct_session;
|
|
||||||
struct sockaddr_in client_ip;
|
|
||||||
char *called_station;
|
|
||||||
char *calling_station;
|
|
||||||
struct sockaddr_in nas_ip;
|
|
||||||
char *nas_id;
|
|
||||||
} config;
|
|
||||||
|
|
||||||
static struct blob_buf b = {};
|
static struct blob_buf b = {};
|
||||||
static struct blob_attr *tb[__RADIUS_MAX] = {};
|
static struct blob_attr *tb[__RADIUS_MAX] = {};
|
||||||
|
|
||||||
@@ -104,266 +111,158 @@ result(rc_handle const *rh, int accept, VALUE_PAIR *pair)
|
|||||||
return accept;
|
return accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
config_load(void)
|
radius(void)
|
||||||
{
|
|
||||||
if (tb[RADIUS_TYPE])
|
|
||||||
config.type = blobmsg_get_string(tb[RADIUS_TYPE]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_SERVER])
|
|
||||||
config.server = blobmsg_get_string(tb[RADIUS_SERVER]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_USERNAME])
|
|
||||||
config.username = blobmsg_get_string(tb[RADIUS_USERNAME]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_PASSWORD])
|
|
||||||
config.password = blobmsg_get_string(tb[RADIUS_PASSWORD]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_CHAP_PASSWORD]) {
|
|
||||||
*config.chap_password = '\0';
|
|
||||||
str_to_hex(blobmsg_get_string(tb[RADIUS_CHAP_PASSWORD]), &config.chap_password[1], 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tb[RADIUS_CHAP_CHALLENGE])
|
|
||||||
str_to_hex(blobmsg_get_string(tb[RADIUS_CHAP_CHALLENGE]), config.chap_challenge, 16);
|
|
||||||
|
|
||||||
if (tb[RADIUS_ACCT_SESSION])
|
|
||||||
config.acct_session = blobmsg_get_string(tb[RADIUS_ACCT_SESSION]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_CLIENT_IP]) {
|
|
||||||
inet_pton(AF_INET, blobmsg_get_string(tb[RADIUS_CLIENT_IP]), &(config.client_ip.sin_addr));
|
|
||||||
config.client_ip.sin_addr.s_addr = ntohl(config.client_ip.sin_addr.s_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tb[RADIUS_CALLED_STATION])
|
|
||||||
config.called_station = blobmsg_get_string(tb[RADIUS_CALLED_STATION]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_CALLING_STATION])
|
|
||||||
config.calling_station = blobmsg_get_string(tb[RADIUS_CALLING_STATION]);
|
|
||||||
|
|
||||||
if (tb[RADIUS_NAS_IP]) {
|
|
||||||
inet_pton(AF_INET, blobmsg_get_string(tb[RADIUS_NAS_IP]), &(config.nas_ip.sin_addr));
|
|
||||||
config.nas_ip.sin_addr.s_addr = ntohl(config.nas_ip.sin_addr.s_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tb[RADIUS_NAS_ID])
|
|
||||||
config.nas_id = blobmsg_get_string(tb[RADIUS_NAS_ID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static rc_handle *
|
|
||||||
radius_init(void)
|
|
||||||
{
|
{
|
||||||
|
VALUE_PAIR *send = NULL, *received;
|
||||||
|
struct sockaddr_in client_ip = {};
|
||||||
|
struct sockaddr_in nas_ip = {};
|
||||||
|
char chap_challenge[16] = {};
|
||||||
|
char chap_password[17] = {};
|
||||||
rc_handle *rh = rc_new();
|
rc_handle *rh = rc_new();
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
if (rh == NULL)
|
if (rh == NULL)
|
||||||
return NULL;
|
return result(rh, 0, NULL);;
|
||||||
|
|
||||||
rh = rc_config_init(rh);
|
rh = rc_config_init(rh);
|
||||||
if (rh == NULL)
|
if (rh == NULL)
|
||||||
return NULL;
|
return result(rh, 0, NULL);;
|
||||||
|
|
||||||
rc_add_config(rh, "authserver", config.server, "code", __LINE__);
|
if (tb[RADIUS_SERVER])
|
||||||
|
rc_add_config(rh, "authserver", blobmsg_get_string(tb[RADIUS_SERVER]), "code", __LINE__);
|
||||||
|
|
||||||
|
if (tb[RADIUS_ACCT_SERVER])
|
||||||
|
rc_add_config(rh, "acctserver", blobmsg_get_string(tb[RADIUS_ACCT_SERVER]), "code", __LINE__);
|
||||||
rc_add_config(rh, "servers", "/tmp/radius.servers", "code", __LINE__);
|
rc_add_config(rh, "servers", "/tmp/radius.servers", "code", __LINE__);
|
||||||
rc_add_config(rh, "dictionary", "/etc/radcli/dictionary", "code", __LINE__);
|
rc_add_config(rh, "dictionary", "/etc/radcli/dictionary", "code", __LINE__);
|
||||||
rc_add_config(rh, "radius_timeout", "5", "code", __LINE__);
|
rc_add_config(rh, "radius_timeout", "2", "code", __LINE__);
|
||||||
rc_add_config(rh, "radius_retries", "1", "code", __LINE__);
|
rc_add_config(rh, "radius_retries", "1", "code", __LINE__);
|
||||||
rc_add_config(rh, "bindaddr", "*", "code", __LINE__);
|
rc_add_config(rh, "bindaddr", "*", "code", __LINE__);
|
||||||
|
|
||||||
if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0)
|
if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return rh;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
auth(void)
|
|
||||||
{
|
|
||||||
VALUE_PAIR *send = NULL, *received;
|
|
||||||
rc_handle *rh = NULL;
|
|
||||||
|
|
||||||
if (!config.server || !config.username || !config.password)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
rh = radius_init();
|
|
||||||
if (!rh)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, config.username, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, config.password, -1, 0) == NULL)
|
if (tb[RADIUS_ACCT_TYPE]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_ACCT_TYPE]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_USERNAME])
|
||||||
|
if (rc_avpair_add(rh, &send, PW_USER_NAME, blobmsg_get_string(tb[RADIUS_USERNAME]), -1, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_PASSWORD])
|
||||||
|
if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, blobmsg_get_string(tb[RADIUS_PASSWORD]), -1, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_CHAP_PASSWORD]) {
|
||||||
|
str_to_hex(blobmsg_get_string(tb[RADIUS_CHAP_PASSWORD]), &chap_password[1], 16);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_CHAP_PASSWORD, chap_password, 17, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_CHAP_CHALLENGE]) {
|
||||||
|
str_to_hex(blobmsg_get_string(tb[RADIUS_CHAP_CHALLENGE]), chap_challenge, 16);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_CHAP_CHALLENGE, chap_challenge, 16, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_ACCT_SESSION])
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, blobmsg_get_string(tb[RADIUS_ACCT_SESSION]), -1, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_CLIENT_IP]) {
|
||||||
|
inet_pton(AF_INET, blobmsg_get_string(tb[RADIUS_CLIENT_IP]), &(client_ip.sin_addr));
|
||||||
|
client_ip.sin_addr.s_addr = ntohl(client_ip.sin_addr.s_addr);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_FRAMED_IP_ADDRESS, &client_ip.sin_addr, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_CALLED_STATION])
|
||||||
|
if (rc_avpair_add(rh, &send, PW_CALLED_STATION_ID, blobmsg_get_string(tb[RADIUS_CALLED_STATION]), -1, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_LOGOFF_URL])
|
||||||
|
if (rc_avpair_add(rh, &send, 3, blobmsg_get_string(tb[RADIUS_LOGOFF_URL]), -1, 14122) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_CALLING_STATION])
|
||||||
|
if (rc_avpair_add(rh, &send, PW_CALLING_STATION_ID, blobmsg_get_string(tb[RADIUS_CALLING_STATION]), -1, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_NAS_IP]) {
|
||||||
|
inet_pton(AF_INET, blobmsg_get_string(tb[RADIUS_NAS_IP]), &(nas_ip.sin_addr));
|
||||||
|
nas_ip.sin_addr.s_addr = ntohl(nas_ip.sin_addr.s_addr);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_NAS_IP_ADDRESS, &nas_ip.sin_addr, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_NAS_ID])
|
||||||
|
if (rc_avpair_add(rh, &send, PW_NAS_IDENTIFIER, blobmsg_get_string(tb[RADIUS_NAS_ID]), -1, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
|
if (tb[RADIUS_TERMINATE_CAUSE]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_TERMINATE_CAUSE]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_TERMINATE_CAUSE, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_SESSION_TIME]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_SESSION_TIME]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_TIME, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_INPUT_OCTETS]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_INPUT_OCTETS]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_OCTETS, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_OUTPUT_OCTETS]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_OUTPUT_OCTETS]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_OCTETS, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_INPUT_GIGAWORDS]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_INPUT_GIGAWORDS]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_GIGAWORDS, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_OUTPUT_GIGAWORDS]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_OUTPUT_GIGAWORDS]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_GIGAWORDS, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_INPUT_PACKETS]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_INPUT_PACKETS]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_PACKETS, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[RADIUS_OUTPUT_PACKETS]) {
|
||||||
|
val = blobmsg_get_u32(tb[RADIUS_OUTPUT_PACKETS]);
|
||||||
|
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_PACKETS, &val, 4, 0) == NULL)
|
||||||
|
return result(rh, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = 19;
|
||||||
|
if (rc_avpair_add(rh, &send, PW_NAS_PORT_TYPE, &val, 4, 0) == NULL)
|
||||||
return result(rh, 0, NULL);
|
return result(rh, 0, NULL);
|
||||||
|
|
||||||
rc_apply_config(rh);
|
rc_apply_config(rh);
|
||||||
if (rc_auth(rh, 0, send, &received, NULL) == OK_RC)
|
if (tb[RADIUS_ACCT] && blobmsg_get_bool(tb[RADIUS_ACCT])) {
|
||||||
return result(rh, 1, received);
|
if (rc_acct(rh, 0, send) == OK_RC)
|
||||||
|
return result(rh, 1, NULL);
|
||||||
return result(rh, 0, NULL);
|
} else {
|
||||||
}
|
if (rc_auth(rh, 0, send, &received, NULL) == OK_RC)
|
||||||
|
return result(rh, 1, received);
|
||||||
static int
|
}
|
||||||
uam_auth(void)
|
|
||||||
{
|
|
||||||
VALUE_PAIR *send = NULL, *received;
|
|
||||||
rc_handle *rh = NULL;
|
|
||||||
|
|
||||||
if (!config.server || !config.username || !config.password ||
|
|
||||||
!config.acct_session || !config.called_station ||
|
|
||||||
!config.calling_station || !config.nas_id)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
rh = radius_init();
|
|
||||||
if (!rh)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, config.username, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, config.password, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, config.acct_session, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_FRAMED_IP_ADDRESS, &config.client_ip.sin_addr, 4, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
//if (rc_avpair_add(rh, &send, PW_NAS_PORT_TYPE, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
//if (rc_avpair_add(rh, &send, PW_NAS_PORT, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
// if (rc_avpair_add(rh, &send, PW_NAS_PORT_ID_STRING, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CALLED_STATION_ID, config.called_station, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CALLING_STATION_ID, config.calling_station, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_NAS_IP_ADDRESS, &config.nas_ip.sin_addr, 4, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_NAS_IDENTIFIER, config.nas_id, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
rc_apply_config(rh);
|
|
||||||
if (rc_auth(rh, 0, send, &received, NULL) == OK_RC)
|
|
||||||
return result(rh, 1, received);
|
|
||||||
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
uam_chap_auth(void)
|
|
||||||
{
|
|
||||||
VALUE_PAIR *send = NULL, *received;
|
|
||||||
rc_handle *rh = NULL;
|
|
||||||
|
|
||||||
if (!config.server || !config.username ||
|
|
||||||
!config.acct_session || !config.called_station ||
|
|
||||||
!config.calling_station || !config.nas_id)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
rh = radius_init();
|
|
||||||
if (!rh)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, config.username, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CHAP_PASSWORD, config.chap_password, 17, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CHAP_CHALLENGE, config.chap_challenge, 16, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, config.acct_session, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_FRAMED_IP_ADDRESS, &config.client_ip.sin_addr, 4, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
//if (rc_avpair_add(rh, &send, PW_NAS_PORT_TYPE, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
//if (rc_avpair_add(rh, &send, PW_NAS_PORT, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
// if (rc_avpair_add(rh, &send, PW_NAS_PORT_ID_STRING, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CALLED_STATION_ID, config.called_station, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CALLING_STATION_ID, config.calling_station, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_NAS_IP_ADDRESS, &config.nas_ip.sin_addr, 4, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_NAS_IDENTIFIER, config.nas_id, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
rc_apply_config(rh);
|
|
||||||
if (rc_auth(rh, 0, send, &received, NULL) == OK_RC)
|
|
||||||
return result(rh, 1, received);
|
|
||||||
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
uam_acct(void)
|
|
||||||
{
|
|
||||||
VALUE_PAIR *send = NULL, *received;
|
|
||||||
rc_handle *rh = NULL;
|
|
||||||
|
|
||||||
if (!config.server || !config.username || !config.password ||
|
|
||||||
!config.acct_session || !config.called_station ||
|
|
||||||
!config.calling_station || !config.nas_id)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
rh = radius_init();
|
|
||||||
if (!rh)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, config.username, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, config.password, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, config.acct_session, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_FRAMED_IP_ADDRESS, &config.client_ip.sin_addr, 4, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
//if (rc_avpair_add(rh, &send, PW_NAS_PORT_TYPE, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
//if (rc_avpair_add(rh, &send, PW_NAS_PORT, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
// if (rc_avpair_add(rh, &send, PW_NAS_PORT_ID_STRING, , -1, 0) == NULL)
|
|
||||||
// return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CALLED_STATION_ID, config.called_station, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_CALLING_STATION_ID, config.calling_station, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_NAS_IP_ADDRESS, &config.nas_ip.sin_addr, 4, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
if (rc_avpair_add(rh, &send, PW_NAS_IDENTIFIER, config.nas_id, -1, 0) == NULL)
|
|
||||||
return result(rh, 0, NULL);
|
|
||||||
|
|
||||||
rc_apply_config(rh);
|
|
||||||
if (rc_auth(rh, 0, send, &received, NULL) == OK_RC)
|
|
||||||
return result(rh, 1, received);
|
|
||||||
|
|
||||||
return result(rh, 0, NULL);
|
return result(rh, 0, NULL);
|
||||||
}
|
}
|
||||||
@@ -380,21 +279,5 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
blobmsg_parse(radius_policy, __RADIUS_MAX, tb, blob_data(b.head), blob_len(b.head));
|
blobmsg_parse(radius_policy, __RADIUS_MAX, tb, blob_data(b.head), blob_len(b.head));
|
||||||
|
|
||||||
config_load();
|
return radius();
|
||||||
if (!config.type)
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (!strcmp(config.type, "auth"))
|
|
||||||
return auth();
|
|
||||||
|
|
||||||
if (!strcmp(config.type, "uam-auth"))
|
|
||||||
return uam_auth();
|
|
||||||
|
|
||||||
if (!strcmp(config.type, "uam-chap-auth"))
|
|
||||||
return uam_chap_auth();
|
|
||||||
|
|
||||||
if (!strcmp(config.type, "uam-acct"))
|
|
||||||
return uam_acct();
|
|
||||||
|
|
||||||
return result(NULL, 0, NULL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user