aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerry Burton <tez@terryburton.co.uk>2019-07-21 12:05:56 (GMT)
committerJouni Malinen <j@w1.fi>2019-07-30 16:58:09 (GMT)
commitf4111ff3d1f19d219f3818f72cbfab80da10754a (patch)
tree722314a9f298cbe01473ab34c1d86847bd1e0dfd
parent74707def8f1b8cdb1755f4f5698bb52b9c8a5442 (diff)
downloadhostap-f4111ff3d1f19d219f3818f72cbfab80da10754a.zip
hostap-f4111ff3d1f19d219f3818f72cbfab80da10754a.tar.gz
hostap-f4111ff3d1f19d219f3818f72cbfab80da10754a.tar.bz2
Extra RADIUS request attributes from SQLite
Add an SQLite table for defining per station MAC address version of radius_auth_req_attr/radius_acct_req_attr information. Create the necessary table and index where this doesn't exist. Select attributes from the table keyed by station MAC address and request type (auth or acct), parse and apply to a RADIUS message. Add radius_req_attr_sqlite hostapd config option for SQLite database file. Open/close RADIUS attribute database for a lifetime of a BSS and invoke functions to add extra attributes during RADIUS auth and accounting request generation. Signed-off-by: Terry Burton <tez@terryburton.co.uk>
-rw-r--r--hostapd/config_file.c3
-rw-r--r--hostapd/hostapd.conf11
-rw-r--r--src/ap/accounting.c3
-rw-r--r--src/ap/ap_config.c3
-rw-r--r--src/ap/ap_config.h2
-rw-r--r--src/ap/hostapd.c64
-rw-r--r--src/ap/hostapd.h8
-rw-r--r--src/ap/ieee802_1x.c63
-rw-r--r--src/ap/ieee802_1x.h2
9 files changed, 158 insertions, 1 deletions
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 29ea92e..1f2c565 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2832,6 +2832,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
a = a->next;
a->next = attr;
}
+ } else if (os_strcmp(buf, "radius_req_attr_sqlite") == 0) {
+ os_free(bss->radius_req_attr_sqlite);
+ bss->radius_req_attr_sqlite = os_strdup(pos);
} else if (os_strcmp(buf, "radius_das_port") == 0) {
bss->radius_das_port = atoi(pos);
} else if (os_strcmp(buf, "radius_das_client") == 0) {
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index f2d5873..5138aee 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1384,6 +1384,17 @@ own_ip_addr=127.0.0.1
# Operator-Name = "Operator"
#radius_acct_req_attr=126:s:Operator
+# If SQLite support is included, path to a database from which additional
+# RADIUS request attributes are extracted based on the station MAC address.
+#
+# The schema for the radius_attributes table is:
+# id | sta | reqtype | attr : multi-key (sta, reqtype)
+# id = autonumber
+# sta = station MAC address in `11:22:33:44:55:66` format.
+# type = `auth` | `acct` | NULL (match any)
+# attr = existing config file format, e.g. `126:s:Test Operator`
+#radius_req_attr_sqlite=radius_attr.sqlite
+
# Dynamic Authorization Extensions (RFC 5176)
# This mechanism can be used to allow dynamic changes to user session based on
# commands from a RADIUS server (or some other disconnect client that has the
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index 0aacc3c..9fc1886 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -97,6 +97,9 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
msg) < 0)
goto fail;
+ if (sta && add_sqlite_radius_attr(hapd, sta, msg, 1) < 0)
+ goto fail;
+
if (sta) {
for (i = 0; ; i++) {
val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 258a205..968eb65 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -545,7 +545,7 @@ struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value)
}
-static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
+void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
{
struct hostapd_radius_attr *prev;
@@ -694,6 +694,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
}
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
+ os_free(conf->radius_req_attr_sqlite);
os_free(conf->rsn_preauth_interfaces);
os_free(conf->ctrl_interface);
os_free(conf->ca_cert);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index f42505e..0a1d49b 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -301,6 +301,7 @@ struct hostapd_bss_config {
int radius_request_cui;
struct hostapd_radius_attr *radius_auth_req_attr;
struct hostapd_radius_attr *radius_acct_req_attr;
+ char *radius_req_attr_sqlite;
int radius_das_port;
unsigned int radius_das_time_window;
int radius_das_require_event_timestamp;
@@ -1074,6 +1075,7 @@ hostapd_set_oper_centr_freq_seg1_idx(struct hostapd_config *conf,
int hostapd_mac_comp(const void *a, const void *b);
struct hostapd_config * hostapd_config_defaults(void);
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
+void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr);
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
void hostapd_config_free_eap_users(struct hostapd_eap_user *user);
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index cc75a77..bf1975f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -7,6 +7,9 @@
*/
#include "utils/includes.h"
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
#include "utils/common.h"
#include "utils/eloop.h"
@@ -1025,6 +1028,43 @@ hostapd_das_coa(void *ctx, struct radius_das_attrs *attr)
#define hostapd_das_coa NULL
#endif /* CONFIG_HS20 */
+
+#ifdef CONFIG_SQLITE
+
+static int db_table_exists(sqlite3 *db, const char *name)
+{
+ char cmd[128];
+
+ os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
+ return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
+}
+
+
+static int db_table_create_radius_attributes(sqlite3 *db)
+{
+ char *err = NULL;
+ const char *sql =
+ "CREATE TABLE radius_attributes("
+ " id INTEGER PRIMARY KEY,"
+ " sta TEXT,"
+ " reqtype TEXT,"
+ " attr TEXT"
+ ");"
+ "CREATE INDEX idx_sta_reqtype ON radius_attributes(sta,reqtype);";
+
+ wpa_printf(MSG_DEBUG,
+ "Adding database table for RADIUS attribute information");
+ if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
+ wpa_printf(MSG_ERROR, "SQLite error: %s", err);
+ sqlite3_free(err);
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_SQLITE */
+
#endif /* CONFIG_NO_RADIUS */
@@ -1178,6 +1218,24 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
if (wpa_debug_level <= MSG_MSGDUMP)
conf->radius->msg_dumps = 1;
#ifndef CONFIG_NO_RADIUS
+
+#ifdef CONFIG_SQLITE
+ if (conf->radius_req_attr_sqlite) {
+ if (sqlite3_open(conf->radius_req_attr_sqlite,
+ &hapd->rad_attr_db)) {
+ wpa_printf(MSG_ERROR, "Could not open SQLite file '%s'",
+ conf->radius_req_attr_sqlite);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "Opening RADIUS attribute database: %s",
+ conf->radius_req_attr_sqlite);
+ if (!db_table_exists(hapd->rad_attr_db, "radius_attributes") &&
+ db_table_create_radius_attributes(hapd->rad_attr_db) < 0)
+ return -1;
+ }
+#endif /* CONFIG_SQLITE */
+
hapd->radius = radius_client_init(hapd, conf->radius);
if (hapd->radius == NULL) {
wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
@@ -2194,6 +2252,12 @@ static void hostapd_bss_deinit(struct hostapd_data *hapd)
hapd->conf ? hapd->conf->iface : "N/A");
hostapd_bss_deinit_no_free(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+#ifdef CONFIG_SQLITE
+ if (hapd->rad_attr_db) {
+ sqlite3_close(hapd->rad_attr_db);
+ hapd->rad_attr_db = NULL;
+ }
+#endif /* CONFIG_SQLITE */
hostapd_cleanup(hapd);
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index d90bae4..518c7f1 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -9,6 +9,10 @@
#ifndef HOSTAPD_H
#define HOSTAPD_H
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
+
#include "common/defs.h"
#include "utils/list.h"
#include "ap_config.h"
@@ -390,6 +394,10 @@ struct hostapd_data {
#endif /* CONFIG_AIRTIME_POLICY */
u8 last_1x_eapol_key_replay_counter[8];
+
+#ifdef CONFIG_SQLITE
+ sqlite3 *rad_attr_db;
+#endif /* CONFIG_SQLITE */
};
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index d628641..ab6989b 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -7,6 +7,9 @@
*/
#include "utils/includes.h"
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
#include "utils/common.h"
#include "utils/eloop.h"
@@ -615,6 +618,63 @@ int add_common_radius_attr(struct hostapd_data *hapd,
}
+int add_sqlite_radius_attr(struct hostapd_data *hapd, struct sta_info *sta,
+ struct radius_msg *msg, int acct)
+{
+#ifdef CONFIG_SQLITE
+ const char *attrtxt;
+ char addrtxt[3 * ETH_ALEN];
+ char *sql;
+ sqlite3_stmt *stmt = NULL;
+
+ if (!hapd->rad_attr_db)
+ return 0;
+
+ os_snprintf(addrtxt, sizeof(addrtxt), MACSTR, MAC2STR(sta->addr));
+
+ sql = "SELECT attr FROM radius_attributes WHERE sta=? AND (reqtype=? OR reqtype IS NULL);";
+ if (sqlite3_prepare_v2(hapd->rad_attr_db, sql, os_strlen(sql), &stmt,
+ NULL) != SQLITE_OK) {
+ wpa_printf(MSG_ERROR, "DB: Failed to prepare SQL statement: %s",
+ sqlite3_errmsg(hapd->rad_attr_db));
+ return -1;
+ }
+ sqlite3_bind_text(stmt, 1, addrtxt, os_strlen(addrtxt), SQLITE_STATIC);
+ sqlite3_bind_text(stmt, 2, acct ? "acct" : "auth", 4, SQLITE_STATIC);
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ struct hostapd_radius_attr *attr;
+ struct radius_attr_hdr *hdr;
+
+ attrtxt = (const char *) sqlite3_column_text(stmt, 0);
+ attr = hostapd_parse_radius_attr(attrtxt);
+ if (!attr) {
+ wpa_printf(MSG_ERROR,
+ "Skipping invalid attribute from SQL: %s",
+ attrtxt);
+ continue;
+ }
+ wpa_printf(MSG_DEBUG, "Adding RADIUS attribute from SQL: %s",
+ attrtxt);
+ hdr = radius_msg_add_attr(msg, attr->type,
+ wpabuf_head(attr->val),
+ wpabuf_len(attr->val));
+ hostapd_config_free_radius_attr(attr);
+ if (!hdr) {
+ wpa_printf(MSG_ERROR,
+ "Could not add RADIUS attribute from SQL");
+ continue;
+ }
+ }
+
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+#endif /* CONFIG_SQLITE */
+
+ return 0;
+}
+
+
void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
struct sta_info *sta,
const u8 *eap, size_t len)
@@ -654,6 +714,9 @@ void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
msg) < 0)
goto fail;
+ if (sta && add_sqlite_radius_attr(hapd, sta, msg, 0) < 0)
+ goto fail;
+
/* TODO: should probably check MTU from driver config; 2304 is max for
* IEEE 802.11, but use 1400 to avoid problems with too large packets
*/
diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h
index d771ba5..bb85b93 100644
--- a/src/ap/ieee802_1x.h
+++ b/src/ap/ieee802_1x.h
@@ -59,6 +59,8 @@ int add_common_radius_attr(struct hostapd_data *hapd,
struct hostapd_radius_attr *req_attr,
struct sta_info *sta,
struct radius_msg *msg);
+int add_sqlite_radius_attr(struct hostapd_data *hapd, struct sta_info *sta,
+ struct radius_msg *msg, int acct);
void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
struct sta_info *sta,
const u8 *eap, size_t len);