PostgreSQL Source Code git master
Loading...
Searching...
No Matches
auth.c File Reference
#include "postgres.h"
#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.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/oauth.h"
#include "libpq/pqformat.h"
#include "libpq/sasl.h"
#include "libpq/scram.h"
#include "miscadmin.h"
#include "port/pg_bswap.h"
#include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
#include "tcop/backend_startup.h"
#include "utils/memutils.h"
Include dependency graph for auth.c:

Go to the source code of this file.

Macros

#define IDENT_USERNAME_MAX   512
 
#define IDENT_PORT   113
 
#define HOSTNAME_LOOKUP_DETAIL(port)
 

Functions

static void auth_failed (Port *port, int elevel, int status, const char *logdetail)
 
static charrecv_password_packet (Port *port)
 
static bool md5_password_warning_enabled (void)
 
static void queue_md5_password_warning (void)
 
static int CheckPasswordAuth (Port *port, const char **logdetail)
 
static int CheckPWChallengeAuth (Port *port, const char **logdetail)
 
static int CheckMD5Auth (Port *port, char *shadow_pass, const char **logdetail)
 
static int ident_inet (Port *port)
 
static int auth_peer (Port *port)
 
void set_authn_id (Port *port, const char *id)
 
void ClientAuthentication (Port *port)
 
void sendAuthRequest (Port *port, AuthRequest areq, const void *extradata, int extralen)
 
static bool is_ident_whitespace (const char c)
 
static bool interpret_ident_response (const char *ident_response, char *ident_user)
 

Variables

charpg_krb_server_keyfile
 
bool pg_krb_caseins_users
 
bool pg_gss_accept_delegation
 
ClientAuthentication_hook_type ClientAuthentication_hook = NULL
 

Macro Definition Documentation

◆ HOSTNAME_LOOKUP_DETAIL

#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))
int int int errdetail_log(const char *fmt,...) pg_attribute_printf(1
static int port
Definition pg_regress.c:117
static int fb(int x)
const char * gai_strerror(int errcode)

◆ IDENT_PORT

#define IDENT_PORT   113

Definition at line 74 of file auth.c.

◆ IDENT_USERNAME_MAX

#define IDENT_USERNAME_MAX   512

Definition at line 71 of file auth.c.

Function Documentation

◆ auth_failed()

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

Definition at line 236 of file auth.c.

237{
238 const char *errstr;
239 char *cdetail;
241
242 Assert(elevel >= FATAL); /* we must exit here */
243
244 /*
245 * If we failed due to EOF from client, just quit; there's no point in
246 * trying to send a message to the client, and not much point in logging
247 * the failure in the postmaster log. (Logging the failure might be
248 * desirable, were it not for the fact that libpq closes the connection
249 * unceremoniously if challenged for a password when it hasn't got one to
250 * send. We'll get a useless log entry for every psql connection under
251 * password auth, even if it's perfectly successful, if we log STATUS_EOF
252 * events.)
253 */
254 if (status == STATUS_EOF)
255 proc_exit(0);
256
257 switch (port->hba->auth_method)
258 {
259 case uaReject:
260 case uaImplicitReject:
261 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
262 break;
263 case uaTrust:
264 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
265 break;
266 case uaIdent:
267 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
268 break;
269 case uaPeer:
270 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
271 break;
272 case uaPassword:
273 case uaMD5:
274 case uaSCRAM:
275 errstr = gettext_noop("password authentication failed for user \"%s\"");
276 /* We use it to indicate if a .pgpass password failed. */
278 break;
279 case uaGSS:
280 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
281 break;
282 case uaSSPI:
283 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
284 break;
285 case uaPAM:
286 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
287 break;
288 case uaBSD:
289 errstr = gettext_noop("BSD authentication failed for user \"%s\"");
290 break;
291 case uaLDAP:
292 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
293 break;
294 case uaCert:
295 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
296 break;
297 case uaOAuth:
298 errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\"");
299 break;
300 default:
301 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
302 break;
303 }
304
305 cdetail = psprintf(_("Connection matched file \"%s\" line %d: \"%s\""),
306 port->hba->sourcefile, port->hba->linenumber,
307 port->hba->rawline);
308 if (logdetail)
309 logdetail = psprintf("%s\n%s", logdetail, cdetail);
310 else
311 logdetail = cdetail;
312
313 ereport(elevel,
315 errmsg(errstr, port->user_name),
316 logdetail ? errdetail_log("%s", logdetail) : 0));
317
318 /* doesn't return */
320}
#define gettext_noop(x)
Definition c.h:1344
#define Assert(condition)
Definition c.h:1002
#define STATUS_EOF
Definition c.h:1319
#define pg_unreachable()
Definition c.h:426
int errcode(int sqlerrcode)
Definition elog.c:875
#define _(x)
Definition elog.c:96
#define FATAL
Definition elog.h:42
#define ereport(elevel,...)
Definition elog.h:152
#define ERRCODE_INVALID_PASSWORD
Definition fe-connect.c:93
@ uaBSD
Definition hba.h:37
@ uaLDAP
Definition hba.h:38
@ uaPeer
Definition hba.h:40
@ 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
@ uaIdent
Definition hba.h:30
@ uaOAuth
Definition hba.h:41
@ uaTrust
Definition hba.h:29
@ uaSSPI
Definition hba.h:35
void proc_exit(int code)
Definition ipc.c:105
static char * errmsg
char * psprintf(const char *fmt,...)
Definition psprintf.c:43

References _, Assert, ereport, errcode(), ERRCODE_INVALID_PASSWORD, errdetail_log(), errmsg, FATAL, fb(), gettext_noop, pg_unreachable, port, proc_exit(), psprintf(), STATUS_EOF, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaOAuth, uaPAM, uaPassword, uaPeer, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by ClientAuthentication().

◆ auth_peer()

static int auth_peer ( Port port)
static

Definition at line 1903 of file auth.c.

1904{
1905 uid_t uid;
1906 gid_t gid;
1907#ifndef WIN32
1908 struct passwd pwbuf;
1909 struct passwd *pw;
1910 char buf[1024];
1911 int rc;
1912 int ret;
1913#endif
1914
1915 if (getpeereid(port->sock, &uid, &gid) != 0)
1916 {
1917 /* Provide special error message if getpeereid is a stub */
1918 if (errno == ENOSYS)
1919 ereport(LOG,
1921 errmsg("peer authentication is not supported on this platform")));
1922 else
1923 ereport(LOG,
1925 errmsg("could not get peer credentials: %m")));
1926 return STATUS_ERROR;
1927 }
1928
1929#ifndef WIN32
1930 rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1931 if (rc != 0)
1932 {
1933 errno = rc;
1934 ereport(LOG,
1935 errmsg("could not look up local user ID %ld: %m", (long) uid));
1936 return STATUS_ERROR;
1937 }
1938 else if (!pw)
1939 {
1940 ereport(LOG,
1941 errmsg("local user with ID %ld does not exist", (long) uid));
1942 return STATUS_ERROR;
1943 }
1944
1945 /*
1946 * Make a copy of static getpw*() result area; this is our authenticated
1947 * identity. Set it before calling check_usermap, because authentication
1948 * has already succeeded and we want the log file to reflect that.
1949 */
1950 set_authn_id(port, pw->pw_name);
1951
1952 ret = check_usermap(port->hba->usermap, port->user_name,
1954
1955 return ret;
1956#else
1957 /* should have failed with ENOSYS above */
1958 Assert(false);
1959 return STATUS_ERROR;
1960#endif
1961}
void set_authn_id(Port *port, const char *id)
Definition auth.c:338
#define STATUS_ERROR
Definition c.h:1318
int errcode_for_socket_access(void)
Definition elog.c:977
#define LOG
Definition elog.h:32
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
Definition hba.c:2791
ClientConnectionInfo MyClientConnectionInfo
Definition miscinit.c:1020
static char buf[DEFAULT_XLOG_SEG_SIZE]
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition getpeereid.c:33
const char * authn_id
Definition libpq-be.h:99
int gid_t
Definition win32_port.h:235
int uid_t
Definition win32_port.h:234

References Assert, ClientConnectionInfo::authn_id, buf, check_usermap(), ereport, errcode(), errcode_for_socket_access(), errmsg, fb(), getpeereid(), LOG, MyClientConnectionInfo, port, set_authn_id(), and STATUS_ERROR.

Referenced by ClientAuthentication().

◆ CheckMD5Auth()

static int CheckMD5Auth ( Port port,
char shadow_pass,
const char **  logdetail 
)
static

Definition at line 896 of file auth.c.

897{
898 uint8 md5Salt[4]; /* Password salt */
899 char *passwd;
900 int result;
901
902 /* include the salt to use for computing the response */
903 if (!pg_strong_random(md5Salt, 4))
904 {
905 ereport(LOG,
906 (errmsg("could not generate random MD5 salt")));
907 return STATUS_ERROR;
908 }
909
911
913 if (passwd == NULL)
914 return STATUS_EOF; /* client wouldn't send password */
915
916 if (shadow_pass)
918 md5Salt, 4, logdetail);
919 else
921
922 pfree(passwd);
923
924 if (result == STATUS_OK)
926
927 return result;
928}
void sendAuthRequest(Port *port, AuthRequest areq, const void *extradata, int extralen)
Definition auth.c:684
static char * recv_password_packet(Port *port)
Definition auth.c:714
static void queue_md5_password_warning(void)
Definition auth.c:937
#define STATUS_OK
Definition c.h:1317
uint8_t uint8
Definition c.h:681
uint32 result
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const uint8 *md5_salt, int md5_salt_len, const char **logdetail)
Definition crypt.c:265
void pfree(void *pointer)
Definition mcxt.c:1619
bool pg_strong_random(void *buf, size_t len)
#define AUTH_REQ_MD5
Definition protocol.h:101

References AUTH_REQ_MD5, ereport, errmsg, fb(), LOG, md5_crypt_verify(), pfree(), pg_strong_random(), port, queue_md5_password_warning(), recv_password_packet(), result, sendAuthRequest(), STATUS_EOF, STATUS_ERROR, and STATUS_OK.

Referenced by CheckPWChallengeAuth().

◆ CheckPasswordAuth()

static int CheckPasswordAuth ( Port port,
const char **  logdetail 
)
static

Definition at line 795 of file auth.c.

796{
797 char *passwd;
798 int result;
799 char *shadow_pass;
800 bool md5_password = false;
801
803
805 if (passwd == NULL)
806 return STATUS_EOF; /* client wouldn't send password */
807
808 shadow_pass = get_role_password(port->user_name, logdetail);
809 if (shadow_pass)
810 {
812 logdetail);
814 }
815 else
817
818 if (shadow_pass)
820 pfree(passwd);
821
822 if (result == STATUS_OK)
823 {
824 if (md5_password)
826 set_authn_id(port, port->user_name);
827 }
828
829 return result;
830}
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition crypt.c:320
char * get_role_password(const char *role, const char **logdetail)
Definition crypt.c:43
PasswordType get_password_type(const char *shadow_pass)
Definition crypt.c:153
@ PASSWORD_TYPE_MD5
Definition crypt.h:46
#define AUTH_REQ_PASSWORD
Definition protocol.h:99

References AUTH_REQ_PASSWORD, fb(), get_password_type(), get_role_password(), PASSWORD_TYPE_MD5, pfree(), plain_crypt_verify(), port, queue_md5_password_warning(), recv_password_packet(), result, sendAuthRequest(), set_authn_id(), STATUS_EOF, STATUS_ERROR, and STATUS_OK.

Referenced by ClientAuthentication().

◆ CheckPWChallengeAuth()

static int CheckPWChallengeAuth ( Port port,
const char **  logdetail 
)
static

Definition at line 836 of file auth.c.

837{
838 int auth_result;
839 char *shadow_pass;
841
842 Assert(port->hba->auth_method == uaSCRAM ||
843 port->hba->auth_method == uaMD5);
844
845 /* First look up the user's password. */
846 shadow_pass = get_role_password(port->user_name, logdetail);
847
848 /*
849 * If the user does not exist, or has no password or it's expired, we
850 * still go through the motions of authentication, to avoid revealing to
851 * the client that the user didn't exist. If 'md5' is allowed, we choose
852 * whether to use 'md5' or 'scram-sha-256' authentication based on current
853 * password_encryption setting. The idea is that most genuine users
854 * probably have a password of that type, and if we pretend that this user
855 * had a password of that type, too, it "blends in" best.
856 */
857 if (!shadow_pass)
859 else
861
862 /*
863 * If 'md5' authentication is allowed, decide whether to perform 'md5' or
864 * 'scram-sha-256' authentication based on the type of password the user
865 * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
866 * SCRAM secret, we must do SCRAM authentication.
867 *
868 * If MD5 authentication is not allowed, always use SCRAM. If the user
869 * had an MD5 password, CheckSASLAuth() with the SCRAM mechanism will
870 * fail.
871 */
872 if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
874 else
876 logdetail, NULL /* can't abandon SCRAM */ );
877
878 if (shadow_pass)
880 else
881 {
882 /*
883 * If get_role_password() returned error, authentication better not
884 * have succeeded.
885 */
887 }
888
889 if (auth_result == STATUS_OK)
890 set_authn_id(port, port->user_name);
891
892 return auth_result;
893}
int CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, const char **logdetail, bool *abandoned)
Definition auth-sasl.c:50
const pg_be_sasl_mech pg_be_scram_mech
Definition auth-scram.c:114
static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
Definition auth.c:896
PasswordType
Definition crypt.h:44
int Password_encryption
Definition user.c:86

References Assert, CheckMD5Auth(), CheckSASLAuth(), fb(), get_password_type(), get_role_password(), Password_encryption, PASSWORD_TYPE_MD5, pfree(), pg_be_scram_mech, port, set_authn_id(), STATUS_OK, uaMD5, and uaSCRAM.

Referenced by ClientAuthentication().

◆ ClientAuthentication()

void ClientAuthentication ( Port port)

Definition at line 376 of file auth.c.

377{
378 int status = STATUS_ERROR;
379 const char *logdetail = NULL;
380
381 /*
382 * "Abandoned" is a SASL-specific state similar to STATUS_EOF, in that we
383 * don't want to generate any server logs. But it's caused by an in-band
384 * client action that requires a server response, not an out-of-band
385 * connection closure, so we can't just proc_exit() like we do with
386 * STATUS_EOF.
387 */
388 bool abandoned = false;
389
390 /*
391 * Get the authentication method to use for this frontend/database
392 * combination. Note: we do not parse the file at this point; this has
393 * already been done elsewhere. hba.c dropped an error message into the
394 * server logfile if parsing the hba config file failed.
395 */
397
399
400 /*
401 * This is the first point where we have access to the hba record for the
402 * current connection, so perform any verifications based on the hba
403 * options field that should be done *before* the authentication here.
404 */
405 if (port->hba->clientcert != clientCertOff)
406 {
407 /* If we haven't loaded a root certificate store, fail */
411 errmsg("client certificates can only be checked if a root certificate store is available")));
412
413 /*
414 * If we loaded a root certificate store, and if a certificate is
415 * present on the client, then it has been verified against our root
416 * certificate store, and the connection would have been aborted
417 * already if it didn't verify ok.
418 */
419 if (!port->peer_cert_valid)
422 errmsg("connection requires a valid client certificate")));
423 }
424
425 /*
426 * Now proceed to do the actual authentication check
427 */
428 switch (port->hba->auth_method)
429 {
430 case uaReject:
431
432 /*
433 * An explicit "reject" entry in pg_hba.conf. This report exposes
434 * the fact that there's an explicit reject entry, which is
435 * perhaps not so desirable from a security standpoint; but the
436 * message for an implicit reject could confuse the DBA a lot when
437 * the true situation is a match to an explicit reject. And we
438 * don't want to change the message for an implicit reject. As
439 * noted below, the additional information shown here doesn't
440 * expose anything not known to an attacker.
441 */
442 {
443 char hostinfo[NI_MAXHOST];
444 const char *encryption_state;
445
446 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
447 hostinfo, sizeof(hostinfo),
448 NULL, 0,
450
452#ifdef ENABLE_GSS
453 (port->gss && port->gss->enc) ? _("GSS encryption") :
454#endif
455#ifdef USE_SSL
456 port->ssl_in_use ? _("SSL encryption") :
457#endif
458 _("no encryption");
459
463 /* translator: last %s describes encryption state */
464 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
465 hostinfo, port->user_name,
467 else
470 /* translator: last %s describes encryption state */
471 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
472 hostinfo, port->user_name,
473 port->database_name,
475 break;
476 }
477
478 case uaImplicitReject:
479
480 /*
481 * No matching entry, so tell the user we fell through.
482 *
483 * NOTE: the extra info reported here is not a security breach,
484 * because all that info is known at the frontend and must be
485 * assumed known to bad guys. We're merely helping out the less
486 * clueful good guys.
487 */
488 {
489 char hostinfo[NI_MAXHOST];
490 const char *encryption_state;
491
492 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
493 hostinfo, sizeof(hostinfo),
494 NULL, 0,
496
498#ifdef ENABLE_GSS
499 (port->gss && port->gss->enc) ? _("GSS encryption") :
500#endif
501#ifdef USE_SSL
502 port->ssl_in_use ? _("SSL encryption") :
503#endif
504 _("no encryption");
505
506#define HOSTNAME_LOOKUP_DETAIL(port) \
507 (port->remote_hostname ? \
508 (port->remote_hostname_resolv == +1 ? \
509 errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
510 port->remote_hostname) : \
511 port->remote_hostname_resolv == 0 ? \
512 errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
513 port->remote_hostname) : \
514 port->remote_hostname_resolv == -1 ? \
515 errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
516 port->remote_hostname) : \
517 port->remote_hostname_resolv == -2 ? \
518 errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
519 port->remote_hostname, \
520 gai_strerror(port->remote_hostname_errcode)) : \
521 0) \
522 : (port->remote_hostname_resolv == -2 ? \
523 errdetail_log("Could not resolve client IP address to a host name: %s.", \
524 gai_strerror(port->remote_hostname_errcode)) : \
525 0))
526
530 /* translator: last %s describes encryption state */
531 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
532 hostinfo, port->user_name,
535 else
538 /* translator: last %s describes encryption state */
539 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
540 hostinfo, port->user_name,
541 port->database_name,
544 break;
545 }
546
547 case uaGSS:
548#ifdef ENABLE_GSS
549 /* We might or might not have the gss workspace already */
550 if (port->gss == NULL)
551 port->gss = (pg_gssinfo *)
553 sizeof(pg_gssinfo));
554 port->gss->auth = true;
555
556 /*
557 * If GSS state was set up while enabling encryption, we can just
558 * check the client's principal. Otherwise, ask for it.
559 */
560 if (port->gss->enc)
561 status = pg_GSS_checkauth(port);
562 else
563 {
565 status = pg_GSS_recvauth(port);
566 }
567#else
568 Assert(false);
569#endif
570 break;
571
572 case uaSSPI:
573#ifdef ENABLE_SSPI
574 if (port->gss == NULL)
575 port->gss = (pg_gssinfo *)
577 sizeof(pg_gssinfo));
579 status = pg_SSPI_recvauth(port);
580#else
581 Assert(false);
582#endif
583 break;
584
585 case uaPeer:
586 status = auth_peer(port);
587 break;
588
589 case uaIdent:
590 status = ident_inet(port);
591 break;
592
593 case uaMD5:
594 case uaSCRAM:
595 status = CheckPWChallengeAuth(port, &logdetail);
596 break;
597
598 case uaPassword:
599 status = CheckPasswordAuth(port, &logdetail);
600 break;
601
602 case uaPAM:
603#ifdef USE_PAM
604 status = CheckPAMAuth(port, port->user_name, "");
605#else
606 Assert(false);
607#endif /* USE_PAM */
608 break;
609
610 case uaBSD:
611#ifdef USE_BSD_AUTH
612 status = CheckBSDAuth(port, port->user_name);
613#else
614 Assert(false);
615#endif /* USE_BSD_AUTH */
616 break;
617
618 case uaLDAP:
619#ifdef USE_LDAP
620 status = CheckLDAPAuth(port);
621#else
622 Assert(false);
623#endif
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 case uaOAuth:
631 status = CheckSASLAuth(&pg_be_oauth_mech, port, NULL, &logdetail,
632 &abandoned);
633 break;
634 }
635
636 if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
637 || port->hba->auth_method == uaCert)
638 {
639 /*
640 * Make sure we only check the certificate if we use the cert method
641 * or verify-full option.
642 */
643#ifdef USE_SSL
644 status = CheckCertAuth(port);
645#else
646 Assert(false);
647#endif
648 }
649
651 status == STATUS_OK &&
653 {
654 /*
655 * Normally, if log_connections is set, the call to set_authn_id()
656 * will log the connection. However, if that function is never
657 * called, perhaps because the trust method is in use, then we handle
658 * the logging here instead.
659 */
660 ereport(LOG,
661 errmsg("connection authenticated: user=\"%s\" method=%s "
662 "(%s:%d)",
663 port->user_name, hba_authname(port->hba->auth_method),
664 port->hba->sourcefile, port->hba->linenumber));
665 }
666
668 (*ClientAuthentication_hook) (port, status);
669
670 if (status == STATUS_OK)
672 else
675 status,
676 logdetail);
677}
const pg_be_sasl_mech pg_be_oauth_mech
Definition auth-oauth.c:54
static int CheckPWChallengeAuth(Port *port, const char **logdetail)
Definition auth.c:836
static int auth_peer(Port *port)
Definition auth.c:1903
static void auth_failed(Port *port, int elevel, int status, const char *logdetail)
Definition auth.c:236
ClientAuthentication_hook_type ClientAuthentication_hook
Definition auth.c:219
static int ident_inet(Port *port)
Definition auth.c:1718
#define HOSTNAME_LOOKUP_DETAIL(port)
static int CheckPasswordAuth(Port *port, const char **logdetail)
Definition auth.c:795
uint32 log_connections
@ LOG_CONNECTION_AUTHENTICATION
bool secure_loaded_verify_locations(void)
Definition be-secure.c:103
#define FATAL_CLIENT_ONLY
Definition elog.h:43
void hba_getauthmethod(Port *port)
Definition hba.c:2935
const char * hba_authname(UserAuth auth_method)
Definition hba.c:2948
@ 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:117
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
MemoryContext TopMemoryContext
Definition mcxt.c:167
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#define AUTH_REQ_SSPI
Definition protocol.h:105
#define AUTH_REQ_GSS
Definition protocol.h:103
#define AUTH_REQ_OK
Definition protocol.h:96
bool am_walsender
Definition walsender.c:135
bool am_db_walsender
Definition walsender.c:138

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(), CheckSASLAuth(), ClientAuthentication_hook, clientCertFull, clientCertOff, ereport, errcode(), errmsg, FATAL, FATAL_CLIENT_ONLY, fb(), hba_authname(), hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), LOG, LOG_CONNECTION_AUTHENTICATION, log_connections, MemoryContextAllocZero(), MyClientConnectionInfo, pg_be_oauth_mech, pg_getnameinfo_all(), port, secure_loaded_verify_locations(), sendAuthRequest(), STATUS_ERROR, STATUS_OK, TopMemoryContext, uaBSD, uaCert, uaGSS, uaIdent, uaImplicitReject, uaLDAP, uaMD5, uaOAuth, uaPAM, uaPassword, uaPeer, uaReject, uaSCRAM, uaSSPI, and uaTrust.

Referenced by PerformAuthentication().

◆ ident_inet()

static int ident_inet ( Port port)
static

Definition at line 1718 of file auth.c.

1719{
1720 const SockAddr remote_addr = port->raddr;
1721 const SockAddr local_addr = port->laddr;
1723 pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1724 int rc; /* Return code from a locally called function */
1725 bool ident_return;
1727 char remote_port[NI_MAXSERV];
1729 char local_port[NI_MAXSERV];
1730 char ident_port[NI_MAXSERV];
1731 char ident_query[80];
1733 struct addrinfo *ident_serv = NULL,
1734 *la = NULL,
1735 hints;
1736
1737 /*
1738 * Might look a little weird to first convert it to text and then back to
1739 * sockaddr, but it's protocol independent.
1740 */
1743 remote_port, sizeof(remote_port),
1746 local_addr_s, sizeof(local_addr_s),
1747 local_port, sizeof(local_port),
1749
1750 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1751 hints.ai_flags = AI_NUMERICHOST;
1752 hints.ai_family = remote_addr.addr.ss_family;
1753 hints.ai_socktype = SOCK_STREAM;
1754 hints.ai_protocol = 0;
1755 hints.ai_addrlen = 0;
1756 hints.ai_canonname = NULL;
1757 hints.ai_addr = NULL;
1758 hints.ai_next = NULL;
1760 if (rc || !ident_serv)
1761 {
1762 /* we don't expect this to happen */
1763 ident_return = false;
1764 goto ident_inet_done;
1765 }
1766
1767 hints.ai_flags = AI_NUMERICHOST;
1768 hints.ai_family = local_addr.addr.ss_family;
1769 hints.ai_socktype = SOCK_STREAM;
1770 hints.ai_protocol = 0;
1771 hints.ai_addrlen = 0;
1772 hints.ai_canonname = NULL;
1773 hints.ai_addr = NULL;
1774 hints.ai_next = NULL;
1776 if (rc || !la)
1777 {
1778 /* we don't expect this to happen */
1779 ident_return = false;
1780 goto ident_inet_done;
1781 }
1782
1783 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1784 ident_serv->ai_protocol);
1786 {
1787 ereport(LOG,
1789 errmsg("could not create socket for Ident connection: %m")));
1790 ident_return = false;
1791 goto ident_inet_done;
1792 }
1793
1794 /*
1795 * Bind to the address which the client originally contacted, otherwise
1796 * the ident server won't be able to match up the right connection. This
1797 * is necessary if the PostgreSQL server is running on an IP alias.
1798 */
1799 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1800 if (rc != 0)
1801 {
1802 ereport(LOG,
1804 errmsg("could not bind to local address \"%s\": %m",
1805 local_addr_s)));
1806 ident_return = false;
1807 goto ident_inet_done;
1808 }
1809
1810 rc = connect(sock_fd, ident_serv->ai_addr,
1811 ident_serv->ai_addrlen);
1812 if (rc != 0)
1813 {
1814 ereport(LOG,
1816 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1818 ident_return = false;
1819 goto ident_inet_done;
1820 }
1821
1822 /* The query we send to the Ident server */
1823 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1824 remote_port, local_port);
1825
1826 /* loop in case send is interrupted */
1827 do
1828 {
1830
1832 } while (rc < 0 && errno == EINTR);
1833
1834 if (rc < 0)
1835 {
1836 ereport(LOG,
1838 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1840 ident_return = false;
1841 goto ident_inet_done;
1842 }
1843
1844 do
1845 {
1847
1848 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1849 } while (rc < 0 && errno == EINTR);
1850
1851 if (rc < 0)
1852 {
1853 ereport(LOG,
1855 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1857 ident_return = false;
1858 goto ident_inet_done;
1859 }
1860
1861 ident_response[rc] = '\0';
1863 if (!ident_return)
1864 ereport(LOG,
1865 (errmsg("invalidly formatted response from Ident server: \"%s\"",
1866 ident_response)));
1867
1871 if (ident_serv)
1873 if (la)
1874 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1875
1876 if (ident_return)
1877 {
1878 /*
1879 * Success! Store the identity, then check the usermap. Note that
1880 * setting the authenticated identity is done before checking the
1881 * usermap, because at this point authentication has succeeded.
1882 */
1884 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1885 }
1886 return STATUS_ERROR;
1887}
#define IDENT_USERNAME_MAX
Definition auth.c:71
#define IDENT_PORT
Definition auth.c:74
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition auth.c:1637
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition ip.c:85
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition ip.c:56
int pgsocket
Definition port.h:29
#define snprintf
Definition port.h:261
#define PGINVALID_SOCKET
Definition port.h:31
#define closesocket
Definition port.h:398
#define bind(s, addr, addrlen)
Definition win32_port.h:496
#define EINTR
Definition win32_port.h:361
#define recv(s, buf, len, flags)
Definition win32_port.h:501
#define send(s, buf, len, flags)
Definition win32_port.h:502
#define socket(af, type, protocol)
Definition win32_port.h:495
#define connect(s, name, namelen)
Definition win32_port.h:499

References bind, CHECK_FOR_INTERRUPTS, check_usermap(), closesocket, connect, EINTR, ereport, errcode_for_socket_access(), errmsg, fb(), IDENT_PORT, IDENT_USERNAME_MAX, interpret_ident_response(), LOG, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_getnameinfo_all(), PGINVALID_SOCKET, port, recv, send, set_authn_id(), snprintf, socket, and STATUS_ERROR.

Referenced by ClientAuthentication().

◆ interpret_ident_response()

static bool interpret_ident_response ( const char ident_response,
char ident_user 
)
static

Definition at line 1637 of file auth.c.

1639{
1640 const char *cursor = ident_response; /* Cursor into *ident_response */
1641
1642 /*
1643 * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1644 */
1645 if (strlen(ident_response) < 2)
1646 return false;
1647 else if (ident_response[strlen(ident_response) - 2] != '\r')
1648 return false;
1649 else
1650 {
1651 while (*cursor != ':' && *cursor != '\r')
1652 cursor++; /* skip port field */
1653
1654 if (*cursor != ':')
1655 return false;
1656 else
1657 {
1658 /* We're positioned to colon before response type field */
1659 char response_type[80];
1660 int i; /* Index into *response_type */
1661
1662 cursor++; /* Go over colon */
1663 while (is_ident_whitespace(*cursor))
1664 cursor++; /* skip blanks */
1665 i = 0;
1666 while (*cursor != ':' && *cursor != '\r' && !is_ident_whitespace(*cursor) &&
1667 i < (int) (sizeof(response_type) - 1))
1668 response_type[i++] = *cursor++;
1669 response_type[i] = '\0';
1670 while (is_ident_whitespace(*cursor))
1671 cursor++; /* skip blanks */
1672 if (strcmp(response_type, "USERID") != 0)
1673 return false;
1674 else
1675 {
1676 /*
1677 * It's a USERID response. Good. "cursor" should be pointing
1678 * to the colon that precedes the operating system type.
1679 */
1680 if (*cursor != ':')
1681 return false;
1682 else
1683 {
1684 cursor++; /* Go over colon */
1685 /* Skip over operating system field. */
1686 while (*cursor != ':' && *cursor != '\r')
1687 cursor++;
1688 if (*cursor != ':')
1689 return false;
1690 else
1691 {
1692 cursor++; /* Go over colon */
1693 while (is_ident_whitespace(*cursor))
1694 cursor++; /* skip blanks */
1695 /* Rest of line is user name. Copy it over. */
1696 i = 0;
1697 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1698 ident_user[i++] = *cursor++;
1699 ident_user[i] = '\0';
1700 return true;
1701 }
1702 }
1703 }
1704 }
1705 }
1706}
static bool is_ident_whitespace(const char c)
Definition auth.c:1625
int i
Definition isn.c:77
Definition type.h:139

References fb(), i, IDENT_USERNAME_MAX, and is_ident_whitespace().

Referenced by ident_inet().

◆ is_ident_whitespace()

static bool is_ident_whitespace ( const char  c)
static

Definition at line 1625 of file auth.c.

1626{
1627 return c == ' ' || c == '\t';
1628}
char * c

Referenced by interpret_ident_response().

◆ md5_password_warning_enabled()

static bool md5_password_warning_enabled ( void  )
static

Definition at line 931 of file auth.c.

932{
934}
bool md5_password_warnings
Definition crypt.c:33

References md5_password_warnings.

Referenced by queue_md5_password_warning().

◆ queue_md5_password_warning()

static void queue_md5_password_warning ( void  )
static

Definition at line 937 of file auth.c.

938{
939 MemoryContext oldcontext;
940 char *warning;
941 char *detail;
942
944
945 warning = pstrdup(_("authenticated with an MD5-encrypted password"));
946 detail = pstrdup(_("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."));
948
949 MemoryContextSwitchTo(oldcontext);
950}
static bool md5_password_warning_enabled(void)
Definition auth.c:931
char * pstrdup(const char *in)
Definition mcxt.c:1910
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
void StoreConnectionWarning(char *msg, char *detail, ConnectionWarningFilter filter)
Definition postinit.c:1517
static void static void static void warning(const char *const string,...) pg_attribute_printf(1
Definition zic.c:682

References _, md5_password_warning_enabled(), MemoryContextSwitchTo(), pstrdup(), StoreConnectionWarning(), TopMemoryContext, and warning().

Referenced by CheckMD5Auth(), and CheckPasswordAuth().

◆ recv_password_packet()

static char * recv_password_packet ( Port port)
static

Definition at line 714 of file auth.c.

715{
717 int mtype;
718
720
721 /* Expect 'p' message type */
722 mtype = pq_getbyte();
724 {
725 /*
726 * If the client just disconnects without offering a password, don't
727 * make a log entry. This is legal per protocol spec and in fact
728 * commonly done by psql, so complaining just clutters the log.
729 */
730 if (mtype != EOF)
733 errmsg("expected password response, got message type %d",
734 mtype)));
735 return NULL; /* EOF or bad message type */
736 }
737
739 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH)) /* receive password */
740 {
741 /* EOF - pq_getmessage already logged a suitable message */
742 pfree(buf.data);
743 return NULL;
744 }
745
746 /*
747 * Apply sanity check: password packet length should agree with length of
748 * contained string. Note it is safe to use strlen here because
749 * StringInfo is guaranteed to have an appended '\0'.
750 */
751 if (strlen(buf.data) + 1 != buf.len)
754 errmsg("invalid password packet size")));
755
756 /*
757 * Don't allow an empty password. Libpq treats an empty password the same
758 * as no password at all, and won't even try to authenticate. But other
759 * clients might, so allowing it would be confusing.
760 *
761 * Note that this only catches an empty password sent by the client in
762 * plaintext. There's also a check in CREATE/ALTER USER that prevents an
763 * empty string from being stored as a user's password in the first place.
764 * We rely on that for MD5 and SCRAM authentication, but we still need
765 * this check here, to prevent an empty password from being used with
766 * authentication methods that check the password against an external
767 * system, like PAM and LDAP.
768 */
769 if (buf.len == 1)
772 errmsg("empty password returned by client")));
773
774 /* Do not echo password to logs, for security. */
775 elog(DEBUG5, "received password packet");
776
777 /*
778 * Return the received string. Note we do not attempt to do any
779 * character-set conversion on it; since we don't yet know the client's
780 * encoding, there wouldn't be much point.
781 */
782 return buf.data;
783}
#define PG_MAX_AUTH_TOKEN_LENGTH
Definition auth.h:33
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define DEBUG5
Definition elog.h:27
#define ERRCODE_PROTOCOL_VIOLATION
Definition fe-connect.c:96
int pq_getmessage(StringInfo s, int maxlen)
Definition pqcomm.c:1204
int pq_getbyte(void)
Definition pqcomm.c:964
void pq_startmsgread(void)
Definition pqcomm.c:1142
#define PqMsg_PasswordMessage
Definition protocol.h:31
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

References buf, DEBUG5, elog, ereport, errcode(), ERRCODE_INVALID_PASSWORD, ERRCODE_PROTOCOL_VIOLATION, errmsg, ERROR, fb(), initStringInfo(), pfree(), PG_MAX_AUTH_TOKEN_LENGTH, pq_getbyte(), pq_getmessage(), pq_startmsgread(), and PqMsg_PasswordMessage.

Referenced by CheckMD5Auth(), and CheckPasswordAuth().

◆ sendAuthRequest()

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

Definition at line 684 of file auth.c.

685{
687
689
692 if (extralen > 0)
694
696
697 /*
698 * Flush message so client will see it, except for AUTH_REQ_OK and
699 * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
700 * queries.
701 */
703 pq_flush();
704
706}
int32_t int32
Definition c.h:679
#define pq_flush()
Definition libpq.h:49
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:108

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

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

◆ set_authn_id()

void set_authn_id ( Port port,
const char id 
)

Definition at line 338 of file auth.c.

339{
340 Assert(id);
341
343 {
344 /*
345 * An existing authn_id should never be overwritten; that means two
346 * authentication providers are fighting (or one is fighting itself).
347 * Don't leak any authn details to the client, but don't let the
348 * connection continue, either.
349 */
351 (errmsg("authentication identifier set more than once"),
352 errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
354 }
355
357 MyClientConnectionInfo.auth_method = port->hba->auth_method;
358
360 {
361 ereport(LOG,
362 errmsg("connection authenticated: identity=\"%s\" method=%s "
363 "(%s:%d)",
366 port->hba->sourcefile, port->hba->linenumber));
367 }
368}
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1897

References Assert, ClientConnectionInfo::auth_method, ClientConnectionInfo::authn_id, ereport, errdetail_log(), errmsg, FATAL, hba_authname(), LOG, LOG_CONNECTION_AUTHENTICATION, log_connections, MemoryContextStrdup(), MyClientConnectionInfo, port, and TopMemoryContext.

Referenced by auth_peer(), CheckPasswordAuth(), CheckPWChallengeAuth(), ident_inet(), and validate().

Variable Documentation

◆ ClientAuthentication_hook

ClientAuthentication_hook_type ClientAuthentication_hook = NULL

Definition at line 219 of file auth.c.

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

◆ pg_gss_accept_delegation

bool pg_gss_accept_delegation

Definition at line 178 of file auth.c.

Referenced by secure_open_gssapi().

◆ pg_krb_caseins_users

bool pg_krb_caseins_users

Definition at line 177 of file auth.c.

◆ pg_krb_server_keyfile

char* pg_krb_server_keyfile

Definition at line 176 of file auth.c.

Referenced by secure_open_gssapi().