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 "libpq/auth.h"
#include "libpq/crypt.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/sasl.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 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 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 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)
 
void sendAuthRequest (Port *port, AuthRequest areq, const char *extradata, int extralen)
 
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 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 222 of file auth.c.

Referenced by CheckMD5Auth(), and recv_password_packet().

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2866 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2867 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2865 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2876 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2845 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2841 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2842 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2873 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2871 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2872 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2879 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2870 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

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

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

1866 {
1867  uid_t uid;
1868  gid_t gid;
1869 #ifndef WIN32
1870  struct passwd *pw;
1871  int ret;
1872 #endif
1873 
1874  if (getpeereid(port->sock, &uid, &gid) != 0)
1875  {
1876  /* Provide special error message if getpeereid is a stub */
1877  if (errno == ENOSYS)
1878  ereport(LOG,
1879  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1880  errmsg("peer authentication is not supported on this platform")));
1881  else
1882  ereport(LOG,
1884  errmsg("could not get peer credentials: %m")));
1885  return STATUS_ERROR;
1886  }
1887 
1888 #ifndef WIN32
1889  errno = 0; /* clear errno before call */
1890  pw = getpwuid(uid);
1891  if (!pw)
1892  {
1893  int save_errno = errno;
1894 
1895  ereport(LOG,
1896  (errmsg("could not look up local user ID %ld: %s",
1897  (long) uid,
1898  save_errno ? strerror(save_errno) : _("user does not exist"))));
1899  return STATUS_ERROR;
1900  }
1901 
1902  /*
1903  * Make a copy of static getpw*() result area; this is our authenticated
1904  * identity. Set it before calling check_usermap, because authentication
1905  * has already succeeded and we want the log file to reflect that.
1906  */
1907  set_authn_id(port, pw->pw_name);
1908 
1909  ret = check_usermap(port->hba->usermap, port->user_name, port->authn_id, false);
1910 
1911  return ret;
1912 #else
1913  /* should have failed with ENOSYS above */
1914  Assert(false);
1915  return STATUS_ERROR;
1916 #endif
1917 }
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:347
#define _(x)
Definition: elog.c:89

◆ CheckMD5Auth()

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

Definition at line 869 of file auth.c.

References _, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, buf, CHECK_FOR_INTERRUPTS, check_usermap(), HbaLine::compat_realm, StringInfoData::data, Db_user_namespace, 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, md5_crypt_verify(), MemoryContextStrdup(), palloc(), pfree(), pg_GSS_error(), pg_krb_caseins_users, pg_krb_server_keyfile, PG_MAX_AUTH_TOKEN_LENGTH, pg_strcasecmp(), pg_strong_random(), port, pq_getbyte(), pq_getmessage(), pq_startmsgread(), psprintf(), recv_password_packet(), 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().

870 {
871  char md5Salt[4]; /* Password salt */
872  char *passwd;
873  int result;
874 
875  if (Db_user_namespace)
876  ereport(FATAL,
877  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
878  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
879 
880  /* include the salt to use for computing the response */
881  if (!pg_strong_random(md5Salt, 4))
882  {
883  ereport(LOG,
884  (errmsg("could not generate random MD5 salt")));
885  return STATUS_ERROR;
886  }
887 
888  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
889 
890  passwd = recv_password_packet(port);
891  if (passwd == NULL)
892  return STATUS_EOF; /* client wouldn't send password */
893 
894  if (shadow_pass)
895  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
896  md5Salt, 4, logdetail);
897  else
898  result = STATUS_ERROR;
899 
900  pfree(passwd);
901 
902  return result;
903 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define STATUS_ERROR
Definition: c.h:1171
void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:661
#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:691
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 772 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().

773 {
774  char *passwd;
775  int result;
776  char *shadow_pass;
777 
778  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
779 
780  passwd = recv_password_packet(port);
781  if (passwd == NULL)
782  return STATUS_EOF; /* client wouldn't send password */
783 
784  shadow_pass = get_role_password(port->user_name, logdetail);
785  if (shadow_pass)
786  {
787  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
788  logdetail);
789  }
790  else
791  result = STATUS_ERROR;
792 
793  if (shadow_pass)
794  pfree(shadow_pass);
795  pfree(passwd);
796 
797  if (result == STATUS_OK)
798  set_authn_id(port, port->user_name);
799 
800  return result;
801 }
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 sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:661
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:691
#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:347

◆ CheckPWChallengeAuth()

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

Definition at line 807 of file auth.c.

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

Referenced by ClientAuthentication().

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

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

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

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

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

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

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

1681 {
1682  const SockAddr remote_addr = port->raddr;
1683  const SockAddr local_addr = port->laddr;
1684  char ident_user[IDENT_USERNAME_MAX + 1];
1685  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1686  int rc; /* Return code from a locally called function */
1687  bool ident_return;
1688  char remote_addr_s[NI_MAXHOST];
1689  char remote_port[NI_MAXSERV];
1690  char local_addr_s[NI_MAXHOST];
1691  char local_port[NI_MAXSERV];
1692  char ident_port[NI_MAXSERV];
1693  char ident_query[80];
1694  char ident_response[80 + IDENT_USERNAME_MAX];
1695  struct addrinfo *ident_serv = NULL,
1696  *la = NULL,
1697  hints;
1698 
1699  /*
1700  * Might look a little weird to first convert it to text and then back to
1701  * sockaddr, but it's protocol independent.
1702  */
1703  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1704  remote_addr_s, sizeof(remote_addr_s),
1705  remote_port, sizeof(remote_port),
1707  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1708  local_addr_s, sizeof(local_addr_s),
1709  local_port, sizeof(local_port),
1711 
1712  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1713  hints.ai_flags = AI_NUMERICHOST;
1714  hints.ai_family = remote_addr.addr.ss_family;
1715  hints.ai_socktype = SOCK_STREAM;
1716  hints.ai_protocol = 0;
1717  hints.ai_addrlen = 0;
1718  hints.ai_canonname = NULL;
1719  hints.ai_addr = NULL;
1720  hints.ai_next = NULL;
1721  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1722  if (rc || !ident_serv)
1723  {
1724  /* we don't expect this to happen */
1725  ident_return = false;
1726  goto ident_inet_done;
1727  }
1728 
1729  hints.ai_flags = AI_NUMERICHOST;
1730  hints.ai_family = local_addr.addr.ss_family;
1731  hints.ai_socktype = SOCK_STREAM;
1732  hints.ai_protocol = 0;
1733  hints.ai_addrlen = 0;
1734  hints.ai_canonname = NULL;
1735  hints.ai_addr = NULL;
1736  hints.ai_next = NULL;
1737  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1738  if (rc || !la)
1739  {
1740  /* we don't expect this to happen */
1741  ident_return = false;
1742  goto ident_inet_done;
1743  }
1744 
1745  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1746  ident_serv->ai_protocol);
1747  if (sock_fd == PGINVALID_SOCKET)
1748  {
1749  ereport(LOG,
1751  errmsg("could not create socket for Ident connection: %m")));
1752  ident_return = false;
1753  goto ident_inet_done;
1754  }
1755 
1756  /*
1757  * Bind to the address which the client originally contacted, otherwise
1758  * the ident server won't be able to match up the right connection. This
1759  * is necessary if the PostgreSQL server is running on an IP alias.
1760  */
1761  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1762  if (rc != 0)
1763  {
1764  ereport(LOG,
1766  errmsg("could not bind to local address \"%s\": %m",
1767  local_addr_s)));
1768  ident_return = false;
1769  goto ident_inet_done;
1770  }
1771 
1772  rc = connect(sock_fd, ident_serv->ai_addr,
1773  ident_serv->ai_addrlen);
1774  if (rc != 0)
1775  {
1776  ereport(LOG,
1778  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1779  remote_addr_s, ident_port)));
1780  ident_return = false;
1781  goto ident_inet_done;
1782  }
1783 
1784  /* The query we send to the Ident server */
1785  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1786  remote_port, local_port);
1787 
1788  /* loop in case send is interrupted */
1789  do
1790  {
1792 
1793  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1794  } while (rc < 0 && errno == EINTR);
1795 
1796  if (rc < 0)
1797  {
1798  ereport(LOG,
1800  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1801  remote_addr_s, ident_port)));
1802  ident_return = false;
1803  goto ident_inet_done;
1804  }
1805 
1806  do
1807  {
1809 
1810  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1811  } while (rc < 0 && errno == EINTR);
1812 
1813  if (rc < 0)
1814  {
1815  ereport(LOG,
1817  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1818  remote_addr_s, ident_port)));
1819  ident_return = false;
1820  goto ident_inet_done;
1821  }
1822 
1823  ident_response[rc] = '\0';
1824  ident_return = interpret_ident_response(ident_response, ident_user);
1825  if (!ident_return)
1826  ereport(LOG,
1827  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1828  ident_response)));
1829 
1830 ident_inet_done:
1831  if (sock_fd != PGINVALID_SOCKET)
1832  closesocket(sock_fd);
1833  if (ident_serv)
1834  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1835  if (la)
1836  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1837 
1838  if (ident_return)
1839  {
1840  /*
1841  * Success! Store the identity, then check the usermap. Note that
1842  * setting the authenticated identity is done before checking the
1843  * usermap, because at this point authentication has succeeded.
1844  */
1845  set_authn_id(port, ident_user);
1846  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1847  }
1848  return STATUS_ERROR;
1849 }
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:68
#define NI_MAXHOST
Definition: getaddrinfo.h:88
char * usermap
Definition: hba.h:94
#define IDENT_PORT
Definition: auth.c:71
#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:347
#define snprintf
Definition: port.h:216
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1597
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 1597 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1599 {
1600  const char *cursor = ident_response; /* Cursor into *ident_response */
1601 
1602  /*
1603  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1604  */
1605  if (strlen(ident_response) < 2)
1606  return false;
1607  else if (ident_response[strlen(ident_response) - 2] != '\r')
1608  return false;
1609  else
1610  {
1611  while (*cursor != ':' && *cursor != '\r')
1612  cursor++; /* skip port field */
1613 
1614  if (*cursor != ':')
1615  return false;
1616  else
1617  {
1618  /* We're positioned to colon before response type field */
1619  char response_type[80];
1620  int i; /* Index into *response_type */
1621 
1622  cursor++; /* Go over colon */
1623  while (pg_isblank(*cursor))
1624  cursor++; /* skip blanks */
1625  i = 0;
1626  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1627  i < (int) (sizeof(response_type) - 1))
1628  response_type[i++] = *cursor++;
1629  response_type[i] = '\0';
1630  while (pg_isblank(*cursor))
1631  cursor++; /* skip blanks */
1632  if (strcmp(response_type, "USERID") != 0)
1633  return false;
1634  else
1635  {
1636  /*
1637  * It's a USERID response. Good. "cursor" should be pointing
1638  * to the colon that precedes the operating system type.
1639  */
1640  if (*cursor != ':')
1641  return false;
1642  else
1643  {
1644  cursor++; /* Go over colon */
1645  /* Skip over operating system field. */
1646  while (*cursor != ':' && *cursor != '\r')
1647  cursor++;
1648  if (*cursor != ':')
1649  return false;
1650  else
1651  {
1652  int i; /* Index into *ident_user */
1653 
1654  cursor++; /* Go over colon */
1655  while (pg_isblank(*cursor))
1656  cursor++; /* skip blanks */
1657  /* Rest of line is user name. Copy it over. */
1658  i = 0;
1659  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1660  ident_user[i++] = *cursor++;
1661  ident_user[i] = '\0';
1662  return true;
1663  }
1664  }
1665  }
1666  }
1667  }
1668 }
bool pg_isblank(const char c)
Definition: hba.c:158
#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 3003 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().

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

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

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

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

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

◆ sendAuthRequest()

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

Definition at line 661 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(), CheckSASLAuth(), and ClientAuthentication().

662 {
664 
666 
667  pq_beginmessage(&buf, 'R');
668  pq_sendint32(&buf, (int32) areq);
669  if (extralen > 0)
670  pq_sendbytes(&buf, extradata, extralen);
671 
672  pq_endmessage(&buf);
673 
674  /*
675  * Flush message so client will see it, except for AUTH_REQ_OK and
676  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
677  * queries.
678  */
679  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
680  pq_flush();
681 
683 }
#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 347 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(), CheckMD5Auth(), CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), and ident_inet().

348 {
349  Assert(id);
350 
351  if (port->authn_id)
352  {
353  /*
354  * An existing authn_id should never be overwritten; that means two
355  * authentication providers are fighting (or one is fighting itself).
356  * Don't leak any authn details to the client, but don't let the
357  * connection continue, either.
358  */
359  ereport(FATAL,
360  (errmsg("authentication identifier set more than once"),
361  errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
362  port->authn_id, id)));
363  }
364 
366 
367  if (Log_connections)
368  {
369  ereport(LOG,
370  errmsg("connection authenticated: identity=\"%s\" method=%s "
371  "(%s:%d)",
373  port->hba->linenumber));
374  }
375 }
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:615
#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 234 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 CheckMD5Auth().

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 169 of file auth.c.

Referenced by CheckMD5Auth(), and secure_open_gssapi().