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)
 
typedef char *(* auth_password_hook_typ) (char *input)
 

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
 
PGDLLIMPORT auth_password_hook_typ ldap_password_hook
 

Typedef Documentation

◆ auth_password_hook_typ

typedef char*(* auth_password_hook_typ) (char *input)

Definition at line 32 of file auth.h.

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

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

662 {
664 
666 
667  pq_beginmessage(&buf, 'R');
668  pq_sendint32(&buf, (int32) areq);
669  if (extralen > 0)
670  pq_sendbytes(&buf, extradata, extralen);
671 
672  pq_endmessage(&buf);
673 
674  /*
675  * Flush message so client will see it, except for AUTH_REQ_OK and
676  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
677  * queries.
678  */
679  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
680  pq_flush();
681 
683 }
signed int int32
Definition: c.h:478
#define pq_flush()
Definition: libpq.h:46
static char * buf
Definition: pg_test_fsync.c:67
#define AUTH_REQ_SASL_FIN
Definition: pqcomm.h:131
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:299
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
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 231 of file auth.c.

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

◆ ldap_password_hook

PGDLLIMPORT auth_password_hook_typ ldap_password_hook
extern

Referenced by _PG_init().

◆ pg_krb_caseins_users

PGDLLIMPORT bool pg_krb_caseins_users
extern

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

Referenced by secure_open_gssapi().