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 bool pg_gss_accept_delegation
 
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 382 of file auth.c.

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

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

Referenced by PerformAuthentication().

◆ sendAuthRequest()

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

Definition at line 676 of file auth.c.

677 {
679 
681 
683  pq_sendint32(&buf, (int32) areq);
684  if (extralen > 0)
685  pq_sendbytes(&buf, extradata, extralen);
686 
687  pq_endmessage(&buf);
688 
689  /*
690  * Flush message so client will see it, except for AUTH_REQ_OK and
691  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
692  * queries.
693  */
694  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
695  pq_flush();
696 
698 }
signed int int32
Definition: c.h:481
#define pq_flush()
Definition: libpq.h:46
static char * buf
Definition: pg_test_fsync.c:73
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:82

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

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

Variable Documentation

◆ ClientAuthentication_hook

PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hook
extern

Definition at line 230 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_gss_accept_delegation

PGDLLIMPORT bool pg_gss_accept_delegation
extern

Definition at line 166 of file auth.c.

Referenced by secure_open_gssapi().

◆ pg_krb_caseins_users

PGDLLIMPORT bool pg_krb_caseins_users
extern

Definition at line 165 of file auth.c.

◆ pg_krb_server_keyfile

PGDLLIMPORT char* pg_krb_server_keyfile
extern

Definition at line 164 of file auth.c.

Referenced by secure_open_gssapi().