Allow arbitrary RADIUS attributes to be added into Access-Accept
This extends the design already available for Access-Request packets to the RADIUS server and Access-Accept messages. Each user entry can be configured to add arbitrary RADIUS attributes. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
0ac3876627
commit
d0ee16edc8
7 changed files with 68 additions and 9 deletions
|
@ -22,6 +22,14 @@
|
||||||
#include "config_file.h"
|
#include "config_file.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CONFIG_NO_RADIUS
|
||||||
|
#ifdef EAP_SERVER
|
||||||
|
static struct hostapd_radius_attr *
|
||||||
|
hostapd_parse_radius_attr(const char *value);
|
||||||
|
#endif /* EAP_SERVER */
|
||||||
|
#endif /* CONFIG_NO_RADIUS */
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_NO_VLAN
|
#ifndef CONFIG_NO_VLAN
|
||||||
static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
|
static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
|
||||||
const char *fname)
|
const char *fname)
|
||||||
|
@ -208,7 +216,7 @@ static int hostapd_config_read_eap_user(const char *fname,
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char buf[512], *pos, *start, *pos2;
|
char buf[512], *pos, *start, *pos2;
|
||||||
int line = 0, ret = 0, num_methods;
|
int line = 0, ret = 0, num_methods;
|
||||||
struct hostapd_eap_user *user, *tail = NULL;
|
struct hostapd_eap_user *user = NULL, *tail = NULL;
|
||||||
|
|
||||||
if (!fname)
|
if (!fname)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -242,6 +250,27 @@ static int hostapd_config_read_eap_user(const char *fname,
|
||||||
if (buf[0] == '\0')
|
if (buf[0] == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifndef CONFIG_NO_RADIUS
|
||||||
|
if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
|
||||||
|
struct hostapd_radius_attr *attr, *a;
|
||||||
|
attr = hostapd_parse_radius_attr(buf + 19);
|
||||||
|
if (attr == NULL) {
|
||||||
|
wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
|
||||||
|
buf + 19);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if (user->accept_attr == NULL) {
|
||||||
|
user->accept_attr = attr;
|
||||||
|
} else {
|
||||||
|
a = user->accept_attr;
|
||||||
|
while (a->next)
|
||||||
|
a = a->next;
|
||||||
|
a->next = attr;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NO_RADIUS */
|
||||||
|
|
||||||
user = NULL;
|
user = NULL;
|
||||||
|
|
||||||
if (buf[0] != '"' && buf[0] != '*') {
|
if (buf[0] != '"' && buf[0] != '*') {
|
||||||
|
@ -468,11 +497,8 @@ static int hostapd_config_read_eap_user(const char *fname,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
if (user) {
|
if (user)
|
||||||
os_free(user->password);
|
hostapd_config_free_eap_user(user);
|
||||||
os_free(user->identity);
|
|
||||||
os_free(user);
|
|
||||||
}
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,12 @@
|
||||||
# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
|
# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
|
||||||
# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
|
# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
|
||||||
# hash.
|
# hash.
|
||||||
|
#
|
||||||
|
# Arbitrary RADIUS attributes can be added into Access-Accept packets similarly
|
||||||
|
# to the way radius_auth_req_attr is used for Access-Request packet in
|
||||||
|
# hostapd.conf. For EAP server, this is configured separately for each user
|
||||||
|
# entry with radius_accept_attr=<value> line(s) following the main user entry
|
||||||
|
# line.
|
||||||
|
|
||||||
# Phase 1 users
|
# Phase 1 users
|
||||||
"user" MD5 "password"
|
"user" MD5 "password"
|
||||||
|
|
|
@ -388,8 +388,9 @@ static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
|
void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
|
||||||
{
|
{
|
||||||
|
hostapd_config_free_radius_attr(user->accept_attr);
|
||||||
os_free(user->identity);
|
os_free(user->identity);
|
||||||
os_free(user->password);
|
os_free(user->password);
|
||||||
os_free(user);
|
os_free(user);
|
||||||
|
|
|
@ -128,6 +128,7 @@ struct hostapd_eap_user {
|
||||||
* nt_password_hash() */
|
* nt_password_hash() */
|
||||||
unsigned int remediation:1;
|
unsigned int remediation:1;
|
||||||
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
||||||
|
struct hostapd_radius_attr *accept_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hostapd_radius_attr {
|
struct hostapd_radius_attr {
|
||||||
|
@ -601,6 +602,7 @@ int hostapd_mac_comp(const void *a, const void *b);
|
||||||
int hostapd_mac_comp_empty(const void *a);
|
int hostapd_mac_comp_empty(const void *a);
|
||||||
struct hostapd_config * hostapd_config_defaults(void);
|
struct hostapd_config * hostapd_config_defaults(void);
|
||||||
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
|
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
|
||||||
|
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
|
||||||
void hostapd_config_free_bss(struct hostapd_bss_config *conf);
|
void hostapd_config_free_bss(struct hostapd_bss_config *conf);
|
||||||
void hostapd_config_free(struct hostapd_config *conf);
|
void hostapd_config_free(struct hostapd_config *conf);
|
||||||
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
||||||
|
|
|
@ -81,6 +81,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
|
||||||
user->force_version = eap_user->force_version;
|
user->force_version = eap_user->force_version;
|
||||||
user->ttls_auth = eap_user->ttls_auth;
|
user->ttls_auth = eap_user->ttls_auth;
|
||||||
user->remediation = eap_user->remediation;
|
user->remediation = eap_user->remediation;
|
||||||
|
user->accept_attr = eap_user->accept_attr;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct eap_user {
|
||||||
unsigned int remediation:1;
|
unsigned int remediation:1;
|
||||||
int ttls_auth; /* bitfield of
|
int ttls_auth; /* bitfield of
|
||||||
* EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
|
* EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
|
||||||
|
struct hostapd_radius_attr *accept_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct eap_eapol_interface {
|
struct eap_eapol_interface {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "radius.h"
|
#include "radius.h"
|
||||||
#include "eloop.h"
|
#include "eloop.h"
|
||||||
#include "eap_server/eap.h"
|
#include "eap_server/eap.h"
|
||||||
|
#include "ap/ap_config.h"
|
||||||
#include "radius_server.h"
|
#include "radius_server.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,6 +80,8 @@ struct radius_session {
|
||||||
u8 last_authenticator[16];
|
u8 last_authenticator[16];
|
||||||
|
|
||||||
unsigned int remediation:1;
|
unsigned int remediation:1;
|
||||||
|
|
||||||
|
struct hostapd_radius_attr *accept_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -483,6 +486,7 @@ radius_server_get_new_session(struct radius_server_data *data,
|
||||||
int res;
|
int res;
|
||||||
struct radius_session *sess;
|
struct radius_session *sess;
|
||||||
struct eap_config eap_conf;
|
struct eap_config eap_conf;
|
||||||
|
struct eap_user tmp;
|
||||||
|
|
||||||
RADIUS_DEBUG("Creating a new session");
|
RADIUS_DEBUG("Creating a new session");
|
||||||
|
|
||||||
|
@ -499,7 +503,9 @@ radius_server_get_new_session(struct radius_server_data *data,
|
||||||
user_len = res;
|
user_len = res;
|
||||||
RADIUS_DUMP_ASCII("User-Name", user, user_len);
|
RADIUS_DUMP_ASCII("User-Name", user, user_len);
|
||||||
|
|
||||||
res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
|
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);
|
os_free(user);
|
||||||
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
|
@ -509,6 +515,7 @@ radius_server_get_new_session(struct radius_server_data *data,
|
||||||
RADIUS_DEBUG("Failed to create a new session");
|
RADIUS_DEBUG("Failed to create a new session");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
sess->accept_attr = tmp.accept_attr;
|
||||||
} else {
|
} else {
|
||||||
RADIUS_DEBUG("User-Name not found from user database");
|
RADIUS_DEBUG("User-Name not found from user database");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -661,6 +668,19 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (code == RADIUS_CODE_ACCESS_ACCEPT) {
|
||||||
|
struct hostapd_radius_attr *attr;
|
||||||
|
for (attr = sess->accept_attr; attr; attr = attr->next) {
|
||||||
|
if (!radius_msg_add_attr(msg, attr->type,
|
||||||
|
wpabuf_head(attr->val),
|
||||||
|
wpabuf_len(attr->val))) {
|
||||||
|
wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
|
||||||
|
radius_msg_free(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
|
if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
|
||||||
client->shared_secret_len,
|
client->shared_secret_len,
|
||||||
hdr->authenticator) < 0) {
|
hdr->authenticator) < 0) {
|
||||||
|
@ -1725,8 +1745,10 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
|
||||||
|
|
||||||
ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
|
ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
|
||||||
phase2, user);
|
phase2, user);
|
||||||
if (ret == 0 && user)
|
if (ret == 0 && user) {
|
||||||
|
sess->accept_attr = user->accept_attr;
|
||||||
sess->remediation = user->remediation;
|
sess->remediation = user->remediation;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue