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.
This commit is contained in:
Darren Tucker 2016-02-19 09:05:39 +11:00
parent 292a8dee14
commit 907091acb1
4 changed files with 47 additions and 21 deletions

View File

@ -896,11 +896,9 @@ mips-sony-bsd|mips-sony-newsos4)
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
AC_CHECK_FUNC([setppriv], AC_CHECK_FUNCS([setppriv])
[ AC_CHECK_HEADERS([priv.h], [ AC_CHECK_FUNCS([priv_basicset])
SOLARIS_PRIVS="yes" AC_CHECK_HEADERS([priv.h])
])
])
AC_ARG_WITH([solaris-contracts], AC_ARG_WITH([solaris-contracts],
[ --with-solaris-contracts Enable Solaris process contracts (experimental)], [ --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)], [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)],
[ [
AC_MSG_CHECKING([for Solaris/Illumos privilege support]) 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_MSG_RESULT([found])
AC_DEFINE([NO_UID_RESTORATION_TEST], [1], AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
[Define to disable UID restoration test]) [Define to disable UID restoration test])

View File

@ -233,6 +233,26 @@ solaris_set_default_project(struct passwd *pw)
# include <priv.h> # include <priv.h>
# endif # 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 void
solaris_drop_privs_pinfo_net_fork_exec(void) solaris_drop_privs_pinfo_net_fork_exec(void)
{ {
@ -254,11 +274,10 @@ solaris_drop_privs_pinfo_net_fork_exec(void)
* etc etc). * etc etc).
*/ */
if ((pset = priv_allocset()) == NULL || if ((pset = priv_allocset()) == NULL)
(npset = priv_allocset()) == NULL)
fatal("priv_allocset: %s", strerror(errno)); fatal("priv_allocset: %s", strerror(errno));
if ((npset = solaris_basic_privset()) == NULL)
priv_basicset(npset); fatal("solaris_basic_privset: %s", strerror(errno));
if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 || if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 ||
priv_addset(npset, PRIV_FILE_DAC_READ) != 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)); fatal("priv_addset: %s", strerror(errno));
if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 || if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 ||
#ifdef PRIV_NET_ACCESS
priv_delset(npset, PRIV_NET_ACCESS) != 0 || priv_delset(npset, PRIV_NET_ACCESS) != 0 ||
#endif
priv_delset(npset, PRIV_PROC_EXEC) != 0 || priv_delset(npset, PRIV_PROC_EXEC) != 0 ||
priv_delset(npset, PRIV_PROC_FORK) != 0 || priv_delset(npset, PRIV_PROC_FORK) != 0 ||
priv_delset(npset, PRIV_PROC_INFO) != 0 || priv_delset(npset, PRIV_PROC_INFO) != 0 ||
@ -294,14 +315,14 @@ solaris_drop_privs_root_pinfo_net(void)
{ {
priv_set_t *pset = NULL; 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. */ /* 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 || if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
#ifdef PRIV_NET_ACCESS
priv_delset(pset, PRIV_NET_ACCESS) != 0 || priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
#endif
priv_delset(pset, PRIV_PROC_INFO) != 0 || priv_delset(pset, PRIV_PROC_INFO) != 0 ||
priv_delset(pset, PRIV_PROC_SESSION) != 0) priv_delset(pset, PRIV_PROC_SESSION) != 0)
fatal("priv_delset: %s", strerror(errno)); fatal("priv_delset: %s", strerror(errno));
@ -319,14 +340,15 @@ solaris_drop_privs_root_pinfo_net_exec(void)
{ {
priv_set_t *pset = NULL; 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. */ /* 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 || if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 ||
#ifdef PRIV_NET_ACCESS
priv_delset(pset, PRIV_NET_ACCESS) != 0 || priv_delset(pset, PRIV_NET_ACCESS) != 0 ||
#endif
priv_delset(pset, PRIV_PROC_EXEC) != 0 || priv_delset(pset, PRIV_PROC_EXEC) != 0 ||
priv_delset(pset, PRIV_PROC_INFO) != 0 || priv_delset(pset, PRIV_PROC_INFO) != 0 ||
priv_delset(pset, PRIV_PROC_SESSION) != 0) priv_delset(pset, PRIV_PROC_SESSION) != 0)

View File

@ -26,8 +26,11 @@ void solaris_contract_pre_fork(void);
void solaris_contract_post_fork_child(void); void solaris_contract_post_fork_child(void);
void solaris_contract_post_fork_parent(pid_t pid); void solaris_contract_post_fork_parent(pid_t pid);
void solaris_set_default_project(struct passwd *); 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_pinfo_net_fork_exec(void);
void solaris_drop_privs_root_pinfo_net(void); void solaris_drop_privs_root_pinfo_net(void);
void solaris_drop_privs_root_pinfo_net_exec(void); void solaris_drop_privs_root_pinfo_net_exec(void);
# endif /* USE_SOLARIS_PRIVS */
#endif #endif

View File

@ -48,19 +48,20 @@ ssh_sandbox_init(struct monitor *monitor)
struct ssh_sandbox *box = NULL; struct ssh_sandbox *box = NULL;
box = xcalloc(1, sizeof(*box)); 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) { if (box->pset == NULL) {
free(box); free(box);
return NULL; 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 */ /* Drop everything except the ability to use already-opened files */
if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 || if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 ||
#ifdef PRIV_NET_ACCESS
priv_delset(box->pset, PRIV_NET_ACCESS) != 0 || priv_delset(box->pset, PRIV_NET_ACCESS) != 0 ||
#endif
priv_delset(box->pset, PRIV_PROC_EXEC) != 0 || priv_delset(box->pset, PRIV_PROC_EXEC) != 0 ||
priv_delset(box->pset, PRIV_PROC_FORK) != 0 || priv_delset(box->pset, PRIV_PROC_FORK) != 0 ||
priv_delset(box->pset, PRIV_PROC_INFO) != 0 || priv_delset(box->pset, PRIV_PROC_INFO) != 0 ||