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
This commit is contained in:
parent
6fb8946b7f
commit
c501d73c7e
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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)")
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
2
contrib/tcpdump/configure
vendored
2
contrib/tcpdump/configure
vendored
@ -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; }
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -15,8 +15,6 @@
|
||||
lib
|
||||
geom
|
||||
..
|
||||
..
|
||||
libexec
|
||||
casper
|
||||
..
|
||||
..
|
||||
|
@ -93,6 +93,8 @@
|
||||
scsi
|
||||
..
|
||||
..
|
||||
casper
|
||||
..
|
||||
crypto
|
||||
..
|
||||
dev
|
||||
|
@ -80,12 +80,12 @@
|
||||
..
|
||||
..
|
||||
lib
|
||||
casper
|
||||
..
|
||||
geom
|
||||
..
|
||||
..
|
||||
libexec
|
||||
casper
|
||||
..
|
||||
resolvconf
|
||||
..
|
||||
..
|
||||
|
@ -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
|
||||
|
@ -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"
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ,
|
||||
|
@ -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>
|
@ -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
|
@ -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));
|
||||
}
|
@ -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_ */
|
@ -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));
|
||||
}
|
@ -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));
|
||||
}
|
@ -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);
|
||||
}
|
@ -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>
|
||||
|
@ -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_ */
|
38
lib/libcasper/libcasper/Makefile
Normal file
38
lib/libcasper/libcasper/Makefile
Normal file
@ -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>
|
@ -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
|
||||
.
|
@ -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);
|
||||
|
||||
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);
|
||||
close(sock[0]);
|
||||
close(pfd);
|
||||
errno = serrno;
|
||||
return (NULL);
|
||||
}
|
||||
ret = cap_add_pd(chan, pfd);
|
||||
assert(ret);
|
||||
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));
|
||||
}
|
@ -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,10 +50,17 @@ typedef struct cap_channel cap_channel_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The function opens unrestricted communication channel to Casper.
|
||||
* The functions opens unrestricted communication channel to Casper.
|
||||
*/
|
||||
cap_channel_t *cap_init(void);
|
||||
|
||||
/*
|
||||
* The functions to communicate with service.
|
||||
*/
|
||||
cap_channel_t *cap_service_open(const cap_channel_t *chan, const char *name);
|
||||
int cap_service_limit(const cap_channel_t *chan,
|
||||
const char * const *names, size_t nnames);
|
||||
|
||||
/*
|
||||
* The function creates cap_channel_t based on the given socket.
|
||||
*/
|
||||
@ -88,16 +98,6 @@ int cap_limit_set(const cap_channel_t *chan, nvlist_t *limits);
|
||||
*/
|
||||
int cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp);
|
||||
|
||||
#ifdef TODO
|
||||
/*
|
||||
* The function registers a service within provided Casper's capability.
|
||||
* It will run with the same privileges the process has at the time of
|
||||
* calling this function.
|
||||
*/
|
||||
int cap_service_register(cap_channel_t *chan, const char *name,
|
||||
cap_func_t *func);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function sends nvlist over the given capability.
|
||||
*/
|
||||
@ -112,4 +112,4 @@ nvlist_t *cap_recv_nvlist(const cap_channel_t *chan, int flags);
|
||||
*/
|
||||
nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags);
|
||||
|
||||
#endif /* !_LIBCAPSICUM_H_ */
|
||||
#endif /* !_LIBCASPER_H_ */
|
@ -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);
|
||||
}
|
82
lib/libcasper/libcasper/libcasper_impl.h
Normal file
82
lib/libcasper/libcasper/libcasper_impl.h
Normal file
@ -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_ */
|
277
lib/libcasper/libcasper/libcasper_service.c
Normal file
277
lib/libcasper/libcasper/libcasper_service.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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_ */
|
@ -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)
|
||||
{
|
||||
|
||||
assert(service->s_magic == SERVICE_MAGIC);
|
||||
return (service->s_name);
|
||||
}
|
||||
|
||||
void
|
||||
service_start(struct service *service, int sock)
|
||||
{
|
||||
struct service *service;
|
||||
struct service_connection *sconn, *sconntmp;
|
||||
fd_set fds;
|
||||
int maxfd, nfds, serrno;
|
||||
int maxfd, nfds;
|
||||
|
||||
assert(argc == 2);
|
||||
|
||||
pjdlog_init(PJDLOG_MODE_STD);
|
||||
pjdlog_debug_set(atoi(argv[1]));
|
||||
|
||||
service = service_alloc(name, limitfunc, commandfunc);
|
||||
if (service == NULL)
|
||||
return (errno);
|
||||
if (service_connection_add(service, sock, NULL) == NULL) {
|
||||
serrno = errno;
|
||||
service_free(service);
|
||||
return (serrno);
|
||||
}
|
||||
assert(service != NULL);
|
||||
assert(service->s_magic == SERVICE_MAGIC);
|
||||
setproctitle("%s", service->s_name);
|
||||
if (service_connection_add(service, sock, NULL) == NULL)
|
||||
exit(1);
|
||||
|
||||
for (;;) {
|
||||
FD_ZERO(&fds);
|
||||
@ -406,17 +360,16 @@ service_start(const char *name, int sock, service_limit_func_t *limitfunc,
|
||||
service_connection_get_sock(sconn));
|
||||
}
|
||||
|
||||
PJDLOG_ASSERT(maxfd >= 0);
|
||||
PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE);
|
||||
assert(maxfd >= 0);
|
||||
assert(maxfd + 1 <= (int)FD_SETSIZE);
|
||||
nfds = select(maxfd + 1, &fds, NULL, NULL, NULL);
|
||||
if (nfds < 0) {
|
||||
if (errno != EINTR)
|
||||
pjdlog_errno(LOG_ERR, "select() failed");
|
||||
exit(1);
|
||||
continue;
|
||||
} else if (nfds == 0) {
|
||||
/* Timeout. */
|
||||
PJDLOG_ABORT("select() timeout");
|
||||
continue;
|
||||
abort();
|
||||
}
|
||||
|
||||
for (sconn = service_connection_first(service); sconn != NULL;
|
||||
@ -437,5 +390,5 @@ service_start(const char *name, int sock, service_limit_func_t *limitfunc,
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
exit(0);
|
||||
}
|
@ -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,7 +123,6 @@ zygote_main(int sock)
|
||||
|
||||
setproctitle("zygote");
|
||||
|
||||
if (pjdlog_mode_get() != PJDLOG_MODE_STD)
|
||||
stdnull();
|
||||
for (fd = STDERR_FILENO + 1; fd < sock; fd++)
|
||||
close(fd);
|
||||
@ -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;
|
@ -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
|
9
lib/libcasper/services/Makefile
Normal file
9
lib/libcasper/services/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= cap_dns
|
||||
SUBDIR+= cap_grp
|
||||
SUBDIR+= cap_pwd
|
||||
SUBDIR+= cap_random
|
||||
SUBDIR+= cap_sysctl
|
||||
|
||||
.include <bsd.subdir.mk>
|
20
lib/libcasper/services/cap_dns/Makefile
Normal file
20
lib/libcasper/services/cap_dns/Makefile
Normal file
@ -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>
|
@ -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,7 +576,9 @@ dns_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
if (host != NULL)
|
||||
nvlist_move_string(nvlout, "host", host);
|
||||
if (serv != NULL)
|
||||
nvlist_move_string(nvlout, "serv", serv);
|
||||
out:
|
||||
if (error != 0) {
|
||||
@ -267,6 +599,7 @@ 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);
|
||||
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);
|
@ -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_ */
|
20
lib/libcasper/services/cap_grp/Makefile
Normal file
20
lib/libcasper/services/cap_grp/Makefile
Normal file
@ -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>
|
@ -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);
|
@ -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_ */
|
20
lib/libcasper/services/cap_pwd/Makefile
Normal file
20
lib/libcasper/services/cap_pwd/Makefile
Normal file
@ -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>
|
@ -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);
|
@ -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_ */
|
20
lib/libcasper/services/cap_random/Makefile
Normal file
20
lib/libcasper/services/cap_random/Makefile
Normal file
@ -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>
|
@ -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);
|
@ -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_ */
|
20
lib/libcasper/services/cap_sysctl/Makefile
Normal file
20
lib/libcasper/services/cap_sysctl/Makefile
Normal file
@ -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>
|
@ -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);
|
@ -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_ */
|
@ -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
|
||||
|
@ -1,11 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= dns
|
||||
SUBDIR+=grp
|
||||
SUBDIR+=pwd
|
||||
SUBDIR+=random
|
||||
SUBDIR+=sysctl
|
||||
|
||||
.include <bsd.subdir.mk>
|
@ -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>
|
@ -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>
|
@ -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));
|
||||
}
|
@ -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>
|
@ -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>
|
@ -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));
|
||||
}
|
@ -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>
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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.
|
@ -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);
|
||||
}
|
@ -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)
|
||||
|
@ -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 \
|
||||
|
@ -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]"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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})
|
||||
|
@ -894,10 +894,6 @@ DIRDEPS.powerpc= \
|
||||
DIRDEPS+= usr.bin/dtc
|
||||
.endif
|
||||
|
||||
.if ${MK_CASPER} == "yes"
|
||||
DIRDEPS+= sbin/casperd
|
||||
.endif
|
||||
|
||||
DIRDEPS+= ${DIRDEPS.${MACHINE}:U}
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user