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