From 189de02d9ad6f3645417c0ddf359b923aae5f926 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 21 Aug 2015 15:45:02 +1000 Subject: expose POLLHUP and POLLNVAL for netcat.c --- openbsd-compat/bsd-poll.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/bsd-poll.h b/openbsd-compat/bsd-poll.h index dcbb9ca40..17945f5b4 100644 --- a/openbsd-compat/bsd-poll.h +++ b/openbsd-compat/bsd-poll.h @@ -42,11 +42,11 @@ typedef unsigned int nfds_t; #define POLLIN 0x0001 #define POLLOUT 0x0004 #define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 #if 0 /* the following are currently not implemented */ #define POLLPRI 0x0002 -#define POLLHUP 0x0010 -#define POLLNVAL 0x0020 #define POLLRDNORM 0x0040 #define POLLNORM POLLRDNORM #define POLLWRNORM POLLOUT -- cgit v1.2.3 From 7365fe5b4859de2305e40ea132da3823830fa710 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:25:09 +1100 Subject: upstream commit revision 1.14 date: 2011/07/24 21:03:00; author: miod; state: Exp; lines: +35 -13; Recent Single Unix will malloc memory if the second argument of realpath() is NULL, and third-party software is starting to rely upon this. Adapted from FreeBSD via Jona Joachim (jaj ; hcl-club , .lu), with minor tweaks from nicm@ and yours truly. --- openbsd-compat/realpath.c | 48 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index ba4cea938..6646330ca 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ +/* $OpenBSD: realpath.c,v 1.14 2011/07/24 21:03:00 miod Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -51,16 +51,30 @@ * in which case the path which caused trouble is left in (resolved). */ char * -realpath(const char *path, char resolved[PATH_MAX]) +realpath(const char *path, char *resolved) { struct stat sb; char *p, *q, *s; size_t left_len, resolved_len; unsigned symlinks; - int serrno, slen; + int serrno, slen, mem_allocated; char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; + if (path[0] == '\0') { + errno = ENOENT; + return (NULL); + } + serrno = errno; + + if (resolved == NULL) { + resolved = malloc(PATH_MAX); + if (resolved == NULL) + return (NULL); + mem_allocated = 1; + } else + mem_allocated = 0; + symlinks = 0; if (path[0] == '/') { resolved[0] = '/'; @@ -71,7 +85,10 @@ realpath(const char *path, char resolved[PATH_MAX]) left_len = strlcpy(left, path + 1, sizeof(left)); } else { if (getcwd(resolved, PATH_MAX) == NULL) { - strlcpy(resolved, ".", PATH_MAX); + if (mem_allocated) + free(resolved); + else + strlcpy(resolved, ".", PATH_MAX); return (NULL); } resolved_len = strlen(resolved); @@ -79,7 +96,7 @@ realpath(const char *path, char resolved[PATH_MAX]) } if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; - return (NULL); + goto err; } /* @@ -94,7 +111,7 @@ realpath(const char *path, char resolved[PATH_MAX]) s = p ? p : left + left_len; if (s - left >= (ptrdiff_t)sizeof(next_token)) { errno = ENAMETOOLONG; - return (NULL); + goto err; } memcpy(next_token, left, s - left); next_token[s - left] = '\0'; @@ -104,7 +121,7 @@ realpath(const char *path, char resolved[PATH_MAX]) if (resolved[resolved_len - 1] != '/') { if (resolved_len + 1 >= PATH_MAX) { errno = ENAMETOOLONG; - return (NULL); + goto err; } resolved[resolved_len++] = '/'; resolved[resolved_len] = '\0'; @@ -135,23 +152,23 @@ realpath(const char *path, char resolved[PATH_MAX]) resolved_len = strlcat(resolved, next_token, PATH_MAX); if (resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; - return (NULL); + goto err; } if (lstat(resolved, &sb) != 0) { if (errno == ENOENT && p == NULL) { errno = serrno; return (resolved); } - return (NULL); + goto err; } if (S_ISLNK(sb.st_mode)) { if (symlinks++ > MAXSYMLINKS) { errno = ELOOP; - return (NULL); + goto err; } slen = readlink(resolved, symlink, sizeof(symlink) - 1); if (slen < 0) - return (NULL); + goto err; symlink[slen] = '\0'; if (symlink[0] == '/') { resolved[1] = 0; @@ -174,7 +191,7 @@ realpath(const char *path, char resolved[PATH_MAX]) if (slen + 1 >= (ptrdiff_t)sizeof(symlink)) { errno = ENAMETOOLONG; - return (NULL); + goto err; } symlink[slen] = '/'; symlink[slen + 1] = 0; @@ -182,7 +199,7 @@ realpath(const char *path, char resolved[PATH_MAX]) left_len = strlcat(symlink, left, sizeof(left)); if (left_len >= sizeof(left)) { errno = ENAMETOOLONG; - return (NULL); + goto err; } } left_len = strlcpy(left, symlink, sizeof(left)); @@ -196,5 +213,10 @@ realpath(const char *path, char resolved[PATH_MAX]) if (resolved_len > 1 && resolved[resolved_len - 1] == '/') resolved[resolved_len - 1] = '\0'; return (resolved); + +err: + if (mem_allocated) + free(resolved); + return (NULL); } #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ -- cgit v1.2.3 From 5225db68e58a1048cb17f0e36e0d33bc4a8fc410 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:25:32 +1100 Subject: upstream commit revision 1.15 date: 2012/09/13 15:39:05; author: deraadt; state: Exp; lines: +2 -2; specify the bounds of the dst to strlcat (both values were static and equal, but it is more correct) from Michal Mazurek --- openbsd-compat/realpath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index 6646330ca..f2083e0f6 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.14 2011/07/24 21:03:00 miod Exp $ */ +/* $OpenBSD: realpath.c,v 1.15 2012/09/13 15:39:05 deraadt Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -196,7 +196,7 @@ realpath(const char *path, char *resolved) symlink[slen] = '/'; symlink[slen + 1] = 0; } - left_len = strlcat(symlink, left, sizeof(left)); + left_len = strlcat(symlink, left, sizeof(symlink)); if (left_len >= sizeof(left)) { errno = ENAMETOOLONG; goto err; -- cgit v1.2.3 From e929a43f957dbd1254aca2aaf85c8c00cbfc25f4 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:25:55 +1100 Subject: upstream commit revision 1.16 date: 2013/04/05 12:59:54; author: kurt; state: Exp; lines: +3 -1; - Add comments regarding copies of these files also in libexec/ld.so okay guenther@ --- openbsd-compat/realpath.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index f2083e0f6..a954b1b7a 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.15 2012/09/13 15:39:05 deraadt Exp $ */ +/* $OpenBSD: realpath.c,v 1.16 2013/04/05 12:59:54 kurt Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -43,6 +43,8 @@ #include #include +/* A slightly modified copy of this file exists in libexec/ld.so */ + /* * char *realpath(const char *path, char resolved[PATH_MAX]); * -- cgit v1.2.3 From c39ad23b06e9aecc3ff788e92f787a08472905b1 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:26:24 +1100 Subject: upstream commit revision 1.17 date: 2014/10/18 20:43:52; author: doug; state: Exp; lines: +10 -10; commitid: I74hI1tVZtsspKEt; Better POSIX compliance in realpath(3). millert@ made changes to realpath.c based on FreeBSD's version. I merged Todd's changes into dl_realpath.c. ok millert@, guenther@ --- openbsd-compat/realpath.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index a954b1b7a..d2f34dde0 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.16 2013/04/05 12:59:54 kurt Exp $ */ +/* $OpenBSD: realpath.c,v 1.17 2014/10/18 20:43:52 doug Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -62,6 +62,10 @@ realpath(const char *path, char *resolved) int serrno, slen, mem_allocated; char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; + if (path == NULL) { + errno = EINVAL; + return (NULL); + } if (path[0] == '\0') { errno = ENOENT; return (NULL); @@ -147,22 +151,15 @@ realpath(const char *path, char *resolved) } /* - * Append the next path component and lstat() it. If - * lstat() fails we still can return successfully if - * there are no more path components left. + * Append the next path component and lstat() it. */ resolved_len = strlcat(resolved, next_token, PATH_MAX); if (resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; goto err; } - if (lstat(resolved, &sb) != 0) { - if (errno == ENOENT && p == NULL) { - errno = serrno; - return (resolved); - } + if (lstat(resolved, &sb) != 0) goto err; - } if (S_ISLNK(sb.st_mode)) { if (symlinks++ > MAXSYMLINKS) { errno = ELOOP; @@ -205,6 +202,9 @@ realpath(const char *path, char *resolved) } } left_len = strlcpy(left, symlink, sizeof(left)); + } else if (!S_ISDIR(sb.st_mode) && p != NULL) { + errno = ENOTDIR; + goto err; } } -- cgit v1.2.3 From c71be375a69af00c2d0a0c24d8752bec12d8fd1b Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:27:08 +1100 Subject: upstream commit revision 1.18 date: 2014/10/19 03:56:28; author: doug; state: Exp; lines: +9 -9; commitid: U6QxmtbXrGoc02S5; Revert last commit due to changed semantics found by make release. --- openbsd-compat/realpath.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index d2f34dde0..e4729a808 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.17 2014/10/18 20:43:52 doug Exp $ */ +/* $OpenBSD: realpath.c,v 1.18 2014/10/19 03:56:28 doug Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -62,10 +62,6 @@ realpath(const char *path, char *resolved) int serrno, slen, mem_allocated; char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; - if (path == NULL) { - errno = EINVAL; - return (NULL); - } if (path[0] == '\0') { errno = ENOENT; return (NULL); @@ -151,15 +147,22 @@ realpath(const char *path, char *resolved) } /* - * Append the next path component and lstat() it. + * Append the next path component and lstat() it. If + * lstat() fails we still can return successfully if + * there are no more path components left. */ resolved_len = strlcat(resolved, next_token, PATH_MAX); if (resolved_len >= PATH_MAX) { errno = ENAMETOOLONG; goto err; } - if (lstat(resolved, &sb) != 0) + if (lstat(resolved, &sb) != 0) { + if (errno == ENOENT && p == NULL) { + errno = serrno; + return (resolved); + } goto err; + } if (S_ISLNK(sb.st_mode)) { if (symlinks++ > MAXSYMLINKS) { errno = ELOOP; @@ -202,9 +205,6 @@ realpath(const char *path, char *resolved) } } left_len = strlcpy(left, symlink, sizeof(left)); - } else if (!S_ISDIR(sb.st_mode) && p != NULL) { - errno = ENOTDIR; - goto err; } } -- cgit v1.2.3 From 23fa695bb735f54f04d46123662609edb6c76767 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:27:51 +1100 Subject: upstream commit revision 1.19 date: 2015/01/16 16:48:51; author: deraadt; state: Exp; lines: +3 -3; commitid: 0DYulI8hhujBHMcR; Move to the universe. review by millert, binary checking process with doug, concept with guenther --- openbsd-compat/realpath.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index e4729a808..a6ac09ba5 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.18 2014/10/19 03:56:28 doug Exp $ */ +/* $OpenBSD: realpath.c,v 1.19 2015/01/16 16:48:51 deraadt Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -42,6 +42,7 @@ #include #include #include +#include /* A slightly modified copy of this file exists in libexec/ld.so */ @@ -164,7 +165,7 @@ realpath(const char *path, char *resolved) goto err; } if (S_ISLNK(sb.st_mode)) { - if (symlinks++ > MAXSYMLINKS) { + if (symlinks++ > SYMLOOP_MAX) { errno = ELOOP; goto err; } -- cgit v1.2.3 From 8f22911027ff6c17d7226d232ccd20727f389310 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 Oct 2015 08:28:19 +1100 Subject: upstream commit revision 1.20 date: 2015/10/13 20:55:37; author: millert; state: Exp; lines: +2 -2; commitid: X39sl5ay1czgFIgp; In rev 1.15 the sizeof argument was fixed in a strlcat() call but the truncation check immediately following it was not updated to match. Not an issue in practice since the buffers are the same size. OK deraadt@ --- openbsd-compat/realpath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index a6ac09ba5..a0199ab34 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: realpath.c,v 1.19 2015/01/16 16:48:51 deraadt Exp $ */ +/* $OpenBSD: realpath.c,v 1.20 2015/10/13 20:55:37 millert Exp $ */ /* * Copyright (c) 2003 Constantin S. Svintsoff * @@ -200,7 +200,7 @@ realpath(const char *path, char *resolved) symlink[slen + 1] = 0; } left_len = strlcat(symlink, left, sizeof(symlink)); - if (left_len >= sizeof(left)) { + if (left_len >= sizeof(symlink)) { errno = ENAMETOOLONG; goto err; } -- cgit v1.2.3 From eb6c50d82aa1f0d3fc95f5630ea69761e918bfcd Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 15 Oct 2015 15:48:28 -0700 Subject: fix compilation on systems without SYMLOOP_MAX --- openbsd-compat/realpath.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'openbsd-compat') diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index a0199ab34..a2f090e55 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -44,6 +44,10 @@ #include #include +#ifndef SYMLOOP_MAX +# define SYMLOOP_MAX 32 +#endif + /* A slightly modified copy of this file exists in libexec/ld.so */ /* -- cgit v1.2.3 From 0f754e29dd3760fc0b172c1220f18b753fb0957e Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Oct 2015 10:53:14 +1100 Subject: need va_copy before va_start reported by Nicholas Lemonias --- openbsd-compat/bsd-asprintf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsd-compat') diff --git a/openbsd-compat/bsd-asprintf.c b/openbsd-compat/bsd-asprintf.c index 3368195d4..db57acce9 100644 --- a/openbsd-compat/bsd-asprintf.c +++ b/openbsd-compat/bsd-asprintf.c @@ -47,6 +47,7 @@ vasprintf(char **str, const char *fmt, va_list ap) char *string, *newstr; size_t len; + va_start(ap); VA_COPY(ap2, ap); if ((string = malloc(INIT_SZ)) == NULL) goto fail; -- cgit v1.2.3 From 8db134e7f457bcb069ec72bc4ee722e2af557c69 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Thu, 29 Oct 2015 10:48:23 +1100 Subject: Prevent name collisions with system glob (bz#2463) Move glob.h from includes.h to the only caller (sftp) and override the names for the symbols. This prevents name collisions with the system glob in the case where something other than ssh uses it (eg kerberos). With jjelen at redhat.com, ok djm@ --- defines.h | 7 +++++++ includes.h | 6 ------ openbsd-compat/glob.c | 1 + openbsd-compat/glob.h | 8 ++++++-- openbsd-compat/openbsd-compat.h | 1 - sftp-client.h | 6 ++++++ 6 files changed, 20 insertions(+), 9 deletions(-) (limited to 'openbsd-compat') diff --git a/defines.h b/defines.h index fa0ccba7c..a438ddd74 100644 --- a/defines.h +++ b/defines.h @@ -850,4 +850,11 @@ struct winsize { # endif /* gcc version */ #endif /* __predict_true */ +#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \ + defined(GLOB_HAS_GL_MATCHC) && defined(GLOB_HAS_GL_STATV) && \ + defined(HAVE_DECL_GLOB_NOMATCH) && HAVE_DECL_GLOB_NOMATCH != 0 && \ + !defined(BROKEN_GLOB) +# define USE_SYSTEM_GLOB +#endif + #endif /* _DEFINES_H */ diff --git a/includes.h b/includes.h index 2893a54cd..497a038b2 100644 --- a/includes.h +++ b/includes.h @@ -32,12 +32,6 @@ #ifdef HAVE_BSTRING_H # include #endif -#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \ - defined(GLOB_HAS_GL_MATCHC) && defined(GLOB_HAS_GL_STATV) && \ - defined(HAVE_DECL_GLOB_NOMATCH) && HAVE_DECL_GLOB_NOMATCH != 0 && \ - !defined(BROKEN_GLOB) -# include -#endif #ifdef HAVE_ENDIAN_H # include #endif diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 742b4b954..7c97e67f5 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c @@ -59,6 +59,7 @@ */ #include "includes.h" +#include "glob.h" #include #include diff --git a/openbsd-compat/glob.h b/openbsd-compat/glob.h index f8a7fa5ff..f069a05dc 100644 --- a/openbsd-compat/glob.h +++ b/openbsd-compat/glob.h @@ -42,11 +42,15 @@ !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ defined(BROKEN_GLOB) -#ifndef _GLOB_H_ -#define _GLOB_H_ +#ifndef _COMPAT_GLOB_H_ +#define _COMPAT_GLOB_H_ #include +# define glob_t _ssh_compat_glob_t +# define glob(a, b, c, d) _ssh__compat_glob(a, b, c, d) +# define globfree(a) _ssh__compat_globfree(a) + struct stat; typedef struct { int gl_pathc; /* Count of total paths so far. */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 1ff7114ef..8cc8a11b7 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -39,7 +39,6 @@ /* OpenBSD function replacements */ #include "base64.h" #include "sigact.h" -#include "glob.h" #include "readpassphrase.h" #include "vis.h" #include "getrrsetbyname.h" diff --git a/sftp-client.h b/sftp-client.h index f814b07d6..14a3b8182 100644 --- a/sftp-client.h +++ b/sftp-client.h @@ -21,6 +21,12 @@ #ifndef _SFTP_CLIENT_H #define _SFTP_CLIENT_H +#ifdef USE_SYSTEM_GLOB +# include +#else +# include "openbsd-compat/glob.h" +#endif + typedef struct SFTP_DIRENT SFTP_DIRENT; struct SFTP_DIRENT { -- cgit v1.2.3 From 3ddd15e1b63a4d4f06c8ab16fbdd8a5a61764f16 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Mon, 30 Nov 2015 07:23:53 +1100 Subject: Add a null implementation of pledge. Fixes builds on almost everything. --- configure.ac | 2 +- openbsd-compat/bsd-misc.c | 8 ++++++++ openbsd-compat/bsd-misc.h | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'openbsd-compat') diff --git a/configure.ac b/configure.ac index 1527a13dc..85e984375 100644 --- a/configure.ac +++ b/configure.ac @@ -854,7 +854,6 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1], [syslog_r function is safe to use in in a signal handler]) TEST_MALLOC_OPTIONS="AFGJPRX" - AC_CHECK_FUNCS([pledge]) ;; *-*-solaris*) if test "x$withval" != "xno" ; then @@ -1669,6 +1668,7 @@ AC_CHECK_FUNCS([ \ nsleep \ ogetaddrinfo \ openlog_r \ + pledge \ poll \ prctl \ pstat \ diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c index f7be415ec..2a788e47f 100644 --- a/openbsd-compat/bsd-misc.c +++ b/openbsd-compat/bsd-misc.c @@ -276,3 +276,11 @@ getpgid(pid_t pid) return -1; } #endif + +#ifndef HAVE_PLEDGE +int +pledge(const char *promises, const char *paths[]) +{ + return 0; +} +#endif diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h index ff347a24b..0d81d1735 100644 --- a/openbsd-compat/bsd-misc.h +++ b/openbsd-compat/bsd-misc.h @@ -122,4 +122,8 @@ pid_t getpgid(pid_t); # define krb5_free_error_message(a,b) do { } while(0) #endif +#ifndef HAVE_PLEDGE +int pledge(const char *promises, const char *paths[]); +#endif + #endif /* _BSD_MISC_H */ -- cgit v1.2.3 From 14c887c8393adde2d9fd437d498be30f8c98535c Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 30 Nov 2015 09:45:29 +1100 Subject: stub for pledge(2) for systems that lack it --- openbsd-compat/bsd-pledge.c | 14 ++++++++++++++ openbsd-compat/openbsd-compat.h | 4 ++++ 2 files changed, 18 insertions(+) create mode 100644 openbsd-compat/bsd-pledge.c (limited to 'openbsd-compat') diff --git a/openbsd-compat/bsd-pledge.c b/openbsd-compat/bsd-pledge.c new file mode 100644 index 000000000..afce3c002 --- /dev/null +++ b/openbsd-compat/bsd-pledge.c @@ -0,0 +1,14 @@ +/* Placed in the public domain. */ + +#include "includes.h" + +#ifndef HAVE_PLEDGE + +/* Stub; real implementations wanted. */ +int +pledge(const char *promises, const char *paths[]) +{ + return 0; +} + +#endif /* HAVE_PLEDGE */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 8cc8a11b7..be7b6877e 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -264,6 +264,10 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t, void explicit_bzero(void *p, size_t n); #endif +#ifndef HAVE_PLEDGE +int pledge(const char *promises, const char *paths[]); +#endif /* HAVE_PLEDGE */ + void *xmmap(size_t size); char *xcrypt(const char *password, const char *salt); char *shadow_pw(struct passwd *pw); -- cgit v1.2.3 From f0191d7c8e76e30551084b79341886d9bb38e453 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 30 Nov 2015 10:53:25 +1100 Subject: Revert "stub for pledge(2) for systems that lack it" This reverts commit 14c887c8393adde2d9fd437d498be30f8c98535c. dtucker beat me to it :/ --- openbsd-compat/bsd-pledge.c | 14 -------------- openbsd-compat/openbsd-compat.h | 4 ---- 2 files changed, 18 deletions(-) delete mode 100644 openbsd-compat/bsd-pledge.c (limited to 'openbsd-compat') diff --git a/openbsd-compat/bsd-pledge.c b/openbsd-compat/bsd-pledge.c deleted file mode 100644 index afce3c002..000000000 --- a/openbsd-compat/bsd-pledge.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Placed in the public domain. */ - -#include "includes.h" - -#ifndef HAVE_PLEDGE - -/* Stub; real implementations wanted. */ -int -pledge(const char *promises, const char *paths[]) -{ - return 0; -} - -#endif /* HAVE_PLEDGE */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index be7b6877e..8cc8a11b7 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -264,10 +264,6 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t, void explicit_bzero(void *p, size_t n); #endif -#ifndef HAVE_PLEDGE -int pledge(const char *promises, const char *paths[]); -#endif /* HAVE_PLEDGE */ - void *xmmap(size_t size); char *xcrypt(const char *password, const char *salt); char *shadow_pw(struct passwd *pw); -- cgit v1.2.3 From 4626cbaf78767fc8e9c86dd04785386c59ae0839 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 8 Jan 2016 14:24:56 +1100 Subject: Support Illumos/Solaris fine-grained privileges Includes a pre-auth privsep sandbox and several pledge() emulations. bz#2511, patch by Alex Wilson. ok dtucker@ --- Makefile.in | 6 ++- configure.ac | 38 +++++++++++++- mux.c | 2 + openbsd-compat/port-solaris.c | 114 ++++++++++++++++++++++++++++++++++++++++++ openbsd-compat/port-solaris.h | 3 ++ platform-pledge.c | 71 ++++++++++++++++++++++++++ platform.h | 5 ++ sandbox-solaris.c | 107 +++++++++++++++++++++++++++++++++++++++ sftp-server.c | 3 ++ ssh-agent.c | 1 + uidswap.c | 18 ++++--- 11 files changed, 358 insertions(+), 10 deletions(-) create mode 100644 platform-pledge.c create mode 100644 sandbox-solaris.c (limited to 'openbsd-compat') diff --git a/Makefile.in b/Makefile.in index 15cf69e1f..9e326411c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -91,7 +91,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ - kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o + kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ + platform-pledge.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o mux.o \ @@ -110,7 +111,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ sftp-server.o sftp-common.o \ roaming_common.o roaming_serv.o \ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ - sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o + sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \ + sandbox-solaris.o MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 diff --git a/configure.ac b/configure.ac index b6854320c..0b399ce2c 100644 --- a/configure.ac +++ b/configure.ac @@ -469,6 +469,11 @@ AC_CHECK_HEADERS([sys/un.h], [], [], [ SIA_MSG="no" SPC_MSG="no" SP_MSG="no" +SPP_MSG="no" + +# Support for Solaris/Illumos privileges (this test is used by both +# the --with-solaris-privs option and --with-sandbox=solaris). +SOLARIS_PRIVS="no" # Check for some target-specific stuff case "$host" in @@ -575,6 +580,8 @@ case "$host" in LIBS="$LIBS /usr/lib/textreadmode.o" AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin]) AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()]) + AC_DEFINE([NO_UID_RESTORATION_TEST], [1], + [Define to disable UID restoration test]) AC_DEFINE([DISABLE_SHADOW], [1], [Define if you want to disable shadow passwords]) AC_DEFINE([NO_X11_UNIX_SOCKETS], [1], @@ -889,13 +896,18 @@ mips-sony-bsd|mips-sony-newsos4) else AC_MSG_RESULT([no]) fi + AC_CHECK_FUNC([setppriv], + [ AC_CHECK_HEADERS([priv.h], [ + SOLARIS_PRIVS="yes" + ]) + ]) AC_ARG_WITH([solaris-contracts], [ --with-solaris-contracts Enable Solaris process contracts (experimental)], [ AC_CHECK_LIB([contract], [ct_tmpl_activate], [ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1], [Define if you have Solaris process contracts]) - SSHDLIBS="$SSHDLIBS -lcontract" + LIBS="$LIBS -lcontract" SPC_MSG="yes" ], ) ], ) @@ -905,10 +917,27 @@ mips-sony-bsd|mips-sony-newsos4) AC_CHECK_LIB([project], [setproject], [ AC_DEFINE([USE_SOLARIS_PROJECTS], [1], [Define if you have Solaris projects]) - SSHDLIBS="$SSHDLIBS -lproject" + LIBS="$LIBS -lproject" SP_MSG="yes" ], ) ], ) + AC_ARG_WITH([solaris-privs], + [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)], + [ + AC_MSG_CHECKING([for Solaris/Illumos privilege support]) + if test "x$SOLARIS_PRIVS" = "xyes" ; then + AC_MSG_RESULT([found]) + AC_DEFINE([NO_UID_RESTORATION_TEST], [1], + [Define to disable UID restoration test]) + AC_DEFINE([USE_SOLARIS_PRIVS], [1], + [Define if you have Solaris privileges]) + SPP_MSG="yes" + else + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([*** must have support for Solaris privileges to use --with-solaris-privs]) + fi + ], + ) TEST_SHELL=$SHELL # let configure find us a capable shell ;; *-*-sunos4*) @@ -3156,6 +3185,10 @@ elif test "x$sandbox_arg" = "xrlimit" || \ AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit]) SANDBOX_STYLE="rlimit" AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)]) +elif test "x$sandbox_arg" = "xsolaris" || \ + ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then + SANDBOX_STYLE="solaris" + AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges]) elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then SANDBOX_STYLE="none" @@ -4945,6 +4978,7 @@ echo " MD5 password support: $MD5_MSG" echo " libedit support: $LIBEDIT_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" +echo " Solaris privilege support: $SPP_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" echo " BSD Auth support: $BSD_AUTH_MSG" diff --git a/mux.c b/mux.c index 09704497f..f9c3af651 100644 --- a/mux.c +++ b/mux.c @@ -1891,6 +1891,7 @@ mux_client_request_session(int fd) if (pledge("stdio proc tty", NULL) == -1) fatal("%s pledge(): %s", __func__, strerror(errno)); + platform_pledge_mux(); signal(SIGHUP, control_client_sighandler); signal(SIGINT, control_client_sighandler); @@ -2001,6 +2002,7 @@ mux_client_request_stdio_fwd(int fd) if (pledge("stdio proc tty", NULL) == -1) fatal("%s pledge(): %s", __func__, strerror(errno)); + platform_pledge_mux(); debug3("%s: stdio forward request sent", __func__); diff --git a/openbsd-compat/port-solaris.c b/openbsd-compat/port-solaris.c index 25382f1c9..962cd1685 100644 --- a/openbsd-compat/port-solaris.c +++ b/openbsd-compat/port-solaris.c @@ -227,3 +227,117 @@ solaris_set_default_project(struct passwd *pw) } } #endif /* USE_SOLARIS_PROJECTS */ + +#ifdef USE_SOLARIS_PRIVS +# ifdef HAVE_PRIV_H +# include +# endif + +void +solaris_drop_privs_pinfo_net_fork_exec(void) +{ + priv_set_t *pset = NULL, *npset = NULL; + + /* + * Note: this variant avoids dropping DAC filesystem rights, in case + * the process calling it is running as root and should have the + * ability to read/write/chown any file on the system. + * + * We start with the basic set, then *add* the DAC rights to it while + * taking away other parts of BASIC we don't need. Then we intersect + * this with our existing PERMITTED set. In this way we keep any + * DAC rights we had before, while otherwise reducing ourselves to + * the minimum set of privileges we need to proceed. + * + * This also means we drop any other parts of "root" that we don't + * need (e.g. the ability to kill any process, create new device nodes + * etc etc). + */ + + if ((pset = priv_allocset()) == NULL || + (npset = priv_allocset()) == NULL) + fatal("priv_allocset: %s", strerror(errno)); + + priv_basicset(npset); + + if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 || + priv_addset(npset, PRIV_FILE_DAC_READ) != 0 || + priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 || + priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 || + priv_addset(npset, PRIV_FILE_OWNER) != 0) + fatal("priv_addset: %s", strerror(errno)); + + if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 || + priv_delset(npset, PRIV_NET_ACCESS) != 0 || + priv_delset(npset, PRIV_PROC_EXEC) != 0 || + priv_delset(npset, PRIV_PROC_FORK) != 0 || + priv_delset(npset, PRIV_PROC_INFO) != 0 || + priv_delset(npset, PRIV_PROC_SESSION) != 0) + fatal("priv_delset: %s", strerror(errno)); + + if (getppriv(PRIV_PERMITTED, pset) != 0) + fatal("getppriv: %s", strerror(errno)); + + priv_intersect(pset, npset); + + if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 || + setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0 || + setppriv(PRIV_SET, PRIV_INHERITABLE, npset) != 0) + fatal("setppriv: %s", strerror(errno)); + + priv_freeset(pset); + priv_freeset(npset); +} + +void +solaris_drop_privs_root_pinfo_net(void) +{ + priv_set_t *pset = NULL; + + if ((pset = priv_allocset()) == NULL) + fatal("priv_allocset: %s", strerror(errno)); + + /* Start with "basic" and drop everything we don't need. */ + priv_basicset(pset); + + if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || + priv_delset(pset, PRIV_NET_ACCESS) != 0 || + priv_delset(pset, PRIV_PROC_INFO) != 0 || + priv_delset(pset, PRIV_PROC_SESSION) != 0) + fatal("priv_delset: %s", strerror(errno)); + + if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 || + setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 || + setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) + fatal("setppriv: %s", strerror(errno)); + + priv_freeset(pset); +} + +void +solaris_drop_privs_root_pinfo_net_exec(void) +{ + priv_set_t *pset = NULL; + + if ((pset = priv_allocset()) == NULL) + fatal("priv_allocset: %s", strerror(errno)); + + /* Start with "basic" and drop everything we don't need. */ + priv_basicset(pset); + + if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || + priv_delset(pset, PRIV_NET_ACCESS) != 0 || + priv_delset(pset, PRIV_PROC_EXEC) != 0 || + priv_delset(pset, PRIV_PROC_INFO) != 0 || + priv_delset(pset, PRIV_PROC_SESSION) != 0) + fatal("priv_delset: %s", strerror(errno)); + + if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 || + setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 || + setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) + fatal("setppriv: %s", strerror(errno)); + + priv_freeset(pset); +} + +#endif diff --git a/openbsd-compat/port-solaris.h b/openbsd-compat/port-solaris.h index cd442e78b..b077e186a 100644 --- a/openbsd-compat/port-solaris.h +++ b/openbsd-compat/port-solaris.h @@ -26,5 +26,8 @@ void solaris_contract_pre_fork(void); void solaris_contract_post_fork_child(void); void solaris_contract_post_fork_parent(pid_t pid); void solaris_set_default_project(struct passwd *); +void solaris_drop_privs_pinfo_net_fork_exec(void); +void solaris_drop_privs_root_pinfo_net(void); +void solaris_drop_privs_root_pinfo_net_exec(void); #endif diff --git a/platform-pledge.c b/platform-pledge.c new file mode 100644 index 000000000..4a6ec15e1 --- /dev/null +++ b/platform-pledge.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Joyent, Inc + * Author: Alex Wilson + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include + +#include +#include + +#include "platform.h" + +#include "openbsd-compat/openbsd-compat.h" + +/* + * Drop any fine-grained privileges that are not needed for post-startup + * operation of ssh-agent + * + * Should be as close as possible to pledge("stdio cpath unix id proc exec", ...) + */ +void +platform_pledge_agent(void) +{ +#ifdef USE_SOLARIS_PRIVS + /* + * Note: Solaris priv dropping is closer to tame() than pledge(), but + * we will use what we have. + */ + solaris_drop_privs_root_pinfo_net(); +#endif +} + +/* + * Drop any fine-grained privileges that are not needed for post-startup + * operation of sftp-server + */ +void +platform_pledge_sftp_server(void) +{ +#ifdef USE_SOLARIS_PRIVS + solaris_drop_privs_pinfo_net_fork_exec(); +#endif +} + +/* + * Drop any fine-grained privileges that are not needed for the post-startup + * operation of the SSH client mux + * + * Should be as close as possible to pledge("stdio proc tty", ...) + */ +void +platform_pledge_mux(void) +{ +#ifdef USE_SOLARIS_PRIVS + solaris_drop_privs_root_pinfo_net_exec(); +#endif +} diff --git a/platform.h b/platform.h index 1c7a45d8f..e687c99b6 100644 --- a/platform.h +++ b/platform.h @@ -31,3 +31,8 @@ void platform_setusercontext_post_groups(struct passwd *); char *platform_get_krb5_client(const char *); char *platform_krb5_get_principal_name(const char *); int platform_sys_dir_uid(uid_t); + +/* in platform-pledge.c */ +void platform_pledge_agent(void); +void platform_pledge_sftp_server(void); +void platform_pledge_mux(void); diff --git a/sandbox-solaris.c b/sandbox-solaris.c new file mode 100644 index 000000000..98714e170 --- /dev/null +++ b/sandbox-solaris.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015 Joyent, Inc + * Author: Alex Wilson + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#ifdef SANDBOX_SOLARIS +#ifndef USE_SOLARIS_PRIVS +# error "--with-solaris-privs must be used with the Solaris sandbox" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_PRIV_H +# include +#endif + +#include "log.h" +#include "ssh-sandbox.h" +#include "xmalloc.h" + +struct ssh_sandbox { + priv_set_t *pset; +}; + +struct ssh_sandbox * +ssh_sandbox_init(struct monitor *monitor) +{ + struct ssh_sandbox *box = NULL; + + box = xcalloc(1, sizeof(*box)); + box->pset = priv_allocset(); + + if (box->pset == NULL) { + free(box); + return NULL; + } + + /* Start with "basic" and drop everything we don't need. */ + priv_basicset(box->pset); + + /* Drop everything except the ability to use already-opened files */ + if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 || + priv_delset(box->pset, PRIV_NET_ACCESS) != 0 || + priv_delset(box->pset, PRIV_PROC_EXEC) != 0 || + priv_delset(box->pset, PRIV_PROC_FORK) != 0 || + priv_delset(box->pset, PRIV_PROC_INFO) != 0 || + priv_delset(box->pset, PRIV_PROC_SESSION) != 0) { + free(box); + return NULL; + } + + /* These may not be available on older Solaris-es */ +# if defined(PRIV_FILE_READ) && defined(PRIV_FILE_WRITE) + if (priv_delset(box->pset, PRIV_FILE_READ) != 0 || + priv_delset(box->pset, PRIV_FILE_WRITE) != 0) { + free(box); + return NULL; + } +# endif + + return box; +} + +void +ssh_sandbox_child(struct ssh_sandbox *box) +{ + if (setppriv(PRIV_SET, PRIV_PERMITTED, box->pset) != 0 || + setppriv(PRIV_SET, PRIV_LIMIT, box->pset) != 0 || + setppriv(PRIV_SET, PRIV_INHERITABLE, box->pset) != 0) + fatal("setppriv: %s", strerror(errno)); +} + +void +ssh_sandbox_parent_finish(struct ssh_sandbox *box) +{ + priv_freeset(box->pset); + box->pset = NULL; + free(box); +} + +void +ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) +{ + /* Nothing to do here */ +} + +#endif /* SANDBOX_SOLARIS */ diff --git a/sftp-server.c b/sftp-server.c index 62e76a505..79ef45b10 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1598,6 +1598,9 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) fatal("unable to make the process undumpable"); #endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */ + /* Drop any fine-grained privileges we don't need */ + platform_pledge_sftp_server(); + if ((cp = getenv("SSH_CONNECTION")) != NULL) { client_addr = xstrdup(cp); if ((cp = strchr(client_addr, ' ')) == NULL) { diff --git a/ssh-agent.c b/ssh-agent.c index 2048a11c4..6c50e0f03 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1417,6 +1417,7 @@ skip: if (pledge("stdio cpath unix id proc exec", NULL) == -1) fatal("%s: pledge: %s", __progname, strerror(errno)); + platform_pledge_agent(); while (1) { prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); diff --git a/uidswap.c b/uidswap.c index 0702e1d9e..8bf6b244e 100644 --- a/uidswap.c +++ b/uidswap.c @@ -134,7 +134,7 @@ temporarily_use_uid(struct passwd *pw) void permanently_drop_suid(uid_t uid) { -#ifndef HAVE_CYGWIN +#ifndef NO_UID_RESTORATION_TEST uid_t old_uid = getuid(); #endif @@ -142,8 +142,14 @@ permanently_drop_suid(uid_t uid) if (setresuid(uid, uid, uid) < 0) fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno)); -#ifndef HAVE_CYGWIN - /* Try restoration of UID if changed (test clearing of saved uid) */ +#ifndef NO_UID_RESTORATION_TEST + /* + * Try restoration of UID if changed (test clearing of saved uid). + * + * Note that we don't do this on Cygwin, or on Solaris-based platforms + * where fine-grained privileges are available (the user might be + * deliberately allowed the right to setuid back to root). + */ if (old_uid != uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) fatal("%s: was able to restore old [e]uid", __func__); @@ -199,7 +205,7 @@ restore_uid(void) void permanently_set_uid(struct passwd *pw) { -#ifndef HAVE_CYGWIN +#ifndef NO_UID_RESTORATION_TEST uid_t old_uid = getuid(); gid_t old_gid = getgid(); #endif @@ -227,7 +233,7 @@ permanently_set_uid(struct passwd *pw) if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); -#ifndef HAVE_CYGWIN +#ifndef NO_UID_RESTORATION_TEST /* Try restoration of GID if changed (test clearing of saved gid) */ if (old_gid != pw->pw_gid && pw->pw_uid != 0 && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) @@ -241,7 +247,7 @@ permanently_set_uid(struct passwd *pw) (u_int)pw->pw_gid); } -#ifndef HAVE_CYGWIN +#ifndef NO_UID_RESTORATION_TEST /* Try restoration of UID if changed (test clearing of saved uid) */ if (old_uid != pw->pw_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) -- cgit v1.2.3 From 60d860e54b4f199e5e89963b1c086981309753cb Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Wed, 17 Feb 2016 13:37:09 +1100 Subject: Rollback addition of va_start. va_start was added in 0f754e29dd3760fc0b172c1220f18b753fb0957e, however it has the wrong number of args and it's not usable in non-variadic functions anyway so it breaks things (for example Solaris 2.6 as reported by Tom G. Christensen).i ok djm@ --- openbsd-compat/bsd-asprintf.c | 1 - 1 file changed, 1 deletion(-) (limited to 'openbsd-compat') diff --git a/openbsd-compat/bsd-asprintf.c b/openbsd-compat/bsd-asprintf.c index db57acce9..3368195d4 100644 --- a/openbsd-compat/bsd-asprintf.c +++ b/openbsd-compat/bsd-asprintf.c @@ -47,7 +47,6 @@ vasprintf(char **str, const char *fmt, va_list ap) char *string, *newstr; size_t len; - va_start(ap); VA_COPY(ap2, ap); if ((string = malloc(INIT_SZ)) == NULL) goto fail; -- cgit v1.2.3 From 907091acb188b1057d50c2158f74c3ecf1c2302b Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 19 Feb 2016 09:05:39 +1100 Subject: Make Solaris privs code build on older systems. Not all systems with Solaris privs have priv_basicset so factor that out and provide backward compatibility code. Similarly, not all have PRIV_NET_ACCESS so wrap that in #ifdef. Based on code from alex at cooperi.net and djm@ with help from carson at taltos.org and wieland at purdue.edu. --- configure.ac | 12 ++++++------ openbsd-compat/port-solaris.c | 44 ++++++++++++++++++++++++++++++++----------- openbsd-compat/port-solaris.h | 3 +++ sandbox-solaris.c | 9 +++++---- 4 files changed, 47 insertions(+), 21 deletions(-) (limited to 'openbsd-compat') diff --git a/configure.ac b/configure.ac index b4c0aaab7..e36b04942 100644 --- a/configure.ac +++ b/configure.ac @@ -896,11 +896,9 @@ mips-sony-bsd|mips-sony-newsos4) else AC_MSG_RESULT([no]) fi - AC_CHECK_FUNC([setppriv], - [ AC_CHECK_HEADERS([priv.h], [ - SOLARIS_PRIVS="yes" - ]) - ]) + AC_CHECK_FUNCS([setppriv]) + AC_CHECK_FUNCS([priv_basicset]) + AC_CHECK_HEADERS([priv.h]) AC_ARG_WITH([solaris-contracts], [ --with-solaris-contracts Enable Solaris process contracts (experimental)], [ @@ -925,7 +923,9 @@ mips-sony-bsd|mips-sony-newsos4) [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)], [ AC_MSG_CHECKING([for Solaris/Illumos privilege support]) - if test "x$SOLARIS_PRIVS" = "xyes" ; then + if test "x$ac_cv_func_setppriv" = "xyes" -a \ + "x$ac_cv_header_priv_h" = "xyes" ; then + SOLARIS_PRIVS=yes AC_MSG_RESULT([found]) AC_DEFINE([NO_UID_RESTORATION_TEST], [1], [Define to disable UID restoration test]) diff --git a/openbsd-compat/port-solaris.c b/openbsd-compat/port-solaris.c index 962cd1685..e36e412d7 100644 --- a/openbsd-compat/port-solaris.c +++ b/openbsd-compat/port-solaris.c @@ -233,6 +233,26 @@ solaris_set_default_project(struct passwd *pw) # include # endif +priv_set_t * +solaris_basic_privset(void) +{ + priv_set_t *pset; + +#ifdef HAVE_PRIV_BASICSET + if ((pset = priv_allocset()) == NULL) { + error("priv_allocset: %s", strerror(errno)); + return NULL; + } + priv_basicset(pset); +#else + if ((pset = priv_str_to_set("basic", ",", NULL)) == NULL) { + error("priv_str_to_set: %s", strerror(errno)); + return NULL; + } +#endif + return pset; +} + void solaris_drop_privs_pinfo_net_fork_exec(void) { @@ -254,11 +274,10 @@ solaris_drop_privs_pinfo_net_fork_exec(void) * etc etc). */ - if ((pset = priv_allocset()) == NULL || - (npset = priv_allocset()) == NULL) + if ((pset = priv_allocset()) == NULL) fatal("priv_allocset: %s", strerror(errno)); - - priv_basicset(npset); + if ((npset = solaris_basic_privset()) == NULL) + fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 || priv_addset(npset, PRIV_FILE_DAC_READ) != 0 || @@ -268,7 +287,9 @@ solaris_drop_privs_pinfo_net_fork_exec(void) fatal("priv_addset: %s", strerror(errno)); if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 || +#ifdef PRIV_NET_ACCESS priv_delset(npset, PRIV_NET_ACCESS) != 0 || +#endif priv_delset(npset, PRIV_PROC_EXEC) != 0 || priv_delset(npset, PRIV_PROC_FORK) != 0 || priv_delset(npset, PRIV_PROC_INFO) != 0 || @@ -294,14 +315,14 @@ solaris_drop_privs_root_pinfo_net(void) { priv_set_t *pset = NULL; - if ((pset = priv_allocset()) == NULL) - fatal("priv_allocset: %s", strerror(errno)); - /* Start with "basic" and drop everything we don't need. */ - priv_basicset(pset); + if ((pset = solaris_basic_privset()) == NULL) + fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || +#ifdef PRIV_NET_ACCESS priv_delset(pset, PRIV_NET_ACCESS) != 0 || +#endif priv_delset(pset, PRIV_PROC_INFO) != 0 || priv_delset(pset, PRIV_PROC_SESSION) != 0) fatal("priv_delset: %s", strerror(errno)); @@ -319,14 +340,15 @@ solaris_drop_privs_root_pinfo_net_exec(void) { priv_set_t *pset = NULL; - if ((pset = priv_allocset()) == NULL) - fatal("priv_allocset: %s", strerror(errno)); /* Start with "basic" and drop everything we don't need. */ - priv_basicset(pset); + if ((pset = solaris_basic_privset()) == NULL) + fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || +#ifdef PRIV_NET_ACCESS priv_delset(pset, PRIV_NET_ACCESS) != 0 || +#endif priv_delset(pset, PRIV_PROC_EXEC) != 0 || priv_delset(pset, PRIV_PROC_INFO) != 0 || priv_delset(pset, PRIV_PROC_SESSION) != 0) diff --git a/openbsd-compat/port-solaris.h b/openbsd-compat/port-solaris.h index b077e186a..3a41ea8cd 100644 --- a/openbsd-compat/port-solaris.h +++ b/openbsd-compat/port-solaris.h @@ -26,8 +26,11 @@ void solaris_contract_pre_fork(void); void solaris_contract_post_fork_child(void); void solaris_contract_post_fork_parent(pid_t pid); void solaris_set_default_project(struct passwd *); +# ifdef USE_SOLARIS_PRIVS +priv_set_t *solaris_basic_privset(void); void solaris_drop_privs_pinfo_net_fork_exec(void); void solaris_drop_privs_root_pinfo_net(void); void solaris_drop_privs_root_pinfo_net_exec(void); +# endif /* USE_SOLARIS_PRIVS */ #endif diff --git a/sandbox-solaris.c b/sandbox-solaris.c index 98714e170..343a01022 100644 --- a/sandbox-solaris.c +++ b/sandbox-solaris.c @@ -48,19 +48,20 @@ ssh_sandbox_init(struct monitor *monitor) struct ssh_sandbox *box = NULL; box = xcalloc(1, sizeof(*box)); - box->pset = priv_allocset(); + + /* Start with "basic" and drop everything we don't need. */ + box->pset = solaris_basic_privset(); if (box->pset == NULL) { free(box); return NULL; } - /* Start with "basic" and drop everything we don't need. */ - priv_basicset(box->pset); - /* Drop everything except the ability to use already-opened files */ if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 || +#ifdef PRIV_NET_ACCESS priv_delset(box->pset, PRIV_NET_ACCESS) != 0 || +#endif priv_delset(box->pset, PRIV_PROC_EXEC) != 0 || priv_delset(box->pset, PRIV_PROC_FORK) != 0 || priv_delset(box->pset, PRIV_PROC_INFO) != 0 || -- cgit v1.2.3