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

Go to the source code of this file.

Data Structures

struct  radius_attribute
 
struct  radius_packet
 

Macros

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

Functions

static void sendAuthRequest (Port *port, AuthRequest areq, const char *extradata, int extralen)
 
static void auth_failed (Port *port, int status, char *logdetail)
 
static char * recv_password_packet (Port *port)
 
static 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:908
static int port
Definition: pg_regress.c:92

Referenced by ClientAuthentication().

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 72 of file auth.c.

Referenced by ident_inet().

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

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

Referenced by CheckSCRAMAuth().

◆ PG_MAX_SASL_MESSAGE_LENGTH

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 227 of file auth.c.

Referenced by CheckSCRAMAuth().

◆ RADIUS_ACCESS_ACCEPT

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2906 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REJECT

#define RADIUS_ACCESS_REJECT   3

Definition at line 2907 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_ACCESS_REQUEST

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2905 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_AUTHENTICATE_ONLY

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2916 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_BUFFER_SIZE

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2885 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

◆ RADIUS_HEADER_LENGTH

#define RADIUS_HEADER_LENGTH   20

Definition at line 2881 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_MAX_PASSWORD_LENGTH

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2882 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

◆ RADIUS_NAS_IDENTIFIER

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2913 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_PASSWORD

#define RADIUS_PASSWORD   2

Definition at line 2911 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_SERVICE_TYPE

#define RADIUS_SERVICE_TYPE   6

Definition at line 2912 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_TIMEOUT

#define RADIUS_TIMEOUT   3

Definition at line 2919 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_USER_NAME

#define RADIUS_USER_NAME   1

Definition at line 2910 of file auth.c.

Referenced by PerformRadiusTransaction().

◆ RADIUS_VECTOR_LENGTH

#define RADIUS_VECTOR_LENGTH   16

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

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

◆ CheckMD5Auth()

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

Definition at line 847 of file auth.c.

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

Referenced by CheckPWChallengeAuth().

848 {
849  char md5Salt[4]; /* Password salt */
850  char *passwd;
851  int result;
852 
853  if (Db_user_namespace)
854  ereport(FATAL,
855  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
856  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
857 
858  /* include the salt to use for computing the response */
859  if (!pg_strong_random(md5Salt, 4))
860  {
861  ereport(LOG,
862  (errmsg("could not generate random MD5 salt")));
863  return STATUS_ERROR;
864  }
865 
866  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
867 
868  passwd = recv_password_packet(port);
869  if (passwd == NULL)
870  return STATUS_EOF; /* client wouldn't send password */
871 
872  if (shadow_pass)
873  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
874  md5Salt, 4, logdetail);
875  else
876  result = STATUS_ERROR;
877 
878  pfree(passwd);
879 
880  return result;
881 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:638
int errcode(int sqlerrcode)
Definition: elog.c:570
#define STATUS_ERROR
Definition: c.h:1090
#define LOG
Definition: elog.h:26
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
void pfree(void *pointer)
Definition: mcxt.c:1056
#define FATAL
Definition: elog.h:52
bool Db_user_namespace
Definition: postmaster.c:243
char * user_name
Definition: libpq-be.h:141
#define ereport(elevel, rest)
Definition: elog.h:141
static char * recv_password_packet(Port *port)
Definition: auth.c:668
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, char **logdetail)
Definition: crypt.c:166
bool pg_strong_random(void *buf, size_t len)
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define STATUS_EOF
Definition: c.h:1091

◆ CheckPasswordAuth()

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

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

760 {
761  char *passwd;
762  int result;
763  char *shadow_pass;
764 
765  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
766 
767  passwd = recv_password_packet(port);
768  if (passwd == NULL)
769  return STATUS_EOF; /* client wouldn't send password */
770 
771  shadow_pass = get_role_password(port->user_name, logdetail);
772  if (shadow_pass)
773  {
774  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
775  logdetail);
776  }
777  else
778  result = STATUS_ERROR;
779 
780  if (shadow_pass)
781  pfree(shadow_pass);
782  pfree(passwd);
783 
784  return result;
785 }
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:638
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:222
#define STATUS_ERROR
Definition: c.h:1090
void pfree(void *pointer)
Definition: mcxt.c:1056
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:37
char * user_name
Definition: libpq-be.h:141
static char * recv_password_packet(Port *port)
Definition: auth.c:668
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
#define STATUS_EOF
Definition: c.h:1091

◆ CheckPWChallengeAuth()

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

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

792 {
793  int auth_result;
794  char *shadow_pass;
795  PasswordType pwtype;
796 
797  Assert(port->hba->auth_method == uaSCRAM ||
798  port->hba->auth_method == uaMD5);
799 
800  /* First look up the user's password. */
801  shadow_pass = get_role_password(port->user_name, logdetail);
802 
803  /*
804  * If the user does not exist, or has no password or it's expired, we
805  * still go through the motions of authentication, to avoid revealing to
806  * the client that the user didn't exist. If 'md5' is allowed, we choose
807  * whether to use 'md5' or 'scram-sha-256' authentication based on current
808  * password_encryption setting. The idea is that most genuine users
809  * probably have a password of that type, and if we pretend that this user
810  * had a password of that type, too, it "blends in" best.
811  */
812  if (!shadow_pass)
813  pwtype = Password_encryption;
814  else
815  pwtype = get_password_type(shadow_pass);
816 
817  /*
818  * If 'md5' authentication is allowed, decide whether to perform 'md5' or
819  * 'scram-sha-256' authentication based on the type of password the user
820  * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
821  * SCRAM secret, we must do SCRAM authentication.
822  *
823  * If MD5 authentication is not allowed, always use SCRAM. If the user
824  * had an MD5 password, CheckSCRAMAuth() will fail.
825  */
826  if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
827  auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
828  else
829  auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
830 
831  if (shadow_pass)
832  pfree(shadow_pass);
833 
834  /*
835  * If get_role_password() returned error, return error, even if the
836  * authentication succeeded.
837  */
838  if (!shadow_pass)
839  {
840  Assert(auth_result != STATUS_OK);
841  return STATUS_ERROR;
842  }
843  return auth_result;
844 }
Definition: hba.h:32
int Password_encryption
Definition: user.c:46
#define STATUS_ERROR
Definition: c.h:1090
void pfree(void *pointer)
Definition: mcxt.c:1056
static int CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:884
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:37
char * user_name
Definition: libpq-be.h:141
#define STATUS_OK
Definition: c.h:1089
HbaLine * hba
Definition: libpq-be.h:155
static int CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:847
Definition: hba.h:33
PasswordType
Definition: crypt.h:27
#define Assert(condition)
Definition: c.h:732
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:89
UserAuth auth_method
Definition: hba.h:81

◆ CheckRADIUSAuth()

static int CheckRADIUSAuth ( Port port)
static

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

2949 {
2950  char *passwd;
2951  ListCell *server,
2952  *secrets,
2953  *radiusports,
2954  *identifiers;
2955 
2956  /* Make sure struct alignment is correct */
2957  Assert(offsetof(radius_packet, vector) == 4);
2958 
2959  /* Verify parameters */
2960  if (list_length(port->hba->radiusservers) < 1)
2961  {
2962  ereport(LOG,
2963  (errmsg("RADIUS server not specified")));
2964  return STATUS_ERROR;
2965  }
2966 
2967  if (list_length(port->hba->radiussecrets) < 1)
2968  {
2969  ereport(LOG,
2970  (errmsg("RADIUS secret not specified")));
2971  return STATUS_ERROR;
2972  }
2973 
2974  /* Send regular password request to client, and get the response */
2975  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
2976 
2977  passwd = recv_password_packet(port);
2978  if (passwd == NULL)
2979  return STATUS_EOF; /* client wouldn't send password */
2980 
2981  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2982  {
2983  ereport(LOG,
2984  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2985  pfree(passwd);
2986  return STATUS_ERROR;
2987  }
2988 
2989  /*
2990  * Loop over and try each server in order.
2991  */
2992  secrets = list_head(port->hba->radiussecrets);
2993  radiusports = list_head(port->hba->radiusports);
2994  identifiers = list_head(port->hba->radiusidentifiers);
2995  foreach(server, port->hba->radiusservers)
2996  {
2997  int ret = PerformRadiusTransaction(lfirst(server),
2998  lfirst(secrets),
2999  radiusports ? lfirst(radiusports) : NULL,
3000  identifiers ? lfirst(identifiers) : NULL,
3001  port->user_name,
3002  passwd);
3003 
3004  /*------
3005  * STATUS_OK = Login OK
3006  * STATUS_ERROR = Login not OK, but try next server
3007  * STATUS_EOF = Login not OK, and don't try next server
3008  *------
3009  */
3010  if (ret == STATUS_OK)
3011  {
3012  pfree(passwd);
3013  return STATUS_OK;
3014  }
3015  else if (ret == STATUS_EOF)
3016  {
3017  pfree(passwd);
3018  return STATUS_ERROR;
3019  }
3020 
3021  /*
3022  * secret, port and identifiers either have length 0 (use default),
3023  * length 1 (use the same everywhere) or the same length as servers.
3024  * So if the length is >1, we advance one step. In other cases, we
3025  * don't and will then reuse the correct value.
3026  */
3027  if (list_length(port->hba->radiussecrets) > 1)
3028  secrets = lnext(port->hba->radiussecrets, secrets);
3029  if (list_length(port->hba->radiusports) > 1)
3030  radiusports = lnext(port->hba->radiusports, radiusports);
3031  if (list_length(port->hba->radiusidentifiers) > 1)
3032  identifiers = lnext(port->hba->radiusidentifiers, identifiers);
3033  }
3034 
3035  /* No servers left to try, so give up */
3036  pfree(passwd);
3037  return STATUS_ERROR;
3038 }
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:321
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:638
#define STATUS_ERROR
Definition: c.h:1090
#define LOG
Definition: elog.h:26
List * radiussecrets
Definition: hba.h:105
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:3041
void pfree(void *pointer)
Definition: mcxt.c:1056
List * radiusports
Definition: hba.h:109
List * radiusservers
Definition: hba.h:103
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
char * user_name
Definition: libpq-be.h:141
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1089
static char * recv_password_packet(Port *port)
Definition: auth.c:668
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
HbaLine * hba
Definition: libpq-be.h:155
List * radiusidentifiers
Definition: hba.h:107
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2882
static int list_length(const List *l)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define STATUS_EOF
Definition: c.h:1091
#define offsetof(type, field)
Definition: c.h:655

◆ CheckSCRAMAuth()

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

Definition at line 884 of file auth.c.

References _, appendStringInfoChar(), Assert, AUTH_REQ_GSS_CONT, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, buf, CHECK_FOR_INTERRUPTS, check_usermap(), HbaLine::compat_realm, StringInfoData::data, DEBUG2, DEBUG4, DEBUG5, elog, ereport, errcode(), errdetail_internal(), errmsg(), errmsg_internal(), ERROR, FATAL, free, FrontendProtocol, Port::gss, Port::hba, HbaLine::include_realm, initStringInfo(), HbaLine::krb_realm, StringInfoData::len, LOG, malloc, MAXPGPATH, MemoryContextStrdup(), output(), palloc(), pfree(), pg_be_scram_exchange(), pg_be_scram_get_mechanisms(), pg_be_scram_init(), pg_GSS_error(), pg_krb_caseins_users, pg_krb_server_keyfile, PG_MAX_AUTH_TOKEN_LENGTH, PG_MAX_SASL_MESSAGE_LENGTH, PG_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, sendAuthRequest(), snprintf, status(), STATUS_EOF, STATUS_ERROR, STATUS_OK, TopMemoryContext, HbaLine::upn_username, Port::user_name, and HbaLine::usermap.

Referenced by CheckPWChallengeAuth().

885 {
886  StringInfoData sasl_mechs;
887  int mtype;
889  void *scram_opaq = NULL;
890  char *output = NULL;
891  int outputlen = 0;
892  const char *input;
893  int inputlen;
894  int result;
895  bool initial;
896 
897  /*
898  * SASL auth is not supported for protocol versions before 3, because it
899  * relies on the overall message length word to determine the SASL payload
900  * size in AuthenticationSASLContinue and PasswordMessage messages. (We
901  * used to have a hard rule that protocol messages must be parsable
902  * without relying on the length word, but we hardly care about older
903  * protocol version anymore.)
904  */
906  ereport(FATAL,
907  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
908  errmsg("SASL authentication is not supported in protocol version 2")));
909 
910  /*
911  * Send the SASL authentication request to user. It includes the list of
912  * authentication mechanisms that are supported.
913  */
914  initStringInfo(&sasl_mechs);
915 
916  pg_be_scram_get_mechanisms(port, &sasl_mechs);
917  /* Put another '\0' to mark that list is finished. */
918  appendStringInfoChar(&sasl_mechs, '\0');
919 
920  sendAuthRequest(port, AUTH_REQ_SASL, sasl_mechs.data, sasl_mechs.len);
921  pfree(sasl_mechs.data);
922 
923  /*
924  * Loop through SASL message exchange. This exchange can consist of
925  * multiple messages sent in both directions. First message is always
926  * from the client. All messages from client to server are password
927  * packets (type 'p').
928  */
929  initial = true;
930  do
931  {
932  pq_startmsgread();
933  mtype = pq_getbyte();
934  if (mtype != 'p')
935  {
936  /* Only log error if client didn't disconnect. */
937  if (mtype != EOF)
938  {
939  ereport(ERROR,
940  (errcode(ERRCODE_PROTOCOL_VIOLATION),
941  errmsg("expected SASL response, got message type %d",
942  mtype)));
943  }
944  else
945  return STATUS_EOF;
946  }
947 
948  /* Get the actual SASL message */
949  initStringInfo(&buf);
951  {
952  /* EOF - pq_getmessage already logged error */
953  pfree(buf.data);
954  return STATUS_ERROR;
955  }
956 
957  elog(DEBUG4, "Processing received SASL response of length %d", buf.len);
958 
959  /*
960  * The first SASLInitialResponse message is different from the others.
961  * It indicates which SASL mechanism the client selected, and contains
962  * an optional Initial Client Response payload. The subsequent
963  * SASLResponse messages contain just the SASL payload.
964  */
965  if (initial)
966  {
967  const char *selected_mech;
968 
969  selected_mech = pq_getmsgrawstring(&buf);
970 
971  /*
972  * Initialize the status tracker for message exchanges.
973  *
974  * If the user doesn't exist, or doesn't have a valid password, or
975  * it's expired, we still go through the motions of SASL
976  * authentication, but tell the authentication method that the
977  * authentication is "doomed". That is, it's going to fail, no
978  * matter what.
979  *
980  * This is because we don't want to reveal to an attacker what
981  * usernames are valid, nor which users have a valid password.
982  */
983  scram_opaq = pg_be_scram_init(port, selected_mech, shadow_pass);
984 
985  inputlen = pq_getmsgint(&buf, 4);
986  if (inputlen == -1)
987  input = NULL;
988  else
989  input = pq_getmsgbytes(&buf, inputlen);
990 
991  initial = false;
992  }
993  else
994  {
995  inputlen = buf.len;
996  input = pq_getmsgbytes(&buf, buf.len);
997  }
998  pq_getmsgend(&buf);
999 
1000  /*
1001  * The StringInfo guarantees that there's a \0 byte after the
1002  * response.
1003  */
1004  Assert(input == NULL || input[inputlen] == '\0');
1005 
1006  /*
1007  * we pass 'logdetail' as NULL when doing a mock authentication,
1008  * because we should already have a better error message in that case
1009  */
1010  result = pg_be_scram_exchange(scram_opaq, input, inputlen,
1011  &output, &outputlen,
1012  logdetail);
1013 
1014  /* input buffer no longer used */
1015  pfree(buf.data);
1016 
1017  if (output)
1018  {
1019  /*
1020  * Negotiation generated data to be sent to the client.
1021  */
1022  elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
1023 
1024  if (result == SASL_EXCHANGE_SUCCESS)
1025  sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
1026  else
1027  sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
1028 
1029  pfree(output);
1030  }
1031  } while (result == SASL_EXCHANGE_CONTINUE);
1032 
1033  /* Oops, Something bad happened */
1034  if (result != SASL_EXCHANGE_SUCCESS)
1035  {
1036  return STATUS_ERROR;
1037  }
1038 
1039  return STATUS_OK;
1040 }
void pg_be_scram_get_mechanisms(Port *port, StringInfo buf)
Definition: auth-scram.c:181
static void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:638
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:177
static void output(uint64 loop_count)
#define SASL_EXCHANGE_SUCCESS
Definition: scram.h:21
int errcode(int sqlerrcode)
Definition: elog.c:570
#define STATUS_ERROR
Definition: c.h:1090
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 * pg_be_scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
Definition: auth-scram.c:218
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
void pq_startmsgread(void)
Definition: pqcomm.c:1211
#define FATAL
Definition: elog.h:52
static char * buf
Definition: pg_test_fsync.c:68
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1089
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1273
int pg_be_scram_exchange(void *opaq, const char *input, int inputlen, char **output, int *outputlen, char **logdetail)
Definition: auth-scram.c:328
int pq_getbyte(void)
Definition: pqcomm.c:1001
#define AUTH_REQ_SASL_CONT
Definition: pqcomm.h:176
#define Assert(condition)
Definition: c.h:732
#define PG_MAX_SASL_MESSAGE_LENGTH
Definition: auth.c:227
#define AUTH_REQ_SASL
Definition: pqcomm.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:637
#define SASL_EXCHANGE_CONTINUE
Definition: scram.h:20
#define STATUS_EOF
Definition: c.h:1091
ProtocolVersion FrontendProtocol
Definition: globals.c:28

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 343 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, clientCertFull, clientCertOff, Port::database_name, ereport, errcode(), errmsg(), FATAL, Port::gss, 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().

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

◆ ident_inet()

static int ident_inet ( hbaPort port)
static

Definition at line 1806 of file auth.c.

References _, SockAddr::addr, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, HbaLine::auth_method, AUTH_REQ_PASSWORD, bind, calloc, CHECK_FOR_INTERRUPTS, check_usermap(), HbaLine::clientcert, clientCertFull, closesocket, connect, HbaLine::conntype, ctLocal, StringInfoData::data, EINTR, elog, ereport, errcode(), errcode_for_socket_access(), errdetail(), errdetail_plural(), errhint(), 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::ldapscheme, HbaLine::ldapscope, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, HbaLine::ldaptls, StringInfoData::len, 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(), uaCert, unconstify, user, Port::user_name, HbaLine::usermap, and WARNING.

Referenced by ClientAuthentication().

1807 {
1808  const SockAddr remote_addr = port->raddr;
1809  const SockAddr local_addr = port->laddr;
1810  char ident_user[IDENT_USERNAME_MAX + 1];
1811  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1812  int rc; /* Return code from a locally called function */
1813  bool ident_return;
1814  char remote_addr_s[NI_MAXHOST];
1815  char remote_port[NI_MAXSERV];
1816  char local_addr_s[NI_MAXHOST];
1817  char local_port[NI_MAXSERV];
1818  char ident_port[NI_MAXSERV];
1819  char ident_query[80];
1820  char ident_response[80 + IDENT_USERNAME_MAX];
1821  struct addrinfo *ident_serv = NULL,
1822  *la = NULL,
1823  hints;
1824 
1825  /*
1826  * Might look a little weird to first convert it to text and then back to
1827  * sockaddr, but it's protocol independent.
1828  */
1829  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1830  remote_addr_s, sizeof(remote_addr_s),
1831  remote_port, sizeof(remote_port),
1833  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1834  local_addr_s, sizeof(local_addr_s),
1835  local_port, sizeof(local_port),
1837 
1838  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1839  hints.ai_flags = AI_NUMERICHOST;
1840  hints.ai_family = remote_addr.addr.ss_family;
1841  hints.ai_socktype = SOCK_STREAM;
1842  hints.ai_protocol = 0;
1843  hints.ai_addrlen = 0;
1844  hints.ai_canonname = NULL;
1845  hints.ai_addr = NULL;
1846  hints.ai_next = NULL;
1847  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1848  if (rc || !ident_serv)
1849  {
1850  /* we don't expect this to happen */
1851  ident_return = false;
1852  goto ident_inet_done;
1853  }
1854 
1855  hints.ai_flags = AI_NUMERICHOST;
1856  hints.ai_family = local_addr.addr.ss_family;
1857  hints.ai_socktype = SOCK_STREAM;
1858  hints.ai_protocol = 0;
1859  hints.ai_addrlen = 0;
1860  hints.ai_canonname = NULL;
1861  hints.ai_addr = NULL;
1862  hints.ai_next = NULL;
1863  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1864  if (rc || !la)
1865  {
1866  /* we don't expect this to happen */
1867  ident_return = false;
1868  goto ident_inet_done;
1869  }
1870 
1871  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1872  ident_serv->ai_protocol);
1873  if (sock_fd == PGINVALID_SOCKET)
1874  {
1875  ereport(LOG,
1877  errmsg("could not create socket for Ident connection: %m")));
1878  ident_return = false;
1879  goto ident_inet_done;
1880  }
1881 
1882  /*
1883  * Bind to the address which the client originally contacted, otherwise
1884  * the ident server won't be able to match up the right connection. This
1885  * is necessary if the PostgreSQL server is running on an IP alias.
1886  */
1887  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1888  if (rc != 0)
1889  {
1890  ereport(LOG,
1892  errmsg("could not bind to local address \"%s\": %m",
1893  local_addr_s)));
1894  ident_return = false;
1895  goto ident_inet_done;
1896  }
1897 
1898  rc = connect(sock_fd, ident_serv->ai_addr,
1899  ident_serv->ai_addrlen);
1900  if (rc != 0)
1901  {
1902  ereport(LOG,
1904  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1905  remote_addr_s, ident_port)));
1906  ident_return = false;
1907  goto ident_inet_done;
1908  }
1909 
1910  /* The query we send to the Ident server */
1911  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1912  remote_port, local_port);
1913 
1914  /* loop in case send is interrupted */
1915  do
1916  {
1918 
1919  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1920  } while (rc < 0 && errno == EINTR);
1921 
1922  if (rc < 0)
1923  {
1924  ereport(LOG,
1926  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1927  remote_addr_s, ident_port)));
1928  ident_return = false;
1929  goto ident_inet_done;
1930  }
1931 
1932  do
1933  {
1935 
1936  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1937  } while (rc < 0 && errno == EINTR);
1938 
1939  if (rc < 0)
1940  {
1941  ereport(LOG,
1943  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1944  remote_addr_s, ident_port)));
1945  ident_return = false;
1946  goto ident_inet_done;
1947  }
1948 
1949  ident_response[rc] = '\0';
1950  ident_return = interpret_ident_response(ident_response, ident_user);
1951  if (!ident_return)
1952  ereport(LOG,
1953  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1954  ident_response)));
1955 
1956 ident_inet_done:
1957  if (sock_fd != PGINVALID_SOCKET)
1958  closesocket(sock_fd);
1959  if (ident_serv)
1960  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1961  if (la)
1962  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1963 
1964  if (ident_return)
1965  /* Success! Check the usermap */
1966  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1967  return STATUS_ERROR;
1968 }
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:312
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define STATUS_ERROR
Definition: c.h:1090
#define connect(s, name, namelen)
Definition: win32_port.h:435
#define LOG
Definition: elog.h:26
#define AI_NUMERICHOST
Definition: getaddrinfo.h:73
#define bind(s, addr, addrlen)
Definition: win32_port.h:432
#define recv(s, buf, len, flags)
Definition: win32_port.h:437
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:126
#define IDENT_USERNAME_MAX
Definition: auth.c:69
#define NI_MAXHOST
Definition: getaddrinfo.h:88
char * usermap
Definition: hba.h:83
#define IDENT_PORT
Definition: auth.c:72
#define NI_MAXSERV
Definition: getaddrinfo.h:91
char * user_name
Definition: libpq-be.h:141
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define ereport(elevel, rest)
Definition: elog.h:141
int errcode_for_socket_access(void)
Definition: elog.c:664
SockAddr laddr
Definition: libpq-be.h:125
HbaLine * hba
Definition: libpq-be.h:155
#define socket(af, type, protocol)
Definition: win32_port.h:431
#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:2924
#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:784
size_t ai_addrlen
Definition: getaddrinfo.h:104
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define EINTR
Definition: win32_port.h:323
#define snprintf
Definition: port.h:192
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1723
struct sockaddr * ai_addr
Definition: getaddrinfo.h:105
#define send(s, buf, len, flags)
Definition: win32_port.h:438
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 1723 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1725 {
1726  const char *cursor = ident_response; /* Cursor into *ident_response */
1727 
1728  /*
1729  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1730  */
1731  if (strlen(ident_response) < 2)
1732  return false;
1733  else if (ident_response[strlen(ident_response) - 2] != '\r')
1734  return false;
1735  else
1736  {
1737  while (*cursor != ':' && *cursor != '\r')
1738  cursor++; /* skip port field */
1739 
1740  if (*cursor != ':')
1741  return false;
1742  else
1743  {
1744  /* We're positioned to colon before response type field */
1745  char response_type[80];
1746  int i; /* Index into *response_type */
1747 
1748  cursor++; /* Go over colon */
1749  while (pg_isblank(*cursor))
1750  cursor++; /* skip blanks */
1751  i = 0;
1752  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1753  i < (int) (sizeof(response_type) - 1))
1754  response_type[i++] = *cursor++;
1755  response_type[i] = '\0';
1756  while (pg_isblank(*cursor))
1757  cursor++; /* skip blanks */
1758  if (strcmp(response_type, "USERID") != 0)
1759  return false;
1760  else
1761  {
1762  /*
1763  * It's a USERID response. Good. "cursor" should be pointing
1764  * to the colon that precedes the operating system type.
1765  */
1766  if (*cursor != ':')
1767  return false;
1768  else
1769  {
1770  cursor++; /* Go over colon */
1771  /* Skip over operating system field. */
1772  while (*cursor != ':' && *cursor != '\r')
1773  cursor++;
1774  if (*cursor != ':')
1775  return false;
1776  else
1777  {
1778  int i; /* Index into *ident_user */
1779 
1780  cursor++; /* Go over colon */
1781  while (pg_isblank(*cursor))
1782  cursor++; /* skip blanks */
1783  /* Rest of line is user name. Copy it over. */
1784  i = 0;
1785  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1786  ident_user[i++] = *cursor++;
1787  ident_user[i] = '\0';
1788  return true;
1789  }
1790  }
1791  }
1792  }
1793  }
1794 }
bool pg_isblank(const char c)
Definition: hba.c:160
#define IDENT_USERNAME_MAX
Definition: auth.c:69
Definition: type.h:130
int i

◆ PerformRadiusTransaction()

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

Definition at line 3041 of file auth.c.

References addrinfo::ai_family, addrinfo::ai_socktype, bind, closesocket, radius_packet::code, EINTR, ereport, errmsg(), gai_strerror, gettimeofday(), i, radius_packet::id, radius_packet::length, LOG, MemSet, palloc(), pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_hton16, pg_hton32, pg_md5_binary(), pg_ntoh16, pg_strong_random(), PGINVALID_SOCKET, port, RADIUS_ACCESS_ACCEPT, RADIUS_ACCESS_REJECT, RADIUS_ACCESS_REQUEST, radius_add_attribute(), RADIUS_AUTHENTICATE_ONLY, RADIUS_BUFFER_SIZE, RADIUS_HEADER_LENGTH, RADIUS_MAX_PASSWORD_LENGTH, RADIUS_NAS_IDENTIFIER, RADIUS_PASSWORD, RADIUS_SERVICE_TYPE, RADIUS_TIMEOUT, RADIUS_USER_NAME, RADIUS_VECTOR_LENGTH, select, socket, STATUS_EOF, STATUS_ERROR, STATUS_OK, and radius_packet::vector.

Referenced by CheckRADIUSAuth().

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

2923 {
2924  radius_attribute *attr;
2925 
2926  if (packet->length + len > RADIUS_BUFFER_SIZE)
2927  {
2928  /*
2929  * With remotely realistic data, this can never happen. But catch it
2930  * just to make sure we don't overrun a buffer. We'll just skip adding
2931  * the broken attribute, which will in the end cause authentication to
2932  * fail.
2933  */
2934  elog(WARNING,
2935  "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2936  type, len);
2937  return;
2938  }
2939 
2940  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2941  attr->attribute = type;
2942  attr->length = len + 2; /* total size includes type and length */
2943  memcpy(attr->data, data, len);
2944  packet->length += attr->length;
2945 }
uint16 length
Definition: auth.c:2898
uint8 attribute
Definition: auth.c:2889
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2885
#define elog(elevel,...)
Definition: elog.h:226
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2891
uint8 length
Definition: auth.c:2890

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

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

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

◆ sendAuthRequest()

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

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

639 {
641 
643 
644  pq_beginmessage(&buf, 'R');
645  pq_sendint32(&buf, (int32) areq);
646  if (extralen > 0)
647  pq_sendbytes(&buf, extradata, extralen);
648 
649  pq_endmessage(&buf);
650 
651  /*
652  * Flush message so client will see it, except for AUTH_REQ_OK and
653  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
654  * queries.
655  */
656  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
657  pq_flush();
658 
660 }
#define pq_flush()
Definition: libpq.h:39
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:177
#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:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static char * buf
Definition: pg_test_fsync.c:68
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:298
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 239 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(), and secure_open_gssapi().