summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in6
-rw-r--r--configure.ac38
-rw-r--r--mux.c2
-rw-r--r--openbsd-compat/port-solaris.c114
-rw-r--r--openbsd-compat/port-solaris.h3
-rw-r--r--platform-pledge.c71
-rw-r--r--platform.h5
-rw-r--r--sandbox-solaris.c107
-rw-r--r--sftp-server.c3
-rw-r--r--ssh-agent.c1
-rw-r--r--uidswap.c18
11 files changed, 358 insertions, 10 deletions
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} \
91 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ 91 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
92 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ 92 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
93 kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ 93 kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
94 kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o 94 kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
95 platform-pledge.o
95 96
96SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ 97SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
97 sshconnect.o sshconnect1.o sshconnect2.o mux.o \ 98 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 \
110 sftp-server.o sftp-common.o \ 111 sftp-server.o sftp-common.o \
111 roaming_common.o roaming_serv.o \ 112 roaming_common.o roaming_serv.o \
112 sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ 113 sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
113 sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o 114 sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
115 sandbox-solaris.o
114 116
115MANPAGES = 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 117MANPAGES = 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
116MANPAGES_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 118MANPAGES_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], [], [], [
469SIA_MSG="no" 469SIA_MSG="no"
470SPC_MSG="no" 470SPC_MSG="no"
471SP_MSG="no" 471SP_MSG="no"
472SPP_MSG="no"
473
474# Support for Solaris/Illumos privileges (this test is used by both
475# the --with-solaris-privs option and --with-sandbox=solaris).
476SOLARIS_PRIVS="no"
472 477
473# Check for some target-specific stuff 478# Check for some target-specific stuff
474case "$host" in 479case "$host" in
@@ -575,6 +580,8 @@ case "$host" in
575 LIBS="$LIBS /usr/lib/textreadmode.o" 580 LIBS="$LIBS /usr/lib/textreadmode.o"
576 AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin]) 581 AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin])
577 AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()]) 582 AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()])
583 AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
584 [Define to disable UID restoration test])
578 AC_DEFINE([DISABLE_SHADOW], [1], 585 AC_DEFINE([DISABLE_SHADOW], [1],
579 [Define if you want to disable shadow passwords]) 586 [Define if you want to disable shadow passwords])
580 AC_DEFINE([NO_X11_UNIX_SOCKETS], [1], 587 AC_DEFINE([NO_X11_UNIX_SOCKETS], [1],
@@ -889,13 +896,18 @@ mips-sony-bsd|mips-sony-newsos4)
889 else 896 else
890 AC_MSG_RESULT([no]) 897 AC_MSG_RESULT([no])
891 fi 898 fi
899 AC_CHECK_FUNC([setppriv],
900 [ AC_CHECK_HEADERS([priv.h], [
901 SOLARIS_PRIVS="yes"
902 ])
903 ])
892 AC_ARG_WITH([solaris-contracts], 904 AC_ARG_WITH([solaris-contracts],
893 [ --with-solaris-contracts Enable Solaris process contracts (experimental)], 905 [ --with-solaris-contracts Enable Solaris process contracts (experimental)],
894 [ 906 [
895 AC_CHECK_LIB([contract], [ct_tmpl_activate], 907 AC_CHECK_LIB([contract], [ct_tmpl_activate],
896 [ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1], 908 [ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1],
897 [Define if you have Solaris process contracts]) 909 [Define if you have Solaris process contracts])
898 SSHDLIBS="$SSHDLIBS -lcontract" 910 LIBS="$LIBS -lcontract"
899 SPC_MSG="yes" ], ) 911 SPC_MSG="yes" ], )
900 ], 912 ],
901 ) 913 )
@@ -905,10 +917,27 @@ mips-sony-bsd|mips-sony-newsos4)
905 AC_CHECK_LIB([project], [setproject], 917 AC_CHECK_LIB([project], [setproject],
906 [ AC_DEFINE([USE_SOLARIS_PROJECTS], [1], 918 [ AC_DEFINE([USE_SOLARIS_PROJECTS], [1],
907 [Define if you have Solaris projects]) 919 [Define if you have Solaris projects])
908 SSHDLIBS="$SSHDLIBS -lproject" 920 LIBS="$LIBS -lproject"
909 SP_MSG="yes" ], ) 921 SP_MSG="yes" ], )
910 ], 922 ],
911 ) 923 )
924 AC_ARG_WITH([solaris-privs],
925 [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)],
926 [
927 AC_MSG_CHECKING([for Solaris/Illumos privilege support])
928 if test "x$SOLARIS_PRIVS" = "xyes" ; then
929 AC_MSG_RESULT([found])
930 AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
931 [Define to disable UID restoration test])
932 AC_DEFINE([USE_SOLARIS_PRIVS], [1],
933 [Define if you have Solaris privileges])
934 SPP_MSG="yes"
935 else
936 AC_MSG_RESULT([not found])
937 AC_MSG_ERROR([*** must have support for Solaris privileges to use --with-solaris-privs])
938 fi
939 ],
940 )
912 TEST_SHELL=$SHELL # let configure find us a capable shell 941 TEST_SHELL=$SHELL # let configure find us a capable shell
913 ;; 942 ;;
914*-*-sunos4*) 943*-*-sunos4*)
@@ -3156,6 +3185,10 @@ elif test "x$sandbox_arg" = "xrlimit" || \
3156 AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit]) 3185 AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit])
3157 SANDBOX_STYLE="rlimit" 3186 SANDBOX_STYLE="rlimit"
3158 AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)]) 3187 AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)])
3188elif test "x$sandbox_arg" = "xsolaris" || \
3189 ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then
3190 SANDBOX_STYLE="solaris"
3191 AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges])
3159elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ 3192elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
3160 test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then 3193 test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
3161 SANDBOX_STYLE="none" 3194 SANDBOX_STYLE="none"
@@ -4945,6 +4978,7 @@ echo " MD5 password support: $MD5_MSG"
4945echo " libedit support: $LIBEDIT_MSG" 4978echo " libedit support: $LIBEDIT_MSG"
4946echo " Solaris process contract support: $SPC_MSG" 4979echo " Solaris process contract support: $SPC_MSG"
4947echo " Solaris project support: $SP_MSG" 4980echo " Solaris project support: $SP_MSG"
4981echo " Solaris privilege support: $SPP_MSG"
4948echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" 4982echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
4949echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" 4983echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
4950echo " BSD Auth support: $BSD_AUTH_MSG" 4984echo " 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)
1891 1891
1892 if (pledge("stdio proc tty", NULL) == -1) 1892 if (pledge("stdio proc tty", NULL) == -1)
1893 fatal("%s pledge(): %s", __func__, strerror(errno)); 1893 fatal("%s pledge(): %s", __func__, strerror(errno));
1894 platform_pledge_mux();
1894 1895
1895 signal(SIGHUP, control_client_sighandler); 1896 signal(SIGHUP, control_client_sighandler);
1896 signal(SIGINT, control_client_sighandler); 1897 signal(SIGINT, control_client_sighandler);
@@ -2001,6 +2002,7 @@ mux_client_request_stdio_fwd(int fd)
2001 2002
2002 if (pledge("stdio proc tty", NULL) == -1) 2003 if (pledge("stdio proc tty", NULL) == -1)
2003 fatal("%s pledge(): %s", __func__, strerror(errno)); 2004 fatal("%s pledge(): %s", __func__, strerror(errno));
2005 platform_pledge_mux();
2004 2006
2005 debug3("%s: stdio forward request sent", __func__); 2007 debug3("%s: stdio forward request sent", __func__);
2006 2008
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)
227 } 227 }
228} 228}
229#endif /* USE_SOLARIS_PROJECTS */ 229#endif /* USE_SOLARIS_PROJECTS */
230
231#ifdef USE_SOLARIS_PRIVS
232# ifdef HAVE_PRIV_H
233# include <priv.h>
234# endif
235
236void
237solaris_drop_privs_pinfo_net_fork_exec(void)
238{
239 priv_set_t *pset = NULL, *npset = NULL;
240
241 /*
242 * Note: this variant avoids dropping DAC filesystem rights, in case
243 * the process calling it is running as root and should have the
244 * ability to read/write/chown any file on the system.
245 *
246 * We start with the basic set, then *add* the DAC rights to it while
247 * taking away other parts of BASIC we don't need. Then we intersect
248 * this with our existing PERMITTED set. In this way we keep any
249 * DAC rights we had before, while otherwise reducing ourselves to
250 * the minimum set of privileges we need to proceed.
251 *
252 * This also means we drop any other parts of "root" that we don't
253 * need (e.g. the ability to kill any process, create new device nodes
254 * etc etc).
255 */
256
257 if ((pset = priv_allocset()) == NULL ||
258 (npset = priv_allocset()) == NULL)
259 fatal("priv_allocset: %s", strerror(errno));
260
261 priv_basicset(npset);
262
263 if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 ||
264 priv_addset(npset, PRIV_FILE_DAC_READ) != 0 ||
265 priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 ||
266 priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 ||
267 priv_addset(npset, PRIV_FILE_OWNER) != 0)
268 fatal("priv_addset: %s", strerror(errno));
269
270 if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 ||
271 priv_delset(npset, PRIV_NET_ACCESS) != 0 ||
272 priv_delset(npset, PRIV_PROC_EXEC) != 0 ||
273 priv_delset(npset, PRIV_PROC_FORK) != 0 ||
274 priv_delset(npset, PRIV_PROC_INFO) != 0 ||
275 priv_delset(npset, PRIV_PROC_SESSION) != 0)
276 fatal("priv_delset: %s", strerror(errno));
277
278 if (getppriv(PRIV_PERMITTED, pset) != 0)
279 fatal("getppriv: %s", strerror(errno));
280
281 priv_intersect(pset, npset);
282
283 if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 ||
284 setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0 ||
285 setppriv(PRIV_SET, PRIV_INHERITABLE, npset) != 0)
286 fatal("setppriv: %s", strerror(errno));
287
288 priv_freeset(pset);
289 priv_freeset(npset);
290}
291
292void
293solaris_drop_privs_root_pinfo_net(void)
294{
295 priv_set_t *pset = NULL;
296
297 if ((pset = priv_allocset()) == NULL)
298 fatal("priv_allocset: %s", strerror(errno));
299
300 /* Start with "basic" and drop everything we don't need. */
301 priv_basicset(pset);
302
303 if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
304 priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
305 priv_delset(pset, PRIV_PROC_INFO) != 0 ||
306 priv_delset(pset, PRIV_PROC_SESSION) != 0)
307 fatal("priv_delset: %s", strerror(errno));
308
309 if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 ||
310 setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 ||
311 setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0)
312 fatal("setppriv: %s", strerror(errno));
313
314 priv_freeset(pset);
315}
316
317void
318solaris_drop_privs_root_pinfo_net_exec(void)
319{
320 priv_set_t *pset = NULL;
321
322 if ((pset = priv_allocset()) == NULL)
323 fatal("priv_allocset: %s", strerror(errno));
324
325 /* Start with "basic" and drop everything we don't need. */
326 priv_basicset(pset);
327
328 if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
329 priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
330 priv_delset(pset, PRIV_PROC_EXEC) != 0 ||
331 priv_delset(pset, PRIV_PROC_INFO) != 0 ||
332 priv_delset(pset, PRIV_PROC_SESSION) != 0)
333 fatal("priv_delset: %s", strerror(errno));
334
335 if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 ||
336 setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 ||
337 setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0)
338 fatal("setppriv: %s", strerror(errno));
339
340 priv_freeset(pset);
341}
342
343#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);
26void solaris_contract_post_fork_child(void); 26void solaris_contract_post_fork_child(void);
27void solaris_contract_post_fork_parent(pid_t pid); 27void solaris_contract_post_fork_parent(pid_t pid);
28void solaris_set_default_project(struct passwd *); 28void solaris_set_default_project(struct passwd *);
29void solaris_drop_privs_pinfo_net_fork_exec(void);
30void solaris_drop_privs_root_pinfo_net(void);
31void solaris_drop_privs_root_pinfo_net_exec(void);
29 32
30#endif 33#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 @@
1/*
2 * Copyright (c) 2015 Joyent, Inc
3 * Author: Alex Wilson <alex.wilson@joyent.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "includes.h"
19
20#include <sys/types.h>
21
22#include <stdarg.h>
23#include <unistd.h>
24
25#include "platform.h"
26
27#include "openbsd-compat/openbsd-compat.h"
28
29/*
30 * Drop any fine-grained privileges that are not needed for post-startup
31 * operation of ssh-agent
32 *
33 * Should be as close as possible to pledge("stdio cpath unix id proc exec", ...)
34 */
35void
36platform_pledge_agent(void)
37{
38#ifdef USE_SOLARIS_PRIVS
39 /*
40 * Note: Solaris priv dropping is closer to tame() than pledge(), but
41 * we will use what we have.
42 */
43 solaris_drop_privs_root_pinfo_net();
44#endif
45}
46
47/*
48 * Drop any fine-grained privileges that are not needed for post-startup
49 * operation of sftp-server
50 */
51void
52platform_pledge_sftp_server(void)
53{
54#ifdef USE_SOLARIS_PRIVS
55 solaris_drop_privs_pinfo_net_fork_exec();
56#endif
57}
58
59/*
60 * Drop any fine-grained privileges that are not needed for the post-startup
61 * operation of the SSH client mux
62 *
63 * Should be as close as possible to pledge("stdio proc tty", ...)
64 */
65void
66platform_pledge_mux(void)
67{
68#ifdef USE_SOLARIS_PRIVS
69 solaris_drop_privs_root_pinfo_net_exec();
70#endif
71}
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 *);
31char *platform_get_krb5_client(const char *); 31char *platform_get_krb5_client(const char *);
32char *platform_krb5_get_principal_name(const char *); 32char *platform_krb5_get_principal_name(const char *);
33int platform_sys_dir_uid(uid_t); 33int platform_sys_dir_uid(uid_t);
34
35/* in platform-pledge.c */
36void platform_pledge_agent(void);
37void platform_pledge_sftp_server(void);
38void 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 @@
1/*
2 * Copyright (c) 2015 Joyent, Inc
3 * Author: Alex Wilson <alex.wilson@joyent.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "includes.h"
19
20#ifdef SANDBOX_SOLARIS
21#ifndef USE_SOLARIS_PRIVS
22# error "--with-solaris-privs must be used with the Solaris sandbox"
23#endif
24
25#include <sys/types.h>
26
27#include <errno.h>
28#include <stdarg.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#ifdef HAVE_PRIV_H
34# include <priv.h>
35#endif
36
37#include "log.h"
38#include "ssh-sandbox.h"
39#include "xmalloc.h"
40
41struct ssh_sandbox {
42 priv_set_t *pset;
43};
44
45struct ssh_sandbox *
46ssh_sandbox_init(struct monitor *monitor)
47{
48 struct ssh_sandbox *box = NULL;
49
50 box = xcalloc(1, sizeof(*box));
51 box->pset = priv_allocset();
52
53 if (box->pset == NULL) {
54 free(box);
55 return NULL;
56 }
57
58 /* Start with "basic" and drop everything we don't need. */
59 priv_basicset(box->pset);
60
61 /* Drop everything except the ability to use already-opened files */
62 if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 ||
63 priv_delset(box->pset, PRIV_NET_ACCESS) != 0 ||
64 priv_delset(box->pset, PRIV_PROC_EXEC) != 0 ||
65 priv_delset(box->pset, PRIV_PROC_FORK) != 0 ||
66 priv_delset(box->pset, PRIV_PROC_INFO) != 0 ||
67 priv_delset(box->pset, PRIV_PROC_SESSION) != 0) {
68 free(box);
69 return NULL;
70 }
71
72 /* These may not be available on older Solaris-es */
73# if defined(PRIV_FILE_READ) && defined(PRIV_FILE_WRITE)
74 if (priv_delset(box->pset, PRIV_FILE_READ) != 0 ||
75 priv_delset(box->pset, PRIV_FILE_WRITE) != 0) {
76 free(box);
77 return NULL;
78 }
79# endif
80
81 return box;
82}
83
84void
85ssh_sandbox_child(struct ssh_sandbox *box)
86{
87 if (setppriv(PRIV_SET, PRIV_PERMITTED, box->pset) != 0 ||
88 setppriv(PRIV_SET, PRIV_LIMIT, box->pset) != 0 ||
89 setppriv(PRIV_SET, PRIV_INHERITABLE, box->pset) != 0)
90 fatal("setppriv: %s", strerror(errno));
91}
92
93void
94ssh_sandbox_parent_finish(struct ssh_sandbox *box)
95{
96 priv_freeset(box->pset);
97 box->pset = NULL;
98 free(box);
99}
100
101void
102ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
103{
104 /* Nothing to do here */
105}
106
107#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)
1598 fatal("unable to make the process undumpable"); 1598 fatal("unable to make the process undumpable");
1599#endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */ 1599#endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */
1600 1600
1601 /* Drop any fine-grained privileges we don't need */
1602 platform_pledge_sftp_server();
1603
1601 if ((cp = getenv("SSH_CONNECTION")) != NULL) { 1604 if ((cp = getenv("SSH_CONNECTION")) != NULL) {
1602 client_addr = xstrdup(cp); 1605 client_addr = xstrdup(cp);
1603 if ((cp = strchr(client_addr, ' ')) == NULL) { 1606 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:
1417 1417
1418 if (pledge("stdio cpath unix id proc exec", NULL) == -1) 1418 if (pledge("stdio cpath unix id proc exec", NULL) == -1)
1419 fatal("%s: pledge: %s", __progname, strerror(errno)); 1419 fatal("%s: pledge: %s", __progname, strerror(errno));
1420 platform_pledge_agent();
1420 1421
1421 while (1) { 1422 while (1) {
1422 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); 1423 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)
134void 134void
135permanently_drop_suid(uid_t uid) 135permanently_drop_suid(uid_t uid)
136{ 136{
137#ifndef HAVE_CYGWIN 137#ifndef NO_UID_RESTORATION_TEST
138 uid_t old_uid = getuid(); 138 uid_t old_uid = getuid();
139#endif 139#endif
140 140
@@ -142,8 +142,14 @@ permanently_drop_suid(uid_t uid)
142 if (setresuid(uid, uid, uid) < 0) 142 if (setresuid(uid, uid, uid) < 0)
143 fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno)); 143 fatal("setresuid %u: %.100s", (u_int)uid, strerror(errno));
144 144
145#ifndef HAVE_CYGWIN 145#ifndef NO_UID_RESTORATION_TEST
146 /* Try restoration of UID if changed (test clearing of saved uid) */ 146 /*
147 * Try restoration of UID if changed (test clearing of saved uid).
148 *
149 * Note that we don't do this on Cygwin, or on Solaris-based platforms
150 * where fine-grained privileges are available (the user might be
151 * deliberately allowed the right to setuid back to root).
152 */
147 if (old_uid != uid && 153 if (old_uid != uid &&
148 (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) 154 (setuid(old_uid) != -1 || seteuid(old_uid) != -1))
149 fatal("%s: was able to restore old [e]uid", __func__); 155 fatal("%s: was able to restore old [e]uid", __func__);
@@ -199,7 +205,7 @@ restore_uid(void)
199void 205void
200permanently_set_uid(struct passwd *pw) 206permanently_set_uid(struct passwd *pw)
201{ 207{
202#ifndef HAVE_CYGWIN 208#ifndef NO_UID_RESTORATION_TEST
203 uid_t old_uid = getuid(); 209 uid_t old_uid = getuid();
204 gid_t old_gid = getgid(); 210 gid_t old_gid = getgid();
205#endif 211#endif
@@ -227,7 +233,7 @@ permanently_set_uid(struct passwd *pw)
227 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) 233 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0)
228 fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); 234 fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno));
229 235
230#ifndef HAVE_CYGWIN 236#ifndef NO_UID_RESTORATION_TEST
231 /* Try restoration of GID if changed (test clearing of saved gid) */ 237 /* Try restoration of GID if changed (test clearing of saved gid) */
232 if (old_gid != pw->pw_gid && pw->pw_uid != 0 && 238 if (old_gid != pw->pw_gid && pw->pw_uid != 0 &&
233 (setgid(old_gid) != -1 || setegid(old_gid) != -1)) 239 (setgid(old_gid) != -1 || setegid(old_gid) != -1))
@@ -241,7 +247,7 @@ permanently_set_uid(struct passwd *pw)
241 (u_int)pw->pw_gid); 247 (u_int)pw->pw_gid);
242 } 248 }
243 249
244#ifndef HAVE_CYGWIN 250#ifndef NO_UID_RESTORATION_TEST
245 /* Try restoration of UID if changed (test clearing of saved uid) */ 251 /* Try restoration of UID if changed (test clearing of saved uid) */
246 if (old_uid != pw->pw_uid && 252 if (old_uid != pw->pw_uid &&
247 (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) 253 (setuid(old_uid) != -1 || seteuid(old_uid) != -1))