Support RADIUS passwords up to 128 characters
Previous limit was 16 characters, due to lack of support for multiple passes of encryption. Marko Tiikkaja
This commit is contained in:
parent
c314ead5be
commit
643beffe8f
@ -2168,6 +2168,7 @@ CheckCertAuth(Port *port)
|
|||||||
|
|
||||||
#define RADIUS_VECTOR_LENGTH 16
|
#define RADIUS_VECTOR_LENGTH 16
|
||||||
#define RADIUS_HEADER_LENGTH 20
|
#define RADIUS_HEADER_LENGTH 20
|
||||||
|
#define RADIUS_MAX_PASSWORD_LENGTH 128
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -2241,7 +2242,9 @@ CheckRADIUSAuth(Port *port)
|
|||||||
radius_packet *receivepacket = (radius_packet *) receive_buffer;
|
radius_packet *receivepacket = (radius_packet *) receive_buffer;
|
||||||
int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
|
int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
|
||||||
uint8 *cryptvector;
|
uint8 *cryptvector;
|
||||||
uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
|
int encryptedpasswordlen;
|
||||||
|
uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
|
||||||
|
uint8 *md5trailer;
|
||||||
int packetlength;
|
int packetlength;
|
||||||
pgsocket sock;
|
pgsocket sock;
|
||||||
|
|
||||||
@ -2259,6 +2262,7 @@ CheckRADIUSAuth(Port *port)
|
|||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
struct timeval endtime;
|
struct timeval endtime;
|
||||||
int i,
|
int i,
|
||||||
|
j,
|
||||||
r;
|
r;
|
||||||
|
|
||||||
/* Make sure struct alignment is correct */
|
/* Make sure struct alignment is correct */
|
||||||
@ -2316,13 +2320,14 @@ CheckRADIUSAuth(Port *port)
|
|||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(passwd) > RADIUS_VECTOR_LENGTH)
|
if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errmsg("RADIUS authentication does not support passwords longer than 16 characters")));
|
(errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Construct RADIUS packet */
|
/* Construct RADIUS packet */
|
||||||
packet->code = RADIUS_ACCESS_REQUEST;
|
packet->code = RADIUS_ACCESS_REQUEST;
|
||||||
packet->length = RADIUS_HEADER_LENGTH;
|
packet->length = RADIUS_HEADER_LENGTH;
|
||||||
@ -2344,28 +2349,43 @@ CheckRADIUSAuth(Port *port)
|
|||||||
radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
|
radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RADIUS password attributes are calculated as: e[0] = p[0] XOR
|
* RADIUS password attributes are calculated as:
|
||||||
* MD5(secret + vector)
|
* e[0] = p[0] XOR MD5(secret + Request Authenticator)
|
||||||
|
* for the first group of 16 octets, and then:
|
||||||
|
* e[i] = p[i] XOR MD5(secret + e[i-1])
|
||||||
|
* for the following ones (if necessary)
|
||||||
*/
|
*/
|
||||||
cryptvector = palloc(RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret));
|
encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
|
||||||
|
cryptvector = palloc(strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH);
|
||||||
memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
|
memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
|
||||||
memcpy(cryptvector + strlen(port->hba->radiussecret), packet->vector, RADIUS_VECTOR_LENGTH);
|
|
||||||
if (!pg_md5_binary(cryptvector, RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret), encryptedpassword))
|
/* for the first iteration, we use the Request Authenticator vector */
|
||||||
|
md5trailer = packet->vector;
|
||||||
|
for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
memcpy(cryptvector + strlen(port->hba->radiussecret), md5trailer, RADIUS_VECTOR_LENGTH);
|
||||||
(errmsg("could not perform MD5 encryption of password")));
|
/* .. and for subsequent iterations the result of the previous XOR (calculated below) */
|
||||||
pfree(cryptvector);
|
md5trailer = encryptedpassword + i;
|
||||||
return STATUS_ERROR;
|
|
||||||
|
if (!pg_md5_binary(cryptvector, strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
|
||||||
|
{
|
||||||
|
ereport(LOG,
|
||||||
|
(errmsg("could not perform MD5 encryption of password")));
|
||||||
|
pfree(cryptvector);
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = i; j < i+RADIUS_VECTOR_LENGTH; j++)
|
||||||
|
{
|
||||||
|
if (j < strlen(passwd))
|
||||||
|
encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
|
||||||
|
else
|
||||||
|
encryptedpassword[j] = '\0' ^ encryptedpassword[j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pfree(cryptvector);
|
pfree(cryptvector);
|
||||||
for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
|
|
||||||
{
|
radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
|
||||||
if (i < strlen(passwd))
|
|
||||||
encryptedpassword[i] = passwd[i] ^ encryptedpassword[i];
|
|
||||||
else
|
|
||||||
encryptedpassword[i] = '\0' ^ encryptedpassword[i];
|
|
||||||
}
|
|
||||||
radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, RADIUS_VECTOR_LENGTH);
|
|
||||||
|
|
||||||
/* Length need to be in network order on the wire */
|
/* Length need to be in network order on the wire */
|
||||||
packetlength = packet->length;
|
packetlength = packet->length;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user