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