PostgreSQL Source Code  git master
auth.h File Reference
#include "libpq/libpq-be.h"
Include dependency graph for auth.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* ClientAuthentication_hook_type) (Port *, int)
 

Functions

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

Variables

PGDLLIMPORT char * pg_krb_server_keyfile
 
PGDLLIMPORT bool pg_krb_caseins_users
 
PGDLLIMPORT char * pg_krb_realm
 
PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hook
 

Typedef Documentation

◆ ClientAuthentication_hook_type

typedef void(* ClientAuthentication_hook_type) (Port *, int)

Definition at line 28 of file auth.h.

Function Documentation

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 379 of file auth.c.

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

References _, am_db_walsender, am_walsender, Assert(), auth_failed(), auth_peer(), AUTH_REQ_GSS, AUTH_REQ_OK, AUTH_REQ_SSPI, CHECK_FOR_INTERRUPTS, CheckPasswordAuth(), CheckPWChallengeAuth(), CheckRADIUSAuth(), ClientAuthentication_hook, clientCertFull, clientCertOff, ereport, errcode(), errmsg(), FATAL, hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), MemoryContextAllocZero(), pg_getnameinfo_all(), port, secure_loaded_verify_locations(), sendAuthRequest(), status(), STATUS_ERROR, STATUS_OK, TopMemoryContext, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaPAM, uaPassword, uaRADIUS, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by PerformAuthentication().

◆ sendAuthRequest()

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

Definition at line 657 of file auth.c.

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

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

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

Variable Documentation

◆ ClientAuthentication_hook

PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hook
extern

Definition at line 227 of file auth.c.

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

◆ pg_krb_caseins_users

PGDLLIMPORT bool pg_krb_caseins_users
extern

Definition at line 163 of file auth.c.

◆ pg_krb_realm

PGDLLIMPORT char* pg_krb_realm
extern

◆ pg_krb_server_keyfile

PGDLLIMPORT char* pg_krb_server_keyfile
extern

Definition at line 162 of file auth.c.

Referenced by secure_open_gssapi().