aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2014-02-28 12:11:13 (GMT)
committerJouni Malinen <j@w1.fi>2014-03-09 16:21:13 (GMT)
commit8a57da7e28ec48e452eedd76e7f255ebe0e745c4 (patch)
tree438c46915637acb36b7197236bb419dd9bb8bf23
parentf3ef7a264043562a0023e00fad77869008429591 (diff)
downloadhostap-8a57da7e28ec48e452eedd76e7f255ebe0e745c4.zip
hostap-8a57da7e28ec48e452eedd76e7f255ebe0e745c4.tar.gz
hostap-8a57da7e28ec48e452eedd76e7f255ebe0e745c4.tar.bz2
RADIUS server: Add option for storing log information to SQLite DB
If eap_user_file is configured to point to an SQLite database, RADIUS server code can use that database for log information. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
-rw-r--r--hostapd/hostapd.eap_user_sqlite8
-rw-r--r--src/ap/authsrv.c1
-rw-r--r--src/radius/radius_server.c129
-rw-r--r--src/radius/radius_server.h5
4 files changed, 123 insertions, 20 deletions
diff --git a/hostapd/hostapd.eap_user_sqlite b/hostapd/hostapd.eap_user_sqlite
index 2c1f130..826db34 100644
--- a/hostapd/hostapd.eap_user_sqlite
+++ b/hostapd/hostapd.eap_user_sqlite
@@ -16,3 +16,11 @@ INSERT INTO users(identity,methods,password,phase2) VALUES ('DOMAIN\mschapv2 use
INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS');
INSERT INTO wildcards(identity,methods) VALUES ('0','AKA');
+
+CREATE TABLE authlog(
+ timestamp TEXT,
+ session TEXT,
+ nas_ip TEXT,
+ username TEXT,
+ note TEXT
+);
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index 8b922ec..6e3decd 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -115,6 +115,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
srv.pwd_group = conf->pwd_group;
srv.server_id = conf->server_id ? conf->server_id : "hostapd";
+ srv.sqlite_file = conf->eap_user_sqlite;
#ifdef CONFIG_RADIUS_TEST
srv.dump_msk_file = conf->dump_msk_file;
#endif /* CONFIG_RADIUS_TEST */
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index dd96b59..e0dbdf1 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -8,6 +8,9 @@
#include "includes.h"
#include <net/if.h>
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
#include "common.h"
#include "radius.h"
@@ -69,6 +72,8 @@ struct radius_session {
unsigned int sess_id;
struct eap_sm *eap;
struct eap_eapol_interface *eap_if;
+ char *username; /* from User-Name attribute */
+ char *nas_ip;
struct radius_msg *last_msg;
char *last_from_addr;
@@ -315,6 +320,10 @@ struct radius_server_data {
char *subscr_remediation_url;
u8 subscr_remediation_method;
+
+#ifdef CONFIG_SQLITE
+ sqlite3 *db;
+#endif /* CONFIG_SQLITE */
};
@@ -332,6 +341,52 @@ static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx);
static void radius_server_session_remove_timeout(void *eloop_ctx,
void *timeout_ctx);
+void srv_log(struct radius_session *sess, const char *fmt, ...)
+PRINTF_FORMAT(2, 3);
+
+void srv_log(struct radius_session *sess, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ int buflen;
+
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
+ buf = os_malloc(buflen);
+ if (buf == NULL)
+ return;
+ va_start(ap, fmt);
+ vsnprintf(buf, buflen, fmt, ap);
+ va_end(ap);
+
+ RADIUS_DEBUG("[0x%x %s] %s", sess->sess_id, sess->nas_ip, buf);
+
+#ifdef CONFIG_SQLITE
+ if (sess->server->db) {
+ char *sql;
+ sql = sqlite3_mprintf("INSERT INTO authlog"
+ "(timestamp,session,nas_ip,username,note)"
+ " VALUES ("
+ "strftime('%%Y-%%m-%%d %%H:%%M:%%f',"
+ "'now'),%u,%Q,%Q,%Q)",
+ sess->sess_id, sess->nas_ip,
+ sess->username, buf);
+ if (sql) {
+ if (sqlite3_exec(sess->server->db, sql, NULL, NULL,
+ NULL) != SQLITE_OK) {
+ RADIUS_ERROR("Failed to add authlog entry into sqlite database: %s",
+ sqlite3_errmsg(sess->server->db));
+ }
+ sqlite3_free(sql);
+ }
+ }
+#endif /* CONFIG_SQLITE */
+
+ os_free(buf);
+}
+
static struct radius_client *
radius_server_get_client(struct radius_server_data *data, struct in_addr *addr,
@@ -397,6 +452,8 @@ static void radius_server_session_free(struct radius_server_data *data,
radius_msg_free(sess->last_msg);
os_free(sess->last_from_addr);
radius_msg_free(sess->last_reply);
+ os_free(sess->username);
+ os_free(sess->nas_ip);
os_free(sess);
data->num_sess--;
}
@@ -479,7 +536,7 @@ radius_server_new_session(struct radius_server_data *data,
static struct radius_session *
radius_server_get_new_session(struct radius_server_data *data,
struct radius_client *client,
- struct radius_msg *msg)
+ struct radius_msg *msg, const char *from_addr)
{
u8 *user;
size_t user_len;
@@ -490,37 +547,45 @@ radius_server_get_new_session(struct radius_server_data *data,
RADIUS_DEBUG("Creating a new session");
- user = os_malloc(256);
- if (user == NULL) {
- return NULL;
- }
- res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256);
- if (res < 0 || res > 256) {
+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &user,
+ &user_len, NULL) < 0) {
RADIUS_DEBUG("Could not get User-Name");
- os_free(user);
return NULL;
}
- user_len = res;
RADIUS_DUMP_ASCII("User-Name", user, user_len);
os_memset(&tmp, 0, sizeof(tmp));
res = data->get_eap_user(data->conf_ctx, user, user_len, 0, &tmp);
os_free(tmp.password);
- os_free(user);
- if (res == 0) {
- RADIUS_DEBUG("Matching user entry found");
- sess = radius_server_new_session(data, client);
- if (sess == NULL) {
- RADIUS_DEBUG("Failed to create a new session");
- return NULL;
- }
- sess->accept_attr = tmp.accept_attr;
- } else {
+ if (res != 0) {
RADIUS_DEBUG("User-Name not found from user database");
return NULL;
}
+ RADIUS_DEBUG("Matching user entry found");
+ sess = radius_server_new_session(data, client);
+ if (sess == NULL) {
+ RADIUS_DEBUG("Failed to create a new session");
+ return NULL;
+ }
+ sess->accept_attr = tmp.accept_attr;
+
+ sess->username = os_malloc(user_len * 2 + 1);
+ if (sess->username == NULL) {
+ radius_server_session_free(data, sess);
+ return NULL;
+ }
+ printf_encode(sess->username, user_len * 2 + 1, user, user_len);
+
+ sess->nas_ip = os_strdup(from_addr);
+ if (sess->nas_ip == NULL) {
+ radius_server_session_free(data, sess);
+ return NULL;
+ }
+
+ srv_log(sess, "New session created");
+
os_memset(&eap_conf, 0, sizeof(eap_conf));
eap_conf.ssl_ctx = data->ssl_ctx;
eap_conf.msg_ctx = data->msg_ctx;
@@ -789,7 +854,8 @@ static int radius_server_request(struct radius_server_data *data,
from_addr, from_port);
return -1;
} else {
- sess = radius_server_get_new_session(data, client, msg);
+ sess = radius_server_get_new_session(data, client, msg,
+ from_addr);
if (sess == NULL) {
RADIUS_DEBUG("Could not create a new session");
radius_server_reject(data, client, msg, from, fromlen,
@@ -875,6 +941,10 @@ static int radius_server_request(struct radius_server_data *data,
if (sess->eap_if->eapSuccess || sess->eap_if->eapFail)
is_complete = 1;
+ if (sess->eap_if->eapFail)
+ srv_log(sess, "EAP authentication failed");
+ else if (sess->eap_if->eapSuccess)
+ srv_log(sess, "EAP authentication succeeded");
reply = radius_server_encapsulate_eap(data, client, sess, msg);
@@ -889,10 +959,12 @@ static int radius_server_request(struct radius_server_data *data,
switch (radius_msg_get_hdr(reply)->code) {
case RADIUS_CODE_ACCESS_ACCEPT:
+ srv_log(sess, "Sending Access-Accept");
data->counters.access_accepts++;
client->counters.access_accepts++;
break;
case RADIUS_CODE_ACCESS_REJECT:
+ srv_log(sess, "Sending Access-Reject");
data->counters.access_rejects++;
client->counters.access_rejects++;
break;
@@ -1502,6 +1574,17 @@ radius_server_init(struct radius_server_conf *conf)
os_strdup(conf->subscr_remediation_url);
}
+#ifdef CONFIG_SQLITE
+ if (conf->sqlite_file) {
+ if (sqlite3_open(conf->sqlite_file, &data->db)) {
+ RADIUS_ERROR("Could not open SQLite file '%s'",
+ conf->sqlite_file);
+ radius_server_deinit(data);
+ return NULL;
+ }
+ }
+#endif /* CONFIG_SQLITE */
+
#ifdef CONFIG_RADIUS_TEST
if (conf->dump_msk_file)
data->dump_msk_file = os_strdup(conf->dump_msk_file);
@@ -1589,6 +1672,12 @@ void radius_server_deinit(struct radius_server_data *data)
os_free(data->dump_msk_file);
#endif /* CONFIG_RADIUS_TEST */
os_free(data->subscr_remediation_url);
+
+#ifdef CONFIG_SQLITE
+ if (data->db)
+ sqlite3_close(data->db);
+#endif /* CONFIG_SQLITE */
+
os_free(data);
}
diff --git a/src/radius/radius_server.h b/src/radius/radius_server.h
index e85d009..46ac312 100644
--- a/src/radius/radius_server.h
+++ b/src/radius/radius_server.h
@@ -40,6 +40,11 @@ struct radius_server_conf {
char *client_file;
/**
+ * sqlite_file - SQLite database for storing debug log information
+ */
+ const char *sqlite_file;
+
+ /**
* conf_ctx - Context pointer for callbacks
*
* This is used as the ctx argument in get_eap_user() calls.