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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to