|
|
@@ -166,7 +166,7 @@ struct sockaddr_in radiuslist[MAXRADIUS];
|
|
|
struct sockaddr_in6 radiuslist[MAXRADIUS];
|
|
|
#endif
|
|
|
|
|
|
-static int ntry;
|
|
|
+static int ntry = 0;
|
|
|
int nradservers = 0;
|
|
|
char * radiussecret = NULL;
|
|
|
|
|
|
@@ -220,17 +220,6 @@ static int calc_replydigest(char *packet, char *original, const char *secret, in
|
|
|
return memcmp(calc_vector, calc_digest, AUTH_VECTOR_LEN) ? 2 : 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Encode password.
|
|
|
- *
|
|
|
- * We assume that the passwd buffer passed is big enough.
|
|
|
- * RFC2138 says the password is max 128 chars, so the size
|
|
|
- * of the passwd buffer must be at least 129 characters.
|
|
|
- * Preferably it's just MAX_STRING_LEN.
|
|
|
- *
|
|
|
- * int *pwlen is updated to the new length of the encrypted
|
|
|
- * password - a multiple of 16 bytes.
|
|
|
- */
|
|
|
#define AUTH_PASS_LEN (16)
|
|
|
int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vector)
|
|
|
{
|
|
|
@@ -239,9 +228,6 @@ int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vecto
|
|
|
int i, n, secretlen;
|
|
|
int len;
|
|
|
|
|
|
- /*
|
|
|
- * Padd password to multiple of AUTH_PASS_LEN bytes.
|
|
|
- */
|
|
|
len = strlen(passwd);
|
|
|
if (len > 128) len = 128;
|
|
|
*pwlen = len;
|
|
|
@@ -252,26 +238,16 @@ int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vecto
|
|
|
len = *pwlen = i;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Use the secret to setup the decryption digest
|
|
|
- */
|
|
|
secretlen = strlen(secret);
|
|
|
memcpy(buffer, secret, secretlen);
|
|
|
memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
|
|
|
md5_calc((u_char *)digest, buffer, secretlen + AUTH_VECTOR_LEN);
|
|
|
|
|
|
- /*
|
|
|
- * Now we can encode the password *in place*
|
|
|
- */
|
|
|
for (i = 0; i < AUTH_PASS_LEN; i++)
|
|
|
passwd[i] ^= digest[i];
|
|
|
|
|
|
if (len <= AUTH_PASS_LEN) return 0;
|
|
|
|
|
|
- /*
|
|
|
- * Length > AUTH_PASS_LEN, so we need to use the extended
|
|
|
- * algorithm.
|
|
|
- */
|
|
|
for (n = 0; n < 128 && n <= (len - AUTH_PASS_LEN); n += AUTH_PASS_LEN) {
|
|
|
memcpy(buffer + secretlen, passwd + n, AUTH_PASS_LEN);
|
|
|
md5_calc((u_char *)digest, buffer, secretlen + AUTH_PASS_LEN);
|
|
|
@@ -283,9 +259,6 @@ int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vecto
|
|
|
}
|
|
|
|
|
|
|
|
|
-/*
|
|
|
- * Create a random vector of AUTH_VECTOR_LEN bytes.
|
|
|
- */
|
|
|
void random_vector(uint8_t *vector, struct clientparam *param)
|
|
|
{
|
|
|
int i;
|
|
|
@@ -302,23 +275,12 @@ void random_vector(uint8_t *vector, struct clientparam *param)
|
|
|
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Modify our random pool, based on the counter,
|
|
|
- * and put the resulting information through MD5,
|
|
|
- * so it's all mashed together.
|
|
|
- */
|
|
|
counter++;
|
|
|
random_vector_pool[AUTH_VECTOR_LEN] += (counter & 0xff);
|
|
|
md5_calc((u_char *) random_vector_pool,
|
|
|
(u_char *) random_vector_pool,
|
|
|
sizeof(random_vector_pool));
|
|
|
|
|
|
- /*
|
|
|
- * And do another MD5 hash of the result, to give
|
|
|
- * the user a random vector. This ensures that the
|
|
|
- * user has a random vector, without giving them
|
|
|
- * an exact image of what's in the random pool.
|
|
|
- */
|
|
|
md5_calc((u_char *) vector,
|
|
|
(u_char *) random_vector_pool,
|
|
|
sizeof(random_vector_pool));
|
|
|
@@ -335,14 +297,8 @@ typedef struct radius_packet_t {
|
|
|
uint8_t data[4096];
|
|
|
} radius_packet_t;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-char buf[256];
|
|
|
-int ntry = 0;
|
|
|
-
|
|
|
#define RETURN(xxx) { res = xxx; goto CLEANRET; }
|
|
|
|
|
|
-
|
|
|
int radauth(struct clientparam * param){
|
|
|
|
|
|
int loop;
|
|
|
@@ -549,7 +505,6 @@ int radauth(struct clientparam * param){
|
|
|
if(len != ntohs(packet.length)){
|
|
|
continue;
|
|
|
}
|
|
|
- /* And wait for reply, timing out as necessary */
|
|
|
|
|
|
memset(fds, 0, sizeof(fds));
|
|
|
fds[0].fd = sockfd;
|
|
|
@@ -578,51 +533,24 @@ int radauth(struct clientparam * param){
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Check for packets with mismatched size.
|
|
|
- * i.e. We've received 128 bytes, and the packet header
|
|
|
- * says it's 256 bytes long.
|
|
|
- */
|
|
|
total_length = ntohs(rpacket.length);
|
|
|
if (data_len != total_length) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Walk through the packet's attributes, ensuring that
|
|
|
- * they add up EXACTLY to the size of the packet.
|
|
|
- *
|
|
|
- * If they don't, then the attributes either under-fill
|
|
|
- * or over-fill the packet. Any parsing of the packet
|
|
|
- * is impossible, and will result in unknown side effects.
|
|
|
- *
|
|
|
- * This would ONLY happen with buggy RADIUS implementations,
|
|
|
- * or with an intentional attack. Either way, we do NOT want
|
|
|
- * to be vulnerable to this problem.
|
|
|
- */
|
|
|
attr = rpacket.data;
|
|
|
count = total_length - 20;
|
|
|
vendor_len = 0;
|
|
|
|
|
|
while (count >= 2) {
|
|
|
- /*
|
|
|
- * Attribute number zero is NOT defined.
|
|
|
- */
|
|
|
if (!vendor && attr[0] == 0) {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Attributes are at LEAST as long as the ID & length
|
|
|
- * fields. Anything shorter is an invalid attribute.
|
|
|
- */
|
|
|
if (attr[1] < 2) {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Sanity check the attributes for length.
|
|
|
- */
|
|
|
if(!vendor && attr[0] == PW_VENDOR_SPECIFIC) {
|
|
|
if (attr[1] < 6 || count < 6) RETURN(4);
|
|
|
vendorlen = attr[1]-6;
|
|
|
@@ -632,12 +560,7 @@ int radauth(struct clientparam * param){
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- else if (!vendor && attr[0] == PW_REPLY_MESSAGE) {
|
|
|
- memcpy(buf, attr+2, attr[1]-2);
|
|
|
- buf[attr[1]-2]=0;
|
|
|
- }
|
|
|
-
|
|
|
- else if (!vendor && attr[0] == PW_FRAMED_IP_ADDRESS && attr[1] == 6) {
|
|
|
+ if (!vendor && attr[0] == PW_FRAMED_IP_ADDRESS && attr[1] == 6) {
|
|
|
*SAFAMILY(¶m->sinsl) = AF_INET;
|
|
|
memcpy(SAADDR(¶m->sinsl), attr+2, 4);
|
|
|
}
|
|
|
@@ -646,6 +569,10 @@ int radauth(struct clientparam * param){
|
|
|
*SAFAMILY(¶m->sinsl) = AF_INET6;
|
|
|
memcpy(SAADDR(¶m->sinsl), attr+2, 16);
|
|
|
}
|
|
|
+ else if (!vendor && attr[0] == PW_REPLY_MESSAGE && attr[1] >= 3 && isdigit(attr[2])) {
|
|
|
+ res = 0;
|
|
|
+ for(len = 2; len < attr[1] && isdigit(attr[len]); len++) res = (res * 10) + (attr[len] - '0');
|
|
|
+ }
|
|
|
|
|
|
|
|
|
/*
|
|
|
@@ -659,7 +586,7 @@ int radauth(struct clientparam * param){
|
|
|
mailservice = ntohl(*(int *)(attr+2)) ;
|
|
|
}
|
|
|
*/
|
|
|
- count -= attr[1]; /* grab the attribute length */
|
|
|
+ count -= attr[1];
|
|
|
if(vendorlen) {
|
|
|
vendorlen -= attr[1];
|
|
|
if (!vendorlen) vendor = 0;
|
|
|
@@ -671,16 +598,10 @@ int radauth(struct clientparam * param){
|
|
|
if (count !=0 || vendorlen!=0) {
|
|
|
continue;
|
|
|
}
|
|
|
- /*
|
|
|
- * If the attributes add up to a packet, it's allowed.
|
|
|
- *
|
|
|
- * If not, we complain, and throw the packet away.
|
|
|
- */
|
|
|
|
|
|
- if(rpacket.code != PW_AUTHENTICATION_ACK){
|
|
|
- continue;
|
|
|
- }
|
|
|
- RETURN(0);
|
|
|
+ if(rpacket.code == PW_AUTHENTICATION_REJECT) RETURN (res);
|
|
|
+ if(rpacket.code == PW_AUTHENTICATION_ACK) RETURN(0);
|
|
|
+ res = 4;
|
|
|
}
|
|
|
CLEANRET:
|
|
|
if(sockfd >= 0) so._closesocket(sockfd);
|