Hi,
The attached patch adds support for RADIUS passwords longer than 16 octets.
.m
*** a/src/backend/libpq/auth.c
--- b/src/backend/libpq/auth.c
***************
*** 2168,2173 **** CheckCertAuth(Port *port)
--- 2168,2174 ----
#define RADIUS_VECTOR_LENGTH 16
#define RADIUS_HEADER_LENGTH 20
+ #define RADIUS_MAX_PASSWORD_LENGTH 128
typedef struct
{
***************
*** 2241,2247 **** CheckRADIUSAuth(Port *port)
radius_packet *receivepacket = (radius_packet *) receive_buffer;
int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
uint8 *cryptvector;
! uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
int packetlength;
pgsocket sock;
--- 2242,2250 ----
radius_packet *receivepacket = (radius_packet *) receive_buffer;
int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
uint8 *cryptvector;
! int encryptedpasswordlen;
! uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
! uint8 *previousxor;
int packetlength;
pgsocket sock;
***************
*** 2259,2264 **** CheckRADIUSAuth(Port *port)
--- 2262,2268 ----
fd_set fdset;
struct timeval endtime;
int i,
+ j,
r;
/* Make sure struct alignment is correct */
***************
*** 2316,2325 **** CheckRADIUSAuth(Port *port)
return STATUS_ERROR;
}
! if (strlen(passwd) > RADIUS_VECTOR_LENGTH)
{
ereport(LOG,
! (errmsg("RADIUS authentication does not support
passwords longer than 16 characters")));
return STATUS_ERROR;
}
--- 2320,2329 ----
return STATUS_ERROR;
}
! if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
{
ereport(LOG,
! (errmsg("RADIUS authentication does not support
passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
return STATUS_ERROR;
}
***************
*** 2344,2371 **** CheckRADIUSAuth(Port *port)
radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *)
identifier, strlen(identifier));
/*
! * RADIUS password attributes are calculated as: e[0] = p[0] XOR
! * MD5(secret + vector)
*/
! cryptvector = palloc(RADIUS_VECTOR_LENGTH +
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))
! {
! ereport(LOG,
! (errmsg("could not perform MD5 encryption of
password")));
! pfree(cryptvector);
! return STATUS_ERROR;
! }
! pfree(cryptvector);
! for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
{
! 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 */
packetlength = packet->length;
--- 2348,2396 ----
radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *)
identifier, strlen(identifier));
/*
! * RADIUS password attributes are calculated as:
! * e[0] = p[0] XOR MD5(secret + vector)
! * for the first vector, and then:
! * e[i] = p[i] XOR MD5(secret + p[i-1])
! * for the following ones (if necessary)
*/
! 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));
!
! for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
{
! if (i == 0)
! {
! /* for the first iteration, we use the Request
Authenticator vector */
! memcpy(cryptvector + strlen(port->hba->radiussecret),
packet->vector, RADIUS_VECTOR_LENGTH);
! }
else
! {
! /* .. and for the following iterations the result of
the previous XOR */
! memcpy(cryptvector + strlen(port->hba->radiussecret),
previousxor, RADIUS_VECTOR_LENGTH);
! }
!
! 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];
! }
! previousxor = encryptedpassword + i;
}
! pfree(cryptvector);
!
! radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword,
encryptedpasswordlen);
/* Length need to be in network order on the wire */
packetlength = packet->length;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers