Remove lib/libcapsicum and libexec/casper, brought back as

part of a merge mishap.

Reported by:	junovitch
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Glen Barber 2016-04-17 02:51:04 +00:00
parent 0937924af2
commit 659a0a5d64
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298139
34 changed files with 0 additions and 4358 deletions

View file

@ -1,47 +0,0 @@
# $FreeBSD$
PACKAGE= lib${LIB}
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>

View file

@ -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

View file

@ -1,300 +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 May 2, 2015
.Dt LIBCAPSICUM 3
.Os
.Sh NAME
.Nm cap_init ,
.Nm cap_wrap ,
.Nm cap_unwrap ,
.Nm cap_sock ,
.Nm cap_clone ,
.Nm cap_close ,
.Nm cap_limit_get ,
.Nm cap_limit_set ,
.Nm cap_send_nvlist ,
.Nm cap_recv_nvlist ,
.Nm cap_xfer_nvlist ,
.Nm cap_service_open
.Nd "library for handling application capabilities"
.Sh LIBRARY
.Lb libcapsicum
.Sh SYNOPSIS
.In libcapsicum.h
.In nv.h
.Ft "cap_channel_t *"
.Fn cap_init "void"
.Ft "cap_channel_t *"
.Fn cap_wrap "int sock"
.Ft "int"
.Fn cap_unwrap "cap_channel_t *chan"
.Ft "int"
.Fn cap_sock "const cap_channel_t *chan"
.Ft "cap_channel_t *"
.Fn cap_clone "const cap_channel_t *chan"
.Ft "void"
.Fn cap_close "cap_channel_t *chan"
.Ft "int"
.Fn cap_limit_get "const cap_channel_t *chan" "nvlist_t **limitsp"
.Ft "int"
.Fn cap_limit_set "const cap_channel_t *chan" "nvlist_t *limits"
.Ft "int"
.Fn cap_send_nvlist "const cap_channel_t *chan" "const nvlist_t *nvl"
.Ft "nvlist_t *"
.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.
.Pp
The application capability (represented by the
.Vt cap_channel_t
type) is a communication channel between the caller and the
.Xr casperd 8
daemon or an instance of one of its services.
A capability to the
.Xr casperd 8
daemon obtained with the
.Fn cap_init
function allows to create capabilities to casper's services via the
.Fn cap_service_open
function.
.Pp
The
.Fn cap_init
function opens capability to the
.Xr casperd 8
daemon.
.Pp
The
.Fn cap_wrap
function creates
.Vt cap_channel_t
based on the given socket.
The function is used when capability is inherited through
.Xr execve 2
or send over
.Xr unix 4
domain socket as a regular file descriptor and has to be represented as
.Vt cap_channel_t
again.
.Pp
The
.Fn cap_unwrap
function is the opposite of the
.Fn cap_wrap
function.
It frees the
.Vt cap_channel_t
structure and returns
.Xr unix 4
domain socket associated with it.
.Pp
The
.Fn cap_clone
function clones the given capability.
.Pp
The
.Fn cap_close
function closes the given capability.
.Pp
The
.Fn cap_sock
function returns
.Xr unix 4
domain socket descriptor associated with the given capability for use with
system calls like
.Xr kevent 2 ,
.Xr poll 2
and
.Xr select 2 .
.Pp
The
.Fn cap_limit_get
function stores current limits of the given capability in the
.Fa limitsp
argument.
If the function return
.Va 0
and
.Dv NULL
is stored in
.Fa limitsp
it means there are no limits set.
.Pp
The
.Fn cap_limit_set
function sets limits for the given capability.
The limits are provided as nvlist.
The exact format depends on the service the capability represents.
.Pp
The
.Fn cap_send_nvlist
function sends the given nvlist over the given capability.
This is low level interface to communicate with casper services.
Most services should provide higher level API.
.Pp
The
.Fn cap_recv_nvlist
function receives the given nvlist over the given capability.
The
.Fa flags
argument defines what type the top nvlist is expected to be.
If the nvlist flags do not match the flags passed to
.Fn cap_recv_nvlist ,
the nvlist will not be returned.
.Pp
The
.Fn cap_xfer_nvlist
function sends the given nvlist, destroys it and receives new nvlist in
response over the given capability.
The
.Fa flags
argument defines what type the top nvlist is expected to be.
If the nvlist flags do not match the flags passed to
.Fn cap_xfer_nvlist ,
the nvlist will not be returned.
It does not matter if the function succeeds or fails, the nvlist given
for sending will always be destroyed once the function returns.
.Pp
The
.Fn cap_service_open
function opens casper service of the given name through casper capability
obtained via the
.Fn cap_init
function.
The function returns capability that provides access to opened service.
.Sh RETURN VALUES
The
.Fn cap_clone ,
.Fn cap_init ,
.Fn cap_recv_nvlist ,
.Fn cap_service_open ,
.Fn cap_wrap
and
.Fn cap_xfer_nvlist
functions return
.Dv NULL
and set the
.Va errno
variable on failure.
.Pp
The
.Fn cap_limit_get ,
.Fn cap_limit_set
and
.Fn cap_send_nvlist
functions return
.Dv -1
and set the
.Va errno
variable on failure.
.Pp
The
.Fn cap_close ,
.Fn cap_sock
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
.Nm system.dns
casper service and uses the latter capability to resolve IP address.
.Bd -literal
cap_channel_t *capcas, *capdns;
nvlist_t *limits;
const char *ipstr = "127.0.0.1";
struct in_addr ip;
struct hostent *hp;
/* Open capability to the Casper daemon. */
capcas = cap_init();
if (capcas == NULL)
err(1, "Unable to contact Casper daemon");
/* Enter capability mode sandbox. */
if (cap_enter() < 0 && errno != ENOSYS)
err(1, "Unable to enter capability mode");
/* Use Casper capability to create capability to the system.dns service. */
capdns = cap_service_open(capcas, "system.dns");
if (capdns == NULL)
err(1, "Unable to open system.dns service");
/* Close Casper capability, we don't need it anymore. */
cap_close(capcas);
/* Limit system.dns to reverse DNS lookups and IPv4 addresses. */
limits = nvlist_create(0);
nvlist_add_string(limits, "type", "ADDR");
nvlist_add_number(limits, "family", (uint64_t)AF_INET);
if (cap_limit_set(capdns, limits) < 0)
err(1, "Unable to limit access to the system.dns service");
/* Convert IP address in C-string to in_addr. */
if (!inet_aton(ipstr, &ip))
errx(1, "Unable to parse IP address %s.", ipstr);
/* Find hostname for the given IP address. */
hp = cap_gethostbyaddr(capdns, (const void *)&ip, sizeof(ip), AF_INET);
if (hp == NULL)
errx(1, "No name associated with %s.", ipstr);
printf("Name associated with %s is %s.\\n", ipstr, hp->h_name);
.Ed
.Sh SEE ALSO
.Xr cap_enter 2 ,
.Xr execve 2 ,
.Xr kevent 2 ,
.Xr poll 2 ,
.Xr select 2 ,
.Xr cap_gethostbyaddr 3 ,
.Xr err 3 ,
.Xr gethostbyaddr 3 ,
.Xr inet_aton 3 ,
.Xr nv 3 ,
.Xr capsicum 4 ,
.Xr unix 4 ,
.Xr casperd 8
.Sh AUTHORS
The
.Nm libcapsicum
library was implemented by
.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
under sponsorship from the FreeBSD Foundation.

View file

@ -1,266 +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/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/nv.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"
/*
* Structure describing communication channel between two separated processes.
*/
#define CAP_CHANNEL_MAGIC 0xcac8a31
struct cap_channel {
/*
* Magic value helps to ensure that a pointer to the right structure is
* passed to our functions.
*/
int cch_magic;
/* Socket descriptor for IPC. */
int cch_sock;
};
bool
fd_is_valid(int fd)
{
return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
}
cap_channel_t *
cap_init(void)
{
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;
return (NULL);
}
chan = cap_wrap(sock);
if (chan == NULL) {
serrno = errno;
close(sock);
errno = serrno;
return (NULL);
}
return (chan);
}
cap_channel_t *
cap_wrap(int sock)
{
cap_channel_t *chan;
if (!fd_is_valid(sock))
return (NULL);
chan = malloc(sizeof(*chan));
if (chan != NULL) {
chan->cch_sock = sock;
chan->cch_magic = CAP_CHANNEL_MAGIC;
}
return (chan);
}
int
cap_unwrap(cap_channel_t *chan)
{
int sock;
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
sock = chan->cch_sock;
chan->cch_magic = 0;
free(chan);
return (sock);
}
cap_channel_t *
cap_clone(const cap_channel_t *chan)
{
cap_channel_t *newchan;
nvlist_t *nvl;
int newsock;
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", "clone");
nvl = cap_xfer_nvlist(chan, nvl, 0);
if (nvl == NULL)
return (NULL);
if (nvlist_get_number(nvl, "error") != 0) {
errno = (int)nvlist_get_number(nvl, "error");
nvlist_destroy(nvl);
return (NULL);
}
newsock = nvlist_take_descriptor(nvl, "sock");
nvlist_destroy(nvl);
newchan = cap_wrap(newsock);
if (newchan == NULL) {
int serrno;
serrno = errno;
close(newsock);
errno = serrno;
}
return (newchan);
}
void
cap_close(cap_channel_t *chan)
{
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
chan->cch_magic = 0;
close(chan->cch_sock);
free(chan);
}
int
cap_sock(const cap_channel_t *chan)
{
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
return (chan->cch_sock);
}
int
cap_limit_set(const cap_channel_t *chan, nvlist_t *limits)
{
nvlist_t *nvlmsg;
int error;
nvlmsg = nvlist_create(0);
nvlist_add_string(nvlmsg, "cmd", "limit_set");
nvlist_add_nvlist(nvlmsg, "limits", limits);
nvlmsg = cap_xfer_nvlist(chan, nvlmsg, 0);
if (nvlmsg == NULL) {
nvlist_destroy(limits);
return (-1);
}
error = (int)nvlist_get_number(nvlmsg, "error");
nvlist_destroy(nvlmsg);
nvlist_destroy(limits);
if (error != 0) {
errno = error;
return (-1);
}
return (0);
}
int
cap_limit_get(const cap_channel_t *chan, nvlist_t **limitsp)
{
nvlist_t *nvlmsg;
int error;
nvlmsg = nvlist_create(0);
nvlist_add_string(nvlmsg, "cmd", "limit_get");
nvlmsg = cap_xfer_nvlist(chan, nvlmsg, 0);
if (nvlmsg == NULL)
return (-1);
error = (int)nvlist_get_number(nvlmsg, "error");
if (error != 0) {
nvlist_destroy(nvlmsg);
errno = error;
return (-1);
}
if (nvlist_exists_null(nvlmsg, "limits"))
*limitsp = NULL;
else
*limitsp = nvlist_take_nvlist(nvlmsg, "limits");
nvlist_destroy(nvlmsg);
return (0);
}
int
cap_send_nvlist(const cap_channel_t *chan, const nvlist_t *nvl)
{
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
return (nvlist_send(chan->cch_sock, nvl));
}
nvlist_t *
cap_recv_nvlist(const cap_channel_t *chan, int flags)
{
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
return (nvlist_recv(chan->cch_sock, flags));
}
nvlist_t *
cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags)
{
assert(chan != NULL);
assert(chan->cch_magic == CAP_CHANNEL_MAGIC);
return (nvlist_xfer(chan->cch_sock, nvl, flags));
}

View file

@ -1,115 +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_H_
#define _LIBCAPSICUM_H_
#ifndef _NVLIST_T_DECLARED
#define _NVLIST_T_DECLARED
struct nvlist;
typedef struct nvlist nvlist_t;
#endif
#ifndef _CAP_CHANNEL_T_DECLARED
#define _CAP_CHANNEL_T_DECLARED
struct cap_channel;
typedef struct cap_channel cap_channel_t;
#endif
/*
* The function opens unrestricted communication channel to Casper.
*/
cap_channel_t *cap_init(void);
/*
* The function creates cap_channel_t based on the given socket.
*/
cap_channel_t *cap_wrap(int sock);
/*
* The function returns communication socket and frees cap_channel_t.
*/
int cap_unwrap(cap_channel_t *chan);
/*
* The function clones the given capability.
*/
cap_channel_t *cap_clone(const cap_channel_t *chan);
/*
* The function closes the given capability.
*/
void cap_close(cap_channel_t *chan);
/*
* The function returns socket descriptor associated with the given
* cap_channel_t for use with select(2)/kqueue(2)/etc.
*/
int cap_sock(const cap_channel_t *chan);
/*
* The function limits the given capability.
* It always destroys 'limits' on return.
*/
int cap_limit_set(const cap_channel_t *chan, nvlist_t *limits);
/*
* The function returns current limits of the given capability.
*/
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.
*/
int cap_send_nvlist(const cap_channel_t *chan, const nvlist_t *nvl);
/*
* Function receives nvlist over the given capability.
*/
nvlist_t *cap_recv_nvlist(const cap_channel_t *chan, int flags);
/*
* Function sends the given nvlist, destroys it and receives new nvlist in
* response over the given capability.
*/
nvlist_t *cap_xfer_nvlist(const cap_channel_t *chan, nvlist_t *nvl, int flags);
#endif /* !_LIBCAPSICUM_H_ */

View file

@ -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));
}

View file

@ -1,57 +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.
*
* $FreeBSD$
*/
#ifndef _LIBCAPSICUM_DNS_H_
#define _LIBCAPSICUM_DNS_H_
#include <sys/socket.h> /* socklen_t */
struct addrinfo;
struct hostent;
struct hostent *cap_gethostbyname(cap_channel_t *chan, const char *name);
struct hostent *cap_gethostbyname2(cap_channel_t *chan, const char *name,
int type);
struct hostent *cap_gethostbyaddr(cap_channel_t *chan, const void *addr,
socklen_t len, int type);
int cap_getaddrinfo(cap_channel_t *chan, const char *hostname,
const char *servname, const struct addrinfo *hints, struct addrinfo **res);
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);
int cap_dns_type_limit(cap_channel_t *chan, const char * const *types,
size_t ntypes);
int cap_dns_family_limit(cap_channel_t *chan, const int *families,
size_t nfamilies);
#endif /* !_LIBCAPSICUM_DNS_H_ */

View file

@ -1,438 +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/dnv.h>
#include <sys/nv.h>
#include <sys/param.h>
#include <assert.h>
#include <errno.h>
#include <grp.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "libcapsicum.h"
#include "libcapsicum_grp.h"
static struct group ggrp;
static char *gbuffer;
static size_t gbufsize;
static int
group_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
group_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
group_unpack_members(const nvlist_t *nvl, char ***fieldp, char **bufferp,
size_t *bufsizep)
{
const char *mem;
char **outstrs, *str, nvlname[64];
size_t nmem, datasize, strsize;
unsigned int ii;
int n;
if (!nvlist_exists_number(nvl, "gr_nmem")) {
datasize = _ALIGNBYTES + sizeof(char *);
if (datasize >= *bufsizep)
return (ERANGE);
outstrs = (char **)_ALIGN(*bufferp);
outstrs[0] = NULL;
*fieldp = outstrs;
*bufferp += datasize;
*bufsizep -= datasize;
return (0);
}
nmem = (size_t)nvlist_get_number(nvl, "gr_nmem");
datasize = _ALIGNBYTES + sizeof(char *) * (nmem + 1);
for (ii = 0; ii < nmem; ii++) {
n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", ii);
assert(n > 0 && n < (int)sizeof(nvlname));
mem = dnvlist_get_string(nvl, nvlname, NULL);
if (mem == NULL)
return (EINVAL);
datasize += strlen(mem) + 1;
}
if (datasize >= *bufsizep)
return (ERANGE);
outstrs = (char **)_ALIGN(*bufferp);
str = (char *)outstrs + sizeof(char *) * (nmem + 1);
for (ii = 0; ii < nmem; ii++) {
n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", ii);
assert(n > 0 && n < (int)sizeof(nvlname));
mem = nvlist_get_string(nvl, nvlname);
strsize = strlen(mem) + 1;
memcpy(str, mem, strsize);
outstrs[ii] = str;
str += strsize;
}
assert(ii == nmem);
outstrs[ii] = NULL;
*fieldp = outstrs;
*bufferp += datasize;
*bufsizep -= datasize;
return (0);
}
static int
group_unpack(const nvlist_t *nvl, struct group *grp, char *buffer,
size_t bufsize)
{
int error;
if (!nvlist_exists_string(nvl, "gr_name"))
return (EINVAL);
memset(grp, 0, sizeof(*grp));
error = group_unpack_string(nvl, "gr_name", &grp->gr_name, &buffer,
&bufsize);
if (error != 0)
return (error);
error = group_unpack_string(nvl, "gr_passwd", &grp->gr_passwd, &buffer,
&bufsize);
if (error != 0)
return (error);
grp->gr_gid = (gid_t)nvlist_get_number(nvl, "gr_gid");
error = group_unpack_members(nvl, &grp->gr_mem, &buffer, &bufsize);
if (error != 0)
return (error);
return (0);
}
static int
cap_getgrcommon_r(cap_channel_t *chan, const char *cmd, const char *name,
gid_t gid, struct group *grp, char *buffer, size_t bufsize,
struct group **result)
{
nvlist_t *nvl;
bool getgr_r;
int error;
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", cmd);
if (strcmp(cmd, "getgrent") == 0 || strcmp(cmd, "getgrent_r") == 0) {
/* Add nothing. */
} else if (strcmp(cmd, "getgrnam") == 0 ||
strcmp(cmd, "getgrnam_r") == 0) {
nvlist_add_string(nvl, "name", name);
} else if (strcmp(cmd, "getgrgid") == 0 ||
strcmp(cmd, "getgrgid_r") == 0) {
nvlist_add_number(nvl, "gid", (uint64_t)gid);
} 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, "gr_name")) {
/* Not found. */
nvlist_destroy(nvl);
*result = NULL;
return (0);
}
getgr_r = (strcmp(cmd, "getgrent_r") == 0 ||
strcmp(cmd, "getgrnam_r") == 0 || strcmp(cmd, "getgrgid_r") == 0);
for (;;) {
error = group_unpack(nvl, grp, buffer, bufsize);
if (getgr_r || error != ERANGE)
break;
assert(buffer == gbuffer);
assert(bufsize == gbufsize);
error = group_resize();
if (error != 0)
break;
/* Update pointers after resize. */
buffer = gbuffer;
bufsize = gbufsize;
}
nvlist_destroy(nvl);
if (error == 0)
*result = grp;
else
*result = NULL;
return (error);
}
static struct group *
cap_getgrcommon(cap_channel_t *chan, const char *cmd, const char *name,
gid_t gid)
{
struct group *result;
int error, serrno;
serrno = errno;
error = cap_getgrcommon_r(chan, cmd, name, gid, &ggrp, gbuffer,
gbufsize, &result);
if (error != 0) {
errno = error;
return (NULL);
}
errno = serrno;
return (result);
}
struct group *
cap_getgrent(cap_channel_t *chan)
{
return (cap_getgrcommon(chan, "getgrent", NULL, 0));
}
struct group *
cap_getgrnam(cap_channel_t *chan, const char *name)
{
return (cap_getgrcommon(chan, "getgrnam", name, 0));
}
struct group *
cap_getgrgid(cap_channel_t *chan, gid_t gid)
{
return (cap_getgrcommon(chan, "getgrgid", NULL, gid));
}
int
cap_getgrent_r(cap_channel_t *chan, struct group *grp, char *buffer,
size_t bufsize, struct group **result)
{
return (cap_getgrcommon_r(chan, "getgrent_r", NULL, 0, grp, buffer,
bufsize, result));
}
int
cap_getgrnam_r(cap_channel_t *chan, const char *name, struct group *grp,
char *buffer, size_t bufsize, struct group **result)
{
return (cap_getgrcommon_r(chan, "getgrnam_r", name, 0, grp, buffer,
bufsize, result));
}
int
cap_getgrgid_r(cap_channel_t *chan, gid_t gid, struct group *grp, char *buffer,
size_t bufsize, struct group **result)
{
return (cap_getgrcommon_r(chan, "getgrgid_r", NULL, gid, grp, buffer,
bufsize, result));
}
int
cap_setgroupent(cap_channel_t *chan, int stayopen)
{
nvlist_t *nvl;
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", "setgroupent");
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);
}
int
cap_setgrent(cap_channel_t *chan)
{
nvlist_t *nvl;
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", "setgrent");
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);
}
void
cap_endgrent(cap_channel_t *chan)
{
nvlist_t *nvl;
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", "endgrent");
/* Ignore any errors, we have no way to report them. */
nvlist_destroy(cap_xfer_nvlist(chan, nvl, 0));
}
int
cap_grp_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_grp_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_grp_limit_groups(cap_channel_t *chan, const char * const *names,
size_t nnames, gid_t *gids, size_t ngids)
{
nvlist_t *limits, *groups;
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 {
if (nvlist_exists_nvlist(limits, "groups"))
nvlist_free_nvlist(limits, "groups");
}
groups = nvlist_create(0);
for (i = 0; i < ngids; i++) {
n = snprintf(nvlname, sizeof(nvlname), "gid%u", i);
assert(n > 0 && n < (int)sizeof(nvlname));
nvlist_add_number(groups, nvlname, (uint64_t)gids[i]);
}
for (i = 0; i < nnames; i++) {
n = snprintf(nvlname, sizeof(nvlname), "gid%u", i);
assert(n > 0 && n < (int)sizeof(nvlname));
nvlist_add_string(groups, nvlname, names[i]);
}
nvlist_move_nvlist(limits, "groups", groups);
return (cap_limit_set(chan, limits));
}

View file

@ -1,57 +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 _LIBCAPSICUM_GRP_H_
#define _LIBCAPSICUM_GRP_H_
struct group *cap_getgrent(cap_channel_t *chan);
struct group *cap_getgrnam(cap_channel_t *chan, const char *name);
struct group *cap_getgrgid(cap_channel_t *chan, gid_t gid);
int cap_getgrent_r(cap_channel_t *chan, struct group *grp, char *buffer,
size_t bufsize, struct group **result);
int cap_getgrnam_r(cap_channel_t *chan, const char *name, struct group *grp,
char *buffer, size_t bufsize, struct group **result);
int cap_getgrgid_r(cap_channel_t *chan, gid_t gid, struct group *grp,
char *buffer, size_t bufsize, struct group **result);
int cap_setgroupent(cap_channel_t *chan, int stayopen);
int cap_setgrent(cap_channel_t *chan);
void cap_endgrent(cap_channel_t *chan);
int cap_grp_limit_cmds(cap_channel_t *chan, const char * const *cmds,
size_t ncmds);
int cap_grp_limit_fields(cap_channel_t *chan, const char * const *fields,
size_t nfields);
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_ */

View file

@ -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_ */

View file

@ -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));
}

View file

@ -1,57 +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 _LIBCAPSICUM_PWD_H_
#define _LIBCAPSICUM_PWD_H_
struct passwd *cap_getpwent(cap_channel_t *chan);
struct passwd *cap_getpwnam(cap_channel_t *chan, const char *login);
struct passwd *cap_getpwuid(cap_channel_t *chan, uid_t uid);
int cap_getpwent_r(cap_channel_t *chan, struct passwd *pwd, char *buffer,
size_t bufsize, struct passwd **result);
int cap_getpwnam_r(cap_channel_t *chan, const char *name, struct passwd *pwd,
char *buffer, size_t bufsize, struct passwd **result);
int cap_getpwuid_r(cap_channel_t *chan, uid_t uid, struct passwd *pwd,
char *buffer, size_t bufsize, struct passwd **result);
int cap_setpassent(cap_channel_t *chan, int stayopen);
void cap_setpwent(cap_channel_t *chan);
void cap_endpwent(cap_channel_t *chan);
int cap_pwd_limit_cmds(cap_channel_t *chan, const char * const *cmds,
size_t ncmds);
int cap_pwd_limit_fields(cap_channel_t *chan, const char * const *fields,
size_t nfields);
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_ */

View file

@ -1,80 +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 "libcapsicum.h"
#include "libcapsicum_random.h"
#define MAXSIZE (1024 * 1024)
int
cap_random_buf(cap_channel_t *chan, void *buf, size_t nbytes)
{
nvlist_t *nvl;
const void *randbuf;
uint8_t *ptr;
size_t left, randbufsize;
left = nbytes;
ptr = buf;
while (left > 0) {
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", "generate");
nvlist_add_number(nvl, "size",
(uint64_t)(left > MAXSIZE ? MAXSIZE : left));
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);
}
randbuf = nvlist_get_binary(nvl, "data", &randbufsize);
memcpy(ptr, randbuf, randbufsize);
nvlist_destroy(nvl);
ptr += randbufsize;
assert(left >= randbufsize);
left -= randbufsize;
}
return (0);
}

View file

@ -1,37 +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 _LIBCAPSICUM_RANDOM_H_
#define _LIBCAPSICUM_RANDOM_H_
int cap_random_buf(cap_channel_t *chan, void *buf, size_t nbytes);
#endif /* !_LIBCAPSICUM_RANDOM_H_ */

View file

@ -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));
}

View file

@ -1,40 +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 _LIBCAPSICUM_SERVICE_H_
#define _LIBCAPSICUM_SERVICE_H_
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);
#endif /* !_LIBCAPSICUM_SERVICE_H_ */

View file

@ -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);
}

View file

@ -1,43 +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 _LIBCAPSICUM_SYSCTL_H_
#define _LIBCAPSICUM_SYSCTL_H_
#define CAP_SYSCTL_READ 0x01
#define CAP_SYSCTL_WRITE 0x02
#define CAP_SYSCTL_RDWR (CAP_SYSCTL_READ | CAP_SYSCTL_WRITE)
#define CAP_SYSCTL_RECURSIVE 0x04
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_ */

View file

@ -1,12 +0,0 @@
# $FreeBSD$
.include <bsd.own.mk>
PACKAGE=casper
SUBDIR= dns
SUBDIR+=grp
SUBDIR+=pwd
SUBDIR+=random
SUBDIR+=sysctl
.include <bsd.subdir.mk>

View file

@ -1,22 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper
PACKAGE=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>

View file

@ -1,23 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcapsicum \
lib/libcasper \
lib/libcompiler_rt \
lib/libnv \
lib/libpjdlog \
lib/libutil \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View file

@ -1,436 +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 <netinet/in.h>
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <libcapsicum.h>
#include <libcapsicum_dns.h>
#include <libcasper.h>
#include <pjdlog.h>
static bool
dns_allowed_type(const nvlist_t *limits, const char *type)
{
const char *name;
bool notypes;
void *cookie;
if (limits == NULL)
return (true);
notypes = true;
cookie = NULL;
while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) {
if (strncmp(name, "type", sizeof("type") - 1) != 0)
continue;
notypes = false;
if (strcmp(nvlist_get_string(limits, name), type) == 0)
return (true);
}
/* If there are no types at all, allow any type. */
if (notypes)
return (true);
return (false);
}
static bool
dns_allowed_family(const nvlist_t *limits, int family)
{
const char *name;
bool nofamilies;
void *cookie;
if (limits == NULL)
return (true);
nofamilies = true;
cookie = NULL;
while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) {
if (strncmp(name, "family", sizeof("family") - 1) != 0)
continue;
nofamilies = false;
if (family == AF_UNSPEC)
continue;
if (nvlist_get_number(limits, name) == (uint64_t)family)
return (true);
}
/* If there are no families at all, allow any family. */
if (nofamilies)
return (true);
return (false);
}
static void
hostent_pack(const struct hostent *hp, nvlist_t *nvl)
{
unsigned int ii;
char nvlname[64];
int n;
nvlist_add_string(nvl, "name", hp->h_name);
nvlist_add_number(nvl, "addrtype", (uint64_t)hp->h_addrtype);
nvlist_add_number(nvl, "length", (uint64_t)hp->h_length);
if (hp->h_aliases == NULL) {
nvlist_add_number(nvl, "naliases", 0);
} else {
for (ii = 0; hp->h_aliases[ii] != NULL; ii++) {
n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii);
assert(n > 0 && n < (int)sizeof(nvlname));
nvlist_add_string(nvl, nvlname, hp->h_aliases[ii]);
}
nvlist_add_number(nvl, "naliases", (uint64_t)ii);
}
if (hp->h_addr_list == NULL) {
nvlist_add_number(nvl, "naddrs", 0);
} else {
for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) {
n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii);
assert(n > 0 && n < (int)sizeof(nvlname));
nvlist_add_binary(nvl, nvlname, hp->h_addr_list[ii],
(size_t)hp->h_length);
}
nvlist_add_number(nvl, "naddrs", (uint64_t)ii);
}
}
static int
dns_gethostbyname(const nvlist_t *limits, const nvlist_t *nvlin,
nvlist_t *nvlout)
{
struct hostent *hp;
int family;
if (!dns_allowed_type(limits, "NAME"))
return (NO_RECOVERY);
family = (int)nvlist_get_number(nvlin, "family");
if (!dns_allowed_family(limits, family))
return (NO_RECOVERY);
hp = gethostbyname2(nvlist_get_string(nvlin, "name"), family);
if (hp == NULL)
return (h_errno);
hostent_pack(hp, nvlout);
return (0);
}
static int
dns_gethostbyaddr(const nvlist_t *limits, const nvlist_t *nvlin,
nvlist_t *nvlout)
{
struct hostent *hp;
const void *addr;
size_t addrsize;
int family;
if (!dns_allowed_type(limits, "ADDR"))
return (NO_RECOVERY);
family = (int)nvlist_get_number(nvlin, "family");
if (!dns_allowed_family(limits, family))
return (NO_RECOVERY);
addr = nvlist_get_binary(nvlin, "addr", &addrsize);
hp = gethostbyaddr(addr, (socklen_t)addrsize, family);
if (hp == NULL)
return (h_errno);
hostent_pack(hp, nvlout);
return (0);
}
static int
dns_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
struct sockaddr_storage sast;
const void *sabin;
char *host, *serv;
size_t sabinsize, hostlen, servlen;
socklen_t salen;
int error, flags;
if (!dns_allowed_type(limits, "NAME"))
return (NO_RECOVERY);
error = 0;
host = serv = NULL;
memset(&sast, 0, sizeof(sast));
hostlen = (size_t)nvlist_get_number(nvlin, "hostlen");
servlen = (size_t)nvlist_get_number(nvlin, "servlen");
if (hostlen > 0) {
host = calloc(1, hostlen + 1);
if (host == NULL) {
error = EAI_MEMORY;
goto out;
}
}
if (servlen > 0) {
serv = calloc(1, servlen + 1);
if (serv == NULL) {
error = EAI_MEMORY;
goto out;
}
}
sabin = nvlist_get_binary(nvlin, "sa", &sabinsize);
if (sabinsize > sizeof(sast)) {
error = EAI_FAIL;
goto out;
}
memcpy(&sast, sabin, sabinsize);
salen = (socklen_t)sabinsize;
if ((sast.ss_family != AF_INET ||
salen != sizeof(struct sockaddr_in)) &&
(sast.ss_family != AF_INET6 ||
salen != sizeof(struct sockaddr_in6))) {
error = EAI_FAIL;
goto out;
}
if (!dns_allowed_family(limits, (int)sast.ss_family)) {
error = NO_RECOVERY;
goto out;
}
flags = (int)nvlist_get_number(nvlin, "flags");
error = getnameinfo((struct sockaddr *)&sast, salen, host, hostlen,
serv, servlen, flags);
if (error != 0)
goto out;
nvlist_move_string(nvlout, "host", host);
nvlist_move_string(nvlout, "serv", serv);
out:
if (error != 0) {
free(host);
free(serv);
}
return (error);
}
static nvlist_t *
addrinfo_pack(const struct addrinfo *ai)
{
nvlist_t *nvl;
nvl = nvlist_create(0);
nvlist_add_number(nvl, "ai_flags", (uint64_t)ai->ai_flags);
nvlist_add_number(nvl, "ai_family", (uint64_t)ai->ai_family);
nvlist_add_number(nvl, "ai_socktype", (uint64_t)ai->ai_socktype);
nvlist_add_number(nvl, "ai_protocol", (uint64_t)ai->ai_protocol);
nvlist_add_binary(nvl, "ai_addr", ai->ai_addr, (size_t)ai->ai_addrlen);
nvlist_add_string(nvl, "ai_canonname", ai->ai_canonname);
return (nvl);
}
static int
dns_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
struct addrinfo hints, *hintsp, *res, *cur;
const char *hostname, *servname;
char nvlname[64];
nvlist_t *elem;
unsigned int ii;
int error, family, n;
if (!dns_allowed_type(limits, "ADDR"))
return (NO_RECOVERY);
hostname = nvlist_get_string(nvlin, "hostname");
servname = nvlist_get_string(nvlin, "servname");
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,
"hints.ai_family");
hints.ai_socktype = (int)nvlist_get_number(nvlin,
"hints.ai_socktype");
hints.ai_protocol = (int)nvlist_get_number(nvlin,
"hints.ai_protocol");
hints.ai_addrlen = 0;
hints.ai_addr = NULL;
hints.ai_canonname = NULL;
hintsp = &hints;
family = hints.ai_family;
} else {
hintsp = NULL;
family = AF_UNSPEC;
}
if (!dns_allowed_family(limits, family))
return (NO_RECOVERY);
error = getaddrinfo(hostname, servname, hintsp, &res);
if (error != 0)
goto out;
for (cur = res, ii = 0; cur != NULL; cur = cur->ai_next, ii++) {
elem = addrinfo_pack(cur);
n = snprintf(nvlname, sizeof(nvlname), "res%u", ii);
assert(n > 0 && n < (int)sizeof(nvlname));
nvlist_move_nvlist(nvlout, nvlname, elem);
}
freeaddrinfo(res);
error = 0;
out:
return (error);
}
static bool
limit_has_entry(const nvlist_t *limits, const char *prefix)
{
const char *name;
size_t prefixlen;
void *cookie;
if (limits == NULL)
return (false);
prefixlen = strlen(prefix);
cookie = NULL;
while ((name = nvlist_next(limits, NULL, &cookie)) != NULL) {
if (strncmp(name, prefix, prefixlen) == 0)
return (true);
}
return (false);
}
static int
dns_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
{
const char *name;
void *cookie;
int nvtype;
bool hastype, hasfamily;
hastype = false;
hasfamily = false;
cookie = NULL;
while ((name = nvlist_next(newlimits, &nvtype, &cookie)) != NULL) {
if (nvtype == NV_TYPE_STRING) {
const char *type;
if (strncmp(name, "type", sizeof("type") - 1) != 0)
return (EINVAL);
type = nvlist_get_string(newlimits, name);
if (strcmp(type, "ADDR") != 0 &&
strcmp(type, "NAME") != 0) {
return (EINVAL);
}
if (!dns_allowed_type(oldlimits, type))
return (ENOTCAPABLE);
hastype = true;
} else if (nvtype == NV_TYPE_NUMBER) {
int family;
if (strncmp(name, "family", sizeof("family") - 1) != 0)
return (EINVAL);
family = (int)nvlist_get_number(newlimits, name);
if (!dns_allowed_family(oldlimits, family))
return (ENOTCAPABLE);
hasfamily = true;
} else {
return (EINVAL);
}
}
/*
* If the new limit doesn't mention type or family we have to
* check if the current limit does have those. Missing type or
* family in the limit means that all types or families are
* allowed.
*/
if (!hastype) {
if (limit_has_entry(oldlimits, "type"))
return (ENOTCAPABLE);
}
if (!hasfamily) {
if (limit_has_entry(oldlimits, "family"))
return (ENOTCAPABLE);
}
return (0);
}
static int
dns_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
nvlist_t *nvlout)
{
int error;
if (strcmp(cmd, "gethostbyname") == 0)
error = dns_gethostbyname(limits, nvlin, nvlout);
else if (strcmp(cmd, "gethostbyaddr") == 0)
error = dns_gethostbyaddr(limits, nvlin, nvlout);
else if (strcmp(cmd, "getnameinfo") == 0)
error = dns_getnameinfo(limits, nvlin, nvlout);
else if (strcmp(cmd, "getaddrinfo") == 0)
error = dns_getaddrinfo(limits, nvlin, nvlout);
else
error = NO_RECOVERY;
return (error);
}
int
main(int argc, char *argv[])
{
return (service_start("system.dns", PARENT_FILENO, dns_limit,
dns_command, argc, argv));
}

View file

@ -1,22 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper
PACKAGE=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>

View file

@ -1,23 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcapsicum \
lib/libcasper \
lib/libcompiler_rt \
lib/libnv \
lib/libpjdlog \
lib/libutil \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View file

@ -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));
}

View file

@ -1,22 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper
PACKAGE=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>

View file

@ -1,23 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcapsicum \
lib/libcasper \
lib/libcompiler_rt \
lib/libnv \
lib/libpjdlog \
lib/libutil \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View file

@ -1,430 +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 <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <libcapsicum.h>
#include <libcasper.h>
#include <pjdlog.h>
static bool
pwd_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
pwd_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 (!pwd_allowed_cmd(oldlimits, name))
return (ENOTCAPABLE);
}
return (0);
}
static bool
pwd_allowed_user(const nvlist_t *limits, const char *uname, uid_t uid)
{
const char *name;
void *cookie;
int type;
if (limits == NULL)
return (true);
/*
* If no limit was set on allowed users, then all users are allowed.
*/
if (!nvlist_exists_nvlist(limits, "users"))
return (true);
limits = nvlist_get_nvlist(limits, "users");
cookie = NULL;
while ((name = nvlist_next(limits, &type, &cookie)) != NULL) {
switch (type) {
case NV_TYPE_NUMBER:
if (uid != (uid_t)-1 &&
nvlist_get_number(limits, name) == (uint64_t)uid) {
return (true);
}
break;
case NV_TYPE_STRING:
if (uname != NULL &&
strcmp(nvlist_get_string(limits, name),
uname) == 0) {
return (true);
}
break;
default:
PJDLOG_ABORT("Unexpected type %d.", type);
}
}
return (false);
}
static int
pwd_allowed_users(const nvlist_t *oldlimits, const nvlist_t *newlimits)
{
const char *name, *uname;
void *cookie;
uid_t uid;
int type;
cookie = NULL;
while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) {
switch (type) {
case NV_TYPE_NUMBER:
uid = (uid_t)nvlist_get_number(newlimits, name);
uname = NULL;
break;
case NV_TYPE_STRING:
uid = (uid_t)-1;
uname = nvlist_get_string(newlimits, name);
break;
default:
return (EINVAL);
}
if (!pwd_allowed_user(oldlimits, uname, uid))
return (ENOTCAPABLE);
}
return (0);
}
static bool
pwd_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
pwd_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 (!pwd_allowed_field(oldlimits, name))
return (ENOTCAPABLE);
}
return (0);
}
static bool
pwd_pack(const nvlist_t *limits, const struct passwd *pwd, nvlist_t *nvl)
{
int fields;
if (pwd == NULL)
return (true);
/*
* If either name or UID is allowed, we allow it.
*/
if (!pwd_allowed_user(limits, pwd->pw_name, pwd->pw_uid))
return (false);
fields = pwd->pw_fields;
if (pwd_allowed_field(limits, "pw_name")) {
nvlist_add_string(nvl, "pw_name", pwd->pw_name);
} else {
nvlist_add_string(nvl, "pw_name", "");
fields &= ~_PWF_NAME;
}
if (pwd_allowed_field(limits, "pw_uid")) {
nvlist_add_number(nvl, "pw_uid", (uint64_t)pwd->pw_uid);
} else {
nvlist_add_number(nvl, "pw_uid", (uint64_t)-1);
fields &= ~_PWF_UID;
}
if (pwd_allowed_field(limits, "pw_gid")) {
nvlist_add_number(nvl, "pw_gid", (uint64_t)pwd->pw_gid);
} else {
nvlist_add_number(nvl, "pw_gid", (uint64_t)-1);
fields &= ~_PWF_GID;
}
if (pwd_allowed_field(limits, "pw_change")) {
nvlist_add_number(nvl, "pw_change", (uint64_t)pwd->pw_change);
} else {
nvlist_add_number(nvl, "pw_change", (uint64_t)0);
fields &= ~_PWF_CHANGE;
}
if (pwd_allowed_field(limits, "pw_passwd")) {
nvlist_add_string(nvl, "pw_passwd", pwd->pw_passwd);
} else {
nvlist_add_string(nvl, "pw_passwd", "");
fields &= ~_PWF_PASSWD;
}
if (pwd_allowed_field(limits, "pw_class")) {
nvlist_add_string(nvl, "pw_class", pwd->pw_class);
} else {
nvlist_add_string(nvl, "pw_class", "");
fields &= ~_PWF_CLASS;
}
if (pwd_allowed_field(limits, "pw_gecos")) {
nvlist_add_string(nvl, "pw_gecos", pwd->pw_gecos);
} else {
nvlist_add_string(nvl, "pw_gecos", "");
fields &= ~_PWF_GECOS;
}
if (pwd_allowed_field(limits, "pw_dir")) {
nvlist_add_string(nvl, "pw_dir", pwd->pw_dir);
} else {
nvlist_add_string(nvl, "pw_dir", "");
fields &= ~_PWF_DIR;
}
if (pwd_allowed_field(limits, "pw_shell")) {
nvlist_add_string(nvl, "pw_shell", pwd->pw_shell);
} else {
nvlist_add_string(nvl, "pw_shell", "");
fields &= ~_PWF_SHELL;
}
if (pwd_allowed_field(limits, "pw_expire")) {
nvlist_add_number(nvl, "pw_expire", (uint64_t)pwd->pw_expire);
} else {
nvlist_add_number(nvl, "pw_expire", (uint64_t)0);
fields &= ~_PWF_EXPIRE;
}
nvlist_add_number(nvl, "pw_fields", (uint64_t)fields);
return (true);
}
static int
pwd_getpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
struct passwd *pwd;
for (;;) {
errno = 0;
pwd = getpwent();
if (errno != 0)
return (errno);
if (pwd_pack(limits, pwd, nvlout))
return (0);
}
/* NOTREACHED */
}
static int
pwd_getpwnam(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
struct passwd *pwd;
const char *name;
if (!nvlist_exists_string(nvlin, "name"))
return (EINVAL);
name = nvlist_get_string(nvlin, "name");
PJDLOG_ASSERT(name != NULL);
errno = 0;
pwd = getpwnam(name);
if (errno != 0)
return (errno);
(void)pwd_pack(limits, pwd, nvlout);
return (0);
}
static int
pwd_getpwuid(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
struct passwd *pwd;
uid_t uid;
if (!nvlist_exists_number(nvlin, "uid"))
return (EINVAL);
uid = (uid_t)nvlist_get_number(nvlin, "uid");
errno = 0;
pwd = getpwuid(uid);
if (errno != 0)
return (errno);
(void)pwd_pack(limits, pwd, nvlout);
return (0);
}
static int
pwd_setpassent(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 (setpassent(stayopen) == 0 ? EFAULT : 0);
}
static int
pwd_setpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
setpwent();
return (0);
}
static int
pwd_endpwent(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
endpwent();
return (0);
}
static int
pwd_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, "users") &&
!nvlist_exists_nvlist(newlimits, "users")) {
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 = pwd_allowed_cmds(oldlimits, limits);
else if (strcmp(name, "fields") == 0)
error = pwd_allowed_fields(oldlimits, limits);
else if (strcmp(name, "users") == 0)
error = pwd_allowed_users(oldlimits, limits);
else
error = EINVAL;
if (error != 0)
return (error);
}
return (0);
}
static int
pwd_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
nvlist_t *nvlout)
{
int error;
if (!pwd_allowed_cmd(limits, cmd))
return (ENOTCAPABLE);
if (strcmp(cmd, "getpwent") == 0 || strcmp(cmd, "getpwent_r") == 0)
error = pwd_getpwent(limits, nvlin, nvlout);
else if (strcmp(cmd, "getpwnam") == 0 || strcmp(cmd, "getpwnam_r") == 0)
error = pwd_getpwnam(limits, nvlin, nvlout);
else if (strcmp(cmd, "getpwuid") == 0 || strcmp(cmd, "getpwuid_r") == 0)
error = pwd_getpwuid(limits, nvlin, nvlout);
else if (strcmp(cmd, "setpassent") == 0)
error = pwd_setpassent(limits, nvlin, nvlout);
else if (strcmp(cmd, "setpwent") == 0)
error = pwd_setpwent(limits, nvlin, nvlout);
else if (strcmp(cmd, "endpwent") == 0)
error = pwd_endpwent(limits, nvlin, nvlout);
else
error = EINVAL;
return (error);
}
int
main(int argc, char *argv[])
{
return (service_start("system.pwd", PARENT_FILENO, pwd_limit,
pwd_command, argc, argv));
}

View file

@ -1,22 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper
PACKAGE=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>

View file

@ -1,23 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcapsicum \
lib/libcasper \
lib/libcompiler_rt \
lib/libnv \
lib/libpjdlog \
lib/libutil \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View file

@ -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));
}

View file

@ -1,22 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR} ${.CURDIR}/../../../sbin/casper
PACKAGE=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>

View file

@ -1,23 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcapsicum \
lib/libcasper \
lib/libcompiler_rt \
lib/libnv \
lib/libpjdlog \
lib/libutil \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View file

@ -1,249 +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/sysctl.h>
#include <sys/nv.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <libcapsicum.h>
#include <libcapsicum_sysctl.h>
#include <libcasper.h>
#include <pjdlog.h>
static int
sysctl_check_one(const nvlist_t *nvl, bool islimit)
{
const char *name;
void *cookie;
int type;
unsigned int fields;
/* NULL nvl is of course invalid. */
if (nvl == NULL)
return (EINVAL);
if (nvlist_error(nvl) != 0)
return (nvlist_error(nvl));
#define HAS_NAME 0x01
#define HAS_OPERATION 0x02
fields = 0;
cookie = NULL;
while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
/* We accept only one 'name' and one 'operation' in nvl. */
if (strcmp(name, "name") == 0) {
if (type != NV_TYPE_STRING)
return (EINVAL);
/* Only one 'name' can be present. */
if ((fields & HAS_NAME) != 0)
return (EINVAL);
fields |= HAS_NAME;
} else if (strcmp(name, "operation") == 0) {
uint64_t operation;
if (type != NV_TYPE_NUMBER)
return (EINVAL);
/*
* We accept only CAP_SYSCTL_READ and
* CAP_SYSCTL_WRITE flags.
*/
operation = nvlist_get_number(nvl, name);
if ((operation & ~(CAP_SYSCTL_RDWR)) != 0)
return (EINVAL);
/* ...but there has to be at least one of them. */
if ((operation & (CAP_SYSCTL_RDWR)) == 0)
return (EINVAL);
/* Only one 'operation' can be present. */
if ((fields & HAS_OPERATION) != 0)
return (EINVAL);
fields |= HAS_OPERATION;
} else if (islimit) {
/* If this is limit, there can be no other fields. */
return (EINVAL);
}
}
/* Both fields has to be there. */
if (fields != (HAS_NAME | HAS_OPERATION))
return (EINVAL);
#undef HAS_OPERATION
#undef HAS_NAME
return (0);
}
static bool
sysctl_allowed(const nvlist_t *limits, const char *chname, uint64_t choperation)
{
uint64_t operation;
const char *name;
void *cookie;
int type;
if (limits == NULL)
return (true);
cookie = NULL;
while ((name = nvlist_next(limits, &type, &cookie)) != NULL) {
PJDLOG_ASSERT(type == NV_TYPE_NUMBER);
operation = nvlist_get_number(limits, name);
if ((operation & choperation) != choperation)
continue;
if ((operation & CAP_SYSCTL_RECURSIVE) == 0) {
if (strcmp(name, chname) != 0)
continue;
} else {
size_t namelen;
namelen = strlen(name);
if (strncmp(name, chname, namelen) != 0)
continue;
if (chname[namelen] != '.' && chname[namelen] != '\0')
continue;
}
return (true);
}
return (false);
}
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;
cookie = NULL;
while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) {
if (type != NV_TYPE_NUMBER)
return (EINVAL);
operation = nvlist_get_number(newlimits, name);
if ((operation & ~(CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE)) != 0)
return (EINVAL);
if ((operation & (CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE)) == 0)
return (EINVAL);
if (!sysctl_allowed(oldlimits, name, operation))
return (ENOTCAPABLE);
}
return (0);
}
static int
sysctl_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
nvlist_t *nvlout)
{
const char *name;
const void *newp;
void *oldp;
uint64_t operation;
size_t oldlen, newlen;
size_t *oldlenp;
int error;
if (strcmp(cmd, "sysctl") != 0)
return (EINVAL);
error = sysctl_check_one(nvlin, false);
if (error != 0)
return (error);
name = nvlist_get_string(nvlin, "name");
operation = nvlist_get_number(nvlin, "operation");
if (!sysctl_allowed(limits, name, operation))
return (ENOTCAPABLE);
if ((operation & CAP_SYSCTL_WRITE) != 0) {
if (!nvlist_exists_binary(nvlin, "newp"))
return (EINVAL);
newp = nvlist_get_binary(nvlin, "newp", &newlen);
PJDLOG_ASSERT(newp != NULL && newlen > 0);
} else {
newp = NULL;
newlen = 0;
}
if ((operation & CAP_SYSCTL_READ) != 0) {
if (nvlist_exists_null(nvlin, "justsize")) {
oldp = NULL;
oldlen = 0;
oldlenp = &oldlen;
} else {
if (!nvlist_exists_number(nvlin, "oldlen"))
return (EINVAL);
oldlen = (size_t)nvlist_get_number(nvlin, "oldlen");
if (oldlen == 0)
return (EINVAL);
oldp = calloc(1, oldlen);
if (oldp == NULL)
return (ENOMEM);
oldlenp = &oldlen;
}
} else {
oldp = NULL;
oldlen = 0;
oldlenp = NULL;
}
if (sysctlbyname(name, oldp, oldlenp, newp, newlen) == -1) {
error = errno;
free(oldp);
return (error);
}
if ((operation & CAP_SYSCTL_READ) != 0) {
if (nvlist_exists_null(nvlin, "justsize"))
nvlist_add_number(nvlout, "oldlen", (uint64_t)oldlen);
else
nvlist_move_binary(nvlout, "oldp", oldp, oldlen);
}
return (0);
}
int
main(int argc, char *argv[])
{
return (service_start("system.sysctl", PARENT_FILENO, sysctl_limit,
sysctl_command, argc, argv));
}