int radius_msg_verify(struct radius_msg *msg, const u8 *secret, size_t secret_len, struct radius_msg *sent_msg, int auth) { const u8 *addr[4]; size_t len[4]; u8 hash[MD5_MAC_LEN]; if (sent_msg == NULL) { printf("No matching Access-Request message found\n"); return 1; } if (auth && radius_msg_verify_msg_auth(msg, secret, secret_len, sent_msg->hdr->authenticator)) { return 1; } /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ addr[0] = (u8 *) msg->hdr; len[0] = 1 + 1 + 2; addr[1] = sent_msg->hdr->authenticator; len[1] = MD5_MAC_LEN; addr[2] = (u8 *) (msg->hdr + 1); len[2] = msg->buf_used - sizeof(*msg->hdr); addr[3] = secret; len[3] = secret_len; md5_vector(4, addr, len, hash); if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) { printf("Response Authenticator invalid!\n"); return 1; } return 0; }
int radius_msg_verify(struct radius_msg *msg, const u8 *secret, size_t secret_len, struct radius_msg *sent_msg, int auth) { const u8 *addr[4]; size_t len[4]; u8 hash[MD5_MAC_LEN]; if (sent_msg == NULL) { wpa_printf(MSG_INFO, "No matching Access-Request message found"); return 1; } if (auth && radius_msg_verify_msg_auth(msg, secret, secret_len, sent_msg->hdr->authenticator)) { return 1; } /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ addr[0] = (u8 *) msg->hdr; len[0] = 1 + 1 + 2; addr[1] = sent_msg->hdr->authenticator; len[1] = MD5_MAC_LEN; addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr); len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr); addr[3] = secret; len[3] = secret_len; if (md5_vector(4, addr, len, hash) < 0 || os_memcmp_const(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) { wpa_printf(MSG_INFO, "Response Authenticator invalid!"); return 1; } return 0; }
static void radius_server_receive_auth(int sock, void *eloop_ctx, void *sock_ctx) { struct radius_server_data *data = eloop_ctx; u8 *buf = NULL; union { struct sockaddr_storage ss; struct sockaddr_in sin; #ifdef CONFIG_IPV6 struct sockaddr_in6 sin6; #endif /* CONFIG_IPV6 */ } from; socklen_t fromlen; int len; struct radius_client *client = NULL; struct radius_msg *msg = NULL; char abuf[50]; int from_port = 0; buf = os_malloc(RADIUS_MAX_MSG_LEN); if (buf == NULL) { goto fail; } fromlen = sizeof(from); len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, (struct sockaddr *) &from.ss, &fromlen); if (len < 0) { perror("recvfrom[radius_server]"); goto fail; } #ifdef CONFIG_IPV6 if (data->ipv6) { if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, sizeof(abuf)) == NULL) abuf[0] = '\0'; from_port = ntohs(from.sin6.sin6_port); RADIUS_DEBUG("Received %d bytes from %s:%d", len, abuf, from_port); client = radius_server_get_client(data, (struct in_addr *) &from.sin6.sin6_addr, 1); } #endif /* CONFIG_IPV6 */ if (!data->ipv6) { os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); from_port = ntohs(from.sin.sin_port); RADIUS_DEBUG("Received %d bytes from %s:%d", len, abuf, from_port); client = radius_server_get_client(data, &from.sin.sin_addr, 0); } RADIUS_DUMP("Received data", buf, len); if (client == NULL) { RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); data->counters.invalid_requests++; goto fail; } msg = radius_msg_parse(buf, len); if (msg == NULL) { RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); data->counters.malformed_access_requests++; client->counters.malformed_access_requests++; goto fail; } os_free(buf); buf = NULL; if (wpa_debug_level <= MSG_MSGDUMP) { radius_msg_dump(msg); } if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) { RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code); data->counters.unknown_types++; client->counters.unknown_types++; goto fail; } data->counters.access_requests++; client->counters.access_requests++; if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, client->shared_secret_len, NULL)) { RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); data->counters.bad_authenticators++; client->counters.bad_authenticators++; goto fail; } if (radius_server_request(data, msg, (struct sockaddr *) &from, fromlen, client, abuf, from_port, NULL) == -2) return; /* msg was stored with the session */ fail: if (msg) { radius_msg_free(msg); os_free(msg); } os_free(buf); }
static void radius_server_receive_auth(int sock, void *eloop_ctx, void *sock_ctx) { struct radius_server_data *data = eloop_ctx; u8 *buf = NULL; struct sockaddr_in from; socklen_t fromlen; int len; struct radius_client *client; struct radius_msg *msg = NULL; buf = malloc(RADIUS_MAX_MSG_LEN); if (buf == NULL) { goto fail; } fromlen = sizeof(from); len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, (struct sockaddr *) &from, &fromlen); if (len < 0) { perror("recvfrom[radius_server]"); goto fail; } RADIUS_DEBUG("Received %d bytes from %s:%d", len, inet_ntoa(from.sin_addr), ntohs(from.sin_port)); RADIUS_DUMP("Received data", buf, len); client = radius_server_get_client(data, &from.sin_addr); if (client == NULL) { RADIUS_DEBUG("Unknown client %s - packet ignored", inet_ntoa(from.sin_addr)); goto fail; } msg = radius_msg_parse(buf, len); if (msg == NULL) { RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); goto fail; } free(buf); buf = NULL; if (wpa_debug_level <= MSG_MSGDUMP) { radius_msg_dump(msg); } if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) { RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code); goto fail; } if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, client->shared_secret_len, NULL)) { RADIUS_DEBUG("Invalid Message-Authenticator from %s", inet_ntoa(from.sin_addr)); goto fail; } radius_server_request(data, msg, &from, client); fail: if (msg) { radius_msg_free(msg); free(msg); } free(buf); }