PostgreSQL Source Code git master
Loading...
Searching...
No Matches
auth.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * auth.c
4 * Routines to handle network authentication
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/libpq/auth.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include <sys/param.h>
19#include <sys/select.h>
20#include <sys/socket.h>
21#include <netinet/in.h>
22#include <netdb.h>
23#include <pwd.h>
24#include <unistd.h>
25
26#include "commands/user.h"
27#include "common/ip.h"
28#include "common/md5.h"
29#include "libpq/auth.h"
30#include "libpq/crypt.h"
31#include "libpq/libpq.h"
32#include "libpq/oauth.h"
33#include "libpq/pqformat.h"
34#include "libpq/sasl.h"
35#include "libpq/scram.h"
36#include "miscadmin.h"
37#include "port/pg_bswap.h"
40#include "storage/ipc.h"
42#include "utils/memutils.h"
43
44/*----------------------------------------------------------------
45 * Global authentication functions
46 *----------------------------------------------------------------
47 */
48static void auth_failed(Port *port, int elevel, int status,
49 const char *logdetail);
50static char *recv_password_packet(Port *port);
51
52
53/*----------------------------------------------------------------
54 * Password-based authentication methods (password, md5, and scram-sha-256)
55 *----------------------------------------------------------------
56 */
57static int CheckPasswordAuth(Port *port, const char **logdetail);
58static int CheckPWChallengeAuth(Port *port, const char **logdetail);
59
60static int CheckMD5Auth(Port *port, char *shadow_pass,
61 const char **logdetail);
62
63
64/*----------------------------------------------------------------
65 * Ident authentication
66 *----------------------------------------------------------------
67 */
68/* Max size of username ident server can return (per RFC 1413) */
69#define IDENT_USERNAME_MAX 512
70
71/* Standard TCP port number for Ident service. Assigned by IANA */
72#define IDENT_PORT 113
73
74static int ident_inet(Port *port);
75
76
77/*----------------------------------------------------------------
78 * Peer authentication
79 *----------------------------------------------------------------
80 */
81static int auth_peer(Port *port);
82
83
84/*----------------------------------------------------------------
85 * PAM authentication
86 *----------------------------------------------------------------
87 */
88#ifdef USE_PAM
89#ifdef HAVE_PAM_PAM_APPL_H
90#include <pam/pam_appl.h>
91#endif
92#ifdef HAVE_SECURITY_PAM_APPL_H
93#include <security/pam_appl.h>
94#endif
95
96#define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */
97
98/* Work around original Solaris' lack of "const" in the conv_proc signature */
99#ifdef _PAM_LEGACY_NONCONST
100#define PG_PAM_CONST
101#else
102#define PG_PAM_CONST const
103#endif
104
105static int CheckPAMAuth(Port *port, const char *user, const char *password);
106static int pam_passwd_conv_proc(int num_msg,
107 PG_PAM_CONST struct pam_message **msg,
108 struct pam_response **resp, void *appdata_ptr);
109
110static struct pam_conv pam_passw_conv = {
112 NULL
113};
114
115static const char *pam_passwd = NULL; /* Workaround for Solaris 2.6
116 * brokenness */
117static Port *pam_port_cludge; /* Workaround for passing "Port *port" into
118 * pam_passwd_conv_proc */
119static bool pam_no_password; /* For detecting no-password-given */
120#endif /* USE_PAM */
121
122
123/*----------------------------------------------------------------
124 * BSD authentication
125 *----------------------------------------------------------------
126 */
127#ifdef USE_BSD_AUTH
128#include <bsd_auth.h>
129
130static int CheckBSDAuth(Port *port, char *user);
131#endif /* USE_BSD_AUTH */
132
133
134/*----------------------------------------------------------------
135 * LDAP authentication
136 *----------------------------------------------------------------
137 */
138#ifdef USE_LDAP
139#ifndef WIN32
140/* We use a deprecated function to keep the codepath the same as win32. */
141#define LDAP_DEPRECATED 1
142#include <ldap.h>
143#else
144#include <winldap.h>
145
146#endif
147
148static int CheckLDAPAuth(Port *port);
149
150/* LDAP_OPT_DIAGNOSTIC_MESSAGE is the newer spelling */
151#ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE
152#define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING
153#endif
154
155/* Default LDAP password mutator hook, can be overridden by a shared library */
156static char *dummy_ldap_password_mutator(char *input);
158
159#endif /* USE_LDAP */
160
161/*----------------------------------------------------------------
162 * Cert authentication
163 *----------------------------------------------------------------
164 */
165#ifdef USE_SSL
166static int CheckCertAuth(Port *port);
167#endif
168
169
170/*----------------------------------------------------------------
171 * Kerberos and GSSAPI GUCs
172 *----------------------------------------------------------------
173 */
177
178
179/*----------------------------------------------------------------
180 * GSSAPI Authentication
181 *----------------------------------------------------------------
182 */
183#ifdef ENABLE_GSS
185
186static int pg_GSS_checkauth(Port *port);
187static int pg_GSS_recvauth(Port *port);
188#endif /* ENABLE_GSS */
189
190
191/*----------------------------------------------------------------
192 * SSPI Authentication
193 *----------------------------------------------------------------
194 */
195#ifdef ENABLE_SSPI
196typedef SECURITY_STATUS
198static int pg_SSPI_recvauth(Port *port);
199static int pg_SSPI_make_upn(char *accountname,
200 size_t accountnamesize,
201 char *domainname,
202 size_t domainnamesize,
203 bool update_accountname);
204#endif
205
206
207/*----------------------------------------------------------------
208 * Global authentication functions
209 *----------------------------------------------------------------
210 */
211
212/*
213 * This hook allows plugins to get control following client authentication,
214 * but before the user has been informed about the results. It could be used
215 * to record login events, insert a delay after failed authentication, etc.
216 */
218
219/*
220 * Tell the user the authentication failed, but not (much about) why.
221 *
222 * There is a tradeoff here between security concerns and making life
223 * unnecessarily difficult for legitimate users. We would not, for example,
224 * want to report the password we were expecting to receive...
225 * But it seems useful to report the username and authorization method
226 * in use, and these are items that must be presumed known to an attacker
227 * anyway.
228 * Note that many sorts of failure report additional information in the
229 * postmaster log, which we hope is only readable by good guys. In
230 * particular, if logdetail isn't NULL, we send that string to the log
231 * when the elevel allows.
232 */
233static void
234auth_failed(Port *port, int elevel, int status, const char *logdetail)
235{
236 const char *errstr;
237 char *cdetail;
239
240 Assert(elevel >= FATAL); /* we must exit here */
241
242 /*
243 * If we failed due to EOF from client, just quit; there's no point in
244 * trying to send a message to the client, and not much point in logging
245 * the failure in the postmaster log. (Logging the failure might be
246 * desirable, were it not for the fact that libpq closes the connection
247 * unceremoniously if challenged for a password when it hasn't got one to
248 * send. We'll get a useless log entry for every psql connection under
249 * password auth, even if it's perfectly successful, if we log STATUS_EOF
250 * events.)
251 */
252 if (status == STATUS_EOF)
253 proc_exit(0);
254
255 switch (port->hba->auth_method)
256 {
257 case uaReject:
258 case uaImplicitReject:
259 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
260 break;
261 case uaTrust:
262 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
263 break;
264 case uaIdent:
265 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
266 break;
267 case uaPeer:
268 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
269 break;
270 case uaPassword:
271 case uaMD5:
272 case uaSCRAM:
273 errstr = gettext_noop("password authentication failed for user \"%s\"");
274 /* We use it to indicate if a .pgpass password failed. */
276 break;
277 case uaGSS:
278 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
279 break;
280 case uaSSPI:
281 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
282 break;
283 case uaPAM:
284 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
285 break;
286 case uaBSD:
287 errstr = gettext_noop("BSD authentication failed for user \"%s\"");
288 break;
289 case uaLDAP:
290 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
291 break;
292 case uaCert:
293 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
294 break;
295 case uaOAuth:
296 errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\"");
297 break;
298 default:
299 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
300 break;
301 }
302
303 cdetail = psprintf(_("Connection matched file \"%s\" line %d: \"%s\""),
304 port->hba->sourcefile, port->hba->linenumber,
305 port->hba->rawline);
306 if (logdetail)
307 logdetail = psprintf("%s\n%s", logdetail, cdetail);
308 else
309 logdetail = cdetail;
310
311 ereport(elevel,
313 errmsg(errstr, port->user_name),
314 logdetail ? errdetail_log("%s", logdetail) : 0));
315
316 /* doesn't return */
318}
319
320
321/*
322 * Sets the authenticated identity for the current user. The provided string
323 * will be stored into MyClientConnectionInfo, alongside the current HBA
324 * method in use. The ID will be logged if log_connections has the
325 * 'authentication' option specified.
326 *
327 * Auth methods should call this routine exactly once, as soon as the user is
328 * successfully authenticated, even if they have reasons to know that
329 * authorization will fail later.
330 *
331 * The provided string will be copied into TopMemoryContext, to match the
332 * lifetime of MyClientConnectionInfo, so it is safe to pass a string that is
333 * managed by an external library.
334 */
335void
336set_authn_id(Port *port, const char *id)
337{
338 Assert(id);
339
341 {
342 /*
343 * An existing authn_id should never be overwritten; that means two
344 * authentication providers are fighting (or one is fighting itself).
345 * Don't leak any authn details to the client, but don't let the
346 * connection continue, either.
347 */
349 (errmsg("authentication identifier set more than once"),
350 errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
352 }
353
355 MyClientConnectionInfo.auth_method = port->hba->auth_method;
356
358 {
359 ereport(LOG,
360 errmsg("connection authenticated: identity=\"%s\" method=%s "
361 "(%s:%d)",
364 port->hba->sourcefile, port->hba->linenumber));
365 }
366}
367
368
369/*
370 * Client authentication starts here. If there is an error, this
371 * function does not return and the backend process is terminated.
372 */
373void
375{
376 int status = STATUS_ERROR;
377 const char *logdetail = NULL;
378
379 /*
380 * "Abandoned" is a SASL-specific state similar to STATUS_EOF, in that we
381 * don't want to generate any server logs. But it's caused by an in-band
382 * client action that requires a server response, not an out-of-band
383 * connection closure, so we can't just proc_exit() like we do with
384 * STATUS_EOF.
385 */
386 bool abandoned = false;
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 */
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)
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,
448
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
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,
465 else
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,
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,
494
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
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,
533 else
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,
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 {
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 uaCert:
624 /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
625 case uaTrust:
626 status = STATUS_OK;
627 break;
628 case uaOAuth:
629 status = CheckSASLAuth(&pg_be_oauth_mech, port, NULL, &logdetail,
630 &abandoned);
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
649 status == STATUS_OK &&
651 {
652 /*
653 * Normally, if log_connections is set, the call to set_authn_id()
654 * will log the connection. However, if that function is never
655 * called, perhaps because the trust method is in use, then we handle
656 * the logging here instead.
657 */
658 ereport(LOG,
659 errmsg("connection authenticated: user=\"%s\" method=%s "
660 "(%s:%d)",
661 port->user_name, hba_authname(port->hba->auth_method),
662 port->hba->sourcefile, port->hba->linenumber));
663 }
664
666 (*ClientAuthentication_hook) (port, status);
667
668 if (status == STATUS_OK)
670 else
673 status,
674 logdetail);
675}
676
677
678/*
679 * Send an authentication request packet to the frontend.
680 */
681void
683{
685
687
690 if (extralen > 0)
692
694
695 /*
696 * Flush message so client will see it, except for AUTH_REQ_OK and
697 * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
698 * queries.
699 */
701 pq_flush();
702
704}
705
706/*
707 * Collect password response packet from frontend.
708 *
709 * Returns NULL if couldn't get password, else palloc'd string.
710 */
711static char *
713{
715 int mtype;
716
718
719 /* Expect 'p' message type */
720 mtype = pq_getbyte();
722 {
723 /*
724 * If the client just disconnects without offering a password, don't
725 * make a log entry. This is legal per protocol spec and in fact
726 * commonly done by psql, so complaining just clutters the log.
727 */
728 if (mtype != EOF)
731 errmsg("expected password response, got message type %d",
732 mtype)));
733 return NULL; /* EOF or bad message type */
734 }
735
737 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH)) /* receive password */
738 {
739 /* EOF - pq_getmessage already logged a suitable message */
740 pfree(buf.data);
741 return NULL;
742 }
743
744 /*
745 * Apply sanity check: password packet length should agree with length of
746 * contained string. Note it is safe to use strlen here because
747 * StringInfo is guaranteed to have an appended '\0'.
748 */
749 if (strlen(buf.data) + 1 != buf.len)
752 errmsg("invalid password packet size")));
753
754 /*
755 * Don't allow an empty password. Libpq treats an empty password the same
756 * as no password at all, and won't even try to authenticate. But other
757 * clients might, so allowing it would be confusing.
758 *
759 * Note that this only catches an empty password sent by the client in
760 * plaintext. There's also a check in CREATE/ALTER USER that prevents an
761 * empty string from being stored as a user's password in the first place.
762 * We rely on that for MD5 and SCRAM authentication, but we still need
763 * this check here, to prevent an empty password from being used with
764 * authentication methods that check the password against an external
765 * system, like PAM and LDAP.
766 */
767 if (buf.len == 1)
770 errmsg("empty password returned by client")));
771
772 /* Do not echo password to logs, for security. */
773 elog(DEBUG5, "received password packet");
774
775 /*
776 * Return the received string. Note we do not attempt to do any
777 * character-set conversion on it; since we don't yet know the client's
778 * encoding, there wouldn't be much point.
779 */
780 return buf.data;
781}
782
783
784/*----------------------------------------------------------------
785 * Password-based authentication mechanisms
786 *----------------------------------------------------------------
787 */
788
789/*
790 * Plaintext password authentication.
791 */
792static int
793CheckPasswordAuth(Port *port, const char **logdetail)
794{
795 char *passwd;
796 int result;
797 char *shadow_pass;
798
800
802 if (passwd == NULL)
803 return STATUS_EOF; /* client wouldn't send password */
804
805 shadow_pass = get_role_password(port->user_name, logdetail);
806 if (shadow_pass)
807 {
809 logdetail);
810 }
811 else
813
814 if (shadow_pass)
816 pfree(passwd);
817
818 if (result == STATUS_OK)
819 set_authn_id(port, port->user_name);
820
821 return result;
822}
823
824/*
825 * MD5 and SCRAM authentication.
826 */
827static int
828CheckPWChallengeAuth(Port *port, const char **logdetail)
829{
830 int auth_result;
831 char *shadow_pass;
833
834 Assert(port->hba->auth_method == uaSCRAM ||
835 port->hba->auth_method == uaMD5);
836
837 /* First look up the user's password. */
838 shadow_pass = get_role_password(port->user_name, logdetail);
839
840 /*
841 * If the user does not exist, or has no password or it's expired, we
842 * still go through the motions of authentication, to avoid revealing to
843 * the client that the user didn't exist. If 'md5' is allowed, we choose
844 * whether to use 'md5' or 'scram-sha-256' authentication based on current
845 * password_encryption setting. The idea is that most genuine users
846 * probably have a password of that type, and if we pretend that this user
847 * had a password of that type, too, it "blends in" best.
848 */
849 if (!shadow_pass)
851 else
853
854 /*
855 * If 'md5' authentication is allowed, decide whether to perform 'md5' or
856 * 'scram-sha-256' authentication based on the type of password the user
857 * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
858 * SCRAM secret, we must do SCRAM authentication.
859 *
860 * If MD5 authentication is not allowed, always use SCRAM. If the user
861 * had an MD5 password, CheckSASLAuth() with the SCRAM mechanism will
862 * fail.
863 */
864 if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
866 else
868 logdetail, NULL /* can't abandon SCRAM */ );
869
870 if (shadow_pass)
872 else
873 {
874 /*
875 * If get_role_password() returned error, authentication better not
876 * have succeeded.
877 */
879 }
880
881 if (auth_result == STATUS_OK)
882 set_authn_id(port, port->user_name);
883
884 return auth_result;
885}
886
887static int
888CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
889{
890 uint8 md5Salt[4]; /* Password salt */
891 char *passwd;
892 int result;
893
894 /* include the salt to use for computing the response */
895 if (!pg_strong_random(md5Salt, 4))
896 {
897 ereport(LOG,
898 (errmsg("could not generate random MD5 salt")));
899 return STATUS_ERROR;
900 }
901
903
905 if (passwd == NULL)
906 return STATUS_EOF; /* client wouldn't send password */
907
908 if (shadow_pass)
910 md5Salt, 4, logdetail);
911 else
913
914 pfree(passwd);
915
916 return result;
917}
918
919
920/*----------------------------------------------------------------
921 * GSSAPI authentication system
922 *----------------------------------------------------------------
923 */
924#ifdef ENABLE_GSS
925static int
927{
929 min_stat,
930 lmin_s,
931 gflags;
932 int mtype;
936
937 /*
938 * Use the configured keytab, if there is one. As we now require MIT
939 * Kerberos, we might consider using the credential store extensions in
940 * the future instead of the environment variable.
941 */
943 {
944 if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
945 {
946 /* The only likely failure cause is OOM, so use that errcode */
949 errmsg("could not set environment: %m")));
950 }
951 }
952
953 /*
954 * We accept any service principal that's present in our keytab. This
955 * increases interoperability between kerberos implementations that see
956 * for example case sensitivity differently, while not really opening up
957 * any vector of attack.
958 */
959 port->gss->cred = GSS_C_NO_CREDENTIAL;
960
961 /*
962 * Initialize sequence with an empty context
963 */
964 port->gss->ctx = GSS_C_NO_CONTEXT;
965
967 port->gss->delegated_creds = false;
968
969 /*
970 * Loop through GSSAPI message exchange. This exchange can consist of
971 * multiple messages sent in both directions. First message is always from
972 * the client. All messages from client to server are password packets
973 * (type 'p').
974 */
975 do
976 {
978
980
981 mtype = pq_getbyte();
983 {
984 /* Only log error if client didn't disconnect. */
985 if (mtype != EOF)
988 errmsg("expected GSS response, got message type %d",
989 mtype)));
990 return STATUS_ERROR;
991 }
992
993 /* Get the actual GSS token */
996 {
997 /* EOF - pq_getmessage already logged error */
998 pfree(buf.data);
999 return STATUS_ERROR;
1000 }
1001
1002 /* Map to GSSAPI style buffer */
1003 gbuf.length = buf.len;
1004 gbuf.value = buf.data;
1005
1006 elog(DEBUG4, "processing received GSS token of length %zu",
1007 gbuf.length);
1008
1010 &port->gss->ctx,
1011 port->gss->cred,
1012 &gbuf,
1014 &port->gss->name,
1015 NULL,
1016 &port->gss->outbuf,
1017 &gflags,
1018 NULL,
1020
1021 /* gbuf no longer used */
1022 pfree(buf.data);
1023
1024 elog(DEBUG5, "gss_accept_sec_context major: %u, "
1025 "minor: %u, outlen: %zu, outflags: %x",
1027 port->gss->outbuf.length, gflags);
1028
1030
1032 {
1034 port->gss->delegated_creds = true;
1035 }
1036
1037 if (port->gss->outbuf.length != 0)
1038 {
1039 /*
1040 * Negotiation generated data to be sent to the client.
1041 */
1042 elog(DEBUG4, "sending GSS response token of length %zu",
1043 port->gss->outbuf.length);
1044
1046 port->gss->outbuf.value, port->gss->outbuf.length);
1047
1048 gss_release_buffer(&lmin_s, &port->gss->outbuf);
1049 }
1050
1052 {
1054 pg_GSS_error(_("accepting GSS security context failed"),
1056 return STATUS_ERROR;
1057 }
1058
1060 elog(DEBUG4, "GSS continue needed");
1061
1062 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
1063
1064 if (port->gss->cred != GSS_C_NO_CREDENTIAL)
1065 {
1066 /*
1067 * Release service principal credentials
1068 */
1069 gss_release_cred(&min_stat, &port->gss->cred);
1070 }
1071 return pg_GSS_checkauth(port);
1072}
1073
1074/*
1075 * Check whether the GSSAPI-authenticated user is allowed to connect as the
1076 * claimed username.
1077 */
1078static int
1080{
1081 int ret;
1083 min_stat,
1084 lmin_s;
1086 char *princ;
1087
1088 /*
1089 * Get the name of the user that authenticated, and compare it to the pg
1090 * username that was specified for the connection.
1091 */
1092 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
1093 if (maj_stat != GSS_S_COMPLETE)
1094 {
1095 pg_GSS_error(_("retrieving GSS user name failed"),
1097 return STATUS_ERROR;
1098 }
1099
1100 /*
1101 * gbuf.value might not be null-terminated, so turn it into a regular
1102 * null-terminated string.
1103 */
1104 princ = palloc(gbuf.length + 1);
1105 memcpy(princ, gbuf.value, gbuf.length);
1106 princ[gbuf.length] = '\0';
1108
1109 /*
1110 * Copy the original name of the authenticated principal into our backend
1111 * memory for display later.
1112 *
1113 * This is also our authenticated identity. Set it now, rather than
1114 * waiting for the usermap check below, because authentication has already
1115 * succeeded and we want the log file to reflect that.
1116 */
1119
1120 /*
1121 * Split the username at the realm separator
1122 */
1123 if (strchr(princ, '@'))
1124 {
1125 char *cp = strchr(princ, '@');
1126
1127 /*
1128 * If we are not going to include the realm in the username that is
1129 * passed to the ident map, destructively modify it here to remove the
1130 * realm. Then advance past the separator to check the realm.
1131 */
1132 if (!port->hba->include_realm)
1133 *cp = '\0';
1134 cp++;
1135
1136 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
1137 {
1138 /*
1139 * Match the realm part of the name first
1140 */
1142 ret = pg_strcasecmp(port->hba->krb_realm, cp);
1143 else
1144 ret = strcmp(port->hba->krb_realm, cp);
1145
1146 if (ret)
1147 {
1148 /* GSS realm does not match */
1149 elog(DEBUG2,
1150 "GSSAPI realm (%s) and configured realm (%s) don't match",
1151 cp, port->hba->krb_realm);
1152 pfree(princ);
1153 return STATUS_ERROR;
1154 }
1155 }
1156 }
1157 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1158 {
1159 elog(DEBUG2,
1160 "GSSAPI did not return realm but realm matching was requested");
1161 pfree(princ);
1162 return STATUS_ERROR;
1163 }
1164
1165 ret = check_usermap(port->hba->usermap, port->user_name, princ,
1167
1168 pfree(princ);
1169
1170 return ret;
1171}
1172#endif /* ENABLE_GSS */
1173
1174
1175/*----------------------------------------------------------------
1176 * SSPI authentication system
1177 *----------------------------------------------------------------
1178 */
1179#ifdef ENABLE_SSPI
1180
1181/*
1182 * Generate an error for SSPI authentication. The caller should apply
1183 * _() to errmsg to make it translatable.
1184 */
1185static void
1186pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
1187{
1188 char sysmsg[256];
1189
1192 NULL, r, 0,
1193 sysmsg, sizeof(sysmsg), NULL) == 0)
1195 (errmsg_internal("%s", errmsg),
1196 errdetail_internal("SSPI error %x", (unsigned int) r)));
1197 else
1199 (errmsg_internal("%s", errmsg),
1200 errdetail_internal("%s (%x)", sysmsg, (unsigned int) r)));
1201}
1202
1203static int
1205{
1206 int mtype;
1211 newctx;
1215 SecBufferDesc outbuf;
1218 HANDLE token;
1220 DWORD retlen;
1221 char accountname[MAXPGPATH];
1222 char domainname[MAXPGPATH];
1224 DWORD domainnamesize = sizeof(domainname);
1226 char *authn_id;
1227
1228 /*
1229 * Acquire a handle to the server credentials.
1230 */
1232 "negotiate",
1234 NULL,
1235 NULL,
1236 NULL,
1237 NULL,
1238 &sspicred,
1239 &expiry);
1240 if (r != SEC_E_OK)
1241 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
1242
1243 /*
1244 * Loop through SSPI message exchange. This exchange can consist of
1245 * multiple messages sent in both directions. First message is always from
1246 * the client. All messages from client to server are password packets
1247 * (type 'p').
1248 */
1249 do
1250 {
1252 mtype = pq_getbyte();
1253 if (mtype != PqMsg_GSSResponse)
1254 {
1255 if (sspictx != NULL)
1256 {
1258 free(sspictx);
1259 }
1261
1262 /* Only log error if client didn't disconnect. */
1263 if (mtype != EOF)
1264 ereport(ERROR,
1266 errmsg("expected SSPI response, got message type %d",
1267 mtype)));
1268 return STATUS_ERROR;
1269 }
1270
1271 /* Get the actual SSPI token */
1274 {
1275 /* EOF - pq_getmessage already logged error */
1276 pfree(buf.data);
1277 if (sspictx != NULL)
1278 {
1280 free(sspictx);
1281 }
1283 return STATUS_ERROR;
1284 }
1285
1286 /* Map to SSPI style buffer */
1287 inbuf.ulVersion = SECBUFFER_VERSION;
1288 inbuf.cBuffers = 1;
1289 inbuf.pBuffers = InBuffers;
1290 InBuffers[0].pvBuffer = buf.data;
1291 InBuffers[0].cbBuffer = buf.len;
1292 InBuffers[0].BufferType = SECBUFFER_TOKEN;
1293
1294 /* Prepare output buffer */
1295 OutBuffers[0].pvBuffer = NULL;
1296 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1297 OutBuffers[0].cbBuffer = 0;
1298 outbuf.cBuffers = 1;
1299 outbuf.pBuffers = OutBuffers;
1300 outbuf.ulVersion = SECBUFFER_VERSION;
1301
1302 elog(DEBUG4, "processing received SSPI token of length %u",
1303 (unsigned int) buf.len);
1304
1306 sspictx,
1307 &inbuf,
1310 &newctx,
1311 &outbuf,
1312 &contextattr,
1313 NULL);
1314
1315 /* input buffer no longer used */
1316 pfree(buf.data);
1317
1318 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
1319 {
1320 /*
1321 * Negotiation generated data to be sent to the client.
1322 */
1323 elog(DEBUG4, "sending SSPI response token of length %u",
1324 (unsigned int) outbuf.pBuffers[0].cbBuffer);
1325
1326 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
1327 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
1328
1330 port->gss->outbuf.value, port->gss->outbuf.length);
1331
1332 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
1333 }
1334
1335 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
1336 {
1337 if (sspictx != NULL)
1338 {
1340 free(sspictx);
1341 }
1344 _("could not accept SSPI security context"), r);
1345 }
1346
1347 /*
1348 * Overwrite the current context with the one we just received. If
1349 * sspictx is NULL it was the first loop and we need to allocate a
1350 * buffer for it. On subsequent runs, we can just overwrite the buffer
1351 * contents since the size does not change.
1352 */
1353 if (sspictx == NULL)
1354 {
1355 sspictx = malloc(sizeof(CtxtHandle));
1356 if (sspictx == NULL)
1357 ereport(ERROR,
1358 (errmsg("out of memory")));
1359 }
1360
1361 memcpy(sspictx, &newctx, sizeof(CtxtHandle));
1362
1363 if (r == SEC_I_CONTINUE_NEEDED)
1364 elog(DEBUG4, "SSPI continue needed");
1365
1366 } while (r == SEC_I_CONTINUE_NEEDED);
1367
1368
1369 /*
1370 * Release service principal credentials
1371 */
1373
1374
1375 /*
1376 * SEC_E_OK indicates that authentication is now complete.
1377 *
1378 * Get the name of the user that authenticated, and compare it to the pg
1379 * username that was specified for the connection.
1380 */
1381
1383 if (r != SEC_E_OK)
1385 _("could not get token from SSPI security context"), r);
1386
1387 /*
1388 * No longer need the security context, everything from here on uses the
1389 * token instead.
1390 */
1392 free(sspictx);
1393
1394 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
1395 ereport(ERROR,
1396 (errmsg_internal("could not get token information buffer size: error code %lu",
1397 GetLastError())));
1398
1400 if (tokenuser == NULL)
1401 ereport(ERROR,
1402 (errmsg("out of memory")));
1403
1405 ereport(ERROR,
1406 (errmsg_internal("could not get token information: error code %lu",
1407 GetLastError())));
1408
1410
1412 domainname, &domainnamesize, &accountnameuse))
1413 ereport(ERROR,
1414 (errmsg_internal("could not look up account SID: error code %lu",
1415 GetLastError())));
1416
1417 free(tokenuser);
1418
1419 if (!port->hba->compat_realm)
1420 {
1421 int status = pg_SSPI_make_upn(accountname, sizeof(accountname),
1422 domainname, sizeof(domainname),
1423 port->hba->upn_username);
1424
1425 if (status != STATUS_OK)
1426 /* Error already reported from pg_SSPI_make_upn */
1427 return status;
1428 }
1429
1430 /*
1431 * We have all of the information necessary to construct the authenticated
1432 * identity. Set it now, rather than waiting for check_usermap below,
1433 * because authentication has already succeeded and we want the log file
1434 * to reflect that.
1435 */
1436 if (port->hba->compat_realm)
1437 {
1438 /* SAM-compatible format. */
1439 authn_id = psprintf("%s\\%s", domainname, accountname);
1440 }
1441 else
1442 {
1443 /* Kerberos principal format. */
1444 authn_id = psprintf("%s@%s", accountname, domainname);
1445 }
1446
1448 pfree(authn_id);
1449
1450 /*
1451 * Compare realm/domain if requested. In SSPI, always compare case
1452 * insensitive.
1453 */
1454 if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1455 {
1456 if (pg_strcasecmp(port->hba->krb_realm, domainname) != 0)
1457 {
1458 elog(DEBUG2,
1459 "SSPI domain (%s) and configured domain (%s) don't match",
1460 domainname, port->hba->krb_realm);
1461
1462 return STATUS_ERROR;
1463 }
1464 }
1465
1466 /*
1467 * We have the username (without domain/realm) in accountname, compare to
1468 * the supplied value. In SSPI, always compare case insensitive.
1469 *
1470 * If set to include realm, append it in <username>@<realm> format.
1471 */
1472 if (port->hba->include_realm)
1473 {
1474 char *namebuf;
1475 int retval;
1476
1477 namebuf = psprintf("%s@%s", accountname, domainname);
1478 retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
1479 pfree(namebuf);
1480 return retval;
1481 }
1482 else
1483 return check_usermap(port->hba->usermap, port->user_name, accountname, true);
1484}
1485
1486/*
1487 * Replaces the domainname with the Kerberos realm name,
1488 * and optionally the accountname with the Kerberos user name.
1489 */
1490static int
1492 size_t accountnamesize,
1493 char *domainname,
1494 size_t domainnamesize,
1495 bool update_accountname)
1496{
1497 char *samname;
1498 char *upname = NULL;
1499 char *p = NULL;
1500 ULONG upnamesize = 0;
1501 size_t upnamerealmsize;
1502 BOOLEAN res;
1503
1504 /*
1505 * Build SAM name (DOMAIN\user), then translate to UPN
1506 * (user@kerberos.realm). The realm name is returned in lower case, but
1507 * that is fine because in SSPI auth, string comparisons are always
1508 * case-insensitive.
1509 */
1510
1511 samname = psprintf("%s\\%s", domainname, accountname);
1513 NULL, &upnamesize);
1514
1515 if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1516 || upnamesize == 0)
1517 {
1518 pfree(samname);
1519 ereport(LOG,
1521 errmsg("could not translate name")));
1522 return STATUS_ERROR;
1523 }
1524
1525 /* upnamesize includes the terminating NUL. */
1527
1529 upname, &upnamesize);
1530
1531 pfree(samname);
1532 if (res)
1533 p = strchr(upname, '@');
1534
1535 if (!res || p == NULL)
1536 {
1537 pfree(upname);
1538 ereport(LOG,
1540 errmsg("could not translate name")));
1541 return STATUS_ERROR;
1542 }
1543
1544 /* Length of realm name after the '@', including the NUL. */
1545 upnamerealmsize = upnamesize - (p - upname + 1);
1546
1547 /* Replace domainname with realm name. */
1549 {
1550 pfree(upname);
1551 ereport(LOG,
1553 errmsg("realm name too long")));
1554 return STATUS_ERROR;
1555 }
1556
1557 /* Length is now safe. */
1558 strcpy(domainname, p + 1);
1559
1560 /* Replace account name as well (in case UPN != SAM)? */
1562 {
1563 if ((p - upname + 1) > accountnamesize)
1564 {
1565 pfree(upname);
1566 ereport(LOG,
1568 errmsg("translated account name too long")));
1569 return STATUS_ERROR;
1570 }
1571
1572 *p = 0;
1574 }
1575
1576 pfree(upname);
1577 return STATUS_OK;
1578}
1579#endif /* ENABLE_SSPI */
1580
1581
1582
1583/*----------------------------------------------------------------
1584 * Ident authentication system
1585 *----------------------------------------------------------------
1586 */
1587
1588/*
1589 * Per RFC 1413, space and tab are whitespace in ident messages.
1590 */
1591static bool
1593{
1594 return c == ' ' || c == '\t';
1595}
1596
1597/*
1598 * Parse the string "*ident_response" as a response from a query to an Ident
1599 * server. If it's a normal response indicating a user name, return true
1600 * and store the user name at *ident_user. If it's anything else,
1601 * return false.
1602 */
1603static bool
1605 char *ident_user)
1606{
1607 const char *cursor = ident_response; /* Cursor into *ident_response */
1608
1609 /*
1610 * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1611 */
1612 if (strlen(ident_response) < 2)
1613 return false;
1614 else if (ident_response[strlen(ident_response) - 2] != '\r')
1615 return false;
1616 else
1617 {
1618 while (*cursor != ':' && *cursor != '\r')
1619 cursor++; /* skip port field */
1620
1621 if (*cursor != ':')
1622 return false;
1623 else
1624 {
1625 /* We're positioned to colon before response type field */
1626 char response_type[80];
1627 int i; /* Index into *response_type */
1628
1629 cursor++; /* Go over colon */
1630 while (is_ident_whitespace(*cursor))
1631 cursor++; /* skip blanks */
1632 i = 0;
1633 while (*cursor != ':' && *cursor != '\r' && !is_ident_whitespace(*cursor) &&
1634 i < (int) (sizeof(response_type) - 1))
1635 response_type[i++] = *cursor++;
1636 response_type[i] = '\0';
1637 while (is_ident_whitespace(*cursor))
1638 cursor++; /* skip blanks */
1639 if (strcmp(response_type, "USERID") != 0)
1640 return false;
1641 else
1642 {
1643 /*
1644 * It's a USERID response. Good. "cursor" should be pointing
1645 * to the colon that precedes the operating system type.
1646 */
1647 if (*cursor != ':')
1648 return false;
1649 else
1650 {
1651 cursor++; /* Go over colon */
1652 /* Skip over operating system field. */
1653 while (*cursor != ':' && *cursor != '\r')
1654 cursor++;
1655 if (*cursor != ':')
1656 return false;
1657 else
1658 {
1659 cursor++; /* Go over colon */
1660 while (is_ident_whitespace(*cursor))
1661 cursor++; /* skip blanks */
1662 /* Rest of line is user name. Copy it over. */
1663 i = 0;
1664 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1665 ident_user[i++] = *cursor++;
1666 ident_user[i] = '\0';
1667 return true;
1668 }
1669 }
1670 }
1671 }
1672 }
1673}
1674
1675
1676/*
1677 * Talk to the ident server on "remote_addr" and find out who
1678 * owns the tcp connection to "local_addr"
1679 * If the username is successfully retrieved, check the usermap.
1680 *
1681 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if the
1682 * latch was set would improve the responsiveness to timeouts/cancellations.
1683 */
1684static int
1686{
1687 const SockAddr remote_addr = port->raddr;
1688 const SockAddr local_addr = port->laddr;
1690 pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1691 int rc; /* Return code from a locally called function */
1692 bool ident_return;
1694 char remote_port[NI_MAXSERV];
1696 char local_port[NI_MAXSERV];
1697 char ident_port[NI_MAXSERV];
1698 char ident_query[80];
1700 struct addrinfo *ident_serv = NULL,
1701 *la = NULL,
1702 hints;
1703
1704 /*
1705 * Might look a little weird to first convert it to text and then back to
1706 * sockaddr, but it's protocol independent.
1707 */
1710 remote_port, sizeof(remote_port),
1713 local_addr_s, sizeof(local_addr_s),
1714 local_port, sizeof(local_port),
1716
1717 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1718 hints.ai_flags = AI_NUMERICHOST;
1719 hints.ai_family = remote_addr.addr.ss_family;
1720 hints.ai_socktype = SOCK_STREAM;
1721 hints.ai_protocol = 0;
1722 hints.ai_addrlen = 0;
1723 hints.ai_canonname = NULL;
1724 hints.ai_addr = NULL;
1725 hints.ai_next = NULL;
1727 if (rc || !ident_serv)
1728 {
1729 /* we don't expect this to happen */
1730 ident_return = false;
1731 goto ident_inet_done;
1732 }
1733
1734 hints.ai_flags = AI_NUMERICHOST;
1735 hints.ai_family = local_addr.addr.ss_family;
1736 hints.ai_socktype = SOCK_STREAM;
1737 hints.ai_protocol = 0;
1738 hints.ai_addrlen = 0;
1739 hints.ai_canonname = NULL;
1740 hints.ai_addr = NULL;
1741 hints.ai_next = NULL;
1743 if (rc || !la)
1744 {
1745 /* we don't expect this to happen */
1746 ident_return = false;
1747 goto ident_inet_done;
1748 }
1749
1750 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1751 ident_serv->ai_protocol);
1753 {
1754 ereport(LOG,
1756 errmsg("could not create socket for Ident connection: %m")));
1757 ident_return = false;
1758 goto ident_inet_done;
1759 }
1760
1761 /*
1762 * Bind to the address which the client originally contacted, otherwise
1763 * the ident server won't be able to match up the right connection. This
1764 * is necessary if the PostgreSQL server is running on an IP alias.
1765 */
1766 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1767 if (rc != 0)
1768 {
1769 ereport(LOG,
1771 errmsg("could not bind to local address \"%s\": %m",
1772 local_addr_s)));
1773 ident_return = false;
1774 goto ident_inet_done;
1775 }
1776
1777 rc = connect(sock_fd, ident_serv->ai_addr,
1778 ident_serv->ai_addrlen);
1779 if (rc != 0)
1780 {
1781 ereport(LOG,
1783 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1785 ident_return = false;
1786 goto ident_inet_done;
1787 }
1788
1789 /* The query we send to the Ident server */
1790 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1791 remote_port, local_port);
1792
1793 /* loop in case send is interrupted */
1794 do
1795 {
1797
1799 } while (rc < 0 && errno == EINTR);
1800
1801 if (rc < 0)
1802 {
1803 ereport(LOG,
1805 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1807 ident_return = false;
1808 goto ident_inet_done;
1809 }
1810
1811 do
1812 {
1814
1815 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1816 } while (rc < 0 && errno == EINTR);
1817
1818 if (rc < 0)
1819 {
1820 ereport(LOG,
1822 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1824 ident_return = false;
1825 goto ident_inet_done;
1826 }
1827
1828 ident_response[rc] = '\0';
1830 if (!ident_return)
1831 ereport(LOG,
1832 (errmsg("invalidly formatted response from Ident server: \"%s\"",
1833 ident_response)));
1834
1838 if (ident_serv)
1840 if (la)
1841 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1842
1843 if (ident_return)
1844 {
1845 /*
1846 * Success! Store the identity, then check the usermap. Note that
1847 * setting the authenticated identity is done before checking the
1848 * usermap, because at this point authentication has succeeded.
1849 */
1851 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1852 }
1853 return STATUS_ERROR;
1854}
1855
1856
1857/*----------------------------------------------------------------
1858 * Peer authentication system
1859 *----------------------------------------------------------------
1860 */
1861
1862/*
1863 * Ask kernel about the credentials of the connecting process,
1864 * determine the symbolic name of the corresponding user, and check
1865 * if valid per the usermap.
1866 *
1867 * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
1868 */
1869static int
1871{
1872 uid_t uid;
1873 gid_t gid;
1874#ifndef WIN32
1875 struct passwd pwbuf;
1876 struct passwd *pw;
1877 char buf[1024];
1878 int rc;
1879 int ret;
1880#endif
1881
1882 if (getpeereid(port->sock, &uid, &gid) != 0)
1883 {
1884 /* Provide special error message if getpeereid is a stub */
1885 if (errno == ENOSYS)
1886 ereport(LOG,
1888 errmsg("peer authentication is not supported on this platform")));
1889 else
1890 ereport(LOG,
1892 errmsg("could not get peer credentials: %m")));
1893 return STATUS_ERROR;
1894 }
1895
1896#ifndef WIN32
1897 rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1898 if (rc != 0)
1899 {
1900 errno = rc;
1901 ereport(LOG,
1902 errmsg("could not look up local user ID %ld: %m", (long) uid));
1903 return STATUS_ERROR;
1904 }
1905 else if (!pw)
1906 {
1907 ereport(LOG,
1908 errmsg("local user with ID %ld does not exist", (long) uid));
1909 return STATUS_ERROR;
1910 }
1911
1912 /*
1913 * Make a copy of static getpw*() result area; this is our authenticated
1914 * identity. Set it before calling check_usermap, because authentication
1915 * has already succeeded and we want the log file to reflect that.
1916 */
1917 set_authn_id(port, pw->pw_name);
1918
1919 ret = check_usermap(port->hba->usermap, port->user_name,
1921
1922 return ret;
1923#else
1924 /* should have failed with ENOSYS above */
1925 Assert(false);
1926 return STATUS_ERROR;
1927#endif
1928}
1929
1930
1931/*----------------------------------------------------------------
1932 * PAM authentication system
1933 *----------------------------------------------------------------
1934 */
1935#ifdef USE_PAM
1936
1937/*
1938 * PAM conversation function
1939 */
1940
1941static int
1943 struct pam_response **resp, void *appdata_ptr)
1944{
1945 const char *passwd;
1946 struct pam_response *reply;
1947 int i;
1948
1949 if (appdata_ptr)
1950 passwd = (char *) appdata_ptr;
1951 else
1952 {
1953 /*
1954 * Workaround for Solaris 2.6 where the PAM library is broken and does
1955 * not pass appdata_ptr to the conversation routine
1956 */
1958 }
1959
1960 *resp = NULL; /* in case of error exit */
1961
1963 return PAM_CONV_ERR;
1964
1965 /*
1966 * Explicitly not using palloc here - PAM will free this memory in
1967 * pam_end()
1968 */
1969 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
1970 {
1971 ereport(LOG,
1973 errmsg("out of memory")));
1974 return PAM_CONV_ERR;
1975 }
1976
1977 for (i = 0; i < num_msg; i++)
1978 {
1979 switch (msg[i]->msg_style)
1980 {
1982 if (strlen(passwd) == 0)
1983 {
1984 /*
1985 * Password wasn't passed to PAM the first time around -
1986 * let's go ask the client to send a password, which we
1987 * then stuff into PAM.
1988 */
1991 if (passwd == NULL)
1992 {
1993 /*
1994 * Client didn't want to send password. We
1995 * intentionally do not log anything about this,
1996 * either here or at higher levels.
1997 */
1998 pam_no_password = true;
1999 goto fail;
2000 }
2001 }
2002 if ((reply[i].resp = strdup(passwd)) == NULL)
2003 goto fail;
2004 reply[i].resp_retcode = PAM_SUCCESS;
2005 break;
2006 case PAM_ERROR_MSG:
2007 ereport(LOG,
2008 (errmsg("error from underlying PAM layer: %s",
2009 msg[i]->msg)));
2011 case PAM_TEXT_INFO:
2012 /* we don't bother to log TEXT_INFO messages */
2013 if ((reply[i].resp = strdup("")) == NULL)
2014 goto fail;
2015 reply[i].resp_retcode = PAM_SUCCESS;
2016 break;
2017 default:
2018 ereport(LOG,
2019 (errmsg("unsupported PAM conversation %d/\"%s\"",
2020 msg[i]->msg_style,
2021 msg[i]->msg ? msg[i]->msg : "(none)")));
2022 goto fail;
2023 }
2024 }
2025
2026 *resp = reply;
2027 return PAM_SUCCESS;
2028
2029fail:
2030 /* free up whatever we allocated */
2031 for (i = 0; i < num_msg; i++)
2032 free(reply[i].resp);
2033 free(reply);
2034
2035 return PAM_CONV_ERR;
2036}
2037
2038
2039/*
2040 * Check authentication against PAM.
2041 */
2042static int
2043CheckPAMAuth(Port *port, const char *user, const char *password)
2044{
2045 int retval;
2047
2048 /*
2049 * We can't entirely rely on PAM to pass through appdata --- it appears
2050 * not to work on at least Solaris 2.6. So use these ugly static
2051 * variables instead.
2052 */
2055 pam_no_password = false;
2056
2057 /*
2058 * Set the application data portion of the conversation struct. This is
2059 * later used inside the PAM conversation to pass the password to the
2060 * authentication module.
2061 */
2062 pam_passw_conv.appdata_ptr = unconstify(char *, password); /* from password above,
2063 * not allocated */
2064
2065 /* Optionally, one can set the service name in pg_hba.conf */
2066 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
2067 retval = pam_start(port->hba->pamservice, "pgsql@",
2068 &pam_passw_conv, &pamh);
2069 else
2070 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
2071 &pam_passw_conv, &pamh);
2072
2073 if (retval != PAM_SUCCESS)
2074 {
2075 ereport(LOG,
2076 (errmsg("could not create PAM authenticator: %s",
2077 pam_strerror(pamh, retval))));
2078 pam_passwd = NULL; /* Unset pam_passwd */
2079 return STATUS_ERROR;
2080 }
2081
2082 retval = pam_set_item(pamh, PAM_USER, user);
2083
2084 if (retval != PAM_SUCCESS)
2085 {
2086 ereport(LOG,
2087 (errmsg("pam_set_item(PAM_USER) failed: %s",
2088 pam_strerror(pamh, retval))));
2089 pam_passwd = NULL; /* Unset pam_passwd */
2090 return STATUS_ERROR;
2091 }
2092
2093 if (port->hba->conntype != ctLocal)
2094 {
2095 char hostinfo[NI_MAXHOST];
2096 int flags;
2097
2098 if (port->hba->pam_use_hostname)
2099 flags = 0;
2100 else
2102
2103 retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
2104 hostinfo, sizeof(hostinfo), NULL, 0,
2105 flags);
2106 if (retval != 0)
2107 {
2109 (errmsg_internal("pg_getnameinfo_all() failed: %s",
2110 gai_strerror(retval))));
2111 return STATUS_ERROR;
2112 }
2113
2114 retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
2115
2116 if (retval != PAM_SUCCESS)
2117 {
2118 ereport(LOG,
2119 (errmsg("pam_set_item(PAM_RHOST) failed: %s",
2120 pam_strerror(pamh, retval))));
2121 pam_passwd = NULL;
2122 return STATUS_ERROR;
2123 }
2124 }
2125
2127
2128 if (retval != PAM_SUCCESS)
2129 {
2130 ereport(LOG,
2131 (errmsg("pam_set_item(PAM_CONV) failed: %s",
2132 pam_strerror(pamh, retval))));
2133 pam_passwd = NULL; /* Unset pam_passwd */
2134 return STATUS_ERROR;
2135 }
2136
2137 retval = pam_authenticate(pamh, 0);
2138
2139 if (retval != PAM_SUCCESS)
2140 {
2141 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2142 if (!pam_no_password)
2143 ereport(LOG,
2144 (errmsg("pam_authenticate failed: %s",
2145 pam_strerror(pamh, retval))));
2146 pam_passwd = NULL; /* Unset pam_passwd */
2148 }
2149
2150 retval = pam_acct_mgmt(pamh, 0);
2151
2152 if (retval != PAM_SUCCESS)
2153 {
2154 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2155 if (!pam_no_password)
2156 ereport(LOG,
2157 (errmsg("pam_acct_mgmt failed: %s",
2158 pam_strerror(pamh, retval))));
2159 pam_passwd = NULL; /* Unset pam_passwd */
2161 }
2162
2163 retval = pam_end(pamh, retval);
2164
2165 if (retval != PAM_SUCCESS)
2166 {
2167 ereport(LOG,
2168 (errmsg("could not release PAM authenticator: %s",
2169 pam_strerror(pamh, retval))));
2170 }
2171
2172 pam_passwd = NULL; /* Unset pam_passwd */
2173
2174 if (retval == PAM_SUCCESS)
2176
2177 return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
2178}
2179#endif /* USE_PAM */
2180
2181
2182/*----------------------------------------------------------------
2183 * BSD authentication system
2184 *----------------------------------------------------------------
2185 */
2186#ifdef USE_BSD_AUTH
2187static int
2188CheckBSDAuth(Port *port, char *user)
2189{
2190 char *passwd;
2191 int retval;
2192
2193 /* Send regular password request to client, and get the response */
2195
2197 if (passwd == NULL)
2198 return STATUS_EOF;
2199
2200 /*
2201 * Ask the BSD auth system to verify password. Note that auth_userokay
2202 * will overwrite the password string with zeroes, but it's just a
2203 * temporary string so we don't care.
2204 */
2205 retval = auth_userokay(user, NULL, "auth-postgresql", passwd);
2206
2207 pfree(passwd);
2208
2209 if (!retval)
2210 return STATUS_ERROR;
2211
2213 return STATUS_OK;
2214}
2215#endif /* USE_BSD_AUTH */
2216
2217
2218/*----------------------------------------------------------------
2219 * LDAP authentication system
2220 *----------------------------------------------------------------
2221 */
2222#ifdef USE_LDAP
2223
2224static int errdetail_for_ldap(LDAP *ldap);
2225
2226/*
2227 * Initialize a connection to the LDAP server, including setting up
2228 * TLS if requested.
2229 */
2230static int
2232{
2233 const char *scheme;
2235 int r;
2236
2237 scheme = port->hba->ldapscheme;
2238 if (scheme == NULL)
2239 scheme = "ldap";
2240#ifdef WIN32
2241 if (strcmp(scheme, "ldaps") == 0)
2242 *ldap = ldap_sslinit(port->hba->ldapserver, port->hba->ldapport, 1);
2243 else
2244 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2245 if (!*ldap)
2246 {
2247 ereport(LOG,
2248 (errmsg("could not initialize LDAP: error code %lu",
2249 LdapGetLastError())));
2250
2251 return STATUS_ERROR;
2252 }
2253#else
2254#ifdef HAVE_LDAP_INITIALIZE
2255
2256 /*
2257 * OpenLDAP provides a non-standard extension ldap_initialize() that takes
2258 * a list of URIs, allowing us to request "ldaps" instead of "ldap". It
2259 * also provides ldap_domain2hostlist() to find LDAP servers automatically
2260 * using DNS SRV. They were introduced in the same version, so for now we
2261 * don't have an extra configure check for the latter.
2262 */
2263 {
2265 char *hostlist = NULL;
2266 char *p;
2267 bool append_port;
2268
2269 /* We'll build a space-separated scheme://hostname:port list here */
2271
2272 /*
2273 * If pg_hba.conf provided no hostnames, we can ask OpenLDAP to try to
2274 * find some by extracting a domain name from the base DN and looking
2275 * up DSN SRV records for _ldap._tcp.<domain>.
2276 */
2277 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2278 {
2279 char *domain;
2280
2281 /* ou=blah,dc=foo,dc=bar -> foo.bar */
2282 if (ldap_dn2domain(port->hba->ldapbasedn, &domain))
2283 {
2284 ereport(LOG,
2285 (errmsg("could not extract domain name from ldapbasedn")));
2286 return STATUS_ERROR;
2287 }
2288
2289 /* Look up a list of LDAP server hosts and port numbers */
2290 if (ldap_domain2hostlist(domain, &hostlist))
2291 {
2292 ereport(LOG,
2293 (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
2294 domain),
2295 (errhint("Set an LDAP server name explicitly."))));
2296 ldap_memfree(domain);
2297 return STATUS_ERROR;
2298 }
2299 ldap_memfree(domain);
2300
2301 /* We have a space-separated list of host:port entries */
2302 p = hostlist;
2303 append_port = false;
2304 }
2305 else
2306 {
2307 /* We have a space-separated list of hosts from pg_hba.conf */
2308 p = port->hba->ldapserver;
2309 append_port = true;
2310 }
2311
2312 /* Convert the list of host[:port] entries to full URIs */
2313 do
2314 {
2315 size_t size;
2316
2317 /* Find the span of the next entry */
2318 size = strcspn(p, " ");
2319
2320 /* Append a space separator if this isn't the first URI */
2321 if (uris.len > 0)
2323
2324 /* Append scheme://host:port */
2327 appendBinaryStringInfo(&uris, p, size);
2328 if (append_port)
2329 appendStringInfo(&uris, ":%d", port->hba->ldapport);
2330
2331 /* Step over this entry and any number of trailing spaces */
2332 p += size;
2333 while (*p == ' ')
2334 ++p;
2335 } while (*p);
2336
2337 /* Free memory from OpenLDAP if we looked up SRV records */
2338 if (hostlist)
2340
2341 /* Finally, try to connect using the URI list */
2342 r = ldap_initialize(ldap, uris.data);
2343 pfree(uris.data);
2344 if (r != LDAP_SUCCESS)
2345 {
2346 ereport(LOG,
2347 (errmsg("could not initialize LDAP: %s",
2348 ldap_err2string(r))));
2349
2350 return STATUS_ERROR;
2351 }
2352 }
2353#else
2354 if (strcmp(scheme, "ldaps") == 0)
2355 {
2356 ereport(LOG,
2357 (errmsg("ldaps not supported with this LDAP library")));
2358
2359 return STATUS_ERROR;
2360 }
2361 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2362 if (!*ldap)
2363 {
2364 ereport(LOG,
2365 (errmsg("could not initialize LDAP: %m")));
2366
2367 return STATUS_ERROR;
2368 }
2369#endif
2370#endif
2371
2373 {
2374 ereport(LOG,
2375 (errmsg("could not set LDAP protocol version: %s",
2376 ldap_err2string(r)),
2378 ldap_unbind(*ldap);
2379 return STATUS_ERROR;
2380 }
2381
2382 if (port->hba->ldaptls)
2383 {
2384#ifndef WIN32
2385 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
2386#else
2387 if ((r = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
2388#endif
2389 {
2390 ereport(LOG,
2391 (errmsg("could not start LDAP TLS session: %s",
2392 ldap_err2string(r)),
2394 ldap_unbind(*ldap);
2395 return STATUS_ERROR;
2396 }
2397 }
2398
2399 return STATUS_OK;
2400}
2401
2402/* Placeholders recognized by FormatSearchFilter. For now just one. */
2403#define LPH_USERNAME "$username"
2404#define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
2405
2406/* Not all LDAP implementations define this. */
2407#ifndef LDAP_NO_ATTRS
2408#define LDAP_NO_ATTRS "1.1"
2409#endif
2410
2411/* Not all LDAP implementations define this. */
2412#ifndef LDAPS_PORT
2413#define LDAPS_PORT 636
2414#endif
2415
2416static char *
2418{
2419 return input;
2420}
2421
2422/*
2423 * Return a newly allocated C string copied from "pattern" with all
2424 * occurrences of the placeholder "$username" replaced with "user_name".
2425 */
2426static char *
2427FormatSearchFilter(const char *pattern, const char *user_name)
2428{
2430
2432 while (*pattern != '\0')
2433 {
2434 if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)
2435 {
2436 appendStringInfoString(&output, user_name);
2437 pattern += LPH_USERNAME_LEN;
2438 }
2439 else
2440 appendStringInfoChar(&output, *pattern++);
2441 }
2442
2443 return output.data;
2444}
2445
2446/*
2447 * Perform LDAP authentication
2448 */
2449static int
2451{
2452 char *passwd;
2453 LDAP *ldap;
2454 int r;
2455 char *fulluser;
2456 const char *server_name;
2457
2458#ifdef HAVE_LDAP_INITIALIZE
2459
2460 /*
2461 * For OpenLDAP, allow empty hostname if we have a basedn. We'll look for
2462 * servers with DNS SRV records via OpenLDAP library facilities.
2463 */
2464 if ((!port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
2465 (!port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
2466 {
2467 ereport(LOG,
2468 (errmsg("LDAP server not specified, and no ldapbasedn")));
2469 return STATUS_ERROR;
2470 }
2471#else
2472 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2473 {
2474 ereport(LOG,
2475 (errmsg("LDAP server not specified")));
2476 return STATUS_ERROR;
2477 }
2478#endif
2479
2480 /*
2481 * If we're using SRV records, we don't have a server name so we'll just
2482 * show an empty string in error messages.
2483 */
2484 server_name = port->hba->ldapserver ? port->hba->ldapserver : "";
2485
2486 if (port->hba->ldapport == 0)
2487 {
2488 if (port->hba->ldapscheme != NULL &&
2489 strcmp(port->hba->ldapscheme, "ldaps") == 0)
2490 port->hba->ldapport = LDAPS_PORT;
2491 else
2492 port->hba->ldapport = LDAP_PORT;
2493 }
2494
2496
2498 if (passwd == NULL)
2499 return STATUS_EOF; /* client wouldn't send password */
2500
2502 {
2503 /* Error message already sent */
2504 pfree(passwd);
2505 return STATUS_ERROR;
2506 }
2507
2508 if (port->hba->ldapbasedn)
2509 {
2510 /*
2511 * First perform an LDAP search to find the DN for the user we are
2512 * trying to log in as.
2513 */
2514 char *filter;
2516 LDAPMessage *entry;
2517 char *attributes[] = {LDAP_NO_ATTRS, NULL};
2518 char *dn;
2519 char *c;
2520 int count;
2521
2522 /*
2523 * Disallow any characters that we would otherwise need to escape,
2524 * since they aren't really reasonable in a username anyway. Allowing
2525 * them would make it possible to inject any kind of custom filters in
2526 * the LDAP filter.
2527 */
2528 for (c = port->user_name; *c; c++)
2529 {
2530 if (*c == '*' ||
2531 *c == '(' ||
2532 *c == ')' ||
2533 *c == '\\' ||
2534 *c == '/')
2535 {
2536 ereport(LOG,
2537 (errmsg("invalid character in user name for LDAP authentication")));
2539 pfree(passwd);
2540 return STATUS_ERROR;
2541 }
2542 }
2543
2544 /*
2545 * Bind with a pre-defined username/password (if available) for
2546 * searching. If none is specified, this turns into an anonymous bind.
2547 */
2549 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2550 port->hba->ldapbindpasswd ? ldap_password_hook(port->hba->ldapbindpasswd) : "");
2551 if (r != LDAP_SUCCESS)
2552 {
2553 ereport(LOG,
2554 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",
2555 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2556 server_name,
2557 ldap_err2string(r)),
2560 pfree(passwd);
2561 return STATUS_ERROR;
2562 }
2563
2564 /* Build a custom filter or a single attribute filter? */
2565 if (port->hba->ldapsearchfilter)
2566 filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);
2567 else if (port->hba->ldapsearchattribute)
2568 filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);
2569 else
2570 filter = psprintf("(uid=%s)", port->user_name);
2571
2573 r = ldap_search_s(ldap,
2574 port->hba->ldapbasedn,
2575 port->hba->ldapscope,
2576 filter,
2577 attributes,
2578 0,
2580
2581 if (r != LDAP_SUCCESS)
2582 {
2583 ereport(LOG,
2584 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
2585 filter, server_name, ldap_err2string(r)),
2587 if (search_message != NULL)
2590 pfree(passwd);
2591 pfree(filter);
2592 return STATUS_ERROR;
2593 }
2594
2596 if (count != 1)
2597 {
2598 if (count == 0)
2599 ereport(LOG,
2600 (errmsg("LDAP user \"%s\" does not exist", port->user_name),
2601 errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
2602 filter, server_name)));
2603 else
2604 ereport(LOG,
2605 (errmsg("LDAP user \"%s\" is not unique", port->user_name),
2606 errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",
2607 "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
2608 count,
2609 filter, server_name, count)));
2610
2612 pfree(passwd);
2613 pfree(filter);
2615 return STATUS_ERROR;
2616 }
2617
2619 dn = ldap_get_dn(ldap, entry);
2620 if (dn == NULL)
2621 {
2622 int error;
2623
2625 ereport(LOG,
2626 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
2627 filter, server_name,
2631 pfree(passwd);
2632 pfree(filter);
2634 return STATUS_ERROR;
2635 }
2636 fulluser = pstrdup(dn);
2637
2638 pfree(filter);
2641 }
2642 else
2643 fulluser = psprintf("%s%s%s",
2644 port->hba->ldapprefix ? port->hba->ldapprefix : "",
2645 port->user_name,
2646 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
2647
2649
2650 if (r != LDAP_SUCCESS)
2651 {
2652 ereport(LOG,
2653 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
2654 fulluser, server_name, ldap_err2string(r)),
2657 pfree(passwd);
2658 pfree(fulluser);
2659 return STATUS_ERROR;
2660 }
2661
2662 /* Save the original bind DN as the authenticated identity. */
2664
2666 pfree(passwd);
2667 pfree(fulluser);
2668
2669 return STATUS_OK;
2670}
2671
2672/*
2673 * Add a detail error message text to the current error if one can be
2674 * constructed from the LDAP 'diagnostic message'.
2675 */
2676static int
2678{
2679 char *message;
2680 int rc;
2681
2683 if (rc == LDAP_SUCCESS && message != NULL)
2684 {
2685 errdetail("LDAP diagnostics: %s", message);
2686 ldap_memfree(message);
2687 }
2688
2689 return 0;
2690}
2691
2692#endif /* USE_LDAP */
2693
2694
2695/*----------------------------------------------------------------
2696 * SSL client certificate authentication
2697 *----------------------------------------------------------------
2698 */
2699#ifdef USE_SSL
2700static int
2702{
2704 char *peer_username = NULL;
2705
2706 Assert(port->ssl);
2707
2708 /* select the correct field to compare */
2709 switch (port->hba->clientcertname)
2710 {
2711 case clientCertDN:
2712 peer_username = port->peer_dn;
2713 break;
2714 case clientCertCN:
2715 peer_username = port->peer_cn;
2716 }
2717
2718 /* Make sure we have received a username in the certificate */
2719 if (peer_username == NULL ||
2720 strlen(peer_username) <= 0)
2721 {
2722 ereport(LOG,
2723 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
2724 port->user_name)));
2725 return STATUS_ERROR;
2726 }
2727
2728 if (port->hba->auth_method == uaCert)
2729 {
2730 /*
2731 * For cert auth, the client's Subject DN is always our authenticated
2732 * identity, even if we're only using its CN for authorization. Set
2733 * it now, rather than waiting for check_usermap() below, because
2734 * authentication has already succeeded and we want the log file to
2735 * reflect that.
2736 */
2737 if (!port->peer_dn)
2738 {
2739 /*
2740 * This should not happen as both peer_dn and peer_cn should be
2741 * set in this context.
2742 */
2743 ereport(LOG,
2744 (errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",
2745 port->user_name)));
2746 return STATUS_ERROR;
2747 }
2748
2749 set_authn_id(port, port->peer_dn);
2750 }
2751
2752 /* Just pass the certificate cn/dn to the usermap check */
2753 status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);
2755 {
2756 /*
2757 * If clientcert=verify-full was specified and the authentication
2758 * method is other than uaCert, log the reason for rejecting the
2759 * authentication.
2760 */
2761 if (port->hba->clientcert == clientCertFull && port->hba->auth_method != uaCert)
2762 {
2763 switch (port->hba->clientcertname)
2764 {
2765 case clientCertDN:
2766 ereport(LOG,
2767 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
2768 port->user_name)));
2769 break;
2770 case clientCertCN:
2771 ereport(LOG,
2772 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
2773 port->user_name)));
2774 }
2775 }
2776 }
2777 return status_check_usermap;
2778}
2779#endif
const pg_be_sasl_mech pg_be_oauth_mech
Definition auth-oauth.c:54
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
void sendAuthRequest(Port *port, AuthRequest areq, const void *extradata, int extralen)
Definition auth.c:682
static int CheckPWChallengeAuth(Port *port, const char **logdetail)
Definition auth.c:828
static int auth_peer(Port *port)
Definition auth.c:1870
static void auth_failed(Port *port, int elevel, int status, const char *logdetail)
Definition auth.c:234
char * pg_krb_server_keyfile
Definition auth.c:174
#define IDENT_USERNAME_MAX
Definition auth.c:69
bool pg_krb_caseins_users
Definition auth.c:175
static char * recv_password_packet(Port *port)
Definition auth.c:712
bool pg_gss_accept_delegation
Definition auth.c:176
ClientAuthentication_hook_type ClientAuthentication_hook
Definition auth.c:217
#define IDENT_PORT
Definition auth.c:72
void ClientAuthentication(Port *port)
Definition auth.c:374
static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
Definition auth.c:888
void set_authn_id(Port *port, const char *id)
Definition auth.c:336
static bool is_ident_whitespace(const char c)
Definition auth.c:1592
static int ident_inet(Port *port)
Definition auth.c:1685
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition auth.c:1604
#define HOSTNAME_LOOKUP_DETAIL(port)
static int CheckPasswordAuth(Port *port, const char **logdetail)
Definition auth.c:793
PGDLLIMPORT auth_password_hook_typ ldap_password_hook
void(* ClientAuthentication_hook_type)(Port *, int)
Definition auth.h:45
char *(* auth_password_hook_typ)(char *input)
Definition auth.h:49
#define PG_MAX_AUTH_TOKEN_LENGTH
Definition auth.h:33
uint32 log_connections
@ LOG_CONNECTION_AUTHENTICATION
void pg_store_delegated_credential(gss_cred_id_t cred)
void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
bool secure_loaded_verify_locations(void)
Definition be-secure.c:103
#define unconstify(underlying_type, expr)
Definition c.h:1325
#define STATUS_OK
Definition c.h:1258
uint8_t uint8
Definition c.h:622
#define gettext_noop(x)
Definition c.h:1285
#define Assert(condition)
Definition c.h:943
#define STATUS_EOF
Definition c.h:1260
int32_t int32
Definition c.h:620
#define pg_unreachable()
Definition c.h:367
#define pg_fallthrough
Definition c.h:161
#define STATUS_ERROR
Definition c.h:1259
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
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
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition crypt.c:336
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
PasswordType
Definition crypt.h:44
@ PASSWORD_TYPE_MD5
Definition crypt.h:46
int errcode_for_socket_access(void)
Definition elog.c:976
int errcode(int sqlerrcode)
Definition elog.c:874
#define _(x)
Definition elog.c:95
#define LOG
Definition elog.h:32
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define FATAL
Definition elog.h:42
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define DEBUG2
Definition elog.h:30
#define ERROR
Definition elog.h:40
int int int errdetail_log(const char *fmt,...) pg_attribute_printf(1
#define elog(elevel,...)
Definition elog.h:228
#define FATAL_CLIENT_ONLY
Definition elog.h:43
#define ereport(elevel,...)
Definition elog.h:152
#define DEBUG5
Definition elog.h:27
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
#define DEBUG4
Definition elog.h:28
#define ERRCODE_PROTOCOL_VIOLATION
Definition fe-connect.c:96
#define ERRCODE_INVALID_PASSWORD
Definition fe-connect.c:93
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
Definition hba.c:2791
void hba_getauthmethod(Port *port)
Definition hba.c:2935
const char * hba_authname(UserAuth auth_method)
Definition hba.c:2948
@ ctLocal
Definition hba.h:59
@ 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
@ clientCertDN
Definition hba.h:77
@ clientCertCN
Definition hba.h:76
@ clientCertOff
Definition hba.h:69
@ clientCertFull
Definition hba.h:71
#define token
FILE * input
FILE * output
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition ip.c:85
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
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition ip.c:56
void proc_exit(int code)
Definition ipc.c:105
int i
Definition isn.c:77
#define pq_flush()
Definition libpq.h:49
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1768
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1266
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext TopMemoryContext
Definition mcxt.c:166
void * palloc(Size size)
Definition mcxt.c:1387
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
ClientConnectionInfo MyClientConnectionInfo
Definition miscinit.c:1020
static char * errmsg
#define MAXPGPATH
static char * user
Definition pg_regress.c:121
static int port
Definition pg_regress.c:117
static char buf[DEFAULT_XLOG_SEG_SIZE]
bool pg_strong_random(void *buf, size_t len)
int pg_strcasecmp(const char *s1, const char *s2)
int pgsocket
Definition port.h:29
#define snprintf
Definition port.h:260
#define PGINVALID_SOCKET
Definition port.h:31
#define closesocket
Definition port.h:397
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition getpeereid.c:33
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
uint32 AuthRequest
Definition pqcomm.h:151
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
char * c
static int fb(int x)
#define AUTH_REQ_SSPI
Definition protocol.h:105
#define PqMsg_GSSResponse
Definition protocol.h:30
#define AUTH_REQ_GSS
Definition protocol.h:103
#define AUTH_REQ_MD5
Definition protocol.h:101
#define AUTH_REQ_OK
Definition protocol.h:96
#define PqMsg_AuthenticationRequest
Definition protocol.h:50
#define AUTH_REQ_PASSWORD
Definition protocol.h:99
#define AUTH_REQ_GSS_CONT
Definition protocol.h:104
#define PqMsg_PasswordMessage
Definition protocol.h:31
#define AUTH_REQ_SASL_FIN
Definition protocol.h:108
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
#define calloc(a, b)
#define free(a)
#define malloc(a)
const char * gai_strerror(int errcode)
static void error(void)
static char * password
Definition streamutil.c:51
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition stringinfo.c:281
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
const char * authn_id
Definition libpq-be.h:99
Definition type.h:138
int Password_encryption
Definition user.c:86
static char * authn_id
Definition validator.c:41
bool am_walsender
Definition walsender.c:135
bool am_db_walsender
Definition walsender.c:138
#define bind(s, addr, addrlen)
Definition win32_port.h:496
#define EINTR
Definition win32_port.h:361
int gid_t
Definition win32_port.h:235
#define recv(s, buf, len, flags)
Definition win32_port.h:501
#define setenv(x, y, z)
Definition win32_port.h:542
#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
int uid_t
Definition win32_port.h:234