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 <arpa/inet.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 "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:89

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

#define PG_MAX_SASL_MESSAGE_LENGTH   1024

Definition at line 223 of file auth.c.

Referenced by CheckSCRAMAuth().

#define RADIUS_ACCESS_ACCEPT   2

Definition at line 2656 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_ACCESS_REJECT   3

Definition at line 2657 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_ACCESS_REQUEST   1

Definition at line 2655 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_AUTHENTICATE_ONLY   8

Definition at line 2666 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_BUFFER_SIZE   1024

Definition at line 2635 of file auth.c.

Referenced by PerformRadiusTransaction(), and radius_add_attribute().

#define RADIUS_HEADER_LENGTH   20

Definition at line 2631 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_MAX_PASSWORD_LENGTH   128

Definition at line 2632 of file auth.c.

Referenced by CheckRADIUSAuth(), and PerformRadiusTransaction().

#define RADIUS_NAS_IDENTIFIER   32

Definition at line 2663 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_PASSWORD   2

Definition at line 2661 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_SERVICE_TYPE   6

Definition at line 2662 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_TIMEOUT   3

Definition at line 2669 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_USER_NAME   1

Definition at line 2660 of file auth.c.

Referenced by PerformRadiusTransaction().

#define RADIUS_VECTOR_LENGTH   16

Definition at line 2630 of file auth.c.

Referenced by PerformRadiusTransaction().

Function Documentation

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

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

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

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

Referenced by CheckPWChallengeAuth().

811 {
812  char md5Salt[4]; /* Password salt */
813  char *passwd;
814  int result;
815 
816  if (Db_user_namespace)
817  ereport(FATAL,
818  (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
819  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
820 
821  /* include the salt to use for computing the response */
822  if (!pg_backend_random(md5Salt, 4))
823  {
824  ereport(LOG,
825  (errmsg("could not generate random MD5 salt")));
826  return STATUS_ERROR;
827  }
828 
829  sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
830 
831  passwd = recv_password_packet(port);
832  if (passwd == NULL)
833  return STATUS_EOF; /* client wouldn't send password */
834 
835  if (shadow_pass)
836  result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
837  md5Salt, 4, logdetail);
838  else
839  result = STATUS_ERROR;
840 
841  pfree(passwd);
842 
843  return result;
844 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define STATUS_ERROR
Definition: c.h:976
return result
Definition: formatting.c:1618
#define LOG
Definition: elog.h:26
#define AUTH_REQ_MD5
Definition: pqcomm.h:170
void pfree(void *pointer)
Definition: mcxt.c:950
#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:609
#define ereport(elevel, rest)
Definition: elog.h:122
static char * recv_password_packet(Port *port)
Definition: auth.c:639
#define NULL
Definition: c.h:229
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:193
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define STATUS_EOF
Definition: c.h:977
static int CheckPasswordAuth ( Port port,
char **  logdetail 
)
static

Definition at line 712 of file auth.c.

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

Referenced by ClientAuthentication().

713 {
714  char *passwd;
715  int result;
716  char *shadow_pass;
717 
719 
720  passwd = recv_password_packet(port);
721  if (passwd == NULL)
722  return STATUS_EOF; /* client wouldn't send password */
723 
724  shadow_pass = get_role_password(port->user_name, logdetail);
725  if (shadow_pass)
726  {
727  result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
728  logdetail);
729  }
730  else
731  result = STATUS_ERROR;
732 
733  if (shadow_pass)
734  pfree(shadow_pass);
735  pfree(passwd);
736 
737  return result;
738 }
#define STATUS_ERROR
Definition: c.h:976
return result
Definition: formatting.c:1618
void pfree(void *pointer)
Definition: mcxt.c:950
char * user_name
Definition: libpq-be.h:137
static void sendAuthRequest(Port *port, AuthRequest areq, char *extradata, int extralen)
Definition: auth.c:609
static char * recv_password_packet(Port *port)
Definition: auth.c:639
#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:270
#define NULL
Definition: c.h:229
char * get_role_password(const char *role, char **logdetail)
Definition: crypt.c:39
#define STATUS_EOF
Definition: c.h:977
static int CheckPWChallengeAuth ( Port port,
char **  logdetail 
)
static

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

745 {
746  int auth_result;
747  char *shadow_pass;
748  PasswordType pwtype;
749 
750  Assert(port->hba->auth_method == uaSCRAM ||
751  port->hba->auth_method == uaMD5);
752 
753  /* First look up the user's password. */
754  shadow_pass = get_role_password(port->user_name, logdetail);
755 
756  /*
757  * If the user does not exist, or has no password, we still go through the
758  * motions of authentication, to avoid revealing to the client that the
759  * user didn't exist. If 'md5' is allowed, we choose whether to use 'md5'
760  * or 'scram-sha-256' authentication based on current password_encryption
761  * setting. The idea is that most genuine users probably have a password
762  * of that type, if we pretend that this user had a password of that type,
763  * too, it "blends in" best.
764  *
765  * If the user had a password, but it was expired, we'll use the details
766  * of the expired password for the authentication, but report it as
767  * failure to the client even if correct password was given.
768  */
769  if (!shadow_pass)
770  pwtype = Password_encryption;
771  else
772  pwtype = get_password_type(shadow_pass);
773 
774  /*
775  * If 'md5' authentication is allowed, decide whether to perform 'md5' or
776  * 'scram-sha-256' authentication based on the type of password the user
777  * has. If it's an MD5 hash, we must do MD5 authentication, and if it's
778  * a SCRAM verifier, we must do SCRAM authentication. If it's stored in
779  * plaintext, we could do either one, so we opt for the more secure
780  * mechanism, SCRAM.
781  *
782  * If MD5 authentication is not allowed, always use SCRAM. If the user
783  * had an MD5 password, CheckSCRAMAuth() will fail.
784  */
785  if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
786  {
787  auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
788  }
789  else
790  {
791  auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
792  }
793 
794  if (shadow_pass)
795  pfree(shadow_pass);
796 
797  /*
798  * If get_role_password() returned error, return error, even if the
799  * authentication succeeded.
800  */
801  if (!shadow_pass)
802  {
803  Assert(auth_result != STATUS_OK);
804  return STATUS_ERROR;
805  }
806  return auth_result;
807 }
Definition: hba.h:32
int Password_encryption
Definition: user.c:47
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:99
#define STATUS_ERROR
Definition: c.h:976
void pfree(void *pointer)
Definition: mcxt.c:950
static int CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:847
char * user_name
Definition: libpq-be.h:137
#define STATUS_OK
Definition: c.h:975
HbaLine * hba
Definition: libpq-be.h:144
static int CheckMD5Auth(Port *port, char *shadow_pass, char **logdetail)
Definition: auth.c:810
Definition: hba.h:33
PasswordType
Definition: crypt.h:24
#define Assert(condition)
Definition: c.h:675
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 2698 of file auth.c.

References Assert, AUTH_REQ_PASSWORD, ereport, errmsg(), Port::hba, lfirst, list_head(), list_length(), lnext, LOG, NULL, offsetof, PerformRadiusTransaction(), 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().

2699 {
2700  char *passwd;
2701  ListCell *server,
2702  *secrets,
2703  *radiusports,
2704  *identifiers;
2705 
2706  /* Make sure struct alignment is correct */
2707  Assert(offsetof(radius_packet, vector) == 4);
2708 
2709  /* Verify parameters */
2710  if (list_length(port->hba->radiusservers) < 1)
2711  {
2712  ereport(LOG,
2713  (errmsg("RADIUS server not specified")));
2714  return STATUS_ERROR;
2715  }
2716 
2717  if (list_length(port->hba->radiussecrets) < 1)
2718  {
2719  ereport(LOG,
2720  (errmsg("RADIUS secret not specified")));
2721  return STATUS_ERROR;
2722  }
2723 
2724  /* Send regular password request to client, and get the response */
2726 
2727  passwd = recv_password_packet(port);
2728  if (passwd == NULL)
2729  return STATUS_EOF; /* client wouldn't send password */
2730 
2731  if (strlen(passwd) == 0)
2732  {
2733  ereport(LOG,
2734  (errmsg("empty password returned by client")));
2735  return STATUS_ERROR;
2736  }
2737 
2738  if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2739  {
2740  ereport(LOG,
2741  (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2742  return STATUS_ERROR;
2743  }
2744 
2745  /*
2746  * Loop over and try each server in order.
2747  */
2748  secrets = list_head(port->hba->radiussecrets);
2749  radiusports = list_head(port->hba->radiusports);
2750  identifiers = list_head(port->hba->radiusidentifiers);
2751  foreach(server, port->hba->radiusservers)
2752  {
2753  int ret = PerformRadiusTransaction(lfirst(server),
2754  lfirst(secrets),
2755  radiusports ? lfirst(radiusports) : NULL,
2756  identifiers ? lfirst(identifiers) : NULL,
2757  port->user_name,
2758  passwd);
2759 
2760  /*------
2761  * STATUS_OK = Login OK
2762  * STATUS_ERROR = Login not OK, but try next server
2763  * STATUS_EOF = Login not OK, and don't try next server
2764  *------
2765  */
2766  if (ret == STATUS_OK)
2767  return STATUS_OK;
2768  else if (ret == STATUS_EOF)
2769  return STATUS_ERROR;
2770 
2771  /*
2772  * secret, port and identifiers either have length 0 (use default),
2773  * length 1 (use the same everywhere) or the same length as servers.
2774  * So if the length is >1, we advance one step. In other cases, we
2775  * don't and will then reuse the correct value.
2776  */
2777  if (list_length(port->hba->radiussecrets) > 1)
2778  secrets = lnext(secrets);
2779  if (list_length(port->hba->radiusports) > 1)
2780  radiusports = lnext(radiusports);
2781  if (list_length(port->hba->radiusidentifiers) > 1)
2782  identifiers = lnext(identifiers);
2783  }
2784 
2785  /* No servers left to try, so give up */
2786  return STATUS_ERROR;
2787 }
#define STATUS_ERROR
Definition: c.h:976
#define LOG
Definition: elog.h:26
List * radiussecrets
Definition: hba.h:94
List * radiusports
Definition: hba.h:98
List * radiusservers
Definition: hba.h:92
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:609
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
#define STATUS_OK
Definition: c.h:975
static char * recv_password_packet(Port *port)
Definition: auth.c:639
#define AUTH_REQ_PASSWORD
Definition: pqcomm.h:168
HbaLine * hba
Definition: libpq-be.h:144
List * radiusidentifiers
Definition: hba.h:96
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#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:2790
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2632
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:977
#define offsetof(type, field)
Definition: c.h:555
static int CheckSCRAMAuth ( Port port,
char *  shadow_pass,
char **  logdetail 
)
static

Definition at line 847 of file auth.c.

References Assert, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, buf, COMMERROR, StringInfoData::data, DEBUG4, elog, ereport, errcode(), errmsg(), FATAL, FrontendProtocol, initStringInfo(), StringInfoData::len, NULL, 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(), result, SASL_EXCHANGE_CONTINUE, SASL_EXCHANGE_SUCCESS, SCRAM_SHA256_NAME, sendAuthRequest(), STATUS_EOF, STATUS_ERROR, STATUS_OK, and Port::user_name.

Referenced by CheckPWChallengeAuth().

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

Definition at line 339 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, NULL, 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().

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

1812 {
1813  const SockAddr remote_addr = port->raddr;
1814  const SockAddr local_addr = port->laddr;
1815  char ident_user[IDENT_USERNAME_MAX + 1];
1816  pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1817  int rc; /* Return code from a locally called function */
1818  bool ident_return;
1819  char remote_addr_s[NI_MAXHOST];
1820  char remote_port[NI_MAXSERV];
1821  char local_addr_s[NI_MAXHOST];
1822  char local_port[NI_MAXSERV];
1823  char ident_port[NI_MAXSERV];
1824  char ident_query[80];
1825  char ident_response[80 + IDENT_USERNAME_MAX];
1826  struct addrinfo *ident_serv = NULL,
1827  *la = NULL,
1828  hints;
1829 
1830  /*
1831  * Might look a little weird to first convert it to text and then back to
1832  * sockaddr, but it's protocol independent.
1833  */
1834  pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1835  remote_addr_s, sizeof(remote_addr_s),
1836  remote_port, sizeof(remote_port),
1838  pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1839  local_addr_s, sizeof(local_addr_s),
1840  local_port, sizeof(local_port),
1842 
1843  snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1844  hints.ai_flags = AI_NUMERICHOST;
1845  hints.ai_family = remote_addr.addr.ss_family;
1846  hints.ai_socktype = SOCK_STREAM;
1847  hints.ai_protocol = 0;
1848  hints.ai_addrlen = 0;
1849  hints.ai_canonname = NULL;
1850  hints.ai_addr = NULL;
1851  hints.ai_next = NULL;
1852  rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1853  if (rc || !ident_serv)
1854  {
1855  /* we don't expect this to happen */
1856  ident_return = false;
1857  goto ident_inet_done;
1858  }
1859 
1860  hints.ai_flags = AI_NUMERICHOST;
1861  hints.ai_family = local_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(local_addr_s, NULL, &hints, &la);
1869  if (rc || !la)
1870  {
1871  /* we don't expect this to happen */
1872  ident_return = false;
1873  goto ident_inet_done;
1874  }
1875 
1876  sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1877  ident_serv->ai_protocol);
1878  if (sock_fd == PGINVALID_SOCKET)
1879  {
1880  ereport(LOG,
1882  errmsg("could not create socket for Ident connection: %m")));
1883  ident_return = false;
1884  goto ident_inet_done;
1885  }
1886 
1887  /*
1888  * Bind to the address which the client originally contacted, otherwise
1889  * the ident server won't be able to match up the right connection. This
1890  * is necessary if the PostgreSQL server is running on an IP alias.
1891  */
1892  rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1893  if (rc != 0)
1894  {
1895  ereport(LOG,
1897  errmsg("could not bind to local address \"%s\": %m",
1898  local_addr_s)));
1899  ident_return = false;
1900  goto ident_inet_done;
1901  }
1902 
1903  rc = connect(sock_fd, ident_serv->ai_addr,
1904  ident_serv->ai_addrlen);
1905  if (rc != 0)
1906  {
1907  ereport(LOG,
1909  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1910  remote_addr_s, ident_port)));
1911  ident_return = false;
1912  goto ident_inet_done;
1913  }
1914 
1915  /* The query we send to the Ident server */
1916  snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1917  remote_port, local_port);
1918 
1919  /* loop in case send is interrupted */
1920  do
1921  {
1923 
1924  rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1925  } while (rc < 0 && errno == EINTR);
1926 
1927  if (rc < 0)
1928  {
1929  ereport(LOG,
1931  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1932  remote_addr_s, ident_port)));
1933  ident_return = false;
1934  goto ident_inet_done;
1935  }
1936 
1937  do
1938  {
1940 
1941  rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1942  } while (rc < 0 && errno == EINTR);
1943 
1944  if (rc < 0)
1945  {
1946  ereport(LOG,
1948  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1949  remote_addr_s, ident_port)));
1950  ident_return = false;
1951  goto ident_inet_done;
1952  }
1953 
1954  ident_response[rc] = '\0';
1955  ident_return = interpret_ident_response(ident_response, ident_user);
1956  if (!ident_return)
1957  ereport(LOG,
1958  (errmsg("invalidly formatted response from Ident server: \"%s\"",
1959  ident_response)));
1960 
1961 ident_inet_done:
1962  if (sock_fd != PGINVALID_SOCKET)
1963  closesocket(sock_fd);
1964  if (ident_serv)
1965  pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1966  if (la)
1967  pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1968 
1969  if (ident_return)
1970  /* Success! Check the usermap */
1971  return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1972  return STATUS_ERROR;
1973 }
#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:328
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define socket(af, type, protocol)
Definition: win32.h:369
#define STATUS_ERROR
Definition: c.h:976
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:2818
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
int ai_protocol
Definition: getaddrinfo.h:103
#define NULL
Definition: c.h:229
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:97
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1723
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 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:68
Definition: type.h:125
int i
static int PerformRadiusTransaction ( char *  server,
char *  secret,
char *  portstr,
char *  identifier,
char *  user_name,
char *  passwd 
)
static

Definition at line 2790 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, NULL, palloc(), pfree(), pg_backend_random(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_md5_binary(), 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().

2791 {
2792  radius_packet radius_send_pack;
2793  radius_packet radius_recv_pack;
2794  radius_packet *packet = &radius_send_pack;
2795  radius_packet *receivepacket = &radius_recv_pack;
2796  char *radius_buffer = (char *) &radius_send_pack;
2797  char *receive_buffer = (char *) &radius_recv_pack;
2798  int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
2799  uint8 *cryptvector;
2800  int encryptedpasswordlen;
2801  uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
2802  uint8 *md5trailer;
2803  int packetlength;
2804  pgsocket sock;
2805 
2806 #ifdef HAVE_IPV6
2807  struct sockaddr_in6 localaddr;
2808  struct sockaddr_in6 remoteaddr;
2809 #else
2810  struct sockaddr_in localaddr;
2811  struct sockaddr_in remoteaddr;
2812 #endif
2813  struct addrinfo hint;
2814  struct addrinfo *serveraddrs;
2815  int port;
2816  ACCEPT_TYPE_ARG3 addrsize;
2817  fd_set fdset;
2818  struct timeval endtime;
2819  int i,
2820  j,
2821  r;
2822 
2823  /* Assign default values */
2824  if (portstr == NULL)
2825  portstr = "1812";
2826  if (identifier == NULL)
2827  identifier = "postgresql";
2828 
2829  MemSet(&hint, 0, sizeof(hint));
2830  hint.ai_socktype = SOCK_DGRAM;
2831  hint.ai_family = AF_UNSPEC;
2832  port = atoi(portstr);
2833 
2834  r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
2835  if (r || !serveraddrs)
2836  {
2837  ereport(LOG,
2838  (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2839  server, gai_strerror(r))));
2840  if (serveraddrs)
2841  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2842  return STATUS_ERROR;
2843  }
2844  /* XXX: add support for multiple returned addresses? */
2845 
2846  /* Construct RADIUS packet */
2847  packet->code = RADIUS_ACCESS_REQUEST;
2848  packet->length = RADIUS_HEADER_LENGTH;
2849  if (!pg_backend_random((char *) packet->vector, RADIUS_VECTOR_LENGTH))
2850  {
2851  ereport(LOG,
2852  (errmsg("could not generate random encryption vector")));
2853  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2854  return STATUS_ERROR;
2855  }
2856  packet->id = packet->vector[0];
2857  radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (unsigned char *) &service, sizeof(service));
2858  radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) user_name, strlen(user_name));
2859  radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
2860 
2861  /*
2862  * RADIUS password attributes are calculated as: e[0] = p[0] XOR
2863  * MD5(secret + Request Authenticator) for the first group of 16 octets,
2864  * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
2865  * (if necessary)
2866  */
2867  encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
2868  cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
2869  memcpy(cryptvector, secret, strlen(secret));
2870 
2871  /* for the first iteration, we use the Request Authenticator vector */
2872  md5trailer = packet->vector;
2873  for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
2874  {
2875  memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
2876 
2877  /*
2878  * .. and for subsequent iterations the result of the previous XOR
2879  * (calculated below)
2880  */
2881  md5trailer = encryptedpassword + i;
2882 
2883  if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH, encryptedpassword + i))
2884  {
2885  ereport(LOG,
2886  (errmsg("could not perform MD5 encryption of password")));
2887  pfree(cryptvector);
2888  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2889  return STATUS_ERROR;
2890  }
2891 
2892  for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
2893  {
2894  if (j < strlen(passwd))
2895  encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
2896  else
2897  encryptedpassword[j] = '\0' ^ encryptedpassword[j];
2898  }
2899  }
2900  pfree(cryptvector);
2901 
2902  radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
2903 
2904  /* Length needs to be in network order on the wire */
2905  packetlength = packet->length;
2906  packet->length = htons(packet->length);
2907 
2908  sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
2909  if (sock == PGINVALID_SOCKET)
2910  {
2911  ereport(LOG,
2912  (errmsg("could not create RADIUS socket: %m")));
2913  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2914  return STATUS_ERROR;
2915  }
2916 
2917  memset(&localaddr, 0, sizeof(localaddr));
2918 #ifdef HAVE_IPV6
2919  localaddr.sin6_family = serveraddrs[0].ai_family;
2920  localaddr.sin6_addr = in6addr_any;
2921  if (localaddr.sin6_family == AF_INET6)
2922  addrsize = sizeof(struct sockaddr_in6);
2923  else
2924  addrsize = sizeof(struct sockaddr_in);
2925 #else
2926  localaddr.sin_family = serveraddrs[0].ai_family;
2927  localaddr.sin_addr.s_addr = INADDR_ANY;
2928  addrsize = sizeof(struct sockaddr_in);
2929 #endif
2930 
2931  if (bind(sock, (struct sockaddr *) & localaddr, addrsize))
2932  {
2933  ereport(LOG,
2934  (errmsg("could not bind local RADIUS socket: %m")));
2935  closesocket(sock);
2936  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2937  return STATUS_ERROR;
2938  }
2939 
2940  if (sendto(sock, radius_buffer, packetlength, 0,
2941  serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
2942  {
2943  ereport(LOG,
2944  (errmsg("could not send RADIUS packet: %m")));
2945  closesocket(sock);
2946  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2947  return STATUS_ERROR;
2948  }
2949 
2950  /* Don't need the server address anymore */
2951  pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2952 
2953  /*
2954  * Figure out at what time we should time out. We can't just use a single
2955  * call to select() with a timeout, since somebody can be sending invalid
2956  * packets to our port thus causing us to retry in a loop and never time
2957  * out.
2958  *
2959  * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
2960  * the latch was set would improve the responsiveness to
2961  * timeouts/cancellations.
2962  */
2963  gettimeofday(&endtime, NULL);
2964  endtime.tv_sec += RADIUS_TIMEOUT;
2965 
2966  while (true)
2967  {
2968  struct timeval timeout;
2969  struct timeval now;
2970  int64 timeoutval;
2971 
2972  gettimeofday(&now, NULL);
2973  timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
2974  if (timeoutval <= 0)
2975  {
2976  ereport(LOG,
2977  (errmsg("timeout waiting for RADIUS response from %s",
2978  server)));
2979  closesocket(sock);
2980  return STATUS_ERROR;
2981  }
2982  timeout.tv_sec = timeoutval / 1000000;
2983  timeout.tv_usec = timeoutval % 1000000;
2984 
2985  FD_ZERO(&fdset);
2986  FD_SET(sock, &fdset);
2987 
2988  r = select(sock + 1, &fdset, NULL, NULL, &timeout);
2989  if (r < 0)
2990  {
2991  if (errno == EINTR)
2992  continue;
2993 
2994  /* Anything else is an actual error */
2995  ereport(LOG,
2996  (errmsg("could not check status on RADIUS socket: %m")));
2997  closesocket(sock);
2998  return STATUS_ERROR;
2999  }
3000  if (r == 0)
3001  {
3002  ereport(LOG,
3003  (errmsg("timeout waiting for RADIUS response from %s",
3004  server)));
3005  closesocket(sock);
3006  return STATUS_ERROR;
3007  }
3008 
3009  /*
3010  * Attempt to read the response packet, and verify the contents.
3011  *
3012  * Any packet that's not actually a RADIUS packet, or otherwise does
3013  * not validate as an explicit reject, is just ignored and we retry
3014  * for another packet (until we reach the timeout). This is to avoid
3015  * the possibility to denial-of-service the login by flooding the
3016  * server with invalid packets on the port that we're expecting the
3017  * RADIUS response on.
3018  */
3019 
3020  addrsize = sizeof(remoteaddr);
3021  packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3022  (struct sockaddr *) & remoteaddr, &addrsize);
3023  if (packetlength < 0)
3024  {
3025  ereport(LOG,
3026  (errmsg("could not read RADIUS response: %m")));
3027  closesocket(sock);
3028  return STATUS_ERROR;
3029  }
3030 
3031 #ifdef HAVE_IPV6
3032  if (remoteaddr.sin6_port != htons(port))
3033 #else
3034  if (remoteaddr.sin_port != htons(port))
3035 #endif
3036  {
3037 #ifdef HAVE_IPV6
3038  ereport(LOG,
3039  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3040  server, ntohs(remoteaddr.sin6_port))));
3041 #else
3042  ereport(LOG,
3043  (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3044  server, ntohs(remoteaddr.sin_port))));
3045 #endif
3046  continue;
3047  }
3048 
3049  if (packetlength < RADIUS_HEADER_LENGTH)
3050  {
3051  ereport(LOG,
3052  (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3053  continue;
3054  }
3055 
3056  if (packetlength != ntohs(receivepacket->length))
3057  {
3058  ereport(LOG,
3059  (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3060  server, ntohs(receivepacket->length), packetlength)));
3061  continue;
3062  }
3063 
3064  if (packet->id != receivepacket->id)
3065  {
3066  ereport(LOG,
3067  (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3068  server, receivepacket->id, packet->id)));
3069  continue;
3070  }
3071 
3072  /*
3073  * Verify the response authenticator, which is calculated as
3074  * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3075  */
3076  cryptvector = palloc(packetlength + strlen(secret));
3077 
3078  memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3079  memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3080  * authenticator, from
3081  * original packet */
3082  if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3083  * attributes at all */
3084  memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
3085  memcpy(cryptvector + packetlength, secret, strlen(secret));
3086 
3087  if (!pg_md5_binary(cryptvector,
3088  packetlength + strlen(secret),
3089  encryptedpassword))
3090  {
3091  ereport(LOG,
3092  (errmsg("could not perform MD5 encryption of received packet")));
3093  pfree(cryptvector);
3094  continue;
3095  }
3096  pfree(cryptvector);
3097 
3098  if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3099  {
3100  ereport(LOG,
3101  (errmsg("RADIUS response from %s has incorrect MD5 signature",
3102  server)));
3103  continue;
3104  }
3105 
3106  if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3107  {
3108  closesocket(sock);
3109  return STATUS_OK;
3110  }
3111  else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3112  {
3113  closesocket(sock);
3114  return STATUS_EOF;
3115  }
3116  else
3117  {
3118  ereport(LOG,
3119  (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3120  server, receivepacket->code, user_name)));
3121  continue;
3122  }
3123  } /* while (true) */
3124 }
#define RADIUS_PASSWORD
Definition: auth.c:2661
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:328
uint16 length
Definition: auth.c:2648
unsigned char uint8
Definition: c.h:266
#define RADIUS_VECTOR_LENGTH
Definition: auth.c:2630
#define socket(af, type, protocol)
Definition: win32.h:369
#define STATUS_ERROR
Definition: c.h:976
#define MemSet(start, val, len)
Definition: c.h:857
#define select(n, r, w, e, timeout)
Definition: win32.h:374
#define LOG
Definition: elog.h:26
#define RADIUS_NAS_IDENTIFIER
Definition: auth.c:2663
#define RADIUS_TIMEOUT
Definition: auth.c:2669
#define gai_strerror
Definition: getaddrinfo.h:146
signed int int32
Definition: c.h:256
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2631
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:950
#define bind(s, addr, addrlen)
Definition: win32.h:370
#define RADIUS_USER_NAME
Definition: auth.c:2660
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:975
static int port
Definition: pg_regress.c:89
#define RADIUS_ACCESS_ACCEPT
Definition: auth.c:2656
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2635
#define PGINVALID_SOCKET
Definition: port.h:24
#define EINTR
Definition: win32.h:285
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:2666
#define NULL
Definition: c.h:229
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:2655
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2632
#define RADIUS_SERVICE_TYPE
Definition: auth.c:2662
uint8 id
Definition: auth.c:2647
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
uint8 code
Definition: auth.c:2646
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:2649
bool pg_md5_binary(const void *buff, size_t len, void *outbuf)
Definition: md5.c:305
#define STATUS_EOF
Definition: c.h:977
static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
Definition: auth.c:2672
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
#define RADIUS_ACCESS_REJECT
Definition: auth.c:2657
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 2672 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().

2673 {
2674  radius_attribute *attr;
2675 
2676  if (packet->length + len > RADIUS_BUFFER_SIZE)
2677  {
2678  /*
2679  * With remotely realistic data, this can never happen. But catch it
2680  * just to make sure we don't overrun a buffer. We'll just skip adding
2681  * the broken attribute, which will in the end cause authentication to
2682  * fail.
2683  */
2684  elog(WARNING,
2685  "Adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2686  type, len);
2687  return;
2688  }
2689 
2690  attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2691  attr->attribute = type;
2692  attr->length = len + 2; /* total size includes type and length */
2693  memcpy(attr->data, data, len);
2694  packet->length += attr->length;
2695 }
uint16 length
Definition: auth.c:2648
uint8 attribute
Definition: auth.c:2639
#define WARNING
Definition: elog.h:40
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2635
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2641
#define elog
Definition: elog.h:219
uint8 length
Definition: auth.c:2640
static char * recv_password_packet ( Port port)
static

Definition at line 639 of file auth.c.

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

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

640 {
642 
643  pq_startmsgread();
644  if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
645  {
646  /* Expect 'p' message type */
647  int mtype;
648 
649  mtype = pq_getbyte();
650  if (mtype != 'p')
651  {
652  /*
653  * If the client just disconnects without offering a password,
654  * don't make a log entry. This is legal per protocol spec and in
655  * fact commonly done by psql, so complaining just clutters the
656  * log.
657  */
658  if (mtype != EOF)
660  (errcode(ERRCODE_PROTOCOL_VIOLATION),
661  errmsg("expected password response, got message type %d",
662  mtype)));
663  return NULL; /* EOF or bad message type */
664  }
665  }
666  else
667  {
668  /* For pre-3.0 clients, avoid log entry if they just disconnect */
669  if (pq_peekbyte() == EOF)
670  return NULL; /* EOF */
671  }
672 
673  initStringInfo(&buf);
674  if (pq_getmessage(&buf, 1000)) /* receive password */
675  {
676  /* EOF - pq_getmessage already logged a suitable message */
677  pfree(buf.data);
678  return NULL;
679  }
680 
681  /*
682  * Apply sanity check: password packet length should agree with length of
683  * contained string. Note it is safe to use strlen here because
684  * StringInfo is guaranteed to have an appended '\0'.
685  */
686  if (strlen(buf.data) + 1 != buf.len)
688  (errcode(ERRCODE_PROTOCOL_VIOLATION),
689  errmsg("invalid password packet size")));
690 
691  /* Do not echo password to logs, for security. */
692  elog(DEBUG5, "received password packet");
693 
694  /*
695  * Return the received string. Note we do not attempt to do any
696  * character-set conversion on it; since we don't yet know the client's
697  * encoding, there wouldn't be much point.
698  */
699  return buf.data;
700 }
int pq_peekbyte(void)
Definition: pqcomm.c:1000
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:104
void pfree(void *pointer)
Definition: mcxt.c:950
void pq_startmsgread(void)
Definition: pqcomm.c:1191
static char * buf
Definition: pg_test_fsync.c:66
#define COMMERROR
Definition: elog.h:30
#define ereport(elevel, rest)
Definition: elog.h:122
void initStringInfo(StringInfo str)
Definition: stringinfo.c:65
int pq_getmessage(StringInfo s, int maxlen)
Definition: pqcomm.c:1253
int pq_getbyte(void)
Definition: pqcomm.c:981
#define NULL
Definition: c.h:229
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
static void sendAuthRequest ( Port port,
AuthRequest  areq,
char *  extradata,
int  extralen 
)
static

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

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

610 {
612 
614 
615  pq_beginmessage(&buf, 'R');
616  pq_sendint(&buf, (int32) areq, sizeof(int32));
617  if (extralen > 0)
618  pq_sendbytes(&buf, extradata, extralen);
619 
620  pq_endmessage(&buf);
621 
622  /*
623  * Flush message so client will see it, except for AUTH_REQ_OK and
624  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
625  * queries.
626  */
627  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
628  pq_flush();
629 
631 }
#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:88
signed int int32
Definition: c.h:256
static char * buf
Definition: pg_test_fsync.c:66
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:115
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:344
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97

Variable Documentation

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 235 of file auth.c.

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

bool pg_krb_caseins_users

Definition at line 160 of file auth.c.

char* pg_krb_server_keyfile

Definition at line 159 of file auth.c.