static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, struct hostapd_acl_query_data *query) { struct radius_msg *msg; char buf[128]; query->radius_id = radius_client_get_id(hapd->radius); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); if (msg == NULL) return -1; radius_msg_make_authenticator(msg, addr, ETH_ALEN); os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add User-Name"); goto fail; } if (!radius_msg_add_attr_user_password( msg, (u8 *) buf, os_strlen(buf), hapd->conf->radius->auth_server->shared_secret, hapd->conf->radius->auth_server->shared_secret_len)) { wpa_printf(MSG_DEBUG, "Could not add User-Password"); goto fail; } if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, NULL, msg) < 0) goto fail; os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); goto fail; } os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); goto fail; } if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0) goto fail; return 0; fail: radius_msg_free(msg); return -1; }
static void start_example(void *eloop_ctx, void *timeout_ctx) { struct radius_ctx *ctx = eloop_ctx; struct radius_msg *msg; printf("Sending a RADIUS authentication message\n"); ctx->radius_identifier = radius_client_get_id(ctx->radius); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, ctx->radius_identifier); if (msg == NULL) { printf("Could not create net RADIUS packet\n"); return; } radius_msg_make_authenticator(msg, (u8 *) ctx, sizeof(*ctx)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) "user", 4)) { printf("Could not add User-Name\n"); radius_msg_free(msg); return; } if (!radius_msg_add_attr_user_password( msg, (u8 *) "password", 8, ctx->conf.auth_server->shared_secret, ctx->conf.auth_server->shared_secret_len)) { printf("Could not add User-Password\n"); radius_msg_free(msg); return; } if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &ctx->own_ip_addr, 4)) { printf("Could not add NAS-IP-Address\n"); radius_msg_free(msg); return; } if (radius_client_send(ctx->radius, msg, RADIUS_AUTH, NULL) < 0) radius_msg_free(msg); }
static int radius_server_reject(struct radius_server_data *data, struct radius_client *client, struct radius_msg *request, struct sockaddr_in *from) { struct radius_msg *msg; int ret = 0; RADIUS_DEBUG("Reject invalid request from %s:%d", inet_ntoa(from->sin_addr), ntohs(from->sin_port)); msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, request->hdr->identifier); if (msg == NULL) { return -1; } if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, client->shared_secret_len, request->hdr->authenticator) < 0) { RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); } if (wpa_debug_level <= MSG_MSGDUMP) { radius_msg_dump(msg); } if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0, (struct sockaddr *) from, sizeof(*from)) < 0) { perror("sendto[RADIUS SRV]"); ret = -1; } radius_msg_free(msg); free(msg); return ret; }
static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e, const u8 *eap, size_t len) { struct radius_msg *msg; char buf[128]; const struct eap_hdr *hdr; const u8 *pos; wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " "packet"); e->radius_identifier = radius_client_get_id(e->radius); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, e->radius_identifier); if (msg == NULL) { printf("Could not create net RADIUS packet\n"); return; } radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e)); hdr = (const struct eap_hdr *) eap; pos = (const u8 *) (hdr + 1); if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE && pos[0] == EAP_TYPE_IDENTITY) { pos++; os_free(e->eap_identity); e->eap_identity_len = len - sizeof(*hdr) - 1; e->eap_identity = os_malloc(e->eap_identity_len); if (e->eap_identity) { os_memcpy(e->eap_identity, pos, e->eap_identity_len); wpa_hexdump(MSG_DEBUG, "Learned identity from " "EAP-Response-Identity", e->eap_identity, e->eap_identity_len); } } if (e->eap_identity && !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, e->eap_identity, e->eap_identity_len)) { printf("Could not add User-Name\n"); goto fail; } if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_IP_ADDRESS) && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &e->own_ip_addr, 4)) { printf("Could not add NAS-IP-Address\n"); goto fail; } os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(e->wpa_s->own_addr)); if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CALLING_STATION_ID) && !radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, (u8 *) buf, os_strlen(buf))) { printf("Could not add Calling-Station-Id\n"); goto fail; } /* TODO: should probably check MTU from driver config; 2304 is max for * IEEE 802.11, but use 1400 to avoid problems with too large packets */ if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_FRAMED_MTU) && !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { printf("Could not add Framed-MTU\n"); goto fail; } if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_PORT_TYPE) && !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { printf("Could not add NAS-Port-Type\n"); goto fail; } os_snprintf(buf, sizeof(buf), "%s", e->connect_info); if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) && !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, (u8 *) buf, os_strlen(buf))) { printf("Could not add Connect-Info\n"); goto fail; } if (add_extra_attrs(msg, e->extra_attrs) < 0) goto fail; if (eap && !radius_msg_add_eap(msg, eap, len)) { printf("Could not add EAP-Message\n"); goto fail; } /* State attribute must be copied if and only if this packet is * Access-Request reply to the previous Access-Challenge */ if (e->last_recv_radius && radius_msg_get_hdr(e->last_recv_radius)->code == RADIUS_CODE_ACCESS_CHALLENGE) { int res = radius_msg_copy_attr(msg, e->last_recv_radius, RADIUS_ATTR_STATE); if (res < 0) { printf("Could not copy State attribute from previous " "Access-Challenge\n"); goto fail; } if (res > 0) { wpa_printf(MSG_DEBUG, " Copied RADIUS State " "Attribute"); } } radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr); return; fail: radius_msg_free(msg); }
static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, struct hostapd_acl_query_data *query) { struct radius_msg *msg; char buf[128]; query->radius_id = radius_client_get_id(hapd->radius); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); if (msg == NULL) return -1; radius_msg_make_authenticator(msg, addr, ETH_ALEN); os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add User-Name"); goto fail; } if (!radius_msg_add_attr_user_password( msg, (u8 *) buf, os_strlen(buf), hapd->conf->radius->auth_server->shared_secret, hapd->conf->radius->auth_server->shared_secret_len)) { wpa_printf(MSG_DEBUG, "Could not add User-Password"); goto fail; } if (hapd->conf->own_ip_addr.af == AF_INET && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address"); goto fail; } #ifdef CONFIG_IPV6 if (hapd->conf->own_ip_addr.af == AF_INET6 && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address"); goto fail; } #endif /* CONFIG_IPV6 */ if (hapd->conf->nas_identifier && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, (u8 *) hapd->conf->nas_identifier, os_strlen(hapd->conf->nas_identifier))) { wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier"); goto fail; } os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id"); goto fail; } os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type"); goto fail; } os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); goto fail; } radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); return 0; fail: radius_msg_free(msg); return -1; }
static void ieee802_1x_encapsulate_radius(struct wpa_supplicant *wpa_s, u8 *eap, size_t len) { struct radius_msg *msg; char buf[128]; struct wpa_ssid *ssid = wpa_s->current_ssid; u8 *identity; size_t identity_len; wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " "packet"); wpa_s->radius_identifier = radius_client_get_id(wpa_s); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, wpa_s->radius_identifier); if (msg == NULL) { printf("Could not create net RADIUS packet\n"); return; } radius_msg_make_authenticator(msg, (u8 *) wpa_s, sizeof(*wpa_s)); if (ssid->anonymous_identity) { identity = ssid->anonymous_identity; identity_len = ssid->anonymous_identity_len; } else { identity = ssid->identity; identity_len = ssid->identity_len; } if (identity && !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, identity, identity_len)) { printf("Could not add User-Name\n"); goto fail; } if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &wpa_s->own_ip_addr, 4)) { printf("Could not add NAS-IP-Address\n"); goto fail; } snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(wpa_s->own_addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, buf, strlen(buf))) { printf("Could not add Calling-Station-Id\n"); goto fail; } /* TODO: should probably check MTU from driver config; 2304 is max for * IEEE 802.11, but use 1400 to avoid problems with too large packets */ if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { printf("Could not add Framed-MTU\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { printf("Could not add NAS-Port-Type\n"); goto fail; } snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, buf, strlen(buf))) { printf("Could not add Connect-Info\n"); goto fail; } if (eap && !radius_msg_add_eap(msg, eap, len)) { printf("Could not add EAP-Message\n"); goto fail; } /* State attribute must be copied if and only if this packet is * Access-Request reply to the previous Access-Challenge */ if (wpa_s->last_recv_radius && wpa_s->last_recv_radius->hdr->code == RADIUS_CODE_ACCESS_CHALLENGE) { int res = radius_msg_copy_attr(msg, wpa_s->last_recv_radius, RADIUS_ATTR_STATE); if (res < 0) { printf("Could not copy State attribute from previous " "Access-Challenge\n"); goto fail; } if (res > 0) { wpa_printf(MSG_DEBUG, " Copied RADIUS State " "Attribute"); } } radius_client_send(wpa_s, msg, RADIUS_AUTH, wpa_s->own_addr); return; fail: radius_msg_free(msg); free(msg); }
static struct radius_msg * radius_server_encapsulate_eap(struct radius_server_data *data, struct radius_client *client, struct radius_session *sess, struct radius_msg *request) { struct radius_msg *msg; int code; unsigned int sess_id; if (sess->eap_if->eapFail) { sess->eap_if->eapFail = FALSE; code = RADIUS_CODE_ACCESS_REJECT; } else if (sess->eap_if->eapSuccess) { sess->eap_if->eapSuccess = FALSE; code = RADIUS_CODE_ACCESS_ACCEPT; } else { sess->eap_if->eapReq = FALSE; code = RADIUS_CODE_ACCESS_CHALLENGE; } msg = radius_msg_new(code, request->hdr->identifier); if (msg == NULL) { RADIUS_DEBUG("Failed to allocate reply message"); return NULL; } sess_id = htonl(sess->sess_id); if (code == RADIUS_CODE_ACCESS_CHALLENGE && !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, (u8 *) &sess_id, sizeof(sess_id))) { RADIUS_DEBUG("Failed to add State attribute"); } if (sess->eap_if->eapReqData && !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), wpabuf_len(sess->eap_if->eapReqData))) { RADIUS_DEBUG("Failed to add EAP-Message attribute"); } if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { int len; if (sess->eap_if->eapKeyDataLen > 64) { len = 32; } else { len = sess->eap_if->eapKeyDataLen / 2; } if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator, (u8 *) client->shared_secret, client->shared_secret_len, sess->eap_if->eapKeyData + len, len, sess->eap_if->eapKeyData, len)) { RADIUS_DEBUG("Failed to add MPPE key attributes"); } } 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); os_free(msg); return NULL; } if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, client->shared_secret_len, request->hdr->authenticator) < 0) { RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); } return msg; }
static struct radius_msg * radius_das_disconnect(struct radius_das_data *das, struct radius_msg *msg, const char *abuf, int from_port) { struct radius_hdr *hdr; struct radius_msg *reply; u8 allowed[] = { RADIUS_ATTR_USER_NAME, RADIUS_ATTR_NAS_IP_ADDRESS, RADIUS_ATTR_CALLING_STATION_ID, RADIUS_ATTR_NAS_IDENTIFIER, RADIUS_ATTR_ACCT_SESSION_ID, RADIUS_ATTR_ACCT_MULTI_SESSION_ID, RADIUS_ATTR_EVENT_TIMESTAMP, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, #ifdef CONFIG_IPV6 RADIUS_ATTR_NAS_IPV6_ADDRESS, #endif /* CONFIG_IPV6 */ 0 }; int error = 405; u8 attr; enum radius_das_res res; struct radius_das_attrs attrs; u8 *buf; size_t len; char tmp[100]; u8 sta_addr[ETH_ALEN]; hdr = radius_msg_get_hdr(msg); attr = radius_msg_find_unlisted_attr(msg, allowed); if (attr) { wpa_printf(MSG_INFO, "DAS: Unsupported attribute %u in " "Disconnect-Request from %s:%d", attr, abuf, from_port); error = 401; goto fail; } os_memset(&attrs, 0, sizeof(attrs)); if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, &buf, &len, NULL) == 0) { if (len != 4) { wpa_printf(MSG_INFO, "DAS: Invalid NAS-IP-Address from %s:%d", abuf, from_port); error = 407; goto fail; } attrs.nas_ip_addr = buf; } #ifdef CONFIG_IPV6 if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, &buf, &len, NULL) == 0) { if (len != 16) { wpa_printf(MSG_INFO, "DAS: Invalid NAS-IPv6-Address from %s:%d", abuf, from_port); error = 407; goto fail; } attrs.nas_ipv6_addr = buf; } #endif /* CONFIG_IPV6 */ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER, &buf, &len, NULL) == 0) { attrs.nas_identifier = buf; attrs.nas_identifier_len = len; } if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID, &buf, &len, NULL) == 0) { if (len >= sizeof(tmp)) len = sizeof(tmp) - 1; os_memcpy(tmp, buf, len); tmp[len] = '\0'; if (hwaddr_aton2(tmp, sta_addr) < 0) { wpa_printf(MSG_INFO, "DAS: Invalid Calling-Station-Id " "'%s' from %s:%d", tmp, abuf, from_port); error = 407; goto fail; } attrs.sta_addr = sta_addr; } if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, NULL) == 0) { attrs.user_name = buf; attrs.user_name_len = len; } if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_ACCT_SESSION_ID, &buf, &len, NULL) == 0) { attrs.acct_session_id = buf; attrs.acct_session_id_len = len; } if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_ACCT_MULTI_SESSION_ID, &buf, &len, NULL) == 0) { attrs.acct_multi_session_id = buf; attrs.acct_multi_session_id_len = len; } if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, &buf, &len, NULL) == 0) { attrs.cui = buf; attrs.cui_len = len; } res = das->disconnect(das->ctx, &attrs); switch (res) { case RADIUS_DAS_NAS_MISMATCH: wpa_printf(MSG_INFO, "DAS: NAS mismatch from %s:%d", abuf, from_port); error = 403; break; case RADIUS_DAS_SESSION_NOT_FOUND: wpa_printf(MSG_INFO, "DAS: Session not found for request from " "%s:%d", abuf, from_port); error = 503; break; case RADIUS_DAS_MULTI_SESSION_MATCH: wpa_printf(MSG_INFO, "DAS: Multiple sessions match for request from %s:%d", abuf, from_port); error = 508; break; case RADIUS_DAS_SUCCESS: error = 0; break; } fail: reply = radius_msg_new(error ? RADIUS_CODE_DISCONNECT_NAK : RADIUS_CODE_DISCONNECT_ACK, hdr->identifier); if (reply == NULL) return NULL; if (error) { if (!radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, error)) { radius_msg_free(reply); return NULL; } } return reply; }
static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx) { struct radius_das_data *das = eloop_ctx; u8 buf[1500]; union { struct sockaddr_storage ss; struct sockaddr_in sin; #ifdef CONFIG_IPV6 struct sockaddr_in6 sin6; #endif /* CONFIG_IPV6 */ } from; char abuf[50]; int from_port = 0; socklen_t fromlen; int len; struct radius_msg *msg, *reply = NULL; struct radius_hdr *hdr; struct wpabuf *rbuf; u32 val; int res; struct os_time now; fromlen = sizeof(from); len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from.ss, &fromlen); if (len < 0) { wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno)); return; } os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); from_port = ntohs(from.sin.sin_port); wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d", len, abuf, from_port); if (das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) { wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client"); return; } msg = radius_msg_parse(buf, len); if (msg == NULL) { wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet " "from %s:%d failed", abuf, from_port); return; } if (wpa_debug_level <= MSG_MSGDUMP) radius_msg_dump(msg); if (radius_msg_verify_das_req(msg, das->shared_secret, das->shared_secret_len)) { wpa_printf(MSG_DEBUG, "DAS: Invalid authenticator in packet " "from %s:%d - drop", abuf, from_port); goto fail; } os_get_time(&now); res = radius_msg_get_attr(msg, RADIUS_ATTR_EVENT_TIMESTAMP, (u8 *) &val, 4); if (res == 4) { u32 timestamp = ntohl(val); if ((unsigned int) abs((int) (now.sec - timestamp)) > das->time_window) { wpa_printf(MSG_DEBUG, "DAS: Unacceptable " "Event-Timestamp (%u; local time %u) in " "packet from %s:%d - drop", timestamp, (unsigned int) now.sec, abuf, from_port); goto fail; } } else if (das->require_event_timestamp) { wpa_printf(MSG_DEBUG, "DAS: Missing Event-Timestamp in packet " "from %s:%d - drop", abuf, from_port); goto fail; } hdr = radius_msg_get_hdr(msg); switch (hdr->code) { case RADIUS_CODE_DISCONNECT_REQUEST: reply = radius_das_disconnect(das, msg, abuf, from_port); break; case RADIUS_CODE_COA_REQUEST: /* TODO */ reply = radius_msg_new(RADIUS_CODE_COA_NAK, hdr->identifier); if (reply == NULL) break; /* Unsupported Service */ if (!radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, 405)) { radius_msg_free(reply); reply = NULL; break; } break; default: wpa_printf(MSG_DEBUG, "DAS: Unexpected RADIUS code %u in " "packet from %s:%d", hdr->code, abuf, from_port); } if (reply) { wpa_printf(MSG_DEBUG, "DAS: Reply to %s:%d", abuf, from_port); if (!radius_msg_add_attr_int32(reply, RADIUS_ATTR_EVENT_TIMESTAMP, now.sec)) { wpa_printf(MSG_DEBUG, "DAS: Failed to add " "Event-Timestamp attribute"); } if (radius_msg_finish_das_resp(reply, das->shared_secret, das->shared_secret_len, hdr) < 0) { wpa_printf(MSG_DEBUG, "DAS: Failed to add " "Message-Authenticator attribute"); } if (wpa_debug_level <= MSG_MSGDUMP) radius_msg_dump(reply); rbuf = radius_msg_get_buf(reply); res = sendto(das->sock, wpabuf_head(rbuf), wpabuf_len(rbuf), 0, (struct sockaddr *) &from.ss, fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s", abuf, from_port, strerror(errno)); } } fail: radius_msg_free(msg); radius_msg_free(reply); }
static struct radius_msg * accounting_msg(struct hostapd_data *hapd, struct sta_info *sta, int status_type) { struct radius_msg *msg; char buf[128]; u8 *val; size_t len; int i; struct wpabuf *b; msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, radius_client_get_id(hapd->radius)); if (msg == NULL) { wpa_printf(MSG_INFO, "Could not create new RADIUS packet"); return NULL; } if (sta) { radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); os_snprintf(buf, sizeof(buf), "%08X-%08X", sta->acct_session_id_hi, sta->acct_session_id_lo); if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, (u8 *) buf, os_strlen(buf))) { wpa_printf(MSG_INFO, "Could not add Acct-Session-Id"); goto fail; } } else { radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd)); } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE, status_type)) { wpa_printf(MSG_INFO, "Could not add Acct-Status-Type"); goto fail; } if (!hostapd_config_get_radius_attr(hapd->conf->radius_acct_req_attr, RADIUS_ATTR_ACCT_AUTHENTIC) && !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, hapd->conf->ieee802_1x ? RADIUS_ACCT_AUTHENTIC_RADIUS : RADIUS_ACCT_AUTHENTIC_LOCAL)) { wpa_printf(MSG_INFO, "Could not add Acct-Authentic"); goto fail; } if (sta) { /* Use 802.1X identity if available */ val = ieee802_1x_get_identity(sta->eapol_sm, &len); /* Use RADIUS ACL identity if 802.1X provides no identity */ if (!val && sta->identity) { val = (u8 *) sta->identity; len = os_strlen(sta->identity); } /* Use STA MAC if neither 802.1X nor RADIUS ACL provided * identity */ if (!val) { os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(sta->addr)); val = (u8 *) buf; len = os_strlen(buf); } if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val, len)) { wpa_printf(MSG_INFO, "Could not add User-Name"); goto fail; } } if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta, msg) < 0) goto fail; if (sta) { for (i = 0; ; i++) { val = ieee802_1x_get_radius_class(sta->eapol_sm, &len, i); if (val == NULL) break; if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS, val, len)) { wpa_printf(MSG_INFO, "Could not add Class"); goto fail; } } b = ieee802_1x_get_radius_cui(sta->eapol_sm); if (b && !radius_msg_add_attr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, wpabuf_head(b), wpabuf_len(b))) { wpa_printf(MSG_ERROR, "Could not add CUI"); goto fail; } if (!b && sta->radius_cui && !radius_msg_add_attr(msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, (u8 *) sta->radius_cui, os_strlen(sta->radius_cui))) { wpa_printf(MSG_ERROR, "Could not add CUI from ACL"); goto fail; } } return msg; fail: radius_msg_free(msg); return NULL; }
static struct radius_msg * accounting_msg(struct hostapd_data *hapd, struct sta_info *sta, int status_type) { struct radius_msg *msg; char buf[128]; u8 *val; size_t len; int i; msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, radius_client_get_id(hapd->radius)); if (msg == NULL) { printf("Could not create net RADIUS packet\n"); return NULL; } if (sta) { radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); os_snprintf(buf, sizeof(buf), "%08X-%08X", sta->acct_session_id_hi, sta->acct_session_id_lo); if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, (u8 *) buf, os_strlen(buf))) { printf("Could not add Acct-Session-Id\n"); goto fail; } } else { radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd)); } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE, status_type)) { printf("Could not add Acct-Status-Type\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, hapd->conf->ieee802_1x ? RADIUS_ACCT_AUTHENTIC_RADIUS : RADIUS_ACCT_AUTHENTIC_LOCAL)) { printf("Could not add Acct-Authentic\n"); goto fail; } if (sta) { val = ieee802_1x_get_identity(sta->eapol_sm, &len); if (!val) { os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(sta->addr)); val = (u8 *) buf; len = os_strlen(buf); } if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val, len)) { printf("Could not add User-Name\n"); goto fail; } } if (hapd->conf->own_ip_addr.af == AF_INET && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { printf("Could not add NAS-IP-Address\n"); goto fail; } #ifdef CONFIG_IPV6 if (hapd->conf->own_ip_addr.af == AF_INET6 && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { printf("Could not add NAS-IPv6-Address\n"); goto fail; } #endif /* CONFIG_IPV6 */ if (hapd->conf->nas_identifier && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, (u8 *) hapd->conf->nas_identifier, os_strlen(hapd->conf->nas_identifier))) { printf("Could not add NAS-Identifier\n"); goto fail; } if (sta && !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { printf("Could not add NAS-Port\n"); goto fail; } os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, (u8 *) buf, os_strlen(buf))) { printf("Could not add Called-Station-Id\n"); goto fail; } if (sta) { os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(sta->addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, (u8 *) buf, os_strlen(buf))) { printf("Could not add Calling-Station-Id\n"); goto fail; } if (!radius_msg_add_attr_int32( msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { printf("Could not add NAS-Port-Type\n"); goto fail; } os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", radius_sta_rate(hapd, sta) / 2, (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", radius_mode_txt(hapd)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, (u8 *) buf, os_strlen(buf))) { printf("Could not add Connect-Info\n"); goto fail; } for (i = 0; ; i++) { val = ieee802_1x_get_radius_class(sta->eapol_sm, &len, i); if (val == NULL) break; if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS, val, len)) { printf("Could not add Class\n"); goto fail; } } } return msg; fail: radius_msg_free(msg); os_free(msg); return NULL; }
static struct radius_msg * accounting_msg(hostapd *hapd, struct sta_info *sta, int status_type) { struct radius_msg *msg; char buf[128]; u8 *val; size_t len; msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, radius_client_get_id(hapd)); if (msg == NULL) { printf("Could not create net RADIUS packet\n"); return NULL; } radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(sta)); snprintf(buf, sizeof(buf), "%08X-%08X", hapd->radius->acct_session_id_hi, sta->acct_session_id_lo); if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, buf, strlen(buf))) { printf("Could not add Acct-Session-Id\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE, status_type)) { printf("Could not add Acct-Status-Type\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, hapd->conf->ieee802_1x ? RADIUS_ACCT_AUTHENTIC_RADIUS : RADIUS_ACCT_AUTHENTIC_LOCAL)) { printf("Could not add Acct-Authentic\n"); goto fail; } val = sta->identity; len = sta->identity_len; if (!val) { snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(sta->addr)); val = buf; len = strlen(val); } if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val, len)) { printf("Could not add User-Name\n"); goto fail; } if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &hapd->conf->own_ip_addr, 4)) { printf("Could not add NAS-IP-Address\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { printf("Could not add NAS-Port\n"); goto fail; } snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", MAC2STR(hapd->own_addr), hapd->conf->ssid); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, buf, strlen(buf))) { printf("Could not add Called-Station-Id\n"); goto fail; } snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(sta->addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, buf, strlen(buf))) { printf("Could not add Calling-Station-Id\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { printf("Could not add NAS-Port-Type\n"); goto fail; } snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, buf, strlen(buf))) { printf("Could not add Connect-Info\n"); goto fail; } return msg; fail: radius_msg_free(msg); free(msg); return NULL; }
static int hostapd_radius_acl_query(hostapd *hapd, u8 *addr, struct hostapd_acl_query_data *query) { struct radius_msg *msg; char buf[128]; query->radius_id = radius_client_get_id(hapd); msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); if (msg == NULL) return -1; radius_msg_make_authenticator(msg, addr, ETH_ALEN); snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, buf, strlen(buf))) { printf("Could not add User-Name\n"); goto fail; } if (!radius_msg_add_attr_user_password( msg, buf, strlen(buf), hapd->conf->auth_server->shared_secret, hapd->conf->auth_server->shared_secret_len)) { printf("Could not add User-Password\n"); goto fail; } if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, (u8 *) &hapd->conf->own_ip_addr, 4)) { printf("Could not add NAS-IP-Address\n"); goto fail; } if (hapd->conf->nas_identifier && !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, hapd->conf->nas_identifier, strlen(hapd->conf->nas_identifier))) { printf("Could not add NAS-Identifier\n"); goto fail; } snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", MAC2STR(hapd->own_addr), hapd->conf->ssid); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, buf, strlen(buf))) { printf("Could not add Called-Station-Id\n"); goto fail; } snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, MAC2STR(addr)); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, buf, strlen(buf))) { printf("Could not add Calling-Station-Id\n"); goto fail; } if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { printf("Could not add NAS-Port-Type\n"); goto fail; } snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, buf, strlen(buf))) { printf("Could not add Connect-Info\n"); goto fail; } radius_client_send(hapd, msg, RADIUS_AUTH, addr); return 0; fail: radius_msg_free(msg); free(msg); return -1; }
static struct radius_msg * radius_server_encapsulate_eap(struct radius_server_data *data, struct radius_client *client, struct radius_session *sess, struct radius_msg *request) { struct radius_msg *msg; int code; unsigned int sess_id; struct radius_hdr *hdr = radius_msg_get_hdr(request); if (sess->eap_if->eapFail) { sess->eap_if->eapFail = FALSE; code = RADIUS_CODE_ACCESS_REJECT; } else if (sess->eap_if->eapSuccess) { sess->eap_if->eapSuccess = FALSE; code = RADIUS_CODE_ACCESS_ACCEPT; } else { sess->eap_if->eapReq = FALSE; code = RADIUS_CODE_ACCESS_CHALLENGE; } msg = radius_msg_new(code, hdr->identifier); if (msg == NULL) { RADIUS_DEBUG("Failed to allocate reply message"); return NULL; } sess_id = htonl(sess->sess_id); if (code == RADIUS_CODE_ACCESS_CHALLENGE && !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, (u8 *) &sess_id, sizeof(sess_id))) { RADIUS_DEBUG("Failed to add State attribute"); } if (sess->eap_if->eapReqData && !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), wpabuf_len(sess->eap_if->eapReqData))) { RADIUS_DEBUG("Failed to add EAP-Message attribute"); } if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { int len; #ifdef CONFIG_RADIUS_TEST if (data->dump_msk_file) { FILE *f; char buf[2 * 64 + 1]; f = fopen(data->dump_msk_file, "a"); if (f) { len = sess->eap_if->eapKeyDataLen; if (len > 64) len = 64; len = wpa_snprintf_hex( buf, sizeof(buf), sess->eap_if->eapKeyData, len); buf[len] = '\0'; fprintf(f, "%s\n", buf); fclose(f); } } #endif /* CONFIG_RADIUS_TEST */ if (sess->eap_if->eapKeyDataLen > 64) { len = 32; } else { len = sess->eap_if->eapKeyDataLen / 2; } if (!radius_msg_add_mppe_keys(msg, hdr->authenticator, (u8 *) client->shared_secret, client->shared_secret_len, sess->eap_if->eapKeyData + len, len, sess->eap_if->eapKeyData, len)) { RADIUS_DEBUG("Failed to add MPPE key attributes"); } } 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 (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; }