diff options
author | oshogbo <oshogbo@FreeBSD.org> | 2016-02-25 18:23:40 +0000 |
---|---|---|
committer | oshogbo <oshogbo@FreeBSD.org> | 2016-02-25 18:23:40 +0000 |
commit | 023f14d65b31db71d1a4e6655205dd919bfeb5fb (patch) | |
tree | faa5b7886c70249c03078cb4861e837c2d0f6582 | |
parent | 85f8ae969b95a5539c68ffb09c545b5023901f4e (diff) | |
download | FreeBSD-src-023f14d65b31db71d1a4e6655205dd919bfeb5fb.zip FreeBSD-src-023f14d65b31db71d1a4e6655205dd919bfeb5fb.tar.gz |
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
85 files changed, 2072 insertions, 2997 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1 index ed0415b..5bd9cfa 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 f49544e..d321abb 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 ca04e94..dec561a 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 b02d0f7..e224606 100644 --- a/contrib/tcpdump/addrtoname.c +++ b/contrib/tcpdump/addrtoname.c @@ -29,10 +29,10 @@ #include "config.h" #endif -#ifdef HAVE_CAPSICUM -#include <libcapsicum.h> -#include <libcapsicum_dns.h> -#endif /* HAVE_CAPSICUM */ +#ifdef HAVE_CAPSPER +#include <libcasper.h> +#include <casper/cap_dns.h> +#endif /* HAVE_CAPSPER */ #include <tcpdump-stdinc.h> #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 914289a..f233245 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 43b3068..390af31 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 a629559..b5ac48f 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 ed3ce5e..bc0c5ee 100644 --- a/contrib/tcpdump/tcpdump.c +++ b/contrib/tcpdump/tcpdump.c @@ -87,17 +87,16 @@ extern int SIZE_BUF; #include <sys/capsicum.h> #include <sys/sysctl.h> #endif /* __FreeBSD__ */ -#ifdef HAVE_CAPSICUM -#include <libcapsicum.h> -#include <libcapsicum_dns.h> -#include <libcapsicum_service.h> +#ifdef HAVE_CAPSPER +#include <libcasper.h> +#include <casper/cap_dns.h> #include <sys/nv.h> #include <sys/capability.h> #include <sys/ioccom.h> #include <net/bpf.h> #include <fcntl.h> #include <libgen.h> -#endif /* HAVE_CAPSICUM */ +#endif /* HAVE_CAPSPER */ #include <pcap.h> #include <signal.h> #include <stdio.h> @@ -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 12bf3f2..32bac4d 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 4a499ea..2f0aae9 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 88e80e6..a9baa7e 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 af2f6a9..1c1a1dd 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 1e6e28f..6cc860b 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 0b80169..0000000 --- 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 e7ec4cf..046b16b 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 699aa6a..cfa0ea9 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 257b6f5..02fb3ef 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 6ee5bb8..0000000 --- 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 <bsd.lib.mk> diff --git a/lib/libcapsicum/Makefile.depend b/lib/libcapsicum/Makefile.depend deleted file mode 100644 index 4f7989b..0000000 --- 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 <dirdeps.mk> - -.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 5f54283..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/nv.h> - -#include <assert.h> -#include <netdb.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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 ce6f49f..0000000 --- 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 5b44c34..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/nv.h> - -#include <assert.h> -#include <errno.h> -#include <pwd.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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 6b6ceea..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/nv.h> - -#include <assert.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> - -#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 3f1ccd9..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/nv.h> - -#include <errno.h> -#include <string.h> - -#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 e57accd..af0701b 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 <bsd.lib.mk> +.include <bsd.subdir.mk> diff --git a/lib/libcasper/libcasper.h b/lib/libcasper/libcasper.h deleted file mode 100644 index 91d6027..0000000 --- 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 0000000..2a123ac --- /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 <bsd.lib.mk> diff --git a/lib/libcapsicum/libcapsicum.3 b/lib/libcasper/libcasper/libcasper.3 index cbfd214..220b5b3 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 index 8c4d04d..f23d8b1 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 <oshogbo@FreeBSD.org> * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -32,19 +33,18 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/socket.h> -#include <sys/un.h> #include <sys/nv.h> +#include <sys/procdesc.h> #include <assert.h> #include <errno.h> -#include <fcntl.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#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 index c7110d8..2d6f158 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 <oshogbo@FreeBSD.org> * 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 <sys/types.h> #ifndef _NVLIST_T_DECLARED #define _NVLIST_T_DECLARED @@ -47,11 +50,18 @@ 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. */ cap_channel_t *cap_wrap(int sock); @@ -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 index 05c654f..57d4899 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 <oshogbo@FreeBSD.org> * 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 <errno.h> +#include <fcntl.h> +#include <stdlib.h> -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 0000000..bf2e6ce --- /dev/null +++ b/lib/libcasper/libcasper/libcasper_impl.h @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org> + * 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 <stdbool.h> + +#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 0000000..5b1c7c8 --- /dev/null +++ b/lib/libcasper/libcasper/libcasper_service.c @@ -0,0 +1,277 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/nv.h> + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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 index 320f21a..4efbeb2 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 <oshogbo@FreeBSD.org> * 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 index e241888..e02d7d9 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 <oshogbo@FreeBSD.org> * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -31,11 +32,8 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> -#include <sys/capsicum.h> #include <sys/queue.h> #include <sys/socket.h> -#include <sys/stat.h> -#include <sys/un.h> #include <sys/nv.h> #include <assert.h> @@ -50,10 +48,8 @@ __FBSDID("$FreeBSD$"); #include <strings.h> #include <unistd.h> -#include <libcapsicum.h> -#include <libcasper.h> -#include <libcasper_impl.h> -#include <pjdlog.h> +#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) { - struct service *service; - struct service_connection *sconn, *sconntmp; - fd_set fds; - int maxfd, nfds, serrno; - assert(argc == 2); + assert(service->s_magic == SERVICE_MAGIC); + return (service->s_name); +} - pjdlog_init(PJDLOG_MODE_STD); - pjdlog_debug_set(atoi(argv[1])); +void +service_start(struct service *service, int sock) +{ + struct service_connection *sconn, *sconntmp; + fd_set fds; + int maxfd, nfds; - 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 index 5bc9396..e554a3e 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 <oshogbo@FreeBSD.org> * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -45,10 +46,6 @@ __FBSDID("$FreeBSD$"); #include <strings.h> #include <unistd.h> -#include <libcapsicum.h> -#include <libcapsicum_impl.h> -#include <pjdlog.h> - #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 index 4c9c771..e147287 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 <oshogbo@FreeBSD.org> * 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 0000000..39b79af --- /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 <bsd.subdir.mk> diff --git a/lib/libcasper/services/cap_dns/Makefile b/lib/libcasper/services/cap_dns/Makefile new file mode 100644 index 0000000..871975d --- /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 <bsd.lib.mk> diff --git a/libexec/casper/dns/dns.c b/lib/libcasper/services/cap_dns/cap_dns.c index dbdb2a2..873af4c 100644 --- a/libexec/casper/dns/dns.c +++ b/lib/libcasper/services/cap_dns/cap_dns.c @@ -30,6 +30,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/dnv.h> #include <sys/nv.h> #include <netinet/in.h> @@ -38,12 +39,341 @@ __FBSDID("$FreeBSD$"); #include <netdb.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> -#include <libcapsicum.h> -#include <libcapsicum_dns.h> #include <libcasper.h> -#include <pjdlog.h> +#include <libcasper_service.h> +#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 index 0223510..ea37542 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 <sys/socket.h> /* 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 0000000..81b9477 --- /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 <bsd.lib.mk> diff --git a/lib/libcapsicum/libcapsicum_grp.c b/lib/libcasper/services/cap_grp/cap_grp.c index 44d573e..d358cea 100644 --- a/lib/libcapsicum/libcapsicum_grp.c +++ b/lib/libcasper/services/cap_grp/cap_grp.c @@ -39,10 +39,11 @@ __FBSDID("$FreeBSD$"); #include <grp.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> -#include "libcapsicum.h" -#include "libcapsicum_grp.h" +#include <libcasper.h> +#include <libcasper_service.h> + +#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 index e0b44f0..68595c1 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 0000000..34b8a12 --- /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 <bsd.lib.mk> diff --git a/libexec/casper/pwd/pwd.c b/lib/libcasper/services/cap_pwd/cap_pwd.c index 0a06c5f..254e244 100644 --- a/libexec/casper/pwd/pwd.c +++ b/lib/libcasper/services/cap_pwd/cap_pwd.c @@ -30,17 +30,372 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/types.h> #include <sys/nv.h> +#include <assert.h> #include <errno.h> #include <pwd.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> -#include <libcapsicum.h> #include <libcasper.h> -#include <pjdlog.h> +#include <libcasper_service.h> +#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 index 960a490..a75fba7 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 0000000..2447236 --- /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 <bsd.lib.mk> diff --git a/lib/libcapsicum/libcapsicum_random.c b/lib/libcasper/services/cap_random/cap_random.c index 2a7b109..d19fe96 100644 --- a/lib/libcapsicum/libcapsicum_random.c +++ b/lib/libcasper/services/cap_random/cap_random.c @@ -34,10 +34,14 @@ __FBSDID("$FreeBSD$"); #include <assert.h> #include <errno.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include "libcapsicum.h" -#include "libcapsicum_random.h" +#include <libcasper.h> +#include <libcasper_service.h> + +#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 index 672afa0..2039b5f 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 0000000..779ed7e --- /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 <bsd.lib.mk> diff --git a/libexec/casper/sysctl/sysctl.c b/lib/libcasper/services/cap_sysctl/cap_sysctl.c index 4cbc505..7611d64 100644 --- a/libexec/casper/sysctl/sysctl.c +++ b/lib/libcasper/services/cap_sysctl/cap_sysctl.c @@ -34,15 +34,66 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/nv.h> +#include <assert.h> #include <errno.h> #include <stdlib.h> #include <string.h> -#include <libcapsicum.h> -#include <libcapsicum_sysctl.h> #include <libcasper.h> -#include <pjdlog.h> +#include <libcasper_service.h> +#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 index d0df143..2af6d21 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 a8ace18..b60cc34 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 ed6bd7b..0000000 --- a/libexec/casper/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD$ - -.include <bsd.own.mk> - -SUBDIR= dns -SUBDIR+=grp -SUBDIR+=pwd -SUBDIR+=random -SUBDIR+=sysctl - -.include <bsd.subdir.mk> diff --git a/libexec/casper/dns/Makefile b/libexec/casper/dns/Makefile deleted file mode 100644 index b101891..0000000 --- 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 <bsd.prog.mk> diff --git a/libexec/casper/grp/Makefile b/libexec/casper/grp/Makefile deleted file mode 100644 index 75274d1..0000000 --- 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 <bsd.prog.mk> diff --git a/libexec/casper/grp/grp.c b/libexec/casper/grp/grp.c deleted file mode 100644 index 5b3e13d..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/nv.h> - -#include <assert.h> -#include <errno.h> -#include <grp.h> -#include <stdlib.h> -#include <string.h> - -#include <libcapsicum.h> -#include <libcasper.h> -#include <pjdlog.h> - -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 23ad3f2..0000000 --- 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 <bsd.prog.mk> diff --git a/libexec/casper/random/Makefile b/libexec/casper/random/Makefile deleted file mode 100644 index 3b5d155..0000000 --- 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 <bsd.prog.mk> diff --git a/libexec/casper/random/random.c b/libexec/casper/random/random.c deleted file mode 100644 index db91685..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/nv.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> - -#include <libcapsicum.h> -#include <libcasper.h> -#include <pjdlog.h> - -#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 24152ab..0000000 --- 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 <bsd.prog.mk> diff --git a/libexec/rtld-elf/paths.h b/libexec/rtld-elf/paths.h index 7d9d372..69b1d03 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 3b17e10..affca8e 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 93f145c..0000000 --- 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 <bsd.prog.mk> diff --git a/sbin/casperd/casperd.8 b/sbin/casperd/casperd.8 deleted file mode 100644 index 945b517..0000000 --- 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 65da58a..0000000 --- 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/capsicum.h> -#include <sys/queue.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/un.h> -#include <sys/nv.h> - -#include <assert.h> -#include <dirent.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <libutil.h> -#include <paths.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> - -#include <libcapsicum.h> -#include <libcapsicum_impl.h> -#include <libcasper.h> -#include <libcasper_impl.h> -#include <msgio.h> -#include <pjdlog.h> - -#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 533f8b8..31e6153 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 35832c2..5222563 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 23d5696..1831cb7 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -75,10 +75,10 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_icmp.h> #include <netinet/ip_var.h> #include <arpa/inet.h> -#ifdef HAVE_LIBCAPSICUM -#include <libcapsicum.h> -#include <libcapsicum_dns.h> -#include <libcapsicum_service.h> + +#ifdef HAVE_LIBCASPER +#include <libcasper.h> +#include <casper/cap_dns.h> #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 1d208b0..afdf586 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 d22f99a..6db6973 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 d27597f..902f4fb 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 cebce7c..dcb8706 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 1b2c35b..bfd444f 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 <dirdeps.mk> diff --git a/targets/pseudo/userland/libexec/Makefile.depend b/targets/pseudo/userland/libexec/Makefile.depend index 427268c..6bdd31e 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 index 468fa33..b024c3b 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 index 4426bf3..eb364da 100644 --- a/tools/regression/capsicum/libcapsicum/dns.c +++ b/tools/regression/capsicum/libcasper/dns.c @@ -44,9 +44,9 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> -#include <libcapsicum.h> -#include <libcapsicum_dns.h> -#include <libcapsicum_service.h> +#include <libcasper.h> + +#include <casper/cap_dns.h> static int ntest = 1; diff --git a/tools/regression/capsicum/libcapsicum/grp.c b/tools/regression/capsicum/libcasper/grp.c index dbffeaf..7b8ada5 100644 --- a/tools/regression/capsicum/libcapsicum/grp.c +++ b/tools/regression/capsicum/libcasper/grp.c @@ -41,9 +41,9 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> -#include <libcapsicum.h> -#include <libcapsicum_grp.h> -#include <libcapsicum_service.h> +#include <libcasper.h> + +#include <casper/cap_grp.h> static int ntest = 1; diff --git a/tools/regression/capsicum/libcapsicum/pwd.c b/tools/regression/capsicum/libcasper/pwd.c index 23e81a3..b102700 100644 --- a/tools/regression/capsicum/libcapsicum/pwd.c +++ b/tools/regression/capsicum/libcasper/pwd.c @@ -41,9 +41,9 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> -#include <libcapsicum.h> -#include <libcapsicum_pwd.h> -#include <libcapsicum_service.h> +#include <libcasper.h> + +#include <casper/cap_pwd.h> static int ntest = 1; diff --git a/tools/regression/capsicum/libcapsicum/sysctl.c b/tools/regression/capsicum/libcasper/sysctl.c index f3ae307..f326820 100644 --- a/tools/regression/capsicum/libcapsicum/sysctl.c +++ b/tools/regression/capsicum/libcasper/sysctl.c @@ -44,9 +44,9 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> -#include <libcapsicum.h> -#include <libcapsicum_service.h> -#include <libcapsicum_sysctl.h> +#include <libcasper.h> + +#include <casper/cap_sysctl.h> /* * We need some sysctls to perform the tests on. diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile index 40109f0..f80f668 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 52001d2..e45a733 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -61,7 +61,7 @@ extern int errno; #include <sys/un.h> #include <sys/queue.h> #include <sys/wait.h> -#ifdef HAVE_LIBCAPSICUM +#ifdef HAVE_LIBCASPER #include <sys/nv.h> #endif #include <arpa/inet.h> @@ -70,12 +70,6 @@ extern int errno; #include <err.h> #include <grp.h> #include <inttypes.h> -#ifdef HAVE_LIBCAPSICUM -#include <libcapsicum.h> -#include <libcapsicum_grp.h> -#include <libcapsicum_pwd.h> -#include <libcapsicum_service.h> -#endif #include <locale.h> #include <netdb.h> #include <nl_types.h> @@ -91,6 +85,13 @@ extern int errno; #include "ktrace.h" #include "kdump_subr.h" +#ifdef HAVE_LIBCASPER +#include <libcasper.h> + +#include <casper/cap_grp.h> +#include <casper/cap_pwd.h> +#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 d54b9bf..ec585f4 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 a3e6f3d..dbd03f7 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 |