From c501d73c7e2d5c843583084b84bd3e6f68a0047e Mon Sep 17 00:00:00 2001 From: Mariusz Zaborski Date: Thu, 25 Feb 2016 18:23:40 +0000 Subject: [PATCH] Convert casperd(8) daemon to the libcasper. After calling the cap_init(3) function Casper will fork from it's original process, using pdfork(2). Forking from a process has a lot of advantages: 1. We have the same cwd as the original process. 2. The same uid, gid and groups. 3. The same MAC labels. 4. The same descriptor table. 5. The same routing table. 6. The same umask. 7. The same cpuset(1). From now services are also in form of libraries. We also removed libcapsicum at all and converts existing program using Casper to new architecture. Discussed with: pjd, jonathan, ed, drysdale@google.com, emaste Partially reviewed by: drysdale@google.com, bdrewery Approved by: pjd (mentor) Differential Revision: https://reviews.freebsd.org/D4277 --- Makefile.inc1 | 8 +- ObsoleteFiles.inc | 19 + contrib/mdocml/lib.in | 2 +- contrib/tcpdump/addrtoname.c | 14 +- contrib/tcpdump/config.h.in | 2 +- contrib/tcpdump/configure | 2 +- contrib/tcpdump/configure.in | 2 +- contrib/tcpdump/tcpdump.c | 63 +- etc/defaults/rc.conf | 1 - etc/mtree/BSD.debug.dist | 2 - etc/mtree/BSD.include.dist | 2 + etc/mtree/BSD.root.dist | 4 +- etc/rc.d/Makefile | 5 - etc/rc.d/casperd | 19 - gnu/usr.bin/groff/tmac/mdoc.local.in | 2 +- lib/Makefile | 5 +- lib/libc/posix1e/posix1e.3 | 4 +- lib/libcapsicum/Makefile | 46 -- lib/libcapsicum/Makefile.depend | 19 - lib/libcapsicum/libcapsicum_dns.c | 365 --------- lib/libcapsicum/libcapsicum_impl.h | 39 - lib/libcapsicum/libcapsicum_pwd.c | 391 ---------- lib/libcapsicum/libcapsicum_service.c | 97 --- lib/libcapsicum/libcapsicum_sysctl.c | 86 --- lib/libcasper/Makefile | 19 +- lib/libcasper/libcasper.h | 70 -- lib/libcasper/libcasper/Makefile | 38 + .../libcasper/libcasper.3} | 43 +- .../libcasper/libcasper.c} | 127 ++- .../libcasper/libcasper.h} | 28 +- .../libcasper/libcasper_impl.c} | 16 +- lib/libcasper/libcasper/libcasper_impl.h | 82 ++ lib/libcasper/libcasper/libcasper_service.c | 277 +++++++ .../libcasper_service.h} | 32 +- .../{libcasper.c => libcasper/service.c} | 135 ++-- .../libcasper/libcasper}/zygote.c | 10 +- .../libcasper/libcasper}/zygote.h | 5 +- lib/libcasper/services/Makefile | 9 + lib/libcasper/services/cap_dns/Makefile | 20 + .../libcasper/services/cap_dns/cap_dns.c | 359 ++++++++- .../services/cap_dns/cap_dns.h} | 6 +- lib/libcasper/services/cap_grp/Makefile | 20 + .../services/cap_grp/cap_grp.c} | 355 ++++++++- .../services/cap_grp/cap_grp.h} | 6 +- lib/libcasper/services/cap_pwd/Makefile | 20 + .../libcasper/services/cap_pwd/cap_pwd.c | 383 +++++++++- .../services/cap_pwd/cap_pwd.h} | 6 +- lib/libcasper/services/cap_random/Makefile | 20 + .../services/cap_random/cap_random.c} | 41 +- .../services/cap_random/cap_random.h} | 6 +- lib/libcasper/services/cap_sysctl/Makefile | 20 + .../services/cap_sysctl/cap_sysctl.c | 72 +- .../services/cap_sysctl/cap_sysctl.h} | 6 +- libexec/Makefile | 5 - libexec/casper/Makefile | 11 - libexec/casper/dns/Makefile | 21 - libexec/casper/grp/Makefile | 21 - libexec/casper/grp/grp.c | 390 ---------- libexec/casper/pwd/Makefile | 21 - libexec/casper/random/Makefile | 21 - libexec/casper/random/random.c | 82 -- libexec/casper/sysctl/Makefile | 21 - libexec/rtld-elf/paths.h | 2 +- sbin/Makefile | 1 - sbin/casperd/Makefile | 17 - sbin/casperd/casperd.8 | 132 ---- sbin/casperd/casperd.c | 721 ------------------ sbin/ping/Makefile | 5 +- sbin/ping/Makefile.depend | 3 +- sbin/ping/ping.c | 34 +- share/man/man4/capsicum.4 | 5 +- share/mk/bsd.libnames.mk | 1 - share/mk/src.libnames.mk | 33 +- targets/pseudo/userland/Makefile.depend | 4 - targets/pseudo/userland/lib/Makefile.depend | 12 +- .../pseudo/userland/libexec/Makefile.depend | 5 - .../{libcapsicum => libcasper}/Makefile | 3 +- .../capsicum/{libcapsicum => libcasper}/dns.c | 6 +- .../capsicum/{libcapsicum => libcasper}/grp.c | 6 +- .../capsicum/{libcapsicum => libcasper}/pwd.c | 6 +- .../{libcapsicum => libcasper}/sysctl.c | 6 +- usr.bin/kdump/Makefile | 6 +- usr.bin/kdump/kdump.c | 31 +- usr.sbin/tcpdump/tcpdump/Makefile | 5 +- usr.sbin/tcpdump/tcpdump/config.h | 2 +- 85 files changed, 2072 insertions(+), 2997 deletions(-) delete mode 100644 etc/rc.d/casperd delete mode 100644 lib/libcapsicum/Makefile delete mode 100644 lib/libcapsicum/Makefile.depend delete mode 100644 lib/libcapsicum/libcapsicum_dns.c delete mode 100644 lib/libcapsicum/libcapsicum_impl.h delete mode 100644 lib/libcapsicum/libcapsicum_pwd.c delete mode 100644 lib/libcapsicum/libcapsicum_service.c delete mode 100644 lib/libcapsicum/libcapsicum_sysctl.c delete mode 100644 lib/libcasper/libcasper.h create mode 100644 lib/libcasper/libcasper/Makefile rename lib/{libcapsicum/libcapsicum.3 => libcasper/libcasper/libcasper.3} (91%) rename lib/{libcapsicum/libcapsicum.c => libcasper/libcasper/libcasper.c} (72%) rename lib/{libcapsicum/libcapsicum.h => libcasper/libcasper/libcasper.h} (87%) rename lib/{libcapsicum/libcapsicum_service.h => libcasper/libcasper/libcasper_impl.c} (84%) create mode 100644 lib/libcasper/libcasper/libcasper_impl.h create mode 100644 lib/libcasper/libcasper/libcasper_service.c rename lib/libcasper/{libcasper_impl.h => libcasper/libcasper_service.h} (67%) rename lib/libcasper/{libcasper.c => libcasper/service.c} (74%) rename {sbin/casperd => lib/libcasper/libcasper}/zygote.c (97%) rename {sbin/casperd => lib/libcasper/libcasper}/zygote.h (91%) create mode 100644 lib/libcasper/services/Makefile create mode 100644 lib/libcasper/services/cap_dns/Makefile rename libexec/casper/dns/dns.c => lib/libcasper/services/cap_dns/cap_dns.c (54%) rename lib/{libcapsicum/libcapsicum_dns.h => libcasper/services/cap_dns/cap_dns.h} (96%) create mode 100644 lib/libcasper/services/cap_grp/Makefile rename lib/{libcapsicum/libcapsicum_grp.c => libcasper/services/cap_grp/cap_grp.c} (57%) rename lib/{libcapsicum/libcapsicum_grp.h => libcasper/services/cap_grp/cap_grp.h} (96%) create mode 100644 lib/libcasper/services/cap_pwd/Makefile rename libexec/casper/pwd/pwd.c => lib/libcasper/services/cap_pwd/cap_pwd.c (54%) rename lib/{libcapsicum/libcapsicum_pwd.h => libcasper/services/cap_pwd/cap_pwd.h} (96%) create mode 100644 lib/libcasper/services/cap_random/Makefile rename lib/{libcapsicum/libcapsicum_random.c => libcasper/services/cap_random/cap_random.c} (76%) rename lib/{libcapsicum/libcapsicum_random.h => libcasper/services/cap_random/cap_random.h} (94%) create mode 100644 lib/libcasper/services/cap_sysctl/Makefile rename libexec/casper/sysctl/sysctl.c => lib/libcasper/services/cap_sysctl/cap_sysctl.c (80%) rename lib/{libcapsicum/libcapsicum_sysctl.h => libcasper/services/cap_sysctl/cap_sysctl.h} (94%) delete mode 100644 libexec/casper/Makefile delete mode 100644 libexec/casper/dns/Makefile delete mode 100644 libexec/casper/grp/Makefile delete mode 100644 libexec/casper/grp/grp.c delete mode 100644 libexec/casper/pwd/Makefile delete mode 100644 libexec/casper/random/Makefile delete mode 100644 libexec/casper/random/random.c delete mode 100644 libexec/casper/sysctl/Makefile delete mode 100644 sbin/casperd/Makefile delete mode 100644 sbin/casperd/casperd.8 delete mode 100644 sbin/casperd/casperd.c rename tools/regression/capsicum/{libcapsicum => libcasper}/Makefile (87%) rename tools/regression/capsicum/{libcapsicum => libcasper}/dns.c (99%) rename tools/regression/capsicum/{libcapsicum => libcasper}/grp.c (99%) rename tools/regression/capsicum/{libcapsicum => libcasper}/pwd.c (99%) rename tools/regression/capsicum/{libcapsicum => libcasper}/sysctl.c (99%) diff --git a/Makefile.inc1 b/Makefile.inc1 index ed0415b157c7..5bd9cfa54b0c 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -585,7 +585,7 @@ _worldtmp: .PHONY rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/kdump_subr.c .endif .for _dir in \ - lib usr legacy/bin legacy/usr + lib lib/casper usr legacy/bin legacy/usr mkdir -p ${WORLDTMP}/${_dir} .endfor mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \ @@ -1870,7 +1870,7 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \ lib/libfigpar \ ${_lib_libgssapi} \ lib/libkiconv lib/libkvm lib/liblzma lib/libmd lib/libnv \ - ${_lib_libcapsicum} \ + ${_lib_casper} \ lib/ncurses/ncurses lib/ncurses/ncursesw \ lib/libopie lib/libpam ${_lib_libthr} \ ${_lib_libradius} lib/libsbuf lib/libtacplus \ @@ -1910,11 +1910,11 @@ _ofed_lib= contrib/ofed/usr.lib/ .endif .if ${MK_CASPER} != "no" -_lib_libcapsicum=lib/libcapsicum +_lib_casper= lib/libcasper .endif -lib/libcapsicum__L: lib/libnv__L lib/libpjdlog__L: lib/libutil__L +lib/libcasper__L: lib/libnv__L lib/liblzma__L: lib/libthr__L _generic_libs= ${_cddl_lib} gnu/lib ${_kerberos5_lib} lib ${_secure_lib} usr.bin/lex/lib ${_ofed_lib} diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index f49544ea1a5a..d321abbf7fe0 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,25 @@ # xargs -n1 | sort | uniq -d; # done +# 20160225: Remove casperd and libcapsicum. +OLD_FILES+=sbin/casperd +OLD_FILES+=etc/rc.d/casperd +OLD_FILES+=usr/share/man/man8/casperd.8.gz +OLD_FILES+=usr/include/libcapsicum.h +OLD_FILES+=usr/include/libcapsicum_service.h +OLD_FILES+=usr/include/libcapsicum.h +OLD_FILES+=usr/share/man/man3/libcapsicum.3.gz +OLD_FILES+=usr/include/libcapsicum_dns.h +OLD_FILES+=usr/include/libcapsicum_grp.h +OLD_FILES+=usr/include/libcapsicum_impl.h +OLD_FILES+=usr/include/libcapsicum_pwd.h +OLD_FILES+=usr/include/libcapsicum_random.h +OLD_FILES+=usr/include/libcapsicum_sysctl.h +OLD_FILES+=libexec/casper/dns +OLD_FILES+=libexec/casper/grp +OLD_FILES+=libexec/casper/pwd +OLD_FILES+=libexec/casper/random +OLD_FILES+=libexec/casper/sysctl # 20160223: functionality from mkulzma(1) merged into mkuzip(1) OLD_FILES+=usr/bin/mkulzma # 20160211: Remove obsolete unbound-control-setup diff --git a/contrib/mdocml/lib.in b/contrib/mdocml/lib.in index ca04e94845c2..dec561af672a 100644 --- a/contrib/mdocml/lib.in +++ b/contrib/mdocml/lib.in @@ -34,7 +34,7 @@ LINE("libc", "Standard C\\~Library (libc, \\-lc)") LINE("libc_r", "Reentrant C\\~Library (libc_r, \\-lc_r)") LINE("libcalendar", "Calendar Arithmetic Library (libcalendar, \\-lcalendar)") LINE("libcam", "Common Access Method User Library (libcam, \\-lcam)") -LINE("libcapsicum", "Capsicum Library (libcapsicum, \\-lcapsicum)") +LINE("libcasper", "Casper Library (libcasper, \\-lcapser)") LINE("libcdk", "Curses Development Kit Library (libcdk, \\-lcdk)") LINE("libcipher", "FreeSec Crypt Library (libcipher, \\-lcipher)") LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)") diff --git a/contrib/tcpdump/addrtoname.c b/contrib/tcpdump/addrtoname.c index b02d0f78e120..e22460654dea 100644 --- a/contrib/tcpdump/addrtoname.c +++ b/contrib/tcpdump/addrtoname.c @@ -29,10 +29,10 @@ #include "config.h" #endif -#ifdef HAVE_CAPSICUM -#include -#include -#endif /* HAVE_CAPSICUM */ +#ifdef HAVE_CAPSPER +#include +#include +#endif /* HAVE_CAPSPER */ #include #ifdef USE_ETHER_NTOHOST @@ -204,7 +204,7 @@ intoa(uint32_t addr) static uint32_t f_netmask; static uint32_t f_localnet; -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER extern cap_channel_t *capdns; #endif @@ -252,7 +252,7 @@ getname(netdissect_options *ndo, const u_char *ap) */ if (!ndo->ndo_nflag && (addr & f_netmask) == f_localnet) { -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER if (capdns != NULL) { hp = cap_gethostbyaddr(capdns, (char *)&addr, 4, AF_INET); @@ -309,7 +309,7 @@ getname6(netdissect_options *ndo, const u_char *ap) * Do not print names if -n was given. */ if (!ndo->ndo_nflag) { -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER if (capdns != NULL) { hp = cap_gethostbyaddr(capdns, (char *)&addr, sizeof(addr), AF_INET6); diff --git a/contrib/tcpdump/config.h.in b/contrib/tcpdump/config.h.in index 914289a8f9fc..f233245fb574 100644 --- a/contrib/tcpdump/config.h.in +++ b/contrib/tcpdump/config.h.in @@ -10,7 +10,7 @@ #undef HAVE_BPF_DUMP /* capsicum support available */ -#undef HAVE_CAPSICUM +#undef HAVE_CAPSPER /* Define to 1 if you have the `cap_enter' function. */ #undef HAVE_CAP_ENTER diff --git a/contrib/tcpdump/configure b/contrib/tcpdump/configure index 43b3068aab43..390af318a3b7 100755 --- a/contrib/tcpdump/configure +++ b/contrib/tcpdump/configure @@ -4566,7 +4566,7 @@ fi $as_echo_n "checking whether to sandbox using capsicum... " >&6; } if test "x$ac_lbl_capsicum_function_seen" = "xyes" -a "x$ac_lbl_capsicum_function_not_seen" != "xyes"; then -$as_echo "#define HAVE_CAPSICUM 1" >>confdefs.h +$as_echo "#define HAVE_CAPSPER 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } diff --git a/contrib/tcpdump/configure.in b/contrib/tcpdump/configure.in index a629559ed1cb..b5ac48f35f2d 100644 --- a/contrib/tcpdump/configure.in +++ b/contrib/tcpdump/configure.in @@ -222,7 +222,7 @@ if test ! -z "$with_sandbox-capsicum" && test "$with_sandbox-capsicum" != "no" ; fi AC_MSG_CHECKING([whether to sandbox using capsicum]) if test "x$ac_lbl_capsicum_function_seen" = "xyes" -a "x$ac_lbl_capsicum_function_not_seen" != "xyes"; then - AC_DEFINE(HAVE_CAPSICUM, 1, [capsicum support available]) + AC_DEFINE(HAVE_CASPER, 1, [casper support available]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c index ed3ce5efb0e4..bc0c5ee86c55 100644 --- a/contrib/tcpdump/tcpdump.c +++ b/contrib/tcpdump/tcpdump.c @@ -87,17 +87,16 @@ extern int SIZE_BUF; #include #include #endif /* __FreeBSD__ */ -#ifdef HAVE_CAPSICUM -#include -#include -#include +#ifdef HAVE_CAPSPER +#include +#include #include #include #include #include #include #include -#endif /* HAVE_CAPSICUM */ +#endif /* HAVE_CAPSPER */ #include #include #include @@ -161,7 +160,7 @@ static int infoprint; char *program_name; -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER cap_channel_t *capdns; #endif @@ -485,7 +484,7 @@ struct dump_info { char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER int dirfd; #endif }; @@ -909,7 +908,7 @@ get_next_file(FILE *VFile, char *ptr) return ret; } -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER static cap_channel_t * capdns_setup(void) { @@ -918,10 +917,8 @@ capdns_setup(void) int families[2]; capcas = cap_init(); - if (capcas == NULL) { - warning("unable to contact casperd"); - return (NULL); - } + if (capcas == NULL) + error("unable to create casper process"); capdnsloc = cap_service_open(capcas, "system.dns"); /* Casper capability no longer needed. */ cap_close(capcas); @@ -938,7 +935,7 @@ capdns_setup(void) return (capdnsloc); } -#endif /* HAVE_CAPSICUM */ +#endif /* HAVE_CAPSPER */ #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION static int @@ -970,7 +967,7 @@ tstamp_precision_to_string(int precision) } #endif -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER /* * Ensure that, on a dump file's descriptor, we have all the rights * necessary to make the standard I/O library work with an fdopen()ed @@ -1070,9 +1067,9 @@ main(int argc, char **argv) #endif int status; FILE *VFile; -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER cap_rights_t rights; -#endif /* HAVE_CAPSICUM */ +#endif /* HAVE_CAPSPER */ int cansandbox; #ifdef WIN32 @@ -1613,7 +1610,7 @@ main(int argc, char **argv) if (pd == NULL) error("%s", ebuf); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER cap_rights_init(&rights, CAP_READ); if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && errno != ENOSYS) { @@ -1850,10 +1847,10 @@ main(int argc, char **argv) exit(0); } -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER if (!nflag) capdns = capdns_setup(); -#endif /* HAVE_CAPSICUM */ +#endif /* HAVE_CAPSPER */ init_addrtoname(gndo, localnet, netmask); init_checksum(); @@ -1921,7 +1918,7 @@ main(int argc, char **argv) if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER if (RFileName == NULL && VFileName == NULL) { static const unsigned long cmds[] = { BIOCGSTATS }; @@ -1971,11 +1968,11 @@ main(int argc, char **argv) #endif /* HAVE_LIBCAP_NG */ if (p == NULL) error("%s", pcap_geterr(pd)); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER set_dumper_capsicum_rights(p); #endif if (Cflag != 0 || Gflag != 0) { -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER dumpinfo.WFileName = strdup(basename(WFileName)); dumpinfo.dirfd = open(dirname(WFileName), O_DIRECTORY | O_RDONLY); @@ -1993,7 +1990,7 @@ main(int argc, char **argv) errno != ENOSYS) { error("unable to limit dump descriptor fcntls"); } -#else /* !HAVE_CAPSICUM */ +#else /* !HAVE_CAPSPER */ dumpinfo.WFileName = WFileName; #endif callback = dump_packet_and_trunc; @@ -2069,7 +2066,7 @@ main(int argc, char **argv) #ifdef __FreeBSD__ cansandbox = (VFileName == NULL && zflag == NULL); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER cansandbox = (cansandbox && (nflag || capdns != NULL)); #else cansandbox = (cansandbox && nflag); @@ -2125,7 +2122,7 @@ main(int argc, char **argv) pd = pcap_open_offline(RFileName, ebuf); if (pd == NULL) error("%s", ebuf); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER cap_rights_init(&rights, CAP_READ); if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && errno != ENOSYS) { @@ -2328,7 +2325,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s /* If the time is greater than the specified window, rotate */ if (t - Gflag_time >= Gflag) { -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER FILE *fp; int fd; #endif @@ -2386,7 +2383,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER fd = openat(dump_info->dirfd, dump_info->CurrentFileName, O_CREAT | O_WRONLY | O_TRUNC, 0644); @@ -2400,7 +2397,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s dump_info->CurrentFileName); } dump_info->p = pcap_dump_fopen(dump_info->pd, fp); -#else /* !HAVE_CAPSICUM */ +#else /* !HAVE_CAPSPER */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif #ifdef HAVE_LIBCAP_NG @@ -2409,7 +2406,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s #endif /* HAVE_LIBCAP_NG */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER set_dumper_capsicum_rights(dump_info->p); #endif } @@ -2426,7 +2423,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s if (size == -1) error("ftell fails on output file"); if (size > Cflag) { -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER FILE *fp; int fd; #endif @@ -2458,7 +2455,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER fd = openat(dump_info->dirfd, dump_info->CurrentFileName, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd < 0) { @@ -2471,7 +2468,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s dump_info->CurrentFileName); } dump_info->p = pcap_dump_fopen(dump_info->pd, fp); -#else /* !HAVE_CAPSICUM */ +#else /* !HAVE_CAPSPER */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif #ifdef HAVE_LIBCAP_NG @@ -2480,7 +2477,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s #endif /* HAVE_LIBCAP_NG */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); -#ifdef HAVE_CAPSICUM +#ifdef HAVE_CAPSPER set_dumper_capsicum_rights(dump_info->p); #endif } diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 12bf3f218376..32bac4dfa35e 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -681,7 +681,6 @@ newsyslog_enable="YES" # Run newsyslog at startup. newsyslog_flags="-CN" # Newsyslog flags to create marked files mixer_enable="YES" # Run the sound mixer. opensm_enable="NO" # Opensm(8) for infiniband devices defaults to off -casperd_enable="YES" # casperd(8) daemon # rctl(8) requires kernel options RACCT and RCTL rctl_enable="YES" # Load rctl(8) rules on boot diff --git a/etc/mtree/BSD.debug.dist b/etc/mtree/BSD.debug.dist index 4a499ea2ab4d..2f0aae92294b 100644 --- a/etc/mtree/BSD.debug.dist +++ b/etc/mtree/BSD.debug.dist @@ -15,8 +15,6 @@ lib geom .. - .. - libexec casper .. .. diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 88e80e66a479..a9baa7eee814 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -93,6 +93,8 @@ scsi .. .. + casper + .. crypto .. dev diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index af2f6a9add09..1c1a1ddad177 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -80,12 +80,12 @@ .. .. lib + casper + .. geom .. .. libexec - casper - .. resolvconf .. .. diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 1e6e28ffbaa6..6cc860bff108 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -21,7 +21,6 @@ FILES= DAEMON \ ${_bluetooth} \ bridge \ ${_bthidd} \ - ${_casperd} \ cleanvar \ cleartmp \ cron \ @@ -176,10 +175,6 @@ FILES+= bootparams FILES+= bsnmpd .endif -.if ${MK_CASPER} != "no" -_casperd= casperd -.endif - .if ${MK_CCD} != "no" FILES+= ccd .endif diff --git a/etc/rc.d/casperd b/etc/rc.d/casperd deleted file mode 100644 index 0b80169a0262..000000000000 --- a/etc/rc.d/casperd +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# PROVIDE: casperd -# REQUIRE: NETWORKING syslogd -# BEFORE: DAEMON -# KEYWORD: shutdown - -. /etc/rc.subr - -name="casperd" -rcvar="casperd_enable" -pidfile="/var/run/${name}.pid" -command="/sbin/${name}" - -load_rc_config $name -run_rc_command "$1" diff --git a/gnu/usr.bin/groff/tmac/mdoc.local.in b/gnu/usr.bin/groff/tmac/mdoc.local.in index e7ec4cf4ad78..046b16b249c7 100644 --- a/gnu/usr.bin/groff/tmac/mdoc.local.in +++ b/gnu/usr.bin/groff/tmac/mdoc.local.in @@ -34,7 +34,7 @@ .\" FreeBSD .Lb values .ds doc-str-Lb-libarchive Streaming Archive Library (libarchive, \-larchive) .ds doc-str-Lb-libbluetooth Bluetooth User Library (libbluetooth, \-lbluetooth) -.ds doc-str-Lb-libcapsicum Capsicum Library (libcapsicum, \-lcapsicum) +.ds doc-str-Lb-libcseper Casper Library (libcapsicum, \-lcasper) .ds doc-str-Lb-libcuse Userland Character Device Library (libcuse, \-lcuse) .ds doc-str-Lb-libedit Line Editor and History Library (libedit, \-ledit) .ds doc-str-Lb-libefi EFI Runtime Services Library (libefi, \-lefi) diff --git a/lib/Makefile b/lib/Makefile index 699aa6ac7c02..cfa0ea9d2b70 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -36,7 +36,6 @@ SUBDIR= ${SUBDIR_ORDERED} \ libbz2 \ libcalendar \ libcam \ - ${_libcapsicum} \ ${_libcasper} \ ${_libcom_err} \ libcompat \ @@ -135,8 +134,7 @@ SUBDIR_DEPEND_libbsnmp= ${_libnetgraph} SUBDIR_DEPEND_libc++:= libcxxrt SUBDIR_DEPEND_libc= libcompiler_rt SUBDIR_DEPEND_libcam= libsbuf -SUBDIR_DEPEND_libcapsicum= libnv -SUBDIR_DEPEND_libcasper= libcapsicum libnv libpjdlog +SUBDIR_DEPEND_libcasper= libnv SUBDIR_DEPEND_libdevstat= libkvm SUBDIR_DEPEND_libdpv= libfigpar ncurses libutil SUBDIR_DEPEND_libedit= ncurses @@ -171,7 +169,6 @@ _libbsnmp= libbsnmp .endif .if ${MK_CASPER} != "no" -_libcapsicum= libcapsicum _libcasper= libcasper .endif diff --git a/lib/libc/posix1e/posix1e.3 b/lib/libc/posix1e/posix1e.3 index 257b6f510955..02fb3ef27e99 100644 --- a/lib/libc/posix1e/posix1e.3 +++ b/lib/libc/posix1e/posix1e.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 15, 2014 +.Dd February 25, 2016 .Dt POSIX1E 3 .Os .Sh NAME @@ -94,7 +94,7 @@ for mandatory access control labels. .Xr acl 3 , .Xr extattr 3 , .Xr libbsm 3 , -.Xr libcapsicum 3 , +.Xr libcasper 3 , .Xr mac 3 , .Xr capsicum 4 , .Xr ffs 7 , diff --git a/lib/libcapsicum/Makefile b/lib/libcapsicum/Makefile deleted file mode 100644 index 6ee5bb83eada..000000000000 --- a/lib/libcapsicum/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# $FreeBSD$ - -LIB= capsicum - -SHLIB_MAJOR= 0 -SHLIBDIR?= /lib - -SRCS= libcapsicum.c -SRCS+= libcapsicum_dns.c -SRCS+= libcapsicum_grp.c -SRCS+= libcapsicum_pwd.c -SRCS+= libcapsicum_random.c -SRCS+= libcapsicum_service.c -SRCS+= libcapsicum_sysctl.c - -INCS= libcapsicum.h -INCS+= libcapsicum_dns.h -INCS+= libcapsicum_grp.h -INCS+= libcapsicum_pwd.h -INCS+= libcapsicum_random.h -INCS+= libcapsicum_service.h -INCS+= libcapsicum_sysctl.h - -LIBADD= nv - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../libnv - -WARNS?= 6 - -MAN+= libcapsicum.3 - -MLINKS+=libcapsicum.3 cap_init.3 -MLINKS+=libcapsicum.3 cap_wrap.3 -MLINKS+=libcapsicum.3 cap_unwrap.3 -MLINKS+=libcapsicum.3 cap_sock.3 -MLINKS+=libcapsicum.3 cap_clone.3 -MLINKS+=libcapsicum.3 cap_close.3 -MLINKS+=libcapsicum.3 cap_limit_get.3 -MLINKS+=libcapsicum.3 cap_limit_set.3 -MLINKS+=libcapsicum.3 cap_send_nvlist.3 -MLINKS+=libcapsicum.3 cap_recv_nvlist.3 -MLINKS+=libcapsicum.3 cap_xfer_nvlist.3 -MLINKS+=libcapsicum.3 cap_service_open.3 - -.include diff --git a/lib/libcapsicum/Makefile.depend b/lib/libcapsicum/Makefile.depend deleted file mode 100644 index 4f7989bd2e64..000000000000 --- a/lib/libcapsicum/Makefile.depend +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - gnu/lib/libgcc \ - include \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcompiler_rt \ - lib/libnv \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/lib/libcapsicum/libcapsicum_dns.c b/lib/libcapsicum/libcapsicum_dns.c deleted file mode 100644 index 5f54283a460c..000000000000 --- a/lib/libcapsicum/libcapsicum_dns.c +++ /dev/null @@ -1,365 +0,0 @@ -/*- - * Copyright (c) 2012-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include - -#include "libcapsicum.h" -#include "libcapsicum_dns.h" - -static struct hostent hent; - -static void -hostent_free(struct hostent *hp) -{ - unsigned int ii; - - free(hp->h_name); - hp->h_name = NULL; - if (hp->h_aliases != NULL) { - for (ii = 0; hp->h_aliases[ii] != NULL; ii++) - free(hp->h_aliases[ii]); - free(hp->h_aliases); - hp->h_aliases = NULL; - } - if (hp->h_addr_list != NULL) { - for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) - free(hp->h_addr_list[ii]); - free(hp->h_addr_list); - hp->h_addr_list = NULL; - } -} - -static struct hostent * -hostent_unpack(const nvlist_t *nvl, struct hostent *hp) -{ - unsigned int ii, nitems; - char nvlname[64]; - int n; - - hostent_free(hp); - - hp->h_name = strdup(nvlist_get_string(nvl, "name")); - if (hp->h_name == NULL) - goto fail; - hp->h_addrtype = (int)nvlist_get_number(nvl, "addrtype"); - hp->h_length = (int)nvlist_get_number(nvl, "length"); - - nitems = (unsigned int)nvlist_get_number(nvl, "naliases"); - hp->h_aliases = calloc(sizeof(hp->h_aliases[0]), nitems + 1); - if (hp->h_aliases == NULL) - goto fail; - for (ii = 0; ii < nitems; ii++) { - n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii); - assert(n > 0 && n < (int)sizeof(nvlname)); - hp->h_aliases[ii] = - strdup(nvlist_get_string(nvl, nvlname)); - if (hp->h_aliases[ii] == NULL) - goto fail; - } - hp->h_aliases[ii] = NULL; - - nitems = (unsigned int)nvlist_get_number(nvl, "naddrs"); - hp->h_addr_list = calloc(sizeof(hp->h_addr_list[0]), nitems + 1); - if (hp->h_addr_list == NULL) - goto fail; - for (ii = 0; ii < nitems; ii++) { - hp->h_addr_list[ii] = malloc(hp->h_length); - if (hp->h_addr_list[ii] == NULL) - goto fail; - n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii); - assert(n > 0 && n < (int)sizeof(nvlname)); - bcopy(nvlist_get_binary(nvl, nvlname, NULL), - hp->h_addr_list[ii], hp->h_length); - } - hp->h_addr_list[ii] = NULL; - - return (hp); -fail: - hostent_free(hp); - h_errno = NO_RECOVERY; - return (NULL); -} - -struct hostent * -cap_gethostbyname(cap_channel_t *chan, const char *name) -{ - - return (cap_gethostbyname2(chan, name, AF_INET)); -} - -struct hostent * -cap_gethostbyname2(cap_channel_t *chan, const char *name, int type) -{ - struct hostent *hp; - nvlist_t *nvl; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "gethostbyname"); - nvlist_add_number(nvl, "family", (uint64_t)type); - nvlist_add_string(nvl, "name", name); - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) { - h_errno = NO_RECOVERY; - return (NULL); - } - if (nvlist_get_number(nvl, "error") != 0) { - h_errno = (int)nvlist_get_number(nvl, "error"); - nvlist_destroy(nvl); - return (NULL); - } - - hp = hostent_unpack(nvl, &hent); - nvlist_destroy(nvl); - return (hp); -} - -struct hostent * -cap_gethostbyaddr(cap_channel_t *chan, const void *addr, socklen_t len, - int type) -{ - struct hostent *hp; - nvlist_t *nvl; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "gethostbyaddr"); - nvlist_add_binary(nvl, "addr", addr, (size_t)len); - nvlist_add_number(nvl, "family", (uint64_t)type); - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) { - h_errno = NO_RECOVERY; - return (NULL); - } - if (nvlist_get_number(nvl, "error") != 0) { - h_errno = (int)nvlist_get_number(nvl, "error"); - nvlist_destroy(nvl); - return (NULL); - } - hp = hostent_unpack(nvl, &hent); - nvlist_destroy(nvl); - return (hp); -} - -static struct addrinfo * -addrinfo_unpack(const nvlist_t *nvl) -{ - struct addrinfo *ai; - const void *addr; - size_t addrlen; - const char *canonname; - - addr = nvlist_get_binary(nvl, "ai_addr", &addrlen); - ai = malloc(sizeof(*ai) + addrlen); - if (ai == NULL) - return (NULL); - ai->ai_flags = (int)nvlist_get_number(nvl, "ai_flags"); - ai->ai_family = (int)nvlist_get_number(nvl, "ai_family"); - ai->ai_socktype = (int)nvlist_get_number(nvl, "ai_socktype"); - ai->ai_protocol = (int)nvlist_get_number(nvl, "ai_protocol"); - ai->ai_addrlen = (socklen_t)addrlen; - canonname = nvlist_get_string(nvl, "ai_canonname"); - if (canonname != NULL) { - ai->ai_canonname = strdup(canonname); - if (ai->ai_canonname == NULL) { - free(ai); - return (NULL); - } - } else { - ai->ai_canonname = NULL; - } - ai->ai_addr = (void *)(ai + 1); - bcopy(addr, ai->ai_addr, addrlen); - ai->ai_next = NULL; - - return (ai); -} - -int -cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) -{ - struct addrinfo *firstai, *prevai, *curai; - unsigned int ii; - const nvlist_t *nvlai; - char nvlname[64]; - nvlist_t *nvl; - int error, n; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "getaddrinfo"); - nvlist_add_string(nvl, "hostname", hostname); - nvlist_add_string(nvl, "servname", servname); - if (hints != NULL) { - nvlist_add_number(nvl, "hints.ai_flags", - (uint64_t)hints->ai_flags); - nvlist_add_number(nvl, "hints.ai_family", - (uint64_t)hints->ai_family); - nvlist_add_number(nvl, "hints.ai_socktype", - (uint64_t)hints->ai_socktype); - nvlist_add_number(nvl, "hints.ai_protocol", - (uint64_t)hints->ai_protocol); - } - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) - return (EAI_MEMORY); - if (nvlist_get_number(nvl, "error") != 0) { - error = (int)nvlist_get_number(nvl, "error"); - nvlist_destroy(nvl); - return (error); - } - - nvlai = NULL; - firstai = prevai = curai = NULL; - for (ii = 0; ; ii++) { - n = snprintf(nvlname, sizeof(nvlname), "res%u", ii); - assert(n > 0 && n < (int)sizeof(nvlname)); - if (!nvlist_exists_nvlist(nvl, nvlname)) - break; - nvlai = nvlist_get_nvlist(nvl, nvlname); - curai = addrinfo_unpack(nvlai); - if (curai == NULL) - break; - if (prevai != NULL) - prevai->ai_next = curai; - else if (firstai == NULL) - firstai = curai; - prevai = curai; - } - nvlist_destroy(nvl); - if (curai == NULL && nvlai != NULL) { - if (firstai == NULL) - freeaddrinfo(firstai); - return (EAI_MEMORY); - } - - *res = firstai; - return (0); -} - -int -cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, char *serv, size_t servlen, int flags) -{ - nvlist_t *nvl; - int error; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "getnameinfo"); - nvlist_add_number(nvl, "hostlen", (uint64_t)hostlen); - nvlist_add_number(nvl, "servlen", (uint64_t)servlen); - nvlist_add_binary(nvl, "sa", sa, (size_t)salen); - nvlist_add_number(nvl, "flags", (uint64_t)flags); - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) - return (EAI_MEMORY); - if (nvlist_get_number(nvl, "error") != 0) { - error = (int)nvlist_get_number(nvl, "error"); - nvlist_destroy(nvl); - return (error); - } - - if (host != NULL) - strlcpy(host, nvlist_get_string(nvl, "host"), hostlen + 1); - if (serv != NULL) - strlcpy(serv, nvlist_get_string(nvl, "serv"), servlen + 1); - nvlist_destroy(nvl); - return (0); -} - -static void -limit_remove(nvlist_t *limits, const char *prefix) -{ - const char *name; - size_t prefixlen; - void *cookie; - - prefixlen = strlen(prefix); -again: - cookie = NULL; - while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) { - if (strncmp(name, prefix, prefixlen) == 0) { - nvlist_free(limits, name); - goto again; - } - } -} - -int -cap_dns_type_limit(cap_channel_t *chan, const char * const *types, - size_t ntypes) -{ - nvlist_t *limits; - unsigned int i; - char nvlname[64]; - int n; - - if (cap_limit_get(chan, &limits) < 0) - return (-1); - if (limits == NULL) - limits = nvlist_create(0); - else - limit_remove(limits, "type"); - for (i = 0; i < ntypes; i++) { - n = snprintf(nvlname, sizeof(nvlname), "type%u", i); - assert(n > 0 && n < (int)sizeof(nvlname)); - nvlist_add_string(limits, nvlname, types[i]); - } - return (cap_limit_set(chan, limits)); -} - -int -cap_dns_family_limit(cap_channel_t *chan, const int *families, - size_t nfamilies) -{ - nvlist_t *limits; - unsigned int i; - char nvlname[64]; - int n; - - if (cap_limit_get(chan, &limits) < 0) - return (-1); - if (limits == NULL) - limits = nvlist_create(0); - else - limit_remove(limits, "family"); - for (i = 0; i < nfamilies; i++) { - n = snprintf(nvlname, sizeof(nvlname), "family%u", i); - assert(n > 0 && n < (int)sizeof(nvlname)); - nvlist_add_number(limits, nvlname, (uint64_t)families[i]); - } - return (cap_limit_set(chan, limits)); -} diff --git a/lib/libcapsicum/libcapsicum_impl.h b/lib/libcapsicum/libcapsicum_impl.h deleted file mode 100644 index ce6f49fdfcda..000000000000 --- a/lib/libcapsicum/libcapsicum_impl.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 2012-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _LIBCAPSICUM_IMPL_H_ -#define _LIBCAPSICUM_IMPL_H_ - -#define CASPER_SOCKPATH "/var/run/casper" - -bool fd_is_valid(int fd); - -#endif /* !_LIBCAPSICUM_IMPL_H_ */ diff --git a/lib/libcapsicum/libcapsicum_pwd.c b/lib/libcapsicum/libcapsicum_pwd.c deleted file mode 100644 index 5b44c3463def..000000000000 --- a/lib/libcapsicum/libcapsicum_pwd.c +++ /dev/null @@ -1,391 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "libcapsicum.h" -#include "libcapsicum_pwd.h" - -static struct passwd gpwd; -static char *gbuffer; -static size_t gbufsize; - -static int -passwd_resize(void) -{ - char *buf; - - if (gbufsize == 0) - gbufsize = 1024; - else - gbufsize *= 2; - - buf = gbuffer; - gbuffer = realloc(buf, gbufsize); - if (gbuffer == NULL) { - free(buf); - gbufsize = 0; - return (ENOMEM); - } - memset(gbuffer, 0, gbufsize); - - return (0); -} - -static int -passwd_unpack_string(const nvlist_t *nvl, const char *fieldname, char **fieldp, - char **bufferp, size_t *bufsizep) -{ - const char *str; - size_t len; - - str = nvlist_get_string(nvl, fieldname); - len = strlcpy(*bufferp, str, *bufsizep); - if (len >= *bufsizep) - return (ERANGE); - *fieldp = *bufferp; - *bufferp += len + 1; - *bufsizep -= len + 1; - - return (0); -} - -static int -passwd_unpack(const nvlist_t *nvl, struct passwd *pwd, char *buffer, - size_t bufsize) -{ - int error; - - if (!nvlist_exists_string(nvl, "pw_name")) - return (EINVAL); - - memset(pwd, 0, sizeof(*pwd)); - - error = passwd_unpack_string(nvl, "pw_name", &pwd->pw_name, &buffer, - &bufsize); - if (error != 0) - return (error); - pwd->pw_uid = (uid_t)nvlist_get_number(nvl, "pw_uid"); - pwd->pw_gid = (gid_t)nvlist_get_number(nvl, "pw_gid"); - pwd->pw_change = (time_t)nvlist_get_number(nvl, "pw_change"); - error = passwd_unpack_string(nvl, "pw_passwd", &pwd->pw_passwd, &buffer, - &bufsize); - if (error != 0) - return (error); - error = passwd_unpack_string(nvl, "pw_class", &pwd->pw_class, &buffer, - &bufsize); - if (error != 0) - return (error); - error = passwd_unpack_string(nvl, "pw_gecos", &pwd->pw_gecos, &buffer, - &bufsize); - if (error != 0) - return (error); - error = passwd_unpack_string(nvl, "pw_dir", &pwd->pw_dir, &buffer, - &bufsize); - if (error != 0) - return (error); - error = passwd_unpack_string(nvl, "pw_shell", &pwd->pw_shell, &buffer, - &bufsize); - if (error != 0) - return (error); - pwd->pw_expire = (time_t)nvlist_get_number(nvl, "pw_expire"); - pwd->pw_fields = (int)nvlist_get_number(nvl, "pw_fields"); - - return (0); -} - -static int -cap_getpwcommon_r(cap_channel_t *chan, const char *cmd, const char *login, - uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, - struct passwd **result) -{ - nvlist_t *nvl; - bool getpw_r; - int error; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", cmd); - if (strcmp(cmd, "getpwent") == 0 || strcmp(cmd, "getpwent_r") == 0) { - /* Add nothing. */ - } else if (strcmp(cmd, "getpwnam") == 0 || - strcmp(cmd, "getpwnam_r") == 0) { - nvlist_add_string(nvl, "name", login); - } else if (strcmp(cmd, "getpwuid") == 0 || - strcmp(cmd, "getpwuid_r") == 0) { - nvlist_add_number(nvl, "uid", (uint64_t)uid); - } else { - abort(); - } - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) { - assert(errno != 0); - *result = NULL; - return (errno); - } - error = (int)nvlist_get_number(nvl, "error"); - if (error != 0) { - nvlist_destroy(nvl); - *result = NULL; - return (error); - } - - if (!nvlist_exists_string(nvl, "pw_name")) { - /* Not found. */ - nvlist_destroy(nvl); - *result = NULL; - return (0); - } - - getpw_r = (strcmp(cmd, "getpwent_r") == 0 || - strcmp(cmd, "getpwnam_r") == 0 || strcmp(cmd, "getpwuid_r") == 0); - - for (;;) { - error = passwd_unpack(nvl, pwd, buffer, bufsize); - if (getpw_r || error != ERANGE) - break; - assert(buffer == gbuffer); - assert(bufsize == gbufsize); - error = passwd_resize(); - if (error != 0) - break; - /* Update pointers after resize. */ - buffer = gbuffer; - bufsize = gbufsize; - } - - nvlist_destroy(nvl); - - if (error == 0) - *result = pwd; - else - *result = NULL; - - return (error); -} - -static struct passwd * -cap_getpwcommon(cap_channel_t *chan, const char *cmd, const char *login, - uid_t uid) -{ - struct passwd *result; - int error, serrno; - - serrno = errno; - - error = cap_getpwcommon_r(chan, cmd, login, uid, &gpwd, gbuffer, - gbufsize, &result); - if (error != 0) { - errno = error; - return (NULL); - } - - errno = serrno; - - return (result); -} - -struct passwd * -cap_getpwent(cap_channel_t *chan) -{ - - return (cap_getpwcommon(chan, "getpwent", NULL, 0)); -} - -struct passwd * -cap_getpwnam(cap_channel_t *chan, const char *login) -{ - - return (cap_getpwcommon(chan, "getpwnam", login, 0)); -} - -struct passwd * -cap_getpwuid(cap_channel_t *chan, uid_t uid) -{ - - return (cap_getpwcommon(chan, "getpwuid", NULL, uid)); -} - -int -cap_getpwent_r(cap_channel_t *chan, struct passwd *pwd, char *buffer, - size_t bufsize, struct passwd **result) -{ - - return (cap_getpwcommon_r(chan, "getpwent_r", NULL, 0, pwd, buffer, - bufsize, result)); -} - -int -cap_getpwnam_r(cap_channel_t *chan, const char *name, struct passwd *pwd, - char *buffer, size_t bufsize, struct passwd **result) -{ - - return (cap_getpwcommon_r(chan, "getpwnam_r", name, 0, pwd, buffer, - bufsize, result)); -} - -int -cap_getpwuid_r(cap_channel_t *chan, uid_t uid, struct passwd *pwd, char *buffer, - size_t bufsize, struct passwd **result) -{ - - return (cap_getpwcommon_r(chan, "getpwuid_r", NULL, uid, pwd, buffer, - bufsize, result)); -} - -int -cap_setpassent(cap_channel_t *chan, int stayopen) -{ - nvlist_t *nvl; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "setpassent"); - nvlist_add_bool(nvl, "stayopen", stayopen != 0); - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) - return (0); - if (nvlist_get_number(nvl, "error") != 0) { - errno = nvlist_get_number(nvl, "error"); - nvlist_destroy(nvl); - return (0); - } - nvlist_destroy(nvl); - - return (1); -} - -static void -cap_set_end_pwent(cap_channel_t *chan, const char *cmd) -{ - nvlist_t *nvl; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", cmd); - /* Ignore any errors, we have no way to report them. */ - nvlist_destroy(cap_xfer_nvlist(chan, nvl, 0)); -} - -void -cap_setpwent(cap_channel_t *chan) -{ - - cap_set_end_pwent(chan, "setpwent"); -} - -void -cap_endpwent(cap_channel_t *chan) -{ - - cap_set_end_pwent(chan, "endpwent"); -} - -int -cap_pwd_limit_cmds(cap_channel_t *chan, const char * const *cmds, size_t ncmds) -{ - nvlist_t *limits, *nvl; - unsigned int i; - - if (cap_limit_get(chan, &limits) < 0) - return (-1); - if (limits == NULL) { - limits = nvlist_create(0); - } else { - if (nvlist_exists_nvlist(limits, "cmds")) - nvlist_free_nvlist(limits, "cmds"); - } - nvl = nvlist_create(0); - for (i = 0; i < ncmds; i++) - nvlist_add_null(nvl, cmds[i]); - nvlist_move_nvlist(limits, "cmds", nvl); - return (cap_limit_set(chan, limits)); -} - -int -cap_pwd_limit_fields(cap_channel_t *chan, const char * const *fields, - size_t nfields) -{ - nvlist_t *limits, *nvl; - unsigned int i; - - if (cap_limit_get(chan, &limits) < 0) - return (-1); - if (limits == NULL) { - limits = nvlist_create(0); - } else { - if (nvlist_exists_nvlist(limits, "fields")) - nvlist_free_nvlist(limits, "fields"); - } - nvl = nvlist_create(0); - for (i = 0; i < nfields; i++) - nvlist_add_null(nvl, fields[i]); - nvlist_move_nvlist(limits, "fields", nvl); - return (cap_limit_set(chan, limits)); -} - -int -cap_pwd_limit_users(cap_channel_t *chan, const char * const *names, - size_t nnames, uid_t *uids, size_t nuids) -{ - nvlist_t *limits, *users; - char nvlname[64]; - unsigned int i; - int n; - - if (cap_limit_get(chan, &limits) < 0) - return (-1); - if (limits == NULL) { - limits = nvlist_create(0); - } else { - if (nvlist_exists_nvlist(limits, "users")) - nvlist_free_nvlist(limits, "users"); - } - users = nvlist_create(0); - for (i = 0; i < nuids; i++) { - n = snprintf(nvlname, sizeof(nvlname), "uid%u", i); - assert(n > 0 && n < (int)sizeof(nvlname)); - nvlist_add_number(users, nvlname, (uint64_t)uids[i]); - } - for (i = 0; i < nnames; i++) { - n = snprintf(nvlname, sizeof(nvlname), "name%u", i); - assert(n > 0 && n < (int)sizeof(nvlname)); - nvlist_add_string(users, nvlname, names[i]); - } - nvlist_move_nvlist(limits, "users", users); - return (cap_limit_set(chan, limits)); -} diff --git a/lib/libcapsicum/libcapsicum_service.c b/lib/libcapsicum/libcapsicum_service.c deleted file mode 100644 index 6b6ceeac08de..000000000000 --- a/lib/libcapsicum/libcapsicum_service.c +++ /dev/null @@ -1,97 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include - -#include "msgio.h" - -#include "libcapsicum.h" -#include "libcapsicum_impl.h" -#include "libcapsicum_service.h" - -cap_channel_t * -cap_service_open(const cap_channel_t *chan, const char *name) -{ - cap_channel_t *newchan; - nvlist_t *nvl; - int sock, error; - - sock = -1; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "open"); - nvlist_add_string(nvl, "service", name); - if (fd_is_valid(STDERR_FILENO)) - nvlist_add_descriptor(nvl, "stderrfd", STDERR_FILENO); - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) - return (NULL); - error = (int)nvlist_get_number(nvl, "error"); - if (error != 0) { - nvlist_destroy(nvl); - errno = error; - return (NULL); - } - sock = nvlist_take_descriptor(nvl, "chanfd"); - assert(sock >= 0); - nvlist_destroy(nvl); - nvl = NULL; - if (cred_send(sock) == -1) - goto fail; - newchan = cap_wrap(sock); - if (newchan == NULL) - goto fail; - return (newchan); -fail: - error = errno; - close(sock); - errno = error; - return (NULL); -} - -int -cap_service_limit(const cap_channel_t *chan, const char * const *names, - size_t nnames) -{ - nvlist_t *limits; - unsigned int i; - - limits = nvlist_create(0); - for (i = 0; i < nnames; i++) - nvlist_add_null(limits, names[i]); - return (cap_limit_set(chan, limits)); -} diff --git a/lib/libcapsicum/libcapsicum_sysctl.c b/lib/libcapsicum/libcapsicum_sysctl.c deleted file mode 100644 index 3f1ccd9116c0..000000000000 --- a/lib/libcapsicum/libcapsicum_sysctl.c +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include - -#include "libcapsicum.h" -#include "libcapsicum_sysctl.h" - -int -cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp, - size_t *oldlenp, const void *newp, size_t newlen) -{ - nvlist_t *nvl; - const uint8_t *retoldp; - uint8_t operation; - size_t oldlen; - - operation = 0; - if (oldp != NULL) - operation |= CAP_SYSCTL_READ; - if (newp != NULL) - operation |= CAP_SYSCTL_WRITE; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "cmd", "sysctl"); - nvlist_add_string(nvl, "name", name); - nvlist_add_number(nvl, "operation", (uint64_t)operation); - if (oldp == NULL && oldlenp != NULL) - nvlist_add_null(nvl, "justsize"); - else if (oldlenp != NULL) - nvlist_add_number(nvl, "oldlen", (uint64_t)*oldlenp); - if (newp != NULL) - nvlist_add_binary(nvl, "newp", newp, newlen); - nvl = cap_xfer_nvlist(chan, nvl, 0); - if (nvl == NULL) - return (-1); - if (nvlist_get_number(nvl, "error") != 0) { - errno = (int)nvlist_get_number(nvl, "error"); - nvlist_destroy(nvl); - return (-1); - } - - if (oldp == NULL && oldlenp != NULL) { - *oldlenp = (size_t)nvlist_get_number(nvl, "oldlen"); - } else if (oldp != NULL) { - retoldp = nvlist_get_binary(nvl, "oldp", &oldlen); - memcpy(oldp, retoldp, oldlen); - if (oldlenp != NULL) - *oldlenp = oldlen; - } - nvlist_destroy(nvl); - - return (0); -} diff --git a/lib/libcasper/Makefile b/lib/libcasper/Makefile index e57accdf94a3..af0701be396f 100644 --- a/lib/libcasper/Makefile +++ b/lib/libcasper/Makefile @@ -1,19 +1,6 @@ # $FreeBSD$ -LIB= casper +SUBDIR= libcasper +SUBDIR+= services -SHLIB_MAJOR= 0 -SHLIBDIR?= /lib - -SRCS= libcasper.c -INCS= libcasper.h - -LIBADD= capsicum nv pjdlog - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../libpjdlog -CFLAGS+=-I${.CURDIR}/../../sbin/casper - -WARNS?= 6 - -.include +.include diff --git a/lib/libcasper/libcasper.h b/lib/libcasper/libcasper.h deleted file mode 100644 index 91d602737f9c..000000000000 --- a/lib/libcasper/libcasper.h +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _LIBCASPER_H_ -#define _LIBCASPER_H_ - -#ifndef _NVLIST_T_DECLARED -#define _NVLIST_T_DECLARED -struct nvlist; - -typedef struct nvlist nvlist_t; -#endif - -#define PARENT_FILENO 3 -#define EXECUTABLE_FILENO 4 -#define PROC_FILENO 5 - -struct service; -struct service_connection; - -typedef int service_limit_func_t(const nvlist_t *, const nvlist_t *); -typedef int service_command_func_t(const char *cmd, const nvlist_t *, - nvlist_t *, nvlist_t *); - -struct service_connection *service_connection_add(struct service *service, - int sock, const nvlist_t *limits); -void service_connection_remove(struct service *service, - struct service_connection *sconn); -int service_connection_clone(struct service *service, - struct service_connection *sconn); -struct service_connection *service_connection_first(struct service *service); -struct service_connection *service_connection_next(struct service_connection *sconn); -cap_channel_t *service_connection_get_chan(const struct service_connection *sconn); -int service_connection_get_sock(const struct service_connection *sconn); -const nvlist_t *service_connection_get_limits(const struct service_connection *sconn); -void service_connection_set_limits(struct service_connection *sconn, - nvlist_t *limits); - -int service_start(const char *name, int sock, service_limit_func_t *limitfunc, - service_command_func_t *commandfunc, int argc, char *argv[]); - -#endif /* !_LIBCASPER_H_ */ diff --git a/lib/libcasper/libcasper/Makefile b/lib/libcasper/libcasper/Makefile new file mode 100644 index 000000000000..2a123ac6d24c --- /dev/null +++ b/lib/libcasper/libcasper/Makefile @@ -0,0 +1,38 @@ +# $FreeBSD$ + +LIB= casper + +SHLIB_MAJOR= 0 +SHLIBDIR?= /lib + +SRCS= libcasper.c +SRCS+= libcasper_impl.c +SRCS+= libcasper_service.c +SRCS+= service.c +SRCS+= zygote.c + +INCS= libcasper.h +INCS+= libcasper_service.h + +LIBADD= nv + +CFLAGS+=-I${.CURDIR} + +WARNS?= 6 + +MAN+= libcasper.3 + +MLINKS+=libcasper.3 cap_init.3 +MLINKS+=libcasper.3 cap_wrap.3 +MLINKS+=libcasper.3 cap_unwrap.3 +MLINKS+=libcasper.3 cap_sock.3 +MLINKS+=libcasper.3 cap_clone.3 +MLINKS+=libcasper.3 cap_close.3 +MLINKS+=libcasper.3 cap_limit_get.3 +MLINKS+=libcasper.3 cap_limit_set.3 +MLINKS+=libcasper.3 cap_send_nvlist.3 +MLINKS+=libcasper.3 cap_recv_nvlist.3 +MLINKS+=libcasper.3 cap_xfer_nvlist.3 +MLINKS+=libcasper.3 cap_service_open.3 + +.include diff --git a/lib/libcapsicum/libcapsicum.3 b/lib/libcasper/libcasper/libcasper.3 similarity index 91% rename from lib/libcapsicum/libcapsicum.3 rename to lib/libcasper/libcasper/libcasper.3 index cbfd214a3bc5..220b5b3ffd52 100644 --- a/lib/libcapsicum/libcapsicum.3 +++ b/lib/libcasper/libcasper/libcasper.3 @@ -27,8 +27,8 @@ .\" .\" $FreeBSD$ .\" -.Dd May 2, 2015 -.Dt LIBCAPSICUM 3 +.Dd February 25, 2016 +.Dt LIBCASPER 3 .Os .Sh NAME .Nm cap_init , @@ -45,9 +45,9 @@ .Nm cap_service_open .Nd "library for handling application capabilities" .Sh LIBRARY -.Lb libcapsicum +.Lb libcasper .Sh SYNOPSIS -.In libcapsicum.h +.In libcasper.h .In nv.h .Ft "cap_channel_t *" .Fn cap_init "void" @@ -71,24 +71,18 @@ .Fn cap_recv_nvlist "const cap_channel_t *chan" "int flags" .Ft "nvlist_t *" .Fn cap_xfer_nvlist "const cap_channel_t *chan" "nvlist_t *nvl" "int flags" -.In libcapsicum_service.h .Ft "cap_channel_t *" .Fn cap_service_open "const cap_channel_t *chan" "const char *name" .Sh DESCRIPTION The .Nm libcapsicum -library allows to manage application capabilities through the -.Xr casperd 8 -daemon. +library allows to manage application capabilities through the casper process. .Pp The application capability (represented by the .Vt cap_channel_t -type) is a communication channel between the caller and the -.Xr casperd 8 +type) is a communication channel between the caller and the casper process daemon or an instance of one of its services. -A capability to the -.Xr casperd 8 -daemon obtained with the +A capability to the casper process obtained with the .Fn cap_init function allows to create capabilities to casper's services via the .Fn cap_service_open @@ -96,9 +90,7 @@ function. .Pp The .Fn cap_init -function opens capability to the -.Xr casperd 8 -daemon. +function opens capability to the casper process. .Pp The .Fn cap_wrap @@ -231,9 +223,8 @@ and .Fn cap_unwrap functions always succeed. .Sh EXAMPLES -The following example first opens capability to the -.Xr casperd 8 -daemon, then using this capability creates new capability to the +The following example first opens capability to the casper then using this +capability creates new capability to the .Nm system.dns casper service and uses the latter capability to resolve IP address. .Bd -literal @@ -243,10 +234,10 @@ const char *ipstr = "127.0.0.1"; struct in_addr ip; struct hostent *hp; -/* Open capability to the Casper daemon. */ +/* Open capability to the Casper. */ capcas = cap_init(); if (capcas == NULL) - err(1, "Unable to contact Casper daemon"); + err(1, "Unable to contact Casper"); /* Enter capability mode sandbox. */ if (cap_enter() < 0 && errno != ENOSYS) @@ -290,11 +281,15 @@ printf("Name associated with %s is %s.\\n", ipstr, hp->h_name); .Xr inet_aton 3 , .Xr nv 3 , .Xr capsicum 4 , -.Xr unix 4 , -.Xr casperd 8 +.Xr unix 4 .Sh AUTHORS The -.Nm libcapsicum +.Nm libcasper library was implemented by .An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net under sponsorship from the FreeBSD Foundation. +The +.Nm libcasper +new architecture was implemented by +.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org +. diff --git a/lib/libcapsicum/libcapsicum.c b/lib/libcasper/libcasper/libcasper.c similarity index 72% rename from lib/libcapsicum/libcapsicum.c rename to lib/libcasper/libcasper/libcasper.c index 8c4d04da157e..f23d8b18c861 100644 --- a/lib/libcapsicum/libcapsicum.c +++ b/lib/libcasper/libcasper/libcasper.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2012-2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -32,19 +33,18 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include +#include #include #include -#include #include #include #include #include -#include "libcapsicum.h" -#include "libcapsicum_impl.h" +#include "libcasper.h" +#include "libcasper_impl.h" /* * Structure describing communication channel between two separated processes. @@ -58,44 +58,61 @@ struct cap_channel { int cch_magic; /* Socket descriptor for IPC. */ int cch_sock; + /* Process descriptor for casper. */ + int cch_pd; }; -bool -fd_is_valid(int fd) +static bool +cap_add_pd(cap_channel_t *chan, int pd) { - return (fcntl(fd, F_GETFL) != -1 || errno != EBADF); + if (!fd_is_valid(pd)) + return (false); + chan->cch_pd = pd; + return (true); } cap_channel_t * cap_init(void) { + pid_t pid; + int sock[2], serrno, pfd; + bool ret; cap_channel_t *chan; - struct sockaddr_un sun; - int serrno, sock; - bzero(&sun, sizeof(sun)); - sun.sun_family = AF_UNIX; - strlcpy(sun.sun_path, CASPER_SOCKPATH, sizeof(sun.sun_path)); - sun.sun_len = SUN_LEN(&sun); - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) - return (NULL); - if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) { - serrno = errno; - close(sock); - errno = serrno; + if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, + sock) == -1) { return (NULL); } - chan = cap_wrap(sock); - if (chan == NULL) { - serrno = errno; - close(sock); - errno = serrno; - return (NULL); + + pid = pdfork(&pfd, 0); + if (pid == 0) { + /* Parent. */ + close(sock[0]); + casper_main_loop(sock[1]); + /* NOTREACHED. */ + } else if (pid > 0) { + /* Child. */ + close(sock[1]); + chan = cap_wrap(sock[0]); + if (chan == NULL) { + serrno = errno; + close(sock[0]); + close(pfd); + errno = serrno; + return (NULL); + } + ret = cap_add_pd(chan, pfd); + assert(ret); + return (chan); } - return (chan); + + /* Error. */ + serrno = errno; + close(sock[0]); + close(sock[1]); + errno = serrno; + return (NULL); } cap_channel_t * @@ -109,6 +126,7 @@ cap_wrap(int sock) chan = malloc(sizeof(*chan)); if (chan != NULL) { chan->cch_sock = sock; + chan->cch_pd = -1; chan->cch_magic = CAP_CHANNEL_MAGIC; } @@ -124,6 +142,8 @@ cap_unwrap(cap_channel_t *chan) assert(chan->cch_magic == CAP_CHANNEL_MAGIC); sock = chan->cch_sock; + if (chan->cch_pd != -1) + close(chan->cch_pd); chan->cch_magic = 0; free(chan); @@ -172,6 +192,8 @@ cap_close(cap_channel_t *chan) assert(chan->cch_magic == CAP_CHANNEL_MAGIC); chan->cch_magic = 0; + if (chan->cch_pd != -1) + close(chan->cch_pd); close(chan->cch_sock); free(chan); } @@ -264,3 +286,52 @@ cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags) return (nvlist_xfer(chan->cch_sock, nvl, flags)); } + +cap_channel_t * +cap_service_open(const cap_channel_t *chan, const char *name) +{ + cap_channel_t *newchan; + nvlist_t *nvl; + int sock, error; + + sock = -1; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "open"); + nvlist_add_string(nvl, "service", name); + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) + return (NULL); + error = (int)nvlist_get_number(nvl, "error"); + if (error != 0) { + nvlist_destroy(nvl); + errno = error; + return (NULL); + } + sock = nvlist_take_descriptor(nvl, "chanfd"); + assert(sock >= 0); + nvlist_destroy(nvl); + nvl = NULL; + newchan = cap_wrap(sock); + if (newchan == NULL) + goto fail; + return (newchan); +fail: + error = errno; + close(sock); + errno = error; + return (NULL); +} + +int +cap_service_limit(const cap_channel_t *chan, const char * const *names, + size_t nnames) +{ + nvlist_t *limits; + unsigned int i; + + limits = nvlist_create(0); + for (i = 0; i < nnames; i++) + nvlist_add_null(limits, names[i]); + return (cap_limit_set(chan, limits)); +} diff --git a/lib/libcapsicum/libcapsicum.h b/lib/libcasper/libcasper/libcasper.h similarity index 87% rename from lib/libcapsicum/libcapsicum.h rename to lib/libcasper/libcasper/libcasper.h index c7110d86c9ed..2d6f15825a39 100644 --- a/lib/libcapsicum/libcapsicum.h +++ b/lib/libcasper/libcasper/libcasper.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2012-2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -29,8 +30,10 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_H_ -#define _LIBCAPSICUM_H_ +#ifndef _LIBCASPER_H_ +#define _LIBCASPER_H_ + +#include #ifndef _NVLIST_T_DECLARED #define _NVLIST_T_DECLARED @@ -47,10 +50,17 @@ typedef struct cap_channel cap_channel_t; #endif /* - * The function opens unrestricted communication channel to Casper. + * The functions opens unrestricted communication channel to Casper. */ cap_channel_t *cap_init(void); +/* + * The functions to communicate with service. + */ +cap_channel_t *cap_service_open(const cap_channel_t *chan, const char *name); +int cap_service_limit(const cap_channel_t *chan, + const char * const *names, size_t nnames); + /* * The function creates cap_channel_t based on the given socket. */ @@ -88,16 +98,6 @@ int cap_limit_set(const cap_channel_t *chan, nvlist_t *limits); */ int cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp); -#ifdef TODO -/* - * The function registers a service within provided Casper's capability. - * It will run with the same privileges the process has at the time of - * calling this function. - */ -int cap_service_register(cap_channel_t *chan, const char *name, - cap_func_t *func); -#endif - /* * Function sends nvlist over the given capability. */ @@ -112,4 +112,4 @@ nvlist_t *cap_recv_nvlist(const cap_channel_t *chan, int flags); */ nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags); -#endif /* !_LIBCAPSICUM_H_ */ +#endif /* !_LIBCASPER_H_ */ diff --git a/lib/libcapsicum/libcapsicum_service.h b/lib/libcasper/libcasper/libcasper_impl.c similarity index 84% rename from lib/libcapsicum/libcapsicum_service.h rename to lib/libcasper/libcasper/libcasper_impl.c index 05c654f7bf10..57d489943252 100644 --- a/lib/libcapsicum/libcapsicum_service.h +++ b/lib/libcasper/libcasper/libcasper_impl.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -29,12 +30,15 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_SERVICE_H_ -#define _LIBCAPSICUM_SERVICE_H_ +#include +#include +#include -cap_channel_t *cap_service_open(const cap_channel_t *chan, const char *name); +#include "libcasper_impl.h" -int cap_service_limit(const cap_channel_t *chan, const char * const *names, - size_t nnames); +bool +fd_is_valid(int fd) +{ -#endif /* !_LIBCAPSICUM_SERVICE_H_ */ + return (fcntl(fd, F_GETFL) != -1 || errno != EBADF); +} diff --git a/lib/libcasper/libcasper/libcasper_impl.h b/lib/libcasper/libcasper/libcasper_impl.h new file mode 100644 index 000000000000..bf2e6cee3bc0 --- /dev/null +++ b/lib/libcasper/libcasper/libcasper_impl.h @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LIBCASPER_IMPL_H_ +#define _LIBCASPER_IMPL_H_ + +#include + +#include "libcasper.h" +#include "libcasper_service.h" + +struct service; +struct service_connection; + +bool fd_is_valid(int fd); + +/* Private service functions. */ +struct service *service_alloc(const char *name, + service_limit_func_t *limitfunc, + service_command_func_t *commandfunc); +void service_free(struct service *service); +void service_message(struct service *service, + struct service_connection *sconn); +void service_start(struct service *service, int sock); +const char *service_name(struct service *service); + +/* Private service connection functions. */ +struct service_connection *service_connection_add(struct service *service, + int sock, const nvlist_t *limits); +void service_connection_remove( + struct service *service, + struct service_connection *sconn); +int service_connection_clone( + struct service *service, + struct service_connection *sconn); +struct service_connection *service_connection_first( + struct service *service); +struct service_connection *service_connection_next( + struct service_connection *sconn); +cap_channel_t *service_connection_get_chan( + const struct service_connection *sconn); +int service_connection_get_sock( + const struct service_connection *sconn); +const nvlist_t *service_connection_get_limits( + const struct service_connection *sconn); +void service_connection_set_limits( + struct service_connection *sconn, + nvlist_t *limits); + +/* Private libcasper functions. */ +void casper_main_loop(int fd); + +#endif /* !_LIBCASPER_IMPL_H_ */ diff --git a/lib/libcasper/libcasper/libcasper_service.c b/lib/libcasper/libcasper/libcasper_service.c new file mode 100644 index 000000000000..5b1c7c852478 --- /dev/null +++ b/lib/libcasper/libcasper/libcasper_service.c @@ -0,0 +1,277 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "libcasper_impl.h" +#include "zygote.h" + +struct casper_service { + struct service *cs_service; + TAILQ_ENTRY(casper_service) cs_next; +}; + +static TAILQ_HEAD(, casper_service) casper_services = + TAILQ_HEAD_INITIALIZER(casper_services); + +#define CORE_CASPER_NAME "core.casper" +#define CSERVICE_IS_CORE(service) \ + (strcmp(service_name(service->cs_service), CORE_CASPER_NAME) == 0) + +static struct casper_service * +service_find(const char *name) +{ + struct casper_service *casserv; + + TAILQ_FOREACH(casserv, &casper_services, cs_next) { + if (strcmp(service_name(casserv->cs_service), name) == 0) + break; + } + return (casserv); +} + +struct casper_service * +service_register(const char *name, service_limit_func_t *limitfunc, + service_command_func_t *commandfunc) +{ + struct casper_service *casserv; + + if (commandfunc == NULL) + return (NULL); + if (name == NULL || name[0] == '\0') + return (NULL); + if (service_find(name) != NULL) + return (NULL); + + casserv = malloc(sizeof(*casserv)); + if (casserv == NULL) + return (NULL); + + casserv->cs_service = service_alloc(name, limitfunc, commandfunc); + if (casserv->cs_service == NULL) { + free(casserv); + return (NULL); + } + TAILQ_INSERT_TAIL(&casper_services, casserv, cs_next); + + return (casserv); +} + +static bool +casper_allowed_service(const nvlist_t *limits, const char *service) +{ + + if (limits == NULL) + return (true); + + if (nvlist_exists_null(limits, service)) + return (true); + + return (false); +} + +static int +casper_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) +{ + const char *name; + int type; + void *cookie; + + cookie = NULL; + while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { + if (type != NV_TYPE_NULL) + return (EINVAL); + if (!casper_allowed_service(oldlimits, name)) + return (ENOTCAPABLE); + } + + return (0); +} + +static void +service_execute(int chanfd) +{ + struct service *service; + nvlist_t *nvl; + int procfd; + + nvl = nvlist_recv(chanfd, 0); + if (nvl == NULL) + exit(1); + service = (struct service *)(uintptr_t)nvlist_take_number(nvl, + "service"); + //XXX: We should remove this? + procfd = nvlist_take_descriptor(nvl, "procfd"); + nvlist_destroy(nvl); + + service_start(service, chanfd); + /* Not reached. */ + exit(1); +} + +static int +casper_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, + nvlist_t *nvlout) +{ + struct casper_service *casserv; + const char *servname; + nvlist_t *nvl; + int chanfd, procfd, error; + + if (strcmp(cmd, "open") != 0) + return (EINVAL); + if (!nvlist_exists_string(nvlin, "service")) + return (EINVAL); + + servname = nvlist_get_string(nvlin, "service"); + casserv = service_find(servname); + if (casserv == NULL) + return (ENOENT); + + if (!casper_allowed_service(limits, servname)) + return (ENOTCAPABLE); + + if (zygote_clone(service_execute, &chanfd, &procfd) == -1) + return (errno); + + nvl = nvlist_create(0); + nvlist_add_number(nvl, "service", + (uint64_t)(uintptr_t)casserv->cs_service); + nvlist_move_descriptor(nvl, "procfd", procfd); + if (nvlist_send(chanfd, nvl) == -1) { + error = errno; + nvlist_destroy(nvl); + close(chanfd); + return (error); + } + nvlist_destroy(nvl); + + nvlist_move_descriptor(nvlout, "chanfd", chanfd); + + return (0); +} + +static void +service_register_core(int fd) +{ + struct casper_service *casserv; + struct service_connection *sconn; + + casserv = service_register(CORE_CASPER_NAME, casper_limit, + casper_command); + sconn = service_connection_add(casserv->cs_service, fd, NULL); + if (sconn == NULL) { + close(fd); + abort(); + } +} + +void +casper_main_loop(int fd) +{ + fd_set fds; + struct casper_service *casserv; + struct service_connection *sconn, *sconntmp; + int sock, maxfd, ret; + + if (zygote_init() < 0) + exit(1); + + /* + * Register core services. + */ + service_register_core(fd); + + for (;;) { + FD_ZERO(&fds); + FD_SET(fd, &fds); + maxfd = -1; + TAILQ_FOREACH(casserv, &casper_services, cs_next) { + /* We handle only core services. */ + if (!CSERVICE_IS_CORE(casserv)) + continue; + for (sconn = service_connection_first(casserv->cs_service); + sconn != NULL; + sconn = service_connection_next(sconn)) { + sock = service_connection_get_sock(sconn); + FD_SET(sock, &fds); + maxfd = sock > maxfd ? sock : maxfd; + } + } + if (maxfd == -1) { + /* Nothing to do. */ + exit(0); + } + maxfd++; + + + assert(maxfd <= (int)FD_SETSIZE); + ret = select(maxfd, &fds, NULL, NULL, NULL); + assert(ret == -1 || ret > 0); /* select() cannot timeout */ + if (ret == -1) { + if (errno == EINTR) + continue; + exit(1); + } + + TAILQ_FOREACH(casserv, &casper_services, cs_next) { + /* We handle only core services. */ + if (!CSERVICE_IS_CORE(casserv)) + continue; + for (sconn = service_connection_first(casserv->cs_service); + sconn != NULL; sconn = sconntmp) { + /* + * Prepare for connection to be removed from + * the list on failure. + */ + sconntmp = service_connection_next(sconn); + sock = service_connection_get_sock(sconn); + if (FD_ISSET(sock, &fds)) { + service_message(casserv->cs_service, + sconn); + } + } + } + } +} diff --git a/lib/libcasper/libcasper_impl.h b/lib/libcasper/libcasper/libcasper_service.h similarity index 67% rename from lib/libcasper/libcasper_impl.h rename to lib/libcasper/libcasper/libcasper_service.h index 320f21abb601..4efbeb24d345 100644 --- a/lib/libcasper/libcasper_impl.h +++ b/lib/libcasper/libcasper/libcasper_service.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -29,18 +30,31 @@ * $FreeBSD$ */ -#ifndef _LIBCASPER_IMPL_H_ -#define _LIBCASPER_IMPL_H_ +#ifndef _LIBCASPER_SERVICE_H_ +#define _LIBCASPER_SERVICE_H_ -#include "libcasper.h" +#ifndef _NVLIST_T_DECLARED +#define _NVLIST_T_DECLARED +struct nvlist; -struct service; -struct service_connection; +typedef struct nvlist nvlist_t; +#endif -struct service * service_alloc(const char *name, +typedef int service_limit_func_t(const nvlist_t *, const nvlist_t *); +typedef int service_command_func_t(const char *cmd, const nvlist_t *, + nvlist_t *, nvlist_t *); + +struct casper_service *service_register(const char *name, service_limit_func_t *limitfunc, service_command_func_t *commandfunc); -void service_free(struct service *service); -void service_message(struct service *service, struct service_connection *sconn); +#define __constructor __attribute__((constructor)) +#define CREATE_SERVICE(name, limit_func, command_func) \ + static __constructor void \ + init_casper_service(void) \ + { \ + \ + (void)service_register(name, limit_func, \ + command_func); \ + } -#endif /* !_LIBCASPER_IMPL_H_ */ +#endif /* !_LIBCASPER_SERVICE_H_ */ diff --git a/lib/libcasper/libcasper.c b/lib/libcasper/libcasper/service.c similarity index 74% rename from lib/libcasper/libcasper.c rename to lib/libcasper/libcasper/service.c index e241888aa95e..e02d7d90f0d6 100644 --- a/lib/libcasper/libcasper.c +++ b/lib/libcasper/libcasper/service.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -31,11 +32,8 @@ __FBSDID("$FreeBSD$"); #include -#include #include #include -#include -#include #include #include @@ -50,10 +48,8 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include -#include +#include "libcasper.h" +#include "libcasper_impl.h" /* * Currently there is only one service_connection per service. @@ -114,7 +110,7 @@ service_free(struct service *service) { struct service_connection *sconn; - PJDLOG_ASSERT(service->s_magic == SERVICE_MAGIC); + assert(service->s_magic == SERVICE_MAGIC); service->s_magic = 0; while ((sconn = service_connection_first(service)) != NULL) @@ -130,17 +126,14 @@ service_connection_add(struct service *service, int sock, struct service_connection *sconn; int serrno; - PJDLOG_ASSERT(service->s_magic == SERVICE_MAGIC); + assert(service->s_magic == SERVICE_MAGIC); sconn = malloc(sizeof(*sconn)); - if (sconn == NULL) { - pjdlog_error("Unable to allocate memory for service connection."); + if (sconn == NULL) return (NULL); - } sconn->sc_chan = cap_wrap(sock); if (sconn->sc_chan == NULL) { serrno = errno; - pjdlog_error("Unable to wrap communication channel."); free(sconn); errno = serrno; return (NULL); @@ -151,7 +144,6 @@ service_connection_add(struct service *service, int sock, sconn->sc_limits = nvlist_clone(limits); if (sconn->sc_limits == NULL) { serrno = errno; - pjdlog_error("Unable to clone limits."); (void)cap_unwrap(sconn->sc_chan); free(sconn); errno = serrno; @@ -168,8 +160,8 @@ service_connection_remove(struct service *service, struct service_connection *sconn) { - PJDLOG_ASSERT(service->s_magic == SERVICE_MAGIC); - PJDLOG_ASSERT(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); + assert(service->s_magic == SERVICE_MAGIC); + assert(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); TAILQ_REMOVE(&service->s_connections, sconn, sc_next); sconn->sc_magic = 0; @@ -206,10 +198,10 @@ service_connection_first(struct service *service) { struct service_connection *sconn; - PJDLOG_ASSERT(service->s_magic == SERVICE_MAGIC); + assert(service->s_magic == SERVICE_MAGIC); sconn = TAILQ_FIRST(&service->s_connections); - PJDLOG_ASSERT(sconn == NULL || + assert(sconn == NULL || sconn->sc_magic == SERVICE_CONNECTION_MAGIC); return (sconn); } @@ -218,10 +210,10 @@ struct service_connection * service_connection_next(struct service_connection *sconn) { - PJDLOG_ASSERT(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); + assert(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); sconn = TAILQ_NEXT(sconn, sc_next); - PJDLOG_ASSERT(sconn == NULL || + assert(sconn == NULL || sconn->sc_magic == SERVICE_CONNECTION_MAGIC); return (sconn); } @@ -230,7 +222,7 @@ cap_channel_t * service_connection_get_chan(const struct service_connection *sconn) { - PJDLOG_ASSERT(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); + assert(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); return (sconn->sc_chan); } @@ -239,7 +231,7 @@ int service_connection_get_sock(const struct service_connection *sconn) { - PJDLOG_ASSERT(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); + assert(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); return (cap_sock(sconn->sc_chan)); } @@ -248,7 +240,7 @@ const nvlist_t * service_connection_get_limits(const struct service_connection *sconn) { - PJDLOG_ASSERT(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); + assert(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); return (sconn->sc_limits); } @@ -258,38 +250,12 @@ service_connection_set_limits(struct service_connection *sconn, nvlist_t *limits) { - PJDLOG_ASSERT(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); + assert(sconn->sc_magic == SERVICE_CONNECTION_MAGIC); nvlist_destroy(sconn->sc_limits); sconn->sc_limits = limits; } -#if 0 -static void -casper_message_connection(struct service *service, const nvlist_t *nvl) -{ - - service_connection_add(&service->s_connections, - nvlist_get_descriptor(nvl, "sock")); -} - -static void -casper_message(const cap_channel_t *capcas, struct service *service) -{ - const char *cmd; - nvlist_t *nvl; - - nvl = cap_recv_nvlist(capcas, 0); - if (nvl == NULL) - pjdlog_exit(1, "Unable to receive message from Casper"); - cmd = nvlist_get_string(nvl, "cmd"); - if (strcmp(cmd, "connection") == 0) - casper_message_connection(service, nvl); - else - PJDLOG_ABORT("Unknown command from Casper: %s.", cmd); -} -#endif - void service_message(struct service *service, struct service_connection *sconn) { @@ -299,12 +265,6 @@ service_message(struct service *service, struct service_connection *sconn) nvlin = cap_recv_nvlist(service_connection_get_chan(sconn), 0); if (nvlin == NULL) { - if (errno == ENOTCONN) { - pjdlog_debug(1, "Connection closed by the client."); - } else { - pjdlog_errno(LOG_ERR, - "Unable to receive message from client"); - } service_connection_remove(service, sconn); return; } @@ -313,15 +273,16 @@ service_message(struct service *service, struct service_connection *sconn) nvlout = nvlist_create(0); cmd = nvlist_get_string(nvlin, "cmd"); - pjdlog_debug(1, "Command received from client: %s.", cmd); - if (pjdlog_debug_get() >= 2) - nvlist_fdump(nvlin, stderr); if (strcmp(cmd, "limit_set") == 0) { nvlist_t *nvllim; nvllim = nvlist_take_nvlist(nvlin, "limits"); - error = service->s_limit(service_connection_get_limits(sconn), - nvllim); + if (service->s_limit == NULL) { + error = EOPNOTSUPP; + } else { + error = service->s_limit( + service_connection_get_limits(sconn), nvllim); + } if (error == 0) { service_connection_set_limits(sconn, nvllim); /* Function consumes nvllim. */ @@ -354,14 +315,9 @@ service_message(struct service *service, struct service_connection *sconn) nvlist_destroy(nvlin); nvlist_add_number(nvlout, "error", (uint64_t)error); - pjdlog_debug(1, "Sending reply to client (error=%d).", error); - if (pjdlog_debug_get() >= 2) - nvlist_fdump(nvlout, stderr); - if (cap_send_nvlist(service_connection_get_chan(sconn), nvlout) == -1) { - pjdlog_errno(LOG_ERR, "Unable to send message to client"); + if (cap_send_nvlist(service_connection_get_chan(sconn), nvlout) == -1) service_connection_remove(service, sconn); - } nvlist_destroy(nvlout); } @@ -374,28 +330,26 @@ fd_add(fd_set *fdsp, int maxfd, int fd) return (fd > maxfd ? fd : maxfd); } -int -service_start(const char *name, int sock, service_limit_func_t *limitfunc, - service_command_func_t *commandfunc, int argc, char *argv[]) +const char * +service_name(struct service *service) +{ + + assert(service->s_magic == SERVICE_MAGIC); + return (service->s_name); +} + +void +service_start(struct service *service, int sock) { - struct service *service; struct service_connection *sconn, *sconntmp; fd_set fds; - int maxfd, nfds, serrno; + int maxfd, nfds; - assert(argc == 2); - - pjdlog_init(PJDLOG_MODE_STD); - pjdlog_debug_set(atoi(argv[1])); - - service = service_alloc(name, limitfunc, commandfunc); - if (service == NULL) - return (errno); - if (service_connection_add(service, sock, NULL) == NULL) { - serrno = errno; - service_free(service); - return (serrno); - } + assert(service != NULL); + assert(service->s_magic == SERVICE_MAGIC); + setproctitle("%s", service->s_name); + if (service_connection_add(service, sock, NULL) == NULL) + exit(1); for (;;) { FD_ZERO(&fds); @@ -406,17 +360,16 @@ service_start(const char *name, int sock, service_limit_func_t *limitfunc, service_connection_get_sock(sconn)); } - PJDLOG_ASSERT(maxfd >= 0); - PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); + assert(maxfd >= 0); + assert(maxfd + 1 <= (int)FD_SETSIZE); nfds = select(maxfd + 1, &fds, NULL, NULL, NULL); if (nfds < 0) { if (errno != EINTR) - pjdlog_errno(LOG_ERR, "select() failed"); + exit(1); continue; } else if (nfds == 0) { /* Timeout. */ - PJDLOG_ABORT("select() timeout"); - continue; + abort(); } for (sconn = service_connection_first(service); sconn != NULL; @@ -437,5 +390,5 @@ service_start(const char *name, int sock, service_limit_func_t *limitfunc, } } - return (0); + exit(0); } diff --git a/sbin/casperd/zygote.c b/lib/libcasper/libcasper/zygote.c similarity index 97% rename from sbin/casperd/zygote.c rename to lib/libcasper/libcasper/zygote.c index 5bc9396a5afc..e554a3eee761 100644 --- a/sbin/casperd/zygote.c +++ b/lib/libcasper/libcasper/zygote.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -45,10 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include - #include "zygote.h" /* Zygote info. */ @@ -126,8 +123,7 @@ zygote_main(int sock) setproctitle("zygote"); - if (pjdlog_mode_get() != PJDLOG_MODE_STD) - stdnull(); + stdnull(); for (fd = STDERR_FILENO + 1; fd < sock; fd++) close(fd); closefrom(sock + 1); @@ -136,7 +132,7 @@ zygote_main(int sock) nvlin = nvlist_recv(sock, 0); if (nvlin == NULL) { if (errno == ENOTCONN) { - /* Casperd exited. */ + /* Casper exited. */ exit(0); } continue; diff --git a/sbin/casperd/zygote.h b/lib/libcasper/libcasper/zygote.h similarity index 91% rename from sbin/casperd/zygote.h rename to lib/libcasper/libcasper/zygote.h index 4c9c7717fec1..e147287e1dbc 100644 --- a/sbin/casperd/zygote.h +++ b/lib/libcasper/libcasper/zygote.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -34,7 +35,7 @@ typedef void zygote_func_t(int); -int zygote_init(void); -int zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp); +int zygote_init(void); +int zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp); #endif /* !_ZYGOTE_H_ */ diff --git a/lib/libcasper/services/Makefile b/lib/libcasper/services/Makefile new file mode 100644 index 000000000000..39b79af6885e --- /dev/null +++ b/lib/libcasper/services/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +SUBDIR= cap_dns +SUBDIR+= cap_grp +SUBDIR+= cap_pwd +SUBDIR+= cap_random +SUBDIR+= cap_sysctl + +.include diff --git a/lib/libcasper/services/cap_dns/Makefile b/lib/libcasper/services/cap_dns/Makefile new file mode 100644 index 000000000000..871975d3b098 --- /dev/null +++ b/lib/libcasper/services/cap_dns/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +LIB= cap_dns + +SHLIB_MAJOR= 0 +SHLIBDIR?= /lib/casper +INCSDIR?= ${INCLUDEDIR}/casper + +SRCS= cap_dns.c + +INCS= cap_dns.h + +LIBADD= nv + +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../libcasper + +WARNS?= 6 + +.include diff --git a/libexec/casper/dns/dns.c b/lib/libcasper/services/cap_dns/cap_dns.c similarity index 54% rename from libexec/casper/dns/dns.c rename to lib/libcasper/services/cap_dns/cap_dns.c index dbdb2a27d83b..873af4cdcdde 100644 --- a/libexec/casper/dns/dns.c +++ b/lib/libcasper/services/cap_dns/cap_dns.c @@ -30,6 +30,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include @@ -38,12 +39,341 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include -#include -#include #include -#include +#include +#include "cap_dns.h" + +static struct hostent hent; + +static void +hostent_free(struct hostent *hp) +{ + unsigned int ii; + + free(hp->h_name); + hp->h_name = NULL; + if (hp->h_aliases != NULL) { + for (ii = 0; hp->h_aliases[ii] != NULL; ii++) + free(hp->h_aliases[ii]); + free(hp->h_aliases); + hp->h_aliases = NULL; + } + if (hp->h_addr_list != NULL) { + for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) + free(hp->h_addr_list[ii]); + free(hp->h_addr_list); + hp->h_addr_list = NULL; + } +} + +static struct hostent * +hostent_unpack(const nvlist_t *nvl, struct hostent *hp) +{ + unsigned int ii, nitems; + char nvlname[64]; + int n; + + hostent_free(hp); + + hp->h_name = strdup(nvlist_get_string(nvl, "name")); + if (hp->h_name == NULL) + goto fail; + hp->h_addrtype = (int)nvlist_get_number(nvl, "addrtype"); + hp->h_length = (int)nvlist_get_number(nvl, "length"); + + nitems = (unsigned int)nvlist_get_number(nvl, "naliases"); + hp->h_aliases = calloc(sizeof(hp->h_aliases[0]), nitems + 1); + if (hp->h_aliases == NULL) + goto fail; + for (ii = 0; ii < nitems; ii++) { + n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii); + assert(n > 0 && n < (int)sizeof(nvlname)); + hp->h_aliases[ii] = + strdup(nvlist_get_string(nvl, nvlname)); + if (hp->h_aliases[ii] == NULL) + goto fail; + } + hp->h_aliases[ii] = NULL; + + nitems = (unsigned int)nvlist_get_number(nvl, "naddrs"); + hp->h_addr_list = calloc(sizeof(hp->h_addr_list[0]), nitems + 1); + if (hp->h_addr_list == NULL) + goto fail; + for (ii = 0; ii < nitems; ii++) { + hp->h_addr_list[ii] = malloc(hp->h_length); + if (hp->h_addr_list[ii] == NULL) + goto fail; + n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii); + assert(n > 0 && n < (int)sizeof(nvlname)); + bcopy(nvlist_get_binary(nvl, nvlname, NULL), + hp->h_addr_list[ii], hp->h_length); + } + hp->h_addr_list[ii] = NULL; + + return (hp); +fail: + hostent_free(hp); + h_errno = NO_RECOVERY; + return (NULL); +} + +struct hostent * +cap_gethostbyname(cap_channel_t *chan, const char *name) +{ + + return (cap_gethostbyname2(chan, name, AF_INET)); +} + +struct hostent * +cap_gethostbyname2(cap_channel_t *chan, const char *name, int type) +{ + struct hostent *hp; + nvlist_t *nvl; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "gethostbyname"); + nvlist_add_number(nvl, "family", (uint64_t)type); + nvlist_add_string(nvl, "name", name); + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) { + h_errno = NO_RECOVERY; + return (NULL); + } + if (nvlist_get_number(nvl, "error") != 0) { + h_errno = (int)nvlist_get_number(nvl, "error"); + nvlist_destroy(nvl); + return (NULL); + } + + hp = hostent_unpack(nvl, &hent); + nvlist_destroy(nvl); + return (hp); +} + +struct hostent * +cap_gethostbyaddr(cap_channel_t *chan, const void *addr, socklen_t len, + int type) +{ + struct hostent *hp; + nvlist_t *nvl; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "gethostbyaddr"); + nvlist_add_binary(nvl, "addr", addr, (size_t)len); + nvlist_add_number(nvl, "family", (uint64_t)type); + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) { + h_errno = NO_RECOVERY; + return (NULL); + } + if (nvlist_get_number(nvl, "error") != 0) { + h_errno = (int)nvlist_get_number(nvl, "error"); + nvlist_destroy(nvl); + return (NULL); + } + hp = hostent_unpack(nvl, &hent); + nvlist_destroy(nvl); + return (hp); +} + +static struct addrinfo * +addrinfo_unpack(const nvlist_t *nvl) +{ + struct addrinfo *ai; + const void *addr; + size_t addrlen; + const char *canonname; + + addr = nvlist_get_binary(nvl, "ai_addr", &addrlen); + ai = malloc(sizeof(*ai) + addrlen); + if (ai == NULL) + return (NULL); + ai->ai_flags = (int)nvlist_get_number(nvl, "ai_flags"); + ai->ai_family = (int)nvlist_get_number(nvl, "ai_family"); + ai->ai_socktype = (int)nvlist_get_number(nvl, "ai_socktype"); + ai->ai_protocol = (int)nvlist_get_number(nvl, "ai_protocol"); + ai->ai_addrlen = (socklen_t)addrlen; + canonname = dnvlist_get_string(nvl, "ai_canonname", NULL); + if (canonname != NULL) { + ai->ai_canonname = strdup(canonname); + if (ai->ai_canonname == NULL) { + free(ai); + return (NULL); + } + } else { + ai->ai_canonname = NULL; + } + ai->ai_addr = (void *)(ai + 1); + bcopy(addr, ai->ai_addr, addrlen); + ai->ai_next = NULL; + + return (ai); +} + +int +cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct addrinfo *firstai, *prevai, *curai; + unsigned int ii; + const nvlist_t *nvlai; + char nvlname[64]; + nvlist_t *nvl; + int error, n; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "getaddrinfo"); + if (hostname != NULL) + nvlist_add_string(nvl, "hostname", hostname); + if (servname != NULL) + nvlist_add_string(nvl, "servname", servname); + if (hints != NULL) { + nvlist_add_number(nvl, "hints.ai_flags", + (uint64_t)hints->ai_flags); + nvlist_add_number(nvl, "hints.ai_family", + (uint64_t)hints->ai_family); + nvlist_add_number(nvl, "hints.ai_socktype", + (uint64_t)hints->ai_socktype); + nvlist_add_number(nvl, "hints.ai_protocol", + (uint64_t)hints->ai_protocol); + } + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) + return (EAI_MEMORY); + if (nvlist_get_number(nvl, "error") != 0) { + error = (int)nvlist_get_number(nvl, "error"); + nvlist_destroy(nvl); + return (error); + } + + nvlai = NULL; + firstai = prevai = curai = NULL; + for (ii = 0; ; ii++) { + n = snprintf(nvlname, sizeof(nvlname), "res%u", ii); + assert(n > 0 && n < (int)sizeof(nvlname)); + if (!nvlist_exists_nvlist(nvl, nvlname)) + break; + nvlai = nvlist_get_nvlist(nvl, nvlname); + curai = addrinfo_unpack(nvlai); + if (curai == NULL) + break; + if (prevai != NULL) + prevai->ai_next = curai; + else if (firstai == NULL) + firstai = curai; + prevai = curai; + } + nvlist_destroy(nvl); + if (curai == NULL && nvlai != NULL) { + if (firstai == NULL) + freeaddrinfo(firstai); + return (EAI_MEMORY); + } + + *res = firstai; + return (0); +} + +int +cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, int flags) +{ + nvlist_t *nvl; + int error; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "getnameinfo"); + nvlist_add_number(nvl, "hostlen", (uint64_t)hostlen); + nvlist_add_number(nvl, "servlen", (uint64_t)servlen); + nvlist_add_binary(nvl, "sa", sa, (size_t)salen); + nvlist_add_number(nvl, "flags", (uint64_t)flags); + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) + return (EAI_MEMORY); + if (nvlist_get_number(nvl, "error") != 0) { + error = (int)nvlist_get_number(nvl, "error"); + nvlist_destroy(nvl); + return (error); + } + + if (host != NULL && nvlist_exists_string(nvl, "host")) + strlcpy(host, nvlist_get_string(nvl, "host"), hostlen + 1); + if (serv != NULL && nvlist_exists_string(nvl, "serv")) + strlcpy(serv, nvlist_get_string(nvl, "serv"), servlen + 1); + nvlist_destroy(nvl); + return (0); +} + +static void +limit_remove(nvlist_t *limits, const char *prefix) +{ + const char *name; + size_t prefixlen; + void *cookie; + + prefixlen = strlen(prefix); +again: + cookie = NULL; + while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) { + if (strncmp(name, prefix, prefixlen) == 0) { + nvlist_free(limits, name); + goto again; + } + } +} + +int +cap_dns_type_limit(cap_channel_t *chan, const char * const *types, + size_t ntypes) +{ + nvlist_t *limits; + unsigned int i; + char nvlname[64]; + int n; + + if (cap_limit_get(chan, &limits) < 0) + return (-1); + if (limits == NULL) + limits = nvlist_create(0); + else + limit_remove(limits, "type"); + for (i = 0; i < ntypes; i++) { + n = snprintf(nvlname, sizeof(nvlname), "type%u", i); + assert(n > 0 && n < (int)sizeof(nvlname)); + nvlist_add_string(limits, nvlname, types[i]); + } + return (cap_limit_set(chan, limits)); +} + +int +cap_dns_family_limit(cap_channel_t *chan, const int *families, + size_t nfamilies) +{ + nvlist_t *limits; + unsigned int i; + char nvlname[64]; + int n; + + if (cap_limit_get(chan, &limits) < 0) + return (-1); + if (limits == NULL) + limits = nvlist_create(0); + else + limit_remove(limits, "family"); + for (i = 0; i < nfamilies; i++) { + n = snprintf(nvlname, sizeof(nvlname), "family%u", i); + assert(n > 0 && n < (int)sizeof(nvlname)); + nvlist_add_number(limits, nvlname, (uint64_t)families[i]); + } + return (cap_limit_set(chan, limits)); +} + +/* + * Service functions. + */ static bool dns_allowed_type(const nvlist_t *limits, const char *type) { @@ -246,8 +576,10 @@ dns_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) if (error != 0) goto out; - nvlist_move_string(nvlout, "host", host); - nvlist_move_string(nvlout, "serv", serv); + if (host != NULL) + nvlist_move_string(nvlout, "host", host); + if (serv != NULL) + nvlist_move_string(nvlout, "serv", serv); out: if (error != 0) { free(host); @@ -267,7 +599,8 @@ addrinfo_pack(const struct addrinfo *ai) nvlist_add_number(nvl, "ai_socktype", (uint64_t)ai->ai_socktype); nvlist_add_number(nvl, "ai_protocol", (uint64_t)ai->ai_protocol); nvlist_add_binary(nvl, "ai_addr", ai->ai_addr, (size_t)ai->ai_addrlen); - nvlist_add_string(nvl, "ai_canonname", ai->ai_canonname); + if (ai->ai_canonname != NULL) + nvlist_add_string(nvl, "ai_canonname", ai->ai_canonname); return (nvl); } @@ -285,11 +618,9 @@ dns_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) if (!dns_allowed_type(limits, "ADDR")) return (NO_RECOVERY); - hostname = nvlist_get_string(nvlin, "hostname"); - servname = nvlist_get_string(nvlin, "servname"); + hostname = dnvlist_get_string(nvlin, "hostname", NULL); + servname = dnvlist_get_string(nvlin, "servname", NULL); if (nvlist_exists_number(nvlin, "hints.ai_flags")) { - size_t addrlen; - hints.ai_flags = (int)nvlist_get_number(nvlin, "hints.ai_flags"); hints.ai_family = (int)nvlist_get_number(nvlin, @@ -427,10 +758,4 @@ dns_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, return (error); } -int -main(int argc, char *argv[]) -{ - - return (service_start("system.dns", PARENT_FILENO, dns_limit, - dns_command, argc, argv)); -} +CREATE_SERVICE("system.dns", dns_limit, dns_command); diff --git a/lib/libcapsicum/libcapsicum_dns.h b/lib/libcasper/services/cap_dns/cap_dns.h similarity index 96% rename from lib/libcapsicum/libcapsicum_dns.h rename to lib/libcasper/services/cap_dns/cap_dns.h index 02235107cec4..ea3754255286 100644 --- a/lib/libcapsicum/libcapsicum_dns.h +++ b/lib/libcasper/services/cap_dns/cap_dns.h @@ -29,8 +29,8 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_DNS_H_ -#define _LIBCAPSICUM_DNS_H_ +#ifndef _CAP_DNS_H_ +#define _CAP_DNS_H_ #include /* socklen_t */ @@ -54,4 +54,4 @@ int cap_dns_type_limit(cap_channel_t *chan, const char * const *types, int cap_dns_family_limit(cap_channel_t *chan, const int *families, size_t nfamilies); -#endif /* !_LIBCAPSICUM_DNS_H_ */ +#endif /* !_CAP_DNS_H_ */ diff --git a/lib/libcasper/services/cap_grp/Makefile b/lib/libcasper/services/cap_grp/Makefile new file mode 100644 index 000000000000..81b94771e05e --- /dev/null +++ b/lib/libcasper/services/cap_grp/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +LIB= cap_grp + +SHLIB_MAJOR= 0 +SHLIBDIR?= /lib/casper +INCSDIR?= ${INCLUDEDIR}/casper + +SRCS= cap_grp.c + +INCS= cap_grp.h + +LIBADD= nv + +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../libcasper + +WARNS?= 6 + +.include diff --git a/lib/libcapsicum/libcapsicum_grp.c b/lib/libcasper/services/cap_grp/cap_grp.c similarity index 57% rename from lib/libcapsicum/libcapsicum_grp.c rename to lib/libcasper/services/cap_grp/cap_grp.c index 44d573e77b82..d358cea95882 100644 --- a/lib/libcapsicum/libcapsicum_grp.c +++ b/lib/libcasper/services/cap_grp/cap_grp.c @@ -39,10 +39,11 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include "libcapsicum.h" -#include "libcapsicum_grp.h" +#include +#include + +#include "cap_grp.h" static struct group ggrp; static char *gbuffer; @@ -436,3 +437,351 @@ cap_grp_limit_groups(cap_channel_t *chan, const char * const *names, nvlist_move_nvlist(limits, "groups", groups); return (cap_limit_set(chan, limits)); } + +/* + * Service functions. + */ +static bool +grp_allowed_cmd(const nvlist_t *limits, const char *cmd) +{ + + if (limits == NULL) + return (true); + + /* + * If no limit was set on allowed commands, then all commands + * are allowed. + */ + if (!nvlist_exists_nvlist(limits, "cmds")) + return (true); + + limits = nvlist_get_nvlist(limits, "cmds"); + return (nvlist_exists_null(limits, cmd)); +} + +static int +grp_allowed_cmds(const nvlist_t *oldlimits, const nvlist_t *newlimits) +{ + const char *name; + void *cookie; + int type; + + cookie = NULL; + while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { + if (type != NV_TYPE_NULL) + return (EINVAL); + if (!grp_allowed_cmd(oldlimits, name)) + return (ENOTCAPABLE); + } + + return (0); +} + +static bool +grp_allowed_group(const nvlist_t *limits, const char *gname, gid_t gid) +{ + const char *name; + void *cookie; + int type; + + if (limits == NULL) + return (true); + + /* + * If no limit was set on allowed groups, then all groups are allowed. + */ + if (!nvlist_exists_nvlist(limits, "groups")) + return (true); + + limits = nvlist_get_nvlist(limits, "groups"); + cookie = NULL; + while ((name = nvlist_next(limits, &type, &cookie)) != NULL) { + switch (type) { + case NV_TYPE_NUMBER: + if (gid != (gid_t)-1 && + nvlist_get_number(limits, name) == (uint64_t)gid) { + return (true); + } + break; + case NV_TYPE_STRING: + if (gname != NULL && + strcmp(nvlist_get_string(limits, name), + gname) == 0) { + return (true); + } + break; + default: + abort(); + } + } + + return (false); +} + +static int +grp_allowed_groups(const nvlist_t *oldlimits, const nvlist_t *newlimits) +{ + const char *name, *gname; + void *cookie; + gid_t gid; + int type; + + cookie = NULL; + while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { + switch (type) { + case NV_TYPE_NUMBER: + gid = (gid_t)nvlist_get_number(newlimits, name); + gname = NULL; + break; + case NV_TYPE_STRING: + gid = (gid_t)-1; + gname = nvlist_get_string(newlimits, name); + break; + default: + return (EINVAL); + } + if (!grp_allowed_group(oldlimits, gname, gid)) + return (ENOTCAPABLE); + } + + return (0); +} + +static bool +grp_allowed_field(const nvlist_t *limits, const char *field) +{ + + if (limits == NULL) + return (true); + + /* + * If no limit was set on allowed fields, then all fields are allowed. + */ + if (!nvlist_exists_nvlist(limits, "fields")) + return (true); + + limits = nvlist_get_nvlist(limits, "fields"); + return (nvlist_exists_null(limits, field)); +} + +static int +grp_allowed_fields(const nvlist_t *oldlimits, const nvlist_t *newlimits) +{ + const char *name; + void *cookie; + int type; + + cookie = NULL; + while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { + if (type != NV_TYPE_NULL) + return (EINVAL); + if (!grp_allowed_field(oldlimits, name)) + return (ENOTCAPABLE); + } + + return (0); +} + +static bool +grp_pack(const nvlist_t *limits, const struct group *grp, nvlist_t *nvl) +{ + char nvlname[64]; + int n; + + if (grp == NULL) + return (true); + + /* + * If either name or GID is allowed, we allow it. + */ + if (!grp_allowed_group(limits, grp->gr_name, grp->gr_gid)) + return (false); + + if (grp_allowed_field(limits, "gr_name")) + nvlist_add_string(nvl, "gr_name", grp->gr_name); + else + nvlist_add_string(nvl, "gr_name", ""); + if (grp_allowed_field(limits, "gr_passwd")) + nvlist_add_string(nvl, "gr_passwd", grp->gr_passwd); + else + nvlist_add_string(nvl, "gr_passwd", ""); + if (grp_allowed_field(limits, "gr_gid")) + nvlist_add_number(nvl, "gr_gid", (uint64_t)grp->gr_gid); + else + nvlist_add_number(nvl, "gr_gid", (uint64_t)-1); + if (grp_allowed_field(limits, "gr_mem") && grp->gr_mem[0] != NULL) { + unsigned int ngroups; + + for (ngroups = 0; grp->gr_mem[ngroups] != NULL; ngroups++) { + n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", + ngroups); + assert(n > 0 && n < (ssize_t)sizeof(nvlname)); + nvlist_add_string(nvl, nvlname, grp->gr_mem[ngroups]); + } + nvlist_add_number(nvl, "gr_nmem", (uint64_t)ngroups); + } + + return (true); +} + +static int +grp_getgrent(const nvlist_t *limits, const nvlist_t *nvlin __unused, + nvlist_t *nvlout) +{ + struct group *grp; + + for (;;) { + errno = 0; + grp = getgrent(); + if (errno != 0) + return (errno); + if (grp_pack(limits, grp, nvlout)) + return (0); + } + + /* NOTREACHED */ +} + +static int +grp_getgrnam(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) +{ + struct group *grp; + const char *name; + + if (!nvlist_exists_string(nvlin, "name")) + return (EINVAL); + name = nvlist_get_string(nvlin, "name"); + assert(name != NULL); + + errno = 0; + grp = getgrnam(name); + if (errno != 0) + return (errno); + + (void)grp_pack(limits, grp, nvlout); + + return (0); +} + +static int +grp_getgrgid(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) +{ + struct group *grp; + gid_t gid; + + if (!nvlist_exists_number(nvlin, "gid")) + return (EINVAL); + + gid = (gid_t)nvlist_get_number(nvlin, "gid"); + + errno = 0; + grp = getgrgid(gid); + if (errno != 0) + return (errno); + + (void)grp_pack(limits, grp, nvlout); + + return (0); +} + +static int +grp_setgroupent(const nvlist_t *limits __unused, const nvlist_t *nvlin, + nvlist_t *nvlout __unused) +{ + int stayopen; + + if (!nvlist_exists_bool(nvlin, "stayopen")) + return (EINVAL); + + stayopen = nvlist_get_bool(nvlin, "stayopen") ? 1 : 0; + + return (setgroupent(stayopen) == 0 ? EFAULT : 0); +} + +static int +grp_setgrent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, + nvlist_t *nvlout __unused) +{ + + return (setgrent() == 0 ? EFAULT : 0); +} + +static int +grp_endgrent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, + nvlist_t *nvlout __unused) +{ + + endgrent(); + + return (0); +} + +static int +grp_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) +{ + const nvlist_t *limits; + const char *name; + void *cookie; + int error, type; + + if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "cmds") && + !nvlist_exists_nvlist(newlimits, "cmds")) { + return (ENOTCAPABLE); + } + if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "fields") && + !nvlist_exists_nvlist(newlimits, "fields")) { + return (ENOTCAPABLE); + } + if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "groups") && + !nvlist_exists_nvlist(newlimits, "groups")) { + return (ENOTCAPABLE); + } + + cookie = NULL; + while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { + if (type != NV_TYPE_NVLIST) + return (EINVAL); + limits = nvlist_get_nvlist(newlimits, name); + if (strcmp(name, "cmds") == 0) + error = grp_allowed_cmds(oldlimits, limits); + else if (strcmp(name, "fields") == 0) + error = grp_allowed_fields(oldlimits, limits); + else if (strcmp(name, "groups") == 0) + error = grp_allowed_groups(oldlimits, limits); + else + error = EINVAL; + if (error != 0) + return (error); + } + + return (0); +} + +static int +grp_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, + nvlist_t *nvlout) +{ + int error; + + if (!grp_allowed_cmd(limits, cmd)) + return (ENOTCAPABLE); + + if (strcmp(cmd, "getgrent") == 0 || strcmp(cmd, "getgrent_r") == 0) + error = grp_getgrent(limits, nvlin, nvlout); + else if (strcmp(cmd, "getgrnam") == 0 || strcmp(cmd, "getgrnam_r") == 0) + error = grp_getgrnam(limits, nvlin, nvlout); + else if (strcmp(cmd, "getgrgid") == 0 || strcmp(cmd, "getgrgid_r") == 0) + error = grp_getgrgid(limits, nvlin, nvlout); + else if (strcmp(cmd, "setgroupent") == 0) + error = grp_setgroupent(limits, nvlin, nvlout); + else if (strcmp(cmd, "setgrent") == 0) + error = grp_setgrent(limits, nvlin, nvlout); + else if (strcmp(cmd, "endgrent") == 0) + error = grp_endgrent(limits, nvlin, nvlout); + else + error = EINVAL; + + return (error); +} + +CREATE_SERVICE("system.grp", grp_limit, grp_command); diff --git a/lib/libcapsicum/libcapsicum_grp.h b/lib/libcasper/services/cap_grp/cap_grp.h similarity index 96% rename from lib/libcapsicum/libcapsicum_grp.h rename to lib/libcasper/services/cap_grp/cap_grp.h index e0b44f0e1996..68595c145e23 100644 --- a/lib/libcapsicum/libcapsicum_grp.h +++ b/lib/libcasper/services/cap_grp/cap_grp.h @@ -29,8 +29,8 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_GRP_H_ -#define _LIBCAPSICUM_GRP_H_ +#ifndef _CAP_GRP_H_ +#define _CAP_GRP_H_ struct group *cap_getgrent(cap_channel_t *chan); struct group *cap_getgrnam(cap_channel_t *chan, const char *name); @@ -54,4 +54,4 @@ int cap_grp_limit_fields(cap_channel_t *chan, const char * const *fields, int cap_grp_limit_groups(cap_channel_t *chan, const char * const *names, size_t nnames, gid_t *gids, size_t ngids); -#endif /* !_LIBCAPSICUM_GRP_H_ */ +#endif /* !_CAP_GRP_H_ */ diff --git a/lib/libcasper/services/cap_pwd/Makefile b/lib/libcasper/services/cap_pwd/Makefile new file mode 100644 index 000000000000..34b8a1205a99 --- /dev/null +++ b/lib/libcasper/services/cap_pwd/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +LIB= cap_pwd + +SHLIB_MAJOR= 0 +SHLIBDIR?= /lib/casper +INCSDIR?= ${INCLUDEDIR}/casper + +SRCS= cap_pwd.c + +INCS= cap_pwd.h + +LIBADD= nv + +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../libcasper + +WARNS?= 6 + +.include diff --git a/libexec/casper/pwd/pwd.c b/lib/libcasper/services/cap_pwd/cap_pwd.c similarity index 54% rename from libexec/casper/pwd/pwd.c rename to lib/libcasper/services/cap_pwd/cap_pwd.c index 0a06c5f6bfd7..254e2441426b 100644 --- a/libexec/casper/pwd/pwd.c +++ b/lib/libcasper/services/cap_pwd/cap_pwd.c @@ -30,17 +30,372 @@ #include __FBSDID("$FreeBSD$"); +#include #include +#include #include #include #include #include +#include -#include #include -#include +#include +#include "cap_pwd.h" + +static struct passwd gpwd; +static char *gbuffer; +static size_t gbufsize; + +static int +passwd_resize(void) +{ + char *buf; + + if (gbufsize == 0) + gbufsize = 1024; + else + gbufsize *= 2; + + buf = gbuffer; + gbuffer = realloc(buf, gbufsize); + if (gbuffer == NULL) { + free(buf); + gbufsize = 0; + return (ENOMEM); + } + memset(gbuffer, 0, gbufsize); + + return (0); +} + +static int +passwd_unpack_string(const nvlist_t *nvl, const char *fieldname, char **fieldp, + char **bufferp, size_t *bufsizep) +{ + const char *str; + size_t len; + + str = nvlist_get_string(nvl, fieldname); + len = strlcpy(*bufferp, str, *bufsizep); + if (len >= *bufsizep) + return (ERANGE); + *fieldp = *bufferp; + *bufferp += len + 1; + *bufsizep -= len + 1; + + return (0); +} + +static int +passwd_unpack(const nvlist_t *nvl, struct passwd *pwd, char *buffer, + size_t bufsize) +{ + int error; + + if (!nvlist_exists_string(nvl, "pw_name")) + return (EINVAL); + + memset(pwd, 0, sizeof(*pwd)); + + error = passwd_unpack_string(nvl, "pw_name", &pwd->pw_name, &buffer, + &bufsize); + if (error != 0) + return (error); + pwd->pw_uid = (uid_t)nvlist_get_number(nvl, "pw_uid"); + pwd->pw_gid = (gid_t)nvlist_get_number(nvl, "pw_gid"); + pwd->pw_change = (time_t)nvlist_get_number(nvl, "pw_change"); + error = passwd_unpack_string(nvl, "pw_passwd", &pwd->pw_passwd, &buffer, + &bufsize); + if (error != 0) + return (error); + error = passwd_unpack_string(nvl, "pw_class", &pwd->pw_class, &buffer, + &bufsize); + if (error != 0) + return (error); + error = passwd_unpack_string(nvl, "pw_gecos", &pwd->pw_gecos, &buffer, + &bufsize); + if (error != 0) + return (error); + error = passwd_unpack_string(nvl, "pw_dir", &pwd->pw_dir, &buffer, + &bufsize); + if (error != 0) + return (error); + error = passwd_unpack_string(nvl, "pw_shell", &pwd->pw_shell, &buffer, + &bufsize); + if (error != 0) + return (error); + pwd->pw_expire = (time_t)nvlist_get_number(nvl, "pw_expire"); + pwd->pw_fields = (int)nvlist_get_number(nvl, "pw_fields"); + + return (0); +} + +static int +cap_getpwcommon_r(cap_channel_t *chan, const char *cmd, const char *login, + uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, + struct passwd **result) +{ + nvlist_t *nvl; + bool getpw_r; + int error; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", cmd); + if (strcmp(cmd, "getpwent") == 0 || strcmp(cmd, "getpwent_r") == 0) { + /* Add nothing. */ + } else if (strcmp(cmd, "getpwnam") == 0 || + strcmp(cmd, "getpwnam_r") == 0) { + nvlist_add_string(nvl, "name", login); + } else if (strcmp(cmd, "getpwuid") == 0 || + strcmp(cmd, "getpwuid_r") == 0) { + nvlist_add_number(nvl, "uid", (uint64_t)uid); + } else { + abort(); + } + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) { + assert(errno != 0); + *result = NULL; + return (errno); + } + error = (int)nvlist_get_number(nvl, "error"); + if (error != 0) { + nvlist_destroy(nvl); + *result = NULL; + return (error); + } + + if (!nvlist_exists_string(nvl, "pw_name")) { + /* Not found. */ + nvlist_destroy(nvl); + *result = NULL; + return (0); + } + + getpw_r = (strcmp(cmd, "getpwent_r") == 0 || + strcmp(cmd, "getpwnam_r") == 0 || strcmp(cmd, "getpwuid_r") == 0); + + for (;;) { + error = passwd_unpack(nvl, pwd, buffer, bufsize); + if (getpw_r || error != ERANGE) + break; + assert(buffer == gbuffer); + assert(bufsize == gbufsize); + error = passwd_resize(); + if (error != 0) + break; + /* Update pointers after resize. */ + buffer = gbuffer; + bufsize = gbufsize; + } + + nvlist_destroy(nvl); + + if (error == 0) + *result = pwd; + else + *result = NULL; + + return (error); +} + +static struct passwd * +cap_getpwcommon(cap_channel_t *chan, const char *cmd, const char *login, + uid_t uid) +{ + struct passwd *result; + int error, serrno; + + serrno = errno; + + error = cap_getpwcommon_r(chan, cmd, login, uid, &gpwd, gbuffer, + gbufsize, &result); + if (error != 0) { + errno = error; + return (NULL); + } + + errno = serrno; + + return (result); +} + +struct passwd * +cap_getpwent(cap_channel_t *chan) +{ + + return (cap_getpwcommon(chan, "getpwent", NULL, 0)); +} + +struct passwd * +cap_getpwnam(cap_channel_t *chan, const char *login) +{ + + return (cap_getpwcommon(chan, "getpwnam", login, 0)); +} + +struct passwd * +cap_getpwuid(cap_channel_t *chan, uid_t uid) +{ + + return (cap_getpwcommon(chan, "getpwuid", NULL, uid)); +} + +int +cap_getpwent_r(cap_channel_t *chan, struct passwd *pwd, char *buffer, + size_t bufsize, struct passwd **result) +{ + + return (cap_getpwcommon_r(chan, "getpwent_r", NULL, 0, pwd, buffer, + bufsize, result)); +} + +int +cap_getpwnam_r(cap_channel_t *chan, const char *name, struct passwd *pwd, + char *buffer, size_t bufsize, struct passwd **result) +{ + + return (cap_getpwcommon_r(chan, "getpwnam_r", name, 0, pwd, buffer, + bufsize, result)); +} + +int +cap_getpwuid_r(cap_channel_t *chan, uid_t uid, struct passwd *pwd, char *buffer, + size_t bufsize, struct passwd **result) +{ + + return (cap_getpwcommon_r(chan, "getpwuid_r", NULL, uid, pwd, buffer, + bufsize, result)); +} + +int +cap_setpassent(cap_channel_t *chan, int stayopen) +{ + nvlist_t *nvl; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "setpassent"); + nvlist_add_bool(nvl, "stayopen", stayopen != 0); + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) + return (0); + if (nvlist_get_number(nvl, "error") != 0) { + errno = nvlist_get_number(nvl, "error"); + nvlist_destroy(nvl); + return (0); + } + nvlist_destroy(nvl); + + return (1); +} + +static void +cap_set_end_pwent(cap_channel_t *chan, const char *cmd) +{ + nvlist_t *nvl; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", cmd); + /* Ignore any errors, we have no way to report them. */ + nvlist_destroy(cap_xfer_nvlist(chan, nvl, 0)); +} + +void +cap_setpwent(cap_channel_t *chan) +{ + + cap_set_end_pwent(chan, "setpwent"); +} + +void +cap_endpwent(cap_channel_t *chan) +{ + + cap_set_end_pwent(chan, "endpwent"); +} + +int +cap_pwd_limit_cmds(cap_channel_t *chan, const char * const *cmds, size_t ncmds) +{ + nvlist_t *limits, *nvl; + unsigned int i; + + if (cap_limit_get(chan, &limits) < 0) + return (-1); + if (limits == NULL) { + limits = nvlist_create(0); + } else { + if (nvlist_exists_nvlist(limits, "cmds")) + nvlist_free_nvlist(limits, "cmds"); + } + nvl = nvlist_create(0); + for (i = 0; i < ncmds; i++) + nvlist_add_null(nvl, cmds[i]); + nvlist_move_nvlist(limits, "cmds", nvl); + return (cap_limit_set(chan, limits)); +} + +int +cap_pwd_limit_fields(cap_channel_t *chan, const char * const *fields, + size_t nfields) +{ + nvlist_t *limits, *nvl; + unsigned int i; + + if (cap_limit_get(chan, &limits) < 0) + return (-1); + if (limits == NULL) { + limits = nvlist_create(0); + } else { + if (nvlist_exists_nvlist(limits, "fields")) + nvlist_free_nvlist(limits, "fields"); + } + nvl = nvlist_create(0); + for (i = 0; i < nfields; i++) + nvlist_add_null(nvl, fields[i]); + nvlist_move_nvlist(limits, "fields", nvl); + return (cap_limit_set(chan, limits)); +} + +int +cap_pwd_limit_users(cap_channel_t *chan, const char * const *names, + size_t nnames, uid_t *uids, size_t nuids) +{ + nvlist_t *limits, *users; + char nvlname[64]; + unsigned int i; + int n; + + if (cap_limit_get(chan, &limits) < 0) + return (-1); + if (limits == NULL) { + limits = nvlist_create(0); + } else { + if (nvlist_exists_nvlist(limits, "users")) + nvlist_free_nvlist(limits, "users"); + } + users = nvlist_create(0); + for (i = 0; i < nuids; i++) { + n = snprintf(nvlname, sizeof(nvlname), "uid%u", i); + assert(n > 0 && n < (int)sizeof(nvlname)); + nvlist_add_number(users, nvlname, (uint64_t)uids[i]); + } + for (i = 0; i < nnames; i++) { + n = snprintf(nvlname, sizeof(nvlname), "name%u", i); + assert(n > 0 && n < (int)sizeof(nvlname)); + nvlist_add_string(users, nvlname, names[i]); + } + nvlist_move_nvlist(limits, "users", users); + return (cap_limit_set(chan, limits)); +} + + +/* + * Service functions. + */ static bool pwd_allowed_cmd(const nvlist_t *limits, const char *cmd) { @@ -111,7 +466,7 @@ pwd_allowed_user(const nvlist_t *limits, const char *uname, uid_t uid) } break; default: - PJDLOG_ABORT("Unexpected type %d.", type); + abort(); } } @@ -264,7 +619,8 @@ pwd_pack(const nvlist_t *limits, const struct passwd *pwd, nvlist_t *nvl) } static int -pwd_getpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) +pwd_getpwent(const nvlist_t *limits, const nvlist_t *nvlin __unused, + nvlist_t *nvlout) { struct passwd *pwd; @@ -289,7 +645,7 @@ pwd_getpwnam(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) if (!nvlist_exists_string(nvlin, "name")) return (EINVAL); name = nvlist_get_string(nvlin, "name"); - PJDLOG_ASSERT(name != NULL); + assert(name != NULL); errno = 0; pwd = getpwnam(name); @@ -323,7 +679,8 @@ pwd_getpwuid(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) } static int -pwd_setpassent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) +pwd_setpassent(const nvlist_t *limits __unused, const nvlist_t *nvlin, + nvlist_t *nvlout __unused) { int stayopen; @@ -336,7 +693,8 @@ pwd_setpassent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) } static int -pwd_setpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) +pwd_setpwent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, + nvlist_t *nvlout __unused) { setpwent(); @@ -345,7 +703,8 @@ pwd_setpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) } static int -pwd_endpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) +pwd_endpwent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, + nvlist_t *nvlout __unused) { endpwent(); @@ -421,10 +780,4 @@ pwd_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, return (error); } -int -main(int argc, char *argv[]) -{ - - return (service_start("system.pwd", PARENT_FILENO, pwd_limit, - pwd_command, argc, argv)); -} +CREATE_SERVICE("system.pwd", pwd_limit, pwd_command); diff --git a/lib/libcapsicum/libcapsicum_pwd.h b/lib/libcasper/services/cap_pwd/cap_pwd.h similarity index 96% rename from lib/libcapsicum/libcapsicum_pwd.h rename to lib/libcasper/services/cap_pwd/cap_pwd.h index 960a490faf86..a75fba74f972 100644 --- a/lib/libcapsicum/libcapsicum_pwd.h +++ b/lib/libcasper/services/cap_pwd/cap_pwd.h @@ -29,8 +29,8 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_PWD_H_ -#define _LIBCAPSICUM_PWD_H_ +#ifndef _CAP_PWD_H_ +#define _CAP_PWD_H_ struct passwd *cap_getpwent(cap_channel_t *chan); struct passwd *cap_getpwnam(cap_channel_t *chan, const char *login); @@ -54,4 +54,4 @@ int cap_pwd_limit_fields(cap_channel_t *chan, const char * const *fields, int cap_pwd_limit_users(cap_channel_t *chan, const char * const *names, size_t nnames, uid_t *uids, size_t nuids); -#endif /* !_LIBCAPSICUM_PWD_H_ */ +#endif /* !_CAP_PWD_H_ */ diff --git a/lib/libcasper/services/cap_random/Makefile b/lib/libcasper/services/cap_random/Makefile new file mode 100644 index 000000000000..244723683a34 --- /dev/null +++ b/lib/libcasper/services/cap_random/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +LIB= cap_random + +SHLIB_MAJOR= 0 +SHLIBDIR?= /lib/casper +INCSDIR?= ${INCLUDEDIR}/casper + +SRCS= cap_random.c + +INCS= cap_random.h + +LIBADD= nv + +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../libcasper + +WARNS?= 6 + +.include diff --git a/lib/libcapsicum/libcapsicum_random.c b/lib/libcasper/services/cap_random/cap_random.c similarity index 76% rename from lib/libcapsicum/libcapsicum_random.c rename to lib/libcasper/services/cap_random/cap_random.c index 2a7b109cd47a..d19fe960ea3a 100644 --- a/lib/libcapsicum/libcapsicum_random.c +++ b/lib/libcasper/services/cap_random/cap_random.c @@ -34,10 +34,14 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include -#include "libcapsicum.h" -#include "libcapsicum_random.h" +#include +#include + +#include "cap_random.h" #define MAXSIZE (1024 * 1024) @@ -78,3 +82,36 @@ cap_random_buf(cap_channel_t *chan, void *buf, size_t nbytes) return (0); } + +/* + * Service functions. + */ + +static int +random_command(const char *cmd, const nvlist_t *limits __unused, + nvlist_t *nvlin, nvlist_t *nvlout) +{ + void *data; + size_t size; + + if (strcmp(cmd, "generate") != 0) + return (EINVAL); + if (!nvlist_exists_number(nvlin, "size")) + return (EINVAL); + + size = (size_t)nvlist_get_number(nvlin, "size"); + if (size == 0 || size > MAXSIZE) + return (EINVAL); + + data = malloc(size); + if (data == NULL) + return (ENOMEM); + + arc4random_buf(data, size); + + nvlist_move_binary(nvlout, "data", data, size); + + return (0); +} + +CREATE_SERVICE("system.random", NULL, random_command); diff --git a/lib/libcapsicum/libcapsicum_random.h b/lib/libcasper/services/cap_random/cap_random.h similarity index 94% rename from lib/libcapsicum/libcapsicum_random.h rename to lib/libcasper/services/cap_random/cap_random.h index 672afa04f293..2039b5fe8460 100644 --- a/lib/libcapsicum/libcapsicum_random.h +++ b/lib/libcasper/services/cap_random/cap_random.h @@ -29,9 +29,9 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_RANDOM_H_ -#define _LIBCAPSICUM_RANDOM_H_ +#ifndef _CAP_RANDOM_H_ +#define _CAP_RANDOM_H_ int cap_random_buf(cap_channel_t *chan, void *buf, size_t nbytes); -#endif /* !_LIBCAPSICUM_RANDOM_H_ */ +#endif /* !_CAP_RANDOM_H_ */ diff --git a/lib/libcasper/services/cap_sysctl/Makefile b/lib/libcasper/services/cap_sysctl/Makefile new file mode 100644 index 000000000000..779ed7ecee39 --- /dev/null +++ b/lib/libcasper/services/cap_sysctl/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +LIB= cap_sysctl + +SHLIB_MAJOR= 0 +SHLIBDIR?= /lib/casper +INCSDIR?= ${INCLUDEDIR}/casper + +SRCS= cap_sysctl.c + +INCS= cap_sysctl.h + +LIBADD= nv + +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../libcasper + +WARNS?= 6 + +.include diff --git a/libexec/casper/sysctl/sysctl.c b/lib/libcasper/services/cap_sysctl/cap_sysctl.c similarity index 80% rename from libexec/casper/sysctl/sysctl.c rename to lib/libcasper/services/cap_sysctl/cap_sysctl.c index 4cbc505630a7..7611d647f11a 100644 --- a/libexec/casper/sysctl/sysctl.c +++ b/lib/libcasper/services/cap_sysctl/cap_sysctl.c @@ -34,15 +34,66 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include -#include -#include #include -#include +#include +#include "cap_sysctl.h" + +int +cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp, + size_t *oldlenp, const void *newp, size_t newlen) +{ + nvlist_t *nvl; + const uint8_t *retoldp; + uint8_t operation; + size_t oldlen; + + operation = 0; + if (oldp != NULL) + operation |= CAP_SYSCTL_READ; + if (newp != NULL) + operation |= CAP_SYSCTL_WRITE; + + nvl = nvlist_create(0); + nvlist_add_string(nvl, "cmd", "sysctl"); + nvlist_add_string(nvl, "name", name); + nvlist_add_number(nvl, "operation", (uint64_t)operation); + if (oldp == NULL && oldlenp != NULL) + nvlist_add_null(nvl, "justsize"); + else if (oldlenp != NULL) + nvlist_add_number(nvl, "oldlen", (uint64_t)*oldlenp); + if (newp != NULL) + nvlist_add_binary(nvl, "newp", newp, newlen); + nvl = cap_xfer_nvlist(chan, nvl, 0); + if (nvl == NULL) + return (-1); + if (nvlist_get_number(nvl, "error") != 0) { + errno = (int)nvlist_get_number(nvl, "error"); + nvlist_destroy(nvl); + return (-1); + } + + if (oldp == NULL && oldlenp != NULL) { + *oldlenp = (size_t)nvlist_get_number(nvl, "oldlen"); + } else if (oldp != NULL) { + retoldp = nvlist_get_binary(nvl, "oldp", &oldlen); + memcpy(oldp, retoldp, oldlen); + if (oldlenp != NULL) + *oldlenp = oldlen; + } + nvlist_destroy(nvl); + + return (0); +} + +/* + * Service functions. + */ static int sysctl_check_one(const nvlist_t *nvl, bool islimit) { @@ -119,7 +170,7 @@ sysctl_allowed(const nvlist_t *limits, const char *chname, uint64_t choperation) cookie = NULL; while ((name = nvlist_next(limits, &type, &cookie)) != NULL) { - PJDLOG_ASSERT(type == NV_TYPE_NUMBER); + assert(type == NV_TYPE_NUMBER); operation = nvlist_get_number(limits, name); if ((operation & choperation) != choperation) @@ -147,11 +198,10 @@ sysctl_allowed(const nvlist_t *limits, const char *chname, uint64_t choperation) static int sysctl_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) { - const nvlist_t *nvl; const char *name; void *cookie; uint64_t operation; - int error, type; + int type; cookie = NULL; while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { @@ -196,7 +246,7 @@ sysctl_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, if (!nvlist_exists_binary(nvlin, "newp")) return (EINVAL); newp = nvlist_get_binary(nvlin, "newp", &newlen); - PJDLOG_ASSERT(newp != NULL && newlen > 0); + assert(newp != NULL && newlen > 0); } else { newp = NULL; newlen = 0; @@ -240,10 +290,4 @@ sysctl_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, return (0); } -int -main(int argc, char *argv[]) -{ - - return (service_start("system.sysctl", PARENT_FILENO, sysctl_limit, - sysctl_command, argc, argv)); -} +CREATE_SERVICE("system.sysctl", sysctl_limit, sysctl_command); diff --git a/lib/libcapsicum/libcapsicum_sysctl.h b/lib/libcasper/services/cap_sysctl/cap_sysctl.h similarity index 94% rename from lib/libcapsicum/libcapsicum_sysctl.h rename to lib/libcasper/services/cap_sysctl/cap_sysctl.h index d0df1437cec5..2af6d2157695 100644 --- a/lib/libcapsicum/libcapsicum_sysctl.h +++ b/lib/libcasper/services/cap_sysctl/cap_sysctl.h @@ -29,8 +29,8 @@ * $FreeBSD$ */ -#ifndef _LIBCAPSICUM_SYSCTL_H_ -#define _LIBCAPSICUM_SYSCTL_H_ +#ifndef _CAP_SYSCTL_H_ +#define _CAP_SYSCTL_H_ #define CAP_SYSCTL_READ 0x01 #define CAP_SYSCTL_WRITE 0x02 @@ -40,4 +40,4 @@ int cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp, size_t *oldlenp, const void *newp, size_t newlen); -#endif /* !_LIBCAPSICUM_SYSCTL_H_ */ +#endif /* !_CAP_SYSCTL_H_ */ diff --git a/libexec/Makefile b/libexec/Makefile index a8ace185469f..b60cc34ec70d 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -5,7 +5,6 @@ SUBDIR= ${_atf} \ ${_atrun} \ - ${_casper} \ ${_comsat} \ ${_dma} \ getty \ @@ -38,10 +37,6 @@ _atrun= atrun SUBDIR+= bootpd .endif -.if ${MK_CASPER} != "no" -_casper= casper -.endif - .if ${MK_FINGER} != "no" SUBDIR+= fingerd .endif diff --git a/libexec/casper/Makefile b/libexec/casper/Makefile deleted file mode 100644 index ed6bd7b42aa6..000000000000 --- a/libexec/casper/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD$ - -.include - -SUBDIR= dns -SUBDIR+=grp -SUBDIR+=pwd -SUBDIR+=random -SUBDIR+=sysctl - -.include diff --git a/libexec/casper/dns/Makefile b/libexec/casper/dns/Makefile deleted file mode 100644 index b101891cc954..000000000000 --- a/libexec/casper/dns/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper - -PROG= dns - -SRCS= dns.c - -LIBADD= casper nv - -BINDIR= /libexec/casper - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../../../lib/libcapsicum -CFLAGS+=-I${.CURDIR}/../../../lib/libcasper -CFLAGS+=-I${.CURDIR}/../../../lib/libpjdlog -CFLAGS+=-I${.CURDIR}/../../../sbin/casper - -MAN= - -.include diff --git a/libexec/casper/grp/Makefile b/libexec/casper/grp/Makefile deleted file mode 100644 index 75274d101a2c..000000000000 --- a/libexec/casper/grp/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper - -PROG= grp - -SRCS= grp.c - -LIBADD= casper nv pjdlog - -BINDIR= /libexec/casper - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../../../lib/libcapsicum -CFLAGS+=-I${.CURDIR}/../../../lib/libcasper -CFLAGS+=-I${.CURDIR}/../../../lib/libpjdlog -CFLAGS+=-I${.CURDIR}/../../../sbin/casper - -MAN= - -.include diff --git a/libexec/casper/grp/grp.c b/libexec/casper/grp/grp.c deleted file mode 100644 index 5b3e13d9415d..000000000000 --- a/libexec/casper/grp/grp.c +++ /dev/null @@ -1,390 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -static bool -grp_allowed_cmd(const nvlist_t *limits, const char *cmd) -{ - - if (limits == NULL) - return (true); - - /* - * If no limit was set on allowed commands, then all commands - * are allowed. - */ - if (!nvlist_exists_nvlist(limits, "cmds")) - return (true); - - limits = nvlist_get_nvlist(limits, "cmds"); - return (nvlist_exists_null(limits, cmd)); -} - -static int -grp_allowed_cmds(const nvlist_t *oldlimits, const nvlist_t *newlimits) -{ - const char *name; - void *cookie; - int type; - - cookie = NULL; - while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { - if (type != NV_TYPE_NULL) - return (EINVAL); - if (!grp_allowed_cmd(oldlimits, name)) - return (ENOTCAPABLE); - } - - return (0); -} - -static bool -grp_allowed_group(const nvlist_t *limits, const char *gname, gid_t gid) -{ - const char *name; - void *cookie; - int type; - - if (limits == NULL) - return (true); - - /* - * If no limit was set on allowed groups, then all groups are allowed. - */ - if (!nvlist_exists_nvlist(limits, "groups")) - return (true); - - limits = nvlist_get_nvlist(limits, "groups"); - cookie = NULL; - while ((name = nvlist_next(limits, &type, &cookie)) != NULL) { - switch (type) { - case NV_TYPE_NUMBER: - if (gid != (gid_t)-1 && - nvlist_get_number(limits, name) == (uint64_t)gid) { - return (true); - } - break; - case NV_TYPE_STRING: - if (gname != NULL && - strcmp(nvlist_get_string(limits, name), - gname) == 0) { - return (true); - } - break; - default: - PJDLOG_ABORT("Unexpected type %d.", type); - } - } - - return (false); -} - -static int -grp_allowed_groups(const nvlist_t *oldlimits, const nvlist_t *newlimits) -{ - const char *name, *gname; - void *cookie; - gid_t gid; - int type; - - cookie = NULL; - while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { - switch (type) { - case NV_TYPE_NUMBER: - gid = (gid_t)nvlist_get_number(newlimits, name); - gname = NULL; - break; - case NV_TYPE_STRING: - gid = (gid_t)-1; - gname = nvlist_get_string(newlimits, name); - break; - default: - return (EINVAL); - } - if (!grp_allowed_group(oldlimits, gname, gid)) - return (ENOTCAPABLE); - } - - return (0); -} - -static bool -grp_allowed_field(const nvlist_t *limits, const char *field) -{ - - if (limits == NULL) - return (true); - - /* - * If no limit was set on allowed fields, then all fields are allowed. - */ - if (!nvlist_exists_nvlist(limits, "fields")) - return (true); - - limits = nvlist_get_nvlist(limits, "fields"); - return (nvlist_exists_null(limits, field)); -} - -static int -grp_allowed_fields(const nvlist_t *oldlimits, const nvlist_t *newlimits) -{ - const char *name; - void *cookie; - int type; - - cookie = NULL; - while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { - if (type != NV_TYPE_NULL) - return (EINVAL); - if (!grp_allowed_field(oldlimits, name)) - return (ENOTCAPABLE); - } - - return (0); -} - -static bool -grp_pack(const nvlist_t *limits, const struct group *grp, nvlist_t *nvl) -{ - char nvlname[64]; - int n; - - if (grp == NULL) - return (true); - - /* - * If either name or GID is allowed, we allow it. - */ - if (!grp_allowed_group(limits, grp->gr_name, grp->gr_gid)) - return (false); - - if (grp_allowed_field(limits, "gr_name")) - nvlist_add_string(nvl, "gr_name", grp->gr_name); - else - nvlist_add_string(nvl, "gr_name", ""); - if (grp_allowed_field(limits, "gr_passwd")) - nvlist_add_string(nvl, "gr_passwd", grp->gr_passwd); - else - nvlist_add_string(nvl, "gr_passwd", ""); - if (grp_allowed_field(limits, "gr_gid")) - nvlist_add_number(nvl, "gr_gid", (uint64_t)grp->gr_gid); - else - nvlist_add_number(nvl, "gr_gid", (uint64_t)-1); - if (grp_allowed_field(limits, "gr_mem") && grp->gr_mem[0] != NULL) { - unsigned int ngroups; - - for (ngroups = 0; grp->gr_mem[ngroups] != NULL; ngroups++) { - n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", - ngroups); - assert(n > 0 && n < sizeof(nvlname)); - nvlist_add_string(nvl, nvlname, grp->gr_mem[ngroups]); - } - nvlist_add_number(nvl, "gr_nmem", (uint64_t)ngroups); - } - - return (true); -} - -static int -grp_getgrent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) -{ - struct group *grp; - - for (;;) { - errno = 0; - grp = getgrent(); - if (errno != 0) - return (errno); - if (grp_pack(limits, grp, nvlout)) - return (0); - } - - /* NOTREACHED */ -} - -static int -grp_getgrnam(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) -{ - struct group *grp; - const char *name; - - if (!nvlist_exists_string(nvlin, "name")) - return (EINVAL); - name = nvlist_get_string(nvlin, "name"); - PJDLOG_ASSERT(name != NULL); - - errno = 0; - grp = getgrnam(name); - if (errno != 0) - return (errno); - - (void)grp_pack(limits, grp, nvlout); - - return (0); -} - -static int -grp_getgrgid(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) -{ - struct group *grp; - gid_t gid; - - if (!nvlist_exists_number(nvlin, "gid")) - return (EINVAL); - - gid = (gid_t)nvlist_get_number(nvlin, "gid"); - - errno = 0; - grp = getgrgid(gid); - if (errno != 0) - return (errno); - - (void)grp_pack(limits, grp, nvlout); - - return (0); -} - -static int -grp_setgroupent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) -{ - int stayopen; - - if (!nvlist_exists_bool(nvlin, "stayopen")) - return (EINVAL); - - stayopen = nvlist_get_bool(nvlin, "stayopen") ? 1 : 0; - - return (setgroupent(stayopen) == 0 ? EFAULT : 0); -} - -static int -grp_setgrent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) -{ - - return (setgrent() == 0 ? EFAULT : 0); -} - -static int -grp_endgrent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) -{ - - endgrent(); - - return (0); -} - -static int -grp_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) -{ - const nvlist_t *limits; - const char *name; - void *cookie; - int error, type; - - if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "cmds") && - !nvlist_exists_nvlist(newlimits, "cmds")) { - return (ENOTCAPABLE); - } - if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "fields") && - !nvlist_exists_nvlist(newlimits, "fields")) { - return (ENOTCAPABLE); - } - if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "groups") && - !nvlist_exists_nvlist(newlimits, "groups")) { - return (ENOTCAPABLE); - } - - cookie = NULL; - while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { - if (type != NV_TYPE_NVLIST) - return (EINVAL); - limits = nvlist_get_nvlist(newlimits, name); - if (strcmp(name, "cmds") == 0) - error = grp_allowed_cmds(oldlimits, limits); - else if (strcmp(name, "fields") == 0) - error = grp_allowed_fields(oldlimits, limits); - else if (strcmp(name, "groups") == 0) - error = grp_allowed_groups(oldlimits, limits); - else - error = EINVAL; - if (error != 0) - return (error); - } - - return (0); -} - -static int -grp_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, - nvlist_t *nvlout) -{ - int error; - - if (!grp_allowed_cmd(limits, cmd)) - return (ENOTCAPABLE); - - if (strcmp(cmd, "getgrent") == 0 || strcmp(cmd, "getgrent_r") == 0) - error = grp_getgrent(limits, nvlin, nvlout); - else if (strcmp(cmd, "getgrnam") == 0 || strcmp(cmd, "getgrnam_r") == 0) - error = grp_getgrnam(limits, nvlin, nvlout); - else if (strcmp(cmd, "getgrgid") == 0 || strcmp(cmd, "getgrgid_r") == 0) - error = grp_getgrgid(limits, nvlin, nvlout); - else if (strcmp(cmd, "setgroupent") == 0) - error = grp_setgroupent(limits, nvlin, nvlout); - else if (strcmp(cmd, "setgrent") == 0) - error = grp_setgrent(limits, nvlin, nvlout); - else if (strcmp(cmd, "endgrent") == 0) - error = grp_endgrent(limits, nvlin, nvlout); - else - error = EINVAL; - - return (error); -} - -int -main(int argc, char *argv[]) -{ - - return (service_start("system.grp", PARENT_FILENO, grp_limit, - grp_command, argc, argv)); -} diff --git a/libexec/casper/pwd/Makefile b/libexec/casper/pwd/Makefile deleted file mode 100644 index 23ad3f277a81..000000000000 --- a/libexec/casper/pwd/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper - -PROG= pwd - -SRCS= pwd.c - -LIBADD= casper nv pjdlog - -BINDIR= /libexec/casper - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../../../lib/libcapsicum -CFLAGS+=-I${.CURDIR}/../../../lib/libcasper -CFLAGS+=-I${.CURDIR}/../../../lib/libpjdlog -CFLAGS+=-I${.CURDIR}/../../../sbin/casper - -MAN= - -.include diff --git a/libexec/casper/random/Makefile b/libexec/casper/random/Makefile deleted file mode 100644 index 3b5d15585afd..000000000000 --- a/libexec/casper/random/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper - -PROG= random - -SRCS= random.c - -LIBADD= casper nv - -BINDIR= /libexec/casper - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../../../lib/libcapsicum -CFLAGS+=-I${.CURDIR}/../../../lib/libcasper -CFLAGS+=-I${.CURDIR}/../../../lib/libpjdlog -CFLAGS+=-I${.CURDIR}/../../../sbin/casper - -MAN= - -.include diff --git a/libexec/casper/random/random.c b/libexec/casper/random/random.c deleted file mode 100644 index db91685a0eaa..000000000000 --- a/libexec/casper/random/random.c +++ /dev/null @@ -1,82 +0,0 @@ -/*- - * Copyright (c) 2012-2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include - -#include -#include -#include - -#define MAXSIZE (1024 * 1024) - -static int -random_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, - nvlist_t *nvlout) -{ - void *data; - size_t size; - - if (strcmp(cmd, "generate") != 0) - return (EINVAL); - if (!nvlist_exists_number(nvlin, "size")) - return (EINVAL); - - size = (size_t)nvlist_get_number(nvlin, "size"); - if (size == 0 || size > MAXSIZE) - return (EINVAL); - - data = malloc(size); - if (data == NULL) - return (ENOMEM); - - arc4random_buf(data, size); - - nvlist_move_binary(nvlout, "data", data, size); - - return (0); -} - -int -main(int argc, char *argv[]) -{ - - /* - * TODO: Sandbox this. - */ - - return (service_start("system.random", PARENT_FILENO, NULL, - random_command, argc, argv)); -} diff --git a/libexec/casper/sysctl/Makefile b/libexec/casper/sysctl/Makefile deleted file mode 100644 index 24152abdc90e..000000000000 --- a/libexec/casper/sysctl/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper - -PROG= sysctl - -SRCS= sysctl.c - -LIBADD= casper nv pjdlog - -BINDIR= /libexec/casper - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../../../lib/libcapsicum -CFLAGS+=-I${.CURDIR}/../../../lib/libcasper -CFLAGS+=-I${.CURDIR}/../../../lib/libpjdlog -CFLAGS+=-I${.CURDIR}/../../../sbin/casper - -MAN= - -.include diff --git a/libexec/rtld-elf/paths.h b/libexec/rtld-elf/paths.h index 7d9d372c293c..69b1d03e1a8a 100644 --- a/libexec/rtld-elf/paths.h +++ b/libexec/rtld-elf/paths.h @@ -52,7 +52,7 @@ #endif #ifndef STANDARD_LIBRARY_PATH -#define STANDARD_LIBRARY_PATH "/lib:/usr/lib" +#define STANDARD_LIBRARY_PATH "/lib/casper:/lib:/usr/lib" #endif #ifndef LD_ diff --git a/sbin/Makefile b/sbin/Makefile index 3b17e106e058..affca8e19d91 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -71,7 +71,6 @@ SUBDIR=adjkerntz \ umount SUBDIR.${MK_ATM}+= atm -SUBDIR.${MK_CASPER}+= casperd SUBDIR.${MK_CCD}+= ccdconfig SUBDIR.${MK_CXX}+= devd SUBDIR.${MK_HAST}+= hastctl diff --git a/sbin/casperd/Makefile b/sbin/casperd/Makefile deleted file mode 100644 index 93f145ceeb38..000000000000 --- a/sbin/casperd/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $FreeBSD$ - -PROG= casperd - -SRCS= casperd.c zygote.c - -LIBADD= casper nv pjdlog util - -MAN= casperd.8 - -CFLAGS+=-I${.CURDIR} -CFLAGS+=-I${.CURDIR}/../../lib/libcapsicum -CFLAGS+=-I${.CURDIR}/../../lib/libcasper -CFLAGS+=-I${.CURDIR}/../../lib/libnv -CFLAGS+=-I${.CURDIR}/../../lib/libpjdlog - -.include diff --git a/sbin/casperd/casperd.8 b/sbin/casperd/casperd.8 deleted file mode 100644 index 945b517a0e8a..000000000000 --- a/sbin/casperd/casperd.8 +++ /dev/null @@ -1,132 +0,0 @@ -.\" Copyright (c) 2013 The FreeBSD Foundation -.\" All rights reserved. -.\" -.\" This documentation was written by Pawel Jakub Dawidek under sponsorship -.\" from the FreeBSD Foundation. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd October 26, 2013 -.Dt CASPERD 8 -.Os -.Sh NAME -.Nm casperd -.Nd "Capability Services friendly daemon" -.Sh SYNOPSIS -.Nm -.Op Fl Fhv -.Op Fl l Ar listenqueue -.Op Fl D Ar servconfdir -.Op Fl P Ar pidfile -.Op Fl S Ar sockpath -.Sh DESCRIPTION -The -.Nm -daemon hosts various services that can be accessed through -libcapsicum's capabilities by programs running in sandboxes. -For example it is prohibited to send UDP packets to arbitrary destinations -when operating in capability mode, which makes DNS resolution impossible. -To make it possible the -.Nm -daemon provides the -.Nm system.dns -service that proxies DNS resolution requests through a dedicated, -non-sandboxed process provided by -.Nm . -.Pp -The -.Nm -daemon can be started with the following command line arguments: -.Bl -tag -width ".Fl D Ar servconfdir" -.It Fl D Ar servconfdir -Specify alternative location of the service configuration directory. -The default location is -.Pa /etc/casper/ . -.It Fl F -Start the -.Nm -daemon in the foreground. -By default -.Nm -starts in the background. -.It Fl h -Print the -.Nm -usage message. -.It Fl l Ar listenqueue -Specify depth of socket listen queue for the -.Nm -daemon. -The default queue length is -.Pa SOMAXCONN . -.It Fl P Ar pidfile -Specify alternative location of a file where main process PID will be -stored. -The default location is -.Pa /var/run/casperd.pid . -.It Fl S Ar sockpath -Specify alternative location of the -.Xr unix 4 -domain socket used to connect to the -.Nm -daemon. -The default location is -.Pa /var/run/casper . -.It Fl v -Print or log verbose/debugging information. -This option can be specified multiple times to raise the verbosity -level. -.El -.Sh FILES -.Bl -tag -width ".Pa /var/run/casperd.pid" -compact -.It Pa /etc/casper/ -The configuration directory for -.Nm -services. -.It Pa /var/run/casper -.Xr unix 4 -domain socket used to connect to the -.Nm -daemon. -.It Pa /var/run/casperd.pid -The default location of the -.Nm -PID file. -.El -.Sh EXIT STATUS -The -.Nm -daemon exits 0 on success, and >0 if an error occurs. -.Sh SEE ALSO -.Xr cap_enter 2 , -.Xr libcapsicum 3 , -.Xr pidfile 3 , -.Xr capsicum 4 , -.Xr unix 4 -.Sh AUTHORS -The -.Nm -was implemented by -.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net -under sponsorship from the FreeBSD Foundation. diff --git a/sbin/casperd/casperd.c b/sbin/casperd/casperd.c deleted file mode 100644 index 65da58a664ec..000000000000 --- a/sbin/casperd/casperd.c +++ /dev/null @@ -1,721 +0,0 @@ -/*- - * Copyright (c) 2012 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "msgio.h" - -#include "zygote.h" - -#define CASPERD_PIDFILE "/var/run/casperd.pid" -#define CASPERD_SERVCONFDIR "/etc/casper" -#define CASPERD_SOCKPATH "/var/run/casper" - -typedef void service_function_t(struct service_connection *, const nvlist_t *, - nvlist_t *); - -struct casper_service { - const char *cs_name; - const char *cs_execpath; - struct service *cs_service; - nvlist_t *cs_attrs; - TAILQ_ENTRY(casper_service) cs_next; -}; - -static TAILQ_HEAD(, casper_service) casper_services = - TAILQ_HEAD_INITIALIZER(casper_services); - -#define SERVICE_IS_CORE(service) ((service)->cs_execpath == NULL) - -static void service_external_execute(int chanfd); - -#define KEEP_ERRNO(work) do { \ - int _serrno; \ - \ - _serrno = errno; \ - work; \ - errno = _serrno; \ -} while (0) - -static struct casper_service * -service_find(const char *name) -{ - struct casper_service *casserv; - - TAILQ_FOREACH(casserv, &casper_services, cs_next) { - if (strcmp(casserv->cs_name, name) == 0) - break; - } - return (casserv); -} - -/* - * Function always consumes the given attrs. - */ -static void -service_register(nvlist_t *attrs) -{ - struct casper_service *casserv; - const char *name; - - PJDLOG_ASSERT(nvlist_exists_string(attrs, "name")); - PJDLOG_ASSERT(nvlist_exists_string(attrs, "execpath") || - (nvlist_exists_number(attrs, "commandfunc") && - nvlist_exists_number(attrs, "limitfunc"))); - - name = nvlist_get_string(attrs, "name"); - PJDLOG_ASSERT(name != NULL); - if (name[0] == '\0') { - pjdlog_error("Unable to register service with an empty name."); - nvlist_destroy(attrs); - return; - } - if (service_find(name) != NULL) { - pjdlog_error("Service \"%s\" is already registered.", name); - nvlist_destroy(attrs); - return; - } - - casserv = malloc(sizeof(*casserv)); - if (casserv == NULL) { - pjdlog_errno(LOG_ERR, "Unable to register service \"%s\"", - name); - nvlist_destroy(attrs); - return; - } - casserv->cs_name = name; - if (nvlist_exists_string(attrs, "execpath")) { - struct stat sb; - - PJDLOG_ASSERT(!nvlist_exists_number(attrs, "commandfunc")); - PJDLOG_ASSERT(!nvlist_exists_number(attrs, "limitfunc")); - - casserv->cs_service = NULL; - - casserv->cs_execpath = nvlist_get_string(attrs, "execpath"); - if (casserv->cs_execpath == NULL || - casserv->cs_execpath[0] == '\0') { - pjdlog_error("Unable to register service with an empty execpath."); - free(casserv); - nvlist_destroy(attrs); - return; - } - if (stat(casserv->cs_execpath, &sb) == -1) { - pjdlog_errno(LOG_ERR, - "Unable to register service \"%s\", problem with executable \"%s\"", - name, casserv->cs_execpath); - free(casserv); - nvlist_destroy(attrs); - return; - } - } else /* if (nvlist_exists_number(attrs, "commandfunc")) */ { - PJDLOG_ASSERT(!nvlist_exists_string(attrs, "execpath")); - - casserv->cs_execpath = NULL; - - casserv->cs_service = service_alloc(name, - (void *)(uintptr_t)nvlist_get_number(attrs, "limitfunc"), - (void *)(uintptr_t)nvlist_get_number(attrs, "commandfunc")); - if (casserv->cs_service == NULL) { - pjdlog_errno(LOG_ERR, - "Unable to register service \"%s\"", name); - free(casserv); - nvlist_destroy(attrs); - return; - } - } - casserv->cs_attrs = attrs; - TAILQ_INSERT_TAIL(&casper_services, casserv, cs_next); - pjdlog_debug(1, "Service %s successfully registered.", - casserv->cs_name); -} - -static bool -casper_allowed_service(const nvlist_t *limits, const char *service) -{ - - if (limits == NULL) - return (true); - - if (nvlist_exists_null(limits, service)) - return (true); - - return (false); -} - -static int -casper_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) -{ - const char *name; - int type; - void *cookie; - - cookie = NULL; - while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { - if (type != NV_TYPE_NULL) - return (EINVAL); - if (!casper_allowed_service(oldlimits, name)) - return (ENOTCAPABLE); - } - - return (0); -} - -static int -casper_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, - nvlist_t *nvlout) -{ - struct casper_service *casserv; - const char *servname; - nvlist_t *nvl; - int chanfd, execfd, procfd, error; - - if (strcmp(cmd, "open") != 0) - return (EINVAL); - if (!nvlist_exists_string(nvlin, "service")) - return (EINVAL); - - servname = nvlist_get_string(nvlin, "service"); - - casserv = service_find(servname); - if (casserv == NULL) - return (ENOENT); - - if (!casper_allowed_service(limits, servname)) - return (ENOTCAPABLE); - -#ifdef O_EXEC_WORKING - execfd = open(casserv->cs_execpath, O_EXEC); -#else - execfd = open(casserv->cs_execpath, O_RDONLY); -#endif - if (execfd < -1) { - error = errno; - pjdlog_errno(LOG_ERR, - "Unable to open executable '%s' of service '%s'", - casserv->cs_execpath, casserv->cs_name); - return (error); - } - - if (zygote_clone(service_external_execute, &chanfd, &procfd) == -1) { - error = errno; - close(execfd); - return (error); - } - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "service", casserv->cs_name); - if (nvlist_exists_descriptor(nvlin, "stderrfd")) { - nvlist_move_descriptor(nvl, "stderrfd", - nvlist_take_descriptor(nvlin, "stderrfd")); - } - nvlist_move_descriptor(nvl, "execfd", execfd); - nvlist_move_descriptor(nvl, "procfd", procfd); - if (nvlist_send(chanfd, nvl) == -1) { - error = errno; - pjdlog_errno(LOG_ERR, "Unable to send nvlist"); - nvlist_destroy(nvl); - close(chanfd); - return (error); - } - nvlist_destroy(nvl); - - nvlist_move_descriptor(nvlout, "chanfd", chanfd); - - return (0); -} - -static void -fdswap(int *fd0, int *fd1) -{ - int tmpfd; - - PJDLOG_VERIFY((tmpfd = dup(*fd0)) != -1); - PJDLOG_VERIFY(dup2(*fd1, *fd0) != -1); - PJDLOG_VERIFY(dup2(tmpfd, *fd1) != -1); - close(tmpfd); - tmpfd = *fd0; - *fd0 = *fd1; - *fd1 = tmpfd; -} - -static void -fdmove(int *oldfdp, int newfd) -{ - - if (*oldfdp != newfd) { - PJDLOG_VERIFY(dup2(*oldfdp, newfd) != -1); - close(*oldfdp); - *oldfdp = newfd; - } -} - -static void -fdcloexec(int fd) -{ - int flags; - - flags = fcntl(fd, F_GETFD); - PJDLOG_ASSERT(flags != -1); - if ((flags & FD_CLOEXEC) != 0) - PJDLOG_VERIFY(fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) != -1); -} - -static void -service_register_core(void) -{ - nvlist_t *nvl; - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "name", "core.casper"); - nvlist_add_number(nvl, "limitfunc", (uint64_t)(uintptr_t)casper_limit); - nvlist_add_number(nvl, "commandfunc", - (uint64_t)(uintptr_t)casper_command); - service_register(nvl); -} - -static int -setup_creds(int sock) -{ - struct cmsgcred cred; - - if (cred_recv(sock, &cred) == -1) - return (-1); - - if (setgroups((int)cred.cmcred_ngroups, cred.cmcred_groups) == -1) - return (-1); - - if (setgid(cred.cmcred_groups[0]) == -1) - return (-1); - - if (setuid(cred.cmcred_euid) == -1) - return (-1); - - return (0); -} - -static void -service_external_execute(int chanfd) -{ - char *service, *argv[3]; - int stderrfd, execfd, procfd; - nvlist_t *nvl; - - nvl = nvlist_recv(chanfd, 0); - if (nvl == NULL) - pjdlog_exit(1, "Unable to receive nvlist"); - service = nvlist_take_string(nvl, "service"); - PJDLOG_ASSERT(service != NULL); - if (nvlist_exists_descriptor(nvl, "stderrfd")) { - stderrfd = nvlist_take_descriptor(nvl, "stderrfd"); - } else { - stderrfd = open(_PATH_DEVNULL, O_RDWR); - if (stderrfd < 0) - pjdlog_exit(1, "Unable to open %s", _PATH_DEVNULL); - } - execfd = nvlist_take_descriptor(nvl, "execfd"); - procfd = nvlist_take_descriptor(nvl, "procfd"); - nvlist_destroy(nvl); - - /* - * Move all descriptors into right slots. - */ - - if (stderrfd != STDERR_FILENO) { - if (chanfd == STDERR_FILENO) - fdswap(&stderrfd, &chanfd); - else if (execfd == STDERR_FILENO) - fdswap(&stderrfd, &execfd); - else if (procfd == STDERR_FILENO) - fdswap(&stderrfd, &procfd); - fdmove(&stderrfd, STDERR_FILENO); - } - fdcloexec(stderrfd); - - if (chanfd != PARENT_FILENO) { - if (execfd == PARENT_FILENO) - fdswap(&chanfd, &execfd); - else if (procfd == PARENT_FILENO) - fdswap(&chanfd, &procfd); - fdmove(&chanfd, PARENT_FILENO); - } - fdcloexec(chanfd); - - if (execfd != EXECUTABLE_FILENO) { - if (procfd == EXECUTABLE_FILENO) - fdswap(&execfd, &procfd); - fdmove(&execfd, EXECUTABLE_FILENO); - } - fdcloexec(execfd); - - if (procfd != PROC_FILENO) - fdmove(&procfd, PROC_FILENO); - fdcloexec(procfd); - - /* - * Use credentials of the caller process. - */ - setup_creds(chanfd); - - argv[0] = service; - asprintf(&argv[1], "%d", pjdlog_debug_get()); - argv[2] = NULL; - - fexecve(execfd, argv, NULL); - pjdlog_exit(1, "Unable to execute service %s", service); -} - -static void -service_register_external_one(const char *dirpath, int dfd, - const char *filename) -{ - char execpath[FILENAME_MAX]; - nvlist_t *nvl; - ssize_t done; - int fd; - - fd = openat(dfd, filename, O_RDONLY); - if (fd == -1) { - pjdlog_errno(LOG_ERR, "Unable to open \"%s/%s\"", dirpath, - filename); - return; - } - - done = read(fd, execpath, sizeof(execpath)); - if (done == -1) { - pjdlog_errno(LOG_ERR, "Unable to read content of \"%s/%s\"", - dirpath, filename); - close(fd); - return; - } - close(fd); - if (done == sizeof(execpath)) { - pjdlog_error("Executable path too long in \"%s/%s\".", dirpath, - filename); - return; - } - execpath[done] = '\0'; - while (done > 0) { - if (execpath[--done] == '\n') - execpath[done] = '\0'; - } - - nvl = nvlist_create(0); - nvlist_add_string(nvl, "name", filename); - nvlist_add_string(nvl, "execpath", execpath); - if (nvlist_error(nvl) != 0) { - pjdlog_common(LOG_ERR, 0, nvlist_error(nvl), - "Unable to allocate attributes for service \"%s/%s\"", - dirpath, filename); - nvlist_destroy(nvl); - return; - } - - service_register(nvl); - /* service_register() consumed nvl. */ -} - -static uint8_t -file_type(int dfd, const char *filename) -{ - struct stat sb; - - if (fstatat(dfd, filename, &sb, AT_SYMLINK_NOFOLLOW) == -1) { - pjdlog_errno(LOG_ERR, "Unable to stat \"%s\"", filename); - return (DT_UNKNOWN); - } - return (IFTODT(sb.st_mode)); -} - -static void -service_register_external(const char *dirpath) -{ - DIR *dirp; - struct dirent *dp; - int dfd; - - dirp = opendir(dirpath); - if (dirp == NULL) { - pjdlog_errno(LOG_WARNING, "Unable to open \"%s\"", dirpath); - return; - } - dfd = dirfd(dirp); - PJDLOG_ASSERT(dfd >= 0); - while ((dp = readdir(dirp)) != NULL) { - dp->d_type = file_type(dfd, dp->d_name); - /* We are only interested in regular files, skip the rest. */ - if (dp->d_type != DT_REG) { - pjdlog_debug(1, - "File \"%s/%s\" is not a regular file, skipping.", - dirpath, dp->d_name); - continue; - } - service_register_external_one(dirpath, dfd, dp->d_name); - } - closedir(dirp); -} - -static void -casper_accept(int lsock) -{ - struct casper_service *casserv; - struct service_connection *sconn; - int sock; - - sock = accept(lsock, NULL, NULL); - if (sock == -1) { - pjdlog_errno(LOG_ERR, "Unable to accept casper connection"); - return; - } - casserv = service_find("core.casper"); - PJDLOG_ASSERT(casserv != NULL); - - sconn = service_connection_add(casserv->cs_service, sock, NULL); - if (sconn == NULL) { - close(sock); - return; - } -} - -static void -main_loop(int lqlen, const char *sockpath, struct pidfh *pfh) -{ - fd_set fds; - struct sockaddr_un sun; - struct casper_service *casserv; - struct service_connection *sconn, *sconntmp; - int lsock, sock, maxfd, ret; - mode_t oldumask; - - lsock = socket(AF_UNIX, SOCK_STREAM, 0); - if (lsock == -1) - pjdlog_exit(1, "Unable to create socket"); - - (void)unlink(sockpath); - - bzero(&sun, sizeof(sun)); - sun.sun_family = AF_UNIX; - PJDLOG_VERIFY(strlcpy(sun.sun_path, sockpath, sizeof(sun.sun_path)) < - sizeof(sun.sun_path)); - sun.sun_len = SUN_LEN(&sun); - - oldumask = umask(S_IXUSR | S_IXGRP | S_IXOTH); - if (bind(lsock, (struct sockaddr *)&sun, sizeof(sun)) == -1) - pjdlog_exit(1, "Unable to bind to %s", sockpath); - (void)umask(oldumask); - if (listen(lsock, lqlen) == -1) - pjdlog_exit(1, "Unable to listen on %s", sockpath); - - for (;;) { - FD_ZERO(&fds); - FD_SET(lsock, &fds); - maxfd = lsock; - TAILQ_FOREACH(casserv, &casper_services, cs_next) { - /* We handle only core services. */ - if (!SERVICE_IS_CORE(casserv)) - continue; - for (sconn = service_connection_first(casserv->cs_service); - sconn != NULL; - sconn = service_connection_next(sconn)) { - sock = service_connection_get_sock(sconn); - FD_SET(sock, &fds); - maxfd = sock > maxfd ? sock : maxfd; - } - } - maxfd++; - - PJDLOG_ASSERT(maxfd <= (int)FD_SETSIZE); - ret = select(maxfd, &fds, NULL, NULL, NULL); - PJDLOG_ASSERT(ret == -1 || ret > 0); /* select() cannot timeout */ - if (ret == -1) { - if (errno == EINTR) - continue; - KEEP_ERRNO((void)pidfile_remove(pfh)); - pjdlog_exit(1, "select() failed"); - } - - if (FD_ISSET(lsock, &fds)) - casper_accept(lsock); - TAILQ_FOREACH(casserv, &casper_services, cs_next) { - /* We handle only core services. */ - if (!SERVICE_IS_CORE(casserv)) - continue; - for (sconn = service_connection_first(casserv->cs_service); - sconn != NULL; sconn = sconntmp) { - /* - * Prepare for connection to be removed from - * the list on failure. - */ - sconntmp = service_connection_next(sconn); - sock = service_connection_get_sock(sconn); - if (FD_ISSET(sock, &fds)) { - service_message(casserv->cs_service, - sconn); - } - } - } - } -} - -static void -usage(void) -{ - - pjdlog_exitx(1, - "usage: casperd [-Fhv] [-D servconfdir] [-P pidfile] [-S sockpath]"); -} - -int -main(int argc, char *argv[]) -{ - struct pidfh *pfh; - const char *pidfile, *servconfdir, *sockpath; - pid_t otherpid; - int ch, debug, lqlen; - bool foreground; - - pjdlog_init(PJDLOG_MODE_STD); - - debug = 0; - foreground = false; - lqlen = SOMAXCONN; - pidfile = CASPERD_PIDFILE; - servconfdir = CASPERD_SERVCONFDIR; - sockpath = CASPERD_SOCKPATH; - - while ((ch = getopt(argc, argv, "D:Fhl:P:S:v")) != -1) { - switch (ch) { - case 'D': - servconfdir = optarg; - break; - case 'F': - foreground = true; - break; - case 'l': - lqlen = strtol(optarg, NULL, 0); - if (lqlen < 1) - lqlen = SOMAXCONN; - break; - case 'P': - pidfile = optarg; - break; - case 'S': - sockpath = optarg; - break; - case 'v': - debug++; - break; - case 'h': - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (argc != 0) - usage(); - - if (!foreground) - pjdlog_mode_set(PJDLOG_MODE_SYSLOG); - pjdlog_prefix_set("(casperd) "); - pjdlog_debug_set(debug); - - if (zygote_init() < 0) - pjdlog_exit(1, "Unable to create zygote process"); - - pfh = pidfile_open(pidfile, 0600, &otherpid); - if (pfh == NULL) { - if (errno == EEXIST) { - pjdlog_exitx(1, "casperd already running, pid: %jd.", - (intmax_t)otherpid); - } - pjdlog_errno(LOG_WARNING, "Cannot open or create pidfile %s", - pidfile); - } - - if (!foreground) { - if (daemon(0, 0) == -1) { - KEEP_ERRNO((void)pidfile_remove(pfh)); - pjdlog_exit(1, "Unable to go into background"); - } - } - - /* Write PID to a file. */ - if (pidfile_write(pfh) == -1) { - pjdlog_errno(LOG_WARNING, "Unable to write to pidfile %s", - pidfile); - } else { - pjdlog_debug(1, "PID stored in %s.", pidfile); - } - - /* - * Register core services. - */ - service_register_core(); - /* - * Register external services. - */ - service_register_external(servconfdir); - - /* - * Wait for connections. - */ - main_loop(lqlen, sockpath, pfh); -} diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile index 533f8b845d7a..31e6153871bd 100644 --- a/sbin/ping/Makefile +++ b/sbin/ping/Makefile @@ -11,8 +11,9 @@ WARNS?= 3 LIBADD= m .if ${MK_CASPER} != "no" && !defined(RESCUE) -LIBADD+= capsicum -CFLAGS+=-DHAVE_LIBCAPSICUM +LIBADD+= casper +LIBADD+= cap_dns +CFLAGS+=-DHAVE_LIBCASPER .endif .if !defined(RELEASE_CRUNCH) diff --git a/sbin/ping/Makefile.depend b/sbin/ping/Makefile.depend index 35832c24038f..52225631112a 100644 --- a/sbin/ping/Makefile.depend +++ b/sbin/ping/Makefile.depend @@ -9,7 +9,8 @@ DIRDEPS = \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ - lib/libcapsicum \ + lib/libcasper/libcasper \ + lib/libcasper/services \ lib/libcompiler_rt \ lib/libipsec \ lib/libnv \ diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c index 23d5696b3ea2..1831cb71b30a 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -75,10 +75,10 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef HAVE_LIBCAPSICUM -#include -#include -#include + +#ifdef HAVE_LIBCASPER +#include +#include #endif #ifdef IPSEC @@ -204,13 +204,13 @@ static double tsumsq = 0.0; /* sum of all times squared, for std. dev. */ static volatile sig_atomic_t finish_up; static volatile sig_atomic_t siginfo_p; -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER static cap_channel_t *capdns; #endif static void fill(char *, char *); static u_short in_cksum(u_short *, int); -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER static cap_channel_t *capdns_setup(void); #endif static void check_status(void); @@ -553,7 +553,7 @@ main(int argc, char *const *argv) if (options & F_PINGFILLED) { fill((char *)datap, payload); } -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER capdns = capdns_setup(); #endif if (source) { @@ -562,7 +562,7 @@ main(int argc, char *const *argv) if (inet_aton(source, &sock_in.sin_addr) != 0) { shostname = source; } else { -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER if (capdns != NULL) hp = cap_gethostbyname2(capdns, source, AF_INET); @@ -596,7 +596,7 @@ main(int argc, char *const *argv) if (inet_aton(target, &to->sin_addr) != 0) { hostname = target; } else { -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER if (capdns != NULL) hp = cap_gethostbyname2(capdns, target, AF_INET); else @@ -614,7 +614,7 @@ main(int argc, char *const *argv) hostname = hnamebuf; } -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER /* From now on we will use only reverse DNS lookups. */ if (capdns != NULL) { const char *types[1]; @@ -722,7 +722,7 @@ main(int argc, char *const *argv) if (options & F_NUMERIC) cansandbox = true; -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER else if (capdns != NULL) cansandbox = true; #endif @@ -1704,7 +1704,7 @@ pr_addr(struct in_addr ina) if (options & F_NUMERIC) return inet_ntoa(ina); -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER if (capdns != NULL) hp = cap_gethostbyaddr(capdns, (char *)&ina, 4, AF_INET); else @@ -1788,7 +1788,7 @@ fill(char *bp, char *patp) } } -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER static cap_channel_t * capdns_setup(void) { @@ -1797,10 +1797,8 @@ capdns_setup(void) int families[1]; capcas = cap_init(); - if (capcas == NULL) { - warn("unable to contact casperd"); - return (NULL); - } + if (capcas == NULL) + err(1, "unable to create casper process"); capdnsloc = cap_service_open(capcas, "system.dns"); /* Casper capability no longer needed. */ cap_close(capcas); @@ -1816,7 +1814,7 @@ capdns_setup(void) return (capdnsloc); } -#endif /* HAVE_LIBCAPSICUM */ +#endif /* HAVE_LIBCASPER */ #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) #define SECOPT " [-P policy]" diff --git a/share/man/man4/capsicum.4 b/share/man/man4/capsicum.4 index 1d208b04a94c..afdf5862c8dc 100644 --- a/share/man/man4/capsicum.4 +++ b/share/man/man4/capsicum.4 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 25, 2015 +.Dd February 25, 2016 .Dt CAPSICUM 4 .Os .Sh NAME @@ -104,9 +104,8 @@ associated with file descriptors; described in greater detail in .Xr shm_open 2 , .Xr write 2 , .Xr cap_rights_get 3 , -.Xr libcapsicum 3 , +.Xr casper 3 , .Xr procdesc 4 , -.Xr casperd 8 .Sh HISTORY .Nm first appeared in diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index d22f99a89c10..6db697363d5d 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -30,7 +30,6 @@ LIBBZ2?= ${DESTDIR}${LIBDIR}/libbz2.a LIBC?= ${DESTDIR}${LIBDIR}/libc.a LIBCALENDAR?= ${DESTDIR}${LIBDIR}/libcalendar.a LIBCAM?= ${DESTDIR}${LIBDIR}/libcam.a -LIBCAPSICUM?= ${DESTDIR}${LIBDIR}/libcapsicum.a LIBCASPER?= ${DESTDIR}${LIBDIR}/libcasper.a LIBCOMPAT?= ${DESTDIR}${LIBDIR}/libcompat.a LIBCOMPILER_RT?=${DESTDIR}${LIBDIR}/libcompiler_rt.a diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index d27597f6641b..902f4fb371bd 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -68,8 +68,12 @@ _LIBRARIES= \ c_pic \ calendar \ cam \ - capsicum \ casper \ + cap_dns \ + cap_grp \ + cap_pwd \ + cap_random \ + cap_sysctl \ com_err \ compiler_rt \ crypt \ @@ -211,9 +215,13 @@ _DP_bsnmp= crypto .endif _DP_geom= bsdxml sbuf _DP_cam= sbuf -_DP_casper= capsicum nv pjdlog -_DP_capsicum= nv _DP_kvm= elf +_DP_casper= nv +_DP_cap_dns= nv +_DP_cap_grp= nv +_DP_cap_pwd= nv +_DP_cap_random= nv +_DP_cap_sysctl= nv _DP_pjdlog= util _DP_opie= md _DP_usb= pthread @@ -507,6 +515,25 @@ LIBTERMCAPWDIR= ${LIBNCURSESWDIR} LIB${lib:tu}DIR?= ${OBJTOP}/lib/lib${lib} .endfor +# Casper exception. +LIBCAP_CASPERDIR= ${OBJTOP}/lib/libcasper/libcasper +LIBCAP_CASPER= ${DESTDIR}${LIBDIR}/libcasper.a + +LIBCAP_DNSDIR= ${OBJTOP}/lib/libcasper/services/cap_dns +LIBCAP_DNS?= ${DESTDIR}${LIBDIR}/libcap_dns.a + +LIBCAP_GRPDIR= ${OBJTOP}/lib/libcasper/services/cap_grp +LIBCAP_GRP?= ${DESTDIR}${LIBDIR}/libcap_grp.a + +LIBCAP_PWDDIR= ${OBJTOP}/lib/libcasper/services/cap_pwd +LIBCAP_PWD?= ${DESTDIR}${LIBDIR}/libcap_pwd.a + +LIBCAP_RANDOMDIR= ${OBJTOP}/lib/libcasper/services/cap_random +LIBCAP_RANDOM?= ${DESTDIR}${LIBDIR}/libcap_random.a + +LIBCAP_SYSCTLDIR= ${OBJTOP}/lib/libcasper/services/cap_sysctl +LIBCAP_SYSCTL?= ${DESTDIR}${LIBDIR}/libcap_sysctl.a + # Validate that listed LIBADD are valid. .for _l in ${LIBADD} .if empty(_LIBRARIES:M${_l}) diff --git a/targets/pseudo/userland/Makefile.depend b/targets/pseudo/userland/Makefile.depend index cebce7cdc24f..dcb870656f6a 100644 --- a/targets/pseudo/userland/Makefile.depend +++ b/targets/pseudo/userland/Makefile.depend @@ -894,10 +894,6 @@ DIRDEPS.powerpc= \ DIRDEPS+= usr.bin/dtc .endif -.if ${MK_CASPER} == "yes" -DIRDEPS+= sbin/casperd -.endif - DIRDEPS+= ${DIRDEPS.${MACHINE}:U} diff --git a/targets/pseudo/userland/lib/Makefile.depend b/targets/pseudo/userland/lib/Makefile.depend index 1b2c35b56b59..bfd444f96a66 100644 --- a/targets/pseudo/userland/lib/Makefile.depend +++ b/targets/pseudo/userland/lib/Makefile.depend @@ -33,7 +33,6 @@ DIRDEPS = \ lib/libc++ \ lib/libcalendar \ lib/libcam \ - lib/libcasper \ lib/libcom_err/doc \ lib/libcompat \ lib/libcompiler_rt \ @@ -187,4 +186,15 @@ DIRDEPS+= \ DIRDEPS+= lib/libnandfs .endif +.if ${MK_CASPER} != "no" +DIRDEPS+= \ + lib/libcasper \ + lib/libcasper/services/cap_dns \ + lib/libcasper/services/cap_grp \ + lib/libcasper/services/cap_pwd \ + lib/libcasper/services/cap_random \ + lib/libcasper/services/cap_sysctl \ + +.endif + .include diff --git a/targets/pseudo/userland/libexec/Makefile.depend b/targets/pseudo/userland/libexec/Makefile.depend index 427268ce93fe..6bdd31e64225 100644 --- a/targets/pseudo/userland/libexec/Makefile.depend +++ b/targets/pseudo/userland/libexec/Makefile.depend @@ -10,11 +10,6 @@ DIRDEPS = \ libexec/bootpd/bootpgw \ libexec/bootpd/tools/bootpef \ libexec/bootpd/tools/bootptest \ - libexec/casper/dns \ - libexec/casper/grp \ - libexec/casper/pwd \ - libexec/casper/random \ - libexec/casper/sysctl \ libexec/comsat \ libexec/fingerd \ libexec/ftpd \ diff --git a/tools/regression/capsicum/libcapsicum/Makefile b/tools/regression/capsicum/libcasper/Makefile similarity index 87% rename from tools/regression/capsicum/libcapsicum/Makefile rename to tools/regression/capsicum/libcasper/Makefile index 468fa334d3fa..b024c3b50121 100644 --- a/tools/regression/capsicum/libcapsicum/Makefile +++ b/tools/regression/capsicum/libcasper/Makefile @@ -12,7 +12,6 @@ CFLAGS+= -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wunused-parameter CFLAGS+= -Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls CFLAGS+= -Wold-style-definition -Wno-pointer-sign -CFLAGS+= -I${.CURDIR}/../../../../lib/libcapsicum CFLAGS+= -ggdb SERVTEST= ${SERVICES:=.t} @@ -22,7 +21,7 @@ all: ${SERVTEST} .for SERVICE in ${SERVICES} ${SERVICE}.t: ${SERVICE}.c - ${CC} ${CFLAGS} ${@:.t=.c} -o $@ -lcapsicum -lnv + ${CC} ${CFLAGS} ${@:.t=.c} -o $@ -lnv -lcasper -lcap_${@:.t=} .endfor diff --git a/tools/regression/capsicum/libcapsicum/dns.c b/tools/regression/capsicum/libcasper/dns.c similarity index 99% rename from tools/regression/capsicum/libcapsicum/dns.c rename to tools/regression/capsicum/libcasper/dns.c index 4426bf31e6f3..eb364daf8cd2 100644 --- a/tools/regression/capsicum/libcapsicum/dns.c +++ b/tools/regression/capsicum/libcasper/dns.c @@ -44,9 +44,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include +#include + +#include static int ntest = 1; diff --git a/tools/regression/capsicum/libcapsicum/grp.c b/tools/regression/capsicum/libcasper/grp.c similarity index 99% rename from tools/regression/capsicum/libcapsicum/grp.c rename to tools/regression/capsicum/libcasper/grp.c index dbffeaf2c72e..7b8ada590a03 100644 --- a/tools/regression/capsicum/libcapsicum/grp.c +++ b/tools/regression/capsicum/libcasper/grp.c @@ -41,9 +41,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include +#include + +#include static int ntest = 1; diff --git a/tools/regression/capsicum/libcapsicum/pwd.c b/tools/regression/capsicum/libcasper/pwd.c similarity index 99% rename from tools/regression/capsicum/libcapsicum/pwd.c rename to tools/regression/capsicum/libcasper/pwd.c index 23e81a3dd923..b1027004491d 100644 --- a/tools/regression/capsicum/libcapsicum/pwd.c +++ b/tools/regression/capsicum/libcasper/pwd.c @@ -41,9 +41,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include +#include + +#include static int ntest = 1; diff --git a/tools/regression/capsicum/libcapsicum/sysctl.c b/tools/regression/capsicum/libcasper/sysctl.c similarity index 99% rename from tools/regression/capsicum/libcapsicum/sysctl.c rename to tools/regression/capsicum/libcasper/sysctl.c index f3ae30738346..f3268204313d 100644 --- a/tools/regression/capsicum/libcapsicum/sysctl.c +++ b/tools/regression/capsicum/libcasper/sysctl.c @@ -44,9 +44,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include +#include + +#include /* * We need some sysctls to perform the tests on. diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile index 40109f0ca3ab..f80f6684a9e5 100644 --- a/usr.bin/kdump/Makefile +++ b/usr.bin/kdump/Makefile @@ -11,8 +11,10 @@ CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I. LIBADD= sysdecode .if ${MK_CASPER} != "no" -LIBADD+= capsicum -CFLAGS+=-DHAVE_LIBCAPSICUM +LIBADD+= casper +LIBADD+= cap_grp +LIBADD+= cap_pwd +CFLAGS+=-DHAVE_LIBCASPER .endif NO_WERROR?= YES diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 52001d245674..e45a7332eed3 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -61,7 +61,7 @@ extern int errno; #include #include #include -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER #include #endif #include @@ -70,12 +70,6 @@ extern int errno; #include #include #include -#ifdef HAVE_LIBCAPSICUM -#include -#include -#include -#include -#endif #include #include #include @@ -91,6 +85,13 @@ extern int errno; #include "ktrace.h" #include "kdump_subr.h" +#ifdef HAVE_LIBCASPER +#include + +#include +#include +#endif + u_int abidump(struct ktr_header *); int fetchprocinfo(struct ktr_header *, u_int *); int fread_tail(void *, int, int); @@ -151,7 +152,7 @@ struct proc_info static TAILQ_HEAD(trace_procs, proc_info) trace_procs; -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER static cap_channel_t *cappwd, *capgrp; #endif @@ -180,7 +181,7 @@ localtime_init(void) (void)localtime(<ime); } -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER static int cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) { @@ -189,8 +190,8 @@ cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) capcas = cap_init(); if (capcas == NULL) { - warn("unable to contact casperd"); - return (-1); + err(1, "unable to create casper process"); + exit(1); } cappwdloc = cap_service_open(capcas, "system.pwd"); capgrploc = cap_service_open(capcas, "system.grp"); @@ -222,7 +223,7 @@ cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) *capgrpp = capgrploc; return (0); } -#endif /* HAVE_LIBCAPSICUM */ +#endif /* HAVE_LIBCASPER */ int main(int argc, char *argv[]) @@ -302,7 +303,7 @@ main(int argc, char *argv[]) strerror_init(); localtime_init(); -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER if (resolv != 0) { if (cappwdgrp_setup(&cappwd, &capgrp) < 0) { cappwd = NULL; @@ -1648,7 +1649,7 @@ ktrstat(struct stat *statp) if (resolv == 0) { pwd = NULL; } else { -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER if (cappwd != NULL) pwd = cap_getpwuid(cappwd, statp->st_uid); else @@ -1662,7 +1663,7 @@ ktrstat(struct stat *statp) if (resolv == 0) { grp = NULL; } else { -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER if (capgrp != NULL) grp = cap_getgrgid(capgrp, statp->st_gid); else diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile index d54b9bf93e38..ec585f4931ca 100644 --- a/usr.sbin/tcpdump/tcpdump/Makefile +++ b/usr.sbin/tcpdump/tcpdump/Makefile @@ -177,8 +177,9 @@ CFLAGS+= -DLBL_ALIGN LIBADD= l pcap .if ${MK_CASPER} != "no" -LIBADD+= capsicum -CFLAGS+=-DHAVE_CAPSICUM +LIBADD+= casper +LIBADD+= cap_dns +CFLAGS+=-DHAVE_CASPER .endif .if ${MK_OPENSSL} != "no" LIBADD+= crypto diff --git a/usr.sbin/tcpdump/tcpdump/config.h b/usr.sbin/tcpdump/tcpdump/config.h index a3e6f3ddb6f5..dbd03f7e73bf 100644 --- a/usr.sbin/tcpdump/tcpdump/config.h +++ b/usr.sbin/tcpdump/tcpdump/config.h @@ -15,7 +15,7 @@ /* capsicum support available */ /* See Makefile */ -/* #undef HAVE_CAPSICUM */ +/* #undef HAVE_CAPSPER */ /* Define to 1 if you have the `cap_enter' function. */ #define HAVE_CAP_ENTER 1