MD5_PACKET *packet;
unsigned short name_len;
- if (!eap_ds ||
- !eap_ds->response ||
- (eap_ds->response->code != PW_MD5_RESPONSE) ||
- eap_ds->response->type.type != PW_EAP_MD5 ||
- !eap_ds->response->type.data ||
- (eap_ds->response->length < MD5_HEADER_LEN) ||
- (eap_ds->response->type.data[0] <= 0) ) {
-
+ if (!eap_ds ||
+ !eap_ds->response ||
+ (eap_ds->response->code != PW_MD5_RESPONSE) ||
+ eap_ds->response->type.type != PW_EAP_MD5 ||
+ !eap_ds->response->type.data ||
+ (eap_ds->response->length < MD5_HEADER_LEN) ||
+ (eap_ds->response->type.data[0] <= 0) ) {
+
radlog(L_ERR, "rlm_eap_md5: corrupted data");
return NULL;
}
data = (md5_packet_t *)eap_ds->response->type.data;
packet->value_size = data->value_size;
+ if (packet->value_size < 1) {
+ radlog(L_ERR, "rlm_eap_md5: Value size is too small");
+ eapmd5_free(&packet);
+ return NULL;
+ }
packet->value = malloc(packet->value_size);
if (packet->value == NULL) {
*/
int eapmd5_challenge(unsigned char *value, int len)
{
+ int i;
+
/*
- * TODO: Make sure Challenge is always unique,
- * no matter how many times it is called.
- * random_vector() in lib/radius.c should be used.
+ * Get real pseudo-random numbers.
*/
- librad_md5_calc((u_char *)value, (u_char *)value, len);
+ for (i = 0; i < len; i++) {
+ value[i] = lrad_rand();
+ }
radlog(L_INFO, "rlm_eap_md5: Issuing Challenge");
return 1;
return 0;
}
+ /*
+ * Sanity check it.
+ */
+ if (packet->value_size != 16) {
+ radlog(L_ERR, "rlm_eap_md5: Expected 16 bytes of response to challenge, got %d", packet->value_size);
+ return 0;
+ }
+
len = 0;
ptr = string;
librad_md5_calc((u_char *)output, (u_char *)string, len);
- if (memcmp(output, packet->value, packet->value_size) != 0) {
+ /*
+ * The length of the response is always 16 for MD5.
+ */
+ if (memcmp(output, packet->value, 16) != 0) {
return 0;
}
return 1;
else {
reply->code = PW_MD5_SUCCESS;
}
+
} else {
/*
* Previous request not found.
* TODO: Later Send these challenges for the configurable
* number of times for each user & stop.
*/
- eapmd5_challenge(reply->value, MD5_LEN);
+
+ /*
+ * Ensure that the challenge is always of the correct
+ * length. i.e. Don't take value size from data
+ * supplied by the client.
+ */
+ if (reply->value_size != MD5_LEN) {
+ free(reply->value);
+ reply->value_size = MD5_LEN;
+ reply->value = malloc(reply->value_size);
+ }
+
+ eapmd5_challenge(reply->value, reply->value_size);
reply->code = PW_MD5_CHALLENGE;
radlog(L_INFO, "rlm_eap_md5: Previous request not found");
radlog(L_INFO, "rlm_eap_md5: Issuing Challenge to the user - %s",
return NULL;
}
- eapmd5_challenge(reply->value, MD5_LEN);
+ eapmd5_challenge(reply->value, reply->value_size);
return reply;
}
VALUE_PAIR *password;
EAP_DS *temp;
- if (!(packet = eapmd5_extract(handler->eap_ds)))
- return 0;
-
- username = (char *)handler->username->strvalue;
-
/*
* Password is never sent over the wire.
* Always get the configured password, for each user.
password = pairfind(handler->configured, PW_PASSWORD);
if (password == NULL) {
radlog(L_INFO, "rlm_eap_md5: No password configured for this user");
- eapmd5_free(&packet);
return 0;
}
+ /*
+ * Allocate memory AFTER doing sanity checks.
+ */
+ if (!(packet = eapmd5_extract(handler->eap_ds)))
+ return 0;
+
+ username = (char *)handler->username->strvalue;
+
temp = (EAP_DS *)handler->prev_eapds;
request = temp?(md5_packet_t *)(temp->request->type.data):NULL;
reply = eapmd5_process(packet, handler->eap_ds->request->id,