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 "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
#include "utils/guc.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 void set_authn_id (Port *port, const char *id)
 
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:1090
static int port
Definition: pg_regress.c:92

Referenced by ClientAuthentication().

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 74 of file auth.c.

Referenced by ident_inet().

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 71 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 225 of file auth.c.

Referenced by CheckSCRAMAuth(), and recv_password_packet().

◆ PG_MAX_SASL_MESSAGE_LENGTH

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 233 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 3012 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 3013 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 3011 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 3022 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2991 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2987 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2988 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 3019 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 3017 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 3018 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 3025 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 3016 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2986 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 261 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().

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

◆ auth_peer()

static int auth_peer ( hbaPort port)
static

Definition at line 2011 of file auth.c.

References _, SockAddr::addr, appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, HbaLine::auth_method, AUTH_REQ_PASSWORD, Port::authn_id, calloc, check_usermap(), HbaLine::clientcert, clientCertCN, clientCertDN, clientCertFull, HbaLine::clientcertname, 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, Port::peer_dn, pfree(), pg_getnameinfo_all(), port, psprintf(), pstrdup(), Port::raddr, recv_password_packet(), SockAddr::salen, sendAuthRequest(), set_authn_id(), Port::sock, STATUS_EOF, STATUS_ERROR, STATUS_OK, strerror, uaCert, unconstify, user, Port::user_name, HbaLine::usermap, and WARNING.

Referenced by ClientAuthentication().

2012 {
2013  uid_t uid;
2014  gid_t gid;
2015 #ifndef WIN32
2016  struct passwd *pw;
2017  int ret;
2018 #endif
2019 
2020  if (getpeereid(port->sock, &uid, &gid) != 0)
2021  {
2022  /* Provide special error message if getpeereid is a stub */
2023  if (errno == ENOSYS)
2024  ereport(LOG,
2025  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2026  errmsg("peer authentication is not supported on this platform")));
2027  else
2028  ereport(LOG,
2030  errmsg("could not get peer credentials: %m")));
2031  return STATUS_ERROR;
2032  }
2033 
2034 #ifndef WIN32
2035  errno = 0; /* clear errno before call */
2036  pw = getpwuid(uid);
2037  if (!pw)
2038  {
2039  int save_errno = errno;
2040 
2041  ereport(LOG,
2042  (errmsg("could not look up local user ID %ld: %s",
2043  (long) uid,
2044  save_errno ? strerror(save_errno) : _("user does not exist"))));
2045  return STATUS_ERROR;
2046  }
2047 
2048  /*
2049  * Make a copy of static getpw*() result area; this is our authenticated
2050  * identity. Set it before calling check_usermap, because authentication
2051  * has already succeeded and we want the log file to reflect that.
2052  */
2053  set_authn_id(port, pw->pw_name);
2054 
2055  ret = check_usermap(port->hba->usermap, port->user_name, port->authn_id, false);
2056 
2057  return ret;
2058 #else
2059  /* should have failed with ENOSYS above */
2060  Assert(false);
2061  return STATUS_ERROR;
2062 #endif
2063 }
const char * authn_id
Definition: libpq-be.h:173
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:35
int errcode(int sqlerrcode)
Definition: elog.c:698
#define STATUS_ERROR
Definition: c.h:1171
#define LOG
Definition: elog.h:26
pgsocket sock
Definition: libpq-be.h:127
char * usermap
Definition: hba.h:94
char * user_name
Definition: libpq-be.h:146
int errcode_for_socket_access(void)
Definition: elog.c:792
HbaLine * hba
Definition: libpq-be.h:160
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2974
#define ereport(elevel,...)
Definition: elog.h:157
#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:909
int gid_t
Definition: win32_port.h:237
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:358
#define _(x)
Definition: elog.c:89

◆ CheckMD5Auth()

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

Definition at line 878 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().

879 {
880  char md5Salt[4]; /* Password salt */
881  char *passwd;
882  int result;
883 
884  if (Db_user_namespace)
885  ereport(FATAL,
886  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
887  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
888 
889  /* include the salt to use for computing the response */
890  if (!pg_strong_random(md5Salt, 4))
891  {
892  ereport(LOG,
893  (errmsg("could not generate random MD5 salt")));
894  return STATUS_ERROR;
895  }
896 
897  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
898 
899  passwd = recv_password_packet(port);
900  if (passwd == NULL)
901  return STATUS_EOF; /* client wouldn't send password */
902 
903  if (shadow_pass)
904  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
905  md5Salt, 4, logdetail);
906  else
907  result = STATUS_ERROR;
908 
909  pfree(passwd);
910 
911  return result;
912 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:672
int errcode(int sqlerrcode)
Definition: elog.c:698
#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:1169
#define FATAL
Definition: elog.h:49
bool Db_user_namespace
Definition: postmaster.c:241
char * user_name
Definition: libpq-be.h:146
static char * recv_password_packet(Port *port)
Definition: auth.c:702
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:157
bool pg_strong_random(void *buf, size_t len)
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define STATUS_EOF
Definition: c.h:1172

◆ CheckPasswordAuth()

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

Definition at line 783 of file auth.c.

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

Referenced by ClientAuthentication().

784 {
785  char *passwd;
786  int result;
787  char *shadow_pass;
788 
789  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
790 
791  passwd = recv_password_packet(port);
792  if (passwd == NULL)
793  return STATUS_EOF; /* client wouldn't send password */
794 
795  shadow_pass = get_role_password(port->user_name, logdetail);
796  if (shadow_pass)
797  {
798  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
799  logdetail);
800  }
801  else
802  result = STATUS_ERROR;
803 
804  if (shadow_pass)
805  pfree(shadow_pass);
806  pfree(passwd);
807 
808  if (result == STATUS_OK)
809  set_authn_id(port, port->user_name);
810 
811  return result;
812 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:672
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:1169
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:37
char * user_name
Definition: libpq-be.h:146
#define STATUS_OK
Definition: c.h:1170
static char * recv_password_packet(Port *port)
Definition: auth.c:702
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:154
#define STATUS_EOF
Definition: c.h:1172
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:358

◆ CheckPWChallengeAuth()

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

Definition at line 818 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(), set_authn_id(), STATUS_ERROR, STATUS_OK, uaMD5, uaSCRAM, and Port::user_name.

Referenced by ClientAuthentication().

819 {
820  int auth_result;
821  char *shadow_pass;
822  PasswordType pwtype;
823 
824  Assert(port->hba->auth_method == uaSCRAM ||
825  port->hba->auth_method == uaMD5);
826 
827  /* First look up the user's password. */
828  shadow_pass = get_role_password(port->user_name, logdetail);
829 
830  /*
831  * If the user does not exist, or has no password or it's expired, we
832  * still go through the motions of authentication, to avoid revealing to
833  * the client that the user didn't exist. If 'md5' is allowed, we choose
834  * whether to use 'md5' or 'scram-sha-256' authentication based on current
835  * password_encryption setting. The idea is that most genuine users
836  * probably have a password of that type, and if we pretend that this user
837  * had a password of that type, too, it "blends in" best.
838  */
839  if (!shadow_pass)
840  pwtype = Password_encryption;
841  else
842  pwtype = get_password_type(shadow_pass);
843 
844  /*
845  * If 'md5' authentication is allowed, decide whether to perform 'md5' or
846  * 'scram-sha-256' authentication based on the type of password the user
847  * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
848  * SCRAM secret, we must do SCRAM authentication.
849  *
850  * If MD5 authentication is not allowed, always use SCRAM. If the user
851  * had an MD5 password, CheckSCRAMAuth() will fail.
852  */
853  if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
854  auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
855  else
856  auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
857 
858  if (shadow_pass)
859  pfree(shadow_pass);
860 
861  /*
862  * If get_role_password() returned error, return error, even if the
863  * authentication succeeded.
864  */
865  if (!shadow_pass)
866  {
867  Assert(auth_result != STATUS_OK);
868  return STATUS_ERROR;
869  }
870 
871  if (auth_result == STATUS_OK)
872  set_authn_id(port, port->user_name);
873 
874  return auth_result;
875 }
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:1169
static int CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:915
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:37
char * user_name
Definition: libpq-be.h:146
#define STATUS_OK
Definition: c.h:1170
HbaLine * hba
Definition: libpq-be.h:160
static int CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:878
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
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:358
UserAuth auth_method
Definition: hba.h:93

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

Definition at line 3054 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(), set_authn_id(), STATUS_EOF, STATUS_ERROR, STATUS_OK, and Port::user_name.

Referenced by ClientAuthentication().

3055 {
3056  char *passwd;
3057  ListCell *server,
3058  *secrets,
3059  *radiusports,
3060  *identifiers;
3061 
3062  /* Make sure struct alignment is correct */
3063  Assert(offsetof(radius_packet, vector) == 4);
3064 
3065  /* Verify parameters */
3066  if (list_length(port->hba->radiusservers) < 1)
3067  {
3068  ereport(LOG,
3069  (errmsg("RADIUS server not specified")));
3070  return STATUS_ERROR;
3071  }
3072 
3073  if (list_length(port->hba->radiussecrets) < 1)
3074  {
3075  ereport(LOG,
3076  (errmsg("RADIUS secret not specified")));
3077  return STATUS_ERROR;
3078  }
3079 
3080  /* Send regular password request to client, and get the response */
3081  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
3082 
3083  passwd = recv_password_packet(port);
3084  if (passwd == NULL)
3085  return STATUS_EOF; /* client wouldn't send password */
3086 
3087  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
3088  {
3089  ereport(LOG,
3090  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
3091  pfree(passwd);
3092  return STATUS_ERROR;
3093  }
3094 
3095  /*
3096  * Loop over and try each server in order.
3097  */
3098  secrets = list_head(port->hba->radiussecrets);
3099  radiusports = list_head(port->hba->radiusports);
3100  identifiers = list_head(port->hba->radiusidentifiers);
3101  foreach(server, port->hba->radiusservers)
3102  {
3103  int ret = PerformRadiusTransaction(lfirst(server),
3104  lfirst(secrets),
3105  radiusports ? lfirst(radiusports) : NULL,
3106  identifiers ? lfirst(identifiers) : NULL,
3107  port->user_name,
3108  passwd);
3109 
3110  /*------
3111  * STATUS_OK = Login OK
3112  * STATUS_ERROR = Login not OK, but try next server
3113  * STATUS_EOF = Login not OK, and don't try next server
3114  *------
3115  */
3116  if (ret == STATUS_OK)
3117  {
3118  set_authn_id(port, port->user_name);
3119 
3120  pfree(passwd);
3121  return STATUS_OK;
3122  }
3123  else if (ret == STATUS_EOF)
3124  {
3125  pfree(passwd);
3126  return STATUS_ERROR;
3127  }
3128 
3129  /*
3130  * secret, port and identifiers either have length 0 (use default),
3131  * length 1 (use the same everywhere) or the same length as servers.
3132  * So if the length is >1, we advance one step. In other cases, we
3133  * don't and will then reuse the correct value.
3134  */
3135  if (list_length(port->hba->radiussecrets) > 1)
3136  secrets = lnext(port->hba->radiussecrets, secrets);
3137  if (list_length(port->hba->radiusports) > 1)
3138  radiusports = lnext(port->hba->radiusports, radiusports);
3139  if (list_length(port->hba->radiusidentifiers) > 1)
3140  identifiers = lnext(port->hba->radiusidentifiers, identifiers);
3141  }
3142 
3143  /* No servers left to try, so give up */
3144  pfree(passwd);
3145  return STATUS_ERROR;
3146 }
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:672
#define STATUS_ERROR
Definition: c.h:1171
#define LOG
Definition: elog.h:26
List * radiussecrets
Definition: hba.h:117
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:3149
void pfree(void *pointer)
Definition: mcxt.c:1169
List * radiusports
Definition: hba.h:121
List * radiusservers
Definition: hba.h:115
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
char * user_name
Definition: libpq-be.h:146
#define STATUS_OK
Definition: c.h:1170
static char * recv_password_packet(Port *port)
Definition: auth.c:702
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:154
HbaLine * hba
Definition: libpq-be.h:160
List * radiusidentifiers
Definition: hba.h:119
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2988
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define STATUS_EOF
Definition: c.h:1172
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:358
#define offsetof(type, field)
Definition: c.h:727

◆ CheckSCRAMAuth()

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

Definition at line 915 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(), set_authn_id(), setenv, status(), STATUS_EOF, STATUS_ERROR, STATUS_OK, TopMemoryContext, HbaLine::upn_username, Port::user_name, and HbaLine::usermap.

Referenced by CheckPWChallengeAuth().

916 {
917  StringInfoData sasl_mechs;
918  int mtype;
920  void *scram_opaq = NULL;
921  char *output = NULL;
922  int outputlen = 0;
923  const char *input;
924  int inputlen;
925  int result;
926  bool initial;
927 
928  /*
929  * Send the SASL authentication request to user. It includes the list of
930  * authentication mechanisms that are supported.
931  */
932  initStringInfo(&sasl_mechs);
933 
934  pg_be_scram_get_mechanisms(port, &sasl_mechs);
935  /* Put another '\0' to mark that list is finished. */
936  appendStringInfoChar(&sasl_mechs, '\0');
937 
938  sendAuthRequest(port, AUTH_REQ_SASL, sasl_mechs.data, sasl_mechs.len);
939  pfree(sasl_mechs.data);
940 
941  /*
942  * Loop through SASL message exchange. This exchange can consist of
943  * multiple messages sent in both directions. First message is always
944  * from the client. All messages from client to server are password
945  * packets (type 'p').
946  */
947  initial = true;
948  do
949  {
950  pq_startmsgread();
951  mtype = pq_getbyte();
952  if (mtype != 'p')
953  {
954  /* Only log error if client didn't disconnect. */
955  if (mtype != EOF)
956  {
957  ereport(ERROR,
958  (errcode(ERRCODE_PROTOCOL_VIOLATION),
959  errmsg("expected SASL response, got message type %d",
960  mtype)));
961  }
962  else
963  return STATUS_EOF;
964  }
965 
966  /* Get the actual SASL message */
967  initStringInfo(&buf);
969  {
970  /* EOF - pq_getmessage already logged error */
971  pfree(buf.data);
972  return STATUS_ERROR;
973  }
974 
975  elog(DEBUG4, "processing received SASL response of length %d", buf.len);
976 
977  /*
978  * The first SASLInitialResponse message is different from the others.
979  * It indicates which SASL mechanism the client selected, and contains
980  * an optional Initial Client Response payload. The subsequent
981  * SASLResponse messages contain just the SASL payload.
982  */
983  if (initial)
984  {
985  const char *selected_mech;
986 
987  selected_mech = pq_getmsgrawstring(&buf);
988 
989  /*
990  * Initialize the status tracker for message exchanges.
991  *
992  * If the user doesn't exist, or doesn't have a valid password, or
993  * it's expired, we still go through the motions of SASL
994  * authentication, but tell the authentication method that the
995  * authentication is "doomed". That is, it's going to fail, no
996  * matter what.
997  *
998  * This is because we don't want to reveal to an attacker what
999  * usernames are valid, nor which users have a valid password.
1000  */
1001  scram_opaq = pg_be_scram_init(port, selected_mech, shadow_pass);
1002 
1003  inputlen = pq_getmsgint(&buf, 4);
1004  if (inputlen == -1)
1005  input = NULL;
1006  else
1007  input = pq_getmsgbytes(&buf, inputlen);
1008 
1009  initial = false;
1010  }
1011  else
1012  {
1013  inputlen = buf.len;
1014  input = pq_getmsgbytes(&buf, buf.len);
1015  }
1016  pq_getmsgend(&buf);
1017 
1018  /*
1019  * The StringInfo guarantees that there's a \0 byte after the
1020  * response.
1021  */
1022  Assert(input == NULL || input[inputlen] == '\0');
1023 
1024  /*
1025  * we pass 'logdetail' as NULL when doing a mock authentication,
1026  * because we should already have a better error message in that case
1027  */
1028  result = pg_be_scram_exchange(scram_opaq, input, inputlen,
1029  &output, &outputlen,
1030  logdetail);
1031 
1032  /* input buffer no longer used */
1033  pfree(buf.data);
1034 
1035  if (output)
1036  {
1037  /*
1038  * Negotiation generated data to be sent to the client.
1039  */
1040  elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
1041 
1042  if (result == SASL_EXCHANGE_SUCCESS)
1043  sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
1044  else
1045  sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
1046 
1047  pfree(output);
1048  }
1049  } while (result == SASL_EXCHANGE_CONTINUE);
1050 
1051  /* Oops, Something bad happened */
1052  if (result != SASL_EXCHANGE_SUCCESS)
1053  {
1054  return STATUS_ERROR;
1055  }
1056 
1057  return STATUS_OK;
1058 }
void pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
Definition: auth-scram.c:182
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:672
#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:698
#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:219
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
void pq_startmsgread(void)
Definition: pqcomm.c:1152
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:1214
int pg_be_scram_exchange(void *opaq, const char *input, int inputlen, char **output, int *outputlen, char **logdetail)
Definition: auth-scram.c:329
int pq_getbyte(void)
Definition: pqcomm.c:994
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:162
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define PG_MAX_SASL_MESSAGE_LENGTH
Definition: auth.c:233
#define AUTH_REQ_SASL
Definition: pqcomm.h:161
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
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 394 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().

395 {
396  int status = STATUS_ERROR;
397  char *logdetail = NULL;
398 
399  /*
400  * Get the authentication method to use for this frontend/database
401  * combination. Note: we do not parse the file at this point; this has
402  * already been done elsewhere. hba.c dropped an error message into the
403  * server logfile if parsing the hba config file failed.
404  */
405  hba_getauthmethod(port);
406 
408 
409  /*
410  * This is the first point where we have access to the hba record for the
411  * current connection, so perform any verifications based on the hba
412  * options field that should be done *before* the authentication here.
413  */
414  if (port->hba->clientcert != clientCertOff)
415  {
416  /* If we haven't loaded a root certificate store, fail */
418  ereport(FATAL,
419  (errcode(ERRCODE_CONFIG_FILE_ERROR),
420  errmsg("client certificates can only be checked if a root certificate store is available")));
421 
422  /*
423  * If we loaded a root certificate store, and if a certificate is
424  * present on the client, then it has been verified against our root
425  * certificate store, and the connection would have been aborted
426  * already if it didn't verify ok.
427  */
428  if (!port->peer_cert_valid)
429  ereport(FATAL,
430  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
431  errmsg("connection requires a valid client certificate")));
432  }
433 
434  /*
435  * Now proceed to do the actual authentication check
436  */
437  switch (port->hba->auth_method)
438  {
439  case uaReject:
440 
441  /*
442  * An explicit "reject" entry in pg_hba.conf. This report exposes
443  * the fact that there's an explicit reject entry, which is
444  * perhaps not so desirable from a security standpoint; but the
445  * message for an implicit reject could confuse the DBA a lot when
446  * the true situation is a match to an explicit reject. And we
447  * don't want to change the message for an implicit reject. As
448  * noted below, the additional information shown here doesn't
449  * expose anything not known to an attacker.
450  */
451  {
452  char hostinfo[NI_MAXHOST];
453  const char *encryption_state;
454 
455  pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
456  hostinfo, sizeof(hostinfo),
457  NULL, 0,
459 
460  encryption_state =
461 #ifdef ENABLE_GSS
462  (port->gss && port->gss->enc) ? _("GSS encryption") :
463 #endif
464 #ifdef USE_SSL
465  port->ssl_in_use ? _("SSL encryption") :
466 #endif
467  _("no encryption");
468 
470  ereport(FATAL,
471  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
472  /* translator: last %s describes encryption state */
473  errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
474  hostinfo, port->user_name,
475  encryption_state)));
476  else
477  ereport(FATAL,
478  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
479  /* translator: last %s describes encryption state */
480  errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
481  hostinfo, port->user_name,
482  port->database_name,
483  encryption_state)));
484  break;
485  }
486 
487  case uaImplicitReject:
488 
489  /*
490  * No matching entry, so tell the user we fell through.
491  *
492  * NOTE: the extra info reported here is not a security breach,
493  * because all that info is known at the frontend and must be
494  * assumed known to bad guys. We're merely helping out the less
495  * clueful good guys.
496  */
497  {
498  char hostinfo[NI_MAXHOST];
499  const char *encryption_state;
500 
501  pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
502  hostinfo, sizeof(hostinfo),
503  NULL, 0,
505 
506  encryption_state =
507 #ifdef ENABLE_GSS
508  (port->gss && port->gss->enc) ? _("GSS encryption") :
509 #endif
510 #ifdef USE_SSL
511  port->ssl_in_use ? _("SSL encryption") :
512 #endif
513  _("no encryption");
514 
515 #define HOSTNAME_LOOKUP_DETAIL(port) \
516  (port->remote_hostname ? \
517  (port->remote_hostname_resolv == +1 ? \
518  errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
519  port->remote_hostname) : \
520  port->remote_hostname_resolv == 0 ? \
521  errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
522  port->remote_hostname) : \
523  port->remote_hostname_resolv == -1 ? \
524  errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
525  port->remote_hostname) : \
526  port->remote_hostname_resolv == -2 ? \
527  errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
528  port->remote_hostname, \
529  gai_strerror(port->remote_hostname_errcode)) : \
530  0) \
531  : (port->remote_hostname_resolv == -2 ? \
532  errdetail_log("Could not resolve client IP address to a host name: %s.", \
533  gai_strerror(port->remote_hostname_errcode)) : \
534  0))
535 
537  ereport(FATAL,
538  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
539  /* translator: last %s describes encryption state */
540  errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
541  hostinfo, port->user_name,
542  encryption_state),
543  HOSTNAME_LOOKUP_DETAIL(port)));
544  else
545  ereport(FATAL,
546  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
547  /* translator: last %s describes encryption state */
548  errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
549  hostinfo, port->user_name,
550  port->database_name,
551  encryption_state),
552  HOSTNAME_LOOKUP_DETAIL(port)));
553  break;
554  }
555 
556  case uaGSS:
557 #ifdef ENABLE_GSS
558  /* We might or might not have the gss workspace already */
559  if (port->gss == NULL)
560  port->gss = (pg_gssinfo *)
562  sizeof(pg_gssinfo));
563  port->gss->auth = true;
564 
565  /*
566  * If GSS state was set up while enabling encryption, we can just
567  * check the client's principal. Otherwise, ask for it.
568  */
569  if (port->gss->enc)
570  status = pg_GSS_checkauth(port);
571  else
572  {
573  sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
574  status = pg_GSS_recvauth(port);
575  }
576 #else
577  Assert(false);
578 #endif
579  break;
580 
581  case uaSSPI:
582 #ifdef ENABLE_SSPI
583  if (port->gss == NULL)
584  port->gss = (pg_gssinfo *)
586  sizeof(pg_gssinfo));
587  sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
588  status = pg_SSPI_recvauth(port);
589 #else
590  Assert(false);
591 #endif
592  break;
593 
594  case uaPeer:
595  status = auth_peer(port);
596  break;
597 
598  case uaIdent:
599  status = ident_inet(port);
600  break;
601 
602  case uaMD5:
603  case uaSCRAM:
604  status = CheckPWChallengeAuth(port, &logdetail);
605  break;
606 
607  case uaPassword:
608  status = CheckPasswordAuth(port, &logdetail);
609  break;
610 
611  case uaPAM:
612 #ifdef USE_PAM
613  status = CheckPAMAuth(port, port->user_name, "");
614 #else
615  Assert(false);
616 #endif /* USE_PAM */
617  break;
618 
619  case uaBSD:
620 #ifdef USE_BSD_AUTH
621  status = CheckBSDAuth(port, port->user_name);
622 #else
623  Assert(false);
624 #endif /* USE_BSD_AUTH */
625  break;
626 
627  case uaLDAP:
628 #ifdef USE_LDAP
629  status = CheckLDAPAuth(port);
630 #else
631  Assert(false);
632 #endif
633  break;
634  case uaRADIUS:
635  status = CheckRADIUSAuth(port);
636  break;
637  case uaCert:
638  /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
639  case uaTrust:
640  status = STATUS_OK;
641  break;
642  }
643 
644  if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
645  || port->hba->auth_method == uaCert)
646  {
647  /*
648  * Make sure we only check the certificate if we use the cert method
649  * or verify-full option.
650  */
651 #ifdef USE_SSL
652  status = CheckCertAuth(port);
653 #else
654  Assert(false);
655 #endif
656  }
657 
659  (*ClientAuthentication_hook) (port, status);
660 
661  if (status == STATUS_OK)
662  sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
663  else
664  auth_failed(port, status, logdetail);
665 }
#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:2011
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:672
#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:212
struct sockaddr_storage addr
Definition: pqcomm.h:64
int errcode(int sqlerrcode)
Definition: elog.c:698
#define STATUS_ERROR
Definition: c.h:1171
bool ssl_in_use
Definition: libpq-be.h:209
static int CheckRADIUSAuth(Port *port)
Definition: auth.c:3054
Definition: hba.h:34
Definition: hba.h:31
SockAddr raddr
Definition: libpq-be.h:131
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:818
#define FATAL
Definition: elog.h:49
Definition: hba.h:27
Definition: hba.h:29
void hba_getauthmethod(hbaPort *port)
Definition: hba.c:3140
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:245
char * user_name
Definition: libpq-be.h:146
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define STATUS_OK
Definition: c.h:1170
MemoryContext TopMemoryContext
Definition: mcxt.c:48
static int port
Definition: pg_regress.c:92
HbaLine * hba
Definition: libpq-be.h:160
static int ident_inet(hbaPort *port)
Definition: auth.c:1826
Definition: hba.h:33
bool am_db_walsender
Definition: walsender.c:118
static int CheckPasswordAuth(Port *port, char **logdetail)
Definition: auth.c:783
Definition: hba.h:37
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
#define ereport(elevel,...)
Definition: elog.h:157
#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:109
bool secure_loaded_verify_locations(void)
Definition: be-secure.c:102
void * gss
Definition: libpq-be.h:203
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void auth_failed(Port *port, int status, char *logdetail)
Definition: auth.c:261
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
char * database_name
Definition: libpq-be.h:145
Definition: hba.h:36
#define _(x)
Definition: elog.c:89
Definition: hba.h:40
UserAuth auth_method
Definition: hba.h:93

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1826 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, set_authn_id(), snprintf, socket, STATUS_ERROR, Port::user_name, and HbaLine::usermap.

Referenced by ClientAuthentication().

1827 {
1828  const SockAddr remote_addr = port->raddr;
1829  const SockAddr local_addr = port->laddr;
1830  char ident_user[IDENT_USERNAME_MAX + 1];
1831  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1832  int rc; /* Return code from a locally called function */
1833  bool ident_return;
1834  char remote_addr_s[NI_MAXHOST];
1835  char remote_port[NI_MAXSERV];
1836  char local_addr_s[NI_MAXHOST];
1837  char local_port[NI_MAXSERV];
1838  char ident_port[NI_MAXSERV];
1839  char ident_query[80];
1840  char ident_response[80 + IDENT_USERNAME_MAX];
1841  struct addrinfo *ident_serv = NULL,
1842  *la = NULL,
1843  hints;
1844 
1845  /*
1846  * Might look a little weird to first convert it to text and then back to
1847  * sockaddr, but it's protocol independent.
1848  */
1849  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1850  remote_addr_s, sizeof(remote_addr_s),
1851  remote_port, sizeof(remote_port),
1853  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1854  local_addr_s, sizeof(local_addr_s),
1855  local_port, sizeof(local_port),
1857 
1858  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1859  hints.ai_flags = AI_NUMERICHOST;
1860  hints.ai_family = remote_addr.addr.ss_family;
1861  hints.ai_socktype = SOCK_STREAM;
1862  hints.ai_protocol = 0;
1863  hints.ai_addrlen = 0;
1864  hints.ai_canonname = NULL;
1865  hints.ai_addr = NULL;
1866  hints.ai_next = NULL;
1867  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1868  if (rc || !ident_serv)
1869  {
1870  /* we don't expect this to happen */
1871  ident_return = false;
1872  goto ident_inet_done;
1873  }
1874 
1875  hints.ai_flags = AI_NUMERICHOST;
1876  hints.ai_family = local_addr.addr.ss_family;
1877  hints.ai_socktype = SOCK_STREAM;
1878  hints.ai_protocol = 0;
1879  hints.ai_addrlen = 0;
1880  hints.ai_canonname = NULL;
1881  hints.ai_addr = NULL;
1882  hints.ai_next = NULL;
1883  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1884  if (rc || !la)
1885  {
1886  /* we don't expect this to happen */
1887  ident_return = false;
1888  goto ident_inet_done;
1889  }
1890 
1891  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1892  ident_serv->ai_protocol);
1893  if (sock_fd == PGINVALID_SOCKET)
1894  {
1895  ereport(LOG,
1897  errmsg("could not create socket for Ident connection: %m")));
1898  ident_return = false;
1899  goto ident_inet_done;
1900  }
1901 
1902  /*
1903  * Bind to the address which the client originally contacted, otherwise
1904  * the ident server won't be able to match up the right connection. This
1905  * is necessary if the PostgreSQL server is running on an IP alias.
1906  */
1907  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1908  if (rc != 0)
1909  {
1910  ereport(LOG,
1912  errmsg("could not bind to local address \"%s\": %m",
1913  local_addr_s)));
1914  ident_return = false;
1915  goto ident_inet_done;
1916  }
1917 
1918  rc = connect(sock_fd, ident_serv->ai_addr,
1919  ident_serv->ai_addrlen);
1920  if (rc != 0)
1921  {
1922  ereport(LOG,
1924  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1925  remote_addr_s, ident_port)));
1926  ident_return = false;
1927  goto ident_inet_done;
1928  }
1929 
1930  /* The query we send to the Ident server */
1931  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1932  remote_port, local_port);
1933 
1934  /* loop in case send is interrupted */
1935  do
1936  {
1938 
1939  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1940  } while (rc < 0 && errno == EINTR);
1941 
1942  if (rc < 0)
1943  {
1944  ereport(LOG,
1946  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1947  remote_addr_s, ident_port)));
1948  ident_return = false;
1949  goto ident_inet_done;
1950  }
1951 
1952  do
1953  {
1955 
1956  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1957  } while (rc < 0 && errno == EINTR);
1958 
1959  if (rc < 0)
1960  {
1961  ereport(LOG,
1963  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1964  remote_addr_s, ident_port)));
1965  ident_return = false;
1966  goto ident_inet_done;
1967  }
1968 
1969  ident_response[rc] = '\0';
1970  ident_return = interpret_ident_response(ident_response, ident_user);
1971  if (!ident_return)
1972  ereport(LOG,
1973  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1974  ident_response)));
1975 
1976 ident_inet_done:
1977  if (sock_fd != PGINVALID_SOCKET)
1978  closesocket(sock_fd);
1979  if (ident_serv)
1980  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1981  if (la)
1982  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1983 
1984  if (ident_return)
1985  {
1986  /*
1987  * Success! Store the identity, then check the usermap. Note that
1988  * setting the authenticated identity is done before checking the
1989  * usermap, because at this point authentication has succeeded.
1990  */
1991  set_authn_id(port, ident_user);
1992  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1993  }
1994  return STATUS_ERROR;
1995 }
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:131
#define IDENT_USERNAME_MAX
Definition: auth.c:71
#define NI_MAXHOST
Definition: getaddrinfo.h:88
char * usermap
Definition: hba.h:94
#define IDENT_PORT
Definition: auth.c:74
#define NI_MAXSERV
Definition: getaddrinfo.h:91
char * user_name
Definition: libpq-be.h:146
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
int errcode_for_socket_access(void)
Definition: elog.c:792
SockAddr laddr
Definition: libpq-be.h:130
HbaLine * hba
Definition: libpq-be.h:160
#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:2974
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
#define ereport(elevel,...)
Definition: elog.h:157
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:909
size_t ai_addrlen
Definition: getaddrinfo.h:104
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
#define EINTR
Definition: win32_port.h:343
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:358
#define snprintf
Definition: port.h:216
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1743
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 1743 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1745 {
1746  const char *cursor = ident_response; /* Cursor into *ident_response */
1747 
1748  /*
1749  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1750  */
1751  if (strlen(ident_response) < 2)
1752  return false;
1753  else if (ident_response[strlen(ident_response) - 2] != '\r')
1754  return false;
1755  else
1756  {
1757  while (*cursor != ':' && *cursor != '\r')
1758  cursor++; /* skip port field */
1759 
1760  if (*cursor != ':')
1761  return false;
1762  else
1763  {
1764  /* We're positioned to colon before response type field */
1765  char response_type[80];
1766  int i; /* Index into *response_type */
1767 
1768  cursor++; /* Go over colon */
1769  while (pg_isblank(*cursor))
1770  cursor++; /* skip blanks */
1771  i = 0;
1772  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1773  i < (int) (sizeof(response_type) - 1))
1774  response_type[i++] = *cursor++;
1775  response_type[i] = '\0';
1776  while (pg_isblank(*cursor))
1777  cursor++; /* skip blanks */
1778  if (strcmp(response_type, "USERID") != 0)
1779  return false;
1780  else
1781  {
1782  /*
1783  * It's a USERID response. Good. "cursor" should be pointing
1784  * to the colon that precedes the operating system type.
1785  */
1786  if (*cursor != ':')
1787  return false;
1788  else
1789  {
1790  cursor++; /* Go over colon */
1791  /* Skip over operating system field. */
1792  while (*cursor != ':' && *cursor != '\r')
1793  cursor++;
1794  if (*cursor != ':')
1795  return false;
1796  else
1797  {
1798  int i; /* Index into *ident_user */
1799 
1800  cursor++; /* Go over colon */
1801  while (pg_isblank(*cursor))
1802  cursor++; /* skip blanks */
1803  /* Rest of line is user name. Copy it over. */
1804  i = 0;
1805  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1806  ident_user[i++] = *cursor++;
1807  ident_user[i] = '\0';
1808  return true;
1809  }
1810  }
1811  }
1812  }
1813  }
1814 }
bool pg_isblank(const char c)
Definition: hba.c:158
#define IDENT_USERNAME_MAX
Definition: auth.c:71
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 3149 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().

3150 {
3151  radius_packet radius_send_pack;
3152  radius_packet radius_recv_pack;
3153  radius_packet *packet = &radius_send_pack;
3154  radius_packet *receivepacket = &radius_recv_pack;
3155  char *radius_buffer = (char *) &radius_send_pack;
3156  char *receive_buffer = (char *) &radius_recv_pack;
3158  uint8 *cryptvector;
3159  int encryptedpasswordlen;
3160  uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
3161  uint8 *md5trailer;
3162  int packetlength;
3163  pgsocket sock;
3164 
3165 #ifdef HAVE_IPV6
3166  struct sockaddr_in6 localaddr;
3167  struct sockaddr_in6 remoteaddr;
3168 #else
3169  struct sockaddr_in localaddr;
3170  struct sockaddr_in remoteaddr;
3171 #endif
3172  struct addrinfo hint;
3173  struct addrinfo *serveraddrs;
3174  int port;
3175  ACCEPT_TYPE_ARG3 addrsize;
3176  fd_set fdset;
3177  struct timeval endtime;
3178  int i,
3179  j,
3180  r;
3181 
3182  /* Assign default values */
3183  if (portstr == NULL)
3184  portstr = "1812";
3185  if (identifier == NULL)
3186  identifier = "postgresql";
3187 
3188  MemSet(&hint, 0, sizeof(hint));
3189  hint.ai_socktype = SOCK_DGRAM;
3190  hint.ai_family = AF_UNSPEC;
3191  port = atoi(portstr);
3192 
3193  r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
3194  if (r || !serveraddrs)
3195  {
3196  ereport(LOG,
3197  (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
3198  server, gai_strerror(r))));
3199  if (serveraddrs)
3200  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3201  return STATUS_ERROR;
3202  }
3203  /* XXX: add support for multiple returned addresses? */
3204 
3205  /* Construct RADIUS packet */
3206  packet->code = RADIUS_ACCESS_REQUEST;
3207  packet->length = RADIUS_HEADER_LENGTH;
3209  {
3210  ereport(LOG,
3211  (errmsg("could not generate random encryption vector")));
3212  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3213  return STATUS_ERROR;
3214  }
3215  packet->id = packet->vector[0];
3216  radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
3217  radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
3218  radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
3219 
3220  /*
3221  * RADIUS password attributes are calculated as: e[0] = p[0] XOR
3222  * MD5(secret + Request Authenticator) for the first group of 16 octets,
3223  * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
3224  * (if necessary)
3225  */
3226  encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
3227  cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
3228  memcpy(cryptvector, secret, strlen(secret));
3229 
3230  /* for the first iteration, we use the Request Authenticator vector */
3231  md5trailer = packet->vector;
3232  for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
3233  {
3234  memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
3235 
3236  /*
3237  * .. and for subsequent iterations the result of the previous XOR
3238  * (calculated below)
3239  */
3240  md5trailer = encryptedpassword + i;
3241 
3242  if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
3243  {
3244  ereport(LOG,
3245  (errmsg("could not perform MD5 encryption of password")));
3246  pfree(cryptvector);
3247  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3248  return STATUS_ERROR;
3249  }
3250 
3251  for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
3252  {
3253  if (j < strlen(passwd))
3254  encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
3255  else
3256  encryptedpassword[j] = '\0' ^ encryptedpassword[j];
3257  }
3258  }
3259  pfree(cryptvector);
3260 
3261  radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
3262 
3263  /* Length needs to be in network order on the wire */
3264  packetlength = packet->length;
3265  packet->length = pg_hton16(packet->length);
3266 
3267  sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
3268  if (sock == PGINVALID_SOCKET)
3269  {
3270  ereport(LOG,
3271  (errmsg("could not create RADIUS socket: %m")));
3272  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3273  return STATUS_ERROR;
3274  }
3275 
3276  memset(&localaddr, 0, sizeof(localaddr));
3277 #ifdef HAVE_IPV6
3278  localaddr.sin6_family = serveraddrs[0].ai_family;
3279  localaddr.sin6_addr = in6addr_any;
3280  if (localaddr.sin6_family == AF_INET6)
3281  addrsize = sizeof(struct sockaddr_in6);
3282  else
3283  addrsize = sizeof(struct sockaddr_in);
3284 #else
3285  localaddr.sin_family = serveraddrs[0].ai_family;
3286  localaddr.sin_addr.s_addr = INADDR_ANY;
3287  addrsize = sizeof(struct sockaddr_in);
3288 #endif
3289 
3290  if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
3291  {
3292  ereport(LOG,
3293  (errmsg("could not bind local RADIUS socket: %m")));
3294  closesocket(sock);
3295  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3296  return STATUS_ERROR;
3297  }
3298 
3299  if (sendto(sock, radius_buffer, packetlength, 0,
3300  serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
3301  {
3302  ereport(LOG,
3303  (errmsg("could not send RADIUS packet: %m")));
3304  closesocket(sock);
3305  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3306  return STATUS_ERROR;
3307  }
3308 
3309  /* Don't need the server address anymore */
3310  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3311 
3312  /*
3313  * Figure out at what time we should time out. We can't just use a single
3314  * call to select() with a timeout, since somebody can be sending invalid
3315  * packets to our port thus causing us to retry in a loop and never time
3316  * out.
3317  *
3318  * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
3319  * the latch was set would improve the responsiveness to
3320  * timeouts/cancellations.
3321  */
3322  gettimeofday(&endtime, NULL);
3323  endtime.tv_sec += RADIUS_TIMEOUT;
3324 
3325  while (true)
3326  {
3327  struct timeval timeout;
3328  struct timeval now;
3329  int64 timeoutval;
3330 
3331  gettimeofday(&now, NULL);
3332  timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
3333  if (timeoutval <= 0)
3334  {
3335  ereport(LOG,
3336  (errmsg("timeout waiting for RADIUS response from %s",
3337  server)));
3338  closesocket(sock);
3339  return STATUS_ERROR;
3340  }
3341  timeout.tv_sec = timeoutval / 1000000;
3342  timeout.tv_usec = timeoutval % 1000000;
3343 
3344  FD_ZERO(&fdset);
3345  FD_SET(sock, &fdset);
3346 
3347  r = select(sock + 1, &fdset, NULL, NULL, &timeout);
3348  if (r < 0)
3349  {
3350  if (errno == EINTR)
3351  continue;
3352 
3353  /* Anything else is an actual error */
3354  ereport(LOG,
3355  (errmsg("could not check status on RADIUS socket: %m")));
3356  closesocket(sock);
3357  return STATUS_ERROR;
3358  }
3359  if (r == 0)
3360  {
3361  ereport(LOG,
3362  (errmsg("timeout waiting for RADIUS response from %s",
3363  server)));
3364  closesocket(sock);
3365  return STATUS_ERROR;
3366  }
3367 
3368  /*
3369  * Attempt to read the response packet, and verify the contents.
3370  *
3371  * Any packet that's not actually a RADIUS packet, or otherwise does
3372  * not validate as an explicit reject, is just ignored and we retry
3373  * for another packet (until we reach the timeout). This is to avoid
3374  * the possibility to denial-of-service the login by flooding the
3375  * server with invalid packets on the port that we're expecting the
3376  * RADIUS response on.
3377  */
3378 
3379  addrsize = sizeof(remoteaddr);
3380  packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3381  (struct sockaddr *) &remoteaddr, &addrsize);
3382  if (packetlength < 0)
3383  {
3384  ereport(LOG,
3385  (errmsg("could not read RADIUS response: %m")));
3386  closesocket(sock);
3387  return STATUS_ERROR;
3388  }
3389 
3390 #ifdef HAVE_IPV6
3391  if (remoteaddr.sin6_port != pg_hton16(port))
3392 #else
3393  if (remoteaddr.sin_port != pg_hton16(port))
3394 #endif
3395  {
3396 #ifdef HAVE_IPV6
3397  ereport(LOG,
3398  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3399  server, pg_ntoh16(remoteaddr.sin6_port))));
3400 #else
3401  ereport(LOG,
3402  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3403  server, pg_ntoh16(remoteaddr.sin_port))));
3404 #endif
3405  continue;
3406  }
3407 
3408  if (packetlength < RADIUS_HEADER_LENGTH)
3409  {
3410  ereport(LOG,
3411  (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3412  continue;
3413  }
3414 
3415  if (packetlength != pg_ntoh16(receivepacket->length))
3416  {
3417  ereport(LOG,
3418  (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3419  server, pg_ntoh16(receivepacket->length), packetlength)));
3420  continue;
3421  }
3422 
3423  if (packet->id != receivepacket->id)
3424  {
3425  ereport(LOG,
3426  (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3427  server, receivepacket->id, packet->id)));
3428  continue;
3429  }
3430 
3431  /*
3432  * Verify the response authenticator, which is calculated as
3433  * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3434  */
3435  cryptvector = palloc(packetlength + strlen(secret));
3436 
3437  memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3438  memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3439  * authenticator, from
3440  * original packet */
3441  if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3442  * attributes at all */
3443  memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
3444  memcpy(cryptvector + packetlength, secret, strlen(secret));
3445 
3446  if (!pg_md5_binary(cryptvector,
3447  packetlength + strlen(secret),
3448  encryptedpassword))
3449  {
3450  ereport(LOG,
3451  (errmsg("could not perform MD5 encryption of received packet")));
3452  pfree(cryptvector);
3453  continue;
3454  }
3455  pfree(cryptvector);
3456 
3457  if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3458  {
3459  ereport(LOG,
3460  (errmsg("RADIUS response from %s has incorrect MD5 signature",
3461  server)));
3462  continue;
3463  }
3464 
3465  if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3466  {
3467  closesocket(sock);
3468  return STATUS_OK;
3469  }
3470  else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3471  {
3472  closesocket(sock);
3473  return STATUS_EOF;
3474  }
3475  else
3476  {
3477  ereport(LOG,
3478  (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3479  server, receivepacket->code, user_name)));
3480  continue;
3481  }
3482  } /* while (true) */
3483 }
#define RADIUS_PASSWORD
Definition: auth.c:3017
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:3004
#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:2986
#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:3019
#define bind(s, addr, addrlen)
Definition: win32_port.h:460
#define RADIUS_TIMEOUT
Definition: auth.c:3025
#define gai_strerror
Definition: getaddrinfo.h:146
signed int int32
Definition: c.h:429
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2987
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:1169
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define RADIUS_USER_NAME
Definition: auth.c:3016
#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:3012
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2991
#define socket(af, type, protocol)
Definition: win32_port.h:459
#define PGINVALID_SOCKET
Definition: port.h:33
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:3022
#define ereport(elevel,...)
Definition: elog.h:157
bool pg_strong_random(void *buf, size_t len)
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:3011
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2988
#define RADIUS_SERVICE_TYPE
Definition: auth.c:3018
uint8 id
Definition: auth.c:3003
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
uint8 code
Definition: auth.c:3002
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:3005
#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:3028
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1544
#define RADIUS_ACCESS_REJECT
Definition: auth.c:3013
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 3028 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().

3029 {
3030  radius_attribute *attr;
3031 
3032  if (packet->length + len > RADIUS_BUFFER_SIZE)
3033  {
3034  /*
3035  * With remotely realistic data, this can never happen. But catch it
3036  * just to make sure we don't overrun a buffer. We'll just skip adding
3037  * the broken attribute, which will in the end cause authentication to
3038  * fail.
3039  */
3040  elog(WARNING,
3041  "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
3042  type, len);
3043  return;
3044  }
3045 
3046  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
3047  attr->attribute = type;
3048  attr->length = len + 2; /* total size includes type and length */
3049  memcpy(attr->data, data, len);
3050  packet->length += attr->length;
3051 }
uint16 length
Definition: auth.c:3004
uint8 attribute
Definition: auth.c:2995
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2991
#define elog(elevel,...)
Definition: elog.h:232
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2997
uint8 length
Definition: auth.c:2996

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 702 of file auth.c.

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

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

703 {
705  int mtype;
706 
707  pq_startmsgread();
708 
709  /* Expect 'p' message type */
710  mtype = pq_getbyte();
711  if (mtype != 'p')
712  {
713  /*
714  * If the client just disconnects without offering a password, don't
715  * make a log entry. This is legal per protocol spec and in fact
716  * commonly done by psql, so complaining just clutters the log.
717  */
718  if (mtype != EOF)
719  ereport(ERROR,
720  (errcode(ERRCODE_PROTOCOL_VIOLATION),
721  errmsg("expected password response, got message type %d",
722  mtype)));
723  return NULL; /* EOF or bad message type */
724  }
725 
726  initStringInfo(&buf);
727  if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH)) /* receive password */
728  {
729  /* EOF - pq_getmessage already logged a suitable message */
730  pfree(buf.data);
731  return NULL;
732  }
733 
734  /*
735  * Apply sanity check: password packet length should agree with length of
736  * contained string. Note it is safe to use strlen here because
737  * StringInfo is guaranteed to have an appended '\0'.
738  */
739  if (strlen(buf.data) + 1 != buf.len)
740  ereport(ERROR,
741  (errcode(ERRCODE_PROTOCOL_VIOLATION),
742  errmsg("invalid password packet size")));
743 
744  /*
745  * Don't allow an empty password. Libpq treats an empty password the same
746  * as no password at all, and won't even try to authenticate. But other
747  * clients might, so allowing it would be confusing.
748  *
749  * Note that this only catches an empty password sent by the client in
750  * plaintext. There's also a check in CREATE/ALTER USER that prevents an
751  * empty string from being stored as a user's password in the first place.
752  * We rely on that for MD5 and SCRAM authentication, but we still need
753  * this check here, to prevent an empty password from being used with
754  * authentication methods that check the password against an external
755  * system, like PAM, LDAP and RADIUS.
756  */
757  if (buf.len == 1)
758  ereport(ERROR,
760  errmsg("empty password returned by client")));
761 
762  /* Do not echo password to logs, for security. */
763  elog(DEBUG5, "received password packet");
764 
765  /*
766  * Return the received string. Note we do not attempt to do any
767  * character-set conversion on it; since we don't yet know the client's
768  * encoding, there wouldn't be much point.
769  */
770  return buf.data;
771 }
int errcode(int sqlerrcode)
Definition: elog.c:698
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
void pq_startmsgread(void)
Definition: pqcomm.c:1152
static char * buf
Definition: pg_test_fsync.c:68
#define PG_MAX_AUTH_TOKEN_LENGTH
Definition: auth.c:225
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1214
int pq_getbyte(void)
Definition: pqcomm.c:994
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#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 672 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().

673 {
675 
677 
678  pq_beginmessage(&buf, 'R');
679  pq_sendint32(&buf, (int32) areq);
680  if (extralen > 0)
681  pq_sendbytes(&buf, extradata, extralen);
682 
683  pq_endmessage(&buf);
684 
685  /*
686  * Flush message so client will see it, except for AUTH_REQ_OK and
687  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
688  * queries.
689  */
690  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
691  pq_flush();
692 
694 }
#define pq_flush()
Definition: libpq.h:46
#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:120

◆ set_authn_id()

static void set_authn_id ( Port port,
const char *  id 
)
static

Definition at line 358 of file auth.c.

References Assert, HbaLine::auth_method, Port::authn_id, ereport, errdetail_log(), errmsg(), FATAL, Port::hba, hba_authname(), HbaFileName, HbaLine::linenumber, LOG, Log_connections, MemoryContextStrdup(), and TopMemoryContext.

Referenced by auth_peer(), CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), CheckSCRAMAuth(), and ident_inet().

359 {
360  Assert(id);
361 
362  if (port->authn_id)
363  {
364  /*
365  * An existing authn_id should never be overwritten; that means two
366  * authentication providers are fighting (or one is fighting itself).
367  * Don't leak any authn details to the client, but don't let the
368  * connection continue, either.
369  */
370  ereport(FATAL,
371  (errmsg("connection was re-authenticated"),
372  errdetail_log("previous ID: \"%s\"; new ID: \"%s\"",
373  port->authn_id, id)));
374  }
375 
377 
378  if (Log_connections)
379  {
380  ereport(LOG,
381  errmsg("connection authenticated: identity=\"%s\" method=%s "
382  "(%s:%d)",
384  port->hba->linenumber));
385  }
386 }
const char * authn_id
Definition: libpq-be.h:173
#define LOG
Definition: elog.h:26
bool Log_connections
Definition: postmaster.c:240
char * HbaFileName
Definition: guc.c:599
#define FATAL
Definition: elog.h:49
int errdetail_log(const char *fmt,...)
Definition: elog.c:1090
int linenumber
Definition: hba.h:82
MemoryContext TopMemoryContext
Definition: mcxt.c:48
HbaLine * hba
Definition: libpq-be.h:160
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3153
UserAuth auth_method
Definition: hba.h:93

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 245 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 173 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 172 of file auth.c.

Referenced by CheckSCRAMAuth(), and secure_open_gssapi().