mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 10:18:21 -05:00
hostapd: Dynamic MAC ACL management over control interface
Previously, MAC ACL could be modified only through file operations (modify accept/deny_mac_file and reload it to hostapd). Extend this to allow MAC ACL to be modified and displayed through new control interface commands: ACCEPT_ACL <subcmd> [argument] DENY_ACL <subcmd> [argument] subcmd: ADD_MAC <addr>[ VLAN_ID=<id>]|DEL_MAC <addr>|SHOW|CLEAR Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
This commit is contained in:
parent
6a252ece24
commit
3988046de5
@ -113,7 +113,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
|
|||||||
#endif /* CONFIG_NO_VLAN */
|
#endif /* CONFIG_NO_VLAN */
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_acl_comp(const void *a, const void *b)
|
int hostapd_acl_comp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
const struct mac_acl_entry *aa = a;
|
const struct mac_acl_entry *aa = a;
|
||||||
const struct mac_acl_entry *bb = b;
|
const struct mac_acl_entry *bb = b;
|
||||||
@ -121,6 +121,44 @@ static int hostapd_acl_comp(const void *a, const void *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num,
|
||||||
|
int vlan_id, const u8 *addr)
|
||||||
|
{
|
||||||
|
struct mac_acl_entry *newacl;
|
||||||
|
|
||||||
|
newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
|
||||||
|
if (!newacl) {
|
||||||
|
wpa_printf(MSG_ERROR, "MAC list reallocation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*acl = newacl;
|
||||||
|
os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
|
||||||
|
os_memset(&(*acl)[*num].vlan_id, 0, sizeof((*acl)[*num].vlan_id));
|
||||||
|
(*acl)[*num].vlan_id.untagged = vlan_id;
|
||||||
|
(*acl)[*num].vlan_id.notempty = !!vlan_id;
|
||||||
|
(*num)++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num,
|
||||||
|
const u8 *addr)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < *num) {
|
||||||
|
if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) == 0) {
|
||||||
|
os_remove_in_array(*acl, *num, sizeof(**acl), i);
|
||||||
|
(*num)--;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_config_read_maclist(const char *fname,
|
static int hostapd_config_read_maclist(const char *fname,
|
||||||
struct mac_acl_entry **acl, int *num)
|
struct mac_acl_entry **acl, int *num)
|
||||||
{
|
{
|
||||||
@ -128,7 +166,6 @@ static int hostapd_config_read_maclist(const char *fname,
|
|||||||
char buf[128], *pos;
|
char buf[128], *pos;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
struct mac_acl_entry *newacl;
|
|
||||||
int vlan_id;
|
int vlan_id;
|
||||||
|
|
||||||
f = fopen(fname, "r");
|
f = fopen(fname, "r");
|
||||||
@ -138,7 +175,7 @@ static int hostapd_config_read_maclist(const char *fname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), f)) {
|
while (fgets(buf, sizeof(buf), f)) {
|
||||||
int i, rem = 0;
|
int rem = 0;
|
||||||
|
|
||||||
line++;
|
line++;
|
||||||
|
|
||||||
@ -168,16 +205,7 @@ static int hostapd_config_read_maclist(const char *fname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rem) {
|
if (rem) {
|
||||||
i = 0;
|
hostapd_remove_acl_mac(acl, num, addr);
|
||||||
while (i < *num) {
|
|
||||||
if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) ==
|
|
||||||
0) {
|
|
||||||
os_remove_in_array(*acl, *num,
|
|
||||||
sizeof(**acl), i);
|
|
||||||
(*num)--;
|
|
||||||
} else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vlan_id = 0;
|
vlan_id = 0;
|
||||||
@ -189,22 +217,10 @@ static int hostapd_config_read_maclist(const char *fname,
|
|||||||
if (*pos != '\0')
|
if (*pos != '\0')
|
||||||
vlan_id = atoi(pos);
|
vlan_id = atoi(pos);
|
||||||
|
|
||||||
newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
|
if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0)
|
||||||
if (newacl == NULL) {
|
|
||||||
wpa_printf(MSG_ERROR, "MAC list reallocation failed");
|
|
||||||
fclose(f);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*acl = newacl;
|
|
||||||
os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
|
|
||||||
os_memset(&(*acl)[*num].vlan_id, 0,
|
|
||||||
sizeof((*acl)[*num].vlan_id));
|
|
||||||
(*acl)[*num].vlan_id.untagged = vlan_id;
|
|
||||||
(*acl)[*num].vlan_id.notempty = !!vlan_id;
|
|
||||||
(*num)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if (*acl)
|
if (*acl)
|
||||||
|
@ -13,5 +13,10 @@ struct hostapd_config * hostapd_config_read(const char *fname);
|
|||||||
int hostapd_set_iface(struct hostapd_config *conf,
|
int hostapd_set_iface(struct hostapd_config *conf,
|
||||||
struct hostapd_bss_config *bss, const char *field,
|
struct hostapd_bss_config *bss, const char *field,
|
||||||
char *value);
|
char *value);
|
||||||
|
int hostapd_acl_comp(const void *a, const void *b);
|
||||||
|
int hostapd_add_acl_maclist(struct mac_acl_entry **acl, int *num,
|
||||||
|
int vlan_id, const u8 *addr);
|
||||||
|
void hostapd_remove_acl_mac(struct mac_acl_entry **acl, int *num,
|
||||||
|
const u8 *addr);
|
||||||
|
|
||||||
#endif /* CONFIG_FILE_H */
|
#endif /* CONFIG_FILE_H */
|
||||||
|
@ -1248,6 +1248,42 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_disassoc_accept_mac(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct sta_info *sta;
|
||||||
|
struct vlan_description vlan_id;
|
||||||
|
|
||||||
|
if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
|
if (!hostapd_maclist_found(hapd->conf->accept_mac,
|
||||||
|
hapd->conf->num_accept_mac,
|
||||||
|
sta->addr, &vlan_id) ||
|
||||||
|
(vlan_id.notempty &&
|
||||||
|
vlan_compare(&vlan_id, sta->vlan_desc)))
|
||||||
|
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||||
|
WLAN_REASON_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct sta_info *sta;
|
||||||
|
struct vlan_description vlan_id;
|
||||||
|
|
||||||
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
|
if (hostapd_maclist_found(hapd->conf->deny_mac,
|
||||||
|
hapd->conf->num_deny_mac, sta->addr,
|
||||||
|
&vlan_id) &&
|
||||||
|
(!vlan_id.notempty ||
|
||||||
|
!vlan_compare(&vlan_id, sta->vlan_desc)))
|
||||||
|
ap_sta_disconnect(hapd, sta, sta->addr,
|
||||||
|
WLAN_REASON_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
@ -1332,38 +1368,14 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||||||
hapd->dpp_configurator_params = os_strdup(value);
|
hapd->dpp_configurator_params = os_strdup(value);
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
} else {
|
} else {
|
||||||
struct sta_info *sta;
|
|
||||||
struct vlan_description vlan_id;
|
|
||||||
|
|
||||||
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
|
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
|
if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
hostapd_disassoc_deny_mac(hapd);
|
||||||
if (hostapd_maclist_found(
|
} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
|
||||||
hapd->conf->deny_mac,
|
hostapd_disassoc_accept_mac(hapd);
|
||||||
hapd->conf->num_deny_mac, sta->addr,
|
|
||||||
&vlan_id) &&
|
|
||||||
(!vlan_id.notempty ||
|
|
||||||
!vlan_compare(&vlan_id, sta->vlan_desc)))
|
|
||||||
ap_sta_disconnect(
|
|
||||||
hapd, sta, sta->addr,
|
|
||||||
WLAN_REASON_UNSPECIFIED);
|
|
||||||
}
|
|
||||||
} else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
|
|
||||||
os_strcasecmp(cmd, "accept_mac_file") == 0) {
|
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
|
||||||
if (!hostapd_maclist_found(
|
|
||||||
hapd->conf->accept_mac,
|
|
||||||
hapd->conf->num_accept_mac,
|
|
||||||
sta->addr, &vlan_id) ||
|
|
||||||
(vlan_id.notempty &&
|
|
||||||
vlan_compare(&vlan_id, sta->vlan_desc)))
|
|
||||||
ap_sta_disconnect(
|
|
||||||
hapd, sta, sta->addr,
|
|
||||||
WLAN_REASON_UNSPECIFIED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2683,6 +2695,80 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
|
||||||
|
const char *txtaddr)
|
||||||
|
{
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
struct vlan_description vlan_id;
|
||||||
|
|
||||||
|
if (!(*num))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (hwaddr_aton(txtaddr, addr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hostapd_maclist_found(*acl, *num, addr, &vlan_id))
|
||||||
|
hostapd_remove_acl_mac(acl, num, addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl,
|
||||||
|
int *num)
|
||||||
|
{
|
||||||
|
while (*num)
|
||||||
|
hostapd_remove_acl_mac(acl, num, (*acl)[0].addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num,
|
||||||
|
char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
int i = 0, len = 0, ret = 0;
|
||||||
|
|
||||||
|
if (!acl)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (i < num) {
|
||||||
|
ret = os_snprintf(buf + len, buflen - len,
|
||||||
|
MACSTR " VLAN_ID=%d\n",
|
||||||
|
MAC2STR(acl[i].addr),
|
||||||
|
acl[i].vlan_id.untagged);
|
||||||
|
if (ret < 0 || (size_t) ret >= buflen - len)
|
||||||
|
return len;
|
||||||
|
i++;
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num,
|
||||||
|
const char *cmd)
|
||||||
|
{
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
struct vlan_description vlan_id;
|
||||||
|
int ret = 0, vlanid = 0;
|
||||||
|
const char *pos;
|
||||||
|
|
||||||
|
if (hwaddr_aton(cmd, addr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, "VLAN_ID=");
|
||||||
|
if (pos)
|
||||||
|
vlanid = atoi(pos + 8);
|
||||||
|
|
||||||
|
if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) {
|
||||||
|
ret = hostapd_add_acl_maclist(acl, num, vlanid, addr);
|
||||||
|
if (ret != -1 && *acl)
|
||||||
|
qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret < 0 ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||||
char *buf, char *reply,
|
char *buf, char *reply,
|
||||||
int reply_size,
|
int reply_size,
|
||||||
@ -2983,6 +3069,46 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||||||
reply_size);
|
reply_size);
|
||||||
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
} else if (os_strcmp(buf, "TERMINATE") == 0) {
|
||||||
eloop_terminate();
|
eloop_terminate();
|
||||||
|
} else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) {
|
||||||
|
if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) {
|
||||||
|
if (!hostapd_ctrl_iface_acl_add_mac(
|
||||||
|
&hapd->conf->accept_mac,
|
||||||
|
&hapd->conf->num_accept_mac, buf + 19))
|
||||||
|
hostapd_disassoc_accept_mac(hapd);
|
||||||
|
else
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) {
|
||||||
|
hostapd_ctrl_iface_acl_del_mac(
|
||||||
|
&hapd->conf->accept_mac,
|
||||||
|
&hapd->conf->num_accept_mac, buf + 19);
|
||||||
|
} else if (os_strcmp(buf + 11, "SHOW") == 0) {
|
||||||
|
reply_len = hostapd_ctrl_iface_acl_show_mac(
|
||||||
|
hapd->conf->accept_mac,
|
||||||
|
hapd->conf->num_accept_mac, reply, reply_size);
|
||||||
|
} else if (os_strcmp(buf + 11, "CLEAR") == 0) {
|
||||||
|
hostapd_ctrl_iface_acl_clear_list(
|
||||||
|
&hapd->conf->accept_mac,
|
||||||
|
&hapd->conf->num_accept_mac);
|
||||||
|
}
|
||||||
|
} else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) {
|
||||||
|
if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) {
|
||||||
|
if (!hostapd_ctrl_iface_acl_add_mac(
|
||||||
|
&hapd->conf->deny_mac,
|
||||||
|
&hapd->conf->num_deny_mac, buf + 17))
|
||||||
|
hostapd_disassoc_deny_mac(hapd);
|
||||||
|
} else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) {
|
||||||
|
hostapd_ctrl_iface_acl_del_mac(
|
||||||
|
&hapd->conf->deny_mac,
|
||||||
|
&hapd->conf->num_deny_mac, buf + 17);
|
||||||
|
} else if (os_strcmp(buf + 9, "SHOW") == 0) {
|
||||||
|
reply_len = hostapd_ctrl_iface_acl_show_mac(
|
||||||
|
hapd->conf->deny_mac,
|
||||||
|
hapd->conf->num_deny_mac, reply, reply_size);
|
||||||
|
} else if (os_strcmp(buf + 9, "CLEAR") == 0) {
|
||||||
|
hostapd_ctrl_iface_acl_clear_list(
|
||||||
|
&hapd->conf->deny_mac,
|
||||||
|
&hapd->conf->num_deny_mac);
|
||||||
|
}
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
|
} else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) {
|
||||||
res = hostapd_dpp_qr_code(hapd, buf + 12);
|
res = hostapd_dpp_qr_code(hapd, buf + 12);
|
||||||
|
@ -1452,6 +1452,20 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
|
|||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
return hostapd_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
return hostapd_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hostapd_cli_cmd {
|
struct hostapd_cli_cmd {
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
||||||
@ -1614,6 +1628,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
|||||||
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
|
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
|
||||||
"*|<id> = remove DPP pkex information" },
|
"*|<id> = remove DPP pkex information" },
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
|
||||||
|
"=Add/Delete/Show/Clear accept MAC ACL" },
|
||||||
|
{ "deny_acl", hostapd_cli_cmd_deny_macacl, NULL,
|
||||||
|
"=Add/Delete/Show/Clear deny MAC ACL" },
|
||||||
{ NULL, NULL, NULL, NULL }
|
{ NULL, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user