EAP_TTLS_AUTH_MSCHAPV2;
goto skip_eap;
}
+ if (os_strcmp(start, "MACACL") == 0) {
+ user->macacl = 1;
+ goto skip_eap;
+ }
wpa_printf(MSG_ERROR, "Unsupported EAP type "
"'%s' on line %d in '%s'",
start, line, fname);
break;
start = pos3;
}
- if (num_methods == 0 && user->ttls_auth == 0) {
+ if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) {
wpa_printf(MSG_ERROR, "No EAP types configured on "
"line %d in '%s'", line, fname);
goto failed;
unsigned int password_hash:1; /* whether password is hashed with
* nt_password_hash() */
unsigned int remediation:1;
+ unsigned int macacl:1;
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
struct hostapd_radius_attr *accept_attr;
};
user->password_hash = eap_user->password_hash;
}
user->force_version = eap_user->force_version;
+ user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
user->accept_attr = eap_user->accept_attr;
user->password_hash = eap_user->password_hash;
}
user->force_version = eap_user->force_version;
+ user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
int phase2;
int force_version;
unsigned int remediation:1;
+ unsigned int macacl:1;
int ttls_auth; /* bitfield of
* EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
struct hostapd_radius_attr *accept_attr;
}
-/* Add User-Password attribute to a RADIUS message and encrypt it as specified
- * in RFC 2865, Chap. 5.2 */
-struct radius_attr_hdr *
-radius_msg_add_attr_user_password(struct radius_msg *msg,
- const u8 *data, size_t data_len,
- const u8 *secret, size_t secret_len)
+int radius_user_password_hide(struct radius_msg *msg,
+ const u8 *data, size_t data_len,
+ const u8 *secret, size_t secret_len,
+ u8 *buf, size_t buf_len)
{
- u8 buf[128];
- size_t padlen, i, buf_len, pos;
+ size_t padlen, i, pos;
const u8 *addr[2];
size_t len[2];
u8 hash[16];
- if (data_len > 128)
- return NULL;
+ if (data_len + 16 > buf_len)
+ return -1;
os_memcpy(buf, data, data_len);
- buf_len = data_len;
padlen = data_len % 16;
- if (padlen && data_len < sizeof(buf)) {
+ if (padlen && data_len < buf_len) {
padlen = 16 - padlen;
os_memset(buf + data_len, 0, padlen);
- buf_len += padlen;
+ buf_len = data_len + padlen;
+ } else {
+ buf_len = data_len;
}
addr[0] = secret;
pos += 16;
}
+ return buf_len;
+}
+
+
+/* Add User-Password attribute to a RADIUS message and encrypt it as specified
+ * in RFC 2865, Chap. 5.2 */
+struct radius_attr_hdr *
+radius_msg_add_attr_user_password(struct radius_msg *msg,
+ const u8 *data, size_t data_len,
+ const u8 *secret, size_t secret_len)
+{
+ u8 buf[128];
+ int res;
+
+ res = radius_user_password_hide(msg, data, data_len,
+ secret, secret_len, buf, sizeof(buf));
+ if (res < 0)
+ return NULL;
+
return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD,
- buf, buf_len);
+ buf, res);
}
const u8 *recv_key, size_t recv_key_len);
int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data,
size_t len);
+int radius_user_password_hide(struct radius_msg *msg,
+ const u8 *data, size_t data_len,
+ const u8 *secret, size_t secret_len,
+ u8 *buf, size_t buf_len);
struct radius_attr_hdr *
radius_msg_add_attr_user_password(struct radius_msg *msg,
const u8 *data, size_t data_len,
u8 last_authenticator[16];
unsigned int remediation:1;
+ unsigned int macacl:1;
struct hostapd_radius_attr *accept_attr;
};
return NULL;
}
sess->accept_attr = tmp.accept_attr;
+ sess->macacl = tmp.macacl;
sess->username = os_malloc(user_len * 2 + 1);
if (sess->username == NULL) {
}
+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,
}
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);
reply = radius_server_encapsulate_eap(data, client, sess, msg);
+send_reply:
if (reply) {
struct wpabuf *buf;
struct radius_hdr *hdr;
if (ret == 0 && user) {
sess->accept_attr = user->accept_attr;
sess->remediation = user->remediation;
+ sess->macacl = user->macacl;
}
return ret;
}