PostgreSQL Source Code  git master
auth.c File Reference
#include "postgres.h"
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include "commands/user.h"
#include "common/ip.h"
#include "common/md5.h"
#include "common/scram-common.h"
#include "libpq/auth.h"
#include "libpq/crypt.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/scram.h"
#include "miscadmin.h"
#include "port/pg_bswap.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
Include dependency graph for auth.c:

Go to the source code of this file.

Data Structures

struct  radius_attribute
 
struct  radius_packet
 

Macros

#define IDENT_USERNAME_MAX   512
 
#define IDENT_PORT   113
 
#define PG_MAX_AUTH_TOKEN_LENGTH   65535
 
#define PG_MAX_SASL_MESSAGE_LENGTH   1024
 
#define HOSTNAME_LOOKUP_DETAIL(port)
 
#define RADIUS_VECTOR_LENGTH   16
 
#define RADIUS_HEADER_LENGTH   20
 
#define RADIUS_MAX_PASSWORD_LENGTH   128
 
#define RADIUS_BUFFER_SIZE   1024
 
#define RADIUS_ACCESS_REQUEST   1
 
#define RADIUS_ACCESS_ACCEPT   2
 
#define RADIUS_ACCESS_REJECT   3
 
#define RADIUS_USER_NAME   1
 
#define RADIUS_PASSWORD   2
 
#define RADIUS_SERVICE_TYPE   6
 
#define RADIUS_NAS_IDENTIFIER   32
 
#define RADIUS_AUTHENTICATE_ONLY   8
 
#define RADIUS_TIMEOUT   3
 

Functions

static void sendAuthRequest (Port *port, AuthRequest areq, const char *extradata, int extralen)
 
static void auth_failed (Port *port, int status, char *logdetail)
 
static char * recv_password_packet (Port *port)
 
static int CheckPasswordAuth (Port *port, char **logdetail)
 
static int CheckPWChallengeAuth (Port *port, char **logdetail)
 
static int CheckMD5Auth (Port *port, char *shadow_pass, char **logdetail)
 
static int CheckSCRAMAuth (Port *port, char *shadow_pass, char **logdetail)
 
static int ident_inet (hbaPort *port)
 
static int auth_peer (hbaPort *port)
 
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)
 
void ClientAuthentication (Port *port)
 
static bool interpret_ident_response (const char *ident_response, char *ident_user)
 
static void radius_add_attribute (radius_packet *packet, uint8 type, const unsigned char *data, int len)
 

Variables

char * pg_krb_server_keyfile
 
bool pg_krb_caseins_users
 
ClientAuthentication_hook_type ClientAuthentication_hook = NULL
 

Macro Definition Documentation

◆ HOSTNAME_LOOKUP_DETAIL

#define HOSTNAME_LOOKUP_DETAIL (   port)
Value:
(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))
#define gai_strerror
Definition: getaddrinfo.h:146
int errdetail_log(const char *fmt,...)
Definition: elog.c:1086
static int port
Definition: pg_regress.c:92

Referenced by ClientAuthentication().

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 71 of file auth.c.

Referenced by ident_inet().

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 68 of file auth.c.

Referenced by ident_inet(), and interpret_ident_response().

◆ PG_MAX_AUTH_TOKEN_LENGTH

#define PG_MAX_AUTH_TOKEN_LENGTH   65535

Definition at line 221 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ PG_MAX_SASL_MESSAGE_LENGTH

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 229 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2872 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2873 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2871 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2882 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2851 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2847 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2848 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2879 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2877 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2878 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2885 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2876 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2846 of file auth.c.

Referenced by PerformRadiusTransaction().

Function Documentation

◆ auth_failed()

static void auth_failed ( Port port,
int  status,
char *  logdetail 
)
static

Definition at line 257 of file auth.c.

References _, HbaLine::auth_method, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errdetail_log(), errmsg(), FATAL, gettext_noop, Port::hba, HbaLine::linenumber, proc_exit(), psprintf(), HbaLine::rawline, STATUS_EOF, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaRADIUS, uaReject, uaSCRAM, uaSSPI, uaTrust, and Port::user_name.

Referenced by ClientAuthentication().

258 {
259  const char *errstr;
260  char *cdetail;
261  int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
262 
263  /*
264  * If we failed due to EOF from client, just quit; there's no point in
265  * trying to send a message to the client, and not much point in logging
266  * the failure in the postmaster log. (Logging the failure might be
267  * desirable, were it not for the fact that libpq closes the connection
268  * unceremoniously if challenged for a password when it hasn't got one to
269  * send. We'll get a useless log entry for every psql connection under
270  * password auth, even if it's perfectly successful, if we log STATUS_EOF
271  * events.)
272  */
273  if (status == STATUS_EOF)
274  proc_exit(0);
275 
276  switch (port->hba->auth_method)
277  {
278  case uaReject:
279  case uaImplicitReject:
280  errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
281  break;
282  case uaTrust:
283  errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
284  break;
285  case uaIdent:
286  errstr = gettext_noop("Ident authentication failed for user \"%s\"");
287  break;
288  case uaPeer:
289  errstr = gettext_noop("Peer authentication failed for user \"%s\"");
290  break;
291  case uaPassword:
292  case uaMD5:
293  case uaSCRAM:
294  errstr = gettext_noop("password authentication failed for user \"%s\"");
295  /* We use it to indicate if a .pgpass password failed. */
296  errcode_return = ERRCODE_INVALID_PASSWORD;
297  break;
298  case uaGSS:
299  errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
300  break;
301  case uaSSPI:
302  errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
303  break;
304  case uaPAM:
305  errstr = gettext_noop("PAM authentication failed for user \"%s\"");
306  break;
307  case uaBSD:
308  errstr = gettext_noop("BSD authentication failed for user \"%s\"");
309  break;
310  case uaLDAP:
311  errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
312  break;
313  case uaCert:
314  errstr = gettext_noop("certificate authentication failed for user \"%s\"");
315  break;
316  case uaRADIUS:
317  errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
318  break;
319  default:
320  errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
321  break;
322  }
323 
324  cdetail = psprintf(_("Connection matched pg_hba.conf line %d: \"%s\""),
325  port->hba->linenumber, port->hba->rawline);
326  if (logdetail)
327  logdetail = psprintf("%s\n%s", logdetail, cdetail);
328  else
329  logdetail = cdetail;
330 
331  ereport(FATAL,
332  (errcode(errcode_return),
333  errmsg(errstr, port->user_name),
334  logdetail ? errdetail_log("%s", logdetail) : 0));
335 
336  /* doesn't return */
337 }
Definition: hba.h:30
Definition: hba.h:38
Definition: hba.h:32
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: hba.h:35
#define gettext_noop(x)
Definition: c.h:1197
void proc_exit(int code)
Definition: ipc.c:104
int errcode(int sqlerrcode)
Definition: elog.c:694
Definition: hba.h:34
Definition: hba.h:31
Definition: hba.h:39
#define FATAL
Definition: elog.h:54
Definition: hba.h:27
Definition: hba.h:29
char * user_name
Definition: libpq-be.h:141
int errdetail_log(const char *fmt,...)
Definition: elog.c:1086
int linenumber
Definition: hba.h:76
HbaLine * hba
Definition: libpq-be.h:155
Definition: hba.h:33
Definition: hba.h:37
#define ereport(elevel,...)
Definition: elog.h:155
char * rawline
Definition: hba.h:77
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define STATUS_EOF
Definition: c.h:1172
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:95
Definition: hba.h:36
#define _(x)
Definition: elog.c:89
Definition: hba.h:40
UserAuth auth_method
Definition: hba.h:87

◆ auth_peer()

static int auth_peer ( hbaPort port)
static

Definition at line 1923 of file auth.c.

References _, SockAddr::addr, appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, HbaLine::auth_method, AUTH_REQ_PASSWORD, calloc, check_usermap(), HbaLine::clientcert, clientCertFull, HbaLine::conntype, ctLocal, StringInfoData::data, ereport, errcode(), errcode_for_socket_access(), errdetail(), errdetail_plural(), errhint(), errmsg(), errmsg_internal(), error(), free, gai_strerror, getpeereid(), Port::hba, i, initStringInfo(), HbaLine::ldapbasedn, HbaLine::ldapbinddn, HbaLine::ldapbindpasswd, HbaLine::ldapport, HbaLine::ldapprefix, HbaLine::ldapscheme, HbaLine::ldapscope, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, HbaLine::ldaptls, StringInfoData::len, LOG, NI_MAXHOST, NI_NUMERICHOST, NI_NUMERICSERV, output(), HbaLine::pam_use_hostname, HbaLine::pamservice, password, Port::peer_cn, pfree(), pg_getnameinfo_all(), port, psprintf(), pstrdup(), Port::raddr, recv_password_packet(), SockAddr::salen, sendAuthRequest(), Port::sock, STATUS_EOF, STATUS_ERROR, STATUS_OK, strerror, uaCert, unconstify, user, Port::user_name, HbaLine::usermap, and WARNING.

Referenced by ClientAuthentication().

1924 {
1925  uid_t uid;
1926  gid_t gid;
1927 #ifndef WIN32
1928  struct passwd *pw;
1929  char *peer_user;
1930  int ret;
1931 #endif
1932 
1933  if (getpeereid(port->sock, &uid, &gid) != 0)
1934  {
1935  /* Provide special error message if getpeereid is a stub */
1936  if (errno == ENOSYS)
1937  ereport(LOG,
1938  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1939  errmsg("peer authentication is not supported on this platform")));
1940  else
1941  ereport(LOG,
1943  errmsg("could not get peer credentials: %m")));
1944  return STATUS_ERROR;
1945  }
1946 
1947 #ifndef WIN32
1948  errno = 0; /* clear errno before call */
1949  pw = getpwuid(uid);
1950  if (!pw)
1951  {
1952  int save_errno = errno;
1953 
1954  ereport(LOG,
1955  (errmsg("could not look up local user ID %ld: %s",
1956  (long) uid,
1957  save_errno ? strerror(save_errno) : _("user does not exist"))));
1958  return STATUS_ERROR;
1959  }
1960 
1961  /* Make a copy of static getpw*() result area. */
1962  peer_user = pstrdup(pw->pw_name);
1963 
1964  ret = check_usermap(port->hba->usermap, port->user_name, peer_user, false);
1965 
1966  pfree(peer_user);
1967 
1968  return ret;
1969 #else
1970  /* should have failed with ENOSYS above */
1971  Assert(false);
1972  return STATUS_ERROR;
1973 #endif
1974 }
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:35
char * pstrdup(const char *in)
Definition: mcxt.c:1187
int errcode(int sqlerrcode)
Definition: elog.c:694
#define STATUS_ERROR
Definition: c.h:1171
#define LOG
Definition: elog.h:26
pgsocket sock
Definition: libpq-be.h:122
void pfree(void *pointer)
Definition: mcxt.c:1057
char * usermap
Definition: hba.h:88
char * user_name
Definition: libpq-be.h:141
int errcode_for_socket_access(void)
Definition: elog.c:788
HbaLine * hba
Definition: libpq-be.h:155
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2943
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:804
#define strerror
Definition: port.h:229
int uid_t
Definition: win32_port.h:236
int errmsg(const char *fmt,...)
Definition: elog.c:905
int gid_t
Definition: win32_port.h:237
#define _(x)
Definition: elog.c:89

◆ CheckMD5Auth()

static int CheckMD5Auth ( Port port,
char *  shadow_pass,
char **  logdetail 
)
static

Definition at line 823 of file auth.c.

References AUTH_REQ_MD5, Db_user_namespace, ereport, errcode(), errmsg(), FATAL, LOG, md5_crypt_verify(), pfree(), pg_strong_random(), recv_password_packet(), sendAuthRequest(), STATUS_EOF, STATUS_ERROR, and Port::user_name.

Referenced by CheckPWChallengeAuth().

824 {
825  char md5Salt[4]; /* Password salt */
826  char *passwd;
827  int result;
828 
829  if (Db_user_namespace)
830  ereport(FATAL,
831  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
832  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
833 
834  /* include the salt to use for computing the response */
835  if (!pg_strong_random(md5Salt, 4))
836  {
837  ereport(LOG,
838  (errmsg("could not generate random MD5 salt")));
839  return STATUS_ERROR;
840  }
841 
842  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
843 
844  passwd = recv_password_packet(port);
845  if (passwd == NULL)
846  return STATUS_EOF; /* client wouldn't send password */
847 
848  if (shadow_pass)
849  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
850  md5Salt, 4, logdetail);
851  else
852  result = STATUS_ERROR;
853 
854  pfree(passwd);
855 
856  return result;
857 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:623
int errcode(int sqlerrcode)
Definition: elog.c:694
#define STATUS_ERROR
Definition: c.h:1171
#define LOG
Definition: elog.h:26
#define AUTH_REQ_MD5
Definition: pqcomm.h:156
void pfree(void *pointer)
Definition: mcxt.c:1057
#define FATAL
Definition: elog.h:54
bool Db_user_namespace
Definition: postmaster.c:240
char * user_name
Definition: libpq-be.h:141
static char * recv_password_packet(Port *port)
Definition: auth.c:653
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, char **logdetail)
Definition: crypt.c:166
#define ereport(elevel,...)
Definition: elog.h:155
bool pg_strong_random(void *buf, size_t len)
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define STATUS_EOF
Definition: c.h:1172

◆ CheckPasswordAuth()

static int CheckPasswordAuth ( Port port,
char **  logdetail 
)
static

Definition at line 735 of file auth.c.

References AUTH_REQ_PASSWORD, get_role_password(), pfree(), plain_crypt_verify(), recv_password_packet(), sendAuthRequest(), STATUS_EOF, STATUS_ERROR, and Port::user_name.

Referenced by ClientAuthentication().

736 {
737  char *passwd;
738  int result;
739  char *shadow_pass;
740 
741  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
742 
743  passwd = recv_password_packet(port);
744  if (passwd == NULL)
745  return STATUS_EOF; /* client wouldn't send password */
746 
747  shadow_pass = get_role_password(port->user_name, logdetail);
748  if (shadow_pass)
749  {
750  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
751  logdetail);
752  }
753  else
754  result = STATUS_ERROR;
755 
756  if (shadow_pass)
757  pfree(shadow_pass);
758  pfree(passwd);
759 
760  return result;
761 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:623
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:222
#define STATUS_ERROR
Definition: c.h:1171
void pfree(void *pointer)
Definition: mcxt.c:1057
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:37
char * user_name
Definition: libpq-be.h:141
static char * recv_password_packet(Port *port)
Definition: auth.c:653
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:154
#define STATUS_EOF
Definition: c.h:1172

◆ CheckPWChallengeAuth()

static int CheckPWChallengeAuth ( Port port,
char **  logdetail 
)
static

Definition at line 767 of file auth.c.

References Assert, HbaLine::auth_method, CheckMD5Auth(), CheckSCRAMAuth(), get_password_type(), get_role_password(), Port::hba, Password_encryption, PASSWORD_TYPE_MD5, pfree(), STATUS_ERROR, STATUS_OK, uaMD5, uaSCRAM, and Port::user_name.

Referenced by ClientAuthentication().

768 {
769  int auth_result;
770  char *shadow_pass;
771  PasswordType pwtype;
772 
773  Assert(port->hba->auth_method == uaSCRAM ||
774  port->hba->auth_method == uaMD5);
775 
776  /* First look up the user's password. */
777  shadow_pass = get_role_password(port->user_name, logdetail);
778 
779  /*
780  * If the user does not exist, or has no password or it's expired, we
781  * still go through the motions of authentication, to avoid revealing to
782  * the client that the user didn't exist. If 'md5' is allowed, we choose
783  * whether to use 'md5' or 'scram-sha-256' authentication based on current
784  * password_encryption setting. The idea is that most genuine users
785  * probably have a password of that type, and if we pretend that this user
786  * had a password of that type, too, it "blends in" best.
787  */
788  if (!shadow_pass)
789  pwtype = Password_encryption;
790  else
791  pwtype = get_password_type(shadow_pass);
792 
793  /*
794  * If 'md5' authentication is allowed, decide whether to perform 'md5' or
795  * 'scram-sha-256' authentication based on the type of password the user
796  * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
797  * SCRAM secret, we must do SCRAM authentication.
798  *
799  * If MD5 authentication is not allowed, always use SCRAM. If the user
800  * had an MD5 password, CheckSCRAMAuth() will fail.
801  */
802  if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
803  auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
804  else
805  auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
806 
807  if (shadow_pass)
808  pfree(shadow_pass);
809 
810  /*
811  * If get_role_password() returned error, return error, even if the
812  * authentication succeeded.
813  */
814  if (!shadow_pass)
815  {
816  Assert(auth_result != STATUS_OK);
817  return STATUS_ERROR;
818  }
819  return auth_result;
820 }
Definition: hba.h:32
int Password_encryption
Definition: user.c:46
#define STATUS_ERROR
Definition: c.h:1171
void pfree(void *pointer)
Definition: mcxt.c:1057
static int CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:860
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:37
char * user_name
Definition: libpq-be.h:141
#define STATUS_OK
Definition: c.h:1170
HbaLine * hba
Definition: libpq-be.h:155
static int CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:823
Definition: hba.h:33
PasswordType
Definition: crypt.h:27
#define Assert(condition)
Definition: c.h:804
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:89
UserAuth auth_method
Definition: hba.h:87

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

Definition at line 2914 of file auth.c.

References Assert, AUTH_REQ_PASSWORD, ereport, errmsg(), Port::hba, lfirst, list_head(), list_length(), lnext(), LOG, offsetof, PerformRadiusTransaction(), pfree(), RADIUS_MAX_PASSWORD_LENGTH, HbaLine::radiusidentifiers, HbaLine::radiusports, HbaLine::radiussecrets, HbaLine::radiusservers, recv_password_packet(), sendAuthRequest(), STATUS_EOF, STATUS_ERROR, STATUS_OK, and Port::user_name.

Referenced by ClientAuthentication().

2915 {
2916  char *passwd;
2917  ListCell *server,
2918  *secrets,
2919  *radiusports,
2920  *identifiers;
2921 
2922  /* Make sure struct alignment is correct */
2923  Assert(offsetof(radius_packet, vector) == 4);
2924 
2925  /* Verify parameters */
2926  if (list_length(port->hba->radiusservers) < 1)
2927  {
2928  ereport(LOG,
2929  (errmsg("RADIUS server not specified")));
2930  return STATUS_ERROR;
2931  }
2932 
2933  if (list_length(port->hba->radiussecrets) < 1)
2934  {
2935  ereport(LOG,
2936  (errmsg("RADIUS secret not specified")));
2937  return STATUS_ERROR;
2938  }
2939 
2940  /* Send regular password request to client, and get the response */
2941  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
2942 
2943  passwd = recv_password_packet(port);
2944  if (passwd == NULL)
2945  return STATUS_EOF; /* client wouldn't send password */
2946 
2947  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2948  {
2949  ereport(LOG,
2950  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2951  pfree(passwd);
2952  return STATUS_ERROR;
2953  }
2954 
2955  /*
2956  * Loop over and try each server in order.
2957  */
2958  secrets = list_head(port->hba->radiussecrets);
2959  radiusports = list_head(port->hba->radiusports);
2960  identifiers = list_head(port->hba->radiusidentifiers);
2961  foreach(server, port->hba->radiusservers)
2962  {
2963  int ret = PerformRadiusTransaction(lfirst(server),
2964  lfirst(secrets),
2965  radiusports ? lfirst(radiusports) : NULL,
2966  identifiers ? lfirst(identifiers) : NULL,
2967  port->user_name,
2968  passwd);
2969 
2970  /*------
2971  * STATUS_OK = Login OK
2972  * STATUS_ERROR = Login not OK, but try next server
2973  * STATUS_EOF = Login not OK, and don't try next server
2974  *------
2975  */
2976  if (ret == STATUS_OK)
2977  {
2978  pfree(passwd);
2979  return STATUS_OK;
2980  }
2981  else if (ret == STATUS_EOF)
2982  {
2983  pfree(passwd);
2984  return STATUS_ERROR;
2985  }
2986 
2987  /*
2988  * secret, port and identifiers either have length 0 (use default),
2989  * length 1 (use the same everywhere) or the same length as servers.
2990  * So if the length is >1, we advance one step. In other cases, we
2991  * don't and will then reuse the correct value.
2992  */
2993  if (list_length(port->hba->radiussecrets) > 1)
2994  secrets = lnext(port->hba->radiussecrets, secrets);
2995  if (list_length(port->hba->radiusports) > 1)
2996  radiusports = lnext(port->hba->radiusports, radiusports);
2997  if (list_length(port->hba->radiusidentifiers) > 1)
2998  identifiers = lnext(port->hba->radiusidentifiers, identifiers);
2999  }
3000 
3001  /* No servers left to try, so give up */
3002  pfree(passwd);
3003  return STATUS_ERROR;
3004 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:623
#define STATUS_ERROR
Definition: c.h:1171
#define LOG
Definition: elog.h:26
List * radiussecrets
Definition: hba.h:110
static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
Definition: auth.c:3007
void pfree(void *pointer)
Definition: mcxt.c:1057
List * radiusports
Definition: hba.h:114
List * radiusservers
Definition: hba.h:108
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
char * user_name
Definition: libpq-be.h:141
#define STATUS_OK
Definition: c.h:1170
static char * recv_password_packet(Port *port)
Definition: auth.c:653
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:154
HbaLine * hba
Definition: libpq-be.h:155
List * radiusidentifiers
Definition: hba.h:112
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2848
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define STATUS_EOF
Definition: c.h:1172
#define offsetof(type, field)
Definition: c.h:727

◆ CheckSCRAMAuth()

static int CheckSCRAMAuth ( Port port,
char *  shadow_pass,
char **  logdetail 
)
static

Definition at line 860 of file auth.c.

References _, appendStringInfoChar(), Assert, AUTH_REQ_GSS_CONT, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, buf, CHECK_FOR_INTERRUPTS, check_usermap(), HbaLine::compat_realm, StringInfoData::data, DEBUG2, DEBUG4, DEBUG5, elog, ereport, errcode(), errdetail_internal(), errmsg(), errmsg_internal(), ERROR, FATAL, free, Port::gss, Port::hba, HbaLine::include_realm, initStringInfo(), HbaLine::krb_realm, StringInfoData::len, LOG, malloc, MAXPGPATH, MemoryContextStrdup(), output(), palloc(), pfree(), pg_be_scram_exchange(), pg_be_scram_get_mechanisms(), pg_be_scram_init(), pg_GSS_error(), pg_krb_caseins_users, pg_krb_server_keyfile, PG_MAX_AUTH_TOKEN_LENGTH, PG_MAX_SASL_MESSAGE_LENGTH, pg_strcasecmp(), port, pq_getbyte(), pq_getmessage(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), pq_getmsgrawstring(), pq_startmsgread(), psprintf(), SASL_EXCHANGE_CONTINUE, SASL_EXCHANGE_SUCCESS, sendAuthRequest(), setenv, status(), STATUS_EOF, STATUS_ERROR, STATUS_OK, TopMemoryContext, HbaLine::upn_username, Port::user_name, and HbaLine::usermap.

Referenced by CheckPWChallengeAuth().

861 {
862  StringInfoData sasl_mechs;
863  int mtype;
865  void *scram_opaq = NULL;
866  char *output = NULL;
867  int outputlen = 0;
868  const char *input;
869  int inputlen;
870  int result;
871  bool initial;
872 
873  /*
874  * Send the SASL authentication request to user. It includes the list of
875  * authentication mechanisms that are supported.
876  */
877  initStringInfo(&sasl_mechs);
878 
879  pg_be_scram_get_mechanisms(port, &sasl_mechs);
880  /* Put another '\0' to mark that list is finished. */
881  appendStringInfoChar(&sasl_mechs, '\0');
882 
883  sendAuthRequest(port, AUTH_REQ_SASL, sasl_mechs.data, sasl_mechs.len);
884  pfree(sasl_mechs.data);
885 
886  /*
887  * Loop through SASL message exchange. This exchange can consist of
888  * multiple messages sent in both directions. First message is always
889  * from the client. All messages from client to server are password
890  * packets (type 'p').
891  */
892  initial = true;
893  do
894  {
895  pq_startmsgread();
896  mtype = pq_getbyte();
897  if (mtype != 'p')
898  {
899  /* Only log error if client didn't disconnect. */
900  if (mtype != EOF)
901  {
902  ereport(ERROR,
903  (errcode(ERRCODE_PROTOCOL_VIOLATION),
904  errmsg("expected SASL response, got message type %d",
905  mtype)));
906  }
907  else
908  return STATUS_EOF;
909  }
910 
911  /* Get the actual SASL message */
912  initStringInfo(&buf);
914  {
915  /* EOF - pq_getmessage already logged error */
916  pfree(buf.data);
917  return STATUS_ERROR;
918  }
919 
920  elog(DEBUG4, "processing received SASL response of length %d", buf.len);
921 
922  /*
923  * The first SASLInitialResponse message is different from the others.
924  * It indicates which SASL mechanism the client selected, and contains
925  * an optional Initial Client Response payload. The subsequent
926  * SASLResponse messages contain just the SASL payload.
927  */
928  if (initial)
929  {
930  const char *selected_mech;
931 
932  selected_mech = pq_getmsgrawstring(&buf);
933 
934  /*
935  * Initialize the status tracker for message exchanges.
936  *
937  * If the user doesn't exist, or doesn't have a valid password, or
938  * it's expired, we still go through the motions of SASL
939  * authentication, but tell the authentication method that the
940  * authentication is "doomed". That is, it's going to fail, no
941  * matter what.
942  *
943  * This is because we don't want to reveal to an attacker what
944  * usernames are valid, nor which users have a valid password.
945  */
946  scram_opaq = pg_be_scram_init(port, selected_mech, shadow_pass);
947 
948  inputlen = pq_getmsgint(&buf, 4);
949  if (inputlen == -1)
950  input = NULL;
951  else
952  input = pq_getmsgbytes(&buf, inputlen);
953 
954  initial = false;
955  }
956  else
957  {
958  inputlen = buf.len;
959  input = pq_getmsgbytes(&buf, buf.len);
960  }
961  pq_getmsgend(&buf);
962 
963  /*
964  * The StringInfo guarantees that there's a \0 byte after the
965  * response.
966  */
967  Assert(input == NULL || input[inputlen] == '\0');
968 
969  /*
970  * we pass 'logdetail' as NULL when doing a mock authentication,
971  * because we should already have a better error message in that case
972  */
973  result = pg_be_scram_exchange(scram_opaq, input, inputlen,
974  &output, &outputlen,
975  logdetail);
976 
977  /* input buffer no longer used */
978  pfree(buf.data);
979 
980  if (output)
981  {
982  /*
983  * Negotiation generated data to be sent to the client.
984  */
985  elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
986 
987  if (result == SASL_EXCHANGE_SUCCESS)
988  sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
989  else
990  sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
991 
992  pfree(output);
993  }
994  } while (result == SASL_EXCHANGE_CONTINUE);
995 
996  /* Oops, Something bad happened */
997  if (result != SASL_EXCHANGE_SUCCESS)
998  {
999  return STATUS_ERROR;
1000  }
1001 
1002  return STATUS_OK;
1003 }
void pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
Definition: auth-scram.c:181
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:623
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:163
static void output(uint64 loop_count)
#define SASL_EXCHANGE_SUCCESS
Definition: scram.h:21
int errcode(int sqlerrcode)
Definition: elog.c:694
#define STATUS_ERROR
Definition: c.h:1171
const char * pq_getmsgrawstring(StringInfo msg)
Definition: pqformat.c:610
#define DEBUG4
Definition: elog.h:22
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:510
void * pg_be_scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
Definition: auth-scram.c:218
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
void pq_startmsgread(void)
Definition: pqcomm.c:1147
static char * buf
Definition: pg_test_fsync.c:68
#define STATUS_OK
Definition: c.h:1170
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1209
int pg_be_scram_exchange(void *opaq, const char *input, int inputlen, char **output, int *outputlen, char **logdetail)
Definition: auth-scram.c:328
int pq_getbyte(void)
Definition: pqcomm.c:989
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:162
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:804
#define PG_MAX_SASL_MESSAGE_LENGTH
Definition: auth.c:229
#define AUTH_REQ_SASL
Definition: pqcomm.h:161
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define elog(elevel,...)
Definition: elog.h:227
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:637
#define SASL_EXCHANGE_CONTINUE
Definition: scram.h:20
#define STATUS_EOF
Definition: c.h:1172

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 345 of file auth.c.

References _, SockAddr::addr, am_db_walsender, am_walsender, Assert, auth_failed(), HbaLine::auth_method, auth_peer(), AUTH_REQ_GSS, AUTH_REQ_OK, AUTH_REQ_SSPI, CHECK_FOR_INTERRUPTS, CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), ClientAuthentication_hook, HbaLine::clientcert, clientCertFull, clientCertOff, Port::database_name, ereport, errcode(), errmsg(), FATAL, Port::gss, Port::hba, hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), MemoryContextAllocZero(), NI_MAXHOST, NI_NUMERICHOST, Port::peer_cert_valid, pg_getnameinfo_all(), port, Port::raddr, SockAddr::salen, secure_loaded_verify_locations(), sendAuthRequest(), Port::ssl_in_use, status(), STATUS_ERROR, STATUS_OK, TopMemoryContext, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaRADIUS, uaReject, uaSCRAM, uaSSPI, uaTrust, and Port::user_name.

Referenced by PerformAuthentication().

346 {
347  int status = STATUS_ERROR;
348  char *logdetail = NULL;
349 
350  /*
351  * Get the authentication method to use for this frontend/database
352  * combination. Note: we do not parse the file at this point; this has
353  * already been done elsewhere. hba.c dropped an error message into the
354  * server logfile if parsing the hba config file failed.
355  */
356  hba_getauthmethod(port);
357 
359 
360  /*
361  * This is the first point where we have access to the hba record for the
362  * current connection, so perform any verifications based on the hba
363  * options field that should be done *before* the authentication here.
364  */
365  if (port->hba->clientcert != clientCertOff)
366  {
367  /* If we haven't loaded a root certificate store, fail */
369  ereport(FATAL,
370  (errcode(ERRCODE_CONFIG_FILE_ERROR),
371  errmsg("client certificates can only be checked if a root certificate store is available")));
372 
373  /*
374  * If we loaded a root certificate store, and if a certificate is
375  * present on the client, then it has been verified against our root
376  * certificate store, and the connection would have been aborted
377  * already if it didn't verify ok.
378  */
379  if (!port->peer_cert_valid)
380  ereport(FATAL,
381  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
382  errmsg("connection requires a valid client certificate")));
383  }
384 
385  /*
386  * Now proceed to do the actual authentication check
387  */
388  switch (port->hba->auth_method)
389  {
390  case uaReject:
391 
392  /*
393  * An explicit "reject" entry in pg_hba.conf. This report exposes
394  * the fact that there's an explicit reject entry, which is
395  * perhaps not so desirable from a security standpoint; but the
396  * message for an implicit reject could confuse the DBA a lot when
397  * the true situation is a match to an explicit reject. And we
398  * don't want to change the message for an implicit reject. As
399  * noted below, the additional information shown here doesn't
400  * expose anything not known to an attacker.
401  */
402  {
403  char hostinfo[NI_MAXHOST];
404  const char *encryption_state;
405 
406  pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
407  hostinfo, sizeof(hostinfo),
408  NULL, 0,
410 
411  encryption_state =
412 #ifdef ENABLE_GSS
413  (port->gss && port->gss->enc) ? _("GSS encryption") :
414 #endif
415 #ifdef USE_SSL
416  port->ssl_in_use ? _("SSL encryption") :
417 #endif
418  _("no encryption");
419 
421  ereport(FATAL,
422  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
423  /* translator: last %s describes encryption state */
424  errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
425  hostinfo, port->user_name,
426  encryption_state)));
427  else
428  ereport(FATAL,
429  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
430  /* translator: last %s describes encryption state */
431  errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
432  hostinfo, port->user_name,
433  port->database_name,
434  encryption_state)));
435  break;
436  }
437 
438  case uaImplicitReject:
439 
440  /*
441  * No matching entry, so tell the user we fell through.
442  *
443  * NOTE: the extra info reported here is not a security breach,
444  * because all that info is known at the frontend and must be
445  * assumed known to bad guys. We're merely helping out the less
446  * clueful good guys.
447  */
448  {
449  char hostinfo[NI_MAXHOST];
450  const char *encryption_state;
451 
452  pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
453  hostinfo, sizeof(hostinfo),
454  NULL, 0,
456 
457  encryption_state =
458 #ifdef ENABLE_GSS
459  (port->gss && port->gss->enc) ? _("GSS encryption") :
460 #endif
461 #ifdef USE_SSL
462  port->ssl_in_use ? _("SSL encryption") :
463 #endif
464  _("no encryption");
465 
466 #define HOSTNAME_LOOKUP_DETAIL(port) \
467  (port->remote_hostname ? \
468  (port->remote_hostname_resolv == +1 ? \
469  errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
470  port->remote_hostname) : \
471  port->remote_hostname_resolv == 0 ? \
472  errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
473  port->remote_hostname) : \
474  port->remote_hostname_resolv == -1 ? \
475  errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
476  port->remote_hostname) : \
477  port->remote_hostname_resolv == -2 ? \
478  errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
479  port->remote_hostname, \
480  gai_strerror(port->remote_hostname_errcode)) : \
481  0) \
482  : (port->remote_hostname_resolv == -2 ? \
483  errdetail_log("Could not resolve client IP address to a host name: %s.", \
484  gai_strerror(port->remote_hostname_errcode)) : \
485  0))
486 
488  ereport(FATAL,
489  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
490  /* translator: last %s describes encryption state */
491  errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
492  hostinfo, port->user_name,
493  encryption_state),
494  HOSTNAME_LOOKUP_DETAIL(port)));
495  else
496  ereport(FATAL,
497  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
498  /* translator: last %s describes encryption state */
499  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
500  hostinfo, port->user_name,
501  port->database_name,
502  encryption_state),
503  HOSTNAME_LOOKUP_DETAIL(port)));
504  break;
505  }
506 
507  case uaGSS:
508 #ifdef ENABLE_GSS
509  /* We might or might not have the gss workspace already */
510  if (port->gss == NULL)
511  port->gss = (pg_gssinfo *)
513  sizeof(pg_gssinfo));
514  port->gss->auth = true;
515 
516  /*
517  * If GSS state was set up while enabling encryption, we can just
518  * check the client's principal. Otherwise, ask for it.
519  */
520  if (port->gss->enc)
521  status = pg_GSS_checkauth(port);
522  else
523  {
524  sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
525  status = pg_GSS_recvauth(port);
526  }
527 #else
528  Assert(false);
529 #endif
530  break;
531 
532  case uaSSPI:
533 #ifdef ENABLE_SSPI
534  if (port->gss == NULL)
535  port->gss = (pg_gssinfo *)
537  sizeof(pg_gssinfo));
538  sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
539  status = pg_SSPI_recvauth(port);
540 #else
541  Assert(false);
542 #endif
543  break;
544 
545  case uaPeer:
546  status = auth_peer(port);
547  break;
548 
549  case uaIdent:
550  status = ident_inet(port);
551  break;
552 
553  case uaMD5:
554  case uaSCRAM:
555  status = CheckPWChallengeAuth(port, &logdetail);
556  break;
557 
558  case uaPassword:
559  status = CheckPasswordAuth(port, &logdetail);
560  break;
561 
562  case uaPAM:
563 #ifdef USE_PAM
564  status = CheckPAMAuth(port, port->user_name, "");
565 #else
566  Assert(false);
567 #endif /* USE_PAM */
568  break;
569 
570  case uaBSD:
571 #ifdef USE_BSD_AUTH
572  status = CheckBSDAuth(port, port->user_name);
573 #else
574  Assert(false);
575 #endif /* USE_BSD_AUTH */
576  break;
577 
578  case uaLDAP:
579 #ifdef USE_LDAP
580  status = CheckLDAPAuth(port);
581 #else
582  Assert(false);
583 #endif
584  break;
585  case uaRADIUS:
586  status = CheckRADIUSAuth(port);
587  break;
588  case uaCert:
589  /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
590  case uaTrust:
591  status = STATUS_OK;
592  break;
593  }
594 
595  if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
596  || port->hba->auth_method == uaCert)
597  {
598  /*
599  * Make sure we only check the certificate if we use the cert method
600  * or verify-full option.
601  */
602 #ifdef USE_SSL
603  status = CheckCertAuth(port);
604 #else
605  Assert(false);
606 #endif
607  }
608 
610  (*ClientAuthentication_hook) (port, status);
611 
612  if (status == STATUS_OK)
613  sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
614  else
615  auth_failed(port, status, logdetail);
616 }
#define HOSTNAME_LOOKUP_DETAIL(port)
Definition: hba.h:30
#define AUTH_REQ_SSPI
Definition: pqcomm.h:160
static int auth_peer(hbaPort *port)
Definition: auth.c:1923
Definition: hba.h:38
#define NI_NUMERICHOST
Definition: getaddrinfo.h:78
Definition: hba.h:32
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:623
#define AUTH_REQ_OK
Definition: pqcomm.h:151
#define AUTH_REQ_GSS
Definition: pqcomm.h:158
Definition: hba.h:35
bool peer_cert_valid
Definition: libpq-be.h:193
struct sockaddr_storage addr
Definition: pqcomm.h:64
int errcode(int sqlerrcode)
Definition: elog.c:694
#define STATUS_ERROR
Definition: c.h:1171
bool ssl_in_use
Definition: libpq-be.h:191
static int CheckRADIUSAuth(Port *port)
Definition: auth.c:2914
Definition: hba.h:34
Definition: hba.h:31
SockAddr raddr
Definition: libpq-be.h:126
bool am_walsender
Definition: walsender.c:115
#define NI_MAXHOST
Definition: getaddrinfo.h:88
Definition: hba.h:39
static int CheckPWChallengeAuth(Port *port, char **logdetail)
Definition: auth.c:767
#define FATAL
Definition: elog.h:54
Definition: hba.h:27
Definition: hba.h:29
void hba_getauthmethod(hbaPort *port)
Definition: hba.c:3109
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:241
char * user_name
Definition: libpq-be.h:141
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define STATUS_OK
Definition: c.h:1170
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static int port
Definition: pg_regress.c:92
HbaLine * hba
Definition: libpq-be.h:155
static int ident_inet(hbaPort *port)
Definition: auth.c:1745
Definition: hba.h:33
bool am_db_walsender
Definition: walsender.c:118
static int CheckPasswordAuth(Port *port, char **logdetail)
Definition: auth.c:735
Definition: hba.h:37
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:804
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
ClientCertMode clientcert
Definition: hba.h:103
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:102
void * gss
Definition: libpq-be.h:185
int errmsg(const char *fmt,...)
Definition: elog.c:905
static void auth_failed(Port *port, int status, char *logdetail)
Definition: auth.c:257
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:100
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
char * database_name
Definition: libpq-be.h:140
Definition: hba.h:36
#define _(x)
Definition: elog.c:89
Definition: hba.h:40
UserAuth auth_method
Definition: hba.h:87

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1745 of file auth.c.

References SockAddr::addr, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, bind, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, EINTR, ereport, errcode_for_socket_access(), errmsg(), Port::hba, IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), Port::laddr, LOG, NI_MAXHOST, NI_MAXSERV, NI_NUMERICHOST, NI_NUMERICSERV, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, Port::raddr, recv, SockAddr::salen, send, snprintf, socket, STATUS_ERROR, Port::user_name, and HbaLine::usermap.

Referenced by ClientAuthentication().

1746 {
1747  const SockAddr remote_addr = port->raddr;
1748  const SockAddr local_addr = port->laddr;
1749  char ident_user[IDENT_USERNAME_MAX + 1];
1750  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1751  int rc; /* Return code from a locally called function */
1752  bool ident_return;
1753  char remote_addr_s[NI_MAXHOST];
1754  char remote_port[NI_MAXSERV];
1755  char local_addr_s[NI_MAXHOST];
1756  char local_port[NI_MAXSERV];
1757  char ident_port[NI_MAXSERV];
1758  char ident_query[80];
1759  char ident_response[80 + IDENT_USERNAME_MAX];
1760  struct addrinfo *ident_serv = NULL,
1761  *la = NULL,
1762  hints;
1763 
1764  /*
1765  * Might look a little weird to first convert it to text and then back to
1766  * sockaddr, but it's protocol independent.
1767  */
1768  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1769  remote_addr_s, sizeof(remote_addr_s),
1770  remote_port, sizeof(remote_port),
1772  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1773  local_addr_s, sizeof(local_addr_s),
1774  local_port, sizeof(local_port),
1776 
1777  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1778  hints.ai_flags = AI_NUMERICHOST;
1779  hints.ai_family = remote_addr.addr.ss_family;
1780  hints.ai_socktype = SOCK_STREAM;
1781  hints.ai_protocol = 0;
1782  hints.ai_addrlen = 0;
1783  hints.ai_canonname = NULL;
1784  hints.ai_addr = NULL;
1785  hints.ai_next = NULL;
1786  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1787  if (rc || !ident_serv)
1788  {
1789  /* we don't expect this to happen */
1790  ident_return = false;
1791  goto ident_inet_done;
1792  }
1793 
1794  hints.ai_flags = AI_NUMERICHOST;
1795  hints.ai_family = local_addr.addr.ss_family;
1796  hints.ai_socktype = SOCK_STREAM;
1797  hints.ai_protocol = 0;
1798  hints.ai_addrlen = 0;
1799  hints.ai_canonname = NULL;
1800  hints.ai_addr = NULL;
1801  hints.ai_next = NULL;
1802  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1803  if (rc || !la)
1804  {
1805  /* we don't expect this to happen */
1806  ident_return = false;
1807  goto ident_inet_done;
1808  }
1809 
1810  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1811  ident_serv->ai_protocol);
1812  if (sock_fd == PGINVALID_SOCKET)
1813  {
1814  ereport(LOG,
1816  errmsg("could not create socket for Ident connection: %m")));
1817  ident_return = false;
1818  goto ident_inet_done;
1819  }
1820 
1821  /*
1822  * Bind to the address which the client originally contacted, otherwise
1823  * the ident server won't be able to match up the right connection. This
1824  * is necessary if the PostgreSQL server is running on an IP alias.
1825  */
1826  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1827  if (rc != 0)
1828  {
1829  ereport(LOG,
1831  errmsg("could not bind to local address \"%s\": %m",
1832  local_addr_s)));
1833  ident_return = false;
1834  goto ident_inet_done;
1835  }
1836 
1837  rc = connect(sock_fd, ident_serv->ai_addr,
1838  ident_serv->ai_addrlen);
1839  if (rc != 0)
1840  {
1841  ereport(LOG,
1843  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1844  remote_addr_s, ident_port)));
1845  ident_return = false;
1846  goto ident_inet_done;
1847  }
1848 
1849  /* The query we send to the Ident server */
1850  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1851  remote_port, local_port);
1852 
1853  /* loop in case send is interrupted */
1854  do
1855  {
1857 
1858  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1859  } while (rc < 0 && errno == EINTR);
1860 
1861  if (rc < 0)
1862  {
1863  ereport(LOG,
1865  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1866  remote_addr_s, ident_port)));
1867  ident_return = false;
1868  goto ident_inet_done;
1869  }
1870 
1871  do
1872  {
1874 
1875  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1876  } while (rc < 0 && errno == EINTR);
1877 
1878  if (rc < 0)
1879  {
1880  ereport(LOG,
1882  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1883  remote_addr_s, ident_port)));
1884  ident_return = false;
1885  goto ident_inet_done;
1886  }
1887 
1888  ident_response[rc] = '\0';
1889  ident_return = interpret_ident_response(ident_response, ident_user);
1890  if (!ident_return)
1891  ereport(LOG,
1892  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1893  ident_response)));
1894 
1895 ident_inet_done:
1896  if (sock_fd != PGINVALID_SOCKET)
1897  closesocket(sock_fd);
1898  if (ident_serv)
1899  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1900  if (la)
1901  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1902 
1903  if (ident_return)
1904  /* Success! Check the usermap */
1905  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1906  return STATUS_ERROR;
1907 }
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:88
#define NI_NUMERICHOST
Definition: getaddrinfo.h:78
#define closesocket
Definition: port.h:332
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define STATUS_ERROR
Definition: c.h:1171
#define connect(s, name, namelen)
Definition: win32_port.h:463
#define LOG
Definition: elog.h:26
#define AI_NUMERICHOST
Definition: getaddrinfo.h:73
#define bind(s, addr, addrlen)
Definition: win32_port.h:460
#define recv(s, buf, len, flags)
Definition: win32_port.h:465
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:57
SockAddr raddr
Definition: libpq-be.h:126
#define IDENT_USERNAME_MAX
Definition: auth.c:68
#define NI_MAXHOST
Definition: getaddrinfo.h:88
char * usermap
Definition: hba.h:88
#define IDENT_PORT
Definition: auth.c:71
#define NI_MAXSERV
Definition: getaddrinfo.h:91
char * user_name
Definition: libpq-be.h:141
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
int errcode_for_socket_access(void)
Definition: elog.c:788
SockAddr laddr
Definition: libpq-be.h:125
HbaLine * hba
Definition: libpq-be.h:155
#define socket(af, type, protocol)
Definition: win32_port.h:459
#define PGINVALID_SOCKET
Definition: port.h:33
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2943
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
#define ereport(elevel,...)
Definition: elog.h:155
int ai_protocol
Definition: getaddrinfo.h:103
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
int ai_socktype
Definition: getaddrinfo.h:102
int errmsg(const char *fmt,...)
Definition: elog.c:905
size_t ai_addrlen
Definition: getaddrinfo.h:104
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:100
#define EINTR
Definition: win32_port.h:343
#define snprintf
Definition: port.h:216
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1662
struct sockaddr * ai_addr
Definition: getaddrinfo.h:105
#define send(s, buf, len, flags)
Definition: win32_port.h:466
int ai_family
Definition: getaddrinfo.h:101

◆ interpret_ident_response()

static bool interpret_ident_response ( const char *  ident_response,
char *  ident_user 
)
static

Definition at line 1662 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1664 {
1665  const char *cursor = ident_response; /* Cursor into *ident_response */
1666 
1667  /*
1668  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1669  */
1670  if (strlen(ident_response) < 2)
1671  return false;
1672  else if (ident_response[strlen(ident_response) - 2] != '\r')
1673  return false;
1674  else
1675  {
1676  while (*cursor != ':' && *cursor != '\r')
1677  cursor++; /* skip port field */
1678 
1679  if (*cursor != ':')
1680  return false;
1681  else
1682  {
1683  /* We're positioned to colon before response type field */
1684  char response_type[80];
1685  int i; /* Index into *response_type */
1686 
1687  cursor++; /* Go over colon */
1688  while (pg_isblank(*cursor))
1689  cursor++; /* skip blanks */
1690  i = 0;
1691  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1692  i < (int) (sizeof(response_type) - 1))
1693  response_type[i++] = *cursor++;
1694  response_type[i] = '\0';
1695  while (pg_isblank(*cursor))
1696  cursor++; /* skip blanks */
1697  if (strcmp(response_type, "USERID") != 0)
1698  return false;
1699  else
1700  {
1701  /*
1702  * It's a USERID response. Good. "cursor" should be pointing
1703  * to the colon that precedes the operating system type.
1704  */
1705  if (*cursor != ':')
1706  return false;
1707  else
1708  {
1709  cursor++; /* Go over colon */
1710  /* Skip over operating system field. */
1711  while (*cursor != ':' && *cursor != '\r')
1712  cursor++;
1713  if (*cursor != ':')
1714  return false;
1715  else
1716  {
1717  int i; /* Index into *ident_user */
1718 
1719  cursor++; /* Go over colon */
1720  while (pg_isblank(*cursor))
1721  cursor++; /* skip blanks */
1722  /* Rest of line is user name. Copy it over. */
1723  i = 0;
1724  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1725  ident_user[i++] = *cursor++;
1726  ident_user[i] = '\0';
1727  return true;
1728  }
1729  }
1730  }
1731  }
1732  }
1733 }
bool pg_isblank(const char c)
Definition: hba.c:160
#define IDENT_USERNAME_MAX
Definition: auth.c:68
Definition: type.h:130
int i

◆ PerformRadiusTransaction()

static int PerformRadiusTransaction ( const char *  server,
const char *  secret,
const char *  portstr,
const char *  identifier,
const char *  user_name,
const char *  passwd 
)
static

Definition at line 3007 of file auth.c.

References addrinfo::ai_family, addrinfo::ai_socktype, bind, closesocket, radius_packet::code, EINTR, ereport, errmsg(), gai_strerror, gettimeofday(), i, radius_packet::id, radius_packet::length, LOG, MemSet, palloc(), pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_hton16, pg_hton32, pg_md5_binary(), pg_ntoh16, pg_strong_random(), PGINVALID_SOCKET, port, RADIUS_ACCESS_ACCEPT, RADIUS_ACCESS_REJECT, RADIUS_ACCESS_REQUEST, radius_add_attribute(), RADIUS_AUTHENTICATE_ONLY, RADIUS_BUFFER_SIZE, RADIUS_HEADER_LENGTH, RADIUS_MAX_PASSWORD_LENGTH, RADIUS_NAS_IDENTIFIER, RADIUS_PASSWORD, RADIUS_SERVICE_TYPE, RADIUS_TIMEOUT, RADIUS_USER_NAME, RADIUS_VECTOR_LENGTH, select, socket, STATUS_EOF, STATUS_ERROR, STATUS_OK, and radius_packet::vector.

Referenced by CheckRADIUSAuth().

3008 {
3009  radius_packet radius_send_pack;
3010  radius_packet radius_recv_pack;
3011  radius_packet *packet = &radius_send_pack;
3012  radius_packet *receivepacket = &radius_recv_pack;
3013  char *radius_buffer = (char *) &radius_send_pack;
3014  char *receive_buffer = (char *) &radius_recv_pack;
3016  uint8 *cryptvector;
3017  int encryptedpasswordlen;
3018  uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
3019  uint8 *md5trailer;
3020  int packetlength;
3021  pgsocket sock;
3022 
3023 #ifdef HAVE_IPV6
3024  struct sockaddr_in6 localaddr;
3025  struct sockaddr_in6 remoteaddr;
3026 #else
3027  struct sockaddr_in localaddr;
3028  struct sockaddr_in remoteaddr;
3029 #endif
3030  struct addrinfo hint;
3031  struct addrinfo *serveraddrs;
3032  int port;
3033  ACCEPT_TYPE_ARG3 addrsize;
3034  fd_set fdset;
3035  struct timeval endtime;
3036  int i,
3037  j,
3038  r;
3039 
3040  /* Assign default values */
3041  if (portstr == NULL)
3042  portstr = "1812";
3043  if (identifier == NULL)
3044  identifier = "postgresql";
3045 
3046  MemSet(&hint, 0, sizeof(hint));
3047  hint.ai_socktype = SOCK_DGRAM;
3048  hint.ai_family = AF_UNSPEC;
3049  port = atoi(portstr);
3050 
3051  r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
3052  if (r || !serveraddrs)
3053  {
3054  ereport(LOG,
3055  (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
3056  server, gai_strerror(r))));
3057  if (serveraddrs)
3058  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3059  return STATUS_ERROR;
3060  }
3061  /* XXX: add support for multiple returned addresses? */
3062 
3063  /* Construct RADIUS packet */
3064  packet->code = RADIUS_ACCESS_REQUEST;
3065  packet->length = RADIUS_HEADER_LENGTH;
3067  {
3068  ereport(LOG,
3069  (errmsg("could not generate random encryption vector")));
3070  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3071  return STATUS_ERROR;
3072  }
3073  packet->id = packet->vector[0];
3074  radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
3075  radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
3076  radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
3077 
3078  /*
3079  * RADIUS password attributes are calculated as: e[0] = p[0] XOR
3080  * MD5(secret + Request Authenticator) for the first group of 16 octets,
3081  * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
3082  * (if necessary)
3083  */
3084  encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
3085  cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
3086  memcpy(cryptvector, secret, strlen(secret));
3087 
3088  /* for the first iteration, we use the Request Authenticator vector */
3089  md5trailer = packet->vector;
3090  for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
3091  {
3092  memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
3093 
3094  /*
3095  * .. and for subsequent iterations the result of the previous XOR
3096  * (calculated below)
3097  */
3098  md5trailer = encryptedpassword + i;
3099 
3100  if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
3101  {
3102  ereport(LOG,
3103  (errmsg("could not perform MD5 encryption of password")));
3104  pfree(cryptvector);
3105  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3106  return STATUS_ERROR;
3107  }
3108 
3109  for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
3110  {
3111  if (j < strlen(passwd))
3112  encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
3113  else
3114  encryptedpassword[j] = '\0' ^ encryptedpassword[j];
3115  }
3116  }
3117  pfree(cryptvector);
3118 
3119  radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
3120 
3121  /* Length needs to be in network order on the wire */
3122  packetlength = packet->length;
3123  packet->length = pg_hton16(packet->length);
3124 
3125  sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
3126  if (sock == PGINVALID_SOCKET)
3127  {
3128  ereport(LOG,
3129  (errmsg("could not create RADIUS socket: %m")));
3130  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3131  return STATUS_ERROR;
3132  }
3133 
3134  memset(&localaddr, 0, sizeof(localaddr));
3135 #ifdef HAVE_IPV6
3136  localaddr.sin6_family = serveraddrs[0].ai_family;
3137  localaddr.sin6_addr = in6addr_any;
3138  if (localaddr.sin6_family == AF_INET6)
3139  addrsize = sizeof(struct sockaddr_in6);
3140  else
3141  addrsize = sizeof(struct sockaddr_in);
3142 #else
3143  localaddr.sin_family = serveraddrs[0].ai_family;
3144  localaddr.sin_addr.s_addr = INADDR_ANY;
3145  addrsize = sizeof(struct sockaddr_in);
3146 #endif
3147 
3148  if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
3149  {
3150  ereport(LOG,
3151  (errmsg("could not bind local RADIUS socket: %m")));
3152  closesocket(sock);
3153  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3154  return STATUS_ERROR;
3155  }
3156 
3157  if (sendto(sock, radius_buffer, packetlength, 0,
3158  serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
3159  {
3160  ereport(LOG,
3161  (errmsg("could not send RADIUS packet: %m")));
3162  closesocket(sock);
3163  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3164  return STATUS_ERROR;
3165  }
3166 
3167  /* Don't need the server address anymore */
3168  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3169 
3170  /*
3171  * Figure out at what time we should time out. We can't just use a single
3172  * call to select() with a timeout, since somebody can be sending invalid
3173  * packets to our port thus causing us to retry in a loop and never time
3174  * out.
3175  *
3176  * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
3177  * the latch was set would improve the responsiveness to
3178  * timeouts/cancellations.
3179  */
3180  gettimeofday(&endtime, NULL);
3181  endtime.tv_sec += RADIUS_TIMEOUT;
3182 
3183  while (true)
3184  {
3185  struct timeval timeout;
3186  struct timeval now;
3187  int64 timeoutval;
3188 
3189  gettimeofday(&now, NULL);
3190  timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
3191  if (timeoutval <= 0)
3192  {
3193  ereport(LOG,
3194  (errmsg("timeout waiting for RADIUS response from %s",
3195  server)));
3196  closesocket(sock);
3197  return STATUS_ERROR;
3198  }
3199  timeout.tv_sec = timeoutval / 1000000;
3200  timeout.tv_usec = timeoutval % 1000000;
3201 
3202  FD_ZERO(&fdset);
3203  FD_SET(sock, &fdset);
3204 
3205  r = select(sock + 1, &fdset, NULL, NULL, &timeout);
3206  if (r < 0)
3207  {
3208  if (errno == EINTR)
3209  continue;
3210 
3211  /* Anything else is an actual error */
3212  ereport(LOG,
3213  (errmsg("could not check status on RADIUS socket: %m")));
3214  closesocket(sock);
3215  return STATUS_ERROR;
3216  }
3217  if (r == 0)
3218  {
3219  ereport(LOG,
3220  (errmsg("timeout waiting for RADIUS response from %s",
3221  server)));
3222  closesocket(sock);
3223  return STATUS_ERROR;
3224  }
3225 
3226  /*
3227  * Attempt to read the response packet, and verify the contents.
3228  *
3229  * Any packet that's not actually a RADIUS packet, or otherwise does
3230  * not validate as an explicit reject, is just ignored and we retry
3231  * for another packet (until we reach the timeout). This is to avoid
3232  * the possibility to denial-of-service the login by flooding the
3233  * server with invalid packets on the port that we're expecting the
3234  * RADIUS response on.
3235  */
3236 
3237  addrsize = sizeof(remoteaddr);
3238  packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3239  (struct sockaddr *) &remoteaddr, &addrsize);
3240  if (packetlength < 0)
3241  {
3242  ereport(LOG,
3243  (errmsg("could not read RADIUS response: %m")));
3244  closesocket(sock);
3245  return STATUS_ERROR;
3246  }
3247 
3248 #ifdef HAVE_IPV6
3249  if (remoteaddr.sin6_port != pg_hton16(port))
3250 #else
3251  if (remoteaddr.sin_port != pg_hton16(port))
3252 #endif
3253  {
3254 #ifdef HAVE_IPV6
3255  ereport(LOG,
3256  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3257  server, pg_ntoh16(remoteaddr.sin6_port))));
3258 #else
3259  ereport(LOG,
3260  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3261  server, pg_ntoh16(remoteaddr.sin_port))));
3262 #endif
3263  continue;
3264  }
3265 
3266  if (packetlength < RADIUS_HEADER_LENGTH)
3267  {
3268  ereport(LOG,
3269  (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3270  continue;
3271  }
3272 
3273  if (packetlength != pg_ntoh16(receivepacket->length))
3274  {
3275  ereport(LOG,
3276  (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3277  server, pg_ntoh16(receivepacket->length), packetlength)));
3278  continue;
3279  }
3280 
3281  if (packet->id != receivepacket->id)
3282  {
3283  ereport(LOG,
3284  (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3285  server, receivepacket->id, packet->id)));
3286  continue;
3287  }
3288 
3289  /*
3290  * Verify the response authenticator, which is calculated as
3291  * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3292  */
3293  cryptvector = palloc(packetlength + strlen(secret));
3294 
3295  memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3296  memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3297  * authenticator, from
3298  * original packet */
3299  if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3300  * attributes at all */
3301  memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
3302  memcpy(cryptvector + packetlength, secret, strlen(secret));
3303 
3304  if (!pg_md5_binary(cryptvector,
3305  packetlength + strlen(secret),
3306  encryptedpassword))
3307  {
3308  ereport(LOG,
3309  (errmsg("could not perform MD5 encryption of received packet")));
3310  pfree(cryptvector);
3311  continue;
3312  }
3313  pfree(cryptvector);
3314 
3315  if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3316  {
3317  ereport(LOG,
3318  (errmsg("RADIUS response from %s has incorrect MD5 signature",
3319  server)));
3320  continue;
3321  }
3322 
3323  if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3324  {
3325  closesocket(sock);
3326  return STATUS_OK;
3327  }
3328  else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3329  {
3330  closesocket(sock);
3331  return STATUS_EOF;
3332  }
3333  else
3334  {
3335  ereport(LOG,
3336  (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3337  server, receivepacket->code, user_name)));
3338  continue;
3339  }
3340  } /* while (true) */
3341 }
#define RADIUS_PASSWORD
Definition: auth.c:2877
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:88
bool pg_md5_binary(const void *buff, size_t len, void *outbuf)
Definition: md5_common.c:93
#define closesocket
Definition: port.h:332
uint16 length
Definition: auth.c:2864
#define pg_hton16(x)
Definition: pg_bswap.h:120
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
unsigned char uint8
Definition: c.h:439
#define RADIUS_VECTOR_LENGTH
Definition: auth.c:2846
#define STATUS_ERROR
Definition: c.h:1171
#define MemSet(start, val, len)
Definition: c.h:1008
#define LOG
Definition: elog.h:26
#define RADIUS_NAS_IDENTIFIER
Definition: auth.c:2879
#define bind(s, addr, addrlen)
Definition: win32_port.h:460
#define RADIUS_TIMEOUT
Definition: auth.c:2885
#define gai_strerror
Definition: getaddrinfo.h:146
signed int int32
Definition: c.h:429
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2847
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:57
void pfree(void *pointer)
Definition: mcxt.c:1057
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define RADIUS_USER_NAME
Definition: auth.c:2876
#define select(n, r, w, e, timeout)
Definition: win32_port.h:464
int pgsocket
Definition: port.h:31
#define STATUS_OK
Definition: c.h:1170
static int port
Definition: pg_regress.c:92
#define RADIUS_ACCESS_ACCEPT
Definition: auth.c:2872
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2851
#define socket(af, type, protocol)
Definition: win32_port.h:459
#define PGINVALID_SOCKET
Definition: port.h:33
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:2882
#define ereport(elevel,...)
Definition: elog.h:155
bool pg_strong_random(void *buf, size_t len)
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:2871
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2848
#define RADIUS_SERVICE_TYPE
Definition: auth.c:2878
uint8 id
Definition: auth.c:2863
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:905
int i
uint8 code
Definition: auth.c:2862
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:2865
#define EINTR
Definition: win32_port.h:343
#define STATUS_EOF
Definition: c.h:1172
static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
Definition: auth.c:2888
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1542
#define RADIUS_ACCESS_REJECT
Definition: auth.c:2873
int ai_family
Definition: getaddrinfo.h:101

◆ radius_add_attribute()

static void radius_add_attribute ( radius_packet packet,
uint8  type,
const unsigned char *  data,
int  len 
)
static

Definition at line 2888 of file auth.c.

References radius_attribute::attribute, radius_attribute::data, elog, radius_attribute::length, radius_packet::length, RADIUS_BUFFER_SIZE, generate_unaccent_rules::type, and WARNING.

Referenced by PerformRadiusTransaction().

2889 {
2890  radius_attribute *attr;
2891 
2892  if (packet->length + len > RADIUS_BUFFER_SIZE)
2893  {
2894  /*
2895  * With remotely realistic data, this can never happen. But catch it
2896  * just to make sure we don't overrun a buffer. We'll just skip adding
2897  * the broken attribute, which will in the end cause authentication to
2898  * fail.
2899  */
2900  elog(WARNING,
2901  "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2902  type, len);
2903  return;
2904  }
2905 
2906  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2907  attr->attribute = type;
2908  attr->length = len + 2; /* total size includes type and length */
2909  memcpy(attr->data, data, len);
2910  packet->length += attr->length;
2911 }
uint16 length
Definition: auth.c:2864
uint8 attribute
Definition: auth.c:2855
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2851
#define elog(elevel,...)
Definition: elog.h:227
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2857
uint8 length
Definition: auth.c:2856

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 653 of file auth.c.

References buf, StringInfoData::data, DEBUG5, elog, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errmsg(), ERROR, initStringInfo(), StringInfoData::len, pfree(), pq_getbyte(), pq_getmessage(), and pq_startmsgread().

Referenced by auth_peer(), CheckMD5Auth(), CheckPasswordAuth(), and CheckRADIUSAuth().

654 {
656  int mtype;
657 
658  pq_startmsgread();
659 
660  /* Expect 'p' message type */
661  mtype = pq_getbyte();
662  if (mtype != 'p')
663  {
664  /*
665  * If the client just disconnects without offering a password,
666  * don't make a log entry. This is legal per protocol spec and in
667  * fact commonly done by psql, so complaining just clutters the
668  * log.
669  */
670  if (mtype != EOF)
671  ereport(ERROR,
672  (errcode(ERRCODE_PROTOCOL_VIOLATION),
673  errmsg("expected password response, got message type %d",
674  mtype)));
675  return NULL; /* EOF or bad message type */
676  }
677 
678  initStringInfo(&buf);
679  if (pq_getmessage(&buf, 0)) /* receive password */
680  {
681  /* EOF - pq_getmessage already logged a suitable message */
682  pfree(buf.data);
683  return NULL;
684  }
685 
686  /*
687  * Apply sanity check: password packet length should agree with length of
688  * contained string. Note it is safe to use strlen here because
689  * StringInfo is guaranteed to have an appended '\0'.
690  */
691  if (strlen(buf.data) + 1 != buf.len)
692  ereport(ERROR,
693  (errcode(ERRCODE_PROTOCOL_VIOLATION),
694  errmsg("invalid password packet size")));
695 
696  /*
697  * Don't allow an empty password. Libpq treats an empty password the same
698  * as no password at all, and won't even try to authenticate. But other
699  * clients might, so allowing it would be confusing.
700  *
701  * Note that this only catches an empty password sent by the client in
702  * plaintext. There's also a check in CREATE/ALTER USER that prevents an
703  * empty string from being stored as a user's password in the first place.
704  * We rely on that for MD5 and SCRAM authentication, but we still need
705  * this check here, to prevent an empty password from being used with
706  * authentication methods that check the password against an external
707  * system, like PAM, LDAP and RADIUS.
708  */
709  if (buf.len == 1)
710  ereport(ERROR,
712  errmsg("empty password returned by client")));
713 
714  /* Do not echo password to logs, for security. */
715  elog(DEBUG5, "received password packet");
716 
717  /*
718  * Return the received string. Note we do not attempt to do any
719  * character-set conversion on it; since we don't yet know the client's
720  * encoding, there wouldn't be much point.
721  */
722  return buf.data;
723 }
int errcode(int sqlerrcode)
Definition: elog.c:694
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
void pq_startmsgread(void)
Definition: pqcomm.c:1147
static char * buf
Definition: pg_test_fsync.c:68
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1209
int pq_getbyte(void)
Definition: pqcomm.c:989
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define elog(elevel,...)
Definition: elog.h:227
#define DEBUG5
Definition: elog.h:20
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:95

◆ sendAuthRequest()

static void sendAuthRequest ( Port port,
AuthRequest  areq,
const char *  extradata,
int  extralen 
)
static

Definition at line 623 of file auth.c.

References AUTH_REQ_OK, AUTH_REQ_SASL_FIN, buf, CHECK_FOR_INTERRUPTS, pq_beginmessage(), pq_endmessage(), pq_flush, pq_sendbytes(), and pq_sendint32().

Referenced by auth_peer(), CheckMD5Auth(), CheckPasswordAuth(), CheckRADIUSAuth(), CheckSCRAMAuth(), and ClientAuthentication().

624 {
626 
628 
629  pq_beginmessage(&buf, 'R');
630  pq_sendint32(&buf, (int32) areq);
631  if (extralen > 0)
632  pq_sendbytes(&buf, extradata, extralen);
633 
634  pq_endmessage(&buf);
635 
636  /*
637  * Flush message so client will see it, except for AUTH_REQ_OK and
638  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
639  * queries.
640  */
641  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
642  pq_flush();
643 
645 }
#define pq_flush()
Definition: libpq.h:37
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:163
#define AUTH_REQ_OK
Definition: pqcomm.h:151
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
signed int int32
Definition: c.h:429
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static char * buf
Definition: pg_test_fsync.c:68
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:100

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 241 of file auth.c.

Referenced by _PG_init(), ClientAuthentication(), and sepgsql_init_client_label().

◆ pg_krb_caseins_users

bool pg_krb_caseins_users

Definition at line 170 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 169 of file auth.c.

Referenced by CheckSCRAMAuth(), and secure_open_gssapi().