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

Go to the source code of this file.

Data Structures

struct  radius_attribute
 
struct  radius_packet
 

Macros

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

Functions

static void sendAuthRequest (Port *port, AuthRequest areq, const char *extradata, int extralen)
 
static void auth_failed (Port *port, int status, char *logdetail)
 
static char * recv_password_packet (Port *port)
 
static int CheckPasswordAuth (Port *port, char **logdetail)
 
static int CheckPWChallengeAuth (Port *port, char **logdetail)
 
static int CheckMD5Auth (Port *port, char *shadow_pass, char **logdetail)
 
static int CheckSCRAMAuth (Port *port, char *shadow_pass, char **logdetail)
 
static int ident_inet (hbaPort *port)
 
static int CheckRADIUSAuth (Port *port)
 
static int PerformRadiusTransaction (const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
 
void ClientAuthentication (Port *port)
 
static bool interpret_ident_response (const char *ident_response, char *ident_user)
 
static void radius_add_attribute (radius_packet *packet, uint8 type, const unsigned char *data, int len)
 

Variables

char * pg_krb_server_keyfile
 
bool pg_krb_caseins_users
 
ClientAuthentication_hook_type ClientAuthentication_hook = NULL
 

Macro Definition Documentation

◆ HOSTNAME_LOOKUP_DETAIL

#define HOSTNAME_LOOKUP_DETAIL (   port)
Value:
(port->remote_hostname ? \
(port->remote_hostname_resolv == +1 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
port->remote_hostname) : \
port->remote_hostname_resolv == 0 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
port->remote_hostname) : \
port->remote_hostname_resolv == -1 ? \
errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
port->remote_hostname) : \
port->remote_hostname_resolv == -2 ? \
errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
port->remote_hostname, \
gai_strerror(port->remote_hostname_errcode)) : \
0) \
: (port->remote_hostname_resolv == -2 ? \
errdetail_log("Could not resolve client IP address to a host name: %s.", \
gai_strerror(port->remote_hostname_errcode)) : \
0))
#define gai_strerror
Definition: getaddrinfo.h:146
int errdetail_log(const char *fmt,...)
Definition: elog.c:921
static int port
Definition: pg_regress.c:90

Referenced by ClientAuthentication().

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 71 of file auth.c.

Referenced by ident_inet().

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 68 of file auth.c.

Referenced by ident_inet(), and interpret_ident_response().

◆ PG_MAX_AUTH_TOKEN_LENGTH

#define PG_MAX_AUTH_TOKEN_LENGTH   65535

Definition at line 222 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ PG_MAX_SASL_MESSAGE_LENGTH

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 230 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2777 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2778 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2776 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2787 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2756 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2752 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2753 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2784 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2782 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2783 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2790 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2781 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2751 of file auth.c.

Referenced by PerformRadiusTransaction().

Function Documentation

◆ auth_failed()

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

Definition at line 258 of file auth.c.

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

Referenced by ClientAuthentication().

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

◆ CheckMD5Auth()

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

Definition at line 825 of file auth.c.

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

Referenced by CheckPWChallengeAuth().

826 {
827  char md5Salt[4]; /* Password salt */
828  char *passwd;
829  int result;
830 
831  if (Db_user_namespace)
832  ereport(FATAL,
833  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
834  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
835 
836  /* include the salt to use for computing the response */
837  if (!pg_backend_random(md5Salt, 4))
838  {
839  ereport(LOG,
840  (errmsg("could not generate random MD5 salt")));
841  return STATUS_ERROR;
842  }
843 
844  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
845 
846  passwd = recv_password_packet(port);
847  if (passwd == NULL)
848  return STATUS_EOF; /* client wouldn't send password */
849 
850  if (shadow_pass)
851  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
852  md5Salt, 4, logdetail);
853  else
854  result = STATUS_ERROR;
855 
856  pfree(passwd);
857 
858  return result;
859 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:616
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:954
#define LOG
Definition: elog.h:26
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
void pfree(void *pointer)
Definition: mcxt.c:949
#define FATAL
Definition: elog.h:52
bool pg_backend_random(char *dst, int len)
bool Db_user_namespace
Definition: postmaster.c:241
char * user_name
Definition: libpq-be.h:137
#define ereport(elevel, rest)
Definition: elog.h:122
static char * recv_password_packet(Port *port)
Definition: auth.c:646
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, char **logdetail)
Definition: crypt.c:160
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define STATUS_EOF
Definition: c.h:955

◆ CheckPasswordAuth()

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

Definition at line 737 of file auth.c.

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

Referenced by ClientAuthentication().

738 {
739  char *passwd;
740  int result;
741  char *shadow_pass;
742 
743  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
744 
745  passwd = recv_password_packet(port);
746  if (passwd == NULL)
747  return STATUS_EOF; /* client wouldn't send password */
748 
749  shadow_pass = get_role_password(port->user_name, logdetail);
750  if (shadow_pass)
751  {
752  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
753  logdetail);
754  }
755  else
756  result = STATUS_ERROR;
757 
758  if (shadow_pass)
759  pfree(shadow_pass);
760  pfree(passwd);
761 
762  return result;
763 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:616
#define STATUS_ERROR
Definition: c.h:954
void pfree(void *pointer)
Definition: mcxt.c:949
char * user_name
Definition: libpq-be.h:137
static char * recv_password_packet(Port *port)
Definition: auth.c:646
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:216
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:39
#define STATUS_EOF
Definition: c.h:955

◆ CheckPWChallengeAuth()

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

Definition at line 769 of file auth.c.

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

Referenced by ClientAuthentication().

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

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

Definition at line 2819 of file auth.c.

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

Referenced by ClientAuthentication().

2820 {
2821  char *passwd;
2822  ListCell *server,
2823  *secrets,
2824  *radiusports,
2825  *identifiers;
2826 
2827  /* Make sure struct alignment is correct */
2828  Assert(offsetof(radius_packet, vector) == 4);
2829 
2830  /* Verify parameters */
2831  if (list_length(port->hba->radiusservers) < 1)
2832  {
2833  ereport(LOG,
2834  (errmsg("RADIUS server not specified")));
2835  return STATUS_ERROR;
2836  }
2837 
2838  if (list_length(port->hba->radiussecrets) < 1)
2839  {
2840  ereport(LOG,
2841  (errmsg("RADIUS secret not specified")));
2842  return STATUS_ERROR;
2843  }
2844 
2845  /* Send regular password request to client, and get the response */
2846  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
2847 
2848  passwd = recv_password_packet(port);
2849  if (passwd == NULL)
2850  return STATUS_EOF; /* client wouldn't send password */
2851 
2852  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2853  {
2854  ereport(LOG,
2855  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2856  pfree(passwd);
2857  return STATUS_ERROR;
2858  }
2859 
2860  /*
2861  * Loop over and try each server in order.
2862  */
2863  secrets = list_head(port->hba->radiussecrets);
2864  radiusports = list_head(port->hba->radiusports);
2865  identifiers = list_head(port->hba->radiusidentifiers);
2866  foreach(server, port->hba->radiusservers)
2867  {
2868  int ret = PerformRadiusTransaction(lfirst(server),
2869  lfirst(secrets),
2870  radiusports ? lfirst(radiusports) : NULL,
2871  identifiers ? lfirst(identifiers) : NULL,
2872  port->user_name,
2873  passwd);
2874 
2875  /*------
2876  * STATUS_OK = Login OK
2877  * STATUS_ERROR = Login not OK, but try next server
2878  * STATUS_EOF = Login not OK, and don't try next server
2879  *------
2880  */
2881  if (ret == STATUS_OK)
2882  {
2883  pfree(passwd);
2884  return STATUS_OK;
2885  }
2886  else if (ret == STATUS_EOF)
2887  {
2888  pfree(passwd);
2889  return STATUS_ERROR;
2890  }
2891 
2892  /*
2893  * secret, port and identifiers either have length 0 (use default),
2894  * length 1 (use the same everywhere) or the same length as servers.
2895  * So if the length is >1, we advance one step. In other cases, we
2896  * don't and will then reuse the correct value.
2897  */
2898  if (list_length(port->hba->radiussecrets) > 1)
2899  secrets = lnext(secrets);
2900  if (list_length(port->hba->radiusports) > 1)
2901  radiusports = lnext(radiusports);
2902  if (list_length(port->hba->radiusidentifiers) > 1)
2903  identifiers = lnext(identifiers);
2904  }
2905 
2906  /* No servers left to try, so give up */
2907  pfree(passwd);
2908  return STATUS_ERROR;
2909 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:616
#define STATUS_ERROR
Definition: c.h:954
#define LOG
Definition: elog.h:26
List * radiussecrets
Definition: hba.h:95
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:2912
void pfree(void *pointer)
Definition: mcxt.c:949
List * radiusports
Definition: hba.h:99
List * radiusservers
Definition: hba.h:93
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
char * user_name
Definition: libpq-be.h:137
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:953
static char * recv_password_packet(Port *port)
Definition: auth.c:646
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
HbaLine * hba
Definition: libpq-be.h:144
List * radiusidentifiers
Definition: hba.h:97
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2753
static int list_length(const List *l)
Definition: pg_list.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define STATUS_EOF
Definition: c.h:955
#define offsetof(type, field)
Definition: c.h:593

◆ CheckSCRAMAuth()

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

Definition at line 862 of file auth.c.

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

Referenced by CheckPWChallengeAuth().

863 {
864  char *sasl_mechs;
865  char *p;
866  int mtype;
868  void *scram_opaq;
869  char *output = NULL;
870  int outputlen = 0;
871  char *input;
872  int inputlen;
873  int result;
874  bool initial;
875  char *tls_finished = NULL;
876  size_t tls_finished_len = 0;
877 
878  /*
879  * SASL auth is not supported for protocol versions before 3, because it
880  * relies on the overall message length word to determine the SASL payload
881  * size in AuthenticationSASLContinue and PasswordMessage messages. (We
882  * used to have a hard rule that protocol messages must be parsable
883  * without relying on the length word, but we hardly care about older
884  * protocol version anymore.)
885  */
887  ereport(FATAL,
888  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
889  errmsg("SASL authentication is not supported in protocol version 2")));
890 
891  /*
892  * Send the SASL authentication request to user. It includes the list of
893  * authentication mechanisms that are supported. The order of mechanisms
894  * is advertised in decreasing order of importance. So the
895  * channel-binding variants go first, if they are supported. Channel
896  * binding is only supported in SSL builds.
897  */
898  sasl_mechs = palloc(strlen(SCRAM_SHA256_PLUS_NAME) +
899  strlen(SCRAM_SHA256_NAME) + 3);
900  p = sasl_mechs;
901 
902  if (port->ssl_in_use)
903  {
904  strcpy(p, SCRAM_SHA256_PLUS_NAME);
905  p += strlen(SCRAM_SHA256_PLUS_NAME) + 1;
906  }
907 
908  strcpy(p, SCRAM_SHA256_NAME);
909  p += strlen(SCRAM_SHA256_NAME) + 1;
910 
911  /* Put another '\0' to mark that list is finished. */
912  p[0] = '\0';
913 
914  sendAuthRequest(port, AUTH_REQ_SASL, sasl_mechs, p - sasl_mechs + 1);
915  pfree(sasl_mechs);
916 
917 #ifdef USE_SSL
918 
919  /*
920  * Get data for channel binding.
921  */
922  if (port->ssl_in_use)
923  {
924  tls_finished = be_tls_get_peer_finished(port, &tls_finished_len);
925  }
926 #endif
927 
928  /*
929  * Initialize the status tracker for message exchanges.
930  *
931  * If the user doesn't exist, or doesn't have a valid password, or it's
932  * expired, we still go through the motions of SASL authentication, but
933  * tell the authentication method that the authentication is "doomed".
934  * That is, it's going to fail, no matter what.
935  *
936  * This is because we don't want to reveal to an attacker what usernames
937  * are valid, nor which users have a valid password.
938  */
939  scram_opaq = pg_be_scram_init(port->user_name,
940  shadow_pass,
941  port->ssl_in_use,
942  tls_finished,
943  tls_finished_len);
944 
945  /*
946  * Loop through SASL message exchange. This exchange can consist of
947  * multiple messages sent in both directions. First message is always
948  * from the client. All messages from client to server are password
949  * packets (type 'p').
950  */
951  initial = true;
952  do
953  {
954  pq_startmsgread();
955  mtype = pq_getbyte();
956  if (mtype != 'p')
957  {
958  /* Only log error if client didn't disconnect. */
959  if (mtype != EOF)
960  {
961  ereport(ERROR,
962  (errcode(ERRCODE_PROTOCOL_VIOLATION),
963  errmsg("expected SASL response, got message type %d",
964  mtype)));
965  }
966  else
967  return STATUS_EOF;
968  }
969 
970  /* Get the actual SASL message */
971  initStringInfo(&buf);
973  {
974  /* EOF - pq_getmessage already logged error */
975  pfree(buf.data);
976  return STATUS_ERROR;
977  }
978 
979  elog(DEBUG4, "Processing received SASL response of length %d", buf.len);
980 
981  /*
982  * The first SASLInitialResponse message is different from the others.
983  * It indicates which SASL mechanism the client selected, and contains
984  * an optional Initial Client Response payload. The subsequent
985  * SASLResponse messages contain just the SASL payload.
986  */
987  if (initial)
988  {
989  const char *selected_mech;
990 
991  selected_mech = pq_getmsgrawstring(&buf);
992  if (strcmp(selected_mech, SCRAM_SHA256_NAME) != 0 &&
993  strcmp(selected_mech, SCRAM_SHA256_PLUS_NAME) != 0)
994  {
995  ereport(ERROR,
996  (errcode(ERRCODE_PROTOCOL_VIOLATION),
997  errmsg("client selected an invalid SASL authentication mechanism")));
998  }
999 
1000  inputlen = pq_getmsgint(&buf, 4);
1001  if (inputlen == -1)
1002  input = NULL;
1003  else
1004  input = (char *) pq_getmsgbytes(&buf, inputlen);
1005 
1006  initial = false;
1007  }
1008  else
1009  {
1010  inputlen = buf.len;
1011  input = (char *) pq_getmsgbytes(&buf, buf.len);
1012  }
1013  pq_getmsgend(&buf);
1014 
1015  /*
1016  * The StringInfo guarantees that there's a \0 byte after the
1017  * response.
1018  */
1019  Assert(input == NULL || input[inputlen] == '\0');
1020 
1021  /*
1022  * we pass 'logdetail' as NULL when doing a mock authentication,
1023  * because we should already have a better error message in that case
1024  */
1025  result = pg_be_scram_exchange(scram_opaq, input, inputlen,
1026  &output, &outputlen,
1027  logdetail);
1028 
1029  /* input buffer no longer used */
1030  pfree(buf.data);
1031 
1032  if (output)
1033  {
1034  /*
1035  * Negotiation generated data to be sent to the client.
1036  */
1037  elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
1038 
1039  if (result == SASL_EXCHANGE_SUCCESS)
1040  sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
1041  else
1042  sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
1043 
1044  pfree(output);
1045  }
1046  } while (result == SASL_EXCHANGE_CONTINUE);
1047 
1048  /* Oops, Something bad happened */
1049  if (result != SASL_EXCHANGE_SUCCESS)
1050  {
1051  return STATUS_ERROR;
1052  }
1053 
1054  return STATUS_OK;
1055 }
void * pg_be_scram_init(const char *username, const char *shadow_pass, bool ssl_in_use, const char *tls_finished_message, size_t tls_finished_len)
Definition: auth-scram.c:175
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:616
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:177
static void output(uint64 loop_count)
int pg_be_scram_exchange(void *opaq, char *input, int inputlen, char **output, int *outputlen, char **logdetail)
Definition: auth-scram.c:270
#define SASL_EXCHANGE_SUCCESS
Definition: scram.h:25
char * be_tls_get_peer_finished(Port *port, size_t *len)
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:954
bool ssl_in_use
Definition: libpq-be.h:181
const char * pq_getmsgrawstring(StringInfo msg)
Definition: pqformat.c:610
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
#define DEBUG4
Definition: elog.h:22
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:510
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
void pq_startmsgread(void)
Definition: pqcomm.c:1210
#define FATAL
Definition: elog.h:52
static char * buf
Definition: pg_test_fsync.c:67
#define SCRAM_SHA256_NAME
Definition: scram.h:17
char * user_name
Definition: libpq-be.h:137
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:953
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1272
int pq_getbyte(void)
Definition: pqcomm.c:1000
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:176
#define Assert(condition)
Definition: c.h:670
#define PG_MAX_SASL_MESSAGE_LENGTH
Definition: auth.c:230
#define AUTH_REQ_SASL
Definition: pqcomm.h:175
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define elog
Definition: elog.h:219
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:637
#define SASL_EXCHANGE_CONTINUE
Definition: scram.h:24
#define STATUS_EOF
Definition: c.h:955
#define SCRAM_SHA256_PLUS_NAME
Definition: scram.h:18
ProtocolVersion FrontendProtocol
Definition: globals.c:27

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 346 of file auth.c.

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

Referenced by PerformAuthentication().

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

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1861 of file auth.c.

References _, SockAddr::addr, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, appendStringInfoChar(), appendStringInfoString(), Assert, AUTH_REQ_PASSWORD, bind, calloc, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, StringInfoData::data, EINTR, elog, ereport, errcode(), errcode_for_socket_access(), errdetail(), errdetail_plural(), errmsg(), errmsg_internal(), error(), free, gai_strerror, getpeereid(), Port::hba, i, IDENT_PORT, IDENT_USERNAME_MAX, initStringInfo(), interpret_ident_response(), Port::laddr, HbaLine::ldapbasedn, HbaLine::ldapbinddn, HbaLine::ldapbindpasswd, HbaLine::ldapport, HbaLine::ldapprefix, HbaLine::ldapscope, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, HbaLine::ldaptls, LOG, NI_MAXHOST, NI_MAXSERV, NI_NUMERICHOST, NI_NUMERICSERV, output(), HbaLine::pam_use_hostname, HbaLine::pamservice, password, Port::peer_cn, pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, port, psprintf(), pstrdup(), Port::raddr, recv, recv_password_packet(), SockAddr::salen, send, sendAuthRequest(), snprintf(), Port::sock, socket, STATUS_EOF, STATUS_ERROR, STATUS_OK, strerror(), strlcpy(), user, Port::user_name, HbaLine::usermap, and WARNING.

Referenced by ClientAuthentication().

1862 {
1863  const SockAddr remote_addr = port->raddr;
1864  const SockAddr local_addr = port->laddr;
1865  char ident_user[IDENT_USERNAME_MAX + 1];
1866  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1867  int rc; /* Return code from a locally called function */
1868  bool ident_return;
1869  char remote_addr_s[NI_MAXHOST];
1870  char remote_port[NI_MAXSERV];
1871  char local_addr_s[NI_MAXHOST];
1872  char local_port[NI_MAXSERV];
1873  char ident_port[NI_MAXSERV];
1874  char ident_query[80];
1875  char ident_response[80 + IDENT_USERNAME_MAX];
1876  struct addrinfo *ident_serv = NULL,
1877  *la = NULL,
1878  hints;
1879 
1880  /*
1881  * Might look a little weird to first convert it to text and then back to
1882  * sockaddr, but it's protocol independent.
1883  */
1884  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1885  remote_addr_s, sizeof(remote_addr_s),
1886  remote_port, sizeof(remote_port),
1888  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1889  local_addr_s, sizeof(local_addr_s),
1890  local_port, sizeof(local_port),
1892 
1893  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1894  hints.ai_flags = AI_NUMERICHOST;
1895  hints.ai_family = remote_addr.addr.ss_family;
1896  hints.ai_socktype = SOCK_STREAM;
1897  hints.ai_protocol = 0;
1898  hints.ai_addrlen = 0;
1899  hints.ai_canonname = NULL;
1900  hints.ai_addr = NULL;
1901  hints.ai_next = NULL;
1902  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1903  if (rc || !ident_serv)
1904  {
1905  /* we don't expect this to happen */
1906  ident_return = false;
1907  goto ident_inet_done;
1908  }
1909 
1910  hints.ai_flags = AI_NUMERICHOST;
1911  hints.ai_family = local_addr.addr.ss_family;
1912  hints.ai_socktype = SOCK_STREAM;
1913  hints.ai_protocol = 0;
1914  hints.ai_addrlen = 0;
1915  hints.ai_canonname = NULL;
1916  hints.ai_addr = NULL;
1917  hints.ai_next = NULL;
1918  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1919  if (rc || !la)
1920  {
1921  /* we don't expect this to happen */
1922  ident_return = false;
1923  goto ident_inet_done;
1924  }
1925 
1926  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1927  ident_serv->ai_protocol);
1928  if (sock_fd == PGINVALID_SOCKET)
1929  {
1930  ereport(LOG,
1932  errmsg("could not create socket for Ident connection: %m")));
1933  ident_return = false;
1934  goto ident_inet_done;
1935  }
1936 
1937  /*
1938  * Bind to the address which the client originally contacted, otherwise
1939  * the ident server won't be able to match up the right connection. This
1940  * is necessary if the PostgreSQL server is running on an IP alias.
1941  */
1942  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1943  if (rc != 0)
1944  {
1945  ereport(LOG,
1947  errmsg("could not bind to local address \"%s\": %m",
1948  local_addr_s)));
1949  ident_return = false;
1950  goto ident_inet_done;
1951  }
1952 
1953  rc = connect(sock_fd, ident_serv->ai_addr,
1954  ident_serv->ai_addrlen);
1955  if (rc != 0)
1956  {
1957  ereport(LOG,
1959  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1960  remote_addr_s, ident_port)));
1961  ident_return = false;
1962  goto ident_inet_done;
1963  }
1964 
1965  /* The query we send to the Ident server */
1966  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1967  remote_port, local_port);
1968 
1969  /* loop in case send is interrupted */
1970  do
1971  {
1973 
1974  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1975  } while (rc < 0 && errno == EINTR);
1976 
1977  if (rc < 0)
1978  {
1979  ereport(LOG,
1981  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1982  remote_addr_s, ident_port)));
1983  ident_return = false;
1984  goto ident_inet_done;
1985  }
1986 
1987  do
1988  {
1990 
1991  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1992  } while (rc < 0 && errno == EINTR);
1993 
1994  if (rc < 0)
1995  {
1996  ereport(LOG,
1998  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1999  remote_addr_s, ident_port)));
2000  ident_return = false;
2001  goto ident_inet_done;
2002  }
2003 
2004  ident_response[rc] = '\0';
2005  ident_return = interpret_ident_response(ident_response, ident_user);
2006  if (!ident_return)
2007  ereport(LOG,
2008  (errmsg("invalidly formatted response from Ident server: \"%s\"",
2009  ident_response)));
2010 
2011 ident_inet_done:
2012  if (sock_fd != PGINVALID_SOCKET)
2013  closesocket(sock_fd);
2014  if (ident_serv)
2015  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
2016  if (la)
2017  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
2018 
2019  if (ident_return)
2020  /* Success! Check the usermap */
2021  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
2022  return STATUS_ERROR;
2023 }
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:88
#define NI_NUMERICHOST
Definition: getaddrinfo.h:78
#define closesocket
Definition: port.h:292
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define STATUS_ERROR
Definition: c.h:954
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define connect(s, name, namelen)
Definition: win32_port.h:446
#define LOG
Definition: elog.h:26
#define AI_NUMERICHOST
Definition: getaddrinfo.h:73
#define bind(s, addr, addrlen)
Definition: win32_port.h:443
#define recv(s, buf, len, flags)
Definition: win32_port.h:448
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:57
SockAddr raddr
Definition: libpq-be.h:122
#define IDENT_USERNAME_MAX
Definition: auth.c:68
#define NI_MAXHOST
Definition: getaddrinfo.h:88
char * usermap
Definition: hba.h:74
#define IDENT_PORT
Definition: auth.c:71
#define NI_MAXSERV
Definition: getaddrinfo.h:91
char * user_name
Definition: libpq-be.h:137
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
int errcode_for_socket_access(void)
Definition: elog.c:669
SockAddr laddr
Definition: libpq-be.h:121
HbaLine * hba
Definition: libpq-be.h:144
#define socket(af, type, protocol)
Definition: win32_port.h:442
#define PGINVALID_SOCKET
Definition: port.h:33
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2844
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
int ai_protocol
Definition: getaddrinfo.h:103
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
int ai_socktype
Definition: getaddrinfo.h:102
int errmsg(const char *fmt,...)
Definition: elog.c:797
size_t ai_addrlen
Definition: getaddrinfo.h:104
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define EINTR
Definition: win32_port.h:334
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1773
struct sockaddr * ai_addr
Definition: getaddrinfo.h:105
#define send(s, buf, len, flags)
Definition: win32_port.h:449
int ai_family
Definition: getaddrinfo.h:101

◆ interpret_ident_response()

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

Definition at line 1773 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1775 {
1776  const char *cursor = ident_response; /* Cursor into *ident_response */
1777 
1778  /*
1779  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1780  */
1781  if (strlen(ident_response) < 2)
1782  return false;
1783  else if (ident_response[strlen(ident_response) - 2] != '\r')
1784  return false;
1785  else
1786  {
1787  while (*cursor != ':' && *cursor != '\r')
1788  cursor++; /* skip port field */
1789 
1790  if (*cursor != ':')
1791  return false;
1792  else
1793  {
1794  /* We're positioned to colon before response type field */
1795  char response_type[80];
1796  int i; /* Index into *response_type */
1797 
1798  cursor++; /* Go over colon */
1799  while (pg_isblank(*cursor))
1800  cursor++; /* skip blanks */
1801  i = 0;
1802  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1803  i < (int) (sizeof(response_type) - 1))
1804  response_type[i++] = *cursor++;
1805  response_type[i] = '\0';
1806  while (pg_isblank(*cursor))
1807  cursor++; /* skip blanks */
1808  if (strcmp(response_type, "USERID") != 0)
1809  return false;
1810  else
1811  {
1812  /*
1813  * It's a USERID response. Good. "cursor" should be pointing
1814  * to the colon that precedes the operating system type.
1815  */
1816  if (*cursor != ':')
1817  return false;
1818  else
1819  {
1820  cursor++; /* Go over colon */
1821  /* Skip over operating system field. */
1822  while (*cursor != ':' && *cursor != '\r')
1823  cursor++;
1824  if (*cursor != ':')
1825  return false;
1826  else
1827  {
1828  int i; /* Index into *ident_user */
1829 
1830  cursor++; /* Go over colon */
1831  while (pg_isblank(*cursor))
1832  cursor++; /* skip blanks */
1833  /* Rest of line is user name. Copy it over. */
1834  i = 0;
1835  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1836  ident_user[i++] = *cursor++;
1837  ident_user[i] = '\0';
1838  return true;
1839  }
1840  }
1841  }
1842  }
1843  }
1844 }
bool pg_isblank(const char c)
Definition: hba.c:160
#define IDENT_USERNAME_MAX
Definition: auth.c:68
Definition: type.h:124
int i

◆ PerformRadiusTransaction()

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

Definition at line 2912 of file auth.c.

References addrinfo::ai_family, addrinfo::ai_socktype, bind, closesocket, radius_packet::code, EINTR, ereport, errmsg(), gai_strerror, gettimeofday(), i, radius_packet::id, in6addr_any, radius_packet::length, LOG, MemSet, palloc(), pfree(), pg_backend_random(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_hton16, pg_hton32, pg_md5_binary(), pg_ntoh16, 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().

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

◆ radius_add_attribute()

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

Definition at line 2793 of file auth.c.

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

Referenced by PerformRadiusTransaction().

2794 {
2795  radius_attribute *attr;
2796 
2797  if (packet->length + len > RADIUS_BUFFER_SIZE)
2798  {
2799  /*
2800  * With remotely realistic data, this can never happen. But catch it
2801  * just to make sure we don't overrun a buffer. We'll just skip adding
2802  * the broken attribute, which will in the end cause authentication to
2803  * fail.
2804  */
2805  elog(WARNING,
2806  "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2807  type, len);
2808  return;
2809  }
2810 
2811  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2812  attr->attribute = type;
2813  attr->length = len + 2; /* total size includes type and length */
2814  memcpy(attr->data, data, len);
2815  packet->length += attr->length;
2816 }
uint16 length
Definition: auth.c:2769
uint8 attribute
Definition: auth.c:2760
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2756
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2762
#define elog
Definition: elog.h:219
uint8 length
Definition: auth.c:2761

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 646 of file auth.c.

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

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

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

◆ sendAuthRequest()

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

Definition at line 616 of file auth.c.

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

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

617 {
619 
621 
622  pq_beginmessage(&buf, 'R');
623  pq_sendint32(&buf, (int32) areq);
624  if (extralen > 0)
625  pq_sendbytes(&buf, extradata, extralen);
626 
627  pq_endmessage(&buf);
628 
629  /*
630  * Flush message so client will see it, except for AUTH_REQ_OK and
631  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
632  * queries.
633  */
634  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
635  pq_flush();
636 
638 }
#define pq_flush()
Definition: libpq.h:39
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:177
static void pq_sendint32(StringInfo buf, int32 i)
Definition: pqformat.h:148
#define AUTH_REQ_OK
Definition: pqcomm.h:165
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:87
signed int int32
Definition: c.h:284
static char * buf
Definition: pg_test_fsync.c:67
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

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

Referenced by CheckSCRAMAuth().

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 166 of file auth.c.

Referenced by CheckSCRAMAuth().