@@ -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
21722173typedef struct
21732174{
@@ -2241,7 +2242,9 @@ CheckRADIUSAuth(Port *port)
22412242radius_packet * receivepacket = (radius_packet * )receive_buffer ;
22422243int32 service = htonl (RADIUS_AUTHENTICATE_ONLY );
22432244uint8 * cryptvector ;
2244- uint8 encryptedpassword [RADIUS_VECTOR_LENGTH ];
2245+ int encryptedpasswordlen ;
2246+ uint8 encryptedpassword [RADIUS_MAX_PASSWORD_LENGTH ];
2247+ uint8 * md5trailer ;
22452248int packetlength ;
22462249pgsocket sock ;
22472250
@@ -2259,6 +2262,7 @@ CheckRADIUSAuth(Port *port)
22592262fd_set fdset ;
22602263struct timeval endtime ;
22612264int i ,
2265+ j ,
22622266r ;
22632267
22642268/* Make sure struct alignment is correct */
@@ -2316,13 +2320,14 @@ CheckRADIUSAuth(Port *port)
23162320return STATUS_ERROR ;
23172321}
23182322
2319- if (strlen (passwd )> RADIUS_VECTOR_LENGTH )
2323+ if (strlen (passwd )> RADIUS_MAX_PASSWORD_LENGTH )
23202324{
23212325ereport (LOG ,
2322- (errmsg ("RADIUS authentication does not support passwords longer than16 characters" )));
2326+ (errmsg ("RADIUS authentication does not support passwords longer than%d characters" , RADIUS_MAX_PASSWORD_LENGTH )));
23232327return STATUS_ERROR ;
23242328}
23252329
2330+
23262331/* Construct RADIUS packet */
23272332packet -> code = RADIUS_ACCESS_REQUEST ;
23282333packet -> length = RADIUS_HEADER_LENGTH ;
@@ -2344,28 +2349,43 @@ CheckRADIUSAuth(Port *port)
23442349radius_add_attribute (packet ,RADIUS_NAS_IDENTIFIER , (unsignedchar * )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 );
23512360memcpy (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}
23602386pfree (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 */
23712391packetlength = packet -> length ;