diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-03-26 17:35:35 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-03-26 17:35:35 -0400 |
commit | 4c051c41d63e8462971c13956a38030de9c35c51 (patch) | |
tree | 2884c141706cb38cfad4519cf8170060888acd17 /src | |
parent | 7cbd944662854a0a5264895bcba3ce7f9bfd1c1f (diff) | |
download | postgresql-4c051c41d63e8462971c13956a38030de9c35c51.tar.gz postgresql-4c051c41d63e8462971c13956a38030de9c35c51.zip |
Fix unportable disregard of alignment requirements in RADIUS code.
The compiler is entitled to store a char[] local variable with no
particular alignment requirement. Our RADIUS code cavalierly took such
a local variable and cast its address to a struct type that does have
alignment requirements. On an alignment-picky machine this would lead
to bus errors. To fix, declare the local variable honestly, and then
cast its address to char * for use in the I/O calls.
Given the lack of field complaints, there must be very few if any
people affected; but nonetheless this is a clear portability issue,
so back-patch to all supported branches.
Noted while looking at a Coverity complaint in the same code.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/libpq/auth.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 8f77deae6ce..a3c6c6d8b35 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -2570,14 +2570,16 @@ CheckCertAuth(Port *port) */ /* - * RADIUS authentication is described in RFC2865 (and several - * others). + * RADIUS authentication is described in RFC2865 (and several others). */ #define RADIUS_VECTOR_LENGTH 16 #define RADIUS_HEADER_LENGTH 20 #define RADIUS_MAX_PASSWORD_LENGTH 128 +/* Maximum size of a RADIUS packet we will create or accept */ +#define RADIUS_BUFFER_SIZE 1024 + typedef struct { uint8 attribute; @@ -2591,6 +2593,8 @@ typedef struct uint8 id; uint16 length; uint8 vector[RADIUS_VECTOR_LENGTH]; + /* this is a bit longer than strictly necessary: */ + char pad[RADIUS_BUFFER_SIZE - RADIUS_VECTOR_LENGTH]; } radius_packet; /* RADIUS packet types */ @@ -2607,9 +2611,6 @@ typedef struct /* RADIUS service types */ #define RADIUS_AUTHENTICATE_ONLY 8 -/* Maximum size of a RADIUS packet we will create or accept */ -#define RADIUS_BUFFER_SIZE 1024 - /* Seconds to wait - XXX: should be in a config variable! */ #define RADIUS_TIMEOUT 3 @@ -2734,10 +2735,12 @@ CheckRADIUSAuth(Port *port) static int PerformRadiusTransaction(char *server, char *secret, char *portstr, char *identifier, char *user_name, char *passwd) { - char radius_buffer[RADIUS_BUFFER_SIZE]; - char receive_buffer[RADIUS_BUFFER_SIZE]; - radius_packet *packet = (radius_packet *) radius_buffer; - radius_packet *receivepacket = (radius_packet *) receive_buffer; + radius_packet radius_send_pack; + radius_packet radius_recv_pack; + radius_packet *packet = &radius_send_pack; + radius_packet *receivepacket = &radius_recv_pack; + char *radius_buffer = (char *) &radius_send_pack; + char *receive_buffer = (char *) &radius_recv_pack; int32 service = htonl(RADIUS_AUTHENTICATE_ONLY); uint8 *cryptvector; int encryptedpasswordlen; |