|
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 | intpacketlen;
|
1748 | 1753 |
|
| 1754 | +#ifdefHAVE_UNIX_SOCKETS |
| 1755 | +if (conn->requirepeer) |
| 1756 | +{ |
| 1757 | +charpwdbuf[BUFSIZ]; |
| 1758 | +structpasswdpass_buf; |
| 1759 | +structpasswd*pass; |
| 1760 | +uid_tuid; |
| 1761 | + |
| 1762 | +# if defined(HAVE_GETPEEREID) |
| 1763 | +gid_tgid; |
| 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 | +gotoerror_return; |
| 1772 | +} |
| 1773 | +# elif defined(SO_PEERCRED) |
| 1774 | +structucredpeercred; |
| 1775 | +ACCEPT_TYPE_ARG3so_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 | +gotoerror_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 | +gotoerror_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 | +gotoerror_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 | +gotoerror_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 | +gotoerror_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 | +gotoerror_return; |
| 1830 | +} |
| 1831 | +} |
| 1832 | +#endif/* HAVE_UNIX_SOCKETS */ |
| 1833 | + |
1749 | 1834 | #ifdefUSE_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);
|
|