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);
51static bool md5_password_warning_enabled(void);
52static void queue_md5_password_warning(void);
53
54
55/*----------------------------------------------------------------
56 * Password-based authentication methods (password, md5, and scram-sha-256)
57 *----------------------------------------------------------------
58 */
59static int CheckPasswordAuth(Port *port, const char **logdetail);
60static int CheckPWChallengeAuth(Port *port, const char **logdetail);
61
62static int CheckMD5Auth(Port *port, char *shadow_pass,
63 const char **logdetail);
64
65
66/*----------------------------------------------------------------
67 * Ident authentication
68 *----------------------------------------------------------------
69 */
70/* Max size of username ident server can return (per RFC 1413) */
71#define IDENT_USERNAME_MAX 512
72
73/* Standard TCP port number for Ident service. Assigned by IANA */
74#define IDENT_PORT 113
75
76static int ident_inet(Port *port);
77
78
79/*----------------------------------------------------------------
80 * Peer authentication
81 *----------------------------------------------------------------
82 */
83static int auth_peer(Port *port);
84
85
86/*----------------------------------------------------------------
87 * PAM authentication
88 *----------------------------------------------------------------
89 */
90#ifdef USE_PAM
91#ifdef HAVE_PAM_PAM_APPL_H
92#include <pam/pam_appl.h>
93#endif
94#ifdef HAVE_SECURITY_PAM_APPL_H
95#include <security/pam_appl.h>
96#endif
97
98#define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */
99
100/* Work around original Solaris' lack of "const" in the conv_proc signature */
101#ifdef _PAM_LEGACY_NONCONST
102#define PG_PAM_CONST
103#else
104#define PG_PAM_CONST const
105#endif
106
107static int CheckPAMAuth(Port *port, const char *user, const char *password);
108static int pam_passwd_conv_proc(int num_msg,
109 PG_PAM_CONST struct pam_message **msg,
110 struct pam_response **resp, void *appdata_ptr);
111
112static struct pam_conv pam_passw_conv = {
114 NULL
115};
116
117static const char *pam_passwd = NULL; /* Workaround for Solaris 2.6
118 * brokenness */
119static Port *pam_port_cludge; /* Workaround for passing "Port *port" into
120 * pam_passwd_conv_proc */
121static bool pam_no_password; /* For detecting no-password-given */
122#endif /* USE_PAM */
123
124
125/*----------------------------------------------------------------
126 * BSD authentication
127 *----------------------------------------------------------------
128 */
129#ifdef USE_BSD_AUTH
130#include <bsd_auth.h>
131
132static int CheckBSDAuth(Port *port, char *user);
133#endif /* USE_BSD_AUTH */
134
135
136/*----------------------------------------------------------------
137 * LDAP authentication
138 *----------------------------------------------------------------
139 */
140#ifdef USE_LDAP
141#ifndef WIN32
142/* We use a deprecated function to keep the codepath the same as win32. */
143#define LDAP_DEPRECATED 1
144#include <ldap.h>
145#else
146#include <winldap.h>
147
148#endif
149
150static int CheckLDAPAuth(Port *port);
151
152/* LDAP_OPT_DIAGNOSTIC_MESSAGE is the newer spelling */
153#ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE
154#define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING
155#endif
156
157/* Default LDAP password mutator hook, can be overridden by a shared library */
158static char *dummy_ldap_password_mutator(char *input);
160
161#endif /* USE_LDAP */
162
163/*----------------------------------------------------------------
164 * Cert authentication
165 *----------------------------------------------------------------
166 */
167#ifdef USE_SSL
168static int CheckCertAuth(Port *port);
169#endif
170
171
172/*----------------------------------------------------------------
173 * Kerberos and GSSAPI GUCs
174 *----------------------------------------------------------------
175 */
179
180
181/*----------------------------------------------------------------
182 * GSSAPI Authentication
183 *----------------------------------------------------------------
184 */
185#ifdef ENABLE_GSS
187
188static int pg_GSS_checkauth(Port *port);
189static int pg_GSS_recvauth(Port *port);
190#endif /* ENABLE_GSS */
191
192
193/*----------------------------------------------------------------
194 * SSPI Authentication
195 *----------------------------------------------------------------
196 */
197#ifdef ENABLE_SSPI
198typedef SECURITY_STATUS
200static int pg_SSPI_recvauth(Port *port);
201static int pg_SSPI_make_upn(char *accountname,
202 size_t accountnamesize,
203 char *domainname,
204 size_t domainnamesize,
205 bool update_accountname);
206#endif
207
208
209/*----------------------------------------------------------------
210 * Global authentication functions
211 *----------------------------------------------------------------
212 */
213
214/*
215 * This hook allows plugins to get control following client authentication,
216 * but before the user has been informed about the results. It could be used
217 * to record login events, insert a delay after failed authentication, etc.
218 */
220
221/*
222 * Tell the user the authentication failed, but not (much about) why.
223 *
224 * There is a tradeoff here between security concerns and making life
225 * unnecessarily difficult for legitimate users. We would not, for example,
226 * want to report the password we were expecting to receive...
227 * But it seems useful to report the username and authorization method
228 * in use, and these are items that must be presumed known to an attacker
229 * anyway.
230 * Note that many sorts of failure report additional information in the
231 * postmaster log, which we hope is only readable by good guys. In
232 * particular, if logdetail isn't NULL, we send that string to the log
233 * when the elevel allows.
234 */
235static void
236auth_failed(Port *port, int elevel, int status, const char *logdetail)
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}
321
322
323/*
324 * Sets the authenticated identity for the current user. The provided string
325 * will be stored into MyClientConnectionInfo, alongside the current HBA
326 * method in use. The ID will be logged if log_connections has the
327 * 'authentication' option specified.
328 *
329 * Auth methods should call this routine exactly once, as soon as the user is
330 * successfully authenticated, even if they have reasons to know that
331 * authorization will fail later.
332 *
333 * The provided string will be copied into TopMemoryContext, to match the
334 * lifetime of MyClientConnectionInfo, so it is safe to pass a string that is
335 * managed by an external library.
336 */
337void
338set_authn_id(Port *port, const char *id)
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}
369
370
371/*
372 * Client authentication starts here. If there is an error, this
373 * function does not return and the backend process is terminated.
374 */
375void
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}
678
679
680/*
681 * Send an authentication request packet to the frontend.
682 */
683void
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}
707
708/*
709 * Collect password response packet from frontend.
710 *
711 * Returns NULL if couldn't get password, else palloc'd string.
712 */
713static char *
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}
784
785
786/*----------------------------------------------------------------
787 * Password-based authentication mechanisms
788 *----------------------------------------------------------------
789 */
790
791/*
792 * Plaintext password authentication.
793 */
794static int
795CheckPasswordAuth(Port *port, const char **logdetail)
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}
831
832/*
833 * MD5 and SCRAM authentication.
834 */
835static int
836CheckPWChallengeAuth(Port *port, const char **logdetail)
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}
894
895static int
896CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
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}
929
930static bool
935
936static void
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}
951
952
953/*----------------------------------------------------------------
954 * GSSAPI authentication system
955 *----------------------------------------------------------------
956 */
957#ifdef ENABLE_GSS
958static int
960{
962 min_stat,
963 lmin_s,
964 gflags;
965 int mtype;
969
970 /*
971 * Use the configured keytab, if there is one. As we now require MIT
972 * Kerberos, we might consider using the credential store extensions in
973 * the future instead of the environment variable.
974 */
976 {
977 if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
978 {
979 /* The only likely failure cause is OOM, so use that errcode */
982 errmsg("could not set environment: %m")));
983 }
984 }
985
986 /*
987 * We accept any service principal that's present in our keytab. This
988 * increases interoperability between kerberos implementations that see
989 * for example case sensitivity differently, while not really opening up
990 * any vector of attack.
991 */
992 port->gss->cred = GSS_C_NO_CREDENTIAL;
993
994 /*
995 * Initialize sequence with an empty context
996 */
997 port->gss->ctx = GSS_C_NO_CONTEXT;
998
1000 port->gss->delegated_creds = false;
1001
1002 /*
1003 * Loop through GSSAPI message exchange. This exchange can consist of
1004 * multiple messages sent in both directions. First message is always from
1005 * the client. All messages from client to server are password packets
1006 * (type 'p').
1007 */
1008 do
1009 {
1011
1013
1014 mtype = pq_getbyte();
1015 if (mtype != PqMsg_GSSResponse)
1016 {
1017 /* Only log error if client didn't disconnect. */
1018 if (mtype != EOF)
1019 ereport(ERROR,
1021 errmsg("expected GSS response, got message type %d",
1022 mtype)));
1023 return STATUS_ERROR;
1024 }
1025
1026 /* Get the actual GSS token */
1029 {
1030 /* EOF - pq_getmessage already logged error */
1031 pfree(buf.data);
1032 return STATUS_ERROR;
1033 }
1034
1035 /* Map to GSSAPI style buffer */
1036 gbuf.length = buf.len;
1037 gbuf.value = buf.data;
1038
1039 elog(DEBUG4, "processing received GSS token of length %zu",
1040 gbuf.length);
1041
1043 &port->gss->ctx,
1044 port->gss->cred,
1045 &gbuf,
1047 &port->gss->name,
1048 NULL,
1049 &port->gss->outbuf,
1050 &gflags,
1051 NULL,
1053
1054 /* gbuf no longer used */
1055 pfree(buf.data);
1056
1057 elog(DEBUG5, "gss_accept_sec_context major: %u, "
1058 "minor: %u, outlen: %zu, outflags: %x",
1060 port->gss->outbuf.length, gflags);
1061
1063
1065 {
1067 port->gss->delegated_creds = true;
1068 }
1069
1070 if (port->gss->outbuf.length != 0)
1071 {
1072 /*
1073 * Negotiation generated data to be sent to the client.
1074 */
1075 elog(DEBUG4, "sending GSS response token of length %zu",
1076 port->gss->outbuf.length);
1077
1079 port->gss->outbuf.value, port->gss->outbuf.length);
1080
1081 gss_release_buffer(&lmin_s, &port->gss->outbuf);
1082 }
1083
1085 {
1087 pg_GSS_error(_("accepting GSS security context failed"),
1089 return STATUS_ERROR;
1090 }
1091
1093 elog(DEBUG4, "GSS continue needed");
1094
1095 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
1096
1097 if (port->gss->cred != GSS_C_NO_CREDENTIAL)
1098 {
1099 /*
1100 * Release service principal credentials
1101 */
1102 gss_release_cred(&min_stat, &port->gss->cred);
1103 }
1104 return pg_GSS_checkauth(port);
1105}
1106
1107/*
1108 * Check whether the GSSAPI-authenticated user is allowed to connect as the
1109 * claimed username.
1110 */
1111static int
1113{
1114 int ret;
1116 min_stat,
1117 lmin_s;
1119 char *princ;
1120
1121 /*
1122 * Get the name of the user that authenticated, and compare it to the pg
1123 * username that was specified for the connection.
1124 */
1125 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
1126 if (maj_stat != GSS_S_COMPLETE)
1127 {
1128 pg_GSS_error(_("retrieving GSS user name failed"),
1130 return STATUS_ERROR;
1131 }
1132
1133 /*
1134 * gbuf.value might not be null-terminated, so turn it into a regular
1135 * null-terminated string.
1136 */
1137 princ = palloc(gbuf.length + 1);
1138 memcpy(princ, gbuf.value, gbuf.length);
1139 princ[gbuf.length] = '\0';
1141
1142 /*
1143 * Copy the original name of the authenticated principal into our backend
1144 * memory for display later.
1145 *
1146 * This is also our authenticated identity. Set it now, rather than
1147 * waiting for the usermap check below, because authentication has already
1148 * succeeded and we want the log file to reflect that.
1149 */
1152
1153 /*
1154 * Split the username at the realm separator
1155 */
1156 if (strchr(princ, '@'))
1157 {
1158 char *cp = strchr(princ, '@');
1159
1160 /*
1161 * If we are not going to include the realm in the username that is
1162 * passed to the ident map, destructively modify it here to remove the
1163 * realm. Then advance past the separator to check the realm.
1164 */
1165 if (!port->hba->include_realm)
1166 *cp = '\0';
1167 cp++;
1168
1169 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
1170 {
1171 /*
1172 * Match the realm part of the name first
1173 */
1175 ret = pg_strcasecmp(port->hba->krb_realm, cp);
1176 else
1177 ret = strcmp(port->hba->krb_realm, cp);
1178
1179 if (ret)
1180 {
1181 /* GSS realm does not match */
1182 elog(DEBUG2,
1183 "GSSAPI realm (%s) and configured realm (%s) don't match",
1184 cp, port->hba->krb_realm);
1185 pfree(princ);
1186 return STATUS_ERROR;
1187 }
1188 }
1189 }
1190 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1191 {
1192 elog(DEBUG2,
1193 "GSSAPI did not return realm but realm matching was requested");
1194 pfree(princ);
1195 return STATUS_ERROR;
1196 }
1197
1198 ret = check_usermap(port->hba->usermap, port->user_name, princ,
1200
1201 pfree(princ);
1202
1203 return ret;
1204}
1205#endif /* ENABLE_GSS */
1206
1207
1208/*----------------------------------------------------------------
1209 * SSPI authentication system
1210 *----------------------------------------------------------------
1211 */
1212#ifdef ENABLE_SSPI
1213
1214/*
1215 * Generate an error for SSPI authentication. The caller should apply
1216 * _() to errmsg to make it translatable.
1217 */
1218static void
1219pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
1220{
1221 char sysmsg[256];
1222
1225 NULL, r, 0,
1226 sysmsg, sizeof(sysmsg), NULL) == 0)
1228 (errmsg_internal("%s", errmsg),
1229 errdetail_internal("SSPI error %x", (unsigned int) r)));
1230 else
1232 (errmsg_internal("%s", errmsg),
1233 errdetail_internal("%s (%x)", sysmsg, (unsigned int) r)));
1234}
1235
1236static int
1238{
1239 int mtype;
1244 newctx;
1248 SecBufferDesc outbuf;
1251 HANDLE token;
1253 DWORD retlen;
1254 char accountname[MAXPGPATH];
1255 char domainname[MAXPGPATH];
1257 DWORD domainnamesize = sizeof(domainname);
1259 char *authn_id;
1260
1261 /*
1262 * Acquire a handle to the server credentials.
1263 */
1265 "negotiate",
1267 NULL,
1268 NULL,
1269 NULL,
1270 NULL,
1271 &sspicred,
1272 &expiry);
1273 if (r != SEC_E_OK)
1274 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
1275
1276 /*
1277 * Loop through SSPI message exchange. This exchange can consist of
1278 * multiple messages sent in both directions. First message is always from
1279 * the client. All messages from client to server are password packets
1280 * (type 'p').
1281 */
1282 do
1283 {
1285 mtype = pq_getbyte();
1286 if (mtype != PqMsg_GSSResponse)
1287 {
1288 if (sspictx != NULL)
1289 {
1291 free(sspictx);
1292 }
1294
1295 /* Only log error if client didn't disconnect. */
1296 if (mtype != EOF)
1297 ereport(ERROR,
1299 errmsg("expected SSPI response, got message type %d",
1300 mtype)));
1301 return STATUS_ERROR;
1302 }
1303
1304 /* Get the actual SSPI token */
1307 {
1308 /* EOF - pq_getmessage already logged error */
1309 pfree(buf.data);
1310 if (sspictx != NULL)
1311 {
1313 free(sspictx);
1314 }
1316 return STATUS_ERROR;
1317 }
1318
1319 /* Map to SSPI style buffer */
1320 inbuf.ulVersion = SECBUFFER_VERSION;
1321 inbuf.cBuffers = 1;
1322 inbuf.pBuffers = InBuffers;
1323 InBuffers[0].pvBuffer = buf.data;
1324 InBuffers[0].cbBuffer = buf.len;
1325 InBuffers[0].BufferType = SECBUFFER_TOKEN;
1326
1327 /* Prepare output buffer */
1328 OutBuffers[0].pvBuffer = NULL;
1329 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1330 OutBuffers[0].cbBuffer = 0;
1331 outbuf.cBuffers = 1;
1332 outbuf.pBuffers = OutBuffers;
1333 outbuf.ulVersion = SECBUFFER_VERSION;
1334
1335 elog(DEBUG4, "processing received SSPI token of length %u",
1336 (unsigned int) buf.len);
1337
1339 sspictx,
1340 &inbuf,
1343 &newctx,
1344 &outbuf,
1345 &contextattr,
1346 NULL);
1347
1348 /* input buffer no longer used */
1349 pfree(buf.data);
1350
1351 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
1352 {
1353 /*
1354 * Negotiation generated data to be sent to the client.
1355 */
1356 elog(DEBUG4, "sending SSPI response token of length %u",
1357 (unsigned int) outbuf.pBuffers[0].cbBuffer);
1358
1359 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
1360 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
1361
1363 port->gss->outbuf.value, port->gss->outbuf.length);
1364
1365 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
1366 }
1367
1368 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
1369 {
1370 if (sspictx != NULL)
1371 {
1373 free(sspictx);
1374 }
1377 _("could not accept SSPI security context"), r);
1378 }
1379
1380 /*
1381 * Overwrite the current context with the one we just received. If
1382 * sspictx is NULL it was the first loop and we need to allocate a
1383 * buffer for it. On subsequent runs, we can just overwrite the buffer
1384 * contents since the size does not change.
1385 */
1386 if (sspictx == NULL)
1387 {
1388 sspictx = malloc(sizeof(CtxtHandle));
1389 if (sspictx == NULL)
1390 ereport(ERROR,
1391 (errmsg("out of memory")));
1392 }
1393
1394 memcpy(sspictx, &newctx, sizeof(CtxtHandle));
1395
1396 if (r == SEC_I_CONTINUE_NEEDED)
1397 elog(DEBUG4, "SSPI continue needed");
1398
1399 } while (r == SEC_I_CONTINUE_NEEDED);
1400
1401
1402 /*
1403 * Release service principal credentials
1404 */
1406
1407
1408 /*
1409 * SEC_E_OK indicates that authentication is now complete.
1410 *
1411 * Get the name of the user that authenticated, and compare it to the pg
1412 * username that was specified for the connection.
1413 */
1414
1416 if (r != SEC_E_OK)
1418 _("could not get token from SSPI security context"), r);
1419
1420 /*
1421 * No longer need the security context, everything from here on uses the
1422 * token instead.
1423 */
1425 free(sspictx);
1426
1427 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
1428 ereport(ERROR,
1429 (errmsg_internal("could not get token information buffer size: error code %lu",
1430 GetLastError())));
1431
1433 if (tokenuser == NULL)
1434 ereport(ERROR,
1435 (errmsg("out of memory")));
1436
1438 ereport(ERROR,
1439 (errmsg_internal("could not get token information: error code %lu",
1440 GetLastError())));
1441
1443
1445 domainname, &domainnamesize, &accountnameuse))
1446 ereport(ERROR,
1447 (errmsg_internal("could not look up account SID: error code %lu",
1448 GetLastError())));
1449
1450 free(tokenuser);
1451
1452 if (!port->hba->compat_realm)
1453 {
1454 int status = pg_SSPI_make_upn(accountname, sizeof(accountname),
1455 domainname, sizeof(domainname),
1456 port->hba->upn_username);
1457
1458 if (status != STATUS_OK)
1459 /* Error already reported from pg_SSPI_make_upn */
1460 return status;
1461 }
1462
1463 /*
1464 * We have all of the information necessary to construct the authenticated
1465 * identity. Set it now, rather than waiting for check_usermap below,
1466 * because authentication has already succeeded and we want the log file
1467 * to reflect that.
1468 */
1469 if (port->hba->compat_realm)
1470 {
1471 /* SAM-compatible format. */
1472 authn_id = psprintf("%s\\%s", domainname, accountname);
1473 }
1474 else
1475 {
1476 /* Kerberos principal format. */
1477 authn_id = psprintf("%s@%s", accountname, domainname);
1478 }
1479
1481 pfree(authn_id);
1482
1483 /*
1484 * Compare realm/domain if requested. In SSPI, always compare case
1485 * insensitive.
1486 */
1487 if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1488 {
1489 if (pg_strcasecmp(port->hba->krb_realm, domainname) != 0)
1490 {
1491 elog(DEBUG2,
1492 "SSPI domain (%s) and configured domain (%s) don't match",
1493 domainname, port->hba->krb_realm);
1494
1495 return STATUS_ERROR;
1496 }
1497 }
1498
1499 /*
1500 * We have the username (without domain/realm) in accountname, compare to
1501 * the supplied value. In SSPI, always compare case insensitive.
1502 *
1503 * If set to include realm, append it in <username>@<realm> format.
1504 */
1505 if (port->hba->include_realm)
1506 {
1507 char *namebuf;
1508 int retval;
1509
1510 namebuf = psprintf("%s@%s", accountname, domainname);
1511 retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
1512 pfree(namebuf);
1513 return retval;
1514 }
1515 else
1516 return check_usermap(port->hba->usermap, port->user_name, accountname, true);
1517}
1518
1519/*
1520 * Replaces the domainname with the Kerberos realm name,
1521 * and optionally the accountname with the Kerberos user name.
1522 */
1523static int
1525 size_t accountnamesize,
1526 char *domainname,
1527 size_t domainnamesize,
1528 bool update_accountname)
1529{
1530 char *samname;
1531 char *upname = NULL;
1532 char *p = NULL;
1533 ULONG upnamesize = 0;
1534 size_t upnamerealmsize;
1535 BOOLEAN res;
1536
1537 /*
1538 * Build SAM name (DOMAIN\user), then translate to UPN
1539 * (user@kerberos.realm). The realm name is returned in lower case, but
1540 * that is fine because in SSPI auth, string comparisons are always
1541 * case-insensitive.
1542 */
1543
1544 samname = psprintf("%s\\%s", domainname, accountname);
1546 NULL, &upnamesize);
1547
1548 if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1549 || upnamesize == 0)
1550 {
1551 pfree(samname);
1552 ereport(LOG,
1554 errmsg("could not translate name")));
1555 return STATUS_ERROR;
1556 }
1557
1558 /* upnamesize includes the terminating NUL. */
1560
1562 upname, &upnamesize);
1563
1564 pfree(samname);
1565 if (res)
1566 p = strchr(upname, '@');
1567
1568 if (!res || p == NULL)
1569 {
1570 pfree(upname);
1571 ereport(LOG,
1573 errmsg("could not translate name")));
1574 return STATUS_ERROR;
1575 }
1576
1577 /* Length of realm name after the '@', including the NUL. */
1578 upnamerealmsize = upnamesize - (p - upname + 1);
1579
1580 /* Replace domainname with realm name. */
1582 {
1583 pfree(upname);
1584 ereport(LOG,
1586 errmsg("realm name too long")));
1587 return STATUS_ERROR;
1588 }
1589
1590 /* Length is now safe. */
1591 strcpy(domainname, p + 1);
1592
1593 /* Replace account name as well (in case UPN != SAM)? */
1595 {
1596 if ((p - upname + 1) > accountnamesize)
1597 {
1598 pfree(upname);
1599 ereport(LOG,
1601 errmsg("translated account name too long")));
1602 return STATUS_ERROR;
1603 }
1604
1605 *p = 0;
1607 }
1608
1609 pfree(upname);
1610 return STATUS_OK;
1611}
1612#endif /* ENABLE_SSPI */
1613
1614
1615
1616/*----------------------------------------------------------------
1617 * Ident authentication system
1618 *----------------------------------------------------------------
1619 */
1620
1621/*
1622 * Per RFC 1413, space and tab are whitespace in ident messages.
1623 */
1624static bool
1626{
1627 return c == ' ' || c == '\t';
1628}
1629
1630/*
1631 * Parse the string "*ident_response" as a response from a query to an Ident
1632 * server. If it's a normal response indicating a user name, return true
1633 * and store the user name at *ident_user. If it's anything else,
1634 * return false.
1635 */
1636static bool
1638 char *ident_user)
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}
1707
1708
1709/*
1710 * Talk to the ident server on "remote_addr" and find out who
1711 * owns the tcp connection to "local_addr"
1712 * If the username is successfully retrieved, check the usermap.
1713 *
1714 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if the
1715 * latch was set would improve the responsiveness to timeouts/cancellations.
1716 */
1717static int
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}
1888
1889
1890/*----------------------------------------------------------------
1891 * Peer authentication system
1892 *----------------------------------------------------------------
1893 */
1894
1895/*
1896 * Ask kernel about the credentials of the connecting process,
1897 * determine the symbolic name of the corresponding user, and check
1898 * if valid per the usermap.
1899 *
1900 * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
1901 */
1902static int
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}
1962
1963
1964/*----------------------------------------------------------------
1965 * PAM authentication system
1966 *----------------------------------------------------------------
1967 */
1968#ifdef USE_PAM
1969
1970/*
1971 * PAM conversation function
1972 */
1973
1974static int
1976 struct pam_response **resp, void *appdata_ptr)
1977{
1978 const char *passwd;
1979 struct pam_response *reply;
1980 int i;
1981
1982 if (appdata_ptr)
1983 passwd = (char *) appdata_ptr;
1984 else
1985 {
1986 /*
1987 * Workaround for Solaris 2.6 where the PAM library is broken and does
1988 * not pass appdata_ptr to the conversation routine
1989 */
1991 }
1992
1993 *resp = NULL; /* in case of error exit */
1994
1996 return PAM_CONV_ERR;
1997
1998 /*
1999 * Explicitly not using palloc here - PAM will free this memory in
2000 * pam_end()
2001 */
2002 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
2003 {
2004 ereport(LOG,
2006 errmsg("out of memory")));
2007 return PAM_CONV_ERR;
2008 }
2009
2010 for (i = 0; i < num_msg; i++)
2011 {
2012 switch (msg[i]->msg_style)
2013 {
2015 if (strlen(passwd) == 0)
2016 {
2017 /*
2018 * Password wasn't passed to PAM the first time around -
2019 * let's go ask the client to send a password, which we
2020 * then stuff into PAM.
2021 */
2024 if (passwd == NULL)
2025 {
2026 /*
2027 * Client didn't want to send password. We
2028 * intentionally do not log anything about this,
2029 * either here or at higher levels.
2030 */
2031 pam_no_password = true;
2032 goto fail;
2033 }
2034 }
2035 if ((reply[i].resp = strdup(passwd)) == NULL)
2036 goto fail;
2037 reply[i].resp_retcode = PAM_SUCCESS;
2038 break;
2039 case PAM_ERROR_MSG:
2040 ereport(LOG,
2041 (errmsg("error from underlying PAM layer: %s",
2042 msg[i]->msg)));
2044 case PAM_TEXT_INFO:
2045 /* we don't bother to log TEXT_INFO messages */
2046 if ((reply[i].resp = strdup("")) == NULL)
2047 goto fail;
2048 reply[i].resp_retcode = PAM_SUCCESS;
2049 break;
2050 default:
2051 ereport(LOG,
2052 (errmsg("unsupported PAM conversation %d/\"%s\"",
2053 msg[i]->msg_style,
2054 msg[i]->msg ? msg[i]->msg : "(none)")));
2055 goto fail;
2056 }
2057 }
2058
2059 *resp = reply;
2060 return PAM_SUCCESS;
2061
2062fail:
2063 /* free up whatever we allocated */
2064 for (i = 0; i < num_msg; i++)
2065 free(reply[i].resp);
2066 free(reply);
2067
2068 return PAM_CONV_ERR;
2069}
2070
2071
2072/*
2073 * Check authentication against PAM.
2074 */
2075static int
2076CheckPAMAuth(Port *port, const char *user, const char *password)
2077{
2078 int retval;
2080
2081 /*
2082 * We can't entirely rely on PAM to pass through appdata --- it appears
2083 * not to work on at least Solaris 2.6. So use these ugly static
2084 * variables instead.
2085 */
2088 pam_no_password = false;
2089
2090 /*
2091 * Set the application data portion of the conversation struct. This is
2092 * later used inside the PAM conversation to pass the password to the
2093 * authentication module.
2094 */
2095 pam_passw_conv.appdata_ptr = unconstify(char *, password); /* from password above,
2096 * not allocated */
2097
2098 /* Optionally, one can set the service name in pg_hba.conf */
2099 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
2100 retval = pam_start(port->hba->pamservice, "pgsql@",
2101 &pam_passw_conv, &pamh);
2102 else
2103 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
2104 &pam_passw_conv, &pamh);
2105
2106 if (retval != PAM_SUCCESS)
2107 {
2108 ereport(LOG,
2109 (errmsg("could not create PAM authenticator: %s",
2110 pam_strerror(pamh, retval))));
2111 pam_passwd = NULL; /* Unset pam_passwd */
2112 return STATUS_ERROR;
2113 }
2114
2115 retval = pam_set_item(pamh, PAM_USER, user);
2116
2117 if (retval != PAM_SUCCESS)
2118 {
2119 ereport(LOG,
2120 (errmsg("pam_set_item(PAM_USER) failed: %s",
2121 pam_strerror(pamh, retval))));
2122 pam_passwd = NULL; /* Unset pam_passwd */
2123 return STATUS_ERROR;
2124 }
2125
2126 if (port->hba->conntype != ctLocal)
2127 {
2128 char hostinfo[NI_MAXHOST];
2129 int flags;
2130
2131 if (port->hba->pam_use_hostname)
2132 flags = 0;
2133 else
2135
2136 retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
2137 hostinfo, sizeof(hostinfo), NULL, 0,
2138 flags);
2139 if (retval != 0)
2140 {
2142 (errmsg_internal("pg_getnameinfo_all() failed: %s",
2143 gai_strerror(retval))));
2144 return STATUS_ERROR;
2145 }
2146
2147 retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
2148
2149 if (retval != PAM_SUCCESS)
2150 {
2151 ereport(LOG,
2152 (errmsg("pam_set_item(PAM_RHOST) failed: %s",
2153 pam_strerror(pamh, retval))));
2154 pam_passwd = NULL;
2155 return STATUS_ERROR;
2156 }
2157 }
2158
2160
2161 if (retval != PAM_SUCCESS)
2162 {
2163 ereport(LOG,
2164 (errmsg("pam_set_item(PAM_CONV) failed: %s",
2165 pam_strerror(pamh, retval))));
2166 pam_passwd = NULL; /* Unset pam_passwd */
2167 return STATUS_ERROR;
2168 }
2169
2170 retval = pam_authenticate(pamh, 0);
2171
2172 if (retval != PAM_SUCCESS)
2173 {
2174 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2175 if (!pam_no_password)
2176 ereport(LOG,
2177 (errmsg("pam_authenticate failed: %s",
2178 pam_strerror(pamh, retval))));
2179 pam_passwd = NULL; /* Unset pam_passwd */
2181 }
2182
2183 retval = pam_acct_mgmt(pamh, 0);
2184
2185 if (retval != PAM_SUCCESS)
2186 {
2187 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2188 if (!pam_no_password)
2189 ereport(LOG,
2190 (errmsg("pam_acct_mgmt failed: %s",
2191 pam_strerror(pamh, retval))));
2192 pam_passwd = NULL; /* Unset pam_passwd */
2194 }
2195
2196 retval = pam_end(pamh, retval);
2197
2198 if (retval != PAM_SUCCESS)
2199 {
2200 ereport(LOG,
2201 (errmsg("could not release PAM authenticator: %s",
2202 pam_strerror(pamh, retval))));
2203 }
2204
2205 pam_passwd = NULL; /* Unset pam_passwd */
2206
2207 if (retval == PAM_SUCCESS)
2209
2210 return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
2211}
2212#endif /* USE_PAM */
2213
2214
2215/*----------------------------------------------------------------
2216 * BSD authentication system
2217 *----------------------------------------------------------------
2218 */
2219#ifdef USE_BSD_AUTH
2220static int
2221CheckBSDAuth(Port *port, char *user)
2222{
2223 char *passwd;
2224 int retval;
2225
2226 /* Send regular password request to client, and get the response */
2228
2230 if (passwd == NULL)
2231 return STATUS_EOF;
2232
2233 /*
2234 * Ask the BSD auth system to verify password. Note that auth_userokay
2235 * will overwrite the password string with zeroes, but it's just a
2236 * temporary string so we don't care.
2237 */
2238 retval = auth_userokay(user, NULL, "auth-postgresql", passwd);
2239
2240 pfree(passwd);
2241
2242 if (!retval)
2243 return STATUS_ERROR;
2244
2246 return STATUS_OK;
2247}
2248#endif /* USE_BSD_AUTH */
2249
2250
2251/*----------------------------------------------------------------
2252 * LDAP authentication system
2253 *----------------------------------------------------------------
2254 */
2255#ifdef USE_LDAP
2256
2257static int errdetail_for_ldap(LDAP *ldap);
2258
2259/*
2260 * Initialize a connection to the LDAP server, including setting up
2261 * TLS if requested.
2262 */
2263static int
2265{
2266 const char *scheme;
2268 int r;
2269
2270 scheme = port->hba->ldapscheme;
2271 if (scheme == NULL)
2272 scheme = "ldap";
2273#ifdef WIN32
2274 if (strcmp(scheme, "ldaps") == 0)
2275 *ldap = ldap_sslinit(port->hba->ldapserver, port->hba->ldapport, 1);
2276 else
2277 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2278 if (!*ldap)
2279 {
2280 ereport(LOG,
2281 (errmsg("could not initialize LDAP: error code %lu",
2282 LdapGetLastError())));
2283
2284 return STATUS_ERROR;
2285 }
2286#else
2287#ifdef HAVE_LDAP_INITIALIZE
2288
2289 /*
2290 * OpenLDAP provides a non-standard extension ldap_initialize() that takes
2291 * a list of URIs, allowing us to request "ldaps" instead of "ldap". It
2292 * also provides ldap_domain2hostlist() to find LDAP servers automatically
2293 * using DNS SRV. They were introduced in the same version, so for now we
2294 * don't have an extra configure check for the latter.
2295 */
2296 {
2298 char *hostlist = NULL;
2299 char *p;
2300 bool append_port;
2301
2302 /* We'll build a space-separated scheme://hostname:port list here */
2304
2305 /*
2306 * If pg_hba.conf provided no hostnames, we can ask OpenLDAP to try to
2307 * find some by extracting a domain name from the base DN and looking
2308 * up DSN SRV records for _ldap._tcp.<domain>.
2309 */
2310 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2311 {
2312 char *domain;
2313
2314 /* ou=blah,dc=foo,dc=bar -> foo.bar */
2315 if (ldap_dn2domain(port->hba->ldapbasedn, &domain))
2316 {
2317 ereport(LOG,
2318 (errmsg("could not extract domain name from ldapbasedn")));
2319 return STATUS_ERROR;
2320 }
2321
2322 /* Look up a list of LDAP server hosts and port numbers */
2323 if (ldap_domain2hostlist(domain, &hostlist))
2324 {
2325 ereport(LOG,
2326 (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
2327 domain),
2328 (errhint("Set an LDAP server name explicitly."))));
2329 ldap_memfree(domain);
2330 return STATUS_ERROR;
2331 }
2332 ldap_memfree(domain);
2333
2334 /* We have a space-separated list of host:port entries */
2335 p = hostlist;
2336 append_port = false;
2337 }
2338 else
2339 {
2340 /* We have a space-separated list of hosts from pg_hba.conf */
2341 p = port->hba->ldapserver;
2342 append_port = true;
2343 }
2344
2345 /* Convert the list of host[:port] entries to full URIs */
2346 do
2347 {
2348 size_t size;
2349
2350 /* Find the span of the next entry */
2351 size = strcspn(p, " ");
2352
2353 /* Append a space separator if this isn't the first URI */
2354 if (uris.len > 0)
2356
2357 /* Append scheme://host:port */
2360 appendBinaryStringInfo(&uris, p, size);
2361 if (append_port)
2362 appendStringInfo(&uris, ":%d", port->hba->ldapport);
2363
2364 /* Step over this entry and any number of trailing spaces */
2365 p += size;
2366 while (*p == ' ')
2367 ++p;
2368 } while (*p);
2369
2370 /* Free memory from OpenLDAP if we looked up SRV records */
2371 if (hostlist)
2373
2374 /* Finally, try to connect using the URI list */
2375 r = ldap_initialize(ldap, uris.data);
2376 pfree(uris.data);
2377 if (r != LDAP_SUCCESS)
2378 {
2379 ereport(LOG,
2380 (errmsg("could not initialize LDAP: %s",
2381 ldap_err2string(r))));
2382
2383 return STATUS_ERROR;
2384 }
2385 }
2386#else
2387 if (strcmp(scheme, "ldaps") == 0)
2388 {
2389 ereport(LOG,
2390 (errmsg("ldaps not supported with this LDAP library")));
2391
2392 return STATUS_ERROR;
2393 }
2394 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2395 if (!*ldap)
2396 {
2397 ereport(LOG,
2398 (errmsg("could not initialize LDAP: %m")));
2399
2400 return STATUS_ERROR;
2401 }
2402#endif
2403#endif
2404
2406 {
2407 ereport(LOG,
2408 (errmsg("could not set LDAP protocol version: %s",
2409 ldap_err2string(r)),
2411 ldap_unbind(*ldap);
2412 return STATUS_ERROR;
2413 }
2414
2415 if (port->hba->ldaptls)
2416 {
2417#ifndef WIN32
2418 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
2419#else
2420 if ((r = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
2421#endif
2422 {
2423 ereport(LOG,
2424 (errmsg("could not start LDAP TLS session: %s",
2425 ldap_err2string(r)),
2427 ldap_unbind(*ldap);
2428 return STATUS_ERROR;
2429 }
2430 }
2431
2432 return STATUS_OK;
2433}
2434
2435/* Placeholders recognized by FormatSearchFilter. For now just one. */
2436#define LPH_USERNAME "$username"
2437#define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
2438
2439/* Not all LDAP implementations define this. */
2440#ifndef LDAP_NO_ATTRS
2441#define LDAP_NO_ATTRS "1.1"
2442#endif
2443
2444/* Not all LDAP implementations define this. */
2445#ifndef LDAPS_PORT
2446#define LDAPS_PORT 636
2447#endif
2448
2449static char *
2451{
2452 return input;
2453}
2454
2455/*
2456 * Return a newly allocated C string copied from "pattern" with all
2457 * occurrences of the placeholder "$username" replaced with "user_name".
2458 */
2459static char *
2460FormatSearchFilter(const char *pattern, const char *user_name)
2461{
2463
2465 while (*pattern != '\0')
2466 {
2467 if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)
2468 {
2469 appendStringInfoString(&output, user_name);
2470 pattern += LPH_USERNAME_LEN;
2471 }
2472 else
2473 appendStringInfoChar(&output, *pattern++);
2474 }
2475
2476 return output.data;
2477}
2478
2479/*
2480 * Perform LDAP authentication
2481 */
2482static int
2484{
2485 char *passwd;
2486 LDAP *ldap;
2487 int r;
2488 char *fulluser;
2489 const char *server_name;
2490
2491#ifdef HAVE_LDAP_INITIALIZE
2492
2493 /*
2494 * For OpenLDAP, allow empty hostname if we have a basedn. We'll look for
2495 * servers with DNS SRV records via OpenLDAP library facilities.
2496 */
2497 if ((!port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
2498 (!port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
2499 {
2500 ereport(LOG,
2501 (errmsg("LDAP server not specified, and no ldapbasedn")));
2502 return STATUS_ERROR;
2503 }
2504#else
2505 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2506 {
2507 ereport(LOG,
2508 (errmsg("LDAP server not specified")));
2509 return STATUS_ERROR;
2510 }
2511#endif
2512
2513 /*
2514 * If we're using SRV records, we don't have a server name so we'll just
2515 * show an empty string in error messages.
2516 */
2517 server_name = port->hba->ldapserver ? port->hba->ldapserver : "";
2518
2519 if (port->hba->ldapport == 0)
2520 {
2521 if (port->hba->ldapscheme != NULL &&
2522 strcmp(port->hba->ldapscheme, "ldaps") == 0)
2523 port->hba->ldapport = LDAPS_PORT;
2524 else
2525 port->hba->ldapport = LDAP_PORT;
2526 }
2527
2529
2531 if (passwd == NULL)
2532 return STATUS_EOF; /* client wouldn't send password */
2533
2535 {
2536 /* Error message already sent */
2537 pfree(passwd);
2538 return STATUS_ERROR;
2539 }
2540
2541 if (port->hba->ldapbasedn)
2542 {
2543 /*
2544 * First perform an LDAP search to find the DN for the user we are
2545 * trying to log in as.
2546 */
2547 char *filter;
2549 LDAPMessage *entry;
2550 char *attributes[] = {LDAP_NO_ATTRS, NULL};
2551 char *dn;
2552 char *c;
2553 int count;
2554
2555 /*
2556 * Disallow any characters that we would otherwise need to escape,
2557 * since they aren't really reasonable in a username anyway. Allowing
2558 * them would make it possible to inject any kind of custom filters in
2559 * the LDAP filter.
2560 */
2561 for (c = port->user_name; *c; c++)
2562 {
2563 if (*c == '*' ||
2564 *c == '(' ||
2565 *c == ')' ||
2566 *c == '\\' ||
2567 *c == '/')
2568 {
2569 ereport(LOG,
2570 (errmsg("invalid character in user name for LDAP authentication")));
2572 pfree(passwd);
2573 return STATUS_ERROR;
2574 }
2575 }
2576
2577 /*
2578 * Bind with a pre-defined username/password (if available) for
2579 * searching. If none is specified, this turns into an anonymous bind.
2580 */
2582 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2583 port->hba->ldapbindpasswd ? ldap_password_hook(port->hba->ldapbindpasswd) : "");
2584 if (r != LDAP_SUCCESS)
2585 {
2586 ereport(LOG,
2587 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",
2588 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2589 server_name,
2590 ldap_err2string(r)),
2593 pfree(passwd);
2594 return STATUS_ERROR;
2595 }
2596
2597 /* Build a custom filter or a single attribute filter? */
2598 if (port->hba->ldapsearchfilter)
2599 filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);
2600 else if (port->hba->ldapsearchattribute)
2601 filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);
2602 else
2603 filter = psprintf("(uid=%s)", port->user_name);
2604
2606 r = ldap_search_s(ldap,
2607 port->hba->ldapbasedn,
2608 port->hba->ldapscope,
2609 filter,
2610 attributes,
2611 0,
2613
2614 if (r != LDAP_SUCCESS)
2615 {
2616 ereport(LOG,
2617 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
2618 filter, server_name, ldap_err2string(r)),
2620 if (search_message != NULL)
2623 pfree(passwd);
2624 pfree(filter);
2625 return STATUS_ERROR;
2626 }
2627
2629 if (count != 1)
2630 {
2631 if (count == 0)
2632 ereport(LOG,
2633 (errmsg("LDAP user \"%s\" does not exist", port->user_name),
2634 errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
2635 filter, server_name)));
2636 else
2637 ereport(LOG,
2638 (errmsg("LDAP user \"%s\" is not unique", port->user_name),
2639 errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",
2640 "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
2641 count,
2642 filter, server_name, count)));
2643
2645 pfree(passwd);
2646 pfree(filter);
2648 return STATUS_ERROR;
2649 }
2650
2652 dn = ldap_get_dn(ldap, entry);
2653 if (dn == NULL)
2654 {
2655 int error;
2656
2658 ereport(LOG,
2659 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
2660 filter, server_name,
2664 pfree(passwd);
2665 pfree(filter);
2667 return STATUS_ERROR;
2668 }
2669 fulluser = pstrdup(dn);
2670
2671 pfree(filter);
2674 }
2675 else
2676 fulluser = psprintf("%s%s%s",
2677 port->hba->ldapprefix ? port->hba->ldapprefix : "",
2678 port->user_name,
2679 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
2680
2682
2683 if (r != LDAP_SUCCESS)
2684 {
2685 ereport(LOG,
2686 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
2687 fulluser, server_name, ldap_err2string(r)),
2690 pfree(passwd);
2691 pfree(fulluser);
2692 return STATUS_ERROR;
2693 }
2694
2695 /* Save the original bind DN as the authenticated identity. */
2697
2699 pfree(passwd);
2700 pfree(fulluser);
2701
2702 return STATUS_OK;
2703}
2704
2705/*
2706 * Add a detail error message text to the current error if one can be
2707 * constructed from the LDAP 'diagnostic message'.
2708 */
2709static int
2711{
2712 char *message;
2713 int rc;
2714
2716 if (rc == LDAP_SUCCESS && message != NULL)
2717 {
2718 errdetail("LDAP diagnostics: %s", message);
2719 ldap_memfree(message);
2720 }
2721
2722 return 0;
2723}
2724
2725#endif /* USE_LDAP */
2726
2727
2728/*----------------------------------------------------------------
2729 * SSL client certificate authentication
2730 *----------------------------------------------------------------
2731 */
2732#ifdef USE_SSL
2733static int
2735{
2737 char *peer_username = NULL;
2738
2739 Assert(port->ssl);
2740
2741 /* select the correct field to compare */
2742 switch (port->hba->clientcertname)
2743 {
2744 case clientCertDN:
2745 peer_username = port->peer_dn;
2746 break;
2747 case clientCertCN:
2748 peer_username = port->peer_cn;
2749 }
2750
2751 /* Make sure we have received a username in the certificate */
2752 if (peer_username == NULL ||
2753 strlen(peer_username) <= 0)
2754 {
2755 ereport(LOG,
2756 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
2757 port->user_name)));
2758 return STATUS_ERROR;
2759 }
2760
2761 if (port->hba->auth_method == uaCert)
2762 {
2763 /*
2764 * For cert auth, the client's Subject DN is always our authenticated
2765 * identity, even if we're only using its CN for authorization. Set
2766 * it now, rather than waiting for check_usermap() below, because
2767 * authentication has already succeeded and we want the log file to
2768 * reflect that.
2769 */
2770 if (!port->peer_dn)
2771 {
2772 /*
2773 * This should not happen as both peer_dn and peer_cn should be
2774 * set in this context.
2775 */
2776 ereport(LOG,
2777 (errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",
2778 port->user_name)));
2779 return STATUS_ERROR;
2780 }
2781
2782 set_authn_id(port, port->peer_dn);
2783 }
2784
2785 /* Just pass the certificate cn/dn to the usermap check */
2786 status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);
2788 {
2789 /*
2790 * If clientcert=verify-full was specified and the authentication
2791 * method is other than uaCert, log the reason for rejecting the
2792 * authentication.
2793 */
2794 if (port->hba->clientcert == clientCertFull && port->hba->auth_method != uaCert)
2795 {
2796 switch (port->hba->clientcertname)
2797 {
2798 case clientCertDN:
2799 ereport(LOG,
2800 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
2801 port->user_name)));
2802 break;
2803 case clientCertCN:
2804 ereport(LOG,
2805 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
2806 port->user_name)));
2807 }
2808 }
2809 }
2810 return status_check_usermap;
2811}
2812#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:684
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
char * pg_krb_server_keyfile
Definition auth.c:176
#define IDENT_USERNAME_MAX
Definition auth.c:71
bool pg_krb_caseins_users
Definition auth.c:177
static char * recv_password_packet(Port *port)
Definition auth.c:714
bool pg_gss_accept_delegation
Definition auth.c:178
static void queue_md5_password_warning(void)
Definition auth.c:937
ClientAuthentication_hook_type ClientAuthentication_hook
Definition auth.c:219
#define IDENT_PORT
Definition auth.c:74
void ClientAuthentication(Port *port)
Definition auth.c:376
static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
Definition auth.c:896
void set_authn_id(Port *port, const char *id)
Definition auth.c:338
static bool is_ident_whitespace(const char c)
Definition auth.c:1625
static int ident_inet(Port *port)
Definition auth.c:1718
static bool md5_password_warning_enabled(void)
Definition auth.c:931
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition auth.c:1637
#define HOSTNAME_LOOKUP_DETAIL(port)
static int CheckPasswordAuth(Port *port, const char **logdetail)
Definition auth.c:795
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:1370
#define STATUS_OK
Definition c.h:1298
uint8_t uint8
Definition c.h:681
#define gettext_noop(x)
Definition c.h:1325
#define Assert(condition)
Definition c.h:1002
#define STATUS_EOF
Definition c.h:1300
int32_t int32
Definition c.h:679
#define pg_unreachable()
Definition c.h:426
#define pg_fallthrough
Definition c.h:220
#define STATUS_ERROR
Definition c.h:1299
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:320
char * get_role_password(const char *role, const char **logdetail)
Definition crypt.c:43
bool md5_password_warnings
Definition crypt.c:33
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:977
int errcode(int sqlerrcode)
Definition elog.c:875
#define _(x)
Definition elog.c:96
#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:1897
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
MemoryContext TopMemoryContext
Definition mcxt.c:167
void * palloc(Size size)
Definition mcxt.c:1390
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
ClientConnectionInfo MyClientConnectionInfo
Definition miscinit.c:1020
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
#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:261
#define PGINVALID_SOCKET
Definition port.h:31
#define closesocket
Definition port.h:398
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition getpeereid.c:33
void StoreConnectionWarning(char *msg, char *detail, ConnectionWarningFilter filter)
Definition postinit.c:1517
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:139
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:513
#define EINTR
Definition win32_port.h:378
int gid_t
Definition win32_port.h:252
#define recv(s, buf, len, flags)
Definition win32_port.h:518
#define setenv(x, y, z)
Definition win32_port.h:559
#define send(s, buf, len, flags)
Definition win32_port.h:519
#define socket(af, type, protocol)
Definition win32_port.h:512
#define connect(s, name, namelen)
Definition win32_port.h:516
int uid_t
Definition win32_port.h:251
static void static void static void warning(const char *const string,...) pg_attribute_printf(1
Definition zic.c:682