mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Check effective credentials of socket peers
Fix for CVE-2014-2905. Code for getpeereid() on non-BSD systems imported from the PostgreSQL project under a BSD-style license. Closes #1436
This commit is contained in:
parent
97c2ec8dcf
commit
ba1b5e34a7
7 changed files with 137 additions and 5 deletions
|
@ -378,7 +378,7 @@ fi
|
||||||
# Check presense of various header files
|
# Check presense of various header files
|
||||||
#
|
#
|
||||||
|
|
||||||
AC_CHECK_HEADERS([getopt.h termios.h sys/resource.h term.h ncurses/term.h ncurses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h execinfo.h spawn.h sys/sysctl.h])
|
AC_CHECK_HEADERS([getopt.h termios.h sys/resource.h term.h ncurses/term.h ncurses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h execinfo.h spawn.h sys/sysctl.h sys/un.h sys/ucred.h ucred.h ])
|
||||||
|
|
||||||
if test x$local_gettext != xno; then
|
if test x$local_gettext != xno; then
|
||||||
AC_CHECK_HEADERS([libintl.h])
|
AC_CHECK_HEADERS([libintl.h])
|
||||||
|
@ -519,7 +519,7 @@ fi
|
||||||
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf )
|
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf )
|
||||||
AC_CHECK_FUNCS( futimes wcwidth wcswidth wcstok fputwc fgetwc )
|
AC_CHECK_FUNCS( futimes wcwidth wcswidth wcstok fputwc fgetwc )
|
||||||
AC_CHECK_FUNCS( wcstol wcslcat wcslcpy lrand48_r killpg )
|
AC_CHECK_FUNCS( wcstol wcslcat wcslcpy lrand48_r killpg )
|
||||||
AC_CHECK_FUNCS( backtrace backtrace_symbols sysconf getifaddrs )
|
AC_CHECK_FUNCS( backtrace backtrace_symbols sysconf getifaddrs getpeerucred getpeereid )
|
||||||
|
|
||||||
if test x$local_gettext != xno; then
|
if test x$local_gettext != xno; then
|
||||||
AC_CHECK_FUNCS( gettext dcgettext )
|
AC_CHECK_FUNCS( gettext dcgettext )
|
||||||
|
|
|
@ -1400,7 +1400,34 @@ POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
|
|
||||||
*/
|
<hr>
|
||||||
|
|
||||||
|
<h2>License for getpeereid</h2>
|
||||||
|
|
||||||
|
\c fish contains code imported from the PostgreSQL project under
|
||||||
|
license, namely the getpeereid fallback function. This code is copyrighted
|
||||||
|
by:
|
||||||
|
|
||||||
|
Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
||||||
|
|
||||||
|
Portions Copyright (c) 1994, The Regents of the University of California
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose, without fee, and without a written agreement
|
||||||
|
is hereby granted, provided that the above copyright notice and this
|
||||||
|
paragraph and the following two paragraphs appear in all copies.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||||
|
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
|
||||||
|
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
|
||||||
|
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
|
||||||
|
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
<h2>License for UTF8</h2>
|
<h2>License for UTF8</h2>
|
||||||
|
|
||||||
|
@ -1419,3 +1446,4 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
\htmlonly </div> \endhtmlonly
|
\htmlonly </div> \endhtmlonly
|
||||||
|
*/
|
||||||
|
|
|
@ -89,6 +89,8 @@ static int try_get_socket_once(void)
|
||||||
|
|
||||||
wdir = path;
|
wdir = path;
|
||||||
wuname = user;
|
wuname = user;
|
||||||
|
uid_t seuid;
|
||||||
|
gid_t segid;
|
||||||
|
|
||||||
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||||
{
|
{
|
||||||
|
@ -142,6 +144,13 @@ static int try_get_socket_once(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((getpeereid(s, &seuid, &segid) != 0) || seuid != geteuid())
|
||||||
|
{
|
||||||
|
debug(1, L"Wrong credentials for socket %s at fd %d", name.c_str(), s);
|
||||||
|
close(s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((make_fd_nonblocking(s) != 0) || (fcntl(s, F_SETFD, FD_CLOEXEC) != 0))
|
if ((make_fd_nonblocking(s) != 0) || (fcntl(s, F_SETFD, FD_CLOEXEC) != 0))
|
||||||
{
|
{
|
||||||
wperror(L"fcntl");
|
wperror(L"fcntl");
|
||||||
|
|
80
fallback.cpp
80
fallback.cpp
|
@ -15,8 +15,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <sys/param.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
@ -1520,3 +1521,80 @@ static int mk_wcswidth(const wchar_t *pwcs, size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HAVE_BROKEN_WCWIDTH
|
#endif // HAVE_BROKEN_WCWIDTH
|
||||||
|
|
||||||
|
#ifndef HAVE_GETPEEREID
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* getpeereid.c
|
||||||
|
* get peer userid for UNIX-domain socket connection
|
||||||
|
*
|
||||||
|
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* IDENTIFICATION
|
||||||
|
* src/port/getpeereid.c
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
#include <sys/un.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UCRED_H
|
||||||
|
#include <ucred.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
|
#include <sys/ucred.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BSD-style getpeereid() for platforms that lack it.
|
||||||
|
*/
|
||||||
|
int getpeereid(int sock, uid_t *uid, gid_t *gid)
|
||||||
|
{
|
||||||
|
#if defined(SO_PEERCRED)
|
||||||
|
/* Linux: use getsockopt(SO_PEERCRED) */
|
||||||
|
struct ucred peercred;
|
||||||
|
socklen_t so_len = sizeof(peercred);
|
||||||
|
|
||||||
|
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
|
||||||
|
so_len != sizeof(peercred))
|
||||||
|
return -1;
|
||||||
|
*uid = peercred.uid;
|
||||||
|
*gid = peercred.gid;
|
||||||
|
return 0;
|
||||||
|
#elif defined(LOCAL_PEERCRED)
|
||||||
|
/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
|
||||||
|
struct xucred peercred;
|
||||||
|
socklen_t * so_len = sizeof(peercred);
|
||||||
|
|
||||||
|
if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
|
||||||
|
so_len != sizeof(peercred) ||
|
||||||
|
peercred.cr_version != XUCRED_VERSION)
|
||||||
|
return -1;
|
||||||
|
*uid = peercred.cr_uid;
|
||||||
|
*gid = peercred.cr_gid;
|
||||||
|
return 0;
|
||||||
|
#elif defined(HAVE_GETPEERUCRED)
|
||||||
|
/* Solaris: use getpeerucred() */
|
||||||
|
ucred_t *ucred;
|
||||||
|
|
||||||
|
ucred = NULL; /* must be initialized to NULL */
|
||||||
|
if (getpeerucred(sock, &ucred) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*uid = ucred_geteuid(ucred);
|
||||||
|
*gid = ucred_getegid(ucred);
|
||||||
|
ucred_free(ucred);
|
||||||
|
|
||||||
|
if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
/* No implementation available on this platform */
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // HAVE_GETPEEREID
|
||||||
|
|
|
@ -482,3 +482,7 @@ double nan(char *tagp);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_GETPEEREID
|
||||||
|
int getpeereid(int sock, uid_t *uid, gid_t *gid);
|
||||||
|
#endif
|
||||||
|
|
|
@ -880,6 +880,8 @@ int main(int argc, char ** argv)
|
||||||
int child_socket;
|
int child_socket;
|
||||||
struct sockaddr_un remote;
|
struct sockaddr_un remote;
|
||||||
socklen_t t;
|
socklen_t t;
|
||||||
|
uid_t sock_euid;
|
||||||
|
gid_t sock_egid;
|
||||||
int max_fd;
|
int max_fd;
|
||||||
int update_count=0;
|
int update_count=0;
|
||||||
|
|
||||||
|
@ -1000,7 +1002,12 @@ int main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
debug(4, L"Connected with new child on fd %d", child_socket);
|
debug(4, L"Connected with new child on fd %d", child_socket);
|
||||||
|
|
||||||
if (make_fd_nonblocking(child_socket) != 0)
|
if (((getpeereid(child_socket, &sock_euid, &sock_egid) != 0) || sock_euid != geteuid()))
|
||||||
|
{
|
||||||
|
debug(1, L"Wrong credentials for child on fd %d", child_socket);
|
||||||
|
close(child_socket);
|
||||||
|
}
|
||||||
|
else if (make_fd_nonblocking(child_socket) != 0)
|
||||||
{
|
{
|
||||||
wperror(L"fcntl");
|
wperror(L"fcntl");
|
||||||
close(child_socket);
|
close(child_socket);
|
||||||
|
|
|
@ -40,6 +40,12 @@
|
||||||
/* Define to 1 if you have the <getopt.h> header file. */
|
/* Define to 1 if you have the <getopt.h> header file. */
|
||||||
#define HAVE_GETOPT_H 1
|
#define HAVE_GETOPT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpeereid' function. */
|
||||||
|
#define HAVE_GETPEEREID 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getpeerucred' function. */
|
||||||
|
/* #undef HAVE_GETPEERUCRED */
|
||||||
|
|
||||||
/* Define to 1 if you have the `gettext' function. */
|
/* Define to 1 if you have the `gettext' function. */
|
||||||
/* #undef HAVE_GETTEXT */
|
/* #undef HAVE_GETTEXT */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue