mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-24 02:55:40 +08:00
Add support for Reply-Message (may be used to send code with Auth-Reject).
This commit is contained in:
parent
7b4a34f6fc
commit
c5f8a8e139
@ -166,7 +166,7 @@ struct sockaddr_in radiuslist[MAXRADIUS];
|
|||||||
struct sockaddr_in6 radiuslist[MAXRADIUS];
|
struct sockaddr_in6 radiuslist[MAXRADIUS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int ntry;
|
static int ntry = 0;
|
||||||
int nradservers = 0;
|
int nradservers = 0;
|
||||||
char * radiussecret = NULL;
|
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;
|
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)
|
#define AUTH_PASS_LEN (16)
|
||||||
int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vector)
|
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 i, n, secretlen;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
/*
|
|
||||||
* Padd password to multiple of AUTH_PASS_LEN bytes.
|
|
||||||
*/
|
|
||||||
len = strlen(passwd);
|
len = strlen(passwd);
|
||||||
if (len > 128) len = 128;
|
if (len > 128) len = 128;
|
||||||
*pwlen = len;
|
*pwlen = len;
|
||||||
@ -252,26 +238,16 @@ int rad_pwencode(char *passwd, int *pwlen, const char *secret, const char *vecto
|
|||||||
len = *pwlen = i;
|
len = *pwlen = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Use the secret to setup the decryption digest
|
|
||||||
*/
|
|
||||||
secretlen = strlen(secret);
|
secretlen = strlen(secret);
|
||||||
memcpy(buffer, secret, secretlen);
|
memcpy(buffer, secret, secretlen);
|
||||||
memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
|
memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
|
||||||
md5_calc((u_char *)digest, buffer, secretlen + 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++)
|
for (i = 0; i < AUTH_PASS_LEN; i++)
|
||||||
passwd[i] ^= digest[i];
|
passwd[i] ^= digest[i];
|
||||||
|
|
||||||
if (len <= AUTH_PASS_LEN) return 0;
|
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) {
|
for (n = 0; n < 128 && n <= (len - AUTH_PASS_LEN); n += AUTH_PASS_LEN) {
|
||||||
memcpy(buffer + secretlen, passwd + n, AUTH_PASS_LEN);
|
memcpy(buffer + secretlen, passwd + n, AUTH_PASS_LEN);
|
||||||
md5_calc((u_char *)digest, buffer, secretlen + 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)
|
void random_vector(uint8_t *vector, struct clientparam *param)
|
||||||
{
|
{
|
||||||
int i;
|
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++;
|
counter++;
|
||||||
random_vector_pool[AUTH_VECTOR_LEN] += (counter & 0xff);
|
random_vector_pool[AUTH_VECTOR_LEN] += (counter & 0xff);
|
||||||
md5_calc((u_char *) random_vector_pool,
|
md5_calc((u_char *) random_vector_pool,
|
||||||
(u_char *) random_vector_pool,
|
(u_char *) random_vector_pool,
|
||||||
sizeof(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,
|
md5_calc((u_char *) vector,
|
||||||
(u_char *) random_vector_pool,
|
(u_char *) random_vector_pool,
|
||||||
sizeof(random_vector_pool));
|
sizeof(random_vector_pool));
|
||||||
@ -335,14 +297,8 @@ typedef struct radius_packet_t {
|
|||||||
uint8_t data[4096];
|
uint8_t data[4096];
|
||||||
} radius_packet_t;
|
} radius_packet_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char buf[256];
|
|
||||||
int ntry = 0;
|
|
||||||
|
|
||||||
#define RETURN(xxx) { res = xxx; goto CLEANRET; }
|
#define RETURN(xxx) { res = xxx; goto CLEANRET; }
|
||||||
|
|
||||||
|
|
||||||
int radauth(struct clientparam * param){
|
int radauth(struct clientparam * param){
|
||||||
|
|
||||||
int loop;
|
int loop;
|
||||||
@ -549,7 +505,6 @@ int radauth(struct clientparam * param){
|
|||||||
if(len != ntohs(packet.length)){
|
if(len != ntohs(packet.length)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* And wait for reply, timing out as necessary */
|
|
||||||
|
|
||||||
memset(fds, 0, sizeof(fds));
|
memset(fds, 0, sizeof(fds));
|
||||||
fds[0].fd = sockfd;
|
fds[0].fd = sockfd;
|
||||||
@ -578,51 +533,24 @@ int radauth(struct clientparam * param){
|
|||||||
continue;
|
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);
|
total_length = ntohs(rpacket.length);
|
||||||
if (data_len != total_length) {
|
if (data_len != total_length) {
|
||||||
continue;
|
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;
|
attr = rpacket.data;
|
||||||
count = total_length - 20;
|
count = total_length - 20;
|
||||||
vendor_len = 0;
|
vendor_len = 0;
|
||||||
|
|
||||||
while (count >= 2) {
|
while (count >= 2) {
|
||||||
/*
|
|
||||||
* Attribute number zero is NOT defined.
|
|
||||||
*/
|
|
||||||
if (!vendor && attr[0] == 0) {
|
if (!vendor && attr[0] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Attributes are at LEAST as long as the ID & length
|
|
||||||
* fields. Anything shorter is an invalid attribute.
|
|
||||||
*/
|
|
||||||
if (attr[1] < 2) {
|
if (attr[1] < 2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Sanity check the attributes for length.
|
|
||||||
*/
|
|
||||||
if(!vendor && attr[0] == PW_VENDOR_SPECIFIC) {
|
if(!vendor && attr[0] == PW_VENDOR_SPECIFIC) {
|
||||||
if (attr[1] < 6 || count < 6) RETURN(4);
|
if (attr[1] < 6 || count < 6) RETURN(4);
|
||||||
vendorlen = attr[1]-6;
|
vendorlen = attr[1]-6;
|
||||||
@ -632,12 +560,7 @@ int radauth(struct clientparam * param){
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!vendor && attr[0] == PW_REPLY_MESSAGE) {
|
if (!vendor && attr[0] == PW_FRAMED_IP_ADDRESS && attr[1] == 6) {
|
||||||
memcpy(buf, attr+2, attr[1]-2);
|
|
||||||
buf[attr[1]-2]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!vendor && attr[0] == PW_FRAMED_IP_ADDRESS && attr[1] == 6) {
|
|
||||||
*SAFAMILY(¶m->sinsl) = AF_INET;
|
*SAFAMILY(¶m->sinsl) = AF_INET;
|
||||||
memcpy(SAADDR(¶m->sinsl), attr+2, 4);
|
memcpy(SAADDR(¶m->sinsl), attr+2, 4);
|
||||||
}
|
}
|
||||||
@ -646,6 +569,10 @@ int radauth(struct clientparam * param){
|
|||||||
*SAFAMILY(¶m->sinsl) = AF_INET6;
|
*SAFAMILY(¶m->sinsl) = AF_INET6;
|
||||||
memcpy(SAADDR(¶m->sinsl), attr+2, 16);
|
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)) ;
|
mailservice = ntohl(*(int *)(attr+2)) ;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
count -= attr[1]; /* grab the attribute length */
|
count -= attr[1];
|
||||||
if(vendorlen) {
|
if(vendorlen) {
|
||||||
vendorlen -= attr[1];
|
vendorlen -= attr[1];
|
||||||
if (!vendorlen) vendor = 0;
|
if (!vendorlen) vendor = 0;
|
||||||
@ -671,16 +598,10 @@ int radauth(struct clientparam * param){
|
|||||||
if (count !=0 || vendorlen!=0) {
|
if (count !=0 || vendorlen!=0) {
|
||||||
continue;
|
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){
|
if(rpacket.code == PW_AUTHENTICATION_REJECT) RETURN (res);
|
||||||
continue;
|
if(rpacket.code == PW_AUTHENTICATION_ACK) RETURN(0);
|
||||||
}
|
res = 4;
|
||||||
RETURN(0);
|
|
||||||
}
|
}
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
if(sockfd >= 0) so._closesocket(sockfd);
|
if(sockfd >= 0) so._closesocket(sockfd);
|
||||||
|
Loading…
Reference in New Issue
Block a user