00001
00021 #include "includes.h"
00022
00023 #ifndef CONFIG_NATIVE_WINDOWS
00024
00025 #include "hostapd.h"
00026 #include "config.h"
00027 #include "ieee802_11.h"
00028 #include "ieee802_11_auth.h"
00029 #include "radius/radius.h"
00030 #include "radius/radius_client.h"
00031 #include "eloop.h"
00032 #ifdef CONFIG_DRIVER_RADIUS_ACL
00033 #include "driver_i.h"
00034 #endif
00035
00036 #define RADIUS_ACL_TIMEOUT 30
00037
00038
00039 struct hostapd_cached_radius_acl {
00040 time_t timestamp;
00041 macaddr addr;
00042 int accepted;
00043 struct hostapd_cached_radius_acl *next;
00044 u32 session_timeout;
00045 u32 acct_interim_interval;
00046 int vlan_id;
00047 };
00048
00049
00050 struct hostapd_acl_query_data {
00051 time_t timestamp;
00052 u8 radius_id;
00053 macaddr addr;
00054 u8 *auth_msg;
00055 size_t auth_msg_len;
00056 struct hostapd_acl_query_data *next;
00057 };
00058
00059
00060 #ifndef CONFIG_NO_RADIUS
00061 static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
00062 {
00063 struct hostapd_cached_radius_acl *prev;
00064
00065 while (acl_cache) {
00066 prev = acl_cache;
00067 acl_cache = acl_cache->next;
00068 os_free(prev);
00069 }
00070 }
00071
00072
00073 static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
00074 u32 *session_timeout,
00075 u32 *acct_interim_interval, int *vlan_id)
00076 {
00077 struct hostapd_cached_radius_acl *entry;
00078 time_t now;
00079
00080 time(&now);
00081 entry = hapd->acl_cache;
00082
00083 while (entry) {
00084 if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
00085 if (now - entry->timestamp > RADIUS_ACL_TIMEOUT)
00086 return -1;
00087 if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
00088 if (session_timeout)
00089 *session_timeout =
00090 entry->session_timeout;
00091 if (acct_interim_interval)
00092 *acct_interim_interval =
00093 entry->acct_interim_interval;
00094 if (vlan_id)
00095 *vlan_id = entry->vlan_id;
00096 return entry->accepted;
00097 }
00098
00099 entry = entry->next;
00100 }
00101
00102 return -1;
00103 }
00104 #endif
00105
00106
00107 static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
00108 {
00109 if (query == NULL)
00110 return;
00111 os_free(query->auth_msg);
00112 os_free(query);
00113 }
00114
00115
00116 #ifndef CONFIG_NO_RADIUS
00117 static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
00118 struct hostapd_acl_query_data *query)
00119 {
00120 struct radius_msg *msg;
00121 char buf[128];
00122
00123 query->radius_id = radius_client_get_id(hapd->radius);
00124 msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id);
00125 if (msg == NULL)
00126 return -1;
00127
00128 radius_msg_make_authenticator(msg, addr, ETH_ALEN);
00129
00130 os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
00131 if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
00132 os_strlen(buf))) {
00133 wpa_printf(MSG_DEBUG, "Could not add User-Name");
00134 goto fail;
00135 }
00136
00137 if (!radius_msg_add_attr_user_password(
00138 msg, (u8 *) buf, os_strlen(buf),
00139 hapd->conf->radius->auth_server->shared_secret,
00140 hapd->conf->radius->auth_server->shared_secret_len)) {
00141 wpa_printf(MSG_DEBUG, "Could not add User-Password");
00142 goto fail;
00143 }
00144
00145 if (hapd->conf->own_ip_addr.af == AF_INET &&
00146 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
00147 (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) {
00148 wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address");
00149 goto fail;
00150 }
00151
00152 #ifdef CONFIG_IPV6
00153 if (hapd->conf->own_ip_addr.af == AF_INET6 &&
00154 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
00155 (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) {
00156 wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address");
00157 goto fail;
00158 }
00159 #endif
00160
00161 if (hapd->conf->nas_identifier &&
00162 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
00163 (u8 *) hapd->conf->nas_identifier,
00164 os_strlen(hapd->conf->nas_identifier))) {
00165 wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier");
00166 goto fail;
00167 }
00168
00169 os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
00170 MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid);
00171 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
00172 (u8 *) buf, os_strlen(buf))) {
00173 wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id");
00174 goto fail;
00175 }
00176
00177 os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
00178 MAC2STR(addr));
00179 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
00180 (u8 *) buf, os_strlen(buf))) {
00181 wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id");
00182 goto fail;
00183 }
00184
00185 if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
00186 RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
00187 wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type");
00188 goto fail;
00189 }
00190
00191 os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
00192 if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
00193 (u8 *) buf, os_strlen(buf))) {
00194 wpa_printf(MSG_DEBUG, "Could not add Connect-Info");
00195 goto fail;
00196 }
00197
00198 radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr);
00199 return 0;
00200
00201 fail:
00202 radius_msg_free(msg);
00203 os_free(msg);
00204 return -1;
00205 }
00206 #endif
00207
00208
00221 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
00222 const u8 *msg, size_t len, u32 *session_timeout,
00223 u32 *acct_interim_interval, int *vlan_id)
00224 {
00225 if (session_timeout)
00226 *session_timeout = 0;
00227 if (acct_interim_interval)
00228 *acct_interim_interval = 0;
00229 if (vlan_id)
00230 *vlan_id = 0;
00231
00232 if (hostapd_maclist_found(hapd->conf->accept_mac,
00233 hapd->conf->num_accept_mac, addr, vlan_id))
00234 return HOSTAPD_ACL_ACCEPT;
00235
00236 if (hostapd_maclist_found(hapd->conf->deny_mac,
00237 hapd->conf->num_deny_mac, addr, vlan_id))
00238 return HOSTAPD_ACL_REJECT;
00239
00240 if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
00241 return HOSTAPD_ACL_ACCEPT;
00242 if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
00243 return HOSTAPD_ACL_REJECT;
00244
00245 if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
00246 #ifdef CONFIG_NO_RADIUS
00247 return HOSTAPD_ACL_REJECT;
00248 #else
00249 struct hostapd_acl_query_data *query;
00250
00251
00252 int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
00253 acct_interim_interval,
00254 vlan_id);
00255 if (res == HOSTAPD_ACL_ACCEPT ||
00256 res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
00257 return res;
00258 if (res == HOSTAPD_ACL_REJECT)
00259 return HOSTAPD_ACL_REJECT;
00260
00261 query = hapd->acl_queries;
00262 while (query) {
00263 if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) {
00264
00265
00266 return HOSTAPD_ACL_PENDING;
00267 }
00268 query = query->next;
00269 }
00270
00271 if (!hapd->conf->radius->auth_server)
00272 return HOSTAPD_ACL_REJECT;
00273
00274
00275 query = os_zalloc(sizeof(*query));
00276 if (query == NULL) {
00277 wpa_printf(MSG_ERROR, "malloc for query data failed");
00278 return HOSTAPD_ACL_REJECT;
00279 }
00280 time(&query->timestamp);
00281 os_memcpy(query->addr, addr, ETH_ALEN);
00282 if (hostapd_radius_acl_query(hapd, addr, query)) {
00283 wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
00284 "for ACL query.");
00285 hostapd_acl_query_free(query);
00286 return HOSTAPD_ACL_REJECT;
00287 }
00288
00289 query->auth_msg = os_malloc(len);
00290 if (query->auth_msg == NULL) {
00291 wpa_printf(MSG_ERROR, "Failed to allocate memory for "
00292 "auth frame.");
00293 hostapd_acl_query_free(query);
00294 return HOSTAPD_ACL_REJECT;
00295 }
00296 os_memcpy(query->auth_msg, msg, len);
00297 query->auth_msg_len = len;
00298 query->next = hapd->acl_queries;
00299 hapd->acl_queries = query;
00300
00301
00302
00303 return HOSTAPD_ACL_PENDING;
00304 #endif
00305 }
00306
00307 return HOSTAPD_ACL_REJECT;
00308 }
00309
00310
00311 #ifndef CONFIG_NO_RADIUS
00312 static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
00313 {
00314 struct hostapd_cached_radius_acl *prev, *entry, *tmp;
00315
00316 prev = NULL;
00317 entry = hapd->acl_cache;
00318
00319 while (entry) {
00320 if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
00321 wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
00322 " has expired.", MAC2STR(entry->addr));
00323 if (prev)
00324 prev->next = entry->next;
00325 else
00326 hapd->acl_cache = entry->next;
00327 #ifdef CONFIG_DRIVER_RADIUS_ACL
00328 hostapd_set_radius_acl_expire(hapd, entry->addr);
00329 #endif
00330 tmp = entry;
00331 entry = entry->next;
00332 os_free(tmp);
00333 continue;
00334 }
00335
00336 prev = entry;
00337 entry = entry->next;
00338 }
00339 }
00340
00341
00342 static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now)
00343 {
00344 struct hostapd_acl_query_data *prev, *entry, *tmp;
00345
00346 prev = NULL;
00347 entry = hapd->acl_queries;
00348
00349 while (entry) {
00350 if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
00351 wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
00352 " has expired.", MAC2STR(entry->addr));
00353 if (prev)
00354 prev->next = entry->next;
00355 else
00356 hapd->acl_queries = entry->next;
00357
00358 tmp = entry;
00359 entry = entry->next;
00360 hostapd_acl_query_free(tmp);
00361 continue;
00362 }
00363
00364 prev = entry;
00365 entry = entry->next;
00366 }
00367 }
00368
00369
00376 static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
00377 {
00378 struct hostapd_data *hapd = eloop_ctx;
00379 time_t now;
00380
00381 time(&now);
00382 hostapd_acl_expire_cache(hapd, now);
00383 hostapd_acl_expire_queries(hapd, now);
00384
00385 eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
00386 }
00387
00388
00400 static RadiusRxResult
00401 hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
00402 const u8 *shared_secret, size_t shared_secret_len,
00403 void *data)
00404 {
00405 struct hostapd_data *hapd = data;
00406 struct hostapd_acl_query_data *query, *prev;
00407 struct hostapd_cached_radius_acl *cache;
00408
00409 query = hapd->acl_queries;
00410 prev = NULL;
00411 while (query) {
00412 if (query->radius_id == msg->hdr->identifier)
00413 break;
00414 prev = query;
00415 query = query->next;
00416 }
00417 if (query == NULL)
00418 return RADIUS_RX_UNKNOWN;
00419
00420 wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS "
00421 "message (id=%d)", query->radius_id);
00422
00423 if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
00424 wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have "
00425 "correct authenticator - dropped\n");
00426 return RADIUS_RX_INVALID_AUTHENTICATOR;
00427 }
00428
00429 if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
00430 msg->hdr->code != RADIUS_CODE_ACCESS_REJECT) {
00431 wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
00432 "query", msg->hdr->code);
00433 return RADIUS_RX_UNKNOWN;
00434 }
00435
00436
00437 cache = os_zalloc(sizeof(*cache));
00438 if (cache == NULL) {
00439 wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
00440 goto done;
00441 }
00442 time(&cache->timestamp);
00443 os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
00444 if (msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
00445 if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
00446 &cache->session_timeout) == 0)
00447 cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
00448 else
00449 cache->accepted = HOSTAPD_ACL_ACCEPT;
00450
00451 if (radius_msg_get_attr_int32(
00452 msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
00453 &cache->acct_interim_interval) == 0 &&
00454 cache->acct_interim_interval < 60) {
00455 wpa_printf(MSG_DEBUG, "Ignored too small "
00456 "Acct-Interim-Interval %d for STA " MACSTR,
00457 cache->acct_interim_interval,
00458 MAC2STR(query->addr));
00459 cache->acct_interim_interval = 0;
00460 }
00461
00462 cache->vlan_id = radius_msg_get_vlanid(msg);
00463 } else
00464 cache->accepted = HOSTAPD_ACL_REJECT;
00465 cache->next = hapd->acl_cache;
00466 hapd->acl_cache = cache;
00467
00468 #ifdef CONFIG_DRIVER_RADIUS_ACL
00469 hostapd_set_radius_acl_auth(hapd, query->addr, cache->accepted,
00470 cache->session_timeout);
00471 #else
00472 #ifdef NEED_AP_MLME
00473
00474 wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
00475 "successful RADIUS ACL query");
00476 ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len,
00477 WLAN_FC_STYPE_AUTH, NULL);
00478 #endif
00479 #endif
00480
00481 done:
00482 if (prev == NULL)
00483 hapd->acl_queries = query->next;
00484 else
00485 prev->next = query->next;
00486
00487 hostapd_acl_query_free(query);
00488
00489 return RADIUS_RX_PROCESSED;
00490 }
00491 #endif
00492
00493
00499 int hostapd_acl_init(struct hostapd_data *hapd)
00500 {
00501 #ifndef CONFIG_NO_RADIUS
00502 if (radius_client_register(hapd->radius, RADIUS_AUTH,
00503 hostapd_acl_recv_radius, hapd))
00504 return -1;
00505
00506 eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
00507 #endif
00508
00509 return 0;
00510 }
00511
00512
00518 void hostapd_acl_deinit(struct hostapd_data *hapd)
00519 {
00520 struct hostapd_acl_query_data *query, *prev;
00521
00522 #ifndef CONFIG_NO_RADIUS
00523 eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL);
00524
00525 hostapd_acl_cache_free(hapd->acl_cache);
00526 #endif
00527
00528 query = hapd->acl_queries;
00529 while (query) {
00530 prev = query;
00531 query = query->next;
00532 hostapd_acl_query_free(prev);
00533 }
00534 }
00535
00536
00537 int hostapd_acl_reconfig(struct hostapd_data *hapd,
00538 struct hostapd_config *oldconf)
00539 {
00540 if (!hapd->radius_client_reconfigured)
00541 return 0;
00542
00543 hostapd_acl_deinit(hapd);
00544 return hostapd_acl_init(hapd);
00545 }
00546
00547 #endif
00548