/*---------------------------------------------------------------- *Identauthentication *----------------------------------------------------------------
*/ /* Max size of username ident server can return (per RFC 1413) */ #define IDENT_USERNAME_MAX 512
/* Standard TCP port number for Ident service. Assigned by IANA */ #define IDENT_PORT 113
#define PGSQL_PAM_SERVICE "postgresql"/* Service name passed to PAM */
/* Work around original Solaris' lack of "const" in the conv_proc signature */ #ifdef _PAM_LEGACY_NONCONST #define PG_PAM_CONST #else #define PG_PAM_CONST const #endif
/*---------------------------------------------------------------- *LDAPauthentication *----------------------------------------------------------------
*/ #ifdef USE_LDAP #ifndef WIN32 /* We use a deprecated function to keep the codepath the same as win32. */ #define LDAP_DEPRECATED 1 #include <ldap.h> #else #include <winldap.h>
#endif
staticint CheckLDAPAuth(Port *port);
/* LDAP_OPT_DIAGNOSTIC_MESSAGE is the newer spelling */ #ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE #define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING #endif
/* Default LDAP password mutator hook, can be overridden by a shared library */ staticchar *dummy_ldap_password_mutator(char *input);
auth_password_hook_typ ldap_password_hook = dummy_ldap_password_mutator;
switch (port->hba->auth_method)
{ case uaReject: case uaImplicitReject:
errstr = gettext_noop("authentication failed for user \"%s\": host rejected"); break; case uaTrust:
errstr = gettext_noop("\"trust\" authentication failed for user \"%s\""); break; case uaIdent:
errstr = gettext_noop("Ident authentication failed for user \"%s\""); break; case uaPeer:
errstr = gettext_noop("Peer authentication failed for user \"%s\""); break; case uaPassword: case uaMD5: case uaSCRAM:
errstr = gettext_noop("password authentication failed for user \"%s\""); /* We use it to indicate if a .pgpass password failed. */
errcode_return = ERRCODE_INVALID_PASSWORD; break; case uaGSS:
errstr = gettext_noop("GSSAPI authentication failed for user \"%s\""); break; case uaSSPI:
errstr = gettext_noop("SSPI authentication failed for user \"%s\""); break; case uaPAM:
errstr = gettext_noop("PAM authentication failed for user \"%s\""); break; case uaBSD:
errstr = gettext_noop("BSD authentication failed for user \"%s\""); break; case uaLDAP:
errstr = gettext_noop("LDAP authentication failed for user \"%s\""); break; 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; default:
errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method"); break;
}
if (MyClientConnectionInfo.authn_id)
{ /* *Anexistingauthn_idshouldneverbeoverwritten;thatmeanstwo *authenticationprovidersarefighting(oroneisfightingitself). *Don'tleakanyauthndetailstotheclient,butdon'tletthe *connectioncontinue,either.
*/
ereport(FATAL,
(errmsg("authentication identifier set more than once"),
errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
MyClientConnectionInfo.authn_id, id)));
}
/* *Thisisthefirstpointwherewehaveaccesstothehbarecordforthe *currentconnection,soperformanyverificationsbasedonthehba *optionsfieldthatshouldbedone*before*theauthenticationhere.
*/ if (port->hba->clientcert != clientCertOff)
{ /* If we haven't loaded a root certificate store, fail */ if (!secure_loaded_verify_locations())
ereport(FATAL,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("client certificates can only be checked if a root certificate store is available")));
/* *Ifweloadedarootcertificatestore,andifacertificateis *presentontheclient,thenithasbeenverifiedagainstourroot *certificatestore,andtheconnectionwouldhavebeenaborted *alreadyifitdidn'tverifyok.
*/ if (!port->peer_cert_valid)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("connection requires a valid client certificate")));
}
/* *Nowproceedtodotheactualauthenticationcheck
*/ switch (port->hba->auth_method)
{ case uaReject:
#define HOSTNAME_LOOKUP_DETAIL(port) \
(port->remote_hostname ? \
(port->remote_hostname_resolv == +1 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
port->remote_hostname) : \
port->remote_hostname_resolv == 0 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
port->remote_hostname) : \
port->remote_hostname_resolv == -1 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
port->remote_hostname) : \
port->remote_hostname_resolv == -2 ? \
errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
port->remote_hostname, \
gai_strerror(port->remote_hostname_errcode)) : \ 0) \
: (port->remote_hostname_resolv == -2 ? \
errdetail_log("Could not resolve client IP address to a host name: %s.", \
gai_strerror(port->remote_hostname_errcode)) : \ 0))
if (am_walsender && !am_db_walsender)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), /* translator: last %s describes encryption state */
errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
hostinfo, port->user_name,
encryption_state),
HOSTNAME_LOOKUP_DETAIL(port))); else
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), /* translator: last %s describes encryption state */
errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
hostinfo, port->user_name,
port->database_name,
encryption_state),
HOSTNAME_LOOKUP_DETAIL(port))); break;
}
case uaGSS: #ifdef ENABLE_GSS /* We might or might not have the gss workspace already */ if (port->gss == NULL)
port->gss = (pg_gssinfo *)
MemoryContextAllocZero(TopMemoryContext, sizeof(pg_gssinfo));
port->gss->auth = true;
/* *IfGSSstatewassetupwhileenablingencryption,wecanjust *checktheclient'sprincipal.Otherwise,askforit.
*/ if (port->gss->enc)
status = pg_GSS_checkauth(port); else
{
sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
status = pg_GSS_recvauth(port);
} #else
Assert(false); #endif break;
case uaSSPI: #ifdef ENABLE_SSPI if (port->gss == NULL)
port->gss = (pg_gssinfo *)
MemoryContextAllocZero(TopMemoryContext, sizeof(pg_gssinfo));
sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
status = pg_SSPI_recvauth(port); #else
Assert(false); #endif break;
case uaPeer:
status = auth_peer(port); break;
case uaIdent:
status = ident_inet(port); break;
case uaMD5: case uaSCRAM:
status = CheckPWChallengeAuth(port, &logdetail); break;
case uaPassword:
status = CheckPasswordAuth(port, &logdetail); break;
case uaPAM: #ifdef USE_PAM
status = CheckPAMAuth(port, port->user_name, ""); #else
Assert(false); #endif/* USE_PAM */ break;
case uaBSD: #ifdef USE_BSD_AUTH
status = CheckBSDAuth(port, port->user_name); #else
Assert(false); #endif/* USE_BSD_AUTH */ break;
case uaLDAP: #ifdef USE_LDAP
status = CheckLDAPAuth(port); #else
Assert(false); #endif break; case uaRADIUS:
status = CheckRADIUSAuth(port); break; case uaCert: /* uaCert will be treated as if clientcert=verify-full (uaTrust) */ case uaTrust:
status = STATUS_OK; break; case uaOAuth:
status = CheckSASLAuth(&pg_be_oauth_mech, port, NULL, NULL); break;
}
if (auth_result == STATUS_OK)
set_authn_id(port, port->user_name);
return auth_result;
}
staticint
CheckMD5Auth(Port *port, char *shadow_pass, constchar **logdetail)
{
uint8 md5Salt[4]; /* Password salt */ char *passwd; int result;
/* include the salt to use for computing the response */ if (!pg_strong_random(md5Salt, 4))
{
ereport(LOG,
(errmsg("could not generate random MD5 salt"))); return STATUS_ERROR;
}
/* *Usetheconfiguredkeytab,ifthereisone.AswenowrequireMIT *Kerberos,wemightconsiderusingthecredentialstoreextensionsin *thefutureinsteadoftheenvironmentvariable.
*/ if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
{ if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
{ /* The only likely failure cause is OOM, so use that errcode */
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("could not set environment: %m")));
}
}
if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
ereport(ERROR,
(errmsg_internal("could not get token information buffer size: error code %lu",
GetLastError())));
tokenuser = malloc(retlen); if (tokenuser == NULL)
ereport(ERROR,
(errmsg("out of memory")));
if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
ereport(ERROR,
(errmsg_internal("could not get token information: error code %lu",
GetLastError())));
CloseHandle(token);
if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
domainname, &domainnamesize, &accountnameuse))
ereport(ERROR,
(errmsg_internal("could not look up account SID: error code %lu",
GetLastError())));
free(tokenuser);
if (!port->hba->compat_realm)
{ int status = pg_SSPI_make_upn(accountname, sizeof(accountname),
domainname, sizeof(domainname),
port->hba->upn_username);
if (status != STATUS_OK) /* Error already reported from pg_SSPI_make_upn */ return status;
}
/* upnamesize includes the terminating NUL. */
upname = palloc(upnamesize);
res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
upname, &upnamesize);
pfree(samname); if (res)
p = strchr(upname, '@');
if (!res || p == NULL)
{
pfree(upname);
ereport(LOG,
(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
errmsg("could not translate name"))); return STATUS_ERROR;
}
/* Length of realm name after the '@', including the NUL. */
upnamerealmsize = upnamesize - (p - upname + 1);
/* Replace domainname with realm name. */ if (upnamerealmsize > domainnamesize)
{
pfree(upname);
ereport(LOG,
(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
errmsg("realm name too long"))); return STATUS_ERROR;
}
/* Length is now safe. */
strcpy(domainname, p + 1);
/* Replace account name as well (in case UPN != SAM)? */ if (update_accountname)
{ if ((p - upname + 1) > accountnamesize)
{
pfree(upname);
ereport(LOG,
(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
errmsg("translated account name too long"))); return STATUS_ERROR;
}
/* *Ident'sresponse,inthetelnettradition,shouldendincrlf(\r\n).
*/ if (strlen(ident_response) < 2) returnfalse; elseif (ident_response[strlen(ident_response) - 2] != '\r') returnfalse; else
{ while (*cursor != ':' && *cursor != '\r')
cursor++; /* skip port field */
if (*cursor != ':') returnfalse; else
{ /* We're positioned to colon before response type field */ char response_type[80]; int i; /* Index into *response_type */
cursor++; /* Go over colon */ while (pg_isblank(*cursor))
cursor++; /* skip blanks */
i = 0; while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
i < (int) (sizeof(response_type) - 1))
response_type[i++] = *cursor++;
response_type[i] = '\0'; while (pg_isblank(*cursor))
cursor++; /* skip blanks */ if (strcmp(response_type, "USERID") != 0) returnfalse; else
{ /* *It'saUSERIDresponse.Good."cursor"shouldbepointing *tothecolonthatprecedestheoperatingsystemtype.
*/ if (*cursor != ':') returnfalse; else
{
cursor++; /* Go over colon */ /* Skip over operating system field. */ while (*cursor != ':' && *cursor != '\r')
cursor++; if (*cursor != ':') returnfalse; else
{
cursor++; /* Go over colon */ while (pg_isblank(*cursor))
cursor++; /* skip blanks */ /* Rest of line is user name. Copy it over. */
i = 0; while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
ident_user[i++] = *cursor++;
ident_user[i] = '\0'; returntrue;
}
}
}
}
}
}
/* *Talktotheidentserveron"remote_addr"andfindoutwho *ownsthetcpconnectionto"local_addr" *Iftheusernameissuccessfullyretrieved,checktheusermap. * *XXX:UsingWaitLatchOrSocket()anddoingaCHECK_FOR_INTERRUPTS()ifthe *latchwassetwouldimprovetheresponsivenesstotimeouts/cancellations.
*/ staticint
ident_inet(hbaPort *port)
{ const SockAddr remote_addr = port->raddr; const SockAddr local_addr = port->laddr; char ident_user[IDENT_USERNAME_MAX + 1];
pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */ int rc; /* Return code from a locally called function */ bool ident_return; char remote_addr_s[NI_MAXHOST]; char remote_port[NI_MAXSERV]; char local_addr_s[NI_MAXHOST]; char local_port[NI_MAXSERV]; char ident_port[NI_MAXSERV]; char ident_query[80]; char ident_response[80 + IDENT_USERNAME_MAX]; struct addrinfo *ident_serv = NULL,
*la = NULL,
hints;
if (rc < 0)
{
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
remote_addr_s, ident_port)));
ident_return = false; goto ident_inet_done;
}
if (rc < 0)
{
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
remote_addr_s, ident_port)));
ident_return = false; goto ident_inet_done;
}
ident_response[rc] = '\0';
ident_return = interpret_ident_response(ident_response, ident_user); if (!ident_return)
ereport(LOG,
(errmsg("invalidly formatted response from Ident server: \"%s\"",
ident_response)));
ident_inet_done: if (sock_fd != PGINVALID_SOCKET)
closesocket(sock_fd); if (ident_serv)
pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv); if (la)
pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
if (getpeereid(port->sock, &uid, &gid) != 0)
{ /* Provide special error message if getpeereid is a stub */ if (errno == ENOSYS)
ereport(LOG,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("peer authentication is not supported on this platform"))); else
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not get peer credentials: %m"))); return STATUS_ERROR;
}
#ifndef WIN32
rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw); if (rc != 0)
{
errno = rc;
ereport(LOG,
errmsg("could not look up local user ID %ld: %m", (long) uid)); return STATUS_ERROR;
} elseif (!pw)
{
ereport(LOG,
errmsg("local user with ID %ld does not exist", (long) uid)); return STATUS_ERROR;
}
/* *Settheapplicationdataportionoftheconversationstruct.Thisis *laterusedinsidethePAMconversationtopassthepasswordtothe *authenticationmodule.
*/
pam_passw_conv.appdata_ptr = unconstify(char *, password); /* from password above,
* not allocated */
/* Optionally, one can set the service name in pg_hba.conf */ if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
retval = pam_start(port->hba->pamservice, "pgsql@",
&pam_passw_conv, &pamh); else
retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
&pam_passw_conv, &pamh);
/* ou=blah,dc=foo,dc=bar -> foo.bar */ if (ldap_dn2domain(port->hba->ldapbasedn, &domain))
{
ereport(LOG,
(errmsg("could not extract domain name from ldapbasedn"))); return STATUS_ERROR;
}
/* Look up a list of LDAP server hosts and port numbers */ if (ldap_domain2hostlist(domain, &hostlist))
{
ereport(LOG,
(errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
domain),
(errhint("Set an LDAP server name explicitly."))));
ldap_memfree(domain); return STATUS_ERROR;
}
ldap_memfree(domain);
/* We have a space-separated list of host:port entries */
p = hostlist;
append_port = false;
} else
{ /* We have a space-separated list of hosts from pg_hba.conf */
p = port->hba->ldapserver;
append_port = true;
}
/* Convert the list of host[:port] entries to full URIs */ do
{
size_t size;
/* Find the span of the next entry */
size = strcspn(p, " ");
/* Append a space separator if this isn't the first URI */ if (uris.len > 0)
appendStringInfoChar(&uris, ' ');
/* Step over this entry and any number of trailing spaces */
p += size; while (*p == ' ')
++p;
} while (*p);
/* Free memory from OpenLDAP if we looked up SRV records */ if (hostlist)
ldap_memfree(hostlist);
/* Finally, try to connect using the URI list */
r = ldap_initialize(ldap, uris.data);
pfree(uris.data); if (r != LDAP_SUCCESS)
{
ereport(LOG,
(errmsg("could not initialize LDAP: %s",
ldap_err2string(r))));
return STATUS_ERROR;
}
} #else if (strcmp(scheme, "ldaps") == 0)
{
ereport(LOG,
(errmsg("ldaps not supported with this LDAP library")));
return STATUS_ERROR;
}
*ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport); if (!*ldap)
{
ereport(LOG,
(errmsg("could not initialize LDAP: %m")));
return STATUS_ERROR;
} #endif #endif
if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
{
ereport(LOG,
(errmsg("could not set LDAP protocol version: %s",
ldap_err2string(r)),
errdetail_for_ldap(*ldap)));
ldap_unbind(*ldap); return STATUS_ERROR;
}
/* Placeholders recognized by FormatSearchFilter. For now just one. */ #define LPH_USERNAME "$username" #define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
/* Not all LDAP implementations define this. */ #ifndef LDAP_NO_ATTRS #define LDAP_NO_ATTRS "1.1" #endif
/* Not all LDAP implementations define this. */ #ifndef LDAPS_PORT #define LDAPS_PORT 636 #endif
if (r != LDAP_SUCCESS)
{
ereport(LOG,
(errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
filter, server_name, ldap_err2string(r)),
errdetail_for_ldap(ldap))); if (search_message != NULL)
ldap_msgfree(search_message);
ldap_unbind(ldap);
pfree(passwd);
pfree(filter); return STATUS_ERROR;
}
count = ldap_count_entries(ldap, search_message); if (count != 1)
{ if (count == 0)
ereport(LOG,
(errmsg("LDAP user \"%s\" does not exist", port->user_name),
errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
filter, server_name))); else
ereport(LOG,
(errmsg("LDAP user \"%s\" is not unique", port->user_name),
errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.", "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
count,
filter, server_name, count)));
entry = ldap_first_entry(ldap, search_message);
dn = ldap_get_dn(ldap, entry); if (dn == NULL)
{ int error;
(void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
ereport(LOG,
(errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
filter, server_name,
ldap_err2string(error)),
errdetail_for_ldap(ldap)));
ldap_unbind(ldap);
pfree(passwd);
pfree(filter);
ldap_msgfree(search_message); return STATUS_ERROR;
}
fulluser = pstrdup(dn);
/* select the correct field to compare */ switch (port->hba->clientcertname)
{ case clientCertDN:
peer_username = port->peer_dn; break; case clientCertCN:
peer_username = port->peer_cn;
}
/* Make sure we have received a username in the certificate */ if (peer_username == NULL ||
strlen(peer_username) <= 0)
{
ereport(LOG,
(errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
port->user_name))); return STATUS_ERROR;
}
if (port->hba->auth_method == uaCert)
{ /* *Forcertauth,theclient'sSubjectDNisalwaysourauthenticated *identity,evenifwe'reonlyusingitsCNforauthorization.Set *itnow,ratherthanwaitingforcheck_usermap()below,because *authenticationhasalreadysucceededandwewantthelogfileto *reflectthat.
*/ if (!port->peer_dn)
{ /* *Thisshouldnothappenasbothpeer_dnandpeer_cnshouldbe *setinthiscontext.
*/
ereport(LOG,
(errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",
port->user_name))); return STATUS_ERROR;
}
set_authn_id(port, port->peer_dn);
}
/* Just pass the certificate cn/dn to the usermap check */
status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false); if (status_check_usermap != STATUS_OK)
{ /* *Ifclientcert=verify-fullwasspecifiedandtheauthentication *methodisotherthanuaCert,logthereasonforrejectingthe *authentication.
*/ if (port->hba->clientcert == clientCertFull && port->hba->auth_method != uaCert)
{ switch (port->hba->clientcertname)
{ case clientCertDN:
ereport(LOG,
(errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
port->user_name))); break; case clientCertCN:
ereport(LOG,
(errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
port->user_name)));
}
}
} return status_check_usermap;
} #endif
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;
}
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? */
/* for the first iteration, we use the Request Authenticator vector */
md5trailer = packet->vector; for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
{ constchar *errstr = NULL;
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;
}
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;
}