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 <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/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, 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
 
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:1085
#define gai_strerror
Definition: getaddrinfo.h:146
static int port
Definition: pg_regress.c:92

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 73 of file auth.c.

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 70 of file auth.c.

◆ PG_MAX_AUTH_TOKEN_LENGTH

#define PG_MAX_AUTH_TOKEN_LENGTH   65535

Definition at line 224 of file auth.c.

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2868 of file auth.c.

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2869 of file auth.c.

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2867 of file auth.c.

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2878 of file auth.c.

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2847 of file auth.c.

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2843 of file auth.c.

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2844 of file auth.c.

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2875 of file auth.c.

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2873 of file auth.c.

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2874 of file auth.c.

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2881 of file auth.c.

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2872 of file auth.c.

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2842 of file auth.c.

Function Documentation

◆ auth_failed()

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

Definition at line 252 of file auth.c.

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

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

Referenced by ClientAuthentication().

◆ auth_peer()

static int auth_peer ( hbaPort port)
static

Definition at line 1867 of file auth.c.

1868 {
1869  uid_t uid;
1870  gid_t gid;
1871 #ifndef WIN32
1872  struct passwd *pw;
1873  int ret;
1874 #endif
1875 
1876  if (getpeereid(port->sock, &uid, &gid) != 0)
1877  {
1878  /* Provide special error message if getpeereid is a stub */
1879  if (errno == ENOSYS)
1880  ereport(LOG,
1881  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1882  errmsg("peer authentication is not supported on this platform")));
1883  else
1884  ereport(LOG,
1886  errmsg("could not get peer credentials: %m")));
1887  return STATUS_ERROR;
1888  }
1889 
1890 #ifndef WIN32
1891  errno = 0; /* clear errno before call */
1892  pw = getpwuid(uid);
1893  if (!pw)
1894  {
1895  int save_errno = errno;
1896 
1897  ereport(LOG,
1898  (errmsg("could not look up local user ID %ld: %s",
1899  (long) uid,
1900  save_errno ? strerror(save_errno) : _("user does not exist"))));
1901  return STATUS_ERROR;
1902  }
1903 
1904  /*
1905  * Make a copy of static getpw*() result area; this is our authenticated
1906  * identity. Set it before calling check_usermap, because authentication
1907  * has already succeeded and we want the log file to reflect that.
1908  */
1909  set_authn_id(port, pw->pw_name);
1910 
1911  ret = check_usermap(port->hba->usermap, port->user_name, port->authn_id, false);
1912 
1913  return ret;
1914 #else
1915  /* should have failed with ENOSYS above */
1916  Assert(false);
1917  return STATUS_ERROR;
1918 #endif
1919 }
static void set_authn_id(Port *port, const char *id)
Definition: auth.c:349
#define STATUS_ERROR
Definition: c.h:1168
int errcode_for_socket_access(void)
Definition: elog.c:787
#define LOG
Definition: elog.h:25
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2974
Assert(fmt[strlen(fmt) - 1] !='\n')
#define strerror
Definition: port.h:238
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:35
int gid_t
Definition: win32_port.h:245
int uid_t
Definition: win32_port.h:244

References _, Assert(), check_usermap(), ereport, errcode(), errcode_for_socket_access(), errmsg(), getpeereid(), LOG, port, set_authn_id(), STATUS_ERROR, and strerror.

Referenced by ClientAuthentication().

◆ CheckMD5Auth()

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

Definition at line 871 of file auth.c.

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

References AUTH_REQ_MD5, Db_user_namespace, ereport, errcode(), errmsg(), FATAL, 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 774 of file auth.c.

775 {
776  char *passwd;
777  int result;
778  char *shadow_pass;
779 
781 
782  passwd = recv_password_packet(port);
783  if (passwd == NULL)
784  return STATUS_EOF; /* client wouldn't send password */
785 
786  shadow_pass = get_role_password(port->user_name, logdetail);
787  if (shadow_pass)
788  {
789  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
790  logdetail);
791  }
792  else
793  result = STATUS_ERROR;
794 
795  if (shadow_pass)
796  pfree(shadow_pass);
797  pfree(passwd);
798 
799  if (result == STATUS_OK)
800  set_authn_id(port, port->user_name);
801 
802  return result;
803 }
#define STATUS_OK
Definition: c.h:1167
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition: crypt.c:221
char * get_role_password(const char *role, const char **logdetail)
Definition: crypt.c:37
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:154

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

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

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_ERROR, STATUS_OK, uaMD5, and uaSCRAM.

Referenced by ClientAuthentication().

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

Definition at line 2910 of file auth.c.

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

References Assert(), AUTH_REQ_PASSWORD, ereport, errmsg(), lfirst, list_head(), list_length(), lnext(), LOG, offsetof, 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 385 of file auth.c.

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

Referenced by PerformAuthentication().

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1682 of file auth.c.

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

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(), IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), LOG, NI_MAXHOST, NI_MAXSERV, NI_NUMERICHOST, NI_NUMERICSERV, 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 1599 of file auth.c.

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

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

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

References addrinfo::ai_family, addrinfo::ai_socktype, 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, 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 2884 of file auth.c.

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

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

Referenced by PerformRadiusTransaction().

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 693 of file auth.c.

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

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

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

◆ sendAuthRequest()

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

Definition at line 663 of file auth.c.

664 {
666 
668 
669  pq_beginmessage(&buf, 'R');
670  pq_sendint32(&buf, (int32) areq);
671  if (extralen > 0)
672  pq_sendbytes(&buf, extradata, extralen);
673 
674  pq_endmessage(&buf);
675 
676  /*
677  * Flush message so client will see it, except for AUTH_REQ_OK and
678  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
679  * queries.
680  */
681  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
682  pq_flush();
683 
685 }
#define pq_flush()
Definition: libpq.h:46
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:163
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145

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 CheckMD5Auth(), CheckPasswordAuth(), CheckRADIUSAuth(), CheckSASLAuth(), and ClientAuthentication().

◆ set_authn_id()

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

Definition at line 349 of file auth.c.

350 {
351  Assert(id);
352 
353  if (port->authn_id)
354  {
355  /*
356  * An existing authn_id should never be overwritten; that means two
357  * authentication providers are fighting (or one is fighting itself).
358  * Don't leak any authn details to the client, but don't let the
359  * connection continue, either.
360  */
361  ereport(FATAL,
362  (errmsg("authentication identifier set more than once"),
363  errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
364  port->authn_id, id)));
365  }
366 
367  port->authn_id = MemoryContextStrdup(TopMemoryContext, id);
368 
369  if (Log_connections)
370  {
371  ereport(LOG,
372  errmsg("connection authenticated: identity=\"%s\" method=%s "
373  "(%s:%d)",
374  port->authn_id, hba_authname(port->hba->auth_method), HbaFileName,
375  port->hba->linenumber));
376  }
377 }
char * HbaFileName
Definition: guc.c:617
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3153
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
bool Log_connections
Definition: postmaster.c:241

References Assert(), ereport, errdetail_log(), errmsg(), FATAL, hba_authname(), HbaFileName, LOG, Log_connections, MemoryContextStrdup(), 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 236 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 172 of file auth.c.

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 171 of file auth.c.

Referenced by secure_open_gssapi().