RADIUS server: Add support for MAC ACL
"user" MACACL "password" style lines in the eap_user file can now be used to configured user entries for RADIUS-based MAC ACL. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
81699e2e6e
commit
8943cc998a
8 changed files with 135 additions and 15 deletions
|
@ -86,6 +86,7 @@ struct radius_session {
|
|||
u8 last_authenticator[16];
|
||||
|
||||
unsigned int remediation:1;
|
||||
unsigned int macacl:1;
|
||||
|
||||
struct hostapd_radius_attr *accept_attr;
|
||||
};
|
||||
|
@ -636,6 +637,7 @@ radius_server_get_new_session(struct radius_server_data *data,
|
|||
return NULL;
|
||||
}
|
||||
sess->accept_attr = tmp.accept_attr;
|
||||
sess->macacl = tmp.macacl;
|
||||
|
||||
sess->username = os_malloc(user_len * 2 + 1);
|
||||
if (sess->username == NULL) {
|
||||
|
@ -823,6 +825,87 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
|
|||
}
|
||||
|
||||
|
||||
static struct radius_msg *
|
||||
radius_server_macacl(struct radius_server_data *data,
|
||||
struct radius_client *client,
|
||||
struct radius_session *sess,
|
||||
struct radius_msg *request)
|
||||
{
|
||||
struct radius_msg *msg;
|
||||
int code;
|
||||
struct radius_hdr *hdr = radius_msg_get_hdr(request);
|
||||
u8 *pw;
|
||||
size_t pw_len;
|
||||
|
||||
code = RADIUS_CODE_ACCESS_ACCEPT;
|
||||
|
||||
if (radius_msg_get_attr_ptr(request, RADIUS_ATTR_USER_PASSWORD, &pw,
|
||||
&pw_len, NULL) < 0) {
|
||||
RADIUS_DEBUG("Could not get User-Password");
|
||||
code = RADIUS_CODE_ACCESS_REJECT;
|
||||
} else {
|
||||
int res;
|
||||
struct eap_user tmp;
|
||||
|
||||
os_memset(&tmp, 0, sizeof(tmp));
|
||||
res = data->get_eap_user(data->conf_ctx, (u8 *) sess->username,
|
||||
os_strlen(sess->username), 0, &tmp);
|
||||
if (res || !tmp.macacl || tmp.password == NULL) {
|
||||
RADIUS_DEBUG("No MAC ACL user entry");
|
||||
os_free(tmp.password);
|
||||
code = RADIUS_CODE_ACCESS_REJECT;
|
||||
} else {
|
||||
u8 buf[128];
|
||||
res = radius_user_password_hide(
|
||||
request, tmp.password, tmp.password_len,
|
||||
(u8 *) client->shared_secret,
|
||||
client->shared_secret_len,
|
||||
buf, sizeof(buf));
|
||||
os_free(tmp.password);
|
||||
|
||||
if (res < 0 || pw_len != (size_t) res ||
|
||||
os_memcmp(pw, buf, res) != 0) {
|
||||
RADIUS_DEBUG("Incorrect User-Password");
|
||||
code = RADIUS_CODE_ACCESS_REJECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg = radius_msg_new(code, hdr->identifier);
|
||||
if (msg == NULL) {
|
||||
RADIUS_DEBUG("Failed to allocate reply message");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
|
||||
RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
|
||||
radius_msg_free(msg);
|
||||
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,
|
||||
client->shared_secret_len,
|
||||
hdr->authenticator) < 0) {
|
||||
RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
static int radius_server_reject(struct radius_server_data *data,
|
||||
struct radius_client *client,
|
||||
struct radius_msg *request,
|
||||
|
@ -958,6 +1041,12 @@ static int radius_server_request(struct radius_server_data *data,
|
|||
}
|
||||
|
||||
eap = radius_msg_get_eap(msg);
|
||||
if (eap == NULL && sess->macacl) {
|
||||
reply = radius_server_macacl(data, client, sess, msg);
|
||||
if (reply == NULL)
|
||||
return -1;
|
||||
goto send_reply;
|
||||
}
|
||||
if (eap == NULL) {
|
||||
RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s",
|
||||
from_addr);
|
||||
|
@ -1015,6 +1104,7 @@ static int radius_server_request(struct radius_server_data *data,
|
|||
|
||||
reply = radius_server_encapsulate_eap(data, client, sess, msg);
|
||||
|
||||
send_reply:
|
||||
if (reply) {
|
||||
struct wpabuf *buf;
|
||||
struct radius_hdr *hdr;
|
||||
|
@ -1904,6 +1994,7 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
|
|||
if (ret == 0 && user) {
|
||||
sess->accept_attr = user->accept_attr;
|
||||
sess->remediation = user->remediation;
|
||||
sess->macacl = user->macacl;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue