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

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

Referenced by PerformAuthentication().

◆ sendAuthRequest()

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

Definition at line 678 of file auth.c.

679 {
681 
683 
685  pq_sendint32(&buf, (int32) areq);
686  if (extralen > 0)
687  pq_sendbytes(&buf, extradata, extralen);
688 
689  pq_endmessage(&buf);
690 
691  /*
692  * Flush message so client will see it, except for AUTH_REQ_OK and
693  * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
694  * queries.
695  */
696  if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
697  pq_flush();
698 
700 }
signed int int32
Definition: c.h:483
#define pq_flush()
Definition: libpq.h:46
static char * buf
Definition: pg_test_fsync.c:67
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
#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 232 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 168 of file auth.c.

Referenced by secure_open_gssapi().

◆ pg_krb_caseins_users

PGDLLIMPORT bool pg_krb_caseins_users
extern

Definition at line 167 of file auth.c.

◆ pg_krb_server_keyfile

PGDLLIMPORT char* pg_krb_server_keyfile
extern

Definition at line 166 of file auth.c.

Referenced by secure_open_gssapi().