summaryrefslogtreecommitdiff
path: root/src/libradius
diff options
context:
space:
mode:
Diffstat (limited to 'src/libradius')
-rw-r--r--src/libradius/radius_message.c2
-rw-r--r--src/libradius/radius_socket.c104
2 files changed, 70 insertions, 36 deletions
diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c
index 3905a06c7..e6abfe2c2 100644
--- a/src/libradius/radius_message.c
+++ b/src/libradius/radius_message.c
@@ -536,7 +536,7 @@ METHOD(radius_message_t, verify, bool,
/* verify Response-Authenticator */
if (!hasher->get_hash(hasher, msg, NULL) ||
!hasher->get_hash(hasher, secret, buf) ||
- !memeq(buf, res_auth, HASH_SIZE_MD5))
+ !memeq_const(buf, res_auth, HASH_SIZE_MD5))
{
DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
return FALSE;
diff --git a/src/libradius/radius_socket.c b/src/libradius/radius_socket.c
index fe9cf3c01..ad5daa54b 100644
--- a/src/libradius/radius_socket.c
+++ b/src/libradius/radius_socket.c
@@ -125,9 +125,65 @@ static bool check_connection(private_radius_socket_t *this,
return TRUE;
}
+/**
+ * Receive the response to the message with the given ID
+ */
+static status_t receive_response(int fd, int timeout, u_int8_t id,
+ radius_message_t **response)
+{
+ radius_message_t *msg;
+ char buf[4096];
+ int res;
+ struct pollfd pfd = {
+ .fd = fd,
+ .events = POLLIN,
+ };
+
+ while (TRUE)
+ {
+ res = poll(&pfd, 1, timeout);
+ if (res < 0)
+ {
+ DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
+ strerror(errno));
+ return FAILED;
+ }
+ if (res == 0)
+ { /* timeout */
+ return OUT_OF_RES;
+ }
+ res = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
+ if (res <= 0)
+ {
+ DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
+ strerror(errno));
+ return FAILED;
+ }
+ msg = radius_message_parse(chunk_create(buf, res));
+ if (!msg)
+ {
+ DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
+ return FAILED;
+ }
+ if (id != msg->get_identifier(msg))
+ {
+ /* we haven't received the response to our current request, but
+ * perhaps one for an earlier request for which we didn't wait
+ * long enough */
+ DBG1(DBG_CFG, "received RADIUS message with unexpected ID %d "
+ "[%d expected], ignored", msg->get_identifier(msg), id);
+ msg->destroy(msg);
+ continue;
+ }
+ *response = msg;
+ return SUCCESS;
+ }
+}
+
METHOD(radius_socket_t, request, radius_message_t*,
private_radius_socket_t *this, radius_message_t *request)
{
+ radius_message_t *response;
chunk_t data;
int i, *fd, retransmit = 0;
u_int16_t port;
@@ -165,14 +221,6 @@ METHOD(radius_socket_t, request, radius_message_t*,
/* timeout after 2, 3, 4, 5 seconds */
for (i = 2; i <= 5; i++)
{
- radius_message_t *response;
- char buf[4096];
- int res;
- struct pollfd pfd = {
- .fd = *fd,
- .events = POLLIN,
- };
-
if (retransmit)
{
DBG1(DBG_CFG, "retransmitting RADIUS %N (attempt %d)",
@@ -184,37 +232,23 @@ METHOD(radius_socket_t, request, radius_message_t*,
DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
return NULL;
}
- res = poll(&pfd, 1, i * 1000);
- if (res < 0)
- {
- DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
- strerror(errno));
- return NULL;
- }
- if (res == 0)
- { /* timeout */
- retransmit++;
- continue;
- }
- res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT);
- if (res <= 0)
+ switch (receive_response(*fd, i*1000, request->get_identifier(request),
+ &response))
{
- DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
- strerror(errno));
- return NULL;
+ case SUCCESS:
+ break;
+ case OUT_OF_RES:
+ retransmit++;
+ continue;
+ default:
+ return NULL;
}
- response = radius_message_parse(chunk_create(buf, res));
- if (response)
+ if (response->verify(response, request->get_authenticator(request),
+ this->secret, this->hasher, this->signer))
{
- if (response->verify(response,
- request->get_authenticator(request), this->secret,
- this->hasher, this->signer))
- {
- return response;
- }
- response->destroy(response);
+ return response;
}
- DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
+ response->destroy(response);
return NULL;
}
DBG1(DBG_CFG, "RADIUS %N timed out after %d retransmits",