PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2025, 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 status, const char *logdetail);
49static char *recv_password_packet(Port *port);
50
51
52/*----------------------------------------------------------------
53 * Password-based authentication methods (password, md5, and scram-sha-256)
54 *----------------------------------------------------------------
55 */
56static int CheckPasswordAuth(Port *port, const char **logdetail);
57static int CheckPWChallengeAuth(Port *port, const char **logdetail);
58
59static int CheckMD5Auth(Port *port, char *shadow_pass,
60 const char **logdetail);
61
62
63/*----------------------------------------------------------------
64 * Ident authentication
65 *----------------------------------------------------------------
66 */
67/* Max size of username ident server can return (per RFC 1413) */
68#define IDENT_USERNAME_MAX 512
69
70/* Standard TCP port number for Ident service. Assigned by IANA */
71#define IDENT_PORT 113
72
73static int ident_inet(hbaPort *port);
74
75
76/*----------------------------------------------------------------
77 * Peer authentication
78 *----------------------------------------------------------------
79 */
80static int auth_peer(hbaPort *port);
81
82
83/*----------------------------------------------------------------
84 * PAM authentication
85 *----------------------------------------------------------------
86 */
87#ifdef USE_PAM
88#ifdef HAVE_PAM_PAM_APPL_H
89#include <pam/pam_appl.h>
90#endif
91#ifdef HAVE_SECURITY_PAM_APPL_H
92#include <security/pam_appl.h>
93#endif
94
95#define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */
96
97static int CheckPAMAuth(Port *port, const char *user, const char *password);
98static int pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
99 struct pam_response **resp, void *appdata_ptr);
100
101static struct pam_conv pam_passw_conv = {
102 &pam_passwd_conv_proc,
103 NULL
104};
105
106static const char *pam_passwd = NULL; /* Workaround for Solaris 2.6
107 * brokenness */
108static Port *pam_port_cludge; /* Workaround for passing "Port *port" into
109 * pam_passwd_conv_proc */
110static bool pam_no_password; /* For detecting no-password-given */
111#endif /* USE_PAM */
112
113
114/*----------------------------------------------------------------
115 * BSD authentication
116 *----------------------------------------------------------------
117 */
118#ifdef USE_BSD_AUTH
119#include <bsd_auth.h>
120
121static int CheckBSDAuth(Port *port, char *user);
122#endif /* USE_BSD_AUTH */
123
124
125/*----------------------------------------------------------------
126 * LDAP authentication
127 *----------------------------------------------------------------
128 */
129#ifdef USE_LDAP
130#ifndef WIN32
131/* We use a deprecated function to keep the codepath the same as win32. */
132#define LDAP_DEPRECATED 1
133#include <ldap.h>
134#else
135#include <winldap.h>
136
137#endif
138
139static int CheckLDAPAuth(Port *port);
140
141/* LDAP_OPT_DIAGNOSTIC_MESSAGE is the newer spelling */
142#ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE
143#define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING
144#endif
145
146/* Default LDAP password mutator hook, can be overridden by a shared library */
147static char *dummy_ldap_password_mutator(char *input);
148auth_password_hook_typ ldap_password_hook = dummy_ldap_password_mutator;
149
150#endif /* USE_LDAP */
151
152/*----------------------------------------------------------------
153 * Cert authentication
154 *----------------------------------------------------------------
155 */
156#ifdef USE_SSL
157static int CheckCertAuth(Port *port);
158#endif
159
160
161/*----------------------------------------------------------------
162 * Kerberos and GSSAPI GUCs
163 *----------------------------------------------------------------
164 */
168
169
170/*----------------------------------------------------------------
171 * GSSAPI Authentication
172 *----------------------------------------------------------------
173 */
174#ifdef ENABLE_GSS
176
177static int pg_GSS_checkauth(Port *port);
178static int pg_GSS_recvauth(Port *port);
179#endif /* ENABLE_GSS */
180
181
182/*----------------------------------------------------------------
183 * SSPI Authentication
184 *----------------------------------------------------------------
185 */
186#ifdef ENABLE_SSPI
187typedef SECURITY_STATUS
188 (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (PCtxtHandle, void **);
189static int pg_SSPI_recvauth(Port *port);
190static int pg_SSPI_make_upn(char *accountname,
191 size_t accountnamesize,
192 char *domainname,
193 size_t domainnamesize,
194 bool update_accountname);
195#endif
196
197/*----------------------------------------------------------------
198 * RADIUS Authentication
199 *----------------------------------------------------------------
200 */
201static int CheckRADIUSAuth(Port *port);
202static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd);
203
204
205/*----------------------------------------------------------------
206 * Global authentication functions
207 *----------------------------------------------------------------
208 */
209
210/*
211 * This hook allows plugins to get control following client authentication,
212 * but before the user has been informed about the results. It could be used
213 * to record login events, insert a delay after failed authentication, etc.
214 */
216
217/*
218 * Tell the user the authentication failed, but not (much about) why.
219 *
220 * There is a tradeoff here between security concerns and making life
221 * unnecessarily difficult for legitimate users. We would not, for example,
222 * want to report the password we were expecting to receive...
223 * But it seems useful to report the username and authorization method
224 * in use, and these are items that must be presumed known to an attacker
225 * anyway.
226 * Note that many sorts of failure report additional information in the
227 * postmaster log, which we hope is only readable by good guys. In
228 * particular, if logdetail isn't NULL, we send that string to the log.
229 */
230static void
231auth_failed(Port *port, int status, const char *logdetail)
232{
233 const char *errstr;
234 char *cdetail;
235 int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
236
237 /*
238 * If we failed due to EOF from client, just quit; there's no point in
239 * trying to send a message to the client, and not much point in logging
240 * the failure in the postmaster log. (Logging the failure might be
241 * desirable, were it not for the fact that libpq closes the connection
242 * unceremoniously if challenged for a password when it hasn't got one to
243 * send. We'll get a useless log entry for every psql connection under
244 * password auth, even if it's perfectly successful, if we log STATUS_EOF
245 * events.)
246 */
247 if (status == STATUS_EOF)
248 proc_exit(0);
249
250 switch (port->hba->auth_method)
251 {
252 case uaReject:
253 case uaImplicitReject:
254 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
255 break;
256 case uaTrust:
257 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
258 break;
259 case uaIdent:
260 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
261 break;
262 case uaPeer:
263 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
264 break;
265 case uaPassword:
266 case uaMD5:
267 case uaSCRAM:
268 errstr = gettext_noop("password authentication failed for user \"%s\"");
269 /* We use it to indicate if a .pgpass password failed. */
270 errcode_return = ERRCODE_INVALID_PASSWORD;
271 break;
272 case uaGSS:
273 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
274 break;
275 case uaSSPI:
276 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
277 break;
278 case uaPAM:
279 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
280 break;
281 case uaBSD:
282 errstr = gettext_noop("BSD authentication failed for user \"%s\"");
283 break;
284 case uaLDAP:
285 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
286 break;
287 case uaCert:
288 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
289 break;
290 case uaRADIUS:
291 errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
292 break;
293 case uaOAuth:
294 errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\"");
295 break;
296 default:
297 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
298 break;
299 }
300
301 cdetail = psprintf(_("Connection matched file \"%s\" line %d: \"%s\""),
302 port->hba->sourcefile, port->hba->linenumber,
303 port->hba->rawline);
304 if (logdetail)
305 logdetail = psprintf("%s\n%s", logdetail, cdetail);
306 else
307 logdetail = cdetail;
308
310 (errcode(errcode_return),
311 errmsg(errstr, port->user_name),
312 logdetail ? errdetail_log("%s", logdetail) : 0));
313
314 /* doesn't return */
315}
316
317
318/*
319 * Sets the authenticated identity for the current user. The provided string
320 * will be stored into MyClientConnectionInfo, alongside the current HBA
321 * method in use. The ID will be logged if log_connections has the
322 * 'authentication' option specified.
323 *
324 * Auth methods should call this routine exactly once, as soon as the user is
325 * successfully authenticated, even if they have reasons to know that
326 * authorization will fail later.
327 *
328 * The provided string will be copied into TopMemoryContext, to match the
329 * lifetime of MyClientConnectionInfo, so it is safe to pass a string that is
330 * managed by an external library.
331 */
332void
333set_authn_id(Port *port, const char *id)
334{
335 Assert(id);
336
338 {
339 /*
340 * An existing authn_id should never be overwritten; that means two
341 * authentication providers are fighting (or one is fighting itself).
342 * Don't leak any authn details to the client, but don't let the
343 * connection continue, either.
344 */
346 (errmsg("authentication identifier set more than once"),
347 errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
349 }
350
352 MyClientConnectionInfo.auth_method = port->hba->auth_method;
353
355 {
356 ereport(LOG,
357 errmsg("connection authenticated: identity=\"%s\" method=%s "
358 "(%s:%d)",
361 port->hba->sourcefile, port->hba->linenumber));
362 }
363}
364
365
366/*
367 * Client authentication starts here. If there is an error, this
368 * function does not return and the backend process is terminated.
369 */
370void
372{
373 int status = STATUS_ERROR;
374 const char *logdetail = NULL;
375
376 /*
377 * Get the authentication method to use for this frontend/database
378 * combination. Note: we do not parse the file at this point; this has
379 * already been done elsewhere. hba.c dropped an error message into the
380 * server logfile if parsing the hba config file failed.
381 */
383
385
386 /*
387 * This is the first point where we have access to the hba record for the
388 * current connection, so perform any verifications based on the hba
389 * options field that should be done *before* the authentication here.
390 */
391 if (port->hba->clientcert != clientCertOff)
392 {
393 /* If we haven't loaded a root certificate store, fail */
396 (errcode(ERRCODE_CONFIG_FILE_ERROR),
397 errmsg("client certificates can only be checked if a root certificate store is available")));
398
399 /*
400 * If we loaded a root certificate store, and if a certificate is
401 * present on the client, then it has been verified against our root
402 * certificate store, and the connection would have been aborted
403 * already if it didn't verify ok.
404 */
405 if (!port->peer_cert_valid)
407 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
408 errmsg("connection requires a valid client certificate")));
409 }
410
411 /*
412 * Now proceed to do the actual authentication check
413 */
414 switch (port->hba->auth_method)
415 {
416 case uaReject:
417
418 /*
419 * An explicit "reject" entry in pg_hba.conf. This report exposes
420 * the fact that there's an explicit reject entry, which is
421 * perhaps not so desirable from a security standpoint; but the
422 * message for an implicit reject could confuse the DBA a lot when
423 * the true situation is a match to an explicit reject. And we
424 * don't want to change the message for an implicit reject. As
425 * noted below, the additional information shown here doesn't
426 * expose anything not known to an attacker.
427 */
428 {
429 char hostinfo[NI_MAXHOST];
430 const char *encryption_state;
431
432 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
433 hostinfo, sizeof(hostinfo),
434 NULL, 0,
435 NI_NUMERICHOST);
436
437 encryption_state =
438#ifdef ENABLE_GSS
439 (port->gss && port->gss->enc) ? _("GSS encryption") :
440#endif
441#ifdef USE_SSL
442 port->ssl_in_use ? _("SSL encryption") :
443#endif
444 _("no encryption");
445
448 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
449 /* translator: last %s describes encryption state */
450 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
451 hostinfo, port->user_name,
452 encryption_state)));
453 else
455 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
456 /* translator: last %s describes encryption state */
457 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
458 hostinfo, port->user_name,
459 port->database_name,
460 encryption_state)));
461 break;
462 }
463
464 case uaImplicitReject:
465
466 /*
467 * No matching entry, so tell the user we fell through.
468 *
469 * NOTE: the extra info reported here is not a security breach,
470 * because all that info is known at the frontend and must be
471 * assumed known to bad guys. We're merely helping out the less
472 * clueful good guys.
473 */
474 {
475 char hostinfo[NI_MAXHOST];
476 const char *encryption_state;
477
478 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
479 hostinfo, sizeof(hostinfo),
480 NULL, 0,
481 NI_NUMERICHOST);
482
483 encryption_state =
484#ifdef ENABLE_GSS
485 (port->gss && port->gss->enc) ? _("GSS encryption") :
486#endif
487#ifdef USE_SSL
488 port->ssl_in_use ? _("SSL encryption") :
489#endif
490 _("no encryption");
491
492#define HOSTNAME_LOOKUP_DETAIL(port) \
493 (port->remote_hostname ? \
494 (port->remote_hostname_resolv == +1 ? \
495 errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
496 port->remote_hostname) : \
497 port->remote_hostname_resolv == 0 ? \
498 errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
499 port->remote_hostname) : \
500 port->remote_hostname_resolv == -1 ? \
501 errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
502 port->remote_hostname) : \
503 port->remote_hostname_resolv == -2 ? \
504 errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
505 port->remote_hostname, \
506 gai_strerror(port->remote_hostname_errcode)) : \
507 0) \
508 : (port->remote_hostname_resolv == -2 ? \
509 errdetail_log("Could not resolve client IP address to a host name: %s.", \
510 gai_strerror(port->remote_hostname_errcode)) : \
511 0))
512
515 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
516 /* translator: last %s describes encryption state */
517 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
518 hostinfo, port->user_name,
519 encryption_state),
521 else
523 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
524 /* translator: last %s describes encryption state */
525 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
526 hostinfo, port->user_name,
527 port->database_name,
528 encryption_state),
530 break;
531 }
532
533 case uaGSS:
534#ifdef ENABLE_GSS
535 /* We might or might not have the gss workspace already */
536 if (port->gss == NULL)
537 port->gss = (pg_gssinfo *)
539 sizeof(pg_gssinfo));
540 port->gss->auth = true;
541
542 /*
543 * If GSS state was set up while enabling encryption, we can just
544 * check the client's principal. Otherwise, ask for it.
545 */
546 if (port->gss->enc)
547 status = pg_GSS_checkauth(port);
548 else
549 {
551 status = pg_GSS_recvauth(port);
552 }
553#else
554 Assert(false);
555#endif
556 break;
557
558 case uaSSPI:
559#ifdef ENABLE_SSPI
560 if (port->gss == NULL)
561 port->gss = (pg_gssinfo *)
563 sizeof(pg_gssinfo));
565 status = pg_SSPI_recvauth(port);
566#else
567 Assert(false);
568#endif
569 break;
570
571 case uaPeer:
572 status = auth_peer(port);
573 break;
574
575 case uaIdent:
576 status = ident_inet(port);
577 break;
578
579 case uaMD5:
580 case uaSCRAM:
581 status = CheckPWChallengeAuth(port, &logdetail);
582 break;
583
584 case uaPassword:
585 status = CheckPasswordAuth(port, &logdetail);
586 break;
587
588 case uaPAM:
589#ifdef USE_PAM
590 status = CheckPAMAuth(port, port->user_name, "");
591#else
592 Assert(false);
593#endif /* USE_PAM */
594 break;
595
596 case uaBSD:
597#ifdef USE_BSD_AUTH
598 status = CheckBSDAuth(port, port->user_name);
599#else
600 Assert(false);
601#endif /* USE_BSD_AUTH */
602 break;
603
604 case uaLDAP:
605#ifdef USE_LDAP
606 status = CheckLDAPAuth(port);
607#else
608 Assert(false);
609#endif
610 break;
611 case uaRADIUS:
612 status = CheckRADIUSAuth(port);
613 break;
614 case uaCert:
615 /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
616 case uaTrust:
617 status = STATUS_OK;
618 break;
619 case uaOAuth:
620 status = CheckSASLAuth(&pg_be_oauth_mech, port, NULL, NULL);
621 break;
622 }
623
624 if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
625 || port->hba->auth_method == uaCert)
626 {
627 /*
628 * Make sure we only check the certificate if we use the cert method
629 * or verify-full option.
630 */
631#ifdef USE_SSL
632 status = CheckCertAuth(port);
633#else
634 Assert(false);
635#endif
636 }
637
639 status == STATUS_OK &&
641 {
642 /*
643 * Normally, if log_connections is set, the call to set_authn_id()
644 * will log the connection. However, if that function is never
645 * called, perhaps because the trust method is in use, then we handle
646 * the logging here instead.
647 */
648 ereport(LOG,
649 errmsg("connection authenticated: user=\"%s\" method=%s "
650 "(%s:%d)",
651 port->user_name, hba_authname(port->hba->auth_method),
652 port->hba->sourcefile, port->hba->linenumber));
653 }
654
656 (*ClientAuthentication_hook) (port, status);
657
658 if (status == STATUS_OK)
660 else
661 auth_failed(port, status, logdetail);
662}
663
664
665/*
666 * Send an authentication request packet to the frontend.
667 */
668void
669sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
670{
672
674
676 pq_sendint32(&buf, (int32) areq);
677 if (extralen > 0)
678 pq_sendbytes(&buf, extradata, extralen);
679
681
682 /*
683 * Flush message so client will see it, except for AUTH_REQ_OK and
684 * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
685 * queries.
686 */
687 if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
688 pq_flush();
689
691}
692
693/*
694 * Collect password response packet from frontend.
695 *
696 * Returns NULL if couldn't get password, else palloc'd string.
697 */
698static char *
700{
702 int mtype;
703
705
706 /* Expect 'p' message type */
707 mtype = pq_getbyte();
708 if (mtype != PqMsg_PasswordMessage)
709 {
710 /*
711 * If the client just disconnects without offering a password, don't
712 * make a log entry. This is legal per protocol spec and in fact
713 * commonly done by psql, so complaining just clutters the log.
714 */
715 if (mtype != EOF)
717 (errcode(ERRCODE_PROTOCOL_VIOLATION),
718 errmsg("expected password response, got message type %d",
719 mtype)));
720 return NULL; /* EOF or bad message type */
721 }
722
724 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH)) /* receive password */
725 {
726 /* EOF - pq_getmessage already logged a suitable message */
727 pfree(buf.data);
728 return NULL;
729 }
730
731 /*
732 * Apply sanity check: password packet length should agree with length of
733 * contained string. Note it is safe to use strlen here because
734 * StringInfo is guaranteed to have an appended '\0'.
735 */
736 if (strlen(buf.data) + 1 != buf.len)
738 (errcode(ERRCODE_PROTOCOL_VIOLATION),
739 errmsg("invalid password packet size")));
740
741 /*
742 * Don't allow an empty password. Libpq treats an empty password the same
743 * as no password at all, and won't even try to authenticate. But other
744 * clients might, so allowing it would be confusing.
745 *
746 * Note that this only catches an empty password sent by the client in
747 * plaintext. There's also a check in CREATE/ALTER USER that prevents an
748 * empty string from being stored as a user's password in the first place.
749 * We rely on that for MD5 and SCRAM authentication, but we still need
750 * this check here, to prevent an empty password from being used with
751 * authentication methods that check the password against an external
752 * system, like PAM, LDAP and RADIUS.
753 */
754 if (buf.len == 1)
757 errmsg("empty password returned by client")));
758
759 /* Do not echo password to logs, for security. */
760 elog(DEBUG5, "received password packet");
761
762 /*
763 * Return the received string. Note we do not attempt to do any
764 * character-set conversion on it; since we don't yet know the client's
765 * encoding, there wouldn't be much point.
766 */
767 return buf.data;
768}
769
770
771/*----------------------------------------------------------------
772 * Password-based authentication mechanisms
773 *----------------------------------------------------------------
774 */
775
776/*
777 * Plaintext password authentication.
778 */
779static int
780CheckPasswordAuth(Port *port, const char **logdetail)
781{
782 char *passwd;
783 int result;
784 char *shadow_pass;
785
787
788 passwd = recv_password_packet(port);
789 if (passwd == NULL)
790 return STATUS_EOF; /* client wouldn't send password */
791
792 shadow_pass = get_role_password(port->user_name, logdetail);
793 if (shadow_pass)
794 {
795 result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
796 logdetail);
797 }
798 else
799 result = STATUS_ERROR;
800
801 if (shadow_pass)
802 pfree(shadow_pass);
803 pfree(passwd);
804
805 if (result == STATUS_OK)
806 set_authn_id(port, port->user_name);
807
808 return result;
809}
810
811/*
812 * MD5 and SCRAM authentication.
813 */
814static int
815CheckPWChallengeAuth(Port *port, const char **logdetail)
816{
817 int auth_result;
818 char *shadow_pass;
819 PasswordType pwtype;
820
821 Assert(port->hba->auth_method == uaSCRAM ||
822 port->hba->auth_method == uaMD5);
823
824 /* First look up the user's password. */
825 shadow_pass = get_role_password(port->user_name, logdetail);
826
827 /*
828 * If the user does not exist, or has no password or it's expired, we
829 * still go through the motions of authentication, to avoid revealing to
830 * the client that the user didn't exist. If 'md5' is allowed, we choose
831 * whether to use 'md5' or 'scram-sha-256' authentication based on current
832 * password_encryption setting. The idea is that most genuine users
833 * probably have a password of that type, and if we pretend that this user
834 * had a password of that type, too, it "blends in" best.
835 */
836 if (!shadow_pass)
837 pwtype = Password_encryption;
838 else
839 pwtype = get_password_type(shadow_pass);
840
841 /*
842 * If 'md5' authentication is allowed, decide whether to perform 'md5' or
843 * 'scram-sha-256' authentication based on the type of password the user
844 * has. If it's an MD5 hash, we must do MD5 authentication, and if it's a
845 * SCRAM secret, we must do SCRAM authentication.
846 *
847 * If MD5 authentication is not allowed, always use SCRAM. If the user
848 * had an MD5 password, CheckSASLAuth() with the SCRAM mechanism will
849 * fail.
850 */
851 if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
852 auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
853 else
854 auth_result = CheckSASLAuth(&pg_be_scram_mech, port, shadow_pass,
855 logdetail);
856
857 if (shadow_pass)
858 pfree(shadow_pass);
859 else
860 {
861 /*
862 * If get_role_password() returned error, authentication better not
863 * have succeeded.
864 */
865 Assert(auth_result != STATUS_OK);
866 }
867
868 if (auth_result == STATUS_OK)
869 set_authn_id(port, port->user_name);
870
871 return auth_result;
872}
873
874static int
875CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
876{
877 char md5Salt[4]; /* Password salt */
878 char *passwd;
879 int result;
880
881 /* include the salt to use for computing the response */
882 if (!pg_strong_random(md5Salt, 4))
883 {
884 ereport(LOG,
885 (errmsg("could not generate random MD5 salt")));
886 return STATUS_ERROR;
887 }
888
889 sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
890
891 passwd = recv_password_packet(port);
892 if (passwd == NULL)
893 return STATUS_EOF; /* client wouldn't send password */
894
895 if (shadow_pass)
896 result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
897 md5Salt, 4, logdetail);
898 else
899 result = STATUS_ERROR;
900
901 pfree(passwd);
902
903 return result;
904}
905
906
907/*----------------------------------------------------------------
908 * GSSAPI authentication system
909 *----------------------------------------------------------------
910 */
911#ifdef ENABLE_GSS
912static int
913pg_GSS_recvauth(Port *port)
914{
915 OM_uint32 maj_stat,
916 min_stat,
917 lmin_s,
918 gflags;
919 int mtype;
921 gss_buffer_desc gbuf;
922 gss_cred_id_t delegated_creds;
923
924 /*
925 * Use the configured keytab, if there is one. As we now require MIT
926 * Kerberos, we might consider using the credential store extensions in
927 * the future instead of the environment variable.
928 */
929 if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
930 {
931 if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
932 {
933 /* The only likely failure cause is OOM, so use that errcode */
935 (errcode(ERRCODE_OUT_OF_MEMORY),
936 errmsg("could not set environment: %m")));
937 }
938 }
939
940 /*
941 * We accept any service principal that's present in our keytab. This
942 * increases interoperability between kerberos implementations that see
943 * for example case sensitivity differently, while not really opening up
944 * any vector of attack.
945 */
946 port->gss->cred = GSS_C_NO_CREDENTIAL;
947
948 /*
949 * Initialize sequence with an empty context
950 */
951 port->gss->ctx = GSS_C_NO_CONTEXT;
952
953 delegated_creds = GSS_C_NO_CREDENTIAL;
954 port->gss->delegated_creds = false;
955
956 /*
957 * Loop through GSSAPI message exchange. This exchange can consist of
958 * multiple messages sent in both directions. First message is always from
959 * the client. All messages from client to server are password packets
960 * (type 'p').
961 */
962 do
963 {
965
967
968 mtype = pq_getbyte();
969 if (mtype != PqMsg_GSSResponse)
970 {
971 /* Only log error if client didn't disconnect. */
972 if (mtype != EOF)
974 (errcode(ERRCODE_PROTOCOL_VIOLATION),
975 errmsg("expected GSS response, got message type %d",
976 mtype)));
977 return STATUS_ERROR;
978 }
979
980 /* Get the actual GSS token */
983 {
984 /* EOF - pq_getmessage already logged error */
985 pfree(buf.data);
986 return STATUS_ERROR;
987 }
988
989 /* Map to GSSAPI style buffer */
990 gbuf.length = buf.len;
991 gbuf.value = buf.data;
992
993 elog(DEBUG4, "processing received GSS token of length %u",
994 (unsigned int) gbuf.length);
995
996 maj_stat = gss_accept_sec_context(&min_stat,
997 &port->gss->ctx,
998 port->gss->cred,
999 &gbuf,
1000 GSS_C_NO_CHANNEL_BINDINGS,
1001 &port->gss->name,
1002 NULL,
1003 &port->gss->outbuf,
1004 &gflags,
1005 NULL,
1006 pg_gss_accept_delegation ? &delegated_creds : NULL);
1007
1008 /* gbuf no longer used */
1009 pfree(buf.data);
1010
1011 elog(DEBUG5, "gss_accept_sec_context major: %u, "
1012 "minor: %u, outlen: %u, outflags: %x",
1013 maj_stat, min_stat,
1014 (unsigned int) port->gss->outbuf.length, gflags);
1015
1017
1018 if (delegated_creds != GSS_C_NO_CREDENTIAL && gflags & GSS_C_DELEG_FLAG)
1019 {
1020 pg_store_delegated_credential(delegated_creds);
1021 port->gss->delegated_creds = true;
1022 }
1023
1024 if (port->gss->outbuf.length != 0)
1025 {
1026 /*
1027 * Negotiation generated data to be sent to the client.
1028 */
1029 elog(DEBUG4, "sending GSS response token of length %u",
1030 (unsigned int) port->gss->outbuf.length);
1031
1033 port->gss->outbuf.value, port->gss->outbuf.length);
1034
1035 gss_release_buffer(&lmin_s, &port->gss->outbuf);
1036 }
1037
1038 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
1039 {
1040 gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
1041 pg_GSS_error(_("accepting GSS security context failed"),
1042 maj_stat, min_stat);
1043 return STATUS_ERROR;
1044 }
1045
1046 if (maj_stat == GSS_S_CONTINUE_NEEDED)
1047 elog(DEBUG4, "GSS continue needed");
1048
1049 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
1050
1051 if (port->gss->cred != GSS_C_NO_CREDENTIAL)
1052 {
1053 /*
1054 * Release service principal credentials
1055 */
1056 gss_release_cred(&min_stat, &port->gss->cred);
1057 }
1058 return pg_GSS_checkauth(port);
1059}
1060
1061/*
1062 * Check whether the GSSAPI-authenticated user is allowed to connect as the
1063 * claimed username.
1064 */
1065static int
1066pg_GSS_checkauth(Port *port)
1067{
1068 int ret;
1069 OM_uint32 maj_stat,
1070 min_stat,
1071 lmin_s;
1072 gss_buffer_desc gbuf;
1073 char *princ;
1074
1075 /*
1076 * Get the name of the user that authenticated, and compare it to the pg
1077 * username that was specified for the connection.
1078 */
1079 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
1080 if (maj_stat != GSS_S_COMPLETE)
1081 {
1082 pg_GSS_error(_("retrieving GSS user name failed"),
1083 maj_stat, min_stat);
1084 return STATUS_ERROR;
1085 }
1086
1087 /*
1088 * gbuf.value might not be null-terminated, so turn it into a regular
1089 * null-terminated string.
1090 */
1091 princ = palloc(gbuf.length + 1);
1092 memcpy(princ, gbuf.value, gbuf.length);
1093 princ[gbuf.length] = '\0';
1094 gss_release_buffer(&lmin_s, &gbuf);
1095
1096 /*
1097 * Copy the original name of the authenticated principal into our backend
1098 * memory for display later.
1099 *
1100 * This is also our authenticated identity. Set it now, rather than
1101 * waiting for the usermap check below, because authentication has already
1102 * succeeded and we want the log file to reflect that.
1103 */
1104 port->gss->princ = MemoryContextStrdup(TopMemoryContext, princ);
1105 set_authn_id(port, princ);
1106
1107 /*
1108 * Split the username at the realm separator
1109 */
1110 if (strchr(princ, '@'))
1111 {
1112 char *cp = strchr(princ, '@');
1113
1114 /*
1115 * If we are not going to include the realm in the username that is
1116 * passed to the ident map, destructively modify it here to remove the
1117 * realm. Then advance past the separator to check the realm.
1118 */
1119 if (!port->hba->include_realm)
1120 *cp = '\0';
1121 cp++;
1122
1123 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
1124 {
1125 /*
1126 * Match the realm part of the name first
1127 */
1129 ret = pg_strcasecmp(port->hba->krb_realm, cp);
1130 else
1131 ret = strcmp(port->hba->krb_realm, cp);
1132
1133 if (ret)
1134 {
1135 /* GSS realm does not match */
1136 elog(DEBUG2,
1137 "GSSAPI realm (%s) and configured realm (%s) don't match",
1138 cp, port->hba->krb_realm);
1139 pfree(princ);
1140 return STATUS_ERROR;
1141 }
1142 }
1143 }
1144 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1145 {
1146 elog(DEBUG2,
1147 "GSSAPI did not return realm but realm matching was requested");
1148 pfree(princ);
1149 return STATUS_ERROR;
1150 }
1151
1152 ret = check_usermap(port->hba->usermap, port->user_name, princ,
1154
1155 pfree(princ);
1156
1157 return ret;
1158}
1159#endif /* ENABLE_GSS */
1160
1161
1162/*----------------------------------------------------------------
1163 * SSPI authentication system
1164 *----------------------------------------------------------------
1165 */
1166#ifdef ENABLE_SSPI
1167
1168/*
1169 * Generate an error for SSPI authentication. The caller should apply
1170 * _() to errmsg to make it translatable.
1171 */
1172static void
1173pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
1174{
1175 char sysmsg[256];
1176
1177 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
1178 FORMAT_MESSAGE_FROM_SYSTEM,
1179 NULL, r, 0,
1180 sysmsg, sizeof(sysmsg), NULL) == 0)
1181 ereport(severity,
1182 (errmsg_internal("%s", errmsg),
1183 errdetail_internal("SSPI error %x", (unsigned int) r)));
1184 else
1185 ereport(severity,
1186 (errmsg_internal("%s", errmsg),
1187 errdetail_internal("%s (%x)", sysmsg, (unsigned int) r)));
1188}
1189
1190static int
1191pg_SSPI_recvauth(Port *port)
1192{
1193 int mtype;
1195 SECURITY_STATUS r;
1196 CredHandle sspicred;
1197 CtxtHandle *sspictx = NULL,
1198 newctx;
1199 TimeStamp expiry;
1200 ULONG contextattr;
1201 SecBufferDesc inbuf;
1202 SecBufferDesc outbuf;
1203 SecBuffer OutBuffers[1];
1204 SecBuffer InBuffers[1];
1205 HANDLE token;
1206 TOKEN_USER *tokenuser;
1207 DWORD retlen;
1208 char accountname[MAXPGPATH];
1209 char domainname[MAXPGPATH];
1210 DWORD accountnamesize = sizeof(accountname);
1211 DWORD domainnamesize = sizeof(domainname);
1212 SID_NAME_USE accountnameuse;
1213 char *authn_id;
1214
1215 /*
1216 * Acquire a handle to the server credentials.
1217 */
1218 r = AcquireCredentialsHandle(NULL,
1219 "negotiate",
1220 SECPKG_CRED_INBOUND,
1221 NULL,
1222 NULL,
1223 NULL,
1224 NULL,
1225 &sspicred,
1226 &expiry);
1227 if (r != SEC_E_OK)
1228 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
1229
1230 /*
1231 * Loop through SSPI message exchange. This exchange can consist of
1232 * multiple messages sent in both directions. First message is always from
1233 * the client. All messages from client to server are password packets
1234 * (type 'p').
1235 */
1236 do
1237 {
1239 mtype = pq_getbyte();
1240 if (mtype != PqMsg_GSSResponse)
1241 {
1242 if (sspictx != NULL)
1243 {
1244 DeleteSecurityContext(sspictx);
1245 free(sspictx);
1246 }
1247 FreeCredentialsHandle(&sspicred);
1248
1249 /* Only log error if client didn't disconnect. */
1250 if (mtype != EOF)
1251 ereport(ERROR,
1252 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1253 errmsg("expected SSPI response, got message type %d",
1254 mtype)));
1255 return STATUS_ERROR;
1256 }
1257
1258 /* Get the actual SSPI token */
1261 {
1262 /* EOF - pq_getmessage already logged error */
1263 pfree(buf.data);
1264 if (sspictx != NULL)
1265 {
1266 DeleteSecurityContext(sspictx);
1267 free(sspictx);
1268 }
1269 FreeCredentialsHandle(&sspicred);
1270 return STATUS_ERROR;
1271 }
1272
1273 /* Map to SSPI style buffer */
1274 inbuf.ulVersion = SECBUFFER_VERSION;
1275 inbuf.cBuffers = 1;
1276 inbuf.pBuffers = InBuffers;
1277 InBuffers[0].pvBuffer = buf.data;
1278 InBuffers[0].cbBuffer = buf.len;
1279 InBuffers[0].BufferType = SECBUFFER_TOKEN;
1280
1281 /* Prepare output buffer */
1282 OutBuffers[0].pvBuffer = NULL;
1283 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1284 OutBuffers[0].cbBuffer = 0;
1285 outbuf.cBuffers = 1;
1286 outbuf.pBuffers = OutBuffers;
1287 outbuf.ulVersion = SECBUFFER_VERSION;
1288
1289 elog(DEBUG4, "processing received SSPI token of length %u",
1290 (unsigned int) buf.len);
1291
1292 r = AcceptSecurityContext(&sspicred,
1293 sspictx,
1294 &inbuf,
1295 ASC_REQ_ALLOCATE_MEMORY,
1296 SECURITY_NETWORK_DREP,
1297 &newctx,
1298 &outbuf,
1299 &contextattr,
1300 NULL);
1301
1302 /* input buffer no longer used */
1303 pfree(buf.data);
1304
1305 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
1306 {
1307 /*
1308 * Negotiation generated data to be sent to the client.
1309 */
1310 elog(DEBUG4, "sending SSPI response token of length %u",
1311 (unsigned int) outbuf.pBuffers[0].cbBuffer);
1312
1313 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
1314 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
1315
1317 port->gss->outbuf.value, port->gss->outbuf.length);
1318
1319 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
1320 }
1321
1322 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
1323 {
1324 if (sspictx != NULL)
1325 {
1326 DeleteSecurityContext(sspictx);
1327 free(sspictx);
1328 }
1329 FreeCredentialsHandle(&sspicred);
1330 pg_SSPI_error(ERROR,
1331 _("could not accept SSPI security context"), r);
1332 }
1333
1334 /*
1335 * Overwrite the current context with the one we just received. If
1336 * sspictx is NULL it was the first loop and we need to allocate a
1337 * buffer for it. On subsequent runs, we can just overwrite the buffer
1338 * contents since the size does not change.
1339 */
1340 if (sspictx == NULL)
1341 {
1342 sspictx = malloc(sizeof(CtxtHandle));
1343 if (sspictx == NULL)
1344 ereport(ERROR,
1345 (errmsg("out of memory")));
1346 }
1347
1348 memcpy(sspictx, &newctx, sizeof(CtxtHandle));
1349
1350 if (r == SEC_I_CONTINUE_NEEDED)
1351 elog(DEBUG4, "SSPI continue needed");
1352
1353 } while (r == SEC_I_CONTINUE_NEEDED);
1354
1355
1356 /*
1357 * Release service principal credentials
1358 */
1359 FreeCredentialsHandle(&sspicred);
1360
1361
1362 /*
1363 * SEC_E_OK indicates that authentication is now complete.
1364 *
1365 * Get the name of the user that authenticated, and compare it to the pg
1366 * username that was specified for the connection.
1367 */
1368
1369 r = QuerySecurityContextToken(sspictx, &token);
1370 if (r != SEC_E_OK)
1371 pg_SSPI_error(ERROR,
1372 _("could not get token from SSPI security context"), r);
1373
1374 /*
1375 * No longer need the security context, everything from here on uses the
1376 * token instead.
1377 */
1378 DeleteSecurityContext(sspictx);
1379 free(sspictx);
1380
1381 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
1382 ereport(ERROR,
1383 (errmsg_internal("could not get token information buffer size: error code %lu",
1384 GetLastError())));
1385
1386 tokenuser = malloc(retlen);
1387 if (tokenuser == NULL)
1388 ereport(ERROR,
1389 (errmsg("out of memory")));
1390
1391 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
1392 ereport(ERROR,
1393 (errmsg_internal("could not get token information: error code %lu",
1394 GetLastError())));
1395
1396 CloseHandle(token);
1397
1398 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
1399 domainname, &domainnamesize, &accountnameuse))
1400 ereport(ERROR,
1401 (errmsg_internal("could not look up account SID: error code %lu",
1402 GetLastError())));
1403
1404 free(tokenuser);
1405
1406 if (!port->hba->compat_realm)
1407 {
1408 int status = pg_SSPI_make_upn(accountname, sizeof(accountname),
1409 domainname, sizeof(domainname),
1410 port->hba->upn_username);
1411
1412 if (status != STATUS_OK)
1413 /* Error already reported from pg_SSPI_make_upn */
1414 return status;
1415 }
1416
1417 /*
1418 * We have all of the information necessary to construct the authenticated
1419 * identity. Set it now, rather than waiting for check_usermap below,
1420 * because authentication has already succeeded and we want the log file
1421 * to reflect that.
1422 */
1423 if (port->hba->compat_realm)
1424 {
1425 /* SAM-compatible format. */
1426 authn_id = psprintf("%s\\%s", domainname, accountname);
1427 }
1428 else
1429 {
1430 /* Kerberos principal format. */
1431 authn_id = psprintf("%s@%s", accountname, domainname);
1432 }
1433
1435 pfree(authn_id);
1436
1437 /*
1438 * Compare realm/domain if requested. In SSPI, always compare case
1439 * insensitive.
1440 */
1441 if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1442 {
1443 if (pg_strcasecmp(port->hba->krb_realm, domainname) != 0)
1444 {
1445 elog(DEBUG2,
1446 "SSPI domain (%s) and configured domain (%s) don't match",
1447 domainname, port->hba->krb_realm);
1448
1449 return STATUS_ERROR;
1450 }
1451 }
1452
1453 /*
1454 * We have the username (without domain/realm) in accountname, compare to
1455 * the supplied value. In SSPI, always compare case insensitive.
1456 *
1457 * If set to include realm, append it in <username>@<realm> format.
1458 */
1459 if (port->hba->include_realm)
1460 {
1461 char *namebuf;
1462 int retval;
1463
1464 namebuf = psprintf("%s@%s", accountname, domainname);
1465 retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
1466 pfree(namebuf);
1467 return retval;
1468 }
1469 else
1470 return check_usermap(port->hba->usermap, port->user_name, accountname, true);
1471}
1472
1473/*
1474 * Replaces the domainname with the Kerberos realm name,
1475 * and optionally the accountname with the Kerberos user name.
1476 */
1477static int
1478pg_SSPI_make_upn(char *accountname,
1479 size_t accountnamesize,
1480 char *domainname,
1481 size_t domainnamesize,
1482 bool update_accountname)
1483{
1484 char *samname;
1485 char *upname = NULL;
1486 char *p = NULL;
1487 ULONG upnamesize = 0;
1488 size_t upnamerealmsize;
1489 BOOLEAN res;
1490
1491 /*
1492 * Build SAM name (DOMAIN\user), then translate to UPN
1493 * (user@kerberos.realm). The realm name is returned in lower case, but
1494 * that is fine because in SSPI auth, string comparisons are always
1495 * case-insensitive.
1496 */
1497
1498 samname = psprintf("%s\\%s", domainname, accountname);
1499 res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
1500 NULL, &upnamesize);
1501
1502 if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1503 || upnamesize == 0)
1504 {
1505 pfree(samname);
1506 ereport(LOG,
1507 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1508 errmsg("could not translate name")));
1509 return STATUS_ERROR;
1510 }
1511
1512 /* upnamesize includes the terminating NUL. */
1513 upname = palloc(upnamesize);
1514
1515 res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
1516 upname, &upnamesize);
1517
1518 pfree(samname);
1519 if (res)
1520 p = strchr(upname, '@');
1521
1522 if (!res || p == NULL)
1523 {
1524 pfree(upname);
1525 ereport(LOG,
1526 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1527 errmsg("could not translate name")));
1528 return STATUS_ERROR;
1529 }
1530
1531 /* Length of realm name after the '@', including the NUL. */
1532 upnamerealmsize = upnamesize - (p - upname + 1);
1533
1534 /* Replace domainname with realm name. */
1535 if (upnamerealmsize > domainnamesize)
1536 {
1537 pfree(upname);
1538 ereport(LOG,
1539 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1540 errmsg("realm name too long")));
1541 return STATUS_ERROR;
1542 }
1543
1544 /* Length is now safe. */
1545 strcpy(domainname, p + 1);
1546
1547 /* Replace account name as well (in case UPN != SAM)? */
1548 if (update_accountname)
1549 {
1550 if ((p - upname + 1) > accountnamesize)
1551 {
1552 pfree(upname);
1553 ereport(LOG,
1554 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
1555 errmsg("translated account name too long")));
1556 return STATUS_ERROR;
1557 }
1558
1559 *p = 0;
1560 strcpy(accountname, upname);
1561 }
1562
1563 pfree(upname);
1564 return STATUS_OK;
1565}
1566#endif /* ENABLE_SSPI */
1567
1568
1569
1570/*----------------------------------------------------------------
1571 * Ident authentication system
1572 *----------------------------------------------------------------
1573 */
1574
1575/*
1576 * Parse the string "*ident_response" as a response from a query to an Ident
1577 * server. If it's a normal response indicating a user name, return true
1578 * and store the user name at *ident_user. If it's anything else,
1579 * return false.
1580 */
1581static bool
1582interpret_ident_response(const char *ident_response,
1583 char *ident_user)
1584{
1585 const char *cursor = ident_response; /* Cursor into *ident_response */
1586
1587 /*
1588 * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1589 */
1590 if (strlen(ident_response) < 2)
1591 return false;
1592 else if (ident_response[strlen(ident_response) - 2] != '\r')
1593 return false;
1594 else
1595 {
1596 while (*cursor != ':' && *cursor != '\r')
1597 cursor++; /* skip port field */
1598
1599 if (*cursor != ':')
1600 return false;
1601 else
1602 {
1603 /* We're positioned to colon before response type field */
1604 char response_type[80];
1605 int i; /* Index into *response_type */
1606
1607 cursor++; /* Go over colon */
1608 while (pg_isblank(*cursor))
1609 cursor++; /* skip blanks */
1610 i = 0;
1611 while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1612 i < (int) (sizeof(response_type) - 1))
1613 response_type[i++] = *cursor++;
1614 response_type[i] = '\0';
1615 while (pg_isblank(*cursor))
1616 cursor++; /* skip blanks */
1617 if (strcmp(response_type, "USERID") != 0)
1618 return false;
1619 else
1620 {
1621 /*
1622 * It's a USERID response. Good. "cursor" should be pointing
1623 * to the colon that precedes the operating system type.
1624 */
1625 if (*cursor != ':')
1626 return false;
1627 else
1628 {
1629 cursor++; /* Go over colon */
1630 /* Skip over operating system field. */
1631 while (*cursor != ':' && *cursor != '\r')
1632 cursor++;
1633 if (*cursor != ':')
1634 return false;
1635 else
1636 {
1637 cursor++; /* Go over colon */
1638 while (pg_isblank(*cursor))
1639 cursor++; /* skip blanks */
1640 /* Rest of line is user name. Copy it over. */
1641 i = 0;
1642 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1643 ident_user[i++] = *cursor++;
1644 ident_user[i] = '\0';
1645 return true;
1646 }
1647 }
1648 }
1649 }
1650 }
1651}
1652
1653
1654/*
1655 * Talk to the ident server on "remote_addr" and find out who
1656 * owns the tcp connection to "local_addr"
1657 * If the username is successfully retrieved, check the usermap.
1658 *
1659 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if the
1660 * latch was set would improve the responsiveness to timeouts/cancellations.
1661 */
1662static int
1664{
1665 const SockAddr remote_addr = port->raddr;
1666 const SockAddr local_addr = port->laddr;
1667 char ident_user[IDENT_USERNAME_MAX + 1];
1668 pgsocket sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
1669 int rc; /* Return code from a locally called function */
1670 bool ident_return;
1671 char remote_addr_s[NI_MAXHOST];
1672 char remote_port[NI_MAXSERV];
1673 char local_addr_s[NI_MAXHOST];
1674 char local_port[NI_MAXSERV];
1675 char ident_port[NI_MAXSERV];
1676 char ident_query[80];
1677 char ident_response[80 + IDENT_USERNAME_MAX];
1678 struct addrinfo *ident_serv = NULL,
1679 *la = NULL,
1680 hints;
1681
1682 /*
1683 * Might look a little weird to first convert it to text and then back to
1684 * sockaddr, but it's protocol independent.
1685 */
1686 pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1687 remote_addr_s, sizeof(remote_addr_s),
1688 remote_port, sizeof(remote_port),
1689 NI_NUMERICHOST | NI_NUMERICSERV);
1690 pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1691 local_addr_s, sizeof(local_addr_s),
1692 local_port, sizeof(local_port),
1693 NI_NUMERICHOST | NI_NUMERICSERV);
1694
1695 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1696 hints.ai_flags = AI_NUMERICHOST;
1697 hints.ai_family = remote_addr.addr.ss_family;
1698 hints.ai_socktype = SOCK_STREAM;
1699 hints.ai_protocol = 0;
1700 hints.ai_addrlen = 0;
1701 hints.ai_canonname = NULL;
1702 hints.ai_addr = NULL;
1703 hints.ai_next = NULL;
1704 rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1705 if (rc || !ident_serv)
1706 {
1707 /* we don't expect this to happen */
1708 ident_return = false;
1709 goto ident_inet_done;
1710 }
1711
1712 hints.ai_flags = AI_NUMERICHOST;
1713 hints.ai_family = local_addr.addr.ss_family;
1714 hints.ai_socktype = SOCK_STREAM;
1715 hints.ai_protocol = 0;
1716 hints.ai_addrlen = 0;
1717 hints.ai_canonname = NULL;
1718 hints.ai_addr = NULL;
1719 hints.ai_next = NULL;
1720 rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1721 if (rc || !la)
1722 {
1723 /* we don't expect this to happen */
1724 ident_return = false;
1725 goto ident_inet_done;
1726 }
1727
1728 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1729 ident_serv->ai_protocol);
1730 if (sock_fd == PGINVALID_SOCKET)
1731 {
1732 ereport(LOG,
1734 errmsg("could not create socket for Ident connection: %m")));
1735 ident_return = false;
1736 goto ident_inet_done;
1737 }
1738
1739 /*
1740 * Bind to the address which the client originally contacted, otherwise
1741 * the ident server won't be able to match up the right connection. This
1742 * is necessary if the PostgreSQL server is running on an IP alias.
1743 */
1744 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1745 if (rc != 0)
1746 {
1747 ereport(LOG,
1749 errmsg("could not bind to local address \"%s\": %m",
1750 local_addr_s)));
1751 ident_return = false;
1752 goto ident_inet_done;
1753 }
1754
1755 rc = connect(sock_fd, ident_serv->ai_addr,
1756 ident_serv->ai_addrlen);
1757 if (rc != 0)
1758 {
1759 ereport(LOG,
1761 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1762 remote_addr_s, ident_port)));
1763 ident_return = false;
1764 goto ident_inet_done;
1765 }
1766
1767 /* The query we send to the Ident server */
1768 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1769 remote_port, local_port);
1770
1771 /* loop in case send is interrupted */
1772 do
1773 {
1775
1776 rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1777 } while (rc < 0 && errno == EINTR);
1778
1779 if (rc < 0)
1780 {
1781 ereport(LOG,
1783 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1784 remote_addr_s, ident_port)));
1785 ident_return = false;
1786 goto ident_inet_done;
1787 }
1788
1789 do
1790 {
1792
1793 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1794 } while (rc < 0 && errno == EINTR);
1795
1796 if (rc < 0)
1797 {
1798 ereport(LOG,
1800 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1801 remote_addr_s, ident_port)));
1802 ident_return = false;
1803 goto ident_inet_done;
1804 }
1805
1806 ident_response[rc] = '\0';
1807 ident_return = interpret_ident_response(ident_response, ident_user);
1808 if (!ident_return)
1809 ereport(LOG,
1810 (errmsg("invalidly formatted response from Ident server: \"%s\"",
1811 ident_response)));
1812
1813ident_inet_done:
1814 if (sock_fd != PGINVALID_SOCKET)
1815 closesocket(sock_fd);
1816 if (ident_serv)
1817 pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1818 if (la)
1819 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1820
1821 if (ident_return)
1822 {
1823 /*
1824 * Success! Store the identity, then check the usermap. Note that
1825 * setting the authenticated identity is done before checking the
1826 * usermap, because at this point authentication has succeeded.
1827 */
1828 set_authn_id(port, ident_user);
1829 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1830 }
1831 return STATUS_ERROR;
1832}
1833
1834
1835/*----------------------------------------------------------------
1836 * Peer authentication system
1837 *----------------------------------------------------------------
1838 */
1839
1840/*
1841 * Ask kernel about the credentials of the connecting process,
1842 * determine the symbolic name of the corresponding user, and check
1843 * if valid per the usermap.
1844 *
1845 * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
1846 */
1847static int
1849{
1850 uid_t uid;
1851 gid_t gid;
1852#ifndef WIN32
1853 struct passwd pwbuf;
1854 struct passwd *pw;
1855 char buf[1024];
1856 int rc;
1857 int ret;
1858#endif
1859
1860 if (getpeereid(port->sock, &uid, &gid) != 0)
1861 {
1862 /* Provide special error message if getpeereid is a stub */
1863 if (errno == ENOSYS)
1864 ereport(LOG,
1865 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1866 errmsg("peer authentication is not supported on this platform")));
1867 else
1868 ereport(LOG,
1870 errmsg("could not get peer credentials: %m")));
1871 return STATUS_ERROR;
1872 }
1873
1874#ifndef WIN32
1875 rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw);
1876 if (rc != 0)
1877 {
1878 errno = rc;
1879 ereport(LOG,
1880 errmsg("could not look up local user ID %ld: %m", (long) uid));
1881 return STATUS_ERROR;
1882 }
1883 else if (!pw)
1884 {
1885 ereport(LOG,
1886 errmsg("local user with ID %ld does not exist", (long) uid));
1887 return STATUS_ERROR;
1888 }
1889
1890 /*
1891 * Make a copy of static getpw*() result area; this is our authenticated
1892 * identity. Set it before calling check_usermap, because authentication
1893 * has already succeeded and we want the log file to reflect that.
1894 */
1895 set_authn_id(port, pw->pw_name);
1896
1897 ret = check_usermap(port->hba->usermap, port->user_name,
1899
1900 return ret;
1901#else
1902 /* should have failed with ENOSYS above */
1903 Assert(false);
1904 return STATUS_ERROR;
1905#endif
1906}
1907
1908
1909/*----------------------------------------------------------------
1910 * PAM authentication system
1911 *----------------------------------------------------------------
1912 */
1913#ifdef USE_PAM
1914
1915/*
1916 * PAM conversation function
1917 */
1918
1919static int
1920pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
1921 struct pam_response **resp, void *appdata_ptr)
1922{
1923 const char *passwd;
1924 struct pam_response *reply;
1925 int i;
1926
1927 if (appdata_ptr)
1928 passwd = (char *) appdata_ptr;
1929 else
1930 {
1931 /*
1932 * Workaround for Solaris 2.6 where the PAM library is broken and does
1933 * not pass appdata_ptr to the conversation routine
1934 */
1935 passwd = pam_passwd;
1936 }
1937
1938 *resp = NULL; /* in case of error exit */
1939
1940 if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
1941 return PAM_CONV_ERR;
1942
1943 /*
1944 * Explicitly not using palloc here - PAM will free this memory in
1945 * pam_end()
1946 */
1947 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
1948 {
1949 ereport(LOG,
1950 (errcode(ERRCODE_OUT_OF_MEMORY),
1951 errmsg("out of memory")));
1952 return PAM_CONV_ERR;
1953 }
1954
1955 for (i = 0; i < num_msg; i++)
1956 {
1957 switch (msg[i]->msg_style)
1958 {
1959 case PAM_PROMPT_ECHO_OFF:
1960 if (strlen(passwd) == 0)
1961 {
1962 /*
1963 * Password wasn't passed to PAM the first time around -
1964 * let's go ask the client to send a password, which we
1965 * then stuff into PAM.
1966 */
1967 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD, NULL, 0);
1968 passwd = recv_password_packet(pam_port_cludge);
1969 if (passwd == NULL)
1970 {
1971 /*
1972 * Client didn't want to send password. We
1973 * intentionally do not log anything about this,
1974 * either here or at higher levels.
1975 */
1976 pam_no_password = true;
1977 goto fail;
1978 }
1979 }
1980 if ((reply[i].resp = strdup(passwd)) == NULL)
1981 goto fail;
1982 reply[i].resp_retcode = PAM_SUCCESS;
1983 break;
1984 case PAM_ERROR_MSG:
1985 ereport(LOG,
1986 (errmsg("error from underlying PAM layer: %s",
1987 msg[i]->msg)));
1988 /* FALL THROUGH */
1989 case PAM_TEXT_INFO:
1990 /* we don't bother to log TEXT_INFO messages */
1991 if ((reply[i].resp = strdup("")) == NULL)
1992 goto fail;
1993 reply[i].resp_retcode = PAM_SUCCESS;
1994 break;
1995 default:
1996 ereport(LOG,
1997 (errmsg("unsupported PAM conversation %d/\"%s\"",
1998 msg[i]->msg_style,
1999 msg[i]->msg ? msg[i]->msg : "(none)")));
2000 goto fail;
2001 }
2002 }
2003
2004 *resp = reply;
2005 return PAM_SUCCESS;
2006
2007fail:
2008 /* free up whatever we allocated */
2009 for (i = 0; i < num_msg; i++)
2010 free(reply[i].resp);
2011 free(reply);
2012
2013 return PAM_CONV_ERR;
2014}
2015
2016
2017/*
2018 * Check authentication against PAM.
2019 */
2020static int
2021CheckPAMAuth(Port *port, const char *user, const char *password)
2022{
2023 int retval;
2024 pam_handle_t *pamh = NULL;
2025
2026 /*
2027 * We can't entirely rely on PAM to pass through appdata --- it appears
2028 * not to work on at least Solaris 2.6. So use these ugly static
2029 * variables instead.
2030 */
2031 pam_passwd = password;
2032 pam_port_cludge = port;
2033 pam_no_password = false;
2034
2035 /*
2036 * Set the application data portion of the conversation struct. This is
2037 * later used inside the PAM conversation to pass the password to the
2038 * authentication module.
2039 */
2040 pam_passw_conv.appdata_ptr = unconstify(char *, password); /* from password above,
2041 * not allocated */
2042
2043 /* Optionally, one can set the service name in pg_hba.conf */
2044 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
2045 retval = pam_start(port->hba->pamservice, "pgsql@",
2046 &pam_passw_conv, &pamh);
2047 else
2048 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
2049 &pam_passw_conv, &pamh);
2050
2051 if (retval != PAM_SUCCESS)
2052 {
2053 ereport(LOG,
2054 (errmsg("could not create PAM authenticator: %s",
2055 pam_strerror(pamh, retval))));
2056 pam_passwd = NULL; /* Unset pam_passwd */
2057 return STATUS_ERROR;
2058 }
2059
2060 retval = pam_set_item(pamh, PAM_USER, user);
2061
2062 if (retval != PAM_SUCCESS)
2063 {
2064 ereport(LOG,
2065 (errmsg("pam_set_item(PAM_USER) failed: %s",
2066 pam_strerror(pamh, retval))));
2067 pam_passwd = NULL; /* Unset pam_passwd */
2068 return STATUS_ERROR;
2069 }
2070
2071 if (port->hba->conntype != ctLocal)
2072 {
2073 char hostinfo[NI_MAXHOST];
2074 int flags;
2075
2076 if (port->hba->pam_use_hostname)
2077 flags = 0;
2078 else
2079 flags = NI_NUMERICHOST | NI_NUMERICSERV;
2080
2081 retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
2082 hostinfo, sizeof(hostinfo), NULL, 0,
2083 flags);
2084 if (retval != 0)
2085 {
2087 (errmsg_internal("pg_getnameinfo_all() failed: %s",
2088 gai_strerror(retval))));
2089 return STATUS_ERROR;
2090 }
2091
2092 retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
2093
2094 if (retval != PAM_SUCCESS)
2095 {
2096 ereport(LOG,
2097 (errmsg("pam_set_item(PAM_RHOST) failed: %s",
2098 pam_strerror(pamh, retval))));
2099 pam_passwd = NULL;
2100 return STATUS_ERROR;
2101 }
2102 }
2103
2104 retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
2105
2106 if (retval != PAM_SUCCESS)
2107 {
2108 ereport(LOG,
2109 (errmsg("pam_set_item(PAM_CONV) failed: %s",
2110 pam_strerror(pamh, retval))));
2111 pam_passwd = NULL; /* Unset pam_passwd */
2112 return STATUS_ERROR;
2113 }
2114
2115 retval = pam_authenticate(pamh, 0);
2116
2117 if (retval != PAM_SUCCESS)
2118 {
2119 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2120 if (!pam_no_password)
2121 ereport(LOG,
2122 (errmsg("pam_authenticate failed: %s",
2123 pam_strerror(pamh, retval))));
2124 pam_passwd = NULL; /* Unset pam_passwd */
2125 return pam_no_password ? STATUS_EOF : STATUS_ERROR;
2126 }
2127
2128 retval = pam_acct_mgmt(pamh, 0);
2129
2130 if (retval != PAM_SUCCESS)
2131 {
2132 /* If pam_passwd_conv_proc saw EOF, don't log anything */
2133 if (!pam_no_password)
2134 ereport(LOG,
2135 (errmsg("pam_acct_mgmt failed: %s",
2136 pam_strerror(pamh, retval))));
2137 pam_passwd = NULL; /* Unset pam_passwd */
2138 return pam_no_password ? STATUS_EOF : STATUS_ERROR;
2139 }
2140
2141 retval = pam_end(pamh, retval);
2142
2143 if (retval != PAM_SUCCESS)
2144 {
2145 ereport(LOG,
2146 (errmsg("could not release PAM authenticator: %s",
2147 pam_strerror(pamh, retval))));
2148 }
2149
2150 pam_passwd = NULL; /* Unset pam_passwd */
2151
2152 if (retval == PAM_SUCCESS)
2154
2155 return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
2156}
2157#endif /* USE_PAM */
2158
2159
2160/*----------------------------------------------------------------
2161 * BSD authentication system
2162 *----------------------------------------------------------------
2163 */
2164#ifdef USE_BSD_AUTH
2165static int
2166CheckBSDAuth(Port *port, char *user)
2167{
2168 char *passwd;
2169 int retval;
2170
2171 /* Send regular password request to client, and get the response */
2173
2174 passwd = recv_password_packet(port);
2175 if (passwd == NULL)
2176 return STATUS_EOF;
2177
2178 /*
2179 * Ask the BSD auth system to verify password. Note that auth_userokay
2180 * will overwrite the password string with zeroes, but it's just a
2181 * temporary string so we don't care.
2182 */
2183 retval = auth_userokay(user, NULL, "auth-postgresql", passwd);
2184
2185 pfree(passwd);
2186
2187 if (!retval)
2188 return STATUS_ERROR;
2189
2191 return STATUS_OK;
2192}
2193#endif /* USE_BSD_AUTH */
2194
2195
2196/*----------------------------------------------------------------
2197 * LDAP authentication system
2198 *----------------------------------------------------------------
2199 */
2200#ifdef USE_LDAP
2201
2202static int errdetail_for_ldap(LDAP *ldap);
2203
2204/*
2205 * Initialize a connection to the LDAP server, including setting up
2206 * TLS if requested.
2207 */
2208static int
2209InitializeLDAPConnection(Port *port, LDAP **ldap)
2210{
2211 const char *scheme;
2212 int ldapversion = LDAP_VERSION3;
2213 int r;
2214
2215 scheme = port->hba->ldapscheme;
2216 if (scheme == NULL)
2217 scheme = "ldap";
2218#ifdef WIN32
2219 if (strcmp(scheme, "ldaps") == 0)
2220 *ldap = ldap_sslinit(port->hba->ldapserver, port->hba->ldapport, 1);
2221 else
2222 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2223 if (!*ldap)
2224 {
2225 ereport(LOG,
2226 (errmsg("could not initialize LDAP: error code %d",
2227 (int) LdapGetLastError())));
2228
2229 return STATUS_ERROR;
2230 }
2231#else
2232#ifdef HAVE_LDAP_INITIALIZE
2233
2234 /*
2235 * OpenLDAP provides a non-standard extension ldap_initialize() that takes
2236 * a list of URIs, allowing us to request "ldaps" instead of "ldap". It
2237 * also provides ldap_domain2hostlist() to find LDAP servers automatically
2238 * using DNS SRV. They were introduced in the same version, so for now we
2239 * don't have an extra configure check for the latter.
2240 */
2241 {
2242 StringInfoData uris;
2243 char *hostlist = NULL;
2244 char *p;
2245 bool append_port;
2246
2247 /* We'll build a space-separated scheme://hostname:port list here */
2248 initStringInfo(&uris);
2249
2250 /*
2251 * If pg_hba.conf provided no hostnames, we can ask OpenLDAP to try to
2252 * find some by extracting a domain name from the base DN and looking
2253 * up DSN SRV records for _ldap._tcp.<domain>.
2254 */
2255 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2256 {
2257 char *domain;
2258
2259 /* ou=blah,dc=foo,dc=bar -> foo.bar */
2260 if (ldap_dn2domain(port->hba->ldapbasedn, &domain))
2261 {
2262 ereport(LOG,
2263 (errmsg("could not extract domain name from ldapbasedn")));
2264 return STATUS_ERROR;
2265 }
2266
2267 /* Look up a list of LDAP server hosts and port numbers */
2268 if (ldap_domain2hostlist(domain, &hostlist))
2269 {
2270 ereport(LOG,
2271 (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
2272 domain),
2273 (errhint("Set an LDAP server name explicitly."))));
2274 ldap_memfree(domain);
2275 return STATUS_ERROR;
2276 }
2277 ldap_memfree(domain);
2278
2279 /* We have a space-separated list of host:port entries */
2280 p = hostlist;
2281 append_port = false;
2282 }
2283 else
2284 {
2285 /* We have a space-separated list of hosts from pg_hba.conf */
2286 p = port->hba->ldapserver;
2287 append_port = true;
2288 }
2289
2290 /* Convert the list of host[:port] entries to full URIs */
2291 do
2292 {
2293 size_t size;
2294
2295 /* Find the span of the next entry */
2296 size = strcspn(p, " ");
2297
2298 /* Append a space separator if this isn't the first URI */
2299 if (uris.len > 0)
2300 appendStringInfoChar(&uris, ' ');
2301
2302 /* Append scheme://host:port */
2303 appendStringInfoString(&uris, scheme);
2304 appendStringInfoString(&uris, "://");
2305 appendBinaryStringInfo(&uris, p, size);
2306 if (append_port)
2307 appendStringInfo(&uris, ":%d", port->hba->ldapport);
2308
2309 /* Step over this entry and any number of trailing spaces */
2310 p += size;
2311 while (*p == ' ')
2312 ++p;
2313 } while (*p);
2314
2315 /* Free memory from OpenLDAP if we looked up SRV records */
2316 if (hostlist)
2317 ldap_memfree(hostlist);
2318
2319 /* Finally, try to connect using the URI list */
2320 r = ldap_initialize(ldap, uris.data);
2321 pfree(uris.data);
2322 if (r != LDAP_SUCCESS)
2323 {
2324 ereport(LOG,
2325 (errmsg("could not initialize LDAP: %s",
2326 ldap_err2string(r))));
2327
2328 return STATUS_ERROR;
2329 }
2330 }
2331#else
2332 if (strcmp(scheme, "ldaps") == 0)
2333 {
2334 ereport(LOG,
2335 (errmsg("ldaps not supported with this LDAP library")));
2336
2337 return STATUS_ERROR;
2338 }
2339 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2340 if (!*ldap)
2341 {
2342 ereport(LOG,
2343 (errmsg("could not initialize LDAP: %m")));
2344
2345 return STATUS_ERROR;
2346 }
2347#endif
2348#endif
2349
2350 if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
2351 {
2352 ereport(LOG,
2353 (errmsg("could not set LDAP protocol version: %s",
2354 ldap_err2string(r)),
2355 errdetail_for_ldap(*ldap)));
2356 ldap_unbind(*ldap);
2357 return STATUS_ERROR;
2358 }
2359
2360 if (port->hba->ldaptls)
2361 {
2362#ifndef WIN32
2363 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
2364#else
2365 if ((r = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
2366#endif
2367 {
2368 ereport(LOG,
2369 (errmsg("could not start LDAP TLS session: %s",
2370 ldap_err2string(r)),
2371 errdetail_for_ldap(*ldap)));
2372 ldap_unbind(*ldap);
2373 return STATUS_ERROR;
2374 }
2375 }
2376
2377 return STATUS_OK;
2378}
2379
2380/* Placeholders recognized by FormatSearchFilter. For now just one. */
2381#define LPH_USERNAME "$username"
2382#define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
2383
2384/* Not all LDAP implementations define this. */
2385#ifndef LDAP_NO_ATTRS
2386#define LDAP_NO_ATTRS "1.1"
2387#endif
2388
2389/* Not all LDAP implementations define this. */
2390#ifndef LDAPS_PORT
2391#define LDAPS_PORT 636
2392#endif
2393
2394static char *
2395dummy_ldap_password_mutator(char *input)
2396{
2397 return input;
2398}
2399
2400/*
2401 * Return a newly allocated C string copied from "pattern" with all
2402 * occurrences of the placeholder "$username" replaced with "user_name".
2403 */
2404static char *
2405FormatSearchFilter(const char *pattern, const char *user_name)
2406{
2408
2410 while (*pattern != '\0')
2411 {
2412 if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)
2413 {
2414 appendStringInfoString(&output, user_name);
2415 pattern += LPH_USERNAME_LEN;
2416 }
2417 else
2418 appendStringInfoChar(&output, *pattern++);
2419 }
2420
2421 return output.data;
2422}
2423
2424/*
2425 * Perform LDAP authentication
2426 */
2427static int
2428CheckLDAPAuth(Port *port)
2429{
2430 char *passwd;
2431 LDAP *ldap;
2432 int r;
2433 char *fulluser;
2434 const char *server_name;
2435
2436#ifdef HAVE_LDAP_INITIALIZE
2437
2438 /*
2439 * For OpenLDAP, allow empty hostname if we have a basedn. We'll look for
2440 * servers with DNS SRV records via OpenLDAP library facilities.
2441 */
2442 if ((!port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
2443 (!port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
2444 {
2445 ereport(LOG,
2446 (errmsg("LDAP server not specified, and no ldapbasedn")));
2447 return STATUS_ERROR;
2448 }
2449#else
2450 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2451 {
2452 ereport(LOG,
2453 (errmsg("LDAP server not specified")));
2454 return STATUS_ERROR;
2455 }
2456#endif
2457
2458 /*
2459 * If we're using SRV records, we don't have a server name so we'll just
2460 * show an empty string in error messages.
2461 */
2462 server_name = port->hba->ldapserver ? port->hba->ldapserver : "";
2463
2464 if (port->hba->ldapport == 0)
2465 {
2466 if (port->hba->ldapscheme != NULL &&
2467 strcmp(port->hba->ldapscheme, "ldaps") == 0)
2468 port->hba->ldapport = LDAPS_PORT;
2469 else
2470 port->hba->ldapport = LDAP_PORT;
2471 }
2472
2474
2475 passwd = recv_password_packet(port);
2476 if (passwd == NULL)
2477 return STATUS_EOF; /* client wouldn't send password */
2478
2479 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
2480 {
2481 /* Error message already sent */
2482 pfree(passwd);
2483 return STATUS_ERROR;
2484 }
2485
2486 if (port->hba->ldapbasedn)
2487 {
2488 /*
2489 * First perform an LDAP search to find the DN for the user we are
2490 * trying to log in as.
2491 */
2492 char *filter;
2493 LDAPMessage *search_message;
2494 LDAPMessage *entry;
2495 char *attributes[] = {LDAP_NO_ATTRS, NULL};
2496 char *dn;
2497 char *c;
2498 int count;
2499
2500 /*
2501 * Disallow any characters that we would otherwise need to escape,
2502 * since they aren't really reasonable in a username anyway. Allowing
2503 * them would make it possible to inject any kind of custom filters in
2504 * the LDAP filter.
2505 */
2506 for (c = port->user_name; *c; c++)
2507 {
2508 if (*c == '*' ||
2509 *c == '(' ||
2510 *c == ')' ||
2511 *c == '\\' ||
2512 *c == '/')
2513 {
2514 ereport(LOG,
2515 (errmsg("invalid character in user name for LDAP authentication")));
2516 ldap_unbind(ldap);
2517 pfree(passwd);
2518 return STATUS_ERROR;
2519 }
2520 }
2521
2522 /*
2523 * Bind with a pre-defined username/password (if available) for
2524 * searching. If none is specified, this turns into an anonymous bind.
2525 */
2526 r = ldap_simple_bind_s(ldap,
2527 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2528 port->hba->ldapbindpasswd ? ldap_password_hook(port->hba->ldapbindpasswd) : "");
2529 if (r != LDAP_SUCCESS)
2530 {
2531 ereport(LOG,
2532 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",
2533 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2534 server_name,
2535 ldap_err2string(r)),
2536 errdetail_for_ldap(ldap)));
2537 ldap_unbind(ldap);
2538 pfree(passwd);
2539 return STATUS_ERROR;
2540 }
2541
2542 /* Build a custom filter or a single attribute filter? */
2543 if (port->hba->ldapsearchfilter)
2544 filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);
2545 else if (port->hba->ldapsearchattribute)
2546 filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);
2547 else
2548 filter = psprintf("(uid=%s)", port->user_name);
2549
2550 search_message = NULL;
2551 r = ldap_search_s(ldap,
2552 port->hba->ldapbasedn,
2553 port->hba->ldapscope,
2554 filter,
2555 attributes,
2556 0,
2557 &search_message);
2558
2559 if (r != LDAP_SUCCESS)
2560 {
2561 ereport(LOG,
2562 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
2563 filter, server_name, ldap_err2string(r)),
2564 errdetail_for_ldap(ldap)));
2565 if (search_message != NULL)
2566 ldap_msgfree(search_message);
2567 ldap_unbind(ldap);
2568 pfree(passwd);
2569 pfree(filter);
2570 return STATUS_ERROR;
2571 }
2572
2573 count = ldap_count_entries(ldap, search_message);
2574 if (count != 1)
2575 {
2576 if (count == 0)
2577 ereport(LOG,
2578 (errmsg("LDAP user \"%s\" does not exist", port->user_name),
2579 errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
2580 filter, server_name)));
2581 else
2582 ereport(LOG,
2583 (errmsg("LDAP user \"%s\" is not unique", port->user_name),
2584 errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",
2585 "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
2586 count,
2587 filter, server_name, count)));
2588
2589 ldap_unbind(ldap);
2590 pfree(passwd);
2591 pfree(filter);
2592 ldap_msgfree(search_message);
2593 return STATUS_ERROR;
2594 }
2595
2596 entry = ldap_first_entry(ldap, search_message);
2597 dn = ldap_get_dn(ldap, entry);
2598 if (dn == NULL)
2599 {
2600 int error;
2601
2602 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
2603 ereport(LOG,
2604 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
2605 filter, server_name,
2606 ldap_err2string(error)),
2607 errdetail_for_ldap(ldap)));
2608 ldap_unbind(ldap);
2609 pfree(passwd);
2610 pfree(filter);
2611 ldap_msgfree(search_message);
2612 return STATUS_ERROR;
2613 }
2614 fulluser = pstrdup(dn);
2615
2616 pfree(filter);
2617 ldap_memfree(dn);
2618 ldap_msgfree(search_message);
2619 }
2620 else
2621 fulluser = psprintf("%s%s%s",
2622 port->hba->ldapprefix ? port->hba->ldapprefix : "",
2623 port->user_name,
2624 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
2625
2626 r = ldap_simple_bind_s(ldap, fulluser, passwd);
2627
2628 if (r != LDAP_SUCCESS)
2629 {
2630 ereport(LOG,
2631 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
2632 fulluser, server_name, ldap_err2string(r)),
2633 errdetail_for_ldap(ldap)));
2634 ldap_unbind(ldap);
2635 pfree(passwd);
2636 pfree(fulluser);
2637 return STATUS_ERROR;
2638 }
2639
2640 /* Save the original bind DN as the authenticated identity. */
2641 set_authn_id(port, fulluser);
2642
2643 ldap_unbind(ldap);
2644 pfree(passwd);
2645 pfree(fulluser);
2646
2647 return STATUS_OK;
2648}
2649
2650/*
2651 * Add a detail error message text to the current error if one can be
2652 * constructed from the LDAP 'diagnostic message'.
2653 */
2654static int
2655errdetail_for_ldap(LDAP *ldap)
2656{
2657 char *message;
2658 int rc;
2659
2660 rc = ldap_get_option(ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, &message);
2661 if (rc == LDAP_SUCCESS && message != NULL)
2662 {
2663 errdetail("LDAP diagnostics: %s", message);
2664 ldap_memfree(message);
2665 }
2666
2667 return 0;
2668}
2669
2670#endif /* USE_LDAP */
2671
2672
2673/*----------------------------------------------------------------
2674 * SSL client certificate authentication
2675 *----------------------------------------------------------------
2676 */
2677#ifdef USE_SSL
2678static int
2679CheckCertAuth(Port *port)
2680{
2681 int status_check_usermap = STATUS_ERROR;
2682 char *peer_username = NULL;
2683
2684 Assert(port->ssl);
2685
2686 /* select the correct field to compare */
2687 switch (port->hba->clientcertname)
2688 {
2689 case clientCertDN:
2690 peer_username = port->peer_dn;
2691 break;
2692 case clientCertCN:
2693 peer_username = port->peer_cn;
2694 }
2695
2696 /* Make sure we have received a username in the certificate */
2697 if (peer_username == NULL ||
2698 strlen(peer_username) <= 0)
2699 {
2700 ereport(LOG,
2701 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
2702 port->user_name)));
2703 return STATUS_ERROR;
2704 }
2705
2706 if (port->hba->auth_method == uaCert)
2707 {
2708 /*
2709 * For cert auth, the client's Subject DN is always our authenticated
2710 * identity, even if we're only using its CN for authorization. Set
2711 * it now, rather than waiting for check_usermap() below, because
2712 * authentication has already succeeded and we want the log file to
2713 * reflect that.
2714 */
2715 if (!port->peer_dn)
2716 {
2717 /*
2718 * This should not happen as both peer_dn and peer_cn should be
2719 * set in this context.
2720 */
2721 ereport(LOG,
2722 (errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",
2723 port->user_name)));
2724 return STATUS_ERROR;
2725 }
2726
2727 set_authn_id(port, port->peer_dn);
2728 }
2729
2730 /* Just pass the certificate cn/dn to the usermap check */
2731 status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);
2732 if (status_check_usermap != STATUS_OK)
2733 {
2734 /*
2735 * If clientcert=verify-full was specified and the authentication
2736 * method is other than uaCert, log the reason for rejecting the
2737 * authentication.
2738 */
2739 if (port->hba->clientcert == clientCertFull && port->hba->auth_method != uaCert)
2740 {
2741 switch (port->hba->clientcertname)
2742 {
2743 case clientCertDN:
2744 ereport(LOG,
2745 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
2746 port->user_name)));
2747 break;
2748 case clientCertCN:
2749 ereport(LOG,
2750 (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
2751 port->user_name)));
2752 }
2753 }
2754 }
2755 return status_check_usermap;
2756}
2757#endif
2758
2759
2760/*----------------------------------------------------------------
2761 * RADIUS authentication
2762 *----------------------------------------------------------------
2763 */
2764
2765/*
2766 * RADIUS authentication is described in RFC2865 (and several others).
2767 */
2768
2769#define RADIUS_VECTOR_LENGTH 16
2770#define RADIUS_HEADER_LENGTH 20
2771#define RADIUS_MAX_PASSWORD_LENGTH 128
2772
2773/* Maximum size of a RADIUS packet we will create or accept */
2774#define RADIUS_BUFFER_SIZE 1024
2775
2776typedef struct
2777{
2782
2783typedef struct
2784{
2789 /* this is a bit longer than strictly necessary: */
2792
2793/* RADIUS packet types */
2794#define RADIUS_ACCESS_REQUEST 1
2795#define RADIUS_ACCESS_ACCEPT 2
2796#define RADIUS_ACCESS_REJECT 3
2797
2798/* RADIUS attributes */
2799#define RADIUS_USER_NAME 1
2800#define RADIUS_PASSWORD 2
2801#define RADIUS_SERVICE_TYPE 6
2802#define RADIUS_NAS_IDENTIFIER 32
2803
2804/* RADIUS service types */
2805#define RADIUS_AUTHENTICATE_ONLY 8
2806
2807/* Seconds to wait - XXX: should be in a config variable! */
2808#define RADIUS_TIMEOUT 3
2809
2810static void
2811radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
2812{
2813 radius_attribute *attr;
2814
2815 if (packet->length + len > RADIUS_BUFFER_SIZE)
2816 {
2817 /*
2818 * With remotely realistic data, this can never happen. But catch it
2819 * just to make sure we don't overrun a buffer. We'll just skip adding
2820 * the broken attribute, which will in the end cause authentication to
2821 * fail.
2822 */
2823 elog(WARNING,
2824 "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
2825 type, len);
2826 return;
2827 }
2828
2829 attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2830 attr->attribute = type;
2831 attr->length = len + 2; /* total size includes type and length */
2832 memcpy(attr->data, data, len);
2833 packet->length += attr->length;
2834}
2835
2836static int
2838{
2839 char *passwd;
2840 ListCell *server,
2841 *secrets,
2842 *radiusports,
2843 *identifiers;
2844
2845 /* Make sure struct alignment is correct */
2846 Assert(offsetof(radius_packet, vector) == 4);
2847
2848 /* Verify parameters */
2849 if (port->hba->radiusservers == NIL)
2850 {
2851 ereport(LOG,
2852 (errmsg("RADIUS server not specified")));
2853 return STATUS_ERROR;
2854 }
2855
2856 if (port->hba->radiussecrets == NIL)
2857 {
2858 ereport(LOG,
2859 (errmsg("RADIUS secret not specified")));
2860 return STATUS_ERROR;
2861 }
2862
2863 /* Send regular password request to client, and get the response */
2865
2866 passwd = recv_password_packet(port);
2867 if (passwd == NULL)
2868 return STATUS_EOF; /* client wouldn't send password */
2869
2870 if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
2871 {
2872 ereport(LOG,
2873 (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
2874 pfree(passwd);
2875 return STATUS_ERROR;
2876 }
2877
2878 /*
2879 * Loop over and try each server in order.
2880 */
2881 secrets = list_head(port->hba->radiussecrets);
2882 radiusports = list_head(port->hba->radiusports);
2883 identifiers = list_head(port->hba->radiusidentifiers);
2884 foreach(server, port->hba->radiusservers)
2885 {
2886 int ret = PerformRadiusTransaction(lfirst(server),
2887 lfirst(secrets),
2888 radiusports ? lfirst(radiusports) : NULL,
2889 identifiers ? lfirst(identifiers) : NULL,
2890 port->user_name,
2891 passwd);
2892
2893 /*------
2894 * STATUS_OK = Login OK
2895 * STATUS_ERROR = Login not OK, but try next server
2896 * STATUS_EOF = Login not OK, and don't try next server
2897 *------
2898 */
2899 if (ret == STATUS_OK)
2900 {
2901 set_authn_id(port, port->user_name);
2902
2903 pfree(passwd);
2904 return STATUS_OK;
2905 }
2906 else if (ret == STATUS_EOF)
2907 {
2908 pfree(passwd);
2909 return STATUS_ERROR;
2910 }
2911
2912 /*
2913 * secret, port and identifiers either have length 0 (use default),
2914 * length 1 (use the same everywhere) or the same length as servers.
2915 * So if the length is >1, we advance one step. In other cases, we
2916 * don't and will then reuse the correct value.
2917 */
2918 if (list_length(port->hba->radiussecrets) > 1)
2919 secrets = lnext(port->hba->radiussecrets, secrets);
2920 if (list_length(port->hba->radiusports) > 1)
2921 radiusports = lnext(port->hba->radiusports, radiusports);
2922 if (list_length(port->hba->radiusidentifiers) > 1)
2923 identifiers = lnext(port->hba->radiusidentifiers, identifiers);
2924 }
2925
2926 /* No servers left to try, so give up */
2927 pfree(passwd);
2928 return STATUS_ERROR;
2929}
2930
2931static int
2932PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
2933{
2934 radius_packet radius_send_pack;
2935 radius_packet radius_recv_pack;
2936 radius_packet *packet = &radius_send_pack;
2937 radius_packet *receivepacket = &radius_recv_pack;
2938 void *radius_buffer = &radius_send_pack;
2939 void *receive_buffer = &radius_recv_pack;
2941 uint8 *cryptvector;
2942 int encryptedpasswordlen;
2943 uint8 encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
2944 uint8 *md5trailer;
2945 int packetlength;
2946 pgsocket sock;
2947
2948 struct sockaddr_in6 localaddr;
2949 struct sockaddr_in6 remoteaddr;
2950 struct addrinfo hint;
2951 struct addrinfo *serveraddrs;
2952 int port;
2953 socklen_t addrsize;
2954 fd_set fdset;
2955 struct timeval endtime;
2956 int i,
2957 j,
2958 r;
2959
2960 /* Assign default values */
2961 if (portstr == NULL)
2962 portstr = "1812";
2963 if (identifier == NULL)
2964 identifier = "postgresql";
2965
2966 MemSet(&hint, 0, sizeof(hint));
2967 hint.ai_socktype = SOCK_DGRAM;
2968 hint.ai_family = AF_UNSPEC;
2969 port = atoi(portstr);
2970
2971 r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
2972 if (r || !serveraddrs)
2973 {
2974 ereport(LOG,
2975 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2976 server, gai_strerror(r))));
2977 if (serveraddrs)
2978 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2979 return STATUS_ERROR;
2980 }
2981 /* XXX: add support for multiple returned addresses? */
2982
2983 /* Construct RADIUS packet */
2984 packet->code = RADIUS_ACCESS_REQUEST;
2985 packet->length = RADIUS_HEADER_LENGTH;
2987 {
2988 ereport(LOG,
2989 (errmsg("could not generate random encryption vector")));
2990 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2991 return STATUS_ERROR;
2992 }
2993 packet->id = packet->vector[0];
2994 radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
2995 radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
2996 radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
2997
2998 /*
2999 * RADIUS password attributes are calculated as: e[0] = p[0] XOR
3000 * MD5(secret + Request Authenticator) for the first group of 16 octets,
3001 * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
3002 * (if necessary)
3003 */
3004 encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
3005 cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
3006 memcpy(cryptvector, secret, strlen(secret));
3007
3008 /* for the first iteration, we use the Request Authenticator vector */
3009 md5trailer = packet->vector;
3010 for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
3011 {
3012 const char *errstr = NULL;
3013
3014 memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
3015
3016 /*
3017 * .. and for subsequent iterations the result of the previous XOR
3018 * (calculated below)
3019 */
3020 md5trailer = encryptedpassword + i;
3021
3022 if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH,
3023 encryptedpassword + i, &errstr))
3024 {
3025 ereport(LOG,
3026 (errmsg("could not perform MD5 encryption of password: %s",
3027 errstr)));
3028 pfree(cryptvector);
3029 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3030 return STATUS_ERROR;
3031 }
3032
3033 for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
3034 {
3035 if (j < strlen(passwd))
3036 encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
3037 else
3038 encryptedpassword[j] = '\0' ^ encryptedpassword[j];
3039 }
3040 }
3041 pfree(cryptvector);
3042
3043 radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
3044
3045 /* Length needs to be in network order on the wire */
3046 packetlength = packet->length;
3047 packet->length = pg_hton16(packet->length);
3048
3049 sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
3050 if (sock == PGINVALID_SOCKET)
3051 {
3052 ereport(LOG,
3053 (errmsg("could not create RADIUS socket: %m")));
3054 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3055 return STATUS_ERROR;
3056 }
3057
3058 memset(&localaddr, 0, sizeof(localaddr));
3059 localaddr.sin6_family = serveraddrs[0].ai_family;
3060 localaddr.sin6_addr = in6addr_any;
3061 if (localaddr.sin6_family == AF_INET6)
3062 addrsize = sizeof(struct sockaddr_in6);
3063 else
3064 addrsize = sizeof(struct sockaddr_in);
3065
3066 if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
3067 {
3068 ereport(LOG,
3069 (errmsg("could not bind local RADIUS socket: %m")));
3070 closesocket(sock);
3071 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3072 return STATUS_ERROR;
3073 }
3074
3075 if (sendto(sock, radius_buffer, packetlength, 0,
3076 serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
3077 {
3078 ereport(LOG,
3079 (errmsg("could not send RADIUS packet: %m")));
3080 closesocket(sock);
3081 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3082 return STATUS_ERROR;
3083 }
3084
3085 /* Don't need the server address anymore */
3086 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
3087
3088 /*
3089 * Figure out at what time we should time out. We can't just use a single
3090 * call to select() with a timeout, since somebody can be sending invalid
3091 * packets to our port thus causing us to retry in a loop and never time
3092 * out.
3093 *
3094 * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
3095 * the latch was set would improve the responsiveness to
3096 * timeouts/cancellations.
3097 */
3098 gettimeofday(&endtime, NULL);
3099 endtime.tv_sec += RADIUS_TIMEOUT;
3100
3101 while (true)
3102 {
3103 struct timeval timeout;
3104 struct timeval now;
3105 int64 timeoutval;
3106 const char *errstr = NULL;
3107
3108 gettimeofday(&now, NULL);
3109 timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
3110 if (timeoutval <= 0)
3111 {
3112 ereport(LOG,
3113 (errmsg("timeout waiting for RADIUS response from %s",
3114 server)));
3115 closesocket(sock);
3116 return STATUS_ERROR;
3117 }
3118 timeout.tv_sec = timeoutval / 1000000;
3119 timeout.tv_usec = timeoutval % 1000000;
3120
3121 FD_ZERO(&fdset);
3122 FD_SET(sock, &fdset);
3123
3124 r = select(sock + 1, &fdset, NULL, NULL, &timeout);
3125 if (r < 0)
3126 {
3127 if (errno == EINTR)
3128 continue;
3129
3130 /* Anything else is an actual error */
3131 ereport(LOG,
3132 (errmsg("could not check status on RADIUS socket: %m")));
3133 closesocket(sock);
3134 return STATUS_ERROR;
3135 }
3136 if (r == 0)
3137 {
3138 ereport(LOG,
3139 (errmsg("timeout waiting for RADIUS response from %s",
3140 server)));
3141 closesocket(sock);
3142 return STATUS_ERROR;
3143 }
3144
3145 /*
3146 * Attempt to read the response packet, and verify the contents.
3147 *
3148 * Any packet that's not actually a RADIUS packet, or otherwise does
3149 * not validate as an explicit reject, is just ignored and we retry
3150 * for another packet (until we reach the timeout). This is to avoid
3151 * the possibility to denial-of-service the login by flooding the
3152 * server with invalid packets on the port that we're expecting the
3153 * RADIUS response on.
3154 */
3155
3156 addrsize = sizeof(remoteaddr);
3157 packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
3158 (struct sockaddr *) &remoteaddr, &addrsize);
3159 if (packetlength < 0)
3160 {
3161 ereport(LOG,
3162 (errmsg("could not read RADIUS response: %m")));
3163 closesocket(sock);
3164 return STATUS_ERROR;
3165 }
3166
3167 if (remoteaddr.sin6_port != pg_hton16(port))
3168 {
3169 ereport(LOG,
3170 (errmsg("RADIUS response from %s was sent from incorrect port: %d",
3171 server, pg_ntoh16(remoteaddr.sin6_port))));
3172 continue;
3173 }
3174
3175 if (packetlength < RADIUS_HEADER_LENGTH)
3176 {
3177 ereport(LOG,
3178 (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
3179 continue;
3180 }
3181
3182 if (packetlength != pg_ntoh16(receivepacket->length))
3183 {
3184 ereport(LOG,
3185 (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
3186 server, pg_ntoh16(receivepacket->length), packetlength)));
3187 continue;
3188 }
3189
3190 if (packet->id != receivepacket->id)
3191 {
3192 ereport(LOG,
3193 (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
3194 server, receivepacket->id, packet->id)));
3195 continue;
3196 }
3197
3198 /*
3199 * Verify the response authenticator, which is calculated as
3200 * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
3201 */
3202 cryptvector = palloc(packetlength + strlen(secret));
3203
3204 memcpy(cryptvector, receivepacket, 4); /* code+id+length */
3205 memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
3206 * authenticator, from
3207 * original packet */
3208 if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
3209 * attributes at all */
3210 memcpy(cryptvector + RADIUS_HEADER_LENGTH,
3211 (char *) receive_buffer + RADIUS_HEADER_LENGTH,
3212 packetlength - RADIUS_HEADER_LENGTH);
3213 memcpy(cryptvector + packetlength, secret, strlen(secret));
3214
3215 if (!pg_md5_binary(cryptvector,
3216 packetlength + strlen(secret),
3217 encryptedpassword, &errstr))
3218 {
3219 ereport(LOG,
3220 (errmsg("could not perform MD5 encryption of received packet: %s",
3221 errstr)));
3222 pfree(cryptvector);
3223 continue;
3224 }
3225 pfree(cryptvector);
3226
3227 if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
3228 {
3229 ereport(LOG,
3230 (errmsg("RADIUS response from %s has incorrect MD5 signature",
3231 server)));
3232 continue;
3233 }
3234
3235 if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
3236 {
3237 closesocket(sock);
3238 return STATUS_OK;
3239 }
3240 else if (receivepacket->code == RADIUS_ACCESS_REJECT)
3241 {
3242 closesocket(sock);
3243 return STATUS_EOF;
3244 }
3245 else
3246 {
3247 ereport(LOG,
3248 (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
3249 server, receivepacket->code, user_name)));
3250 continue;
3251 }
3252 } /* while (true) */
3253}
const pg_be_sasl_mech pg_be_oauth_mech
Definition: auth-oauth.c:48
int CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, const char **logdetail)
Definition: auth-sasl.c:44
const pg_be_sasl_mech pg_be_scram_mech
Definition: auth-scram.c:114
static void radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
Definition: auth.c:2811
void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
Definition: auth.c:669
#define RADIUS_HEADER_LENGTH
Definition: auth.c:2770
static int CheckPWChallengeAuth(Port *port, const char **logdetail)
Definition: auth.c:815
#define RADIUS_AUTHENTICATE_ONLY
Definition: auth.c:2805
static int ident_inet(hbaPort *port)
Definition: auth.c:1663
char * pg_krb_server_keyfile
Definition: auth.c:165
#define IDENT_USERNAME_MAX
Definition: auth.c:68
#define RADIUS_ACCESS_REQUEST
Definition: auth.c:2794
bool pg_krb_caseins_users
Definition: auth.c:166
static char * recv_password_packet(Port *port)
Definition: auth.c:699
#define RADIUS_NAS_IDENTIFIER
Definition: auth.c:2802
#define RADIUS_TIMEOUT
Definition: auth.c:2808
#define RADIUS_USER_NAME
Definition: auth.c:2799
#define RADIUS_SERVICE_TYPE
Definition: auth.c:2801
bool pg_gss_accept_delegation
Definition: auth.c:167
static int CheckRADIUSAuth(Port *port)
Definition: auth.c:2837
static void auth_failed(Port *port, int status, const char *logdetail)
Definition: auth.c:231
#define RADIUS_MAX_PASSWORD_LENGTH
Definition: auth.c:2771
ClientAuthentication_hook_type ClientAuthentication_hook
Definition: auth.c:215
#define IDENT_PORT
Definition: auth.c:71
void ClientAuthentication(Port *port)
Definition: auth.c:371
#define RADIUS_PASSWORD
Definition: auth.c:2800
static int auth_peer(hbaPort *port)
Definition: auth.c:1848
#define RADIUS_ACCESS_REJECT
Definition: auth.c:2796
static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
Definition: auth.c:875
void set_authn_id(Port *port, const char *id)
Definition: auth.c:333
#define RADIUS_ACCESS_ACCEPT
Definition: auth.c:2795
static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
Definition: auth.c:2932
#define RADIUS_VECTOR_LENGTH
Definition: auth.c:2769
static bool interpret_ident_response(const char *ident_response, char *ident_user)
Definition: auth.c:1582
#define HOSTNAME_LOOKUP_DETAIL(port)
static int CheckPasswordAuth(Port *port, const char **logdetail)
Definition: auth.c:780
#define RADIUS_BUFFER_SIZE
Definition: auth.c:2774
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
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1609
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:99
#define unconstify(underlying_type, expr)
Definition: c.h:1216
#define STATUS_OK
Definition: c.h:1140
uint8_t uint8
Definition: c.h:500
#define gettext_noop(x)
Definition: c.h:1167
int64_t int64
Definition: c.h:499
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:434
#define STATUS_EOF
Definition: c.h:1142
int32_t int32
Definition: c.h:498
uint16_t uint16
Definition: c.h:501
#define MemSet(start, val, len)
Definition: c.h:991
#define STATUS_ERROR
Definition: c.h:1141
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition: crypt.c:256
char * get_role_password(const char *role, const char **logdetail)
Definition: crypt.c:38
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:90
int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char *md5_salt, int md5_salt_len, const char **logdetail)
Definition: crypt.c:202
PasswordType
Definition: crypt.h:41
@ PASSWORD_TYPE_MD5
Definition: crypt.h:43
int errcode_for_socket_access(void)
Definition: elog.c:954
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1231
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1296
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
int errdetail_log(const char *fmt,...)
Definition: elog.c:1252
#define _(x)
Definition: elog.c:91
#define LOG
Definition: elog.h:31
#define FATAL
Definition: elog.h:41
#define WARNING
Definition: elog.h:36
#define DEBUG2
Definition: elog.h:29
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:149
#define DEBUG5
Definition: elog.h:26
#define DEBUG4
Definition: elog.h:27
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:92
Assert(PointerIsAligned(start, uint64))
bool pg_isblank(const char c)
Definition: hba.c:146
void hba_getauthmethod(hbaPort *port)
Definition: hba.c:3110
int check_usermap(const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
Definition: hba.c:2966
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3123
@ ctLocal
Definition: hba.h:60
@ uaBSD
Definition: hba.h:37
@ uaLDAP
Definition: hba.h:38
@ uaPeer
Definition: hba.h:41
@ uaPAM
Definition: hba.h:36
@ uaPassword
Definition: hba.h:31
@ uaCert
Definition: hba.h:39
@ uaMD5
Definition: hba.h:32
@ uaReject
Definition: hba.h:27
@ uaGSS
Definition: hba.h:34
@ uaSCRAM
Definition: hba.h:33
@ uaImplicitReject
Definition: hba.h:28
@ uaRADIUS
Definition: hba.h:40
@ uaIdent
Definition: hba.h:30
@ uaOAuth
Definition: hba.h:42
@ uaTrust
Definition: hba.h:29
@ uaSSPI
Definition: hba.h:35
@ clientCertDN
Definition: hba.h:78
@ clientCertCN
Definition: hba.h:77
@ clientCertOff
Definition: hba.h:70
@ clientCertFull
Definition: hba.h:72
#define calloc(a, b)
Definition: header.h:55
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
#define token
Definition: indent_globs.h:126
FILE * input
FILE * output
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
void proc_exit(int code)
Definition: ipc.c:104
int j
Definition: isn.c:78
int i
Definition: isn.c:77
#define pq_flush()
Definition: libpq.h:46
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:2309
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1290
char * pstrdup(const char *in)
Definition: mcxt.c:2322
void pfree(void *pointer)
Definition: mcxt.c:2147
MemoryContext TopMemoryContext
Definition: mcxt.c:165
void * palloc(Size size)
Definition: mcxt.c:1940
bool pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr)
Definition: md5_common.c:108
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
ClientConnectionInfo MyClientConnectionInfo
Definition: miscinit.c:1069
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define pg_hton16(x)
Definition: pg_bswap.h:120
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
#define MAXPGPATH
const void size_t len
const void * data
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
static char * user
Definition: pg_regress.c:119
static int port
Definition: pg_regress.c:115
static char portstr[16]
Definition: pg_regress.c:116
static char * buf
Definition: pg_test_fsync.c:72
bool pg_strong_random(void *buf, size_t len)
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pgsocket
Definition: port.h:29
#define snprintf
Definition: port.h:239
unsigned int socklen_t
Definition: port.h:40
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:377
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:121
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
#define AUTH_REQ_SSPI
Definition: protocol.h:83
#define PqMsg_GSSResponse
Definition: protocol.h:30
#define AUTH_REQ_GSS
Definition: protocol.h:81
#define AUTH_REQ_MD5
Definition: protocol.h:79
#define AUTH_REQ_OK
Definition: protocol.h:74
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:82
#define PqMsg_PasswordMessage
Definition: protocol.h:31
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
const char * gai_strerror(int ecode)
static void error(void)
Definition: sql-dyntest.c:147
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
UserAuth auth_method
Definition: libpq-be.h:105
Definition: libpq-be.h:129
struct sockaddr_storage addr
Definition: pqcomm.h:32
socklen_t salen
Definition: pqcomm.h:33
Definition: type.h:138
uint8 data[FLEXIBLE_ARRAY_MEMBER]
Definition: auth.c:2780
uint8 length
Definition: auth.c:2779
uint8 attribute
Definition: auth.c:2778
uint8 vector[RADIUS_VECTOR_LENGTH]
Definition: auth.c:2788
uint16 length
Definition: auth.c:2787
uint8 code
Definition: auth.c:2785
uint8 id
Definition: auth.c:2786
int Password_encryption
Definition: user.c:86
static char * authn_id
Definition: validator.c:41
const char * type
bool am_walsender
Definition: walsender.c:120
bool am_db_walsender
Definition: walsender.c:123
#define bind(s, addr, addrlen)
Definition: win32_port.h:499
#define EINTR
Definition: win32_port.h:364
int gid_t
Definition: win32_port.h:235
#define recv(s, buf, len, flags)
Definition: win32_port.h:504
#define setenv(x, y, z)
Definition: win32_port.h:545
#define send(s, buf, len, flags)
Definition: win32_port.h:505
#define socket(af, type, protocol)
Definition: win32_port.h:498
#define connect(s, name, namelen)
Definition: win32_port.h:502
#define select(n, r, w, e, timeout)
Definition: win32_port.h:503
int uid_t
Definition: win32_port.h:234
int gettimeofday(struct timeval *tp, void *tzp)