PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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, 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 (char *server, char *secret, char *portstr, char *identifier, char *user_name, 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

#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().

#define IDENT_PORT   113

Definition at line 71 of file auth.c.

Referenced by ident_inet().

#define IDENT_USERNAME_MAX   512

Definition at line 68 of file auth.c.

Referenced by ident_inet(), and interpret_ident_response().

#define PG_MAX_AUTH_TOKEN_LENGTH   65535

Definition at line 221 of file auth.c.

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 229 of file auth.c.

Referenced by CheckSCRAMAuth().

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2742 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_ACCESS_REJECT   3

Definition at line 2743 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2741 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2752 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2721 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

#define RADIUS_HEADER_LENGTH   20

Definition at line 2717 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2718 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2749 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_PASSWORD   2

Definition at line 2747 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_SERVICE_TYPE   6

Definition at line 2748 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_TIMEOUT   3

Definition at line 2755 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_USER_NAME   1

Definition at line 2746 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2716 of file auth.c.

Referenced by PerformRadiusTransaction().

Function Documentation

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

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

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

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

825 {
826  char md5Salt[4]; /* Password salt */
827  char *passwd;
828  int result;
829 
830  if (Db_user_namespace)
831  ereport(FATAL,
832  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
833  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
834 
835  /* include the salt to use for computing the response */
836  if (!pg_backend_random(md5Salt, 4))
837  {
838  ereport(LOG,
839  (errmsg("could not generate random MD5 salt")));
840  return STATUS_ERROR;
841  }
842 
843  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
844 
845  passwd = recv_password_packet(port);
846  if (passwd == NULL)
847  return STATUS_EOF; /* client wouldn't send password */
848 
849  if (shadow_pass)
850  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
851  md5Salt, 4, logdetail);
852  else
853  result = STATUS_ERROR;
854 
855  pfree(passwd);
856 
857  return result;
858 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:982
#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:240
char * user_name
Definition: libpq-be.h:137
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:615
#define ereport(elevel, rest)
Definition: elog.h:122
static char * recv_password_packet(Port *port)
Definition: auth.c:645
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:983
static int CheckPasswordAuth ( Port port,
char **  logdetail 
)
static

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

737 {
738  char *passwd;
739  int result;
740  char *shadow_pass;
741 
742  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
743 
744  passwd = recv_password_packet(port);
745  if (passwd == NULL)
746  return STATUS_EOF; /* client wouldn't send password */
747 
748  shadow_pass = get_role_password(port->user_name, logdetail);
749  if (shadow_pass)
750  {
751  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
752  logdetail);
753  }
754  else
755  result = STATUS_ERROR;
756 
757  if (shadow_pass)
758  pfree(shadow_pass);
759  pfree(passwd);
760 
761  return result;
762 }
#define STATUS_ERROR
Definition: c.h:982
void pfree(void *pointer)
Definition: mcxt.c:949
char * user_name
Definition: libpq-be.h:137
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:615
static char * recv_password_packet(Port *port)
Definition: auth.c:645
#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:983
static int CheckPWChallengeAuth ( Port port,
char **  logdetail 
)
static

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

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

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

2785 {
2786  char *passwd;
2787  ListCell *server,
2788  *secrets,
2789  *radiusports,
2790  *identifiers;
2791 
2792  /* Make sure struct alignment is correct */
2793  Assert(offsetof(radius_packet, vector) == 4);
2794 
2795  /* Verify parameters */
2796  if (list_length(port->hba->radiusservers) < 1)
2797  {
2798  ereport(LOG,
2799  (errmsg("RADIUS server not specified")));
2800  return STATUS_ERROR;
2801  }
2802 
2803  if (list_length(port->hba->radiussecrets) < 1)
2804  {
2805  ereport(LOG,
2806  (errmsg("RADIUS secret not specified")));
2807  return STATUS_ERROR;
2808  }
2809 
2810  /* Send regular password request to client, and get the response */
2811  sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
2812 
2813  passwd = recv_password_packet(port);
2814  if (passwd == NULL)
2815  return STATUS_EOF; /* client wouldn't send password */
2816 
2817  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2818  {
2819  ereport(LOG,
2820  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2821  pfree(passwd);
2822  return STATUS_ERROR;
2823  }
2824 
2825  /*
2826  * Loop over and try each server in order.
2827  */
2828  secrets = list_head(port->hba->radiussecrets);
2829  radiusports = list_head(port->hba->radiusports);
2830  identifiers = list_head(port->hba->radiusidentifiers);
2831  foreach(server, port->hba->radiusservers)
2832  {
2833  int ret = PerformRadiusTransaction(lfirst(server),
2834  lfirst(secrets),
2835  radiusports ? lfirst(radiusports) : NULL,
2836  identifiers ? lfirst(identifiers) : NULL,
2837  port->user_name,
2838  passwd);
2839 
2840  /*------
2841  * STATUS_OK = Login OK
2842  * STATUS_ERROR = Login not OK, but try next server
2843  * STATUS_EOF = Login not OK, and don't try next server
2844  *------
2845  */
2846  if (ret == STATUS_OK)
2847  {
2848  pfree(passwd);
2849  return STATUS_OK;
2850  }
2851  else if (ret == STATUS_EOF)
2852  {
2853  pfree(passwd);
2854  return STATUS_ERROR;
2855  }
2856 
2857  /*
2858  * secret, port and identifiers either have length 0 (use default),
2859  * length 1 (use the same everywhere) or the same length as servers.
2860  * So if the length is >1, we advance one step. In other cases, we
2861  * don't and will then reuse the correct value.
2862  */
2863  if (list_length(port->hba->radiussecrets) > 1)
2864  secrets = lnext(secrets);
2865  if (list_length(port->hba->radiusports) > 1)
2866  radiusports = lnext(radiusports);
2867  if (list_length(port->hba->radiusidentifiers) > 1)
2868  identifiers = lnext(identifiers);
2869  }
2870 
2871  /* No servers left to try, so give up */
2872  pfree(passwd);
2873  return STATUS_ERROR;
2874 }
#define STATUS_ERROR
Definition: c.h:982
#define LOG
Definition: elog.h:26
List * radiussecrets
Definition: hba.h:95
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
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:615
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:981
static char * recv_password_packet(Port *port)
Definition: auth.c:645
#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:681
#define lfirst(lc)
Definition: pg_list.h:106
static int PerformRadiusTransaction(char *server, char *secret, char *portstr, char *identifier, char *user_name, char *passwd)
Definition: auth.c:2877
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2718
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:983
#define offsetof(type, field)
Definition: c.h:549
static int CheckSCRAMAuth ( Port port,
char *  shadow_pass,
char **  logdetail 
)
static

Definition at line 861 of file auth.c.

References Assert, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, buf, StringInfoData::data, DEBUG4, elog, ereport, errcode(), errmsg(), ERROR, FATAL, FrontendProtocol, initStringInfo(), StringInfoData::len, output(), pfree(), pg_be_scram_exchange(), pg_be_scram_init(), PG_MAX_SASL_MESSAGE_LENGTH, PG_PROTOCOL_MAJOR, pq_getbyte(), pq_getmessage(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), pq_getmsgrawstring(), pq_startmsgread(), SASL_EXCHANGE_CONTINUE, SASL_EXCHANGE_SUCCESS, SCRAM_SHA256_NAME, sendAuthRequest(), STATUS_EOF, STATUS_ERROR, STATUS_OK, and Port::user_name.

Referenced by CheckPWChallengeAuth().

862 {
863  int mtype;
865  void *scram_opaq;
866  char *output = NULL;
867  int outputlen = 0;
868  char *input;
869  int inputlen;
870  int result;
871  bool initial;
872 
873  /*
874  * SASL auth is not supported for protocol versions before 3, because it
875  * relies on the overall message length word to determine the SASL payload
876  * size in AuthenticationSASLContinue and PasswordMessage messages. (We
877  * used to have a hard rule that protocol messages must be parsable
878  * without relying on the length word, but we hardly care about older
879  * protocol version anymore.)
880  */
882  ereport(FATAL,
883  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
884  errmsg("SASL authentication is not supported in protocol version 2")));
885 
886  /*
887  * Send the SASL authentication request to user. It includes the list of
888  * authentication mechanisms (which is trivial, because we only support
889  * SCRAM-SHA-256 at the moment). The extra "\0" is for an empty string to
890  * terminate the list.
891  */
893  strlen(SCRAM_SHA256_NAME) + 2);
894 
895  /*
896  * Initialize the status tracker for message exchanges.
897  *
898  * If the user doesn't exist, or doesn't have a valid password, or it's
899  * expired, we still go through the motions of SASL authentication, but
900  * tell the authentication method that the authentication is "doomed".
901  * That is, it's going to fail, no matter what.
902  *
903  * This is because we don't want to reveal to an attacker what usernames
904  * are valid, nor which users have a valid password.
905  */
906  scram_opaq = pg_be_scram_init(port->user_name, shadow_pass);
907 
908  /*
909  * Loop through SASL message exchange. This exchange can consist of
910  * multiple messages sent in both directions. First message is always
911  * from the client. All messages from client to server are password
912  * packets (type 'p').
913  */
914  initial = true;
915  do
916  {
917  pq_startmsgread();
918  mtype = pq_getbyte();
919  if (mtype != 'p')
920  {
921  /* Only log error if client didn't disconnect. */
922  if (mtype != EOF)
923  {
924  ereport(ERROR,
925  (errcode(ERRCODE_PROTOCOL_VIOLATION),
926  errmsg("expected SASL response, got message type %d",
927  mtype)));
928  }
929  else
930  return STATUS_EOF;
931  }
932 
933  /* Get the actual SASL message */
934  initStringInfo(&buf);
936  {
937  /* EOF - pq_getmessage already logged error */
938  pfree(buf.data);
939  return STATUS_ERROR;
940  }
941 
942  elog(DEBUG4, "Processing received SASL response of length %d", buf.len);
943 
944  /*
945  * The first SASLInitialResponse message is different from the others.
946  * It indicates which SASL mechanism the client selected, and contains
947  * an optional Initial Client Response payload. The subsequent
948  * SASLResponse messages contain just the SASL payload.
949  */
950  if (initial)
951  {
952  const char *selected_mech;
953 
954  /*
955  * We only support SCRAM-SHA-256 at the moment, so anything else
956  * is an error.
957  */
958  selected_mech = pq_getmsgrawstring(&buf);
959  if (strcmp(selected_mech, SCRAM_SHA256_NAME) != 0)
960  {
961  ereport(ERROR,
962  (errcode(ERRCODE_PROTOCOL_VIOLATION),
963  errmsg("client selected an invalid SASL authentication mechanism")));
964  }
965 
966  inputlen = pq_getmsgint(&buf, 4);
967  if (inputlen == -1)
968  input = NULL;
969  else
970  input = (char *) pq_getmsgbytes(&buf, inputlen);
971 
972  initial = false;
973  }
974  else
975  {
976  inputlen = buf.len;
977  input = (char *) pq_getmsgbytes(&buf, buf.len);
978  }
979  pq_getmsgend(&buf);
980 
981  /*
982  * The StringInfo guarantees that there's a \0 byte after the
983  * response.
984  */
985  Assert(input == NULL || input[inputlen] == '\0');
986 
987  /*
988  * we pass 'logdetail' as NULL when doing a mock authentication,
989  * because we should already have a better error message in that case
990  */
991  result = pg_be_scram_exchange(scram_opaq, input, inputlen,
992  &output, &outputlen,
993  logdetail);
994 
995  /* input buffer no longer used */
996  pfree(buf.data);
997 
998  if (output)
999  {
1000  /*
1001  * Negotiation generated data to be sent to the client.
1002  */
1003  elog(DEBUG4, "sending SASL challenge of length %u", outputlen);
1004 
1005  if (result == SASL_EXCHANGE_SUCCESS)
1006  sendAuthRequest(port, AUTH_REQ_SASL_FIN, output, outputlen);
1007  else
1008  sendAuthRequest(port, AUTH_REQ_SASL_CONT, output, outputlen);
1009 
1010  pfree(output);
1011  }
1012  } while (result == SASL_EXCHANGE_CONTINUE);
1013 
1014  /* Oops, Something bad happened */
1015  if (result != SASL_EXCHANGE_SUCCESS)
1016  {
1017  return STATUS_ERROR;
1018  }
1019 
1020  return STATUS_OK;
1021 }
#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:258
#define SASL_EXCHANGE_SUCCESS
Definition: scram.h:21
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:982
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
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:615
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:981
void * pg_be_scram_init(const char *username, const char *shadow_pass)
Definition: auth-scram.c:171
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:681
#define PG_MAX_SASL_MESSAGE_LENGTH
Definition: auth.c:229
#define AUTH_REQ_SASL
Definition: pqcomm.h:175
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:20
#define STATUS_EOF
Definition: c.h:983
ProtocolVersion FrontendProtocol
Definition: globals.c:27
void ClientAuthentication ( Port port)

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

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

Definition at line 1827 of file auth.c.

References SockAddr::addr, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, bind, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, EINTR, ereport, errcode_for_socket_access(), errmsg(), Port::hba, IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), Port::laddr, LOG, NI_MAXHOST, NI_MAXSERV, NI_NUMERICHOST, NI_NUMERICSERV, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, Port::raddr, recv, SockAddr::salen, send, snprintf(), socket, STATUS_ERROR, Port::user_name, and HbaLine::usermap.

Referenced by ClientAuthentication().

1828 {
1829  const SockAddr remote_addr = port->raddr;
1830  const SockAddr local_addr = port->laddr;
1831  char ident_user[IDENT_USERNAME_MAX + 1];
1832  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1833  int rc; /* Return code from a locally called function */
1834  bool ident_return;
1835  char remote_addr_s[NI_MAXHOST];
1836  char remote_port[NI_MAXSERV];
1837  char local_addr_s[NI_MAXHOST];
1838  char local_port[NI_MAXSERV];
1839  char ident_port[NI_MAXSERV];
1840  char ident_query[80];
1841  char ident_response[80 + IDENT_USERNAME_MAX];
1842  struct addrinfo *ident_serv = NULL,
1843  *la = NULL,
1844  hints;
1845 
1846  /*
1847  * Might look a little weird to first convert it to text and then back to
1848  * sockaddr, but it's protocol independent.
1849  */
1850  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1851  remote_addr_s, sizeof(remote_addr_s),
1852  remote_port, sizeof(remote_port),
1854  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1855  local_addr_s, sizeof(local_addr_s),
1856  local_port, sizeof(local_port),
1858 
1859  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1860  hints.ai_flags = AI_NUMERICHOST;
1861  hints.ai_family = remote_addr.addr.ss_family;
1862  hints.ai_socktype = SOCK_STREAM;
1863  hints.ai_protocol = 0;
1864  hints.ai_addrlen = 0;
1865  hints.ai_canonname = NULL;
1866  hints.ai_addr = NULL;
1867  hints.ai_next = NULL;
1868  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1869  if (rc || !ident_serv)
1870  {
1871  /* we don't expect this to happen */
1872  ident_return = false;
1873  goto ident_inet_done;
1874  }
1875 
1876  hints.ai_flags = AI_NUMERICHOST;
1877  hints.ai_family = local_addr.addr.ss_family;
1878  hints.ai_socktype = SOCK_STREAM;
1879  hints.ai_protocol = 0;
1880  hints.ai_addrlen = 0;
1881  hints.ai_canonname = NULL;
1882  hints.ai_addr = NULL;
1883  hints.ai_next = NULL;
1884  rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1885  if (rc || !la)
1886  {
1887  /* we don't expect this to happen */
1888  ident_return = false;
1889  goto ident_inet_done;
1890  }
1891 
1892  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1893  ident_serv->ai_protocol);
1894  if (sock_fd == PGINVALID_SOCKET)
1895  {
1896  ereport(LOG,
1898  errmsg("could not create socket for Ident connection: %m")));
1899  ident_return = false;
1900  goto ident_inet_done;
1901  }
1902 
1903  /*
1904  * Bind to the address which the client originally contacted, otherwise
1905  * the ident server won't be able to match up the right connection. This
1906  * is necessary if the PostgreSQL server is running on an IP alias.
1907  */
1908  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1909  if (rc != 0)
1910  {
1911  ereport(LOG,
1913  errmsg("could not bind to local address \"%s\": %m",
1914  local_addr_s)));
1915  ident_return = false;
1916  goto ident_inet_done;
1917  }
1918 
1919  rc = connect(sock_fd, ident_serv->ai_addr,
1920  ident_serv->ai_addrlen);
1921  if (rc != 0)
1922  {
1923  ereport(LOG,
1925  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1926  remote_addr_s, ident_port)));
1927  ident_return = false;
1928  goto ident_inet_done;
1929  }
1930 
1931  /* The query we send to the Ident server */
1932  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1933  remote_port, local_port);
1934 
1935  /* loop in case send is interrupted */
1936  do
1937  {
1939 
1940  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1941  } while (rc < 0 && errno == EINTR);
1942 
1943  if (rc < 0)
1944  {
1945  ereport(LOG,
1947  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1948  remote_addr_s, ident_port)));
1949  ident_return = false;
1950  goto ident_inet_done;
1951  }
1952 
1953  do
1954  {
1956 
1957  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1958  } while (rc < 0 && errno == EINTR);
1959 
1960  if (rc < 0)
1961  {
1962  ereport(LOG,
1964  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1965  remote_addr_s, ident_port)));
1966  ident_return = false;
1967  goto ident_inet_done;
1968  }
1969 
1970  ident_response[rc] = '\0';
1971  ident_return = interpret_ident_response(ident_response, ident_user);
1972  if (!ident_return)
1973  ereport(LOG,
1974  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1975  ident_response)));
1976 
1977 ident_inet_done:
1978  if (sock_fd != PGINVALID_SOCKET)
1979  closesocket(sock_fd);
1980  if (ident_serv)
1981  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1982  if (la)
1983  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1984 
1985  if (ident_return)
1986  /* Success! Check the usermap */
1987  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1988  return STATUS_ERROR;
1989 }
#define send(s, buf, len, flags)
Definition: win32.h:376
#define connect(s, name, namelen)
Definition: win32.h:373
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:331
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define socket(af, type, protocol)
Definition: win32.h:369
#define STATUS_ERROR
Definition: c.h:982
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define recv(s, buf, len, flags)
Definition: win32.h:375
#define LOG
Definition: elog.h:26
#define AI_NUMERICHOST
Definition: getaddrinfo.h:73
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
#define bind(s, addr, addrlen)
Definition: win32.h:370
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:22
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 PGINVALID_SOCKET
Definition: port.h:24
#define EINTR
Definition: win32.h:285
int check_usermap(const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
Definition: hba.c:2842
#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
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1739
struct sockaddr * ai_addr
Definition: getaddrinfo.h:105
int ai_family
Definition: getaddrinfo.h:101
static bool interpret_ident_response ( const char *  ident_response,
char *  ident_user 
)
static

Definition at line 1739 of file auth.c.

References i, IDENT_USERNAME_MAX, and pg_isblank().

Referenced by ident_inet().

1741 {
1742  const char *cursor = ident_response; /* Cursor into *ident_response */
1743 
1744  /*
1745  * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1746  */
1747  if (strlen(ident_response) < 2)
1748  return false;
1749  else if (ident_response[strlen(ident_response) - 2] != '\r')
1750  return false;
1751  else
1752  {
1753  while (*cursor != ':' && *cursor != '\r')
1754  cursor++; /* skip port field */
1755 
1756  if (*cursor != ':')
1757  return false;
1758  else
1759  {
1760  /* We're positioned to colon before response type field */
1761  char response_type[80];
1762  int i; /* Index into *response_type */
1763 
1764  cursor++; /* Go over colon */
1765  while (pg_isblank(*cursor))
1766  cursor++; /* skip blanks */
1767  i = 0;
1768  while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1769  i < (int) (sizeof(response_type) - 1))
1770  response_type[i++] = *cursor++;
1771  response_type[i] = '\0';
1772  while (pg_isblank(*cursor))
1773  cursor++; /* skip blanks */
1774  if (strcmp(response_type, "USERID") != 0)
1775  return false;
1776  else
1777  {
1778  /*
1779  * It's a USERID response. Good. "cursor" should be pointing
1780  * to the colon that precedes the operating system type.
1781  */
1782  if (*cursor != ':')
1783  return false;
1784  else
1785  {
1786  cursor++; /* Go over colon */
1787  /* Skip over operating system field. */
1788  while (*cursor != ':' && *cursor != '\r')
1789  cursor++;
1790  if (*cursor != ':')
1791  return false;
1792  else
1793  {
1794  int i; /* Index into *ident_user */
1795 
1796  cursor++; /* Go over colon */
1797  while (pg_isblank(*cursor))
1798  cursor++; /* skip blanks */
1799  /* Rest of line is user name. Copy it over. */
1800  i = 0;
1801  while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1802  ident_user[i++] = *cursor++;
1803  ident_user[i] = '\0';
1804  return true;
1805  }
1806  }
1807  }
1808  }
1809  }
1810 }
bool pg_isblank(const char c)
Definition: hba.c:160
#define IDENT_USERNAME_MAX
Definition: auth.c:68
Definition: type.h:124
int i
static int PerformRadiusTransaction ( char *  server,
char *  secret,
char *  portstr,
char *  identifier,
char *  user_name,
char *  passwd 
)
static

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

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

Definition at line 2758 of file auth.c.

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

Referenced by PerformRadiusTransaction().

2759 {
2760  radius_attribute *attr;
2761 
2762  if (packet->length + len > RADIUS_BUFFER_SIZE)
2763  {
2764  /*
2765  * With remotely realistic data, this can never happen. But catch it
2766  * just to make sure we don't overrun a buffer. We'll just skip adding
2767  * the broken attribute, which will in the end cause authentication to
2768  * fail.
2769  */
2770  elog(WARNING,
2771  "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2772  type, len);
2773  return;
2774  }
2775 
2776  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2777  attr->attribute = type;
2778  attr->length = len + 2; /* total size includes type and length */
2779  memcpy(attr->data, data, len);
2780  packet->length += attr->length;
2781 }
uint16 length
Definition: auth.c:2734
uint8 attribute
Definition: auth.c:2725
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2721
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2727
#define elog
Definition: elog.h:219
uint8 length
Definition: auth.c:2726
static char * recv_password_packet ( Port port)
static

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

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

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

616 {
618 
620 
621  pq_beginmessage(&buf, 'R');
622  pq_sendint32(&buf, (int32) areq);
623  if (extralen > 0)
624  pq_sendbytes(&buf, extradata, extralen);
625 
626  pq_endmessage(&buf);
627 
628  /*
629  * Flush message so client will see it, except for AUTH_REQ_OK and
630  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
631  * queries.
632  */
633  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
634  pq_flush();
635 
637 }
#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:246
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_type ClientAuthentication_hook = NULL

Definition at line 241 of file auth.c.

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

bool pg_krb_caseins_users

Definition at line 166 of file auth.c.

char* pg_krb_server_keyfile

Definition at line 165 of file auth.c.