Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 643beff

Browse files
committed
Support RADIUS passwords up to 128 characters
Previous limit was 16 characters, due to lack of support for multiple passes of encryption. Marko Tiikkaja
1 parent c314ead commit 643beff

File tree

1 file changed

+40
-20
lines changed

1 file changed

+40
-20
lines changed

src/backend/libpq/auth.c

+40-20
Original file line numberDiff line numberDiff line change
@@ -2168,6 +2168,7 @@ CheckCertAuth(Port *port)
21682168

21692169
#define RADIUS_VECTOR_LENGTH 16
21702170
#define RADIUS_HEADER_LENGTH 20
2171+
#define RADIUS_MAX_PASSWORD_LENGTH 128
21712172

21722173
typedef struct
21732174
{
@@ -2241,7 +2242,9 @@ CheckRADIUSAuth(Port *port)
22412242
radius_packet *receivepacket = (radius_packet *) receive_buffer;
22422243
int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
22432244
uint8 *cryptvector;
2244-
uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
2245+
int encryptedpasswordlen;
2246+
uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
2247+
uint8 *md5trailer;
22452248
int packetlength;
22462249
pgsocket sock;
22472250

@@ -2259,6 +2262,7 @@ CheckRADIUSAuth(Port *port)
22592262
fd_set fdset;
22602263
struct timeval endtime;
22612264
int i,
2265+
j,
22622266
r;
22632267

22642268
/* Make sure struct alignment is correct */
@@ -2316,13 +2320,14 @@ CheckRADIUSAuth(Port *port)
23162320
return STATUS_ERROR;
23172321
}
23182322

2319-
if (strlen(passwd) > RADIUS_VECTOR_LENGTH)
2323+
if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
23202324
{
23212325
ereport(LOG,
2322-
(errmsg("RADIUS authentication does not support passwords longer than 16 characters")));
2326+
(errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
23232327
return STATUS_ERROR;
23242328
}
23252329

2330+
23262331
/* Construct RADIUS packet */
23272332
packet->code = RADIUS_ACCESS_REQUEST;
23282333
packet->length = RADIUS_HEADER_LENGTH;
@@ -2344,28 +2349,43 @@ CheckRADIUSAuth(Port *port)
23442349
radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
23452350

23462351
/*
2347-
* RADIUS password attributes are calculated as: e[0] = p[0] XOR
2348-
* MD5(secret + vector)
2352+
* RADIUS password attributes are calculated as:
2353+
* e[0] = p[0] XOR MD5(secret + Request Authenticator)
2354+
* for the first group of 16 octets, and then:
2355+
* e[i] = p[i] XOR MD5(secret + e[i-1])
2356+
* for the following ones (if necessary)
23492357
*/
2350-
cryptvector = palloc(RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret));
2358+
encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
2359+
cryptvector = palloc(strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH);
23512360
memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
2352-
memcpy(cryptvector + strlen(port->hba->radiussecret), packet->vector, RADIUS_VECTOR_LENGTH);
2353-
if (!pg_md5_binary(cryptvector, RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret), encryptedpassword))
2361+
2362+
/* for the first iteration, we use the Request Authenticator vector */
2363+
md5trailer = packet->vector;
2364+
for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
23542365
{
2355-
ereport(LOG,
2356-
(errmsg("could not perform MD5 encryption of password")));
2357-
pfree(cryptvector);
2358-
return STATUS_ERROR;
2366+
memcpy(cryptvector + strlen(port->hba->radiussecret), md5trailer, RADIUS_VECTOR_LENGTH);
2367+
/* .. and for subsequent iterations the result of the previous XOR (calculated below) */
2368+
md5trailer = encryptedpassword + i;
2369+
2370+
if (!pg_md5_binary(cryptvector, strlen(port->hba->radiussecret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
2371+
{
2372+
ereport(LOG,
2373+
(errmsg("could not perform MD5 encryption of password")));
2374+
pfree(cryptvector);
2375+
return STATUS_ERROR;
2376+
}
2377+
2378+
for (j = i; j < i+RADIUS_VECTOR_LENGTH; j++)
2379+
{
2380+
if (j < strlen(passwd))
2381+
encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
2382+
else
2383+
encryptedpassword[j] = '\0' ^ encryptedpassword[j];
2384+
}
23592385
}
23602386
pfree(cryptvector);
2361-
for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
2362-
{
2363-
if (i < strlen(passwd))
2364-
encryptedpassword[i] = passwd[i] ^ encryptedpassword[i];
2365-
else
2366-
encryptedpassword[i] = '\0' ^ encryptedpassword[i];
2367-
}
2368-
radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, RADIUS_VECTOR_LENGTH);
2387+
2388+
radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
23692389

23702390
/* Length need to be in network order on the wire */
23712391
packetlength = packet->length;

0 commit comments

Comments
 (0)