PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
auth.c File Reference
#include "postgres.h"
#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.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/memutils.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, const char *logdetail)
 
static char * recv_password_packet (Port *port)
 
static void set_authn_id (Port *port, const char *id)
 
static int CheckPasswordAuth (Port *port, const char **logdetail)
 
static int CheckPWChallengeAuth (Port *port, const char **logdetail)
 
static int CheckMD5Auth (Port *port, char *shadow_pass, const 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
 
bool pg_gss_accept_delegation
 
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))
int errdetail_log(const char *fmt,...)
Definition: elog.c:1251
static int port
Definition: pg_regress.c:115
const char * gai_strerror(int ecode)

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 70 of file auth.c.

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 67 of file auth.c.

◆ PG_MAX_AUTH_TOKEN_LENGTH

#define PG_MAX_AUTH_TOKEN_LENGTH   65535

Definition at line 218 of file auth.c.

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2802 of file auth.c.

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2803 of file auth.c.

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2801 of file auth.c.

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2812 of file auth.c.

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2781 of file auth.c.

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2777 of file auth.c.

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2778 of file auth.c.

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2809 of file auth.c.

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2807 of file auth.c.

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2808 of file auth.c.

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2815 of file auth.c.

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2806 of file auth.c.

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2776 of file auth.c.

Function Documentation

◆ auth_failed()

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

Definition at line 246 of file auth.c.

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

References _, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errdetail_log(), errmsg(), FATAL, gettext_noop, port, proc_exit(), psprintf(), STATUS_EOF, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by ClientAuthentication().

◆ auth_peer()

static int auth_peer ( hbaPort port)
static

Definition at line 1855 of file auth.c.

1856 {
1857  uid_t uid;
1858  gid_t gid;
1859 #ifndef WIN32
1860  struct passwd pwbuf;
1861  struct passwd *pw;
1862  char buf[1024];
1863  int rc;
1864  int ret;
1865 #endif
1866 
1867  if (getpeereid(port->sock, &uid, &gid) != 0)
1868  {
1869  /* Provide special error message if getpeereid is a stub */
1870  if (errno == ENOSYS)
1871  ereport(LOG,
1872  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1873  errmsg("peer authentication is not supported on this platform")));
1874  else
1875  ereport(LOG,
1877  errmsg("could not get peer credentials: %m")));
1878  return STATUS_ERROR;
1879  }
1880 
1881 #ifndef WIN32
1882  rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1883  if (rc != 0)
1884  {
1885  errno = rc;
1886  ereport(LOG,
1887  errmsg("could not look up local user ID %ld: %m", (long) uid));
1888  return STATUS_ERROR;
1889  }
1890  else if (!pw)
1891  {
1892  ereport(LOG,
1893  errmsg("local user with ID %ld does not exist", (long) uid));
1894  return STATUS_ERROR;
1895  }
1896 
1897  /*
1898  * Make a copy of static getpw*() result area; this is our authenticated
1899  * identity. Set it before calling check_usermap, because authentication
1900  * has already succeeded and we want the log file to reflect that.
1901  */
1902  set_authn_id(port, pw->pw_name);
1903 
1904  ret = check_usermap(port->hba->usermap, port->user_name,
1906 
1907  return ret;
1908 #else
1909  /* should have failed with ENOSYS above */
1910  Assert(false);
1911  return STATUS_ERROR;
1912 #endif
1913 }
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:344
#define Assert(condition)
Definition: c.h:863
#define STATUS_ERROR
Definition: c.h:1175
int errcode_for_socket_access(void)
Definition: elog.c:953
#define LOG
Definition: elog.h:31
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
Definition: hba.c:2908
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1071
static char * buf
Definition: pg_test_fsync.c:72
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:33
const char * authn_id
Definition: libpq-be.h:103
int gid_t
Definition: win32_port.h:245
int uid_t
Definition: win32_port.h:244

References Assert, ClientConnectionInfo::authn_id, buf, check_usermap(), ereport, errcode(), errcode_for_socket_access(), errmsg(), getpeereid(), LOG, MyClientConnectionInfo, port, set_authn_id(), and STATUS_ERROR.

Referenced by ClientAuthentication().

◆ CheckMD5Auth()

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

Definition at line 882 of file auth.c.

883 {
884  char md5Salt[4]; /* Password salt */
885  char *passwd;
886  int result;
887 
888  /* include the salt to use for computing the response */
889  if (!pg_strong_random(md5Salt, 4))
890  {
891  ereport(LOG,
892  (errmsg("could not generate random MD5 salt")));
893  return STATUS_ERROR;
894  }
895 
896  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
897 
898  passwd = recv_password_packet(port);
899  if (passwd == NULL)
900  return STATUS_EOF; /* client wouldn't send password */
901 
902  if (shadow_pass)
903  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
904  md5Salt, 4, logdetail);
905  else
906  result = STATUS_ERROR;
907 
908  pfree(passwd);
909 
910  return result;
911 }
void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:676
static char * recv_password_packet(Port *port)
Definition: auth.c:706
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, const char **logdetail)
Definition: crypt.c:192
void pfree(void *pointer)
Definition: mcxt.c:1521
bool pg_strong_random(void *buf, size_t len)
#define AUTH_REQ_MD5
Definition: protocol.h:79

References AUTH_REQ_MD5, ereport, errmsg(), LOG, md5_crypt_verify(), pfree(), pg_strong_random(), port, recv_password_packet(), sendAuthRequest(), STATUS_EOF, and STATUS_ERROR.

Referenced by CheckPWChallengeAuth().

◆ CheckPasswordAuth()

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

Definition at line 787 of file auth.c.

788 {
789  char *passwd;
790  int result;
791  char *shadow_pass;
792 
794 
795  passwd = recv_password_packet(port);
796  if (passwd == NULL)
797  return STATUS_EOF; /* client wouldn't send password */
798 
799  shadow_pass = get_role_password(port->user_name, logdetail);
800  if (shadow_pass)
801  {
802  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
803  logdetail);
804  }
805  else
806  result = STATUS_ERROR;
807 
808  if (shadow_pass)
809  pfree(shadow_pass);
810  pfree(passwd);
811 
812  if (result == STATUS_OK)
813  set_authn_id(port, port->user_name);
814 
815  return result;
816 }
#define STATUS_OK
Definition: c.h:1174
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition: crypt.c:246
char * get_role_password(const char *role, const char **logdetail)
Definition: crypt.c:36
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77

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

Referenced by ClientAuthentication().

◆ CheckPWChallengeAuth()

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

Definition at line 822 of file auth.c.

823 {
824  int auth_result;
825  char *shadow_pass;
826  PasswordType pwtype;
827 
828  Assert(port->hba->auth_method == uaSCRAM ||
829  port->hba->auth_method == uaMD5);
830 
831  /* First look up the user's password. */
832  shadow_pass = get_role_password(port->user_name, logdetail);
833 
834  /*
835  * If the user does not exist, or has no password or it's expired, we
836  * still go through the motions of authentication, to avoid revealing to
837  * the client that the user didn't exist. If 'md5' is allowed, we choose
838  * whether to use 'md5' or 'scram-sha-256' authentication based on current
839  * password_encryption setting. The idea is that most genuine users
840  * probably have a password of that type, and if we pretend that this user
841  * had a password of that type, too, it "blends in" best.
842  */
843  if (!shadow_pass)
844  pwtype = Password_encryption;
845  else
846  pwtype = get_password_type(shadow_pass);
847 
848  /*
849  * If 'md5' authentication is allowed, decide whether to perform 'md5' or
850  * 'scram-sha-256' authentication based on the type of password the user
851  * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
852  * SCRAM secret, we must do SCRAM authentication.
853  *
854  * If MD5 authentication is not allowed, always use SCRAM. If the user
855  * had an MD5 password, CheckSASLAuth() with the SCRAM mechanism will
856  * fail.
857  */
858  if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
859  auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
860  else
861  auth_result = CheckSASLAuth(&pg_be_scram_mech, port, shadow_pass,
862  logdetail);
863 
864  if (shadow_pass)
865  pfree(shadow_pass);
866  else
867  {
868  /*
869  * If get_role_password() returned error, authentication better not
870  * have succeeded.
871  */
872  Assert(auth_result != STATUS_OK);
873  }
874 
875  if (auth_result == STATUS_OK)
876  set_authn_id(port, port->user_name);
877 
878  return auth_result;
879 }
int CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, const char **logdetail)
Definition: auth-sasl.c:44
const pg_be_sasl_mech pg_be_scram_mech
Definition: auth-scram.c:113
static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
Definition: auth.c:882
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:88
PasswordType
Definition: crypt.h:38
@ PASSWORD_TYPE_MD5
Definition: crypt.h:40
int Password_encryption
Definition: user.c:85

References Assert, CheckMD5Auth(), CheckSASLAuth(), get_password_type(), get_role_password(), Password_encryption, PASSWORD_TYPE_MD5, pfree(), pg_be_scram_mech, port, set_authn_id(), STATUS_OK, uaMD5, and uaSCRAM.

Referenced by ClientAuthentication().

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

Definition at line 2844 of file auth.c.

2845 {
2846  char *passwd;
2847  ListCell *server,
2848  *secrets,
2849  *radiusports,
2850  *identifiers;
2851 
2852  /* Make sure struct alignment is correct */
2853  Assert(offsetof(radius_packet, vector) == 4);
2854 
2855  /* Verify parameters */
2856  if (port->hba->radiusservers == NIL)
2857  {
2858  ereport(LOG,
2859  (errmsg("RADIUS server not specified")));
2860  return STATUS_ERROR;
2861  }
2862 
2863  if (port->hba->radiussecrets == NIL)
2864  {
2865  ereport(LOG,
2866  (errmsg("RADIUS secret not specified")));
2867  return STATUS_ERROR;
2868  }
2869 
2870  /* Send regular password request to client, and get the response */
2872 
2873  passwd = recv_password_packet(port);
2874  if (passwd == NULL)
2875  return STATUS_EOF; /* client wouldn't send password */
2876 
2877  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2878  {
2879  ereport(LOG,
2880  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2881  pfree(passwd);
2882  return STATUS_ERROR;
2883  }
2884 
2885  /*
2886  * Loop over and try each server in order.
2887  */
2888  secrets = list_head(port->hba->radiussecrets);
2889  radiusports = list_head(port->hba->radiusports);
2890  identifiers = list_head(port->hba->radiusidentifiers);
2891  foreach(server, port->hba->radiusservers)
2892  {
2893  int ret = PerformRadiusTransaction(lfirst(server),
2894  lfirst(secrets),
2895  radiusports ? lfirst(radiusports) : NULL,
2896  identifiers ? lfirst(identifiers) : NULL,
2897  port->user_name,
2898  passwd);
2899 
2900  /*------
2901  * STATUS_OK = Login OK
2902  * STATUS_ERROR = Login not OK, but try next server
2903  * STATUS_EOF = Login not OK, and don't try next server
2904  *------
2905  */
2906  if (ret == STATUS_OK)
2907  {
2908  set_authn_id(port, port->user_name);
2909 
2910  pfree(passwd);
2911  return STATUS_OK;
2912  }
2913  else if (ret == STATUS_EOF)
2914  {
2915  pfree(passwd);
2916  return STATUS_ERROR;
2917  }
2918 
2919  /*
2920  * secret, port and identifiers either have length 0 (use default),
2921  * length 1 (use the same everywhere) or the same length as servers.
2922  * So if the length is >1, we advance one step. In other cases, we
2923  * don't and will then reuse the correct value.
2924  */
2925  if (list_length(port->hba->radiussecrets) > 1)
2926  secrets = lnext(port->hba->radiussecrets, secrets);
2927  if (list_length(port->hba->radiusports) > 1)
2928  radiusports = lnext(port->hba->radiusports, radiusports);
2929  if (list_length(port->hba->radiusidentifiers) > 1)
2930  identifiers = lnext(port->hba->radiusidentifiers, identifiers);
2931  }
2932 
2933  /* No servers left to try, so give up */
2934  pfree(passwd);
2935  return STATUS_ERROR;
2936 }
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2778
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:2939
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

References Assert, AUTH_REQ_PASSWORD, ereport, errmsg(), lfirst, list_head(), list_length(), lnext(), LOG, NIL, PerformRadiusTransaction(), pfree(), port, RADIUS_MAX_PASSWORD_LENGTH, recv_password_packet(), sendAuthRequest(), set_authn_id(), STATUS_EOF, STATUS_ERROR, and STATUS_OK.

Referenced by ClientAuthentication().

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 382 of file auth.c.

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

References _, am_db_walsender, am_walsender, Assert, auth_failed(), auth_peer(), AUTH_REQ_GSS, AUTH_REQ_OK, AUTH_REQ_SSPI, ClientConnectionInfo::authn_id, CHECK_FOR_INTERRUPTS, CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), ClientAuthentication_hook, clientCertFull, clientCertOff, ereport, errcode(), errmsg(), FATAL, hba_authname(), hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), LOG, Log_connections, MemoryContextAllocZero(), MyClientConnectionInfo, pg_getnameinfo_all(), port, secure_loaded_verify_locations(), sendAuthRequest(), STATUS_ERROR, STATUS_OK, TopMemoryContext, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by PerformAuthentication().

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1670 of file auth.c.

1671 {
1672  const SockAddr remote_addr = port->raddr;
1673  const SockAddr local_addr = port->laddr;
1674  char ident_user[IDENT_USERNAME_MAX + 1];
1675  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1676  int rc; /* Return code from a locally called function */
1677  bool ident_return;
1678  char remote_addr_s[NI_MAXHOST];
1679  char remote_port[NI_MAXSERV];
1680  char local_addr_s[NI_MAXHOST];
1681  char local_port[NI_MAXSERV];
1682  char ident_port[NI_MAXSERV];
1683  char ident_query[80];
1684  char ident_response[80 + IDENT_USERNAME_MAX];
1685  struct addrinfo *ident_serv = NULL,
1686  *la = NULL,
1687  hints;
1688 
1689  /*
1690  * Might look a little weird to first convert it to text and then back to
1691  * sockaddr, but it's protocol independent.
1692  */
1693  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1694  remote_addr_s, sizeof(remote_addr_s),
1695  remote_port, sizeof(remote_port),
1696  NI_NUMERICHOST | NI_NUMERICSERV);
1697  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1698  local_addr_s, sizeof(local_addr_s),
1699  local_port, sizeof(local_port),
1700  NI_NUMERICHOST | NI_NUMERICSERV);
1701 
1702  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1703  hints.ai_flags = AI_NUMERICHOST;
1704  hints.ai_family = remote_addr.addr.ss_family;
1705  hints.ai_socktype = SOCK_STREAM;
1706  hints.ai_protocol = 0;
1707  hints.ai_addrlen = 0;
1708  hints.ai_canonname = NULL;
1709  hints.ai_addr = NULL;
1710  hints.ai_next = NULL;
1711  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1712  if (rc || !ident_serv)
1713  {
1714  /* we don't expect this to happen */
1715  ident_return = false;
1716  goto ident_inet_done;
1717  }
1718 
1719  hints.ai_flags = AI_NUMERICHOST;
1720  hints.ai_family = local_addr.addr.ss_family;
1721  hints.ai_socktype = SOCK_STREAM;
1722  hints.ai_protocol = 0;
1723  hints.ai_addrlen = 0;
1724  hints.ai_canonname = NULL;
1725  hints.ai_addr = NULL;
1726  hints.ai_next = NULL;
1727  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1728  if (rc || !la)
1729  {
1730  /* we don't expect this to happen */
1731  ident_return = false;
1732  goto ident_inet_done;
1733  }
1734 
1735  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1736  ident_serv->ai_protocol);
1737  if (sock_fd == PGINVALID_SOCKET)
1738  {
1739  ereport(LOG,
1741  errmsg("could not create socket for Ident connection: %m")));
1742  ident_return = false;
1743  goto ident_inet_done;
1744  }
1745 
1746  /*
1747  * Bind to the address which the client originally contacted, otherwise
1748  * the ident server won't be able to match up the right connection. This
1749  * is necessary if the PostgreSQL server is running on an IP alias.
1750  */
1751  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1752  if (rc != 0)
1753  {
1754  ereport(LOG,
1756  errmsg("could not bind to local address \"%s\": %m",
1757  local_addr_s)));
1758  ident_return = false;
1759  goto ident_inet_done;
1760  }
1761 
1762  rc = connect(sock_fd, ident_serv->ai_addr,
1763  ident_serv->ai_addrlen);
1764  if (rc != 0)
1765  {
1766  ereport(LOG,
1768  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1769  remote_addr_s, ident_port)));
1770  ident_return = false;
1771  goto ident_inet_done;
1772  }
1773 
1774  /* The query we send to the Ident server */
1775  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1776  remote_port, local_port);
1777 
1778  /* loop in case send is interrupted */
1779  do
1780  {
1782 
1783  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1784  } while (rc < 0 && errno == EINTR);
1785 
1786  if (rc < 0)
1787  {
1788  ereport(LOG,
1790  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1791  remote_addr_s, ident_port)));
1792  ident_return = false;
1793  goto ident_inet_done;
1794  }
1795 
1796  do
1797  {
1799 
1800  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1801  } while (rc < 0 && errno == EINTR);
1802 
1803  if (rc < 0)
1804  {
1805  ereport(LOG,
1807  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1808  remote_addr_s, ident_port)));
1809  ident_return = false;
1810  goto ident_inet_done;
1811  }
1812 
1813  ident_response[rc] = '\0';
1814  ident_return = interpret_ident_response(ident_response, ident_user);
1815  if (!ident_return)
1816  ereport(LOG,
1817  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1818  ident_response)));
1819 
1820 ident_inet_done:
1821  if (sock_fd != PGINVALID_SOCKET)
1822  closesocket(sock_fd);
1823  if (ident_serv)
1824  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1825  if (la)
1826  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1827 
1828  if (ident_return)
1829  {
1830  /*
1831  * Success! Store the identity, then check the usermap. Note that
1832  * setting the authenticated identity is done before checking the
1833  * usermap, because at this point authentication has succeeded.
1834  */
1835  set_authn_id(port, ident_user);
1836  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1837  }
1838  return STATUS_ERROR;
1839 }
#define IDENT_USERNAME_MAX
Definition: auth.c:67
#define IDENT_PORT
Definition: auth.c:70
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1589
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
int pgsocket
Definition: port.h:29
#define snprintf
Definition: port.h:238
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:349
struct sockaddr_storage addr
Definition: pqcomm.h:32
socklen_t salen
Definition: pqcomm.h:33
#define bind(s, addr, addrlen)
Definition: win32_port.h:509
#define EINTR
Definition: win32_port.h:374
#define recv(s, buf, len, flags)
Definition: win32_port.h:514
#define send(s, buf, len, flags)
Definition: win32_port.h:515
#define socket(af, type, protocol)
Definition: win32_port.h:508
#define connect(s, name, namelen)
Definition: win32_port.h:512

References SockAddr::addr, bind, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, EINTR, ereport, errcode_for_socket_access(), errmsg(), IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), LOG, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, port, recv, SockAddr::salen, send, set_authn_id(), snprintf, socket, and STATUS_ERROR.

Referenced by ClientAuthentication().

◆ interpret_ident_response()

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

Definition at line 1589 of file auth.c.

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

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

◆ 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 2939 of file auth.c.

2940 {
2941  radius_packet radius_send_pack;
2942  radius_packet radius_recv_pack;
2943  radius_packet *packet = &radius_send_pack;
2944  radius_packet *receivepacket = &radius_recv_pack;
2945  char *radius_buffer = (char *) &radius_send_pack;
2946  char *receive_buffer = (char *) &radius_recv_pack;
2948  uint8 *cryptvector;
2949  int encryptedpasswordlen;
2950  uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
2951  uint8 *md5trailer;
2952  int packetlength;
2953  pgsocket sock;
2954 
2955  struct sockaddr_in6 localaddr;
2956  struct sockaddr_in6 remoteaddr;
2957  struct addrinfo hint;
2958  struct addrinfo *serveraddrs;
2959  int port;
2960  socklen_t addrsize;
2961  fd_set fdset;
2962  struct timeval endtime;
2963  int i,
2964  j,
2965  r;
2966 
2967  /* Assign default values */
2968  if (portstr == NULL)
2969  portstr = "1812";
2970  if (identifier == NULL)
2971  identifier = "postgresql";
2972 
2973  MemSet(&hint, 0, sizeof(hint));
2974  hint.ai_socktype = SOCK_DGRAM;
2975  hint.ai_family = AF_UNSPEC;
2976  port = atoi(portstr);
2977 
2978  r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
2979  if (r || !serveraddrs)
2980  {
2981  ereport(LOG,
2982  (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2983  server, gai_strerror(r))));
2984  if (serveraddrs)
2985  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2986  return STATUS_ERROR;
2987  }
2988  /* XXX: add support for multiple returned addresses? */
2989 
2990  /* Construct RADIUS packet */
2991  packet->code = RADIUS_ACCESS_REQUEST;
2992  packet->length = RADIUS_HEADER_LENGTH;
2994  {
2995  ereport(LOG,
2996  (errmsg("could not generate random encryption vector")));
2997  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2998  return STATUS_ERROR;
2999  }
3000  packet->id = packet->vector[0];
3001  radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
3002  radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
3003  radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
3004 
3005  /*
3006  * RADIUS password attributes are calculated as: e[0] = p[0] XOR
3007  * MD5(secret + Request Authenticator) for the first group of 16 octets,
3008  * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
3009  * (if necessary)
3010  */
3011  encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
3012  cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
3013  memcpy(cryptvector, secret, strlen(secret));
3014 
3015  /* for the first iteration, we use the Request Authenticator vector */
3016  md5trailer = packet->vector;
3017  for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
3018  {
3019  const char *errstr = NULL;
3020 
3021  memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
3022 
3023  /*
3024  * .. and for subsequent iterations the result of the previous XOR
3025  * (calculated below)
3026  */
3027  md5trailer = encryptedpassword + i;
3028 
3029  if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH,
3030  encryptedpassword + i, &errstr))
3031  {
3032  ereport(LOG,
3033  (errmsg("could not perform MD5 encryption of password: %s",
3034  errstr)));
3035  pfree(cryptvector);
3036  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3037  return STATUS_ERROR;
3038  }
3039 
3040  for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
3041  {
3042  if (j < strlen(passwd))
3043  encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
3044  else
3045  encryptedpassword[j] = '\0' ^ encryptedpassword[j];
3046  }
3047  }
3048  pfree(cryptvector);
3049 
3050  radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
3051 
3052  /* Length needs to be in network order on the wire */
3053  packetlength = packet->length;
3054  packet->length = pg_hton16(packet->length);
3055 
3056  sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
3057  if (sock == PGINVALID_SOCKET)
3058  {
3059  ereport(LOG,
3060  (errmsg("could not create RADIUS socket: %m")));
3061  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3062  return STATUS_ERROR;
3063  }
3064 
3065  memset(&localaddr, 0, sizeof(localaddr));
3066  localaddr.sin6_family = serveraddrs[0].ai_family;
3067  localaddr.sin6_addr = in6addr_any;
3068  if (localaddr.sin6_family == AF_INET6)
3069  addrsize = sizeof(struct sockaddr_in6);
3070  else
3071  addrsize = sizeof(struct sockaddr_in);
3072 
3073  if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
3074  {
3075  ereport(LOG,
3076  (errmsg("could not bind local RADIUS socket: %m")));
3077  closesocket(sock);
3078  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3079  return STATUS_ERROR;
3080  }
3081 
3082  if (sendto(sock, radius_buffer, packetlength, 0,
3083  serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
3084  {
3085  ereport(LOG,
3086  (errmsg("could not send RADIUS packet: %m")));
3087  closesocket(sock);
3088  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3089  return STATUS_ERROR;
3090  }
3091 
3092  /* Don't need the server address anymore */
3093  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3094 
3095  /*
3096  * Figure out at what time we should time out. We can't just use a single
3097  * call to select() with a timeout, since somebody can be sending invalid
3098  * packets to our port thus causing us to retry in a loop and never time
3099  * out.
3100  *
3101  * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
3102  * the latch was set would improve the responsiveness to
3103  * timeouts/cancellations.
3104  */
3105  gettimeofday(&endtime, NULL);
3106  endtime.tv_sec += RADIUS_TIMEOUT;
3107 
3108  while (true)
3109  {
3110  struct timeval timeout;
3111  struct timeval now;
3112  int64 timeoutval;
3113  const char *errstr = NULL;
3114 
3115  gettimeofday(&now, NULL);
3116  timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
3117  if (timeoutval <= 0)
3118  {
3119  ereport(LOG,
3120  (errmsg("timeout waiting for RADIUS response from %s",
3121  server)));
3122  closesocket(sock);
3123  return STATUS_ERROR;
3124  }
3125  timeout.tv_sec = timeoutval / 1000000;
3126  timeout.tv_usec = timeoutval % 1000000;
3127 
3128  FD_ZERO(&fdset);
3129  FD_SET(sock, &fdset);
3130 
3131  r = select(sock + 1, &fdset, NULL, NULL, &timeout);
3132  if (r < 0)
3133  {
3134  if (errno == EINTR)
3135  continue;
3136 
3137  /* Anything else is an actual error */
3138  ereport(LOG,
3139  (errmsg("could not check status on RADIUS socket: %m")));
3140  closesocket(sock);
3141  return STATUS_ERROR;
3142  }
3143  if (r == 0)
3144  {
3145  ereport(LOG,
3146  (errmsg("timeout waiting for RADIUS response from %s",
3147  server)));
3148  closesocket(sock);
3149  return STATUS_ERROR;
3150  }
3151 
3152  /*
3153  * Attempt to read the response packet, and verify the contents.
3154  *
3155  * Any packet that's not actually a RADIUS packet, or otherwise does
3156  * not validate as an explicit reject, is just ignored and we retry
3157  * for another packet (until we reach the timeout). This is to avoid
3158  * the possibility to denial-of-service the login by flooding the
3159  * server with invalid packets on the port that we're expecting the
3160  * RADIUS response on.
3161  */
3162 
3163  addrsize = sizeof(remoteaddr);
3164  packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3165  (struct sockaddr *) &remoteaddr, &addrsize);
3166  if (packetlength < 0)
3167  {
3168  ereport(LOG,
3169  (errmsg("could not read RADIUS response: %m")));
3170  closesocket(sock);
3171  return STATUS_ERROR;
3172  }
3173 
3174  if (remoteaddr.sin6_port != pg_hton16(port))
3175  {
3176  ereport(LOG,
3177  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3178  server, pg_ntoh16(remoteaddr.sin6_port))));
3179  continue;
3180  }
3181 
3182  if (packetlength < RADIUS_HEADER_LENGTH)
3183  {
3184  ereport(LOG,
3185  (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3186  continue;
3187  }
3188 
3189  if (packetlength != pg_ntoh16(receivepacket->length))
3190  {
3191  ereport(LOG,
3192  (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3193  server, pg_ntoh16(receivepacket->length), packetlength)));
3194  continue;
3195  }
3196 
3197  if (packet->id != receivepacket->id)
3198  {
3199  ereport(LOG,
3200  (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3201  server, receivepacket->id, packet->id)));
3202  continue;
3203  }
3204 
3205  /*
3206  * Verify the response authenticator, which is calculated as
3207  * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3208  */
3209  cryptvector = palloc(packetlength + strlen(secret));
3210 
3211  memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3212  memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3213  * authenticator, from
3214  * original packet */
3215  if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3216  * attributes at all */
3217  memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
3218  memcpy(cryptvector + packetlength, secret, strlen(secret));
3219 
3220  if (!pg_md5_binary(cryptvector,
3221  packetlength + strlen(secret),
3222  encryptedpassword, &errstr))
3223  {
3224  ereport(LOG,
3225  (errmsg("could not perform MD5 encryption of received packet: %s",
3226  errstr)));
3227  pfree(cryptvector);
3228  continue;
3229  }
3230  pfree(cryptvector);
3231 
3232  if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3233  {
3234  ereport(LOG,
3235  (errmsg("RADIUS response from %s has incorrect MD5 signature",
3236  server)));
3237  continue;
3238  }
3239 
3240  if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3241  {
3242  closesocket(sock);
3243  return STATUS_OK;
3244  }
3245  else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3246  {
3247  closesocket(sock);
3248  return STATUS_EOF;
3249  }
3250  else
3251  {
3252  ereport(LOG,
3253  (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3254  server, receivepacket->code, user_name)));
3255  continue;
3256  }
3257  } /* while (true) */
3258 }
static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
Definition: auth.c:2818
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2777
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:2812
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:2801
#define RADIUS_NAS_IDENTIFIER
Definition: auth.c:2809
#define RADIUS_TIMEOUT
Definition: auth.c:2815
#define RADIUS_USER_NAME
Definition: auth.c:2806
#define RADIUS_SERVICE_TYPE
Definition: auth.c:2808
#define RADIUS_PASSWORD
Definition: auth.c:2807
#define RADIUS_ACCESS_REJECT
Definition: auth.c:2803
#define RADIUS_ACCESS_ACCEPT
Definition: auth.c:2802
#define RADIUS_VECTOR_LENGTH
Definition: auth.c:2776
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2781
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
signed int int32
Definition: c.h:508
unsigned char uint8
Definition: c.h:516
#define MemSet(start, val, len)
Definition: c.h:1025
int j
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1317
bool pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr)
Definition: md5_common.c:108
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define pg_hton16(x)
Definition: pg_bswap.h:120
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
static char portstr[16]
Definition: pg_regress.c:116
unsigned int socklen_t
Definition: port.h:40
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:2795
uint16 length
Definition: auth.c:2794
uint8 code
Definition: auth.c:2792
uint8 id
Definition: auth.c:2793
#define select(n, r, w, e, timeout)
Definition: win32_port.h:513
int gettimeofday(struct timeval *tp, void *tzp)

References bind, closesocket, radius_packet::code, EINTR, ereport, errmsg(), gai_strerror(), gettimeofday(), i, radius_packet::id, j, radius_packet::length, LOG, MemSet, now(), palloc(), pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_hton16, pg_hton32, pg_md5_binary(), pg_ntoh16, pg_strong_random(), PGINVALID_SOCKET, port, portstr, 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().

◆ radius_add_attribute()

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

Definition at line 2818 of file auth.c.

2819 {
2820  radius_attribute *attr;
2821 
2822  if (packet->length + len > RADIUS_BUFFER_SIZE)
2823  {
2824  /*
2825  * With remotely realistic data, this can never happen. But catch it
2826  * just to make sure we don't overrun a buffer. We'll just skip adding
2827  * the broken attribute, which will in the end cause authentication to
2828  * fail.
2829  */
2830  elog(WARNING,
2831  "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2832  type, len);
2833  return;
2834  }
2835 
2836  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2837  attr->attribute = type;
2838  attr->length = len + 2; /* total size includes type and length */
2839  memcpy(attr->data, data, len);
2840  packet->length += attr->length;
2841 }
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:225
const void size_t len
const void * data
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2787
uint8 length
Definition: auth.c:2786
uint8 attribute
Definition: auth.c:2785
const char * type

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

Referenced by PerformRadiusTransaction().

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 706 of file auth.c.

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

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

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

◆ sendAuthRequest()

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

Definition at line 676 of file auth.c.

677 {
679 
681 
683  pq_sendint32(&buf, (int32) areq);
684  if (extralen > 0)
685  pq_sendbytes(&buf, extradata, extralen);
686 
687  pq_endmessage(&buf);
688 
689  /*
690  * Flush message so client will see it, except for AUTH_REQ_OK and
691  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
692  * queries.
693  */
694  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
695  pq_flush();
696 
698 }
#define pq_flush()
Definition: libpq.h:46
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86

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

Referenced by CheckMD5Auth(), CheckPasswordAuth(), CheckRADIUSAuth(), CheckSASLAuth(), and ClientAuthentication().

◆ set_authn_id()

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

Definition at line 344 of file auth.c.

345 {
346  Assert(id);
347 
349  {
350  /*
351  * An existing authn_id should never be overwritten; that means two
352  * authentication providers are fighting (or one is fighting itself).
353  * Don't leak any authn details to the client, but don't let the
354  * connection continue, either.
355  */
356  ereport(FATAL,
357  (errmsg("authentication identifier set more than once"),
358  errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
360  }
361 
363  MyClientConnectionInfo.auth_method = port->hba->auth_method;
364 
365  if (Log_connections)
366  {
367  ereport(LOG,
368  errmsg("connection authenticated: identity=\"%s\" method=%s "
369  "(%s:%d)",
372  port->hba->sourcefile, port->hba->linenumber));
373  }
374 }
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1683
UserAuth auth_method
Definition: libpq-be.h:109

References Assert, ClientConnectionInfo::auth_method, ClientConnectionInfo::authn_id, ereport, errdetail_log(), errmsg(), FATAL, hba_authname(), LOG, Log_connections, MemoryContextStrdup(), MyClientConnectionInfo, port, and TopMemoryContext.

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

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 230 of file auth.c.

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

◆ pg_gss_accept_delegation

bool pg_gss_accept_delegation

Definition at line 166 of file auth.c.

Referenced by secure_open_gssapi().

◆ pg_krb_caseins_users

bool pg_krb_caseins_users

Definition at line 165 of file auth.c.

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 164 of file auth.c.

Referenced by secure_open_gssapi().