On 2015-08-15 17:55, I wrote:
The attached patch adds support for RADIUS passwords longer than 16 octets.
Improved the coding and comments a bit, new version attached.
.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;
pgsocketsock;
--- 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 *md5trailer;
int packetlength;
pgsocketsock;
***
*** 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,2390
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 + 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)
*/
! 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 the first iteration, we use the Request Authenticator vector */
! md5trailer = packet-vector;
! for (i = 0; i encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
{
! memcpy(cryptvector + strlen(port-hba-radiussecret),
md5trailer, RADIUS_VECTOR_LENGTH);
! /* .. and for subsequent iterations the result of the previous
XOR (calculated below) */
! md5trailer = encryptedpassword + i;
!
! if (!pg_md5_binary(cryptvector, strlen(port-hba-radiussecret)
+