diff --git a/src/authradius.c b/src/authradius.c index e3c30b0..293006c 100644 --- a/src/authradius.c +++ b/src/authradius.c @@ -194,12 +194,20 @@ static int calc_replydigest(char *packet, char *original, const char *secret, in int secretlen; uint8_t calc_digest[AUTH_VECTOR_LEN]; uint8_t calc_vector[AUTH_VECTOR_LEN]; + unsigned int dlen = AUTH_VECTOR_LEN; + mdh_ctx *ctx; memcpy(calc_vector, packet + 4, AUTH_VECTOR_LEN); memcpy(packet + 4, original, AUTH_VECTOR_LEN); secretlen = strlen(secret); - memcpy(packet + len, secret, secretlen); - md5_calc(calc_digest, (u_char *)packet, len + secretlen); + /* hash the reply, then the secret: nothing is written past the reply */ + if(!(ctx = mdh_init(MDH_MD5, 16))) return 2; + if(!mdh_update(ctx, packet, len) || !mdh_update(ctx, secret, secretlen) || + !mdh_final(ctx, calc_digest, &dlen)) { + mdh_free(ctx); + return 2; + } + mdh_free(ctx); /* * Return 0 if OK, 2 if not OK. @@ -294,6 +302,7 @@ int radsend(struct clientparam * param, int auth, int stop){ int total_length; int len; PROXYSOCKADDRTYPE saremote; + PROXYSOCKADDRTYPE safrom; char vector[AUTH_VECTOR_LEN]; radius_packet_t packet, rpacket; int data_len; @@ -550,13 +559,23 @@ int radsend(struct clientparam * param, int auth, int stop){ continue; } - data_len = sockrecvfrom(NULL, remsock, (struct sockaddr *)&saremote, (unsigned char *)&rpacket, + data_len = sockrecvfrom(NULL, remsock, (struct sockaddr *)&safrom, (unsigned char *)&rpacket, sizeof(packet)-16, param->srv->config->timeouts[SINGLEBYTE_L]*1000); if (data_len < 20) { continue; } + /* the reply must come from the server we asked */ + if(*SAFAMILY(&safrom) != *SAFAMILY(&saremote) || + memcmp(SAADDR(&safrom), SAADDR(&saremote), SAADDRLEN(&saremote)) || + *SAPORT(&safrom) != *SAPORT(&saremote)) { + continue; + } + /* and answer this request, and be of its own length */ + if(data_len != ntohs(rpacket.length) || rpacket.id != packet.id) { + continue; + } if( auth && rpacket.code != PW_AUTHENTICATION_ACK && rpacket.code != PW_AUTHENTICATION_REJECT ){