From 849d9cb45286cb9f03111c6b503d7361068be21c Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 5 Aug 2024 17:09:57 +1200 Subject: [PATCH v1 5/5] XXX BlastRADIUS back-patch kludge for 12 and 13 --- doc/src/sgml/client-auth.sgml | 11 +++++++++ src/backend/libpq/auth.c | 42 ++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 6c49ba18346..70a55db3ec1 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -2175,6 +2175,17 @@ host ... ldap ldapbasedn="dc=example,dc=net" always include a Message-Authenticator attribute (but didn't in earlier releases). + + + Message-Authenticator attributes can only be + computed if PostgreSQL was built support for + OpenSSL. Otherwise, they + will be silently omitted from outgoing messages, and ignored on + incoming messages regardless of this setting, which may cause some + RADIUS servers to reject or ignore + requests. + + diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 40f0cabf3a9..8a5876723e0 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -24,7 +24,6 @@ #include #include "commands/user.h" -#include "common/hmac.h" #include "common/ip.h" #include "common/md5.h" #include "libpq/auth.h" @@ -40,6 +39,10 @@ #include "storage/ipc.h" #include "utils/memutils.h" +#ifdef USE_OPENSSL +#include "openssl/hmac.h" +#endif + /*---------------------------------------------------------------- * Global authentication functions *---------------------------------------------------------------- @@ -2811,6 +2814,31 @@ typedef struct /* Seconds to wait - XXX: should be in a config variable! */ #define RADIUS_TIMEOUT 3 +#ifdef USE_OPENSSL +/* + * Locally redirect PostgreSQL 14's pg_hmac_XXX API directly to OpenSSL + * functions, to simplify back-patching of BlastRADIUS mitigation to + * PostgreSQL 12 and 13. If built without OpenSSL, skip HMAC support and + * disable Message-Authenticator attributes. + */ +#define RADIUS_USE_HMAC +#define pg_hmac_ctx HMAC_CTX +#define pg_hmac_create(...) HMAC_CTX_new() +#define pg_hmac_init(ctx, key, key_len, ...) HMAC_Init_ex(ctx, key, key_len, EVP_md5(), NULL) +#define pg_hmac_update HMAC_Update +static inline int +pg_hmac_final(pg_hmac_ctx *ctx, void *md, size_t len) +{ + unsigned int l = len; + int result = HMAC_Final(ctx, md, &l); + + Assert(l == len); + return result; +} +#define pg_hmac_free(x) if (x) HMAC_CTX_free(x) +#define pg_hmac_error(x) "HMAC error" +#endif + static uint8 * radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len) { @@ -2843,6 +2871,7 @@ radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *dat return attr->data; } +#ifdef RADIUS_USE_HMAC /* * Search for an attribute in a received message. If the attribute is found, * sets *value and *length (not including the header), and returns true. If @@ -2889,6 +2918,7 @@ radius_find_attribute(uint8 *packet, *length = 0; return true; } +#endif static int CheckRADIUSAuth(Port *port) @@ -2989,11 +3019,13 @@ CheckRADIUSAuth(Port *port) static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd, bool requirema) { +#ifdef RADIUS_USE_HMAC pg_hmac_ctx *hmac_context; uint8 message_authenticator_key[RADIUS_VECTOR_LENGTH]; uint8 message_authenticator[RADIUS_VECTOR_LENGTH]; uint8 *message_authenticator_location; uint8 message_authenticator_size; +#endif radius_packet radius_send_pack; radius_packet radius_recv_pack; radius_packet *packet = &radius_send_pack; @@ -3055,6 +3087,8 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por } packet->id = packet->vector[0]; +#ifdef RADIUS_USE_HMAC + /* * Add Message-Authenticator attribute first, which for now holds zeroes. * We remember where it is in the message so that we can fill it in later. @@ -3065,6 +3099,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por RADIUS_MESSAGE_AUTHENTICATOR, message_authenticator, lengthof(message_authenticator)); +#endif radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service)); radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name)); @@ -3121,6 +3156,8 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por packetlength = packet->length; packet->length = pg_hton16(packet->length); +#ifdef RADIUS_USE_HMAC + /* * We use the first 16 bytes of the shared secret, zero-padded if too * short, as an HMAC-MD5 key for creating and validating @@ -3158,6 +3195,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por /* Overwrite the attribute with the computed signature. */ memcpy(message_authenticator_location, message_authenticator, lengthof(message_authenticator)); +#endif sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0); if (sock == PGINVALID_SOCKET) @@ -3343,6 +3381,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por continue; } +#ifdef RADIUS_USE_HMAC /* Search for the Message-Authenticator attribute. */ if (!radius_find_attribute((uint8 *) receive_buffer, packetlength, @@ -3429,6 +3468,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por continue; } } +#endif if (receivepacket->code == RADIUS_ACCESS_ACCEPT) { -- 2.39.3 (Apple Git-146)