diff --git a/doc/src/sgml/appendix-obsolete-auth-radius.sgml b/doc/src/sgml/appendix-obsolete-auth-radius.sgml new file mode 100644 index 00000000000..68d49df004a --- /dev/null +++ b/doc/src/sgml/appendix-obsolete-auth-radius.sgml @@ -0,0 +1,20 @@ + + + + + RADIUS authentication removed + + + RADIUS + + + + PostgreSQL 18 and below supported the RADIUS authentication protocol. + Information about an alternative way to configure RADIUS support + is available on the PostgreSQL + wiki. + + + diff --git a/doc/src/sgml/appendix-obsolete.sgml b/doc/src/sgml/appendix-obsolete.sgml index b1a00c8ce67..cc002653052 100644 --- a/doc/src/sgml/appendix-obsolete.sgml +++ b/doc/src/sgml/appendix-obsolete.sgml @@ -38,5 +38,6 @@ &obsolete-pgxlogdump; &obsolete-pgresetxlog; &obsolete-pgreceivexlog; + &obsolete-auth-radius; diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index bca09a80416..e4e65f8feb1 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -616,16 +616,6 @@ include_dir directory - - radius - - - Authenticate using a RADIUS server. See for details. - - - - cert @@ -1127,12 +1117,6 @@ omicron bryanh guest1 relies on an LDAP authentication server. - - - RADIUS authentication, which - relies on a RADIUS authentication server. - - Certificate authentication, which @@ -2096,118 +2080,6 @@ host ... ldap ldapbasedn="dc=example,dc=net" - - RADIUS Authentication - - - RADIUS - - - - This authentication method operates similarly to - password except that it uses RADIUS - as the password verification method. RADIUS is used only to validate - the user name/password pairs. Therefore the user must already - exist in the database before RADIUS can be used for - authentication. - - - - When using RADIUS authentication, an Access Request message will be sent - to the configured RADIUS server. This request will be of type - Authenticate Only, and include parameters for - user name, password (encrypted) and - NAS Identifier. The request will be encrypted using - a secret shared with the server. The RADIUS server will respond to - this request with either Access Accept or - Access Reject. There is no support for RADIUS accounting. - - - - Multiple RADIUS servers can be specified, in which case they will - be tried sequentially. If a negative response is received from - a server, the authentication will fail. If no response is received, - the next server in the list will be tried. To specify multiple - servers, separate the server names with commas and surround the list - with double quotes. If multiple servers are specified, the other - RADIUS options can also be given as comma-separated lists, to provide - individual values for each server. They can also be specified as - a single value, in which case that value will apply to all servers. - - - - The following configuration options are supported for RADIUS: - - - radiusservers - - - The DNS names or IP addresses of the RADIUS servers to connect to. - This parameter is required. - - - - - - radiussecrets - - - The shared secrets used when talking securely to the RADIUS - servers. This must have exactly the same value on the PostgreSQL - and RADIUS servers. It is recommended that this be a string of - at least 16 characters. This parameter is required. - - - The encryption vector used will only be cryptographically - strong if PostgreSQL is built with support for - OpenSSL. In other cases, the transmission to the - RADIUS server should only be considered obfuscated, not secured, and - external security measures should be applied if necessary. - - - - - - - - radiusports - - - The port numbers to connect to on the RADIUS servers. If no port - is specified, the default RADIUS port (1812) - will be used. - - - - - - radiusidentifiers - - - The strings to be used as NAS Identifier in the - RADIUS requests. This parameter can be used, for example, to - identify which database cluster the user is attempting to connect - to, which can be useful for policy matching on - the RADIUS server. If no identifier is specified, the default - postgresql will be used. - - - - - - - - - If it is necessary to have a comma or whitespace in a RADIUS parameter - value, that can be done by putting double quotes around the value, but - it is tedious because two layers of double-quoting are now required. - An example of putting whitespace into RADIUS secret strings is: - -host ... radius radiusservers="server1,server2" radiussecrets="""secret one"",""secret two""" - - - - Certificate Authentication diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index e8f758fc24b..25a85082759 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -208,3 +208,4 @@ + diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 47b5eeb8f22..2af5615e54a 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -203,13 +203,6 @@ static int pg_SSPI_make_upn(char *accountname, bool update_accountname); #endif -/*---------------------------------------------------------------- - * RADIUS Authentication - *---------------------------------------------------------------- - */ -static int 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); - /*---------------------------------------------------------------- * Global authentication functions @@ -299,9 +292,6 @@ auth_failed(Port *port, int elevel, int status, const char *logdetail) case uaCert: errstr = gettext_noop("certificate authentication failed for user \"%s\""); break; - case uaRADIUS: - errstr = gettext_noop("RADIUS authentication failed for user \"%s\""); - break; case uaOAuth: errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\""); break; @@ -630,9 +620,6 @@ ClientAuthentication(Port *port) Assert(false); #endif break; - case uaRADIUS: - status = CheckRADIUSAuth(port); - break; case uaCert: /* uaCert will be treated as if clientcert=verify-full (uaTrust) */ case uaTrust: @@ -775,7 +762,7 @@ recv_password_packet(Port *port) * We rely on that for MD5 and SCRAM authentication, but we still need * this check here, to prevent an empty password from being used with * authentication methods that check the password against an external - * system, like PAM, LDAP and RADIUS. + * system, like PAM and LDAP. */ if (buf.len == 1) ereport(ERROR, @@ -2790,499 +2777,3 @@ CheckCertAuth(Port *port) return status_check_usermap; } #endif - - -/*---------------------------------------------------------------- - * RADIUS authentication - *---------------------------------------------------------------- - */ - -/* - * 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; - uint8 length; - uint8 data[FLEXIBLE_ARRAY_MEMBER]; -} radius_attribute; - -typedef struct -{ - uint8 code; - 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 */ -#define RADIUS_ACCESS_REQUEST 1 -#define RADIUS_ACCESS_ACCEPT 2 -#define RADIUS_ACCESS_REJECT 3 - -/* RADIUS attributes */ -#define RADIUS_USER_NAME 1 -#define RADIUS_PASSWORD 2 -#define RADIUS_SERVICE_TYPE 6 -#define RADIUS_NAS_IDENTIFIER 32 - -/* RADIUS service types */ -#define RADIUS_AUTHENTICATE_ONLY 8 - -/* Seconds to wait - XXX: should be in a config variable! */ -#define RADIUS_TIMEOUT 3 - -static void -radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len) -{ - radius_attribute *attr; - - if (packet->length + len > RADIUS_BUFFER_SIZE) - { - /* - * With remotely realistic data, this can never happen. But catch it - * just to make sure we don't overrun a buffer. We'll just skip adding - * the broken attribute, which will in the end cause authentication to - * fail. - */ - elog(WARNING, - "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring", - type, len); - return; - } - - attr = (radius_attribute *) ((unsigned char *) packet + packet->length); - attr->attribute = type; - attr->length = len + 2; /* total size includes type and length */ - memcpy(attr->data, data, len); - packet->length += attr->length; -} - -static int -CheckRADIUSAuth(Port *port) -{ - char *passwd; - ListCell *server, - *secrets, - *radiusports, - *identifiers; - - /* Make sure struct alignment is correct */ - Assert(offsetof(radius_packet, vector) == 4); - - /* Verify parameters */ - if (port->hba->radiusservers == NIL) - { - ereport(LOG, - (errmsg("RADIUS server not specified"))); - return STATUS_ERROR; - } - - if (port->hba->radiussecrets == NIL) - { - ereport(LOG, - (errmsg("RADIUS secret not specified"))); - return STATUS_ERROR; - } - - /* Send regular password request to client, and get the response */ - sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0); - - passwd = recv_password_packet(port); - if (passwd == NULL) - return STATUS_EOF; /* client wouldn't send password */ - - if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH) - { - ereport(LOG, - (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH))); - pfree(passwd); - return STATUS_ERROR; - } - - /* - * Loop over and try each server in order. - */ - secrets = list_head(port->hba->radiussecrets); - radiusports = list_head(port->hba->radiusports); - identifiers = list_head(port->hba->radiusidentifiers); - foreach(server, port->hba->radiusservers) - { - int ret = PerformRadiusTransaction(lfirst(server), - lfirst(secrets), - radiusports ? lfirst(radiusports) : NULL, - identifiers ? lfirst(identifiers) : NULL, - port->user_name, - passwd); - - /*------ - * STATUS_OK = Login OK - * STATUS_ERROR = Login not OK, but try next server - * STATUS_EOF = Login not OK, and don't try next server - *------ - */ - if (ret == STATUS_OK) - { - set_authn_id(port, port->user_name); - - pfree(passwd); - return STATUS_OK; - } - else if (ret == STATUS_EOF) - { - pfree(passwd); - return STATUS_ERROR; - } - - /* - * secret, port and identifiers either have length 0 (use default), - * length 1 (use the same everywhere) or the same length as servers. - * So if the length is >1, we advance one step. In other cases, we - * don't and will then reuse the correct value. - */ - if (list_length(port->hba->radiussecrets) > 1) - secrets = lnext(port->hba->radiussecrets, secrets); - if (list_length(port->hba->radiusports) > 1) - radiusports = lnext(port->hba->radiusports, radiusports); - if (list_length(port->hba->radiusidentifiers) > 1) - identifiers = lnext(port->hba->radiusidentifiers, identifiers); - } - - /* No servers left to try, so give up */ - pfree(passwd); - return STATUS_ERROR; -} - -static int -PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd) -{ - radius_packet radius_send_pack; - radius_packet radius_recv_pack; - radius_packet *packet = &radius_send_pack; - radius_packet *receivepacket = &radius_recv_pack; - void *radius_buffer = &radius_send_pack; - void *receive_buffer = &radius_recv_pack; - int32 service = pg_hton32(RADIUS_AUTHENTICATE_ONLY); - uint8 *cryptvector; - int encryptedpasswordlen; - uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH]; - uint8 *md5trailer; - int packetlength; - pgsocket sock; - - struct sockaddr_in6 localaddr; - struct sockaddr_in6 remoteaddr; - struct addrinfo hint; - struct addrinfo *serveraddrs; - int port; - socklen_t addrsize; - fd_set fdset; - struct timeval endtime; - int i, - j, - r; - - /* Assign default values */ - if (portstr == NULL) - portstr = "1812"; - if (identifier == NULL) - identifier = "postgresql"; - - MemSet(&hint, 0, sizeof(hint)); - hint.ai_socktype = SOCK_DGRAM; - hint.ai_family = AF_UNSPEC; - port = atoi(portstr); - - r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs); - if (r || !serveraddrs) - { - ereport(LOG, - (errmsg("could not translate RADIUS server name \"%s\" to address: %s", - server, gai_strerror(r)))); - if (serveraddrs) - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - return STATUS_ERROR; - } - /* XXX: add support for multiple returned addresses? */ - - /* Construct RADIUS packet */ - packet->code = RADIUS_ACCESS_REQUEST; - packet->length = RADIUS_HEADER_LENGTH; - if (!pg_strong_random(packet->vector, RADIUS_VECTOR_LENGTH)) - { - ereport(LOG, - (errmsg("could not generate random encryption vector"))); - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - return STATUS_ERROR; - } - packet->id = packet->vector[0]; - 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)); - radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier)); - - /* - * RADIUS password attributes are calculated as: e[0] = p[0] XOR - * MD5(secret + Request Authenticator) for the first group of 16 octets, - * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones - * (if necessary) - */ - encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH; - cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH); - memcpy(cryptvector, secret, strlen(secret)); - - /* for the first iteration, we use the Request Authenticator vector */ - md5trailer = packet->vector; - for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH) - { - const char *errstr = NULL; - - memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH); - - /* - * .. and for subsequent iterations the result of the previous XOR - * (calculated below) - */ - md5trailer = encryptedpassword + i; - - if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, - encryptedpassword + i, &errstr)) - { - ereport(LOG, - (errmsg("could not perform MD5 encryption of password: %s", - errstr))); - pfree(cryptvector); - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - 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]; - } - } - pfree(cryptvector); - - radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen); - - /* Length needs to be in network order on the wire */ - packetlength = packet->length; - packet->length = pg_hton16(packet->length); - - sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0); - if (sock == PGINVALID_SOCKET) - { - ereport(LOG, - (errmsg("could not create RADIUS socket: %m"))); - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - return STATUS_ERROR; - } - - memset(&localaddr, 0, sizeof(localaddr)); - localaddr.sin6_family = serveraddrs[0].ai_family; - localaddr.sin6_addr = in6addr_any; - if (localaddr.sin6_family == AF_INET6) - addrsize = sizeof(struct sockaddr_in6); - else - addrsize = sizeof(struct sockaddr_in); - - if (bind(sock, (struct sockaddr *) &localaddr, addrsize)) - { - ereport(LOG, - (errmsg("could not bind local RADIUS socket: %m"))); - closesocket(sock); - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - return STATUS_ERROR; - } - - if (sendto(sock, radius_buffer, packetlength, 0, - serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0) - { - ereport(LOG, - (errmsg("could not send RADIUS packet: %m"))); - closesocket(sock); - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - return STATUS_ERROR; - } - - /* Don't need the server address anymore */ - pg_freeaddrinfo_all(hint.ai_family, serveraddrs); - - /* - * Figure out at what time we should time out. We can't just use a single - * call to select() with a timeout, since somebody can be sending invalid - * packets to our port thus causing us to retry in a loop and never time - * out. - * - * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if - * the latch was set would improve the responsiveness to - * timeouts/cancellations. - */ - gettimeofday(&endtime, NULL); - endtime.tv_sec += RADIUS_TIMEOUT; - - while (true) - { - struct timeval timeout; - struct timeval now; - int64 timeoutval; - const char *errstr = NULL; - - gettimeofday(&now, NULL); - timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec); - if (timeoutval <= 0) - { - ereport(LOG, - (errmsg("timeout waiting for RADIUS response from %s", - server))); - closesocket(sock); - return STATUS_ERROR; - } - timeout.tv_sec = timeoutval / 1000000; - timeout.tv_usec = timeoutval % 1000000; - - FD_ZERO(&fdset); - FD_SET(sock, &fdset); - - r = select(sock + 1, &fdset, NULL, NULL, &timeout); - if (r < 0) - { - if (errno == EINTR) - continue; - - /* Anything else is an actual error */ - ereport(LOG, - (errmsg("could not check status on RADIUS socket: %m"))); - closesocket(sock); - return STATUS_ERROR; - } - if (r == 0) - { - ereport(LOG, - (errmsg("timeout waiting for RADIUS response from %s", - server))); - closesocket(sock); - return STATUS_ERROR; - } - - /* - * Attempt to read the response packet, and verify the contents. - * - * Any packet that's not actually a RADIUS packet, or otherwise does - * not validate as an explicit reject, is just ignored and we retry - * for another packet (until we reach the timeout). This is to avoid - * the possibility to denial-of-service the login by flooding the - * server with invalid packets on the port that we're expecting the - * RADIUS response on. - */ - - addrsize = sizeof(remoteaddr); - packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0, - (struct sockaddr *) &remoteaddr, &addrsize); - if (packetlength < 0) - { - ereport(LOG, - (errmsg("could not read RADIUS response: %m"))); - closesocket(sock); - return STATUS_ERROR; - } - - if (remoteaddr.sin6_port != pg_hton16(port)) - { - ereport(LOG, - (errmsg("RADIUS response from %s was sent from incorrect port: %d", - server, pg_ntoh16(remoteaddr.sin6_port)))); - continue; - } - - if (packetlength < RADIUS_HEADER_LENGTH) - { - ereport(LOG, - (errmsg("RADIUS response from %s too short: %d", server, packetlength))); - continue; - } - - if (packetlength != pg_ntoh16(receivepacket->length)) - { - ereport(LOG, - (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)", - server, pg_ntoh16(receivepacket->length), packetlength))); - continue; - } - - if (packet->id != receivepacket->id) - { - ereport(LOG, - (errmsg("RADIUS response from %s is to a different request: %d (should be %d)", - server, receivepacket->id, packet->id))); - continue; - } - - /* - * Verify the response authenticator, which is calculated as - * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret) - */ - cryptvector = palloc(packetlength + strlen(secret)); - - memcpy(cryptvector, receivepacket, 4); /* code+id+length */ - memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request - * authenticator, from - * original packet */ - if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no - * attributes at all */ - memcpy(cryptvector + RADIUS_HEADER_LENGTH, - (char *) receive_buffer + RADIUS_HEADER_LENGTH, - packetlength - RADIUS_HEADER_LENGTH); - memcpy(cryptvector + packetlength, secret, strlen(secret)); - - if (!pg_md5_binary(cryptvector, - packetlength + strlen(secret), - encryptedpassword, &errstr)) - { - ereport(LOG, - (errmsg("could not perform MD5 encryption of received packet: %s", - errstr))); - pfree(cryptvector); - continue; - } - pfree(cryptvector); - - if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0) - { - ereport(LOG, - (errmsg("RADIUS response from %s has incorrect MD5 signature", - server))); - continue; - } - - if (receivepacket->code == RADIUS_ACCESS_ACCEPT) - { - closesocket(sock); - return STATUS_OK; - } - else if (receivepacket->code == RADIUS_ACCESS_REJECT) - { - closesocket(sock); - return STATUS_EOF; - } - else - { - ereport(LOG, - (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"", - server, receivepacket->code, user_name))); - continue; - } - } /* while (true) */ -} diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 7694506aaf7..d47eab2cba0 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -114,7 +114,6 @@ static const char *const UserAuthName[] = "bsd", "ldap", "cert", - "radius", "peer", "oauth", }; @@ -1744,8 +1743,6 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel) #else unsupauth = "cert"; #endif - else if (strcmp(token->string, "radius") == 0) - parsedline->auth_method = uaRADIUS; else if (strcmp(token->string, "oauth") == 0) parsedline->auth_method = uaOAuth; else @@ -1947,87 +1944,6 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel) } } - if (parsedline->auth_method == uaRADIUS) - { - MANDATORY_AUTH_ARG(parsedline->radiusservers, "radiusservers", "radius"); - MANDATORY_AUTH_ARG(parsedline->radiussecrets, "radiussecrets", "radius"); - - if (parsedline->radiusservers == NIL) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("list of RADIUS servers cannot be empty"), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - *err_msg = "list of RADIUS servers cannot be empty"; - return NULL; - } - - if (parsedline->radiussecrets == NIL) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("list of RADIUS secrets cannot be empty"), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - *err_msg = "list of RADIUS secrets cannot be empty"; - return NULL; - } - - /* - * Verify length of option lists - each can be 0 (except for secrets, - * but that's already checked above), 1 (use the same value - * everywhere) or the same as the number of servers. - */ - if (!(list_length(parsedline->radiussecrets) == 1 || - list_length(parsedline->radiussecrets) == list_length(parsedline->radiusservers))) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)", - list_length(parsedline->radiussecrets), - list_length(parsedline->radiusservers)), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - *err_msg = psprintf("the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)", - list_length(parsedline->radiussecrets), - list_length(parsedline->radiusservers)); - return NULL; - } - if (!(list_length(parsedline->radiusports) == 0 || - list_length(parsedline->radiusports) == 1 || - list_length(parsedline->radiusports) == list_length(parsedline->radiusservers))) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)", - list_length(parsedline->radiusports), - list_length(parsedline->radiusservers)), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - *err_msg = psprintf("the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)", - list_length(parsedline->radiusports), - list_length(parsedline->radiusservers)); - return NULL; - } - if (!(list_length(parsedline->radiusidentifiers) == 0 || - list_length(parsedline->radiusidentifiers) == 1 || - list_length(parsedline->radiusidentifiers) == list_length(parsedline->radiusservers))) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)", - list_length(parsedline->radiusidentifiers), - list_length(parsedline->radiusservers)), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - *err_msg = psprintf("the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)", - list_length(parsedline->radiusidentifiers), - list_length(parsedline->radiusservers)); - return NULL; - } - } - /* * Enforce any parameters implied by other settings. */ @@ -2350,138 +2266,6 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, else hbaline->upn_username = false; } - else if (strcmp(name, "radiusservers") == 0) - { - struct addrinfo *gai_result; - struct addrinfo hints; - int ret; - List *parsed_servers; - ListCell *l; - char *dupval = pstrdup(val); - - REQUIRE_AUTH_OPTION(uaRADIUS, "radiusservers", "radius"); - - if (!SplitGUCList(dupval, ',', &parsed_servers)) - { - /* syntax error in list */ - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not parse RADIUS server list \"%s\"", - val), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - return false; - } - - /* For each entry in the list, translate it */ - foreach(l, parsed_servers) - { - MemSet(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_DGRAM; - hints.ai_family = AF_UNSPEC; - - ret = pg_getaddrinfo_all((char *) lfirst(l), NULL, &hints, &gai_result); - if (ret || !gai_result) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not translate RADIUS server name \"%s\" to address: %s", - (char *) lfirst(l), gai_strerror(ret)), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - if (gai_result) - pg_freeaddrinfo_all(hints.ai_family, gai_result); - - list_free(parsed_servers); - return false; - } - pg_freeaddrinfo_all(hints.ai_family, gai_result); - } - - /* All entries are OK, so store them */ - hbaline->radiusservers = parsed_servers; - hbaline->radiusservers_s = pstrdup(val); - } - else if (strcmp(name, "radiusports") == 0) - { - List *parsed_ports; - ListCell *l; - char *dupval = pstrdup(val); - - REQUIRE_AUTH_OPTION(uaRADIUS, "radiusports", "radius"); - - if (!SplitGUCList(dupval, ',', &parsed_ports)) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not parse RADIUS port list \"%s\"", - val), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - *err_msg = psprintf("invalid RADIUS port number: \"%s\"", val); - return false; - } - - foreach(l, parsed_ports) - { - if (atoi(lfirst(l)) == 0) - { - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("invalid RADIUS port number: \"%s\"", val), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - - return false; - } - } - hbaline->radiusports = parsed_ports; - hbaline->radiusports_s = pstrdup(val); - } - else if (strcmp(name, "radiussecrets") == 0) - { - List *parsed_secrets; - char *dupval = pstrdup(val); - - REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecrets", "radius"); - - if (!SplitGUCList(dupval, ',', &parsed_secrets)) - { - /* syntax error in list */ - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not parse RADIUS secret list \"%s\"", - val), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - return false; - } - - hbaline->radiussecrets = parsed_secrets; - hbaline->radiussecrets_s = pstrdup(val); - } - else if (strcmp(name, "radiusidentifiers") == 0) - { - List *parsed_identifiers; - char *dupval = pstrdup(val); - - REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifiers", "radius"); - - if (!SplitGUCList(dupval, ',', &parsed_identifiers)) - { - /* syntax error in list */ - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not parse RADIUS identifiers list \"%s\"", - val), - errcontext("line %d of configuration file \"%s\"", - line_num, file_name))); - return false; - } - - hbaline->radiusidentifiers = parsed_identifiers; - hbaline->radiusidentifiers_s = pstrdup(val); - } else if (strcmp(name, "issuer") == 0) { REQUIRE_AUTH_OPTION(uaOAuth, "issuer", "oauth"); diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index 475100f8865..2c8db777479 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -53,8 +53,8 @@ # directly connected to. # # METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", -# "gss", "sspi", "ident", "peer", "pam", "oauth", "ldap", "radius" or -# "cert". Note that "password" sends passwords in clear text; "md5" or +# "gss", "sspi", "ident", "peer", "pam", "oauth", "ldap" or "cert". +# Note that "password" sends passwords in clear text; "md5" or # "scram-sha-256" are preferred since they send encrypted passwords. # # OPTIONS are a set of options for the authentication in the format diff --git a/src/backend/utils/adt/hbafuncs.c b/src/backend/utils/adt/hbafuncs.c index fdce3ed7927..bd23eda3f79 100644 --- a/src/backend/utils/adt/hbafuncs.c +++ b/src/backend/utils/adt/hbafuncs.c @@ -135,25 +135,6 @@ get_hba_options(HbaLine *hba) CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope)); } - if (hba->auth_method == uaRADIUS) - { - if (hba->radiusservers_s) - options[noptions++] = - CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s)); - - if (hba->radiussecrets_s) - options[noptions++] = - CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s)); - - if (hba->radiusidentifiers_s) - options[noptions++] = - CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s)); - - if (hba->radiusports_s) - options[noptions++] = - CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s)); - } - if (hba->auth_method == uaOAuth) { if (hba->oauth_issuer) diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h index e8898561c8c..29e2a6c5b3d 100644 --- a/src/include/libpq/hba.h +++ b/src/include/libpq/hba.h @@ -37,7 +37,6 @@ typedef enum UserAuth uaBSD, uaLDAP, uaCert, - uaRADIUS, uaPeer, uaOAuth, #define USER_AUTH_LAST uaOAuth /* Must be last value of this enum */ @@ -128,14 +127,6 @@ typedef struct HbaLine bool include_realm; bool compat_realm; bool upn_username; - List *radiusservers; - char *radiusservers_s; - List *radiussecrets; - char *radiussecrets_s; - List *radiusidentifiers; - char *radiusidentifiers_s; - List *radiusports; - char *radiusports_s; char *oauth_issuer; char *oauth_scope; char *oauth_validator; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 87832856dba..ea95e7984bc 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -4185,8 +4185,6 @@ qc_hash_func qsort_arg_comparator qsort_comparator query_pathkeys_callback -radius_attribute -radius_packet RadixSortInfo rangeTableEntry_used_context rank_context