|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.398 2010/07/08 16:19:50 mha Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.399 2010/07/18 11:37:26 petere Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -229,6 +229,9 @@ static const PQconninfoOption PQconninfoOptions[] = {
|
229 | 229 | {"sslcrl", "PGSSLCRL", NULL, NULL,
|
230 | 230 | "SSL-Revocation-List", "", 64},
|
231 | 231 |
|
| 232 | + {"requirepeer", "PGREQUIREPEER", NULL, NULL, |
| 233 | + "Require-Peer", "", 10}, |
| 234 | + |
232 | 235 | #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
|
233 | 236 | /* Kerberos and GSSAPI authentication support specifying the service name */
|
234 | 237 | {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
|
@@ -595,6 +598,8 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
|
595 | 598 | conn->sslmode = strdup("require");
|
596 | 599 | }
|
597 | 600 | #endif
|
| 601 | + tmp = conninfo_getval(connOptions, "requirepeer"); |
| 602 | + conn->requirepeer = tmp ? strdup(tmp) : NULL; |
598 | 603 | #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
|
599 | 604 | tmp = conninfo_getval(connOptions, "krbsrvname");
|
600 | 605 | conn->krbsrvname = tmp ? strdup(tmp) : NULL;
|
@@ -1746,6 +1751,86 @@ PQconnectPoll(PGconn *conn)
|
1746 | 1751 | char *startpacket;
|
1747 | 1752 | int packetlen;
|
1748 | 1753 |
|
| 1754 | +#ifdef HAVE_UNIX_SOCKETS |
| 1755 | + if (conn->requirepeer) |
| 1756 | + { |
| 1757 | + char pwdbuf[BUFSIZ]; |
| 1758 | + struct passwd pass_buf; |
| 1759 | + struct passwd *pass; |
| 1760 | + uid_t uid; |
| 1761 | + |
| 1762 | +# if defined(HAVE_GETPEEREID) |
| 1763 | + gid_t gid; |
| 1764 | + |
| 1765 | + errno = 0; |
| 1766 | + if (getpeereid(sock, &uid, &gid) != 0) |
| 1767 | + { |
| 1768 | + appendPQExpBuffer(&conn->errorMessage, |
| 1769 | + libpq_gettext("could not get peer credentials: %s\n"), |
| 1770 | + pqStrerror(errno, sebuf, sizeof(sebuf))); |
| 1771 | + goto error_return; |
| 1772 | + } |
| 1773 | +# elif defined(SO_PEERCRED) |
| 1774 | + struct ucred peercred; |
| 1775 | + ACCEPT_TYPE_ARG3 so_len = sizeof(peercred); |
| 1776 | + |
| 1777 | + errno = 0; |
| 1778 | + if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 || |
| 1779 | + so_len != sizeof(peercred)) |
| 1780 | + { |
| 1781 | + appendPQExpBuffer(&conn->errorMessage, |
| 1782 | + libpq_gettext("could not get peer credentials: %s\n"), |
| 1783 | + pqStrerror(errno, sebuf, sizeof(sebuf))); |
| 1784 | + goto error_return; |
| 1785 | + } |
| 1786 | + uid = peercred.uid; |
| 1787 | +# elif defined(HAVE_GETPEERUCRED) |
| 1788 | + ucred_t *ucred; |
| 1789 | + |
| 1790 | + ucred = NULL; /* must be initialized to NULL */ |
| 1791 | + if (getpeerucred(sock, &ucred) == -1) |
| 1792 | + { |
| 1793 | + appendPQExpBuffer(&conn->errorMessage, |
| 1794 | + libpq_gettext("could not get peer credentials: %s\n"), |
| 1795 | + pqStrerror(errno, sebuf, sizeof(sebuf))); |
| 1796 | + goto error_return; |
| 1797 | + } |
| 1798 | + |
| 1799 | + if ((uid = ucred_geteuid(ucred)) == -1) |
| 1800 | + { |
| 1801 | + appendPQExpBuffer(&conn->errorMessage, |
| 1802 | + libpq_gettext("could not get effective UID from peer credentials: %s\n"), |
| 1803 | + pqStrerror(errno, sebuf, sizeof(sebuf))); |
| 1804 | + ucred_free(ucred); |
| 1805 | + goto error_return; |
| 1806 | + } |
| 1807 | + ucred_free(ucred); |
| 1808 | +# else |
| 1809 | + appendPQExpBuffer(&conn->errorMessage, |
| 1810 | + libpq_gettext("requirepeer parameter is not supported on this platform\n")); |
| 1811 | + goto error_return; |
| 1812 | +# endif |
| 1813 | + |
| 1814 | + pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass); |
| 1815 | + |
| 1816 | + if (pass == NULL) |
| 1817 | + { |
| 1818 | + appendPQExpBuffer(&conn->errorMessage, |
| 1819 | + libpq_gettext("local user with ID %d does not exist\n"), |
| 1820 | + (int) peercred.uid); |
| 1821 | + goto error_return; |
| 1822 | + } |
| 1823 | + |
| 1824 | + if (strcmp(pass->pw_name, conn->requirepeer) != 0) |
| 1825 | + { |
| 1826 | + appendPQExpBuffer(&conn->errorMessage, |
| 1827 | + libpq_gettext("requirepeer failed (actual: %s != required: %s)\n"), |
| 1828 | + pass->pw_name, conn->requirepeer); |
| 1829 | + goto error_return; |
| 1830 | + } |
| 1831 | + } |
| 1832 | +#endif /* HAVE_UNIX_SOCKETS */ |
| 1833 | + |
1749 | 1834 | #ifdef USE_SSL
|
1750 | 1835 |
|
1751 | 1836 | /*
|
@@ -2553,6 +2638,8 @@ freePGconn(PGconn *conn)
|
2553 | 2638 | free(conn->sslrootcert);
|
2554 | 2639 | if (conn->sslcrl)
|
2555 | 2640 | free(conn->sslcrl);
|
| 2641 | + if (conn->requirepeer) |
| 2642 | + free(conn->requirepeer); |
2556 | 2643 | #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI)
|
2557 | 2644 | if (conn->krbsrvname)
|
2558 | 2645 | free(conn->krbsrvname);
|
|
0 commit comments