1 /*-------------------------------------------------------------------------
4 * Routines to handle network authentication
6 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/libpq/auth.c
13 *-------------------------------------------------------------------------
18 #include <sys/param.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
24 #include "libpq/auth.h"
25 #include "libpq/crypt.h"
27 #include "libpq/libpq.h"
28 #include "libpq/pqformat.h"
29 #include "libpq/md5.h"
30 #include "miscadmin.h"
31 #include "replication/walsender.h"
32 #include "storage/ipc.h"
35 /*----------------------------------------------------------------
36 * Global authentication functions
37 *----------------------------------------------------------------
39 static void sendAuthRequest(Port *port, AuthRequest areq);
40 static void auth_failed(Port *port, int status);
41 static char *recv_password_packet(Port *port);
42 static int recv_and_check_password_packet(Port *port);
45 /*----------------------------------------------------------------
46 * Ident authentication
47 *----------------------------------------------------------------
49 /* Max size of username ident server can return */
50 #define IDENT_USERNAME_MAX 512
52 /* Standard TCP port number for Ident service. Assigned by IANA */
53 #define IDENT_PORT 113
55 static int ident_inet(hbaPort *port);
57 #ifdef HAVE_UNIX_SOCKETS
58 static int auth_peer(hbaPort *port);
62 /*----------------------------------------------------------------
64 *----------------------------------------------------------------
67 #ifdef HAVE_PAM_PAM_APPL_H
68 #include <pam/pam_appl.h>
70 #ifdef HAVE_SECURITY_PAM_APPL_H
71 #include <security/pam_appl.h>
74 #define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */
76 static int CheckPAMAuth(Port *port, char *user, char *password);
77 static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
78 struct pam_response ** resp, void *appdata_ptr);
80 static struct pam_conv pam_passw_conv = {
81 &pam_passwd_conv_proc,
85 static char *pam_passwd = NULL; /* Workaround for Solaris 2.6 brokenness */
86 static Port *pam_port_cludge; /* Workaround for passing "Port *port" into
87 * pam_passwd_conv_proc */
91 /*----------------------------------------------------------------
93 *----------------------------------------------------------------
97 /* We use a deprecated function to keep the codepath the same as win32. */
98 #define LDAP_DEPRECATED 1
103 /* Correct header from the Platform SDK */
105 ULONG (*__ldap_start_tls_sA) (
106 IN PLDAP ExternalHandle,
107 OUT PULONG ServerReturnValue,
108 OUT LDAPMessage **result,
109 IN PLDAPControlA * ServerControls,
110 IN PLDAPControlA * ClientControls
114 static int CheckLDAPAuth(Port *port);
115 #endif /* USE_LDAP */
117 /*----------------------------------------------------------------
118 * Cert authentication
119 *----------------------------------------------------------------
122 static int CheckCertAuth(Port *port);
126 /*----------------------------------------------------------------
127 * Kerberos and GSSAPI GUCs
128 *----------------------------------------------------------------
130 char *pg_krb_server_keyfile;
132 bool pg_krb_caseins_users;
135 /*----------------------------------------------------------------
136 * MIT Kerberos authentication system - protocol version 5
137 *----------------------------------------------------------------
140 static int pg_krb5_recvauth(Port *port);
143 /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
144 #if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
148 * Various krb5 state which is not connection specfic, and a flag to
149 * indicate whether we have initialised it yet.
151 static int pg_krb5_initialised;
152 static krb5_context pg_krb5_context;
153 static krb5_keytab pg_krb5_keytab;
154 static krb5_principal pg_krb5_server;
158 /*----------------------------------------------------------------
159 * GSSAPI Authentication
160 *----------------------------------------------------------------
163 #if defined(HAVE_GSSAPI_H)
166 #include <gssapi/gssapi.h>
169 static int pg_GSS_recvauth(Port *port);
170 #endif /* ENABLE_GSS */
173 /*----------------------------------------------------------------
174 * SSPI Authentication
175 *----------------------------------------------------------------
178 typedef SECURITY_STATUS
179 (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
180 PCtxtHandle, void **);
181 static int pg_SSPI_recvauth(Port *port);
184 /*----------------------------------------------------------------
185 * RADIUS Authentication
186 *----------------------------------------------------------------
189 #include <openssl/rand.h>
191 static int CheckRADIUSAuth(Port *port);
195 * Maximum accepted size of GSS and SSPI authentication tokens.
197 * Kerberos tickets are usually quite small, but the TGTs issued by Windows
198 * domain controllers include an authorization field known as the Privilege
199 * Attribute Certificate (PAC), which contains the user's Windows permissions
200 * (group memberships etc.). The PAC is copied into all tickets obtained on
201 * the basis of this TGT (even those issued by Unix realms which the Windows
202 * realm trusts), and can be several kB in size. The maximum token size
203 * accepted by Windows systems is determined by the MaxAuthToken Windows
204 * registry setting. Microsoft recommends that it is not set higher than
205 * 65535 bytes, so that seems like a reasonable limit for us as well.
207 #define PG_MAX_AUTH_TOKEN_LENGTH 65535
210 /*----------------------------------------------------------------
211 * Global authentication functions
212 *----------------------------------------------------------------
216 * This hook allows plugins to get control following client authentication,
217 * but before the user has been informed about the results. It could be used
218 * to record login events, insert a delay after failed authentication, etc.
220 ClientAuthentication_hook_type ClientAuthentication_hook = NULL;
223 * Tell the user the authentication failed, but not (much about) why.
225 * There is a tradeoff here between security concerns and making life
226 * unnecessarily difficult for legitimate users. We would not, for example,
227 * want to report the password we were expecting to receive...
228 * But it seems useful to report the username and authorization method
229 * in use, and these are items that must be presumed known to an attacker
231 * Note that many sorts of failure report additional information in the
232 * postmaster log, which we hope is only readable by good guys.
235 auth_failed(Port *port, int status)
238 int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
241 * If we failed due to EOF from client, just quit; there's no point in
242 * trying to send a message to the client, and not much point in logging
243 * the failure in the postmaster log. (Logging the failure might be
244 * desirable, were it not for the fact that libpq closes the connection
245 * unceremoniously if challenged for a password when it hasn't got one to
246 * send. We'll get a useless log entry for every psql connection under
247 * password auth, even if it's perfectly successful, if we log STATUS_EOF
250 if (status == STATUS_EOF)
253 switch (port->hba->auth_method)
256 case uaImplicitReject:
257 errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
260 errstr = gettext_noop("Kerberos 5 authentication failed for user \"%s\"");
263 errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
266 errstr = gettext_noop("Ident authentication failed for user \"%s\"");
269 errstr = gettext_noop("Peer authentication failed for user \"%s\"");
273 errstr = gettext_noop("password authentication failed for user \"%s\"");
274 /* We use it to indicate if a .pgpass password failed. */
275 errcode_return = ERRCODE_INVALID_PASSWORD;
278 errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
281 errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
284 errstr = gettext_noop("PAM authentication failed for user \"%s\"");
287 errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
290 errstr = gettext_noop("certificate authentication failed for user \"%s\"");
293 errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
296 errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
301 (errcode(errcode_return),
302 errmsg(errstr, port->user_name)));
308 * Client authentication starts here. If there is an error, this
309 * function does not return and the backend process is terminated.
312 ClientAuthentication(Port *port)
314 int status = STATUS_ERROR;
317 * Get the authentication method to use for this frontend/database
318 * combination. Note: we do not parse the file at this point; this has
319 * already been done elsewhere. hba.c dropped an error message
320 * into the server logfile if parsing the hba config file failed.
322 hba_getauthmethod(port);
325 * Enable immediate response to SIGTERM/SIGINT/timeout interrupts. (We
326 * don't want this during hba_getauthmethod() because it might have to do
327 * database access, eg for role membership checks.)
329 ImmediateInterruptOK = true;
330 /* And don't forget to detect one that already arrived */
331 CHECK_FOR_INTERRUPTS();
334 * This is the first point where we have access to the hba record for the
335 * current connection, so perform any verifications based on the hba
336 * options field that should be done *before* the authentication here.
338 if (port->hba->clientcert)
341 * When we parse pg_hba.conf, we have already made sure that we have
342 * been able to load a certificate store. Thus, if a certificate is
343 * present on the client, it has been verified against our root
344 * certificate store, and the connection would have been aborted
345 * already if it didn't verify ok.
351 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
352 errmsg("connection requires a valid client certificate")));
357 * hba.c makes sure hba->clientcert can't be set unless OpenSSL is
365 * Now proceed to do the actual authentication check
367 switch (port->hba->auth_method)
372 * An explicit "reject" entry in pg_hba.conf. This report exposes
373 * the fact that there's an explicit reject entry, which is
374 * perhaps not so desirable from a security standpoint; but the
375 * message for an implicit reject could confuse the DBA a lot when
376 * the true situation is a match to an explicit reject. And we
377 * don't want to change the message for an implicit reject. As
378 * noted below, the additional information shown here doesn't
379 * expose anything not known to an attacker.
382 char hostinfo[NI_MAXHOST];
384 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
385 hostinfo, sizeof(hostinfo),
393 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
394 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
395 hostinfo, port->user_name,
396 port->ssl ? _("SSL on") : _("SSL off"))));
399 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
400 errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\"",
401 hostinfo, port->user_name)));
408 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
409 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
410 hostinfo, port->user_name,
412 port->ssl ? _("SSL on") : _("SSL off"))));
415 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
416 errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\"",
417 hostinfo, port->user_name,
418 port->database_name)));
424 case uaImplicitReject:
427 * No matching entry, so tell the user we fell through.
429 * NOTE: the extra info reported here is not a security breach,
430 * because all that info is known at the frontend and must be
431 * assumed known to bad guys. We're merely helping out the less
435 char hostinfo[NI_MAXHOST];
437 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
438 hostinfo, sizeof(hostinfo),
446 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
447 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
448 hostinfo, port->user_name,
449 port->ssl ? _("SSL on") : _("SSL off"))));
452 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
453 errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\"",
454 hostinfo, port->user_name)));
461 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
462 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
463 hostinfo, port->user_name,
465 port->ssl ? _("SSL on") : _("SSL off"))));
468 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
469 errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
470 hostinfo, port->user_name,
471 port->database_name)));
479 sendAuthRequest(port, AUTH_REQ_KRB5);
480 status = pg_krb5_recvauth(port);
488 sendAuthRequest(port, AUTH_REQ_GSS);
489 status = pg_GSS_recvauth(port);
497 sendAuthRequest(port, AUTH_REQ_SSPI);
498 status = pg_SSPI_recvauth(port);
505 #ifdef HAVE_UNIX_SOCKETS
506 status = auth_peer(port);
513 status = ident_inet(port);
517 if (Db_user_namespace)
519 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
520 errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
521 sendAuthRequest(port, AUTH_REQ_MD5);
522 status = recv_and_check_password_packet(port);
526 sendAuthRequest(port, AUTH_REQ_PASSWORD);
527 status = recv_and_check_password_packet(port);
532 status = CheckPAMAuth(port, port->user_name, "");
540 status = CheckLDAPAuth(port);
548 status = CheckCertAuth(port);
554 status = CheckRADIUSAuth(port);
561 if (ClientAuthentication_hook)
562 (*ClientAuthentication_hook) (port, status);
564 if (status == STATUS_OK)
565 sendAuthRequest(port, AUTH_REQ_OK);
567 auth_failed(port, status);
569 /* Done with authentication, so we should turn off immediate interrupts */
570 ImmediateInterruptOK = false;
575 * Send an authentication request packet to the frontend.
578 sendAuthRequest(Port *port, AuthRequest areq)
582 pq_beginmessage(&buf, 'R');
583 pq_sendint(&buf, (int32) areq, sizeof(int32));
585 /* Add the salt for encrypted passwords. */
586 if (areq == AUTH_REQ_MD5)
587 pq_sendbytes(&buf, port->md5Salt, 4);
589 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
592 * Add the authentication data for the next step of the GSSAPI or SSPI
595 else if (areq == AUTH_REQ_GSS_CONT)
597 if (port->gss->outbuf.length > 0)
599 elog(DEBUG4, "sending GSS token of length %u",
600 (unsigned int) port->gss->outbuf.length);
602 pq_sendbytes(&buf, port->gss->outbuf.value, port->gss->outbuf.length);
610 * Flush message so client will see it, except for AUTH_REQ_OK, which need
611 * not be sent until we are ready for queries.
613 if (areq != AUTH_REQ_OK)
618 * Collect password response packet from frontend.
620 * Returns NULL if couldn't get password, else palloc'd string.
623 recv_password_packet(Port *port)
627 if (PG_PROTOCOL_MAJOR(port->proto) >= 3)
629 /* Expect 'p' message type */
632 mtype = pq_getbyte();
636 * If the client just disconnects without offering a password,
637 * don't make a log entry. This is legal per protocol spec and in
638 * fact commonly done by psql, so complaining just clutters the
643 (errcode(ERRCODE_PROTOCOL_VIOLATION),
644 errmsg("expected password response, got message type %d",
646 return NULL; /* EOF or bad message type */
651 /* For pre-3.0 clients, avoid log entry if they just disconnect */
652 if (pq_peekbyte() == EOF)
653 return NULL; /* EOF */
656 initStringInfo(&buf);
657 if (pq_getmessage(&buf, 1000)) /* receive password */
659 /* EOF - pq_getmessage already logged a suitable message */
665 * Apply sanity check: password packet length should agree with length of
666 * contained string. Note it is safe to use strlen here because
667 * StringInfo is guaranteed to have an appended '\0'.
669 if (strlen(buf.data) + 1 != buf.len)
671 (errcode(ERRCODE_PROTOCOL_VIOLATION),
672 errmsg("invalid password packet size")));
674 /* Do not echo password to logs, for security. */
676 (errmsg("received password packet")));
679 * Return the received string. Note we do not attempt to do any
680 * character-set conversion on it; since we don't yet know the client's
681 * encoding, there wouldn't be much point.
687 /*----------------------------------------------------------------
689 *----------------------------------------------------------------
693 * Called when we have sent an authorization request for a password.
694 * Get the response and check it.
697 recv_and_check_password_packet(Port *port)
702 passwd = recv_password_packet(port);
705 return STATUS_EOF; /* client wouldn't send password */
707 result = md5_crypt_verify(port, port->user_name, passwd);
715 /*----------------------------------------------------------------
716 * MIT Kerberos authentication system - protocol version 5
717 *----------------------------------------------------------------
722 pg_krb5_init(Port *port)
724 krb5_error_code retval;
727 if (pg_krb5_initialised)
730 retval = krb5_init_context(&pg_krb5_context);
734 (errmsg("Kerberos initialization returned error %d",
736 com_err("postgres", retval, "while initializing krb5");
740 retval = krb5_kt_resolve(pg_krb5_context, pg_krb_server_keyfile, &pg_krb5_keytab);
744 (errmsg("Kerberos keytab resolving returned error %d",
746 com_err("postgres", retval, "while resolving keytab file \"%s\"",
747 pg_krb_server_keyfile);
748 krb5_free_context(pg_krb5_context);
753 * If no hostname was specified, pg_krb_server_hostname is already NULL.
754 * If it's set to blank, force it to NULL.
756 khostname = port->hba->krb_server_hostname;
757 if (khostname && khostname[0] == '\0')
760 retval = krb5_sname_to_principal(pg_krb5_context,
768 (errmsg("Kerberos sname_to_principal(\"%s\", \"%s\") returned error %d",
769 khostname ? khostname : "server hostname", pg_krb_srvnam, retval)));
770 com_err("postgres", retval,
771 "while getting server principal for server \"%s\" for service \"%s\"",
772 khostname ? khostname : "server hostname", pg_krb_srvnam);
773 krb5_kt_close(pg_krb5_context, pg_krb5_keytab);
774 krb5_free_context(pg_krb5_context);
778 pg_krb5_initialised = 1;
784 * pg_krb5_recvauth -- server routine to receive authentication information
787 * We still need to compare the username obtained from the client's setup
788 * packet to the authenticated name.
790 * We have our own keytab file because postgres is unlikely to run as root,
791 * and so cannot read the default keytab.
794 pg_krb5_recvauth(Port *port)
796 krb5_error_code retval;
798 krb5_auth_context auth_context = NULL;
803 ret = pg_krb5_init(port);
804 if (ret != STATUS_OK)
807 retval = krb5_recvauth(pg_krb5_context, &auth_context,
808 (krb5_pointer) &port->sock, pg_krb_srvnam,
809 pg_krb5_server, 0, pg_krb5_keytab, &ticket);
813 (errmsg("Kerberos recvauth returned error %d",
815 com_err("postgres", retval, "from krb5_recvauth");
820 * The "client" structure comes out of the ticket and is therefore
821 * authenticated. Use it to check the username obtained from the
822 * postmaster startup packet.
824 #if defined(HAVE_KRB5_TICKET_ENC_PART2)
825 retval = krb5_unparse_name(pg_krb5_context,
826 ticket->enc_part2->client, &kusername);
827 #elif defined(HAVE_KRB5_TICKET_CLIENT)
828 retval = krb5_unparse_name(pg_krb5_context,
829 ticket->client, &kusername);
831 #error "bogus configuration"
836 (errmsg("Kerberos unparse_name returned error %d",
838 com_err("postgres", retval, "while unparsing client name");
839 krb5_free_ticket(pg_krb5_context, ticket);
840 krb5_auth_con_free(pg_krb5_context, auth_context);
844 cp = strchr(kusername, '@');
848 * If we are not going to include the realm in the username that is
849 * passed to the ident map, destructively modify it here to remove the
850 * realm. Then advance past the separator to check the realm.
852 if (!port->hba->include_realm)
856 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
858 /* Match realm against configured */
859 if (pg_krb_caseins_users)
860 ret = pg_strcasecmp(port->hba->krb_realm, cp);
862 ret = strcmp(port->hba->krb_realm, cp);
867 "krb5 realm (%s) and configured realm (%s) don't match",
868 cp, port->hba->krb_realm);
870 krb5_free_ticket(pg_krb5_context, ticket);
871 krb5_auth_con_free(pg_krb5_context, auth_context);
876 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
879 "krb5 did not return realm but realm matching was requested");
881 krb5_free_ticket(pg_krb5_context, ticket);
882 krb5_auth_con_free(pg_krb5_context, auth_context);
886 ret = check_usermap(port->hba->usermap, port->user_name, kusername,
887 pg_krb_caseins_users);
889 krb5_free_ticket(pg_krb5_context, ticket);
890 krb5_auth_con_free(pg_krb5_context, auth_context);
898 /*----------------------------------------------------------------
899 * GSSAPI authentication system
900 *----------------------------------------------------------------
904 #if defined(WIN32) && !defined(WIN32_ONLY_COMPILER)
906 * MIT Kerberos GSSAPI DLL doesn't properly export the symbols for MingW
907 * that contain the OIDs required. Redefine here, values copied
908 * from src/athena/auth/krb5/src/lib/gssapi/generic/gssapi_generic.c
910 static const gss_OID_desc GSS_C_NT_USER_NAME_desc =
911 {10, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"};
912 static GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_desc;
917 pg_GSS_error(int severity, char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat)
919 gss_buffer_desc gmsg;
925 /* Fetch major status message */
927 gss_display_status(&lmin_s, maj_stat, GSS_C_GSS_CODE,
928 GSS_C_NO_OID, &msg_ctx, &gmsg);
929 strlcpy(msg_major, gmsg.value, sizeof(msg_major));
930 gss_release_buffer(&lmin_s, &gmsg);
935 * More than one message available. XXX: Should we loop and read all
936 * messages? (same below)
939 (errmsg_internal("incomplete GSS error report")));
941 /* Fetch mechanism minor status message */
943 gss_display_status(&lmin_s, min_stat, GSS_C_MECH_CODE,
944 GSS_C_NO_OID, &msg_ctx, &gmsg);
945 strlcpy(msg_minor, gmsg.value, sizeof(msg_minor));
946 gss_release_buffer(&lmin_s, &gmsg);
950 (errmsg_internal("incomplete GSS minor error report")));
953 * errmsg_internal, since translation of the first part must be done
954 * before calling this function anyway.
957 (errmsg_internal("%s", errmsg),
958 errdetail("%s: %s", msg_major, msg_minor)));
962 pg_GSS_recvauth(Port *port)
971 gss_buffer_desc gbuf;
974 * GSS auth is not supported for protocol versions before 3, because it
975 * relies on the overall message length word to determine the GSS payload
976 * size in AuthenticationGSSContinue and PasswordMessage messages. (This
977 * is, in fact, a design error in our GSS support, because protocol
978 * messages are supposed to be parsable without relying on the length
979 * word; but it's not worth changing it now.)
981 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
983 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
984 errmsg("GSSAPI is not supported in protocol version 2")));
986 if (pg_krb_server_keyfile && strlen(pg_krb_server_keyfile) > 0)
989 * Set default Kerberos keytab file for the Krb5 mechanism.
991 * setenv("KRB5_KTNAME", pg_krb_server_keyfile, 0); except setenv()
992 * not always available.
994 if (getenv("KRB5_KTNAME") == NULL)
996 size_t kt_len = strlen(pg_krb_server_keyfile) + 14;
997 char *kt_path = malloc(kt_len);
1002 (errcode(ERRCODE_OUT_OF_MEMORY),
1003 errmsg("out of memory")));
1004 return STATUS_ERROR;
1006 snprintf(kt_path, kt_len, "KRB5_KTNAME=%s", pg_krb_server_keyfile);
1012 * We accept any service principal that's present in our keytab. This
1013 * increases interoperability between kerberos implementations that see
1014 * for example case sensitivity differently, while not really opening up
1015 * any vector of attack.
1017 port->gss->cred = GSS_C_NO_CREDENTIAL;
1020 * Initialize sequence with an empty context
1022 port->gss->ctx = GSS_C_NO_CONTEXT;
1025 * Loop through GSSAPI message exchange. This exchange can consist of
1026 * multiple messags sent in both directions. First message is always from
1027 * the client. All messages from client to server are password packets
1032 mtype = pq_getbyte();
1035 /* Only log error if client didn't disconnect. */
1038 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1039 errmsg("expected GSS response, got message type %d",
1041 return STATUS_ERROR;
1044 /* Get the actual GSS token */
1045 initStringInfo(&buf);
1046 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
1048 /* EOF - pq_getmessage already logged error */
1050 return STATUS_ERROR;
1053 /* Map to GSSAPI style buffer */
1054 gbuf.length = buf.len;
1055 gbuf.value = buf.data;
1057 elog(DEBUG4, "Processing received GSS token of length %u",
1058 (unsigned int) gbuf.length);
1060 maj_stat = gss_accept_sec_context(
1065 GSS_C_NO_CHANNEL_BINDINGS,
1073 /* gbuf no longer used */
1076 elog(DEBUG5, "gss_accept_sec_context major: %d, "
1077 "minor: %d, outlen: %u, outflags: %x",
1079 (unsigned int) port->gss->outbuf.length, gflags);
1081 if (port->gss->outbuf.length != 0)
1084 * Negotiation generated data to be sent to the client.
1088 elog(DEBUG4, "sending GSS response token of length %u",
1089 (unsigned int) port->gss->outbuf.length);
1091 sendAuthRequest(port, AUTH_REQ_GSS_CONT);
1093 gss_release_buffer(&lmin_s, &port->gss->outbuf);
1096 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
1100 gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
1102 gettext_noop("accepting GSS security context failed"),
1103 maj_stat, min_stat);
1106 if (maj_stat == GSS_S_CONTINUE_NEEDED)
1107 elog(DEBUG4, "GSS continue needed");
1109 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
1111 if (port->gss->cred != GSS_C_NO_CREDENTIAL)
1114 * Release service principal credentials
1116 gss_release_cred(&min_stat, &port->gss->cred);
1120 * GSS_S_COMPLETE indicates that authentication is now complete.
1122 * Get the name of the user that authenticated, and compare it to the pg
1123 * username that was specified for the connection.
1125 maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
1126 if (maj_stat != GSS_S_COMPLETE)
1128 gettext_noop("retrieving GSS user name failed"),
1129 maj_stat, min_stat);
1132 * Split the username at the realm separator
1134 if (strchr(gbuf.value, '@'))
1136 char *cp = strchr(gbuf.value, '@');
1139 * If we are not going to include the realm in the username that is
1140 * passed to the ident map, destructively modify it here to remove the
1141 * realm. Then advance past the separator to check the realm.
1143 if (!port->hba->include_realm)
1147 if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
1150 * Match the realm part of the name first
1152 if (pg_krb_caseins_users)
1153 ret = pg_strcasecmp(port->hba->krb_realm, cp);
1155 ret = strcmp(port->hba->krb_realm, cp);
1159 /* GSS realm does not match */
1161 "GSSAPI realm (%s) and configured realm (%s) don't match",
1162 cp, port->hba->krb_realm);
1163 gss_release_buffer(&lmin_s, &gbuf);
1164 return STATUS_ERROR;
1168 else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1171 "GSSAPI did not return realm but realm matching was requested");
1173 gss_release_buffer(&lmin_s, &gbuf);
1174 return STATUS_ERROR;
1177 ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
1178 pg_krb_caseins_users);
1180 gss_release_buffer(&lmin_s, &gbuf);
1184 #endif /* ENABLE_GSS */
1187 /*----------------------------------------------------------------
1188 * SSPI authentication system
1189 *----------------------------------------------------------------
1193 pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
1197 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, r, 0,
1198 sysmsg, sizeof(sysmsg), NULL) == 0)
1200 (errmsg_internal("%s", errmsg),
1201 errdetail("SSPI error %x", (unsigned int) r)));
1204 (errmsg_internal("%s", errmsg),
1205 errdetail("%s (%x)", sysmsg, (unsigned int) r)));
1209 pg_SSPI_recvauth(Port *port)
1214 CredHandle sspicred;
1215 CtxtHandle *sspictx = NULL,
1219 SecBufferDesc inbuf;
1220 SecBufferDesc outbuf;
1221 SecBuffer OutBuffers[1];
1222 SecBuffer InBuffers[1];
1224 TOKEN_USER *tokenuser;
1226 char accountname[MAXPGPATH];
1227 char domainname[MAXPGPATH];
1228 DWORD accountnamesize = sizeof(accountname);
1229 DWORD domainnamesize = sizeof(domainname);
1230 SID_NAME_USE accountnameuse;
1232 QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken;
1235 * SSPI auth is not supported for protocol versions before 3, because it
1236 * relies on the overall message length word to determine the SSPI payload
1237 * size in AuthenticationGSSContinue and PasswordMessage messages. (This
1238 * is, in fact, a design error in our SSPI support, because protocol
1239 * messages are supposed to be parsable without relying on the length
1240 * word; but it's not worth changing it now.)
1242 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
1244 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1245 errmsg("SSPI is not supported in protocol version 2")));
1248 * Acquire a handle to the server credentials.
1250 r = AcquireCredentialsHandle(NULL,
1252 SECPKG_CRED_INBOUND,
1260 pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
1263 * Loop through SSPI message exchange. This exchange can consist of
1264 * multiple messags sent in both directions. First message is always from
1265 * the client. All messages from client to server are password packets
1270 mtype = pq_getbyte();
1273 /* Only log error if client didn't disconnect. */
1276 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1277 errmsg("expected SSPI response, got message type %d",
1279 return STATUS_ERROR;
1282 /* Get the actual SSPI token */
1283 initStringInfo(&buf);
1284 if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
1286 /* EOF - pq_getmessage already logged error */
1288 return STATUS_ERROR;
1291 /* Map to SSPI style buffer */
1292 inbuf.ulVersion = SECBUFFER_VERSION;
1294 inbuf.pBuffers = InBuffers;
1295 InBuffers[0].pvBuffer = buf.data;
1296 InBuffers[0].cbBuffer = buf.len;
1297 InBuffers[0].BufferType = SECBUFFER_TOKEN;
1299 /* Prepare output buffer */
1300 OutBuffers[0].pvBuffer = NULL;
1301 OutBuffers[0].BufferType = SECBUFFER_TOKEN;
1302 OutBuffers[0].cbBuffer = 0;
1303 outbuf.cBuffers = 1;
1304 outbuf.pBuffers = OutBuffers;
1305 outbuf.ulVersion = SECBUFFER_VERSION;
1308 elog(DEBUG4, "Processing received SSPI token of length %u",
1309 (unsigned int) buf.len);
1311 r = AcceptSecurityContext(&sspicred,
1314 ASC_REQ_ALLOCATE_MEMORY,
1315 SECURITY_NETWORK_DREP,
1321 /* input buffer no longer used */
1324 if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
1327 * Negotiation generated data to be sent to the client.
1329 elog(DEBUG4, "sending SSPI response token of length %u",
1330 (unsigned int) outbuf.pBuffers[0].cbBuffer);
1332 port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
1333 port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
1335 sendAuthRequest(port, AUTH_REQ_GSS_CONT);
1337 FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
1340 if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
1342 if (sspictx != NULL)
1344 DeleteSecurityContext(sspictx);
1347 FreeCredentialsHandle(&sspicred);
1348 pg_SSPI_error(ERROR,
1349 _("could not accept SSPI security context"), r);
1352 if (sspictx == NULL)
1354 sspictx = malloc(sizeof(CtxtHandle));
1355 if (sspictx == NULL)
1357 (errmsg("out of memory")));
1359 memcpy(sspictx, &newctx, sizeof(CtxtHandle));
1362 if (r == SEC_I_CONTINUE_NEEDED)
1363 elog(DEBUG4, "SSPI continue needed");
1365 } while (r == SEC_I_CONTINUE_NEEDED);
1369 * Release service principal credentials
1371 FreeCredentialsHandle(&sspicred);
1375 * SEC_E_OK indicates that authentication is now complete.
1377 * Get the name of the user that authenticated, and compare it to the pg
1378 * username that was specified for the connection.
1380 * MingW is missing the export for QuerySecurityContextToken in the
1381 * secur32 library, so we have to load it dynamically.
1384 secur32 = LoadLibrary("SECUR32.DLL");
1385 if (secur32 == NULL)
1387 (errmsg_internal("could not load secur32.dll: %d",
1388 (int) GetLastError())));
1390 _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)
1391 GetProcAddress(secur32, "QuerySecurityContextToken");
1392 if (_QuerySecurityContextToken == NULL)
1394 FreeLibrary(secur32);
1396 (errmsg_internal("could not locate QuerySecurityContextToken in secur32.dll: %d",
1397 (int) GetLastError())));
1400 r = (_QuerySecurityContextToken) (sspictx, &token);
1403 FreeLibrary(secur32);
1404 pg_SSPI_error(ERROR,
1405 _("could not get token from SSPI security context"), r);
1408 FreeLibrary(secur32);
1411 * No longer need the security context, everything from here on uses the
1414 DeleteSecurityContext(sspictx);
1417 if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
1419 (errmsg_internal("could not get token user size: error code %d",
1420 (int) GetLastError())));
1422 tokenuser = malloc(retlen);
1423 if (tokenuser == NULL)
1425 (errmsg("out of memory")));
1427 if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
1429 (errmsg_internal("could not get user token: error code %d",
1430 (int) GetLastError())));
1432 if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
1433 domainname, &domainnamesize, &accountnameuse))
1435 (errmsg_internal("could not lookup acconut sid: error code %d",
1436 (int) GetLastError())));
1441 * Compare realm/domain if requested. In SSPI, always compare case
1444 if (port->hba->krb_realm && strlen(port->hba->krb_realm))
1446 if (pg_strcasecmp(port->hba->krb_realm, domainname))
1449 "SSPI domain (%s) and configured domain (%s) don't match",
1450 domainname, port->hba->krb_realm);
1452 return STATUS_ERROR;
1457 * We have the username (without domain/realm) in accountname, compare to
1458 * the supplied value. In SSPI, always compare case insensitive.
1460 * If set to include realm, append it in <username>@<realm> format.
1462 if (port->hba->include_realm)
1467 namebuf = palloc(strlen(accountname) + strlen(domainname) + 2);
1468 sprintf(namebuf, "%s@%s", accountname, domainname);
1469 retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
1474 return check_usermap(port->hba->usermap, port->user_name, accountname, true);
1476 #endif /* ENABLE_SSPI */
1480 /*----------------------------------------------------------------
1481 * Ident authentication system
1482 *----------------------------------------------------------------
1486 * Parse the string "*ident_response" as a response from a query to an Ident
1487 * server. If it's a normal response indicating a user name, return true
1488 * and store the user name at *ident_user. If it's anything else,
1492 interpret_ident_response(const char *ident_response,
1495 const char *cursor = ident_response; /* Cursor into *ident_response */
1498 * Ident's response, in the telnet tradition, should end in crlf (\r\n).
1500 if (strlen(ident_response) < 2)
1502 else if (ident_response[strlen(ident_response) - 2] != '\r')
1506 while (*cursor != ':' && *cursor != '\r')
1507 cursor++; /* skip port field */
1513 /* We're positioned to colon before response type field */
1514 char response_type[80];
1515 int i; /* Index into *response_type */
1517 cursor++; /* Go over colon */
1518 while (pg_isblank(*cursor))
1519 cursor++; /* skip blanks */
1521 while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
1522 i < (int) (sizeof(response_type) - 1))
1523 response_type[i++] = *cursor++;
1524 response_type[i] = '\0';
1525 while (pg_isblank(*cursor))
1526 cursor++; /* skip blanks */
1527 if (strcmp(response_type, "USERID") != 0)
1532 * It's a USERID response. Good. "cursor" should be pointing
1533 * to the colon that precedes the operating system type.
1539 cursor++; /* Go over colon */
1540 /* Skip over operating system field. */
1541 while (*cursor != ':' && *cursor != '\r')
1547 int i; /* Index into *ident_user */
1549 cursor++; /* Go over colon */
1550 while (pg_isblank(*cursor))
1551 cursor++; /* skip blanks */
1552 /* Rest of line is user name. Copy it over. */
1554 while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
1555 ident_user[i++] = *cursor++;
1556 ident_user[i] = '\0';
1567 * Talk to the ident server on host "remote_ip_addr" and find out who
1568 * owns the tcp connection from his port "remote_port" to port
1569 * "local_port_addr" on host "local_ip_addr". Return the user name the
1570 * ident server gives as "*ident_user".
1572 * IP addresses and port numbers are in network byte order.
1574 * But iff we're unable to get the information from ident, return false.
1577 ident_inet(hbaPort *port)
1579 const SockAddr remote_addr = port->raddr;
1580 const SockAddr local_addr = port->laddr;
1581 char ident_user[IDENT_USERNAME_MAX + 1];
1582 pgsocket sock_fd, /* File descriptor for socket on which we talk
1584 rc; /* Return code from a locally called function */
1586 char remote_addr_s[NI_MAXHOST];
1587 char remote_port[NI_MAXSERV];
1588 char local_addr_s[NI_MAXHOST];
1589 char local_port[NI_MAXSERV];
1590 char ident_port[NI_MAXSERV];
1591 char ident_query[80];
1592 char ident_response[80 + IDENT_USERNAME_MAX];
1593 struct addrinfo *ident_serv = NULL,
1598 * Might look a little weird to first convert it to text and then back to
1599 * sockaddr, but it's protocol independent.
1601 pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
1602 remote_addr_s, sizeof(remote_addr_s),
1603 remote_port, sizeof(remote_port),
1604 NI_NUMERICHOST | NI_NUMERICSERV);
1605 pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
1606 local_addr_s, sizeof(local_addr_s),
1607 local_port, sizeof(local_port),
1608 NI_NUMERICHOST | NI_NUMERICSERV);
1610 snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
1611 hints.ai_flags = AI_NUMERICHOST;
1612 hints.ai_family = remote_addr.addr.ss_family;
1613 hints.ai_socktype = SOCK_STREAM;
1614 hints.ai_protocol = 0;
1615 hints.ai_addrlen = 0;
1616 hints.ai_canonname = NULL;
1617 hints.ai_addr = NULL;
1618 hints.ai_next = NULL;
1619 rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
1620 if (rc || !ident_serv)
1623 pg_freeaddrinfo_all(hints.ai_family, ident_serv);
1624 return STATUS_ERROR; /* we don't expect this to happen */
1627 hints.ai_flags = AI_NUMERICHOST;
1628 hints.ai_family = local_addr.addr.ss_family;
1629 hints.ai_socktype = SOCK_STREAM;
1630 hints.ai_protocol = 0;
1631 hints.ai_addrlen = 0;
1632 hints.ai_canonname = NULL;
1633 hints.ai_addr = NULL;
1634 hints.ai_next = NULL;
1635 rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
1639 pg_freeaddrinfo_all(hints.ai_family, la);
1640 return STATUS_ERROR; /* we don't expect this to happen */
1643 sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
1644 ident_serv->ai_protocol);
1648 (errcode_for_socket_access(),
1649 errmsg("could not create socket for Ident connection: %m")));
1650 ident_return = false;
1651 goto ident_inet_done;
1655 * Bind to the address which the client originally contacted, otherwise
1656 * the ident server won't be able to match up the right connection. This
1657 * is necessary if the PostgreSQL server is running on an IP alias.
1659 rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
1663 (errcode_for_socket_access(),
1664 errmsg("could not bind to local address \"%s\": %m",
1666 ident_return = false;
1667 goto ident_inet_done;
1670 rc = connect(sock_fd, ident_serv->ai_addr,
1671 ident_serv->ai_addrlen);
1675 (errcode_for_socket_access(),
1676 errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
1677 remote_addr_s, ident_port)));
1678 ident_return = false;
1679 goto ident_inet_done;
1682 /* The query we send to the Ident server */
1683 snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
1684 remote_port, local_port);
1686 /* loop in case send is interrupted */
1689 rc = send(sock_fd, ident_query, strlen(ident_query), 0);
1690 } while (rc < 0 && errno == EINTR);
1695 (errcode_for_socket_access(),
1696 errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
1697 remote_addr_s, ident_port)));
1698 ident_return = false;
1699 goto ident_inet_done;
1704 rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
1705 } while (rc < 0 && errno == EINTR);
1710 (errcode_for_socket_access(),
1711 errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
1712 remote_addr_s, ident_port)));
1713 ident_return = false;
1714 goto ident_inet_done;
1717 ident_response[rc] = '\0';
1718 ident_return = interpret_ident_response(ident_response, ident_user);
1721 (errmsg("invalidly formatted response from Ident server: \"%s\"",
1726 closesocket(sock_fd);
1727 pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
1728 pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
1731 /* Success! Check the usermap */
1732 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1733 return STATUS_ERROR;
1737 * Ask kernel about the credentials of the connecting process,
1738 * determine the symbolic name of the corresponding user, and check
1739 * if valid per the usermap.
1741 * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
1743 #ifdef HAVE_UNIX_SOCKETS
1746 auth_peer(hbaPort *port)
1748 char ident_user[IDENT_USERNAME_MAX + 1];
1751 struct passwd *pass;
1754 if (getpeereid(port->sock, &uid, &gid) != 0)
1756 /* Provide special error message if getpeereid is a stub */
1757 if (errno == ENOSYS)
1759 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1760 errmsg("peer authentication is not supported on this platform")));
1763 (errcode_for_socket_access(),
1764 errmsg("could not get peer credentials: %m")));
1765 return STATUS_ERROR;
1768 pass = getpwuid(uid);
1773 (errmsg("local user with ID %d does not exist",
1775 return STATUS_ERROR;
1778 strlcpy(ident_user, pass->pw_name, IDENT_USERNAME_MAX + 1);
1780 return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
1782 #endif /* HAVE_UNIX_SOCKETS */
1785 /*----------------------------------------------------------------
1786 * PAM authentication system
1787 *----------------------------------------------------------------
1792 * PAM conversation function
1796 pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
1797 struct pam_response ** resp, void *appdata_ptr)
1800 struct pam_response *reply;
1804 passwd = (char *) appdata_ptr;
1808 * Workaround for Solaris 2.6 where the PAM library is broken and does
1809 * not pass appdata_ptr to the conversation routine
1811 passwd = pam_passwd;
1814 *resp = NULL; /* in case of error exit */
1816 if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
1817 return PAM_CONV_ERR;
1820 * Explicitly not using palloc here - PAM will free this memory in
1823 if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
1826 (errcode(ERRCODE_OUT_OF_MEMORY),
1827 errmsg("out of memory")));
1828 return PAM_CONV_ERR;
1831 for (i = 0; i < num_msg; i++)
1833 switch (msg[i]->msg_style)
1835 case PAM_PROMPT_ECHO_OFF:
1836 if (strlen(passwd) == 0)
1839 * Password wasn't passed to PAM the first time around -
1840 * let's go ask the client to send a password, which we
1841 * then stuff into PAM.
1843 sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
1844 passwd = recv_password_packet(pam_port_cludge);
1848 * Client didn't want to send password. We
1849 * intentionally do not log anything about this.
1853 if (strlen(passwd) == 0)
1856 (errmsg("empty password returned by client")));
1860 if ((reply[i].resp = strdup(passwd)) == NULL)
1862 reply[i].resp_retcode = PAM_SUCCESS;
1866 (errmsg("error from underlying PAM layer: %s",
1870 /* we don't bother to log TEXT_INFO messages */
1871 if ((reply[i].resp = strdup("")) == NULL)
1873 reply[i].resp_retcode = PAM_SUCCESS;
1876 elog(LOG, "unsupported PAM conversation %d/\"%s\"",
1878 msg[i]->msg ? msg[i]->msg : "(none)");
1887 /* free up whatever we allocated */
1888 for (i = 0; i < num_msg; i++)
1890 if (reply[i].resp != NULL)
1891 free(reply[i].resp);
1895 return PAM_CONV_ERR;
1900 * Check authentication against PAM.
1903 CheckPAMAuth(Port *port, char *user, char *password)
1906 pam_handle_t *pamh = NULL;
1909 * We can't entirely rely on PAM to pass through appdata --- it appears
1910 * not to work on at least Solaris 2.6. So use these ugly static
1911 * variables instead.
1913 pam_passwd = password;
1914 pam_port_cludge = port;
1917 * Set the application data portion of the conversation struct This is
1918 * later used inside the PAM conversation to pass the password to the
1919 * authentication module.
1921 pam_passw_conv.appdata_ptr = (char *) password; /* from password above,
1924 /* Optionally, one can set the service name in pg_hba.conf */
1925 if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
1926 retval = pam_start(port->hba->pamservice, "pgsql@",
1927 &pam_passw_conv, &pamh);
1929 retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
1930 &pam_passw_conv, &pamh);
1932 if (retval != PAM_SUCCESS)
1935 (errmsg("could not create PAM authenticator: %s",
1936 pam_strerror(pamh, retval))));
1937 pam_passwd = NULL; /* Unset pam_passwd */
1938 return STATUS_ERROR;
1941 retval = pam_set_item(pamh, PAM_USER, user);
1943 if (retval != PAM_SUCCESS)
1946 (errmsg("pam_set_item(PAM_USER) failed: %s",
1947 pam_strerror(pamh, retval))));
1948 pam_passwd = NULL; /* Unset pam_passwd */
1949 return STATUS_ERROR;
1952 retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
1954 if (retval != PAM_SUCCESS)
1957 (errmsg("pam_set_item(PAM_CONV) failed: %s",
1958 pam_strerror(pamh, retval))));
1959 pam_passwd = NULL; /* Unset pam_passwd */
1960 return STATUS_ERROR;
1963 retval = pam_authenticate(pamh, 0);
1965 if (retval != PAM_SUCCESS)
1968 (errmsg("pam_authenticate failed: %s",
1969 pam_strerror(pamh, retval))));
1970 pam_passwd = NULL; /* Unset pam_passwd */
1971 return STATUS_ERROR;
1974 retval = pam_acct_mgmt(pamh, 0);
1976 if (retval != PAM_SUCCESS)
1979 (errmsg("pam_acct_mgmt failed: %s",
1980 pam_strerror(pamh, retval))));
1981 pam_passwd = NULL; /* Unset pam_passwd */
1982 return STATUS_ERROR;
1985 retval = pam_end(pamh, retval);
1987 if (retval != PAM_SUCCESS)
1990 (errmsg("could not release PAM authenticator: %s",
1991 pam_strerror(pamh, retval))));
1994 pam_passwd = NULL; /* Unset pam_passwd */
1996 return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
1998 #endif /* USE_PAM */
2002 /*----------------------------------------------------------------
2003 * LDAP authentication system
2004 *----------------------------------------------------------------
2009 * Initialize a connection to the LDAP server, including setting up
2013 InitializeLDAPConnection(Port *port, LDAP **ldap)
2015 int ldapversion = LDAP_VERSION3;
2018 *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
2023 (errmsg("could not initialize LDAP: error code %d",
2027 (errmsg("could not initialize LDAP: error code %d",
2028 (int) LdapGetLastError())));
2030 return STATUS_ERROR;
2033 if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
2037 (errmsg("could not set LDAP protocol version: error code %d", r)));
2038 return STATUS_ERROR;
2041 if (port->hba->ldaptls)
2044 if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
2046 static __ldap_start_tls_sA _ldap_start_tls_sA = NULL;
2048 if (_ldap_start_tls_sA == NULL)
2051 * Need to load this function dynamically because it does not
2052 * exist on Windows 2000, and causes a load error for the whole
2053 * exe if referenced.
2057 ldaphandle = LoadLibrary("WLDAP32.DLL");
2058 if (ldaphandle == NULL)
2061 * should never happen since we import other files from
2062 * wldap32, but check anyway
2066 (errmsg("could not load wldap32.dll")));
2067 return STATUS_ERROR;
2069 _ldap_start_tls_sA = (__ldap_start_tls_sA) GetProcAddress(ldaphandle, "ldap_start_tls_sA");
2070 if (_ldap_start_tls_sA == NULL)
2074 (errmsg("could not load function _ldap_start_tls_sA in wldap32.dll"),
2075 errdetail("LDAP over SSL is not supported on this platform.")));
2076 return STATUS_ERROR;
2080 * Leak LDAP handle on purpose, because we need the library to
2081 * stay open. This is ok because it will only ever be leaked once
2082 * per process and is automatically cleaned up on process exit.
2085 if ((r = _ldap_start_tls_sA(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
2090 (errmsg("could not start LDAP TLS session: error code %d", r)));
2091 return STATUS_ERROR;
2099 * Perform LDAP authentication
2102 CheckLDAPAuth(Port *port)
2109 if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
2112 (errmsg("LDAP server not specified")));
2113 return STATUS_ERROR;
2116 if (port->hba->ldapport == 0)
2117 port->hba->ldapport = LDAP_PORT;
2119 sendAuthRequest(port, AUTH_REQ_PASSWORD);
2121 passwd = recv_password_packet(port);
2123 return STATUS_EOF; /* client wouldn't send password */
2125 if (strlen(passwd) == 0)
2128 (errmsg("empty password returned by client")));
2129 return STATUS_ERROR;
2132 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
2133 /* Error message already sent */
2134 return STATUS_ERROR;
2136 if (port->hba->ldapbasedn)
2139 * First perform an LDAP search to find the DN for the user we are
2140 * trying to log in as.
2143 LDAPMessage *search_message;
2145 char *attributes[2];
2150 * Disallow any characters that we would otherwise need to escape,
2151 * since they aren't really reasonable in a username anyway. Allowing
2152 * them would make it possible to inject any kind of custom filters in
2155 for (c = port->user_name; *c; c++)
2164 (errmsg("invalid character in user name for LDAP authentication")));
2165 return STATUS_ERROR;
2170 * Bind with a pre-defined username/password (if available) for
2171 * searching. If none is specified, this turns into an anonymous bind.
2173 r = ldap_simple_bind_s(ldap,
2174 port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
2175 port->hba->ldapbindpasswd ? port->hba->ldapbindpasswd : "");
2176 if (r != LDAP_SUCCESS)
2179 (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": error code %d",
2180 port->hba->ldapbinddn, port->hba->ldapserver, r)));
2181 return STATUS_ERROR;
2184 /* Fetch just one attribute, else *all* attributes are returned */
2185 attributes[0] = port->hba->ldapsearchattribute ? port->hba->ldapsearchattribute : "uid";
2186 attributes[1] = NULL;
2188 filter = palloc(strlen(attributes[0]) + strlen(port->user_name) + 4);
2189 sprintf(filter, "(%s=%s)",
2193 r = ldap_search_s(ldap,
2194 port->hba->ldapbasedn,
2201 if (r != LDAP_SUCCESS)
2204 (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": error code %d",
2205 filter, port->hba->ldapserver, r)));
2207 return STATUS_ERROR;
2210 if (ldap_count_entries(ldap, search_message) != 1)
2212 if (ldap_count_entries(ldap, search_message) == 0)
2214 (errmsg("LDAP search failed for filter \"%s\" on server \"%s\": no such user",
2215 filter, port->hba->ldapserver)));
2218 (errmsg("LDAP search failed for filter \"%s\" on server \"%s\": user is not unique (%ld matches)",
2219 filter, port->hba->ldapserver,
2220 (long) ldap_count_entries(ldap, search_message))));
2223 ldap_msgfree(search_message);
2224 return STATUS_ERROR;
2227 entry = ldap_first_entry(ldap, search_message);
2228 dn = ldap_get_dn(ldap, entry);
2233 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
2235 (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
2236 filter, port->hba->ldapserver, ldap_err2string(error))));
2238 ldap_msgfree(search_message);
2239 return STATUS_ERROR;
2241 fulluser = pstrdup(dn);
2245 ldap_msgfree(search_message);
2247 /* Unbind and disconnect from the LDAP server */
2248 r = ldap_unbind_s(ldap);
2249 if (r != LDAP_SUCCESS)
2253 (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
2255 (errmsg("could not unbind after searching for user \"%s\" on server \"%s\": %s",
2256 fulluser, port->hba->ldapserver, ldap_err2string(error))));
2258 return STATUS_ERROR;
2262 * Need to re-initialize the LDAP connection, so that we can bind to
2263 * it with a different username.
2265 if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
2269 /* Error message already sent */
2270 return STATUS_ERROR;
2275 fulluser = palloc((port->hba->ldapprefix ? strlen(port->hba->ldapprefix) : 0) +
2276 strlen(port->user_name) +
2277 (port->hba->ldapsuffix ? strlen(port->hba->ldapsuffix) : 0) +
2280 sprintf(fulluser, "%s%s%s",
2281 port->hba->ldapprefix ? port->hba->ldapprefix : "",
2283 port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
2286 r = ldap_simple_bind_s(ldap, fulluser, passwd);
2289 if (r != LDAP_SUCCESS)
2292 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
2293 fulluser, port->hba->ldapserver, r)));
2295 return STATUS_ERROR;
2302 #endif /* USE_LDAP */
2305 /*----------------------------------------------------------------
2306 * SSL client certificate authentication
2307 *----------------------------------------------------------------
2311 CheckCertAuth(Port *port)
2315 /* Make sure we have received a username in the certificate */
2316 if (port->peer_cn == NULL ||
2317 strlen(port->peer_cn) <= 0)
2320 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
2322 return STATUS_ERROR;
2325 /* Just pass the certificate CN to the usermap check */
2326 return check_usermap(port->hba->usermap, port->user_name, port->peer_cn, false);
2331 /*----------------------------------------------------------------
2332 * RADIUS authentication
2333 *----------------------------------------------------------------
2337 * RADIUS authentication is described in RFC2865 (and several
2341 #define RADIUS_VECTOR_LENGTH 16
2342 #define RADIUS_HEADER_LENGTH 20
2356 uint8 vector[RADIUS_VECTOR_LENGTH];
2359 /* RADIUS packet types */
2360 #define RADIUS_ACCESS_REQUEST 1
2361 #define RADIUS_ACCESS_ACCEPT 2
2362 #define RADIUS_ACCESS_REJECT 3
2364 /* RAIDUS attributes */
2365 #define RADIUS_USER_NAME 1
2366 #define RADIUS_PASSWORD 2
2367 #define RADIUS_SERVICE_TYPE 6
2368 #define RADIUS_NAS_IDENTIFIER 32
2370 /* RADIUS service types */
2371 #define RADIUS_AUTHENTICATE_ONLY 8
2373 /* Maximum size of a RADIUS packet we will create or accept */
2374 #define RADIUS_BUFFER_SIZE 1024
2376 /* Seconds to wait - XXX: should be in a config variable! */
2377 #define RADIUS_TIMEOUT 3
2380 radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
2382 radius_attribute *attr;
2384 if (packet->length + len > RADIUS_BUFFER_SIZE)
2387 * With remotely realistic data, this can never happen. But catch it
2388 * just to make sure we don't overrun a buffer. We'll just skip adding
2389 * the broken attribute, which will in the end cause authentication to
2393 "Adding attribute code %i with length %i to radius packet would create oversize packet, ignoring",
2399 attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
2400 attr->attribute = type;
2401 attr->length = len + 2; /* total size includes type and length */
2402 memcpy(attr->data, data, len);
2403 packet->length += attr->length;
2407 CheckRADIUSAuth(Port *port)
2410 char *identifier = "postgresql";
2411 char radius_buffer[RADIUS_BUFFER_SIZE];
2412 char receive_buffer[RADIUS_BUFFER_SIZE];
2413 radius_packet *packet = (radius_packet *) radius_buffer;
2414 radius_packet *receivepacket = (radius_packet *) receive_buffer;
2415 int32 service = htonl(RADIUS_AUTHENTICATE_ONLY);
2417 uint8 encryptedpassword[RADIUS_VECTOR_LENGTH];
2422 struct sockaddr_in6 localaddr;
2423 struct sockaddr_in6 remoteaddr;
2425 struct sockaddr_in localaddr;
2426 struct sockaddr_in remoteaddr;
2428 struct addrinfo hint;
2429 struct addrinfo *serveraddrs;
2431 ACCEPT_TYPE_ARG3 addrsize;
2433 struct timeval endtime;
2437 /* Make sure struct alignment is correct */
2438 Assert(offsetof(radius_packet, vector) == 4);
2440 /* Verify parameters */
2441 if (!port->hba->radiusserver || port->hba->radiusserver[0] == '\0')
2444 (errmsg("RADIUS server not specified")));
2445 return STATUS_ERROR;
2448 if (!port->hba->radiussecret || port->hba->radiussecret[0] == '\0')
2451 (errmsg("RADIUS secret not specified")));
2452 return STATUS_ERROR;
2455 if (port->hba->radiusport == 0)
2456 port->hba->radiusport = 1812;
2458 MemSet(&hint, 0, sizeof(hint));
2459 hint.ai_socktype = SOCK_DGRAM;
2460 hint.ai_family = AF_UNSPEC;
2461 snprintf(portstr, sizeof(portstr), "%d", port->hba->radiusport);
2463 r = pg_getaddrinfo_all(port->hba->radiusserver, portstr, &hint, &serveraddrs);
2464 if (r || !serveraddrs)
2467 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2468 port->hba->radiusserver, gai_strerror(r))));
2470 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2471 return STATUS_ERROR;
2473 /* XXX: add support for multiple returned addresses? */
2475 if (port->hba->radiusidentifier && port->hba->radiusidentifier[0])
2476 identifier = port->hba->radiusidentifier;
2478 /* Send regular password request to client, and get the response */
2479 sendAuthRequest(port, AUTH_REQ_PASSWORD);
2481 passwd = recv_password_packet(port);
2483 return STATUS_EOF; /* client wouldn't send password */
2485 if (strlen(passwd) == 0)
2488 (errmsg("empty password returned by client")));
2489 return STATUS_ERROR;
2492 if (strlen(passwd) > RADIUS_VECTOR_LENGTH)
2495 (errmsg("RADIUS authentication does not support passwords longer than 16 characters")));
2496 return STATUS_ERROR;
2499 /* Construct RADIUS packet */
2500 packet->code = RADIUS_ACCESS_REQUEST;
2501 packet->length = RADIUS_HEADER_LENGTH;
2503 if (RAND_bytes(packet->vector, RADIUS_VECTOR_LENGTH) != 1)
2506 (errmsg("could not generate random encryption vector")));
2507 return STATUS_ERROR;
2510 for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
2511 /* Use a lower strengh random number of OpenSSL is not available */
2512 packet->vector[i] = random() % 255;
2514 packet->id = packet->vector[0];
2515 radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (unsigned char *) &service, sizeof(service));
2516 radius_add_attribute(packet, RADIUS_USER_NAME, (unsigned char *) port->user_name, strlen(port->user_name));
2517 radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (unsigned char *) identifier, strlen(identifier));
2520 * RADIUS password attributes are calculated as: e[0] = p[0] XOR
2521 * MD5(secret + vector)
2523 cryptvector = palloc(RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret));
2524 memcpy(cryptvector, port->hba->radiussecret, strlen(port->hba->radiussecret));
2525 memcpy(cryptvector + strlen(port->hba->radiussecret), packet->vector, RADIUS_VECTOR_LENGTH);
2526 if (!pg_md5_binary(cryptvector, RADIUS_VECTOR_LENGTH + strlen(port->hba->radiussecret), encryptedpassword))
2529 (errmsg("could not perform MD5 encryption of password")));
2531 return STATUS_ERROR;
2534 for (i = 0; i < RADIUS_VECTOR_LENGTH; i++)
2536 if (i < strlen(passwd))
2537 encryptedpassword[i] = passwd[i] ^ encryptedpassword[i];
2539 encryptedpassword[i] = '\0' ^ encryptedpassword[i];
2541 radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, RADIUS_VECTOR_LENGTH);
2543 /* Length need to be in network order on the wire */
2544 packetlength = packet->length;
2545 packet->length = htons(packet->length);
2547 sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
2551 (errmsg("could not create RADIUS socket: %m")));
2552 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2553 return STATUS_ERROR;
2556 memset(&localaddr, 0, sizeof(localaddr));
2558 localaddr.sin6_family = serveraddrs[0].ai_family;
2559 localaddr.sin6_addr = in6addr_any;
2560 if (localaddr.sin6_family == AF_INET6)
2561 addrsize = sizeof(struct sockaddr_in6);
2563 addrsize = sizeof(struct sockaddr_in);
2565 localaddr.sin_family = serveraddrs[0].ai_family;
2566 localaddr.sin_addr.s_addr = INADDR_ANY;
2567 addrsize = sizeof(struct sockaddr_in);
2569 if (bind(sock, (struct sockaddr *) & localaddr, addrsize))
2572 (errmsg("could not bind local RADIUS socket: %m")));
2574 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2575 return STATUS_ERROR;
2578 if (sendto(sock, radius_buffer, packetlength, 0,
2579 serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
2582 (errmsg("could not send RADIUS packet: %m")));
2584 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2585 return STATUS_ERROR;
2588 /* Don't need the server address anymore */
2589 pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
2592 * Figure out at what time we should time out. We can't just use a single
2593 * call to select() with a timeout, since somebody can be sending invalid
2594 * packets to our port thus causing us to retry in a loop and never time
2597 gettimeofday(&endtime, NULL);
2598 endtime.tv_sec += RADIUS_TIMEOUT;
2602 struct timeval timeout;
2606 gettimeofday(&now, NULL);
2607 timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
2608 if (timeoutval <= 0)
2611 (errmsg("timeout waiting for RADIUS response")));
2613 return STATUS_ERROR;
2615 timeout.tv_sec = timeoutval / 1000000;
2616 timeout.tv_usec = timeoutval % 1000000;
2619 FD_SET(sock, &fdset);
2621 r = select(sock + 1, &fdset, NULL, NULL, &timeout);
2627 /* Anything else is an actual error */
2629 (errmsg("could not check status on RADIUS socket: %m")));
2631 return STATUS_ERROR;
2636 (errmsg("timeout waiting for RADIUS response")));
2638 return STATUS_ERROR;
2642 * Attempt to read the response packet, and verify the contents.
2644 * Any packet that's not actually a RADIUS packet, or otherwise does
2645 * not validate as an explicit reject, is just ignored and we retry
2646 * for another packet (until we reach the timeout). This is to avoid
2647 * the possibility to denial-of-service the login by flooding the
2648 * server with invalid packets on the port that we're expecting the
2649 * RADIUS response on.
2652 addrsize = sizeof(remoteaddr);
2653 packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
2654 (struct sockaddr *) & remoteaddr, &addrsize);
2655 if (packetlength < 0)
2658 (errmsg("could not read RADIUS response: %m")));
2659 return STATUS_ERROR;
2663 if (remoteaddr.sin6_port != htons(port->hba->radiusport))
2665 if (remoteaddr.sin_port != htons(port->hba->radiusport))
2670 (errmsg("RADIUS response was sent from incorrect port: %i",
2671 ntohs(remoteaddr.sin6_port))));
2674 (errmsg("RADIUS response was sent from incorrect port: %i",
2675 ntohs(remoteaddr.sin_port))));
2680 if (packetlength < RADIUS_HEADER_LENGTH)
2683 (errmsg("RADIUS response too short: %i", packetlength)));
2687 if (packetlength != ntohs(receivepacket->length))
2690 (errmsg("RADIUS response has corrupt length: %i (actual length %i)",
2691 ntohs(receivepacket->length), packetlength)));
2695 if (packet->id != receivepacket->id)
2698 (errmsg("RADIUS response is to a different request: %i (should be %i)",
2699 receivepacket->id, packet->id)));
2704 * Verify the response authenticator, which is calculated as
2705 * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
2707 cryptvector = palloc(packetlength + strlen(port->hba->radiussecret));
2709 memcpy(cryptvector, receivepacket, 4); /* code+id+length */
2710 memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH); /* request
2711 * authenticator, from
2712 * original packet */
2713 if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
2714 * attributes at all */
2715 memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
2716 memcpy(cryptvector + packetlength, port->hba->radiussecret, strlen(port->hba->radiussecret));
2718 if (!pg_md5_binary(cryptvector,
2719 packetlength + strlen(port->hba->radiussecret),
2723 (errmsg("could not perform MD5 encryption of received packet")));
2729 if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
2732 (errmsg("RADIUS response has incorrect MD5 signature")));
2736 if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
2741 else if (receivepacket->code == RADIUS_ACCESS_REJECT)
2744 return STATUS_ERROR;
2749 (errmsg("RADIUS response has invalid code (%i) for user \"%s\"",
2750 receivepacket->code, port->user_name)));
2753 } /* while (true) */