radius_das.c revision 04949598a23f501be6eec21697465fd46a28840a
104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt/* 204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * RADIUS Dynamic Authorization Server (DAS) (RFC 5176) 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2012, Jouni Malinen <j@w1.fi> 404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * This software may be distributed under the terms of the BSD license. 604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * See README for more details. 704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "includes.h" 1004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include <net/if.h> 1104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "utils/common.h" 1304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "utils/eloop.h" 1404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "utils/ip_addr.h" 1504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "radius.h" 1604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "radius_das.h" 1704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtextern int wpa_debug_level; 2004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct radius_das_data { 2304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int sock; 2404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *shared_secret; 2504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t shared_secret_len; 2604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_ip_addr client_addr; 2704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt unsigned int time_window; 2804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int require_event_timestamp; 2904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void *ctx; 3004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt enum radius_das_res (*disconnect)(void *ctx, 3104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_das_attrs *attr); 3204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}; 3304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 3404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 3504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct radius_msg * radius_das_disconnect(struct radius_das_data *das, 3604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_msg *msg, 3704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *abuf, 3804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int from_port) 3904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 4004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_hdr *hdr; 4104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_msg *reply; 4204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 allowed[] = { 4304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_USER_NAME, 4404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_CALLING_STATION_ID, 4504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_ACCT_SESSION_ID, 4604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_EVENT_TIMESTAMP, 4704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_MESSAGE_AUTHENTICATOR, 4804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 4904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0 5004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt }; 5104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int error = 405; 5204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 attr; 5304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt enum radius_das_res res; 5404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_das_attrs attrs; 5504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 *buf; 5604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 5704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char tmp[100]; 5804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 sta_addr[ETH_ALEN]; 5904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 6004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hdr = radius_msg_get_hdr(msg); 6104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 6204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attr = radius_msg_find_unlisted_attr(msg, allowed); 6304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (attr) { 6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_INFO, "DAS: Unsupported attribute %u in " 6504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "Disconnect-Request from %s:%d", attr, 6604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt abuf, from_port); 6704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt error = 401; 6804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 6904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 7004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(&attrs, 0, sizeof(attrs)); 7204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 7304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID, 7404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt &buf, &len, NULL) == 0) { 7504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (len >= sizeof(tmp)) 7604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = sizeof(tmp) - 1; 7704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcpy(tmp, buf, len); 7804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tmp[len] = '\0'; 7904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hwaddr_aton2(tmp, sta_addr) < 0) { 8004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_INFO, "DAS: Invalid Calling-Station-Id " 8104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "'%s' from %s:%d", tmp, abuf, from_port); 8204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt error = 407; 8304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 8404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 8504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.sta_addr = sta_addr; 8604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 8704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 8804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, 8904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt &buf, &len, NULL) == 0) { 9004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.user_name = buf; 9104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.user_name_len = len; 9204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 9304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 9404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_ACCT_SESSION_ID, 9504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt &buf, &len, NULL) == 0) { 9604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.acct_session_id = buf; 9704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.acct_session_id_len = len; 9804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 9904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 10004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, 10104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt &buf, &len, NULL) == 0) { 10204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.cui = buf; 10304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt attrs.cui_len = len; 10404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 10504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 10604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res = das->disconnect(das->ctx, &attrs); 10704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (res) { 10804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case RADIUS_DAS_NAS_MISMATCH: 10904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_INFO, "DAS: NAS mismatch from %s:%d", 11004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt abuf, from_port); 11104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt error = 403; 11204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 11304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case RADIUS_DAS_SESSION_NOT_FOUND: 11404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_INFO, "DAS: Session not found for request from " 11504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "%s:%d", abuf, from_port); 11604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt error = 503; 11704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 11804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case RADIUS_DAS_SUCCESS: 11904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt error = 0; 12004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 12104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 12204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 12304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtfail: 12404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt reply = radius_msg_new(error ? RADIUS_CODE_DISCONNECT_NAK : 12504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_CODE_DISCONNECT_ACK, hdr->identifier); 12604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (reply == NULL) 12704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 12804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 12904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (error) { 13004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, 13104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt error); 13204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 13304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return reply; 13504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 13604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13804949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx) 13904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 14004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_das_data *das = eloop_ctx; 14104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 buf[1500]; 14204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt union { 14304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sockaddr_storage ss; 14404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sockaddr_in sin; 14504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_IPV6 14604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sockaddr_in6 sin6; 14704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_IPV6 */ 14804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } from; 14904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt char abuf[50]; 15004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int from_port = 0; 15104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt socklen_t fromlen; 15204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int len; 15304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_msg *msg, *reply = NULL; 15404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_hdr *hdr; 15504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *rbuf; 15604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u32 val; 15704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int res; 15804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct os_time now; 15904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 16004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt fromlen = sizeof(from); 16104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = recvfrom(sock, buf, sizeof(buf), 0, 16204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (struct sockaddr *) &from.ss, &fromlen); 16304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (len < 0) { 16404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno)); 16504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 16604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 16704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 16804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); 16904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt from_port = ntohs(from.sin.sin_port); 17004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 17104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d", 17204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len, abuf, from_port); 17304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) { 17404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client"); 17504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 17604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 17704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 17804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt msg = radius_msg_parse(buf, len); 17904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (msg == NULL) { 18004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet " 18104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "from %s:%d failed", abuf, from_port); 18204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 18304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 18404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 18504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) 18604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_msg_dump(msg); 18704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 18804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_verify_das_req(msg, das->shared_secret, 18904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->shared_secret_len)) { 19004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Invalid authenticator in packet " 19104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "from %s:%d - drop", abuf, from_port); 19204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 19304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 19404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 19504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_get_time(&now); 19604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res = radius_msg_get_attr(msg, RADIUS_ATTR_EVENT_TIMESTAMP, 19704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (u8 *) &val, 4); 19804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res == 4) { 19904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u32 timestamp = ntohl(val); 20004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (abs(now.sec - timestamp) > das->time_window) { 20104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Unacceptable " 20204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "Event-Timestamp (%u; local time %u) in " 20304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "packet from %s:%d - drop", 20404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt timestamp, (unsigned int) now.sec, 20504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt abuf, from_port); 20604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 20704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 20804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (das->require_event_timestamp) { 20904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Missing Event-Timestamp in packet " 21004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "from %s:%d - drop", abuf, from_port); 21104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt goto fail; 21204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 21304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 21404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hdr = radius_msg_get_hdr(msg); 21504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 21604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt switch (hdr->code) { 21704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case RADIUS_CODE_DISCONNECT_REQUEST: 21804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt reply = radius_das_disconnect(das, msg, abuf, from_port); 21904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 22004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt case RADIUS_CODE_COA_REQUEST: 22104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* TODO */ 22204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt reply = radius_msg_new(RADIUS_CODE_COA_NAK, 22304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hdr->identifier); 22404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (reply == NULL) 22504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 22604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 22704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Unsupported Service */ 22804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, 405); 22904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 23004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt default: 23104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Unexpected RADIUS code %u in " 23204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "packet from %s:%d", 23304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hdr->code, abuf, from_port); 23404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 23504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 23604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (reply) { 23704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Reply to %s:%d", abuf, from_port); 23804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 23904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!radius_msg_add_attr_int32(reply, 24004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt RADIUS_ATTR_EVENT_TIMESTAMP, 24104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt now.sec)) { 24204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Failed to add " 24304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "Event-Timestamp attribute"); 24404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 24504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 24604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (radius_msg_finish_das_resp(reply, das->shared_secret, 24704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->shared_secret_len, hdr) < 24804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 0) { 24904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "DAS: Failed to add " 25004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "Message-Authenticator attribute"); 25104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 25204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 25304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_debug_level <= MSG_MSGDUMP) 25404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_msg_dump(reply); 25504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 25604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt rbuf = radius_msg_get_buf(reply); 25704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res = sendto(das->sock, wpabuf_head(rbuf), 25804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_len(rbuf), 0, 25904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt (struct sockaddr *) &from.ss, fromlen); 26004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (res < 0) { 26104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s", 26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt abuf, from_port, strerror(errno)); 26304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 26404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 26504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtfail: 26704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_msg_free(msg); 26804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_msg_free(reply); 26904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 27004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 27104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 27204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int radius_das_open_socket(int port) 27304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 27404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int s; 27504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct sockaddr_in addr; 27604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 27704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt s = socket(PF_INET, SOCK_DGRAM, 0); 27804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (s < 0) { 27904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt perror("socket"); 28004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 28104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 28204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 28304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 28404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt addr.sin_family = AF_INET; 28504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt addr.sin_port = htons(port); 28604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 28704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt perror("bind"); 28804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt close(s); 28904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 29004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 29104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 29204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return s; 29304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 29404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 29504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 29604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct radius_das_data * 29704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtradius_das_init(struct radius_das_conf *conf) 29804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 29904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct radius_das_data *das; 30004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 30104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (conf->port == 0 || conf->shared_secret == NULL || 30204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt conf->client_addr == NULL) 30304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 30404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 30504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das = os_zalloc(sizeof(*das)); 30604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (das == NULL) 30704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 30804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 30904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->time_window = conf->time_window; 31004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->require_event_timestamp = conf->require_event_timestamp; 31104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->ctx = conf->ctx; 31204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->disconnect = conf->disconnect; 31304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 31404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcpy(&das->client_addr, conf->client_addr, 31504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sizeof(das->client_addr)); 31604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 31704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->shared_secret = os_malloc(conf->shared_secret_len); 31804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (das->shared_secret == NULL) { 31904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_das_deinit(das); 32004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 32104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 32204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcpy(das->shared_secret, conf->shared_secret, 32304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt conf->shared_secret_len); 32404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->shared_secret_len = conf->shared_secret_len; 32504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 32604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt das->sock = radius_das_open_socket(conf->port); 32704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (das->sock < 0) { 32804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS " 32904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "DAS"); 33004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_das_deinit(das); 33104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 33204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 33304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 33404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL)) 33504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt { 33604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt radius_das_deinit(das); 33704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 33804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 33904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return das; 34104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 34204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid radius_das_deinit(struct radius_das_data *das) 34504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 34604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (das == NULL) 34704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 34804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (das->sock >= 0) { 35004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eloop_unregister_read_sock(das->sock); 35104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt close(das->sock); 35204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 35304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 35404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(das->shared_secret); 35504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(das); 35604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 357