--- contrib/openbsm/bin/auditdistd/auditdistd.c.orig +++ contrib/openbsm/bin/auditdistd/auditdistd.c @@ -113,6 +113,10 @@ proto_close(adh->adh_remote); adh->adh_remote = NULL; } + if (adh->adh_conn != NULL) { + proto_close(adh->adh_conn); + adh->adh_conn = NULL; + } } TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (lst->adl_conn != NULL) @@ -126,12 +130,17 @@ child_cleanup(struct adist_host *adhost) { + PJDLOG_ASSERT(adhost->adh_remote == NULL); + if (adhost->adh_conn != NULL) { - PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); proto_close(adhost->adh_conn); adhost->adh_conn = NULL; } adhost->adh_worker_pid = 0; + if (adhost->adh_trail_dirfd >= 0) { + close(adhost->adh_trail_dirfd); + adhost->adh_trail_dirfd = -1; + } } static void @@ -170,11 +179,11 @@ } else { if (adhost->adh_role == ADIST_ROLE_SENDER) restart = true; - pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + pjdlog_prefix_push("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); child_exit_log("Worker", pid, status); child_cleanup(adhost); - pjdlog_prefix_set("%s", ""); + pjdlog_prefix_pop(); } } if (!restart) @@ -186,11 +195,11 @@ continue; if (adhost->adh_worker_pid != 0) continue; - pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + pjdlog_prefix_push("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); pjdlog_info("Restarting sender process."); adist_sender(adcfg, adhost); - pjdlog_prefix_set("%s", ""); + pjdlog_prefix_pop(); } } @@ -320,7 +329,7 @@ adhost->adh_remoteaddr); /* Now that we know host name setup log prefix. */ - pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + pjdlog_prefix_push("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); if (adist_random(rnd, sizeof(rnd)) == -1) { @@ -409,13 +418,14 @@ } adhost->adh_remote = conn; - adist_receiver(adcfg, adhost); + if (adist_receiver(adcfg, adhost) == -1) + child_cleanup(adhost); - pjdlog_prefix_set("%s", ""); + pjdlog_prefix_pop(); return; close: proto_close(conn); - pjdlog_prefix_set("%s", ""); + pjdlog_prefix_pop(); } static void @@ -424,7 +434,7 @@ struct proto_conn *conn; int16_t val = 0; - pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, + pjdlog_prefix_push("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); @@ -456,7 +466,7 @@ if (val == 0 && proto_connection_send(adhost->adh_conn, conn) < 0) pjdlog_errno(LOG_WARNING, "Unable to send connection"); - pjdlog_prefix_set("%s", ""); + pjdlog_prefix_pop(); } static void @@ -495,6 +505,14 @@ } } +static int +fdadd(fd_set *fds, int fd, int maxfd) +{ + + FD_SET(fd, fds); + return (fd > maxfd ? fd : maxfd); +} + static void main_loop(void) { @@ -502,7 +520,7 @@ struct adist_listen *lst; struct timeval seltimeout; int fd, maxfd, ret; - fd_set rfds; + fd_set fds; seltimeout.tv_sec = SIGNALS_CHECK_INTERVAL; seltimeout.tv_usec = 0; @@ -513,31 +531,34 @@ check_signals(); /* Setup descriptors for select(2). */ - FD_ZERO(&rfds); + FD_ZERO(&fds); maxfd = -1; TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (lst->adl_conn == NULL) continue; fd = proto_descriptor(lst->adl_conn); PJDLOG_ASSERT(fd >= 0); - FD_SET(fd, &rfds); - maxfd = fd > maxfd ? fd : maxfd; + maxfd = fdadd(&fds, fd, maxfd); } TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { - if (adhost->adh_role == ADIST_ROLE_SENDER) { - /* Only sender workers asks for connections. */ - PJDLOG_ASSERT(adhost->adh_conn != NULL); + /* + * Sender should always have worker process running, + * thus it should always have connection to the worker. + * Receiver may or may not have worker running, so + * connection with worker is optional. + */ + PJDLOG_ASSERT(adhost->adh_conn != NULL || + adhost->adh_role != ADIST_ROLE_SENDER); + + if (adhost->adh_conn != NULL) { fd = proto_descriptor(adhost->adh_conn); PJDLOG_ASSERT(fd >= 0); - FD_SET(fd, &rfds); - maxfd = fd > maxfd ? fd : maxfd; - } else { - PJDLOG_ASSERT(adhost->adh_conn == NULL); + maxfd = fdadd(&fds, fd, maxfd); } } PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); - ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout); + ret = select(maxfd + 1, &fds, NULL, NULL, &seltimeout); if (ret == 0) { /* * select(2) timed out, so there should be no @@ -561,19 +582,21 @@ TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (lst->adl_conn == NULL) continue; - if (FD_ISSET(proto_descriptor(lst->adl_conn), &rfds)) + if (FD_ISSET(proto_descriptor(lst->adl_conn), &fds)) listen_accept(lst); } TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { - if (adhost->adh_role == ADIST_ROLE_SENDER) { - PJDLOG_ASSERT(adhost->adh_conn != NULL); - if (FD_ISSET(proto_descriptor(adhost->adh_conn), - &rfds)) { - connection_migrate(adhost); - } - } else { - PJDLOG_ASSERT(adhost->adh_conn == NULL); + if (adhost->adh_conn == NULL) { + PJDLOG_ASSERT(adhost->adh_role != + ADIST_ROLE_SENDER); + continue; } + if (!FD_ISSET(proto_descriptor(adhost->adh_conn), &fds)) + continue; + if (adhost->adh_role == ADIST_ROLE_SENDER) + connection_migrate(adhost); + else + receiver_msg(adhost); } } } --- contrib/openbsm/bin/auditdistd/auditdistd.h.orig +++ contrib/openbsm/bin/auditdistd/auditdistd.h @@ -265,7 +265,8 @@ void descriptors_assert(const struct adist_host *adhost, int pjdlogmode); void adist_sender(struct adist_config *config, struct adist_host *adhost); -void adist_receiver(struct adist_config *config, struct adist_host *adhost); +int adist_receiver(struct adist_config *config, struct adist_host *adhost); +void receiver_msg(struct adist_host *adhost); struct adist_config *yy_config_parse(const char *config, bool exitonerror); void yy_config_free(struct adist_config *config); --- /dev/null 2013-09-08 20:00:00.000000000 +0200 +++ contrib/openbsm/bin/auditdistd/nv.c 2013-09-08 20:08:56.133400568 +0200 @@ -0,0 +1,1096 @@ +/*- + * Copyright (c) 2009-2010 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: src/sbin/hastd/nv.c,v 1.8 2012/03/23 20:18:48 trociny Exp $"); + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBCAPSICUM +#include +#include +#endif +#ifdef HAVE_PJDLOG +#include +#endif + +#include "nv.h" + +#ifndef HAVE_PJDLOG +#include +#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) +#define PJDLOG_RASSERT(expr, ...) assert(expr) +#define PJDLOG_ABORT(...) abort() +#endif + +#define NV_TYPE_FIRST NV_TYPE_BOOL +#define NV_TYPE_LAST NV_TYPE_DESCRIPTOR + +#define NV_MAGIC 0xaea1e +struct nv { + int nv_magic; + int nv_error; + unsigned char *nv_data; + size_t nv_datasize; + size_t nv_bufsize; + unsigned int nv_descriptors; +}; + +struct nvhdr { + uint8_t nvh_type; + uint8_t nvh_namesize; + uint32_t nvh_dsize; + char nvh_name[0]; +} __packed; +#define NVH_DATA(nvh) ((const unsigned char *)nvh + NVH_HSIZE(nvh)) +#define NVH_HSIZE(nvh) \ + (sizeof(struct nvhdr) + roundup2((nvh)->nvh_namesize, 8)) +#define NVH_SIZE(nvh) (NVH_HSIZE(nvh) + roundup2(nvh->nvh_dsize, 8)) + +#define NV_CHECK(nv) do { \ + PJDLOG_ASSERT((nv) != NULL); \ + PJDLOG_ASSERT((nv)->nv_magic == NV_MAGIC); \ +} while (0) + +extern bool fd_is_valid(int fd); /* Implementation in nvio.h. */ +static void nv_add(struct nv *nv, const char *name, const unsigned char *value, + size_t vsize, int type); +static const struct nvhdr *nv_find(const struct nv *nv, const char *name, + int type); + +static const char * +nv_type_to_string(int type) +{ + + switch (type) { + case NV_TYPE_BOOL: + return ("NV_TYPE_BOOL"); + case NV_TYPE_CHAR: + return ("NV_TYPE_CHAR"); + case NV_TYPE_UCHAR: + return ("NV_TYPE_UCHAR"); + case NV_TYPE_SHORT: + return ("NV_TYPE_SHORT"); + case NV_TYPE_USHORT: + return ("NV_TYPE_USHORT"); + case NV_TYPE_INT: + return ("NV_TYPE_INT"); + case NV_TYPE_UINT: + return ("NV_TYPE_UINT"); + case NV_TYPE_LONG: + return ("NV_TYPE_LONG"); + case NV_TYPE_ULONG: + return ("NV_TYPE_ULONG"); + case NV_TYPE_LONGLONG: + return ("NV_TYPE_LONGLONG"); + case NV_TYPE_ULONGLONG: + return ("NV_TYPE_ULONGLONG"); + case NV_TYPE_INTMAX: + return ("NV_TYPE_INTMAX"); + case NV_TYPE_UINTMAX: + return ("NV_TYPE_UINTMAX"); + case NV_TYPE_POINTER: + return ("NV_TYPE_POINTER"); + case NV_TYPE_INT8: + return ("NV_TYPE_INT8"); + case NV_TYPE_UINT8: + return ("NV_TYPE_UINT8"); + case NV_TYPE_INT16: + return ("NV_TYPE_INT16"); + case NV_TYPE_UINT16: + return ("NV_TYPE_UINT16"); + case NV_TYPE_INT32: + return ("NV_TYPE_INT32"); + case NV_TYPE_UINT32: + return ("NV_TYPE_UINT32"); + case NV_TYPE_INT64: + return ("NV_TYPE_INT64"); + case NV_TYPE_UINT64: + return ("NV_TYPE_UINT64"); + case NV_TYPE_INT8_ARRAY: + return ("NV_TYPE_INT8_ARRAY"); + case NV_TYPE_UINT8_ARRAY: + return ("NV_TYPE_UINT8_ARRAY"); + case NV_TYPE_INT16_ARRAY: + return ("NV_TYPE_INT16_ARRAY"); + case NV_TYPE_UINT16_ARRAY: + return ("NV_TYPE_UINT16_ARRAY"); + case NV_TYPE_INT32_ARRAY: + return ("NV_TYPE_INT32_ARRAY"); + case NV_TYPE_UINT32_ARRAY: + return ("NV_TYPE_UINT32_ARRAY"); + case NV_TYPE_INT64_ARRAY: + return ("NV_TYPE_INT64_ARRAY"); + case NV_TYPE_UINT64_ARRAY: + return ("NV_TYPE_UINT64_ARRAY"); + case NV_TYPE_STRING: + return ("NV_TYPE_STRING"); + case NV_TYPE_DESCRIPTOR: + return ("NV_TYPE_DESCRIPTOR"); + default: + return (""); + } +} + +/* + * Allocate and initialize new nv structure. + * Return NULL in case of malloc(3) failure. + */ +struct nv * +nv_alloc(void) +{ + struct nv *nv; + + nv = malloc(sizeof(*nv)); + if (nv == NULL) + return (NULL); + nv->nv_data = malloc(PAGE_SIZE); + if (nv->nv_data == NULL) { + free(nv); + return (NULL); + } + nv->nv_datasize = 0; + nv->nv_bufsize = PAGE_SIZE; + nv->nv_descriptors = 0; + nv->nv_error = 0; + nv->nv_magic = NV_MAGIC; + return (nv); +} + +/* + * Free the given nv structure and close all descriptors. + */ +void +nv_free(struct nv *nv) +{ + const char *name; + void *cookie; + int serrno, type; + + if (nv == NULL) + return; + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + + serrno = errno; + + if (nv->nv_descriptors > 0) { + /* + * Reset the error, so nv_next() works. + * Error might have been set after we added some descriptors + * and despite error we have to close them. + */ + nv->nv_error = 0; + cookie = NULL; + while ((name = nv_next(nv, &type, &cookie)) != NULL) { + if (type == NV_TYPE_DESCRIPTOR) { + close(nv_get_descriptor(nv, name)); + nv->nv_descriptors--; + } + } + } + PJDLOG_ASSERT(nv->nv_descriptors == 0); + + nv->nv_magic = 0; + free(nv->nv_data); + free(nv); + + errno = serrno; +} + +/* + * Free the given nv structure, but don't close descriptors. + */ +void +nv_free_data(struct nv *nv) +{ + + if (nv == NULL) + return; + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + + nv->nv_magic = 0; + free(nv->nv_data); + free(nv); +} + +/* + * Return error for the given nv structure. + */ +int +nv_error(const struct nv *nv) +{ + + if (nv == NULL) + return (ENOMEM); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + + return (nv->nv_error); +} + +/* + * Validate correctness of the entire nv structure and all its elements. + */ +int +nv_validate(const struct nv *nv) +{ + const struct nvhdr *nvh; + const unsigned char *data, *ptr; + size_t dsize, size, vsize; + int error; + + if (nv == NULL) { + errno = ENOMEM; + return (-1); + } + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + if (nv->nv_error != 0) { + errno = nv->nv_error; + return (-1); + } + + /* TODO: Check that names are unique? */ + + error = 0; + ptr = nv->nv_data; + size = nv->nv_datasize; + while (size > 0) { + /* + * Minimum size at this point is size of nvhdr structure, one + * character long name plus terminating '\0'. + */ + if (size < sizeof(*nvh) + 2) { + error = EINVAL; + break; + } + nvh = (const struct nvhdr *)ptr; + if (size < NVH_HSIZE(nvh)) { + error = EINVAL; + break; + } + if (nvh->nvh_name[nvh->nvh_namesize - 1] != '\0') { + error = EINVAL; + break; + } + if (strlen(nvh->nvh_name) != + (size_t)(nvh->nvh_namesize - 1)) { + error = EINVAL; + break; + } + if (nvh->nvh_type < NV_TYPE_FIRST || + nvh->nvh_type > NV_TYPE_LAST) { + error = EINVAL; + break; + } + dsize = nvh->nvh_dsize; + if (dsize == 0) { + error = EINVAL; + break; + } + if (size < NVH_SIZE(nvh)) { + error = EINVAL; + break; + } + vsize = 0; + switch (nvh->nvh_type) { + case NV_TYPE_BOOL: + case NV_TYPE_CHAR: + case NV_TYPE_UCHAR: + if (vsize == 0) + vsize = 1; + /* FALLTHROUGH */ + case NV_TYPE_SHORT: + case NV_TYPE_USHORT: + if (vsize == 0) + vsize = sizeof(short); + /* FALLTHROUGH */ + case NV_TYPE_INT: + case NV_TYPE_UINT: + if (vsize == 0) + vsize = sizeof(int); + /* FALLTHROUGH */ + case NV_TYPE_LONG: + case NV_TYPE_ULONG: + if (vsize == 0) + vsize = sizeof(long); + /* FALLTHROUGH */ + case NV_TYPE_LONGLONG: + case NV_TYPE_ULONGLONG: + if (vsize == 0) + vsize = sizeof(long long); + /* FALLTHROUGH */ + case NV_TYPE_INTMAX: + case NV_TYPE_UINTMAX: + if (vsize == 0) + vsize = sizeof(intmax_t); + /* FALLTHROUGH */ + case NV_TYPE_POINTER: + if (vsize == 0) + vsize = sizeof(void *); + /* FALLTHROUGH */ + case NV_TYPE_INT8: + case NV_TYPE_UINT8: + if (vsize == 0) + vsize = 1; + /* FALLTHROUGH */ + case NV_TYPE_INT16: + case NV_TYPE_UINT16: + if (vsize == 0) + vsize = 2; + /* FALLTHROUGH */ + case NV_TYPE_INT32: + case NV_TYPE_UINT32: + if (vsize == 0) + vsize = 4; + /* FALLTHROUGH */ + case NV_TYPE_INT64: + case NV_TYPE_UINT64: + if (vsize == 0) + vsize = 8; + /* FALLTHROUGH */ + case NV_TYPE_DESCRIPTOR: + if (vsize == 0) + vsize = sizeof(int); + if (dsize != vsize) { + error = EINVAL; + break; + } + break; + case NV_TYPE_INT8_ARRAY: + case NV_TYPE_UINT8_ARRAY: + break; + case NV_TYPE_INT16_ARRAY: + case NV_TYPE_UINT16_ARRAY: + if (vsize == 0) + vsize = 2; + /* FALLTHROUGH */ + case NV_TYPE_INT32_ARRAY: + case NV_TYPE_UINT32_ARRAY: + if (vsize == 0) + vsize = 4; + /* FALLTHROUGH */ + case NV_TYPE_INT64_ARRAY: + case NV_TYPE_UINT64_ARRAY: + if (vsize == 0) + vsize = 8; + if ((dsize % vsize) != 0) { + error = EINVAL; + break; + } + break; + case NV_TYPE_STRING: + data = NVH_DATA(nvh); + if (data[dsize - 1] != '\0') { + error = EINVAL; + break; + } + if (strlen((const char *)data) != dsize - 1) { + error = EINVAL; + break; + } + break; + default: + PJDLOG_ABORT("invalid condition"); + } + if (error != 0) + break; + ptr += NVH_SIZE(nvh); + size -= NVH_SIZE(nvh); + } + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +/* + * Raw data size. + */ +size_t +nv_size(const struct nv *nv) +{ + + PJDLOG_ASSERT(nv != NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + + return (nv->nv_datasize); +} + +/* + * Provide a pointer and size to raw data ready to be send over a local socket. + */ +const void * +nv_pack(const struct nv *nv, size_t *sizep) +{ + + PJDLOG_ASSERT(nv != NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + + if (sizep != NULL) + *sizep = nv->nv_datasize; + return (nv->nv_datasize == 0 ? NULL : nv->nv_data); +} + +/* + * Consume raw data into newly created nv structure. + */ +struct nv * +nv_unpack(void *data, size_t size) +{ + struct nv *nv; + void *cookie; + const char *name; + int serrno, type; + + PJDLOG_ASSERT((data != NULL && size > 0) || + (data == NULL && size == 0)); + + nv = malloc(sizeof(*nv)); + if (nv == NULL) + return (NULL); + nv->nv_error = 0; + nv->nv_data = data; + nv->nv_datasize = size; + nv->nv_bufsize = size; + nv->nv_descriptors = 0; + nv->nv_magic = NV_MAGIC; + + if (nv_validate(nv) == -1) { + serrno = errno; + nv->nv_magic = 0; + free(nv); + errno = serrno; + return (NULL); + } + + cookie = NULL; + while ((name = nv_next(nv, &type, &cookie)) != NULL) { + if (type == NV_TYPE_DESCRIPTOR) + nv->nv_descriptors++; + } + + return (nv); +} + +void +nv_add_bool(struct nv *nv, const char *name, bool value) +{ + uint8_t bvalue; + + bvalue = value ? 1 : 0; + nv_add(nv, name, (unsigned char *)&bvalue, sizeof(bvalue), + NV_TYPE_BOOL); +} + +#define NV_DEFINE_ADD(suffix, type, TYPE) \ +void \ +nv_add_##suffix(struct nv *nv, const char *name, type value) \ +{ \ + \ + nv_add(nv, name, (unsigned char *)&value, sizeof(value), \ + NV_TYPE_##TYPE); \ +} + +NV_DEFINE_ADD(char, char, CHAR) +NV_DEFINE_ADD(uchar, unsigned char, UCHAR) +NV_DEFINE_ADD(short, short, SHORT) +NV_DEFINE_ADD(ushort, unsigned short, USHORT) +NV_DEFINE_ADD(int, int, INT) +NV_DEFINE_ADD(uint, unsigned int, UINT) +NV_DEFINE_ADD(long, long, LONG) +NV_DEFINE_ADD(ulong, unsigned long, ULONG) +NV_DEFINE_ADD(longlong, long long, LONGLONG) +NV_DEFINE_ADD(ulonglong, unsigned long long, ULONGLONG) +NV_DEFINE_ADD(intmax, intmax_t, INTMAX) +NV_DEFINE_ADD(uintmax, uintmax_t, UINTMAX) +NV_DEFINE_ADD(pointer, void *, POINTER) +NV_DEFINE_ADD(int8, int8_t, INT8) +NV_DEFINE_ADD(uint8, uint8_t, UINT8) +NV_DEFINE_ADD(int16, int16_t, INT16) +NV_DEFINE_ADD(uint16, uint16_t, UINT16) +NV_DEFINE_ADD(int32, int32_t, INT32) +NV_DEFINE_ADD(uint32, uint32_t, UINT32) +NV_DEFINE_ADD(int64, int64_t, INT64) +NV_DEFINE_ADD(uint64, uint64_t, UINT64) + +#undef NV_DEFINE_ADD + +#define NV_DEFINE_ADD_ARRAY(type, TYPE) \ +void \ +nv_add_##type##_array(struct nv *nv, const char *name, \ + const type##_t *value, size_t nsize) \ +{ \ + \ + nv_add(nv, name, (const unsigned char *)value, \ + sizeof(value[0]) * nsize, NV_TYPE_##TYPE##_ARRAY); \ +} + +NV_DEFINE_ADD_ARRAY(int8, INT8) +NV_DEFINE_ADD_ARRAY(uint8, UINT8) +NV_DEFINE_ADD_ARRAY(int16, INT16) +NV_DEFINE_ADD_ARRAY(uint16, UINT16) +NV_DEFINE_ADD_ARRAY(int32, INT32) +NV_DEFINE_ADD_ARRAY(uint32, UINT32) +NV_DEFINE_ADD_ARRAY(int64, INT64) +NV_DEFINE_ADD_ARRAY(uint64, UINT64) + +#undef NV_DEFINE_ADD_ARRAY + +void +nv_add_string(struct nv *nv, const char *name, const char *value) +{ + + PJDLOG_ASSERT(value != NULL); + + nv_add(nv, name, (const unsigned char *)value, strlen(value) + 1, + NV_TYPE_STRING); +} + +void +nv_add_stringf(struct nv *nv, const char *name, const char *valuefmt, ...) +{ + va_list valueap; + + PJDLOG_ASSERT(valuefmt != NULL); + + va_start(valueap, valuefmt); + nv_add_stringv(nv, name, valuefmt, valueap); + va_end(valueap); +} + +void +nv_add_stringv(struct nv *nv, const char *name, const char *valuefmt, + va_list valueap) +{ + char *value; + ssize_t size; + + PJDLOG_ASSERT(valuefmt != NULL); + + if (nv == NULL) + return; + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + if (nv->nv_error != 0) + return; + + size = vasprintf(&value, valuefmt, valueap); + if (size == -1) { + nv->nv_error = ENOMEM; + return; + } + nv_add(nv, name, (const unsigned char *)value, size + 1, + NV_TYPE_STRING); + free(value); +} + +void +nv_add_descriptor(struct nv *nv, const char *name, int fd) +{ + int newfd; + + PJDLOG_ASSERT(fd_is_valid(fd)); + + if (nv == NULL) + return; + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + if (nv->nv_error != 0) + return; + + newfd = dup(fd); + if (newfd == -1) { + nv->nv_error = errno; + return; + } + + nv_add(nv, name, (unsigned char *)&newfd, sizeof(newfd), + NV_TYPE_DESCRIPTOR); + + if (nv->nv_error != 0) { + close(newfd); + return; + } + + nv->nv_descriptors++; +} + +void +nv_move_descriptor(struct nv *nv, const char *name, int fd) +{ + + PJDLOG_ASSERT(fd_is_valid(fd)); + + if (nv == NULL) { + close(fd); + return; + } + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + if (nv->nv_error != 0) { + close(fd); + return; + } + nv_add(nv, name, (unsigned char *)&fd, sizeof(fd), NV_TYPE_DESCRIPTOR); + if (nv->nv_error != 0) { + close(fd); + return; + } + + nv->nv_descriptors++; +} + +bool +nv_get_bool(const struct nv *nv, const char *name) +{ + const struct nvhdr *nvh; + uint8_t value; + + nvh = nv_find(nv, name, NV_TYPE_BOOL); + PJDLOG_RASSERT(nvh != NULL, "Missing '%s' element of type %s.", name, + nv_type_to_string(NV_TYPE_BOOL)); + PJDLOG_ASSERT(sizeof(value) == nvh->nvh_dsize); + bcopy(NVH_DATA(nvh), &value, sizeof(value)); + + return (value != 0 ? true : false); +} + +#define NV_DEFINE_GET(suffix, type, TYPE) \ +type \ +nv_get_##suffix(const struct nv *nv, const char *name) \ +{ \ + const struct nvhdr *nvh; \ + type value; \ + \ + nvh = nv_find(nv, name, NV_TYPE_##TYPE); \ + PJDLOG_RASSERT(nvh != NULL, "Missing '%s' element of type %s.", \ + name, nv_type_to_string(NV_TYPE_##TYPE)); \ + PJDLOG_ASSERT(nvh != NULL); \ + PJDLOG_ASSERT(sizeof(value) == nvh->nvh_dsize); \ + bcopy(NVH_DATA(nvh), &value, sizeof(value)); \ + \ + return (value); \ +} + +NV_DEFINE_GET(char, char, CHAR) +NV_DEFINE_GET(uchar, unsigned char, UCHAR) +NV_DEFINE_GET(short, short, SHORT) +NV_DEFINE_GET(ushort, unsigned short, USHORT) +NV_DEFINE_GET(int, int, INT) +NV_DEFINE_GET(uint, unsigned int, UINT) +NV_DEFINE_GET(long, long, LONG) +NV_DEFINE_GET(ulong, unsigned long, ULONG) +NV_DEFINE_GET(longlong, long long, LONGLONG) +NV_DEFINE_GET(ulonglong, unsigned long long, ULONGLONG) +NV_DEFINE_GET(intmax, intmax_t, INTMAX) +NV_DEFINE_GET(uintmax, uintmax_t, UINTMAX) +NV_DEFINE_GET(pointer, void *, POINTER) +NV_DEFINE_GET(int8, int8_t, INT8) +NV_DEFINE_GET(uint8, uint8_t, UINT8) +NV_DEFINE_GET(int16, int16_t, INT16) +NV_DEFINE_GET(uint16, uint16_t, UINT16) +NV_DEFINE_GET(int32, int32_t, INT32) +NV_DEFINE_GET(uint32, uint32_t, UINT32) +NV_DEFINE_GET(int64, int64_t, INT64) +NV_DEFINE_GET(uint64, uint64_t, UINT64) + +#undef NV_DEFINE_GET + +#define NV_DEFINE_GET_ARRAY(type, TYPE) \ +const type##_t * \ +nv_get_##type##_array(const struct nv *nv, const char *name, \ + size_t *sizep) \ +{ \ + const struct nvhdr *nvh; \ + \ + nvh = nv_find(nv, name, NV_TYPE_##TYPE##_ARRAY); \ + PJDLOG_RASSERT(nvh != NULL, "Missing '%s' element of type %s.", \ + name, nv_type_to_string(NV_TYPE_##TYPE##_ARRAY)); \ + PJDLOG_ASSERT(nvh != NULL); \ + PJDLOG_ASSERT((nvh->nvh_dsize % sizeof(type##_t)) == 0); \ + if (sizep != NULL) \ + *sizep = nvh->nvh_dsize / sizeof(type##_t); \ + return ((const type##_t *)(const void *)NVH_DATA(nvh)); \ +} + +NV_DEFINE_GET_ARRAY(int8, INT8) +NV_DEFINE_GET_ARRAY(uint8, UINT8) +NV_DEFINE_GET_ARRAY(int16, INT16) +NV_DEFINE_GET_ARRAY(uint16, UINT16) +NV_DEFINE_GET_ARRAY(int32, INT32) +NV_DEFINE_GET_ARRAY(uint32, UINT32) +NV_DEFINE_GET_ARRAY(int64, INT64) +NV_DEFINE_GET_ARRAY(uint64, UINT64) + +#undef NV_DEFINE_GET_ARRAY + +const char * +nv_get_string(const struct nv *nv, const char *name) +{ + const struct nvhdr *nvh; + const char *str; + + nvh = nv_find(nv, name, NV_TYPE_STRING); + PJDLOG_RASSERT(nvh != NULL, "Missing '%s' element of type %s.", name, + nv_type_to_string(NV_TYPE_STRING)); + PJDLOG_ASSERT(nvh->nvh_dsize >= 1); + str = (const char *)NVH_DATA(nvh); + PJDLOG_ASSERT(str[nvh->nvh_dsize - 1] == '\0'); + PJDLOG_ASSERT(strlen(str) == nvh->nvh_dsize - 1); + return (str); +} + +int +nv_get_descriptor(const struct nv *nv, const char *name) +{ + const struct nvhdr *nvh; + int fd; + + nvh = nv_find(nv, name, NV_TYPE_DESCRIPTOR); + PJDLOG_RASSERT(nvh != NULL, "Missing '%s' element of type %s.", name, + nv_type_to_string(NV_TYPE_DESCRIPTOR)); + PJDLOG_ASSERT(sizeof(fd) == nvh->nvh_dsize); + bcopy(NVH_DATA(nvh), &fd, sizeof(fd)); + PJDLOG_ASSERT(fd_is_valid(fd)); + + return (fd); +} + +void +nv_set_descriptor(struct nv *nv, const char *name, int fd) +{ + struct nvhdr *nvh; + + PJDLOG_ASSERT(fd_is_valid(fd)); + + /* Deconst... */ + nvh = (void *)(uintptr_t)nv_find(nv, name, NV_TYPE_DESCRIPTOR); + PJDLOG_ASSERT(nvh != NULL); + PJDLOG_ASSERT(sizeof(fd) == nvh->nvh_dsize); + /* Deconst... */ + bcopy(&fd, (void *)(uintptr_t)NVH_DATA(nvh), sizeof(fd)); +} + +bool +nv_exists(const struct nv *nv, const char *name, int type) +{ + + PJDLOG_ASSERT(nv != NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + + return (nv_find(nv, name, type) != NULL); +} + +unsigned int +nv_type(const struct nv *nv, const char *name) +{ + const struct nvhdr *nvh; + + PJDLOG_ASSERT(nv != NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + + nvh = nv_find(nv, name, NV_TYPE_NONE); + PJDLOG_ASSERT(nvh != NULL); + + return ((unsigned int)nvh->nvh_type); +} + +unsigned int +nv_descriptors(const struct nv *nv) +{ + + PJDLOG_ASSERT(nv != NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + + return (nv->nv_descriptors); +} + +const char * +nv_next(const struct nv *nv, int *typep, void **cookiep) +{ + const struct nvhdr *nvh; + unsigned char *ptr; + size_t size; + + PJDLOG_ASSERT(cookiep != NULL); + + if (nv == NULL) + return (NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + + if (*cookiep == NULL) { + if (nv->nv_datasize == 0) + return (NULL); + ptr = nv->nv_data; + size = nv->nv_datasize; + } else if (*cookiep == nv->nv_data + nv->nv_datasize) { + /* No more entries. */ + return (NULL); + } else { + ptr = *cookiep; + /* + * If cookie is given, it has to point at least at the + * second entry. If the caller wants the first entry, + * cookie should be NULL. + */ + PJDLOG_ASSERT(ptr >= nv->nv_data + sizeof(*nvh) + 2); + size = nv->nv_datasize - (ptr - nv->nv_data); + } + PJDLOG_ASSERT(size >= sizeof(*nvh) + 2); + nvh = (struct nvhdr *)ptr; + PJDLOG_ASSERT(size >= NVH_SIZE(nvh)); + ptr += NVH_SIZE(nvh); + + *cookiep = ptr; + if (typep != NULL) + *typep = (int)nvh->nvh_type; + return (nvh->nvh_name); +} + +void +nv_assert(const struct nv *nv, const char *name, int type) +{ + + PJDLOG_ASSERT(nv_exists(nv, name, type)); +} + +/* + * Dump content of the nv structure. + */ +void +nv_dump(const struct nv *nv) +{ + const struct nvhdr *nvh; + const unsigned char *data, *ptr; + size_t dsize, size; + unsigned int ii; + + if (nv_validate(nv) == -1) { + printf("error: %d\n", errno); + return; + } + + NV_CHECK(nv); + PJDLOG_ASSERT(nv->nv_error == 0); + + ptr = nv->nv_data; + size = nv->nv_datasize; + while (size > 0) { + PJDLOG_ASSERT(size >= sizeof(*nvh) + 2); + nvh = (const struct nvhdr *)ptr; + PJDLOG_ASSERT(size >= NVH_SIZE(nvh)); + dsize = nvh->nvh_dsize; + data = NVH_DATA(nvh); + printf(" %s", nvh->nvh_name); + switch (nvh->nvh_type) { + case NV_TYPE_BOOL: + printf("(bool): %s", + *(const int8_t *)data == 0 ? "false" : "true"); + break; + case NV_TYPE_POINTER: + printf("(pointer): %p", *(const void * const *)data); + break; +#define NV_DUMP_SIGNED(suffix, type, TYPE) \ + case NV_TYPE_##TYPE: \ + printf("(%s): %jd", #suffix, \ + (intmax_t)(*(const type *)data)); \ + break; +#define NV_DUMP_UNSIGNED(suffix, type, TYPE) \ + case NV_TYPE_##TYPE: \ + printf("(%s): %ju", #suffix, \ + (uintmax_t)(*(const type *)data)); \ + break; + NV_DUMP_SIGNED(char, char, CHAR) + NV_DUMP_UNSIGNED(uchar, unsigned char, UCHAR) + NV_DUMP_SIGNED(short, short, SHORT) + NV_DUMP_UNSIGNED(ushort, unsigned short, USHORT) + NV_DUMP_SIGNED(int, int, INT) + NV_DUMP_UNSIGNED(uint, unsigned int, UINT) + NV_DUMP_SIGNED(long, long, LONG) + NV_DUMP_UNSIGNED(ulong, unsigned long, ULONG) + NV_DUMP_SIGNED(longlong, long long, LONGLONG) + NV_DUMP_UNSIGNED(ulonglong, unsigned long long, ULONGLONG) + NV_DUMP_SIGNED(intmax, intmax_t, INTMAX) + NV_DUMP_UNSIGNED(uintmax, uintmax_t, UINTMAX) + NV_DUMP_SIGNED(int8, int8_t, INT8) + NV_DUMP_UNSIGNED(uint8, uint8_t, UINT8) + NV_DUMP_SIGNED(int16, int16_t, INT16) + NV_DUMP_UNSIGNED(uint16, uint16_t, UINT16) + NV_DUMP_SIGNED(int32, int32_t, INT32) + NV_DUMP_UNSIGNED(uint32, uint32_t, UINT32) + NV_DUMP_SIGNED(int64, int64_t, INT64) + NV_DUMP_UNSIGNED(uint64, uint64_t, UINT64) +#undef NV_DUMP_SIGNED +#undef NV_DUMP_UNSIGNED +#define NV_DUMP_SIGNED(suffix, type, TYPE) \ + case NV_TYPE_##TYPE##_ARRAY: \ + printf("(%s array):", #suffix); \ + for (ii = 0; ii < dsize; ii++) { \ + printf(" %jd", \ + (intmax_t)((const type *)(const void *)data)[ii]);\ + } \ + break; +#define NV_DUMP_UNSIGNED(suffix, type, TYPE) \ + case NV_TYPE_##TYPE##_ARRAY: \ + printf("(%s array):", #suffix); \ + for (ii = 0; ii < dsize; ii++) { \ + printf(" %ju", \ + (uintmax_t)((const type *)(const void *)data)[ii]);\ + } \ + break; + NV_DUMP_SIGNED(int8, int8_t, INT8) + NV_DUMP_UNSIGNED(uint8, uint8_t, UINT8) + NV_DUMP_SIGNED(int16, int16_t, INT16) + NV_DUMP_UNSIGNED(uint16, uint16_t, UINT16) + NV_DUMP_SIGNED(int32, int32_t, INT32) + NV_DUMP_UNSIGNED(uint32, uint32_t, UINT32) + NV_DUMP_SIGNED(int64, int64_t, INT64) + NV_DUMP_UNSIGNED(uint64, uint64_t, UINT64) +#undef NV_DUMP_SIGNED +#undef NV_DUMP_UNSIGNED + case NV_TYPE_STRING: + printf("(string): %s", (const char *)data); + break; + case NV_TYPE_DESCRIPTOR: + printf("(descriptor): %d", *(const int *)data); + break; + default: + PJDLOG_ABORT("invalid condition"); + } + printf("\n"); + ptr += NVH_SIZE(nvh); + size -= NVH_SIZE(nvh); + } +} + +/* + * Local routines below. + */ + +static void +nv_add(struct nv *nv, const char *name, const unsigned char *value, + size_t vsize, int type) +{ + size_t namesize, entrysize; + struct nvhdr *nvh; + + if (nv == NULL) + return; + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + if (nv->nv_error != 0) + return; + + namesize = strlen(name) + 1; + PJDLOG_ASSERT(namesize <= 255); + entrysize = sizeof(*nvh) + roundup2(namesize, 8) + roundup2(vsize, 8); + + if (nv->nv_bufsize - nv->nv_datasize < entrysize) { + unsigned char *newdata; + size_t newsize; + + newsize = nv->nv_bufsize + MAX(entrysize * 2, PAGE_SIZE); + newdata = realloc(nv->nv_data, newsize); + if (newdata == NULL) { + nv->nv_error = ENOMEM; + return; + } + nv->nv_data = newdata; + nv->nv_bufsize = newsize; + } + + /* Populate header. */ + nvh = (struct nvhdr *)(nv->nv_data + nv->nv_datasize); + nvh->nvh_type = type; + nvh->nvh_namesize = (uint8_t)namesize; + nvh->nvh_dsize = (uint32_t)vsize; + bcopy(name, nvh->nvh_name, namesize); + bzero(nv->nv_data + nv->nv_datasize + sizeof(*nvh) + namesize, + NVH_HSIZE(nvh) - sizeof(*nvh) - namesize); + nv->nv_datasize += NVH_HSIZE(nvh); + PJDLOG_ASSERT(nv->nv_datasize <= nv->nv_bufsize); + + /* Add the actual data. */ + bcopy(value, nv->nv_data + nv->nv_datasize, vsize); + bzero(nv->nv_data + nv->nv_datasize + vsize, + roundup2(vsize, 8) - vsize); + nv->nv_datasize += roundup2(vsize, 8); + PJDLOG_ASSERT(nv->nv_datasize <= nv->nv_bufsize); +} + +static const struct nvhdr * +nv_find(const struct nv *nv, const char *name, int type) +{ + struct nvhdr *nvh; + unsigned char *ptr; + size_t size, namesize; + + PJDLOG_ASSERT(nv != NULL); + PJDLOG_ASSERT(nv->nv_magic == NV_MAGIC); + PJDLOG_ASSERT(nv->nv_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + + namesize = strlen(name) + 1; + if (namesize > 255) + return (NULL); + + ptr = nv->nv_data; + size = nv->nv_datasize; + while (size > 0) { + PJDLOG_ASSERT(size >= sizeof(*nvh) + 2); + nvh = (struct nvhdr *)ptr; + PJDLOG_ASSERT(size >= NVH_SIZE(nvh)); + if (nvh->nvh_namesize == namesize && + strcmp(nvh->nvh_name, name) == 0) { + if (type != NV_TYPE_NONE && nvh->nvh_type != type) + return (NULL); + return (nvh); + } + ptr += NVH_SIZE(nvh); + size -= NVH_SIZE(nvh); + } + + return (NULL); +} --- /dev/null 2013-09-08 20:00:00.000000000 +0200 +++ contrib/openbsm/bin/auditdistd/nv.h 2013-09-08 20:08:57.164401592 +0200 @@ -0,0 +1,178 @@ +/*- + * Copyright (c) 2009-2010 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: src/sbin/hastd/nv.h,v 1.4 2011/01/22 22:38:18 pjd Exp $ + */ + +#ifndef _NV_H_ +#define _NV_H_ + +#include + +#include +#include +#include +#include + +#ifndef _NV_T_DECLARED +#define _NV_T_DECLARED +struct nv; + +typedef struct nv nv_t; +#endif + +#define NV_TYPE_NONE 0 + +#define NV_TYPE_BOOL 1 +#define NV_TYPE_CHAR 2 +#define NV_TYPE_UCHAR 3 +#define NV_TYPE_SHORT 4 +#define NV_TYPE_USHORT 5 +#define NV_TYPE_INT 6 +#define NV_TYPE_UINT 7 +#define NV_TYPE_LONG 8 +#define NV_TYPE_ULONG 9 +#define NV_TYPE_LONGLONG 10 +#define NV_TYPE_ULONGLONG 11 +#define NV_TYPE_INTMAX 12 +#define NV_TYPE_UINTMAX 13 +#define NV_TYPE_POINTER 14 +#define NV_TYPE_INT8 15 +#define NV_TYPE_UINT8 16 +#define NV_TYPE_INT16 17 +#define NV_TYPE_UINT16 18 +#define NV_TYPE_INT32 19 +#define NV_TYPE_UINT32 20 +#define NV_TYPE_INT64 21 +#define NV_TYPE_UINT64 22 +#define NV_TYPE_INT8_ARRAY 23 +#define NV_TYPE_UINT8_ARRAY 24 +#define NV_TYPE_INT16_ARRAY 25 +#define NV_TYPE_UINT16_ARRAY 26 +#define NV_TYPE_INT32_ARRAY 27 +#define NV_TYPE_UINT32_ARRAY 28 +#define NV_TYPE_INT64_ARRAY 29 +#define NV_TYPE_UINT64_ARRAY 30 +#define NV_TYPE_STRING 31 +#define NV_TYPE_DESCRIPTOR 32 + +struct nv *nv_alloc(void); +void nv_free(nv_t *nv); +void nv_free_data(struct nv *nv); +int nv_error(const nv_t *nv); +int nv_validate(const nv_t *nv); +unsigned int nv_type(const nv_t *nv, const char *name); +unsigned int nv_descriptors(const struct nv *nv); +const char *nv_next(const nv_t *nv, int *typep, void **cookiep); + +bool nv_exists(const nv_t *nv, const char *name, int type); +void nv_assert(const nv_t *nv, const char *name, int type); +void nv_dump(const nv_t *nv); + +size_t nv_size(const nv_t *nv); +const void *nv_pack(const struct nv *nv, size_t *sizep); +nv_t *nv_unpack(void *data, size_t size); + +void nv_add_bool(nv_t *nv, const char *name, bool value); +void nv_add_char(nv_t *nv, const char *name, char value); +void nv_add_uchar(nv_t *nv, const char *name, unsigned char value); +void nv_add_short(nv_t *nv, const char *name, short value); +void nv_add_ushort(nv_t *nv, const char *name, unsigned short value); +void nv_add_int(nv_t *nv, const char *name, int value); +void nv_add_uint(nv_t *nv, const char *name, unsigned int value); +void nv_add_long(nv_t *nv, const char *name, long value); +void nv_add_ulong(nv_t *nv, const char *name, unsigned long value); +void nv_add_longlong(nv_t *nv, const char *name, long long value); +void nv_add_ulonglong(nv_t *nv, const char *name, unsigned long long value); +void nv_add_intmax(nv_t *nv, const char *name, intmax_t value); +void nv_add_uintmax(nv_t *nv, const char *name, uintmax_t value); +void nv_add_pointer(nv_t *nv, const char *name, void *value); +void nv_add_int8(nv_t *nv, const char *name, int8_t value); +void nv_add_uint8(nv_t *nv, const char *name, uint8_t value); +void nv_add_int16(nv_t *nv, const char *name, int16_t value); +void nv_add_uint16(nv_t *nv, const char *name, uint16_t value); +void nv_add_int32(nv_t *nv, const char *name, int32_t value); +void nv_add_uint32(nv_t *nv, const char *name, uint32_t value); +void nv_add_int64(nv_t *nv, const char *name, int64_t value); +void nv_add_uint64(nv_t *nv, const char *name, uint64_t value); +void nv_add_int8_array(nv_t *nv, const char *name, const int8_t *value, size_t size); +void nv_add_uint8_array(nv_t *nv, const char *name, const uint8_t *value, size_t size); +void nv_add_int16_array(nv_t *nv, const char *name, const int16_t *value, size_t size); +void nv_add_uint16_array(nv_t *nv, const char *name, const uint16_t *value, size_t size); +void nv_add_int32_array(nv_t *nv, const char *name, const int32_t *value, size_t size); +void nv_add_uint32_array(nv_t *nv, const char *name, const uint32_t *value, size_t size); +void nv_add_int64_array(nv_t *nv, const char *name, const int64_t *value, size_t size); +void nv_add_uint64_array(nv_t *nv, const char *name, const uint64_t *value, size_t size); +void nv_add_string(nv_t *nv, const char *name, const char *value); +void nv_add_stringf(nv_t *nv, const char *name, const char *valuefmt, ...); +void nv_add_stringv(nv_t *nv, const char *name, const char *valuefmt, va_list valueap); +void nv_add_descriptor(nv_t *nv, const char *name, int fd); +void nv_move_descriptor(nv_t *nv, const char *name, int fd); + +bool nv_get_bool(const nv_t *nv, const char *name); +char nv_get_char(const nv_t *nv, const char *name); +unsigned char nv_get_uchar(const nv_t *nv, const char *name); +short nv_get_short(const nv_t *nv, const char *name); +unsigned short nv_get_ushort(const nv_t *nv, const char *name); +int nv_get_int(const nv_t *nv, const char *name); +unsigned int nv_get_uint(const nv_t *nv, const char *name); +long nv_get_long(const nv_t *nv, const char *name); +unsigned long nv_get_ulong(const nv_t *nv, const char *name); +long long nv_get_longlong(const nv_t *nv, const char *name); +unsigned long long nv_get_ulonglong(const nv_t *nv, const char *name); +intmax_t nv_get_intmax(const nv_t *nv, const char *name); +uintmax_t nv_get_uintmax(const nv_t *nv, const char *name); +void *nv_get_pointer(const nv_t *nv, const char *name); +int8_t nv_get_int8(const nv_t *nv, const char *name); +uint8_t nv_get_uint8(const nv_t *nv, const char *name); +int16_t nv_get_int16(const nv_t *nv, const char *name); +uint16_t nv_get_uint16(const nv_t *nv, const char *name); +int32_t nv_get_int32(const nv_t *nv, const char *name); +uint32_t nv_get_uint32(const nv_t *nv, const char *name); +int64_t nv_get_int64(const nv_t *nv, const char *name); +uint64_t nv_get_uint64(const nv_t *nv, const char *name); +const int8_t *nv_get_int8_array(const nv_t *nv, const char *name, size_t *sizep); +const uint8_t *nv_get_uint8_array(const nv_t *nv, const char *name, size_t *sizep); +const int16_t *nv_get_int16_array(const nv_t *nv, const char *name, size_t *sizep); +const uint16_t *nv_get_uint16_array(const nv_t *nv, const char *name, size_t *sizep); +const int32_t *nv_get_int32_array(const nv_t *nv, const char *name, size_t *sizep); +const uint32_t *nv_get_uint32_array(const nv_t *nv, const char *name, size_t *sizep); +const int64_t *nv_get_int64_array(const nv_t *nv, const char *name, size_t *sizep); +const uint64_t *nv_get_uint64_array(const nv_t *nv, const char *name, size_t *sizep); +const char *nv_get_string(const nv_t *nv, const char *name); +int nv_get_descriptor(const nv_t *nv, const char *name); + +void nv_set_descriptor(nv_t *nv, const char *name, int fd); + +struct proto_conn; + +int nv_send(struct proto_conn *conn, const nv_t *nv); +nv_t *nv_recv(struct proto_conn *conn); +nv_t *nv_xfer(struct proto_conn *conn, nv_t *nv); + +#endif /* !_NV_H_ */ --- /dev/null 2013-09-08 20:00:00.000000000 +0200 +++ contrib/openbsm/bin/auditdistd/nvio.c 2013-09-08 20:08:58.187400434 +0200 @@ -0,0 +1,363 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBCAPSICUM +#include +#include +#endif +#ifdef HAVE_PJDLOG +#include +#endif +#include + +#include "nv.h" +#include "proto.h" + +#ifndef HAVE_PJDLOG +#include +#define PJDLOG_ASSERT(...) assert(__VA_ARGS__) +#endif + +struct caphdr { + size_t ch_datasize; + unsigned int ch_descriptors; +}; + +bool fd_is_valid(int fd); + +bool +fd_is_valid(int fd) +{ + + return (fcntl(fd, F_GETFL) != -1 || errno != EBADF); +} + +static void +fd_wait(int fd, bool doread) +{ + fd_set fds; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds, + NULL, NULL); +} + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +static int +msg_send(int sock, const struct msghdr *msg) +{ + + for (;;) { + fd_wait(sock, false); + if (sendmsg(sock, msg, 0) == -1) { + if (errno == EINTR) + continue; + return (-1); + } + break; + } + + return (0); +} + +static int +msg_recv(int sock, struct msghdr *msg) +{ + + for (;;) { + fd_wait(sock, true); + if (recvmsg(sock, msg, MSG_WAITALL) == -1) { + if (errno == EINTR) + continue; + return (-1); + } + break; + } + + return (0); +} + +static struct cmsghdr * +msghdr_add_fd(struct msghdr *msg, struct cmsghdr *cmsg, int fd) +{ + + PJDLOG_ASSERT(msg != NULL); + PJDLOG_ASSERT(cmsg != NULL); + + if (!fd_is_valid(fd)) { + free(msg->msg_control); + errno = EBADF; + return (NULL); + } + + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + + return (CMSG_NXTHDR(msg, cmsg)); +} + +static int +msghdr_populate(const nv_t *nv, struct msghdr *msg) +{ + struct cmsghdr *cmsg; + const char *name; + void *cookie; + int fd, type; + + bzero(msg, sizeof(*msg)); + + if (nv_descriptors(nv) == 0) { + msg->msg_control = NULL; + msg->msg_controllen = 0; + return (0); + } + + msg->msg_controllen = nv_descriptors(nv) * CMSG_SPACE(sizeof(int)); + msg->msg_control = calloc(1, msg->msg_controllen); + if (msg->msg_control == NULL) + return (-1); + + cookie = NULL; + cmsg = CMSG_FIRSTHDR(msg); + while ((name = nv_next(nv, &type, &cookie)) != NULL) { + if (type == NV_TYPE_DESCRIPTOR) { + fd = nv_get_descriptor(nv, name); + cmsg = msghdr_add_fd(msg, cmsg, fd); + } + } + PJDLOG_ASSERT(cmsg == NULL); + + return (0); +} + +int +nv_send(struct proto_conn *conn, const nv_t *nv) +{ + struct caphdr caphdr; + struct msghdr msg; + struct iovec iov; + int serrno; + + if (nv_error(nv) != 0) { + errno = nv_error(nv); + return (-1); + } + + if (nv_size(nv) == 0) { + caphdr.ch_datasize = 0; + caphdr.ch_descriptors = 0; + } else { + caphdr.ch_datasize = nv_size(nv); + caphdr.ch_descriptors = nv_descriptors(nv); + } + + if (robust_send(proto_descriptor(conn), &caphdr, sizeof(caphdr)) == -1) + return (-1); + + if (caphdr.ch_datasize == 0) + return (0); + + if (msghdr_populate(nv, &msg) == -1) + return (-1); + + bzero(&iov, sizeof(iov)); + /* Deconst... */ + iov.iov_base = (void *)(uintptr_t)nv_pack(nv, NULL); + iov.iov_len = caphdr.ch_datasize; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + if (msg_send(proto_descriptor(conn), &msg) == -1) + goto fail; + + free(msg.msg_control); + return (0); +fail: + serrno = errno; + free(msg.msg_control); + errno = serrno; + return (-1); +} + +static struct cmsghdr * +msghdr_get_fd(struct msghdr *msg, struct cmsghdr *cmsg, int *fdp) +{ + + PJDLOG_ASSERT(cmsg != NULL); + PJDLOG_ASSERT(cmsg->cmsg_level == SOL_SOCKET); + PJDLOG_ASSERT(cmsg->cmsg_type == SCM_RIGHTS); + + bcopy(CMSG_DATA(cmsg), fdp, sizeof(*fdp)); + + return (CMSG_NXTHDR(msg, cmsg)); +} + +static int +msghdr_allocate(const struct caphdr *caphdr, struct msghdr *msg, + struct iovec *iov) +{ + int serrno; + + bzero(msg, sizeof(*msg)); + + if (caphdr->ch_descriptors == 0) { + msg->msg_controllen = 0; + msg->msg_control = NULL; + } else { + msg->msg_controllen = + caphdr->ch_descriptors * CMSG_SPACE(sizeof(int)); + msg->msg_control = calloc(1, msg->msg_controllen); + if (msg->msg_control == NULL) + return (-1); + } + + bzero(iov, sizeof(*iov)); + iov->iov_len = caphdr->ch_datasize; + iov->iov_base = malloc(iov->iov_len); + if (iov->iov_base == NULL) { + serrno = errno; + free(msg->msg_control); + errno = serrno; + return (-1); + } + + msg->msg_iov = iov; + msg->msg_iovlen = 1; + + return (0); +} + +nv_t * +nv_recv(struct proto_conn *conn) +{ + struct caphdr caphdr; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + const char *name; + void *cookie; + nv_t *nv; + int fd, serrno, type; + + if (robust_recv(proto_descriptor(conn), &caphdr, sizeof(caphdr)) == -1) + return (NULL); + + if (caphdr.ch_datasize == 0) + return (nv_unpack(NULL, 0)); + + if (msghdr_allocate(&caphdr, &msg, &iov) == -1) + return (NULL); + + if (msg_recv(proto_descriptor(conn), &msg) == -1) + goto fail_free_memory; + + nv = nv_unpack(iov.iov_base, iov.iov_len); + if (nv == NULL) + goto fail_close_descriptors; + + cookie = NULL; + cmsg = CMSG_FIRSTHDR(&msg); + while ((name = nv_next(nv, &type, &cookie)) != NULL) { + if (type == NV_TYPE_DESCRIPTOR) { + cmsg = msghdr_get_fd(&msg, cmsg, &fd); + nv_set_descriptor(nv, name, fd); + } + } + PJDLOG_ASSERT(cmsg == NULL); + PJDLOG_ASSERT(caphdr.ch_descriptors == nv_descriptors(nv)); + + free(msg.msg_control); + return (nv); + +fail_close_descriptors: + serrno = errno; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + PJDLOG_ASSERT(cmsg->cmsg_level == SOL_SOCKET); + PJDLOG_ASSERT(cmsg->cmsg_type == SCM_RIGHTS); + + bcopy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + close(fd); + } + errno = serrno; + +fail_free_memory: + serrno = errno; + free(iov.iov_base); + free(msg.msg_control); + errno = serrno; + + return (NULL); +} + +nv_t * +nv_xfer(struct proto_conn *conn, nv_t *nv) +{ + int error; + + error = nv_error(nv); + if (error != 0) { + nv_free(nv); + errno = error; + return (NULL); + } + + if (nv_send(conn, nv) == -1) { + nv_free(nv); + return (NULL); + } + + nv_free(nv); + + nv = nv_recv(conn); + if (nv == NULL) + return (NULL); + if (nv_error(nv) != 0) { + errno = nv_error(nv); + nv_free(nv); + return (NULL); + } + return (nv); +} --- contrib/openbsm/bin/auditdistd/pjdlog.c.orig +++ contrib/openbsm/bin/auditdistd/pjdlog.c @@ -55,9 +55,13 @@ #define PJDLOG_NOT_INITIALIZED 1 #define PJDLOG_INITIALIZED 2 +#define PJDLOG_PREFIX_STACK 4 +#define PJDLOG_PREFIX_MAXSIZE 128 + static int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; static int pjdlog_mode, pjdlog_debug_level; -static char pjdlog_prefix[128]; +static int pjdlog_prefix_current; +static char pjdlog_prefix[PJDLOG_PREFIX_STACK][PJDLOG_PREFIX_MAXSIZE]; #ifdef __FreeBSD__ static int @@ -177,7 +181,8 @@ openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); pjdlog_mode = mode; pjdlog_debug_level = 0; - bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); + pjdlog_prefix_current = 0; + pjdlog_prefix[0][0] = '\0'; pjdlog_initialized = PJDLOG_INITIALIZED; @@ -270,7 +275,6 @@ /* * Set prefix that will be used before each log. - * Setting prefix to NULL will remove it. */ void pjdlog_prefix_set(const char *fmt, ...) @@ -286,7 +290,6 @@ /* * Set prefix that will be used before each log. - * Setting prefix to NULL will remove it. */ void pjdlogv_prefix_set(const char *fmt, va_list ap) @@ -298,12 +301,68 @@ saved_errno = errno; - vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); + vsnprintf(pjdlog_prefix[pjdlog_prefix_current], + sizeof(pjdlog_prefix[pjdlog_prefix_current]), fmt, ap); errno = saved_errno; } /* + * Get current prefix. + */ +const char * +pjdlog_prefix_get(void) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + return (pjdlog_prefix[pjdlog_prefix_current]); +} + +/* + * Set new prefix and put the current one on the stack. + */ +void +pjdlog_prefix_push(const char *fmt, ...) +{ + va_list ap; + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + + va_start(ap, fmt); + pjdlogv_prefix_push(fmt, ap); + va_end(ap); +} + +/* + * Set new prefix and put the current one on the stack. + */ +void +pjdlogv_prefix_push(const char *fmt, va_list ap) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + assert(pjdlog_prefix_current < PJDLOG_PREFIX_STACK - 1); + + pjdlog_prefix_current++; + + pjdlogv_prefix_set(fmt, ap); +} + +/* + * Removes current prefix and recovers previous one from the stack. + */ +void +pjdlog_prefix_pop(void) +{ + + assert(pjdlog_initialized == PJDLOG_INITIALIZED); + assert(pjdlog_prefix_current > 0); + + pjdlog_prefix_current--; +} + +/* * Convert log level into string. */ static const char * @@ -402,7 +461,7 @@ /* Attach debuglevel if this is debug log. */ if (loglevel == LOG_DEBUG) fprintf(out, "[%d]", debuglevel); - fprintf(out, " %s", pjdlog_prefix); + fprintf(out, " %s", pjdlog_prefix[pjdlog_prefix_current]); vfprintf(out, fmt, ap); if (error != -1) fprintf(out, ": %s.", strerror(error)); @@ -415,7 +474,8 @@ char log[1024]; int len; - len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); + len = snprintf(log, sizeof(log), "%s", + pjdlog_prefix[pjdlog_prefix_current]); if ((size_t)len < sizeof(log)) len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); if (error != -1 && (size_t)len < sizeof(log)) { --- contrib/openbsm/bin/auditdistd/pjdlog.h.orig +++ contrib/openbsm/bin/auditdistd/pjdlog.h @@ -55,6 +55,10 @@ void pjdlog_prefix_set(const char *fmt, ...) __printflike(1, 2); void pjdlogv_prefix_set(const char *fmt, va_list ap) __printflike(1, 0); +const char *pjdlog_prefix_get(void); +void pjdlog_prefix_push(const char *fmt, ...) __printflike(1, 2); +void pjdlogv_prefix_push(const char *fmt, va_list ap) __printflike(1, 0); +void pjdlog_prefix_pop(void); void pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) __printflike(4, 5); --- contrib/openbsm/bin/auditdistd/proto_common.c.orig +++ contrib/openbsm/bin/auditdistd/proto_common.c @@ -131,7 +131,7 @@ pjdlog_warning("Getting ENOBUFS errors for 11s on send(), giving up."); } else { if (errcount == 0) - pjdlog_warning("Got ENOBUFS error on send(), retrying for a bit."); + pjdlog_warning("Got ENOBUFS error on send(), retrying in a bit."); errcount++; usleep(100000 * errcount); continue; --- contrib/openbsm/bin/auditdistd/proto_tcp.c.orig +++ contrib/openbsm/bin/auditdistd/proto_tcp.c @@ -327,6 +327,7 @@ "fcntl(F_SETFL, ~O_NONBLOCK) failed"); goto fail; } + tctx->tc_wait_called = true; } } --- contrib/openbsm/bin/auditdistd/receiver.c.orig +++ contrib/openbsm/bin/auditdistd/receiver.c @@ -79,6 +79,7 @@ #endif #include "auditdistd.h" +#include "nv.h" #include "pjdlog.h" #include "proto.h" #include "sandbox.h" @@ -87,7 +88,6 @@ #include "trail.h" static struct adist_config *adcfg; -static struct adist_host *adhost; static TAILQ_HEAD(, adreq) adist_free_list; static pthread_mutex_t adist_free_list_lock; @@ -99,6 +99,11 @@ static pthread_mutex_t adist_send_list_lock; static pthread_cond_t adist_send_list_cond; +static nv_t *receiver_msg_lasttrail(struct adist_host *adhost); +static nv_t *receiver_msg_open(struct adist_host *adhost, nv_t *nvin); +static nv_t *receiver_msg_close(struct adist_host *adhost, nv_t *nvin); +static nv_t *receiver_msg_error(struct adist_host *adhost); + static void adreq_clear(struct adreq *adreq) { @@ -206,11 +211,14 @@ /* * Thread receives requests from the sender. */ -static void * -recv_thread(void *arg __unused) +static __attribute__((__noreturn__)) void * +recv_thread(void *arg) { + struct adist_host *adhost; struct adreq *adreq; + adhost = arg; + for (;;) { pjdlog_debug(3, "recv: Taking free request."); QUEUE_TAKE(adreq, &adist_free_list, 0); @@ -264,20 +272,74 @@ } } /* NOTREACHED */ - return (NULL); +} + +void +receiver_msg(struct adist_host *adhost) +{ + nv_t *nvin, *nvout; + const char *cmd; + + pjdlog_prefix_push("[%s] (%s) ", adhost->adh_name, + role2str(adhost->adh_role)); + + nvin = nv_recv(adhost->adh_conn); + if (nv_error(nvin) != 0) { + pjdlog_common(LOG_ERR, 0, nv_error(nvin), + "Unable to receive message from worker"); + nv_free(nvin); + goto out; + } + cmd = nv_get_string(nvin, "cmd"); + if (strcmp(cmd, "lasttrail") == 0) + nvout = receiver_msg_lasttrail(adhost); + else if (strcmp(cmd, "open") == 0) + nvout = receiver_msg_open(adhost, nvin); + else if (strcmp(cmd, "close") == 0) + nvout = receiver_msg_close(adhost, nvin); + else if (strcmp(cmd, "error") == 0) + nvout = receiver_msg_error(adhost); + else { + pjdlog_error("Unrecognized command from worker: %s.", cmd); + nv_free(nvin); + goto out; + } + nv_free(nvin); + if (nv_error(nvout) != 0) { + pjdlog_common(LOG_ERR, 0, nv_error(nvout), + "Unable to compose response to worker"); + nv_free(nvout); + goto out; + } + if (nv_send(adhost->adh_conn, nvout) == -1) + pjdlog_errno(LOG_ERR, "Unable to send response to worker"); + nv_free(nvout); +out: + pjdlog_prefix_pop(); } /* * Function that opens trail file requested by the sender. - * If the file already exist, it has to be the most recent file and it can + * If the file already exists, it has to be the most recent file and it can * only be open for append. * If the file doesn't already exist, it has to be "older" than all existing * files. + * This function is executed in privileged process. */ -static int -receiver_open(const char *filename) +static nv_t * +receiver_msg_open(struct adist_host *adhost, nv_t *nvin) { - int fd; + const char *filename; + nv_t *nvout; + int fd, error; + + if (!nv_exists(nvin, "filename", NV_TYPE_STRING)) { + pjdlog_error("File name doesn't exist in open message"); + return (NULL); + } + + nvout = nv_alloc(); + filename = nv_get_string(nvin, "filename"); /* * Previous file should be closed by now. Sending OPEN request without @@ -286,13 +348,15 @@ if (adhost->adh_trail_fd != -1) { pjdlog_error("Sender requested opening file \"%s\" without first closing \"%s\".", filename, adhost->adh_trail_name); - return (ADIST_ERROR_WRONG_ORDER); + error = ADIST_ERROR_WRONG_ORDER; + goto out; } if (!trail_validate_name(filename, NULL)) { pjdlog_error("Sender wants to open file \"%s\", which has invalid name.", filename); - return (ADIST_ERROR_INVALID_NAME); + error = ADIST_ERROR_INVALID_NAME; + goto out; } switch (trail_name_compare(filename, adhost->adh_trail_name)) { @@ -301,7 +365,8 @@ pjdlog_error("Terminated trail \"%s/%s\" was unterminated on the sender as \"%s/%s\"?", adhost->adh_directory, adhost->adh_trail_name, adhost->adh_directory, filename); - return (ADIST_ERROR_INVALID_NAME); + error = ADIST_ERROR_INVALID_NAME; + goto out; } if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, adhost->adh_trail_dirfd, filename) == -1) { @@ -310,7 +375,8 @@ adhost->adh_directory, adhost->adh_trail_name, adhost->adh_directory, filename); PJDLOG_ASSERT(errno > 0); - return (ADIST_ERROR_RENAME); + error = ADIST_ERROR_RENAME; + goto out; } pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name, @@ -325,10 +391,20 @@ "Unable to open file \"%s/%s\" for append", adhost->adh_directory, filename); PJDLOG_ASSERT(errno > 0); - return (ADIST_ERROR_OPEN); + error = ADIST_ERROR_OPEN; + goto out; } pjdlog_debug(1, "Opened file \"%s/%s\".", adhost->adh_directory, filename); +#ifdef TODO + if (cap_rights_limit(fd, CAP_WRITE) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to limit capability rights to CAP_WRITE"); + close(fd); + error = ADIST_ERROR_OPEN; + goto out; + } +#endif break; case TRAIL_NEWER: /* Opening new file. */ @@ -339,7 +415,8 @@ "Unable to create file \"%s/%s\"", adhost->adh_directory, filename); PJDLOG_ASSERT(errno > 0); - return (ADIST_ERROR_CREATE); + error = ADIST_ERROR_CREATE; + goto out; } pjdlog_debug(1, "Created file \"%s/%s\".", adhost->adh_directory, filename); @@ -347,21 +424,64 @@ case TRAIL_OLDER: /* Trying to open old file. */ pjdlog_error("Sender wants to open an old file \"%s\".", filename); - return (ADIST_ERROR_OPEN_OLD); + error = ADIST_ERROR_OPEN_OLD; + goto out; default: PJDLOG_ABORT("Unknown return value from trail_name_compare()."); } PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); adhost->adh_trail_fd = fd; - return (0); + nv_move_descriptor(nvout, "trailfd", fd); + error = 0; +out: + if (error != 0) + nv_add_int(nvout, "error", error); + return (nvout); +} + +/* + * This function is executed in sandbox. + */ +static int +receiver_open(struct adist_host *adhost, const char *filename) +{ + nv_t *nv; + int error; + + nv = nv_alloc(); + nv_add_string(nv, "cmd", "open"); + nv_add_string(nv, "filename", filename); + nv = nv_xfer(adhost->adh_conn, nv); + if (nv == NULL) { + pjdlog_exit(1, + "Unable to receive send or receive open command"); + } + if (nv_exists(nv, "error", NV_TYPE_INT)) { + error = nv_get_int(nv, "error"); + } else { + adhost->adh_trail_fd = nv_get_descriptor(nv, "trailfd"); + PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, + sizeof(adhost->adh_trail_name)) < + sizeof(adhost->adh_trail_name)); + error = 0; + } + nv_free_data(nv); + + return (error); } /* + * This function is executed in sandbox. + * This function is executed in privileged process. + */ +/* * Function appends data to the trail file that is currently open. + * This function is executed in sandbox. */ static int -receiver_append(const unsigned char *data, size_t size) +receiver_append(struct adist_host *adhost, const unsigned char *data, + size_t size) { ssize_t done; size_t osize; @@ -392,32 +512,46 @@ return (0); } -static int -receiver_close(const char *filename) +/* + * This function is executed in privileged process. + */ +static nv_t * +receiver_msg_close(struct adist_host *adhost, nv_t *nvin) { + const char *filename; + nv_t *nvout; + int error; + + if (!nv_exists(nvin, "filename", NV_TYPE_STRING)) { + pjdlog_error("File name doesn't exist in open message"); + return (NULL); + } + nvout = nv_alloc(); + /* We should have opened trail file. */ if (adhost->adh_trail_fd == -1) { pjdlog_error("Sender requested closing file without first opening it."); - return (ADIST_ERROR_WRONG_ORDER); + error = ADIST_ERROR_WRONG_ORDER; + goto out; } + filename = nv_get_string(nvin, "filename"); + /* Validate if we can do the rename. */ if (!trail_validate_name(adhost->adh_trail_name, filename)) { pjdlog_error("Sender wants to close file \"%s\" using name \"%s\".", adhost->adh_trail_name, filename); - return (ADIST_ERROR_INVALID_NAME); + error = ADIST_ERROR_INVALID_NAME; + goto out; } - PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); adhost->adh_trail_fd = -1; - pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, - adhost->adh_trail_name); - if (strcmp(adhost->adh_trail_name, filename) == 0) { /* File name didn't change, we are done here. */ - return (0); + error = 0; + goto out; } if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, @@ -425,7 +559,8 @@ pjdlog_errno(LOG_ERR, "Unable to rename \"%s\" to \"%s\"", adhost->adh_trail_name, filename); PJDLOG_ASSERT(errno > 0); - return (ADIST_ERROR_RENAME); + error = ADIST_ERROR_RENAME; + goto out; } pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name, @@ -433,33 +568,115 @@ PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); - return (0); + error = 0; +out: + if (error != 0) + nv_add_int(nvout, "error", error); + return (nvout); } +/* + * This function is executed in sandbox. + */ static int -receiver_error(void) +receiver_close(struct adist_host *adhost, const char *filename) +{ + nv_t *nv; + int error; + + nv = nv_alloc(); + nv_add_string(nv, "cmd", "close"); + nv_add_string(nv, "filename", filename); + nv = nv_xfer(adhost->adh_conn, nv); + if (nv == NULL) { + pjdlog_exit(1, + "Unable to receive send or receive close command"); + } + if (nv_exists(nv, "error", NV_TYPE_INT)) { + error = nv_get_int(nv, "error"); + } else { + PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, + sizeof(adhost->adh_trail_name)) < + sizeof(adhost->adh_trail_name)); + error = 0; + } + nv_free(nv); + + if (error == 0 || error == ADIST_ERROR_RENAME) { + PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); + adhost->adh_trail_fd = -1; + pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, + adhost->adh_trail_name); + } + + return (error); +} + +/* + * This function is executed in privileged process. + */ +static nv_t * +receiver_msg_error(struct adist_host *adhost) { + nv_t *nvout; + int error; + + nvout = nv_alloc(); /* We should have opened trail file. */ if (adhost->adh_trail_fd == -1) { pjdlog_error("Sender send read error, but file is not open."); - return (ADIST_ERROR_WRONG_ORDER); + error = ADIST_ERROR_WRONG_ORDER; + goto out; } - PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); adhost->adh_trail_fd = -1; - pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, - adhost->adh_trail_name); + error = 0; +out: + if (error != 0) + nv_add_int(nvout, "error", error); + return (nvout); +} + +/* + * This function is executed in sandbox. + */ +static int +receiver_error(struct adist_host *adhost) +{ + nv_t *nv; + int error; + + nv = nv_alloc(); + nv_add_string(nv, "cmd", "error"); + nv = nv_xfer(adhost->adh_conn, nv); + if (nv == NULL) { + pjdlog_exit(1, + "Unable to receive send or receive error command"); + } + if (nv_exists(nv, "error", NV_TYPE_INT)) { + error = nv_get_int(nv, "error"); + } else { + PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); + adhost->adh_trail_fd = -1; + pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, + adhost->adh_trail_name); + error = 0; + } + nv_free(nv); - return (0); + return (error); } -static void * -disk_thread(void *arg __unused) +static __attribute__((__noreturn__)) void * +disk_thread(void *arg) { + struct adist_host *adhost; struct adreq *adreq; + adhost = arg; + for (;;) { pjdlog_debug(3, "disk: Taking request."); QUEUE_TAKE(adreq, &adist_disk_list, 0); @@ -468,17 +685,19 @@ /* Handle the actual request. */ switch (adreq->adr_cmd) { case ADIST_CMD_OPEN: - adreq->adr_error = receiver_open(adreq->adr_data); + adreq->adr_error = receiver_open(adhost, + adreq->adr_data); break; case ADIST_CMD_APPEND: - adreq->adr_error = receiver_append(adreq->adr_data, - adreq->adr_datasize); + adreq->adr_error = receiver_append(adhost, + adreq->adr_data, adreq->adr_datasize); break; case ADIST_CMD_CLOSE: - adreq->adr_error = receiver_close(adreq->adr_data); + adreq->adr_error = receiver_close(adhost, + adreq->adr_data); break; case ADIST_CMD_ERROR: - adreq->adr_error = receiver_error(); + adreq->adr_error = receiver_error(adhost); break; default: PJDLOG_ABORT("Unexpected command (cmd=%hhu).", @@ -493,18 +712,20 @@ QUEUE_INSERT(adreq, &adist_send_list); } /* NOTREACHED */ - return (NULL); } /* * Thread sends requests back to primary node. */ -static void * -send_thread(void *arg __unused) +static __attribute__((__noreturn__)) void * +send_thread(void *arg) { + struct adist_host *adhost; struct adreq *adreq; struct adrep adrep; + adhost = arg; + for (;;) { pjdlog_debug(3, "send: Taking request."); QUEUE_TAKE(adreq, &adist_send_list, 0); @@ -523,11 +744,10 @@ QUEUE_INSERT(adreq, &adist_free_list); } /* NOTREACHED */ - return (NULL); } -static void -receiver_directory_create(void) +static int +receiver_directory_create(struct adist_host *adhost) { struct passwd *pw; @@ -540,29 +760,31 @@ pw = getpwnam(ADIST_USER); if (pw == NULL) { if (errno != 0) { - pjdlog_exit(EX_NOUSER, + pjdlog_errno(LOG_ERR, "Unable to find info about '%s' user", ADIST_USER); } else { - pjdlog_exitx(EX_NOUSER, "User '%s' doesn't exist.", - ADIST_USER); + pjdlog_error("User '%s' doesn't exist.", ADIST_USER); } + return (-1); } if (mkdir(adhost->adh_directory, 0700) == -1) { - pjdlog_exit(EX_OSFILE, "Unable to create directory \"%s\"", + pjdlog_errno(LOG_ERR, "Unable to create directory \"%s\"", adhost->adh_directory); + return (-1); } if (chown(adhost->adh_directory, pw->pw_uid, pw->pw_gid) == -1) { pjdlog_errno(LOG_ERR, "Unable to change owner of the directory \"%s\"", adhost->adh_directory); (void)rmdir(adhost->adh_directory); - exit(EX_OSFILE); + return (-1); } + return (0); } -static void -receiver_directory_open(void) +static int +receiver_directory_open(struct adist_host *adhost) { #ifdef HAVE_FDOPENDIR @@ -570,47 +792,53 @@ O_RDONLY | O_DIRECTORY); if (adhost->adh_trail_dirfd == -1) { if (errno == ENOENT) { - receiver_directory_create(); + if (receiver_directory_create(adhost) == -1) + return (-1); adhost->adh_trail_dirfd = open(adhost->adh_directory, O_RDONLY | O_DIRECTORY); } if (adhost->adh_trail_dirfd == -1) { - pjdlog_exit(EX_CONFIG, - "Unable to open directory \"%s\"", + pjdlog_errno(LOG_ERR, "Unable to open directory \"%s\"", adhost->adh_directory); + return (-1); } } adhost->adh_trail_dirfp = fdopendir(adhost->adh_trail_dirfd); if (adhost->adh_trail_dirfp == NULL) { - pjdlog_exit(EX_CONFIG, "Unable to fdopen directory \"%s\"", + pjdlog_errno(LOG_ERR, "Unable to fdopen directory \"%s\"", adhost->adh_directory); + return (-1); } #else struct stat sb; if (stat(adhost->adh_directory, &sb) == -1) { if (errno == ENOENT) { - receiver_directory_create(); + if (receiver_directory_create(adhost) == -1) + return (-1); } else { - pjdlog_exit(EX_CONFIG, - "Unable to stat directory \"%s\"", + pjdlog_errno(LOG_ERR, "Unable to stat directory \"%s\"", adhost->adh_directory); + return (-1); } } adhost->adh_trail_dirfp = opendir(adhost->adh_directory); if (adhost->adh_trail_dirfp == NULL) { - pjdlog_exit(EX_CONFIG, "Unable to open directory \"%s\"", + pjdlog_errno(LOG_ERR, "Unable to open directory \"%s\"", adhost->adh_directory); + return (-1); } adhost->adh_trail_dirfd = dirfd(adhost->adh_trail_dirfp); #endif + return (0); } -static void -receiver_connect(void) +static nv_t * +receiver_msg_lasttrail(struct adist_host *adhost) { uint64_t trail_size; struct stat sb; + nv_t *nvout; PJDLOG_ASSERT(adhost->adh_trail_dirfp != NULL); @@ -622,17 +850,45 @@ } else { if (fstatat(adhost->adh_trail_dirfd, adhost->adh_trail_name, &sb, AT_SYMLINK_NOFOLLOW) == -1) { - pjdlog_exit(EX_CONFIG, "Unable to stat \"%s/%s\"", + pjdlog_errno(LOG_ERR, "Unable to stat \"%s/%s\"", adhost->adh_directory, adhost->adh_trail_name); + return (NULL); } if (!S_ISREG(sb.st_mode)) { - pjdlog_exitx(EX_CONFIG, - "File \"%s/%s\" is not a regular file.", + pjdlog_error("File \"%s/%s\" is not a regular file.", adhost->adh_directory, adhost->adh_trail_name); + return (NULL); } trail_size = sb.st_size; } - trail_size = htole64(trail_size); + + nvout = nv_alloc(); + nv_add_string(nvout, "trail_name", adhost->adh_trail_name); + nv_add_uint64(nvout, "trail_size", trail_size); + return (nvout); +} + +static void +receiver_connect(struct adist_host *adhost) +{ + uint64_t trail_size; + nv_t *nv; + + nv = nv_alloc(); + nv_add_string(nv, "cmd", "lasttrail"); + nv = nv_xfer(adhost->adh_conn, nv); + if (nv == NULL) { + pjdlog_exit(1, + "Unable to receive send or receive lasttrail command"); + } + + PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, + nv_get_string(nv, "trail_name"), sizeof(adhost->adh_trail_name)) < + sizeof(adhost->adh_trail_name)); + trail_size = htole64(nv_get_uint64(nv, "trail_size")); + + nv_free(nv); + if (proto_send(adhost->adh_remote, &trail_size, sizeof(trail_size)) == -1) { pjdlog_exit(EX_TEMPFAIL, @@ -645,38 +901,60 @@ } } -void -adist_receiver(struct adist_config *config, struct adist_host *adh) +int +adist_receiver(struct adist_config *config, struct adist_host *adhost) { sigset_t mask; pthread_t td; pid_t pid; int error, mode, debuglevel; + /* + * Create communication channel for sending connection requests from + * child to parent. + */ + if (proto_connect(NULL, "socketpair://", -1, &adhost->adh_conn) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to create connection sockets between child and parent"); + return (-1); + } + pid = fork(); if (pid == -1) { pjdlog_errno(LOG_ERR, "Unable to fork"); - proto_close(adh->adh_remote); - adh->adh_remote = NULL; - return; + proto_close(adhost->adh_remote); + adhost->adh_remote = NULL; + return (-1); } if (pid > 0) { /* This is parent. */ - proto_close(adh->adh_remote); - adh->adh_remote = NULL; - adh->adh_worker_pid = pid; - return; + adhost->adh_worker_pid = pid; + /* Declare that we are receiver. */ + proto_recv(adhost->adh_conn, NULL, 0); + proto_close(adhost->adh_remote); + adhost->adh_remote = NULL; + adhost->adh_trail_fd = -1; + if (receiver_directory_open(adhost) == -1) { + if (kill(pid, SIGKILL) == -1) + pjdlog_warning("Unable to kill worker"); + return (-1); + } + return (0); } adcfg = config; - adhost = adh; mode = pjdlog_mode_get(); debuglevel = pjdlog_debug_get(); + /* Declare that we are sender. */ + proto_send(adhost->adh_conn, NULL, 0); + descriptors_cleanup(adhost); -// descriptors_assert(adhost, mode); +#ifdef TODO + descriptors_assert(adhost, mode); +#endif pjdlog_init(mode); pjdlog_debug_set(debuglevel); @@ -696,7 +974,6 @@ init_environment(); adhost->adh_trail_fd = -1; - receiver_directory_open(); if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)", role2str(adhost->adh_role), adhost->adh_name) != 0) { @@ -704,11 +981,12 @@ } pjdlog_info("Privileges successfully dropped."); - receiver_connect(); + receiver_connect(adhost); error = pthread_create(&td, NULL, recv_thread, adhost); PJDLOG_ASSERT(error == 0); error = pthread_create(&td, NULL, disk_thread, adhost); PJDLOG_ASSERT(error == 0); (void)send_thread(adhost); + /* NOTREACHED */ } --- /dev/null 2013-09-08 20:00:00.000000000 +0200 +++ contrib/openbsm/bin/auditdistd/robustio.c 2013-09-08 20:08:59.212400324 +0200 @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "robustio.h" + +static void +fd_wait(int fd, bool doread) +{ + fd_set fds; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + (void)select(fd + 1, doread ? &fds : NULL, doread ? NULL : &fds, + NULL, NULL); +} + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +int +robust_send(int sock, const void *buf, size_t size) +{ + const unsigned char *ptr; + ssize_t done; + + assert(size > 0); + + ptr = buf; + do { + fd_wait(sock, false); + done = send(sock, ptr, MIN(size, 65536), 0); + if (done == -1) { + if (errno == EINTR) + continue; + return (-1); + } else if (done == 0) { + errno = ENOTCONN; + return (-1); + } + size -= done; + ptr += done; + } while (size > 0); + + return (0); +} + +int +robust_recv(int sock, void *buf, size_t size) +{ + unsigned char *ptr; + ssize_t done; + + assert(size > 0); + + ptr = buf; + do { + fd_wait(sock, true); + done = recv(sock, ptr, size, 0); + if (done == -1) { + if (errno == EINTR) + continue; + return (-1); + } else if (done == 0) { + errno = ENOTCONN; + return (-1); + } + size -= done; + ptr += done; + } while (size > 0); + + return (0); +} + +int +robust_peek(int sock, void *buf, size_t size) +{ + ssize_t done; + + assert(size > 0); + + for (;;) { + fd_wait(sock, true); + done = recv(sock, buf, size, MSG_PEEK | MSG_WAITALL); + if (done == -1) { + if (errno == EINTR) + continue; + return (-1); + } else if (done == 0) { + errno = ENOTCONN; + return (-1); + } else if (done != (ssize_t)size) { + errno = EBADMSG; + return (-1); + } + break; + } + return (0); +} --- /dev/null 2013-09-08 20:00:00.000000000 +0200 +++ contrib/openbsm/bin/auditdistd/robustio.h 2013-09-08 20:09:00.242400512 +0200 @@ -0,0 +1,39 @@ +/*- + * 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 _ROBUSTIO_H_ +#define _ROBUSTIO_H_ + +int robust_send(int sock, const void *buf, size_t size); +int robust_recv(int sock, void *buf, size_t size); +int robust_peek(int sock, void *buf, size_t size); + +#endif /* !_ROBUSTIO_H_ */ --- contrib/openbsm/bin/auditdistd/trail.c.orig +++ contrib/openbsm/bin/auditdistd/trail.c @@ -133,6 +133,17 @@ return (NULL); } } +#ifdef TODO + if (cap_rights_limit(dirfd(trail->tr_dirfp), + CAP_READ | CAP_SEEK) == -1) { + pjdlog_errno(LOG_ERR, + "Unable to limit capability rights on directory \"%s\" descriptor", + dirname); + closedir(trail->tr_dirfp); + free(trail); + return (NULL); + } +#endif trail->tr_filefd = -1; trail->tr_magic = TRAIL_MAGIC; return (trail); --- contrib/openbsm/config/config.h.orig +++ contrib/openbsm/config/config.h @@ -309,3 +309,5 @@ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ + +#define HAVE_PJDLOG --- usr.sbin/auditdistd/Makefile.orig +++ usr.sbin/auditdistd/Makefile @@ -9,14 +9,16 @@ # auditdistd.h. This seems like a makefile non-feature. CFLAGS+=-I${OPENBSMDIR} -I${OPENBSMDIR}/bin/auditdistd +NO_WCAST_ALIGN= NO_WFORMAT= NO_WMISSING_VARIABLE_DECLARATIONS= PROG= auditdistd SRCS= auditdistd.c +SRCS+= nv.c nvio.c SRCS+= parse.y pjdlog.c SRCS+= proto.c proto_common.c proto_socketpair.c proto_tcp.c proto_tls.c -SRCS+= receiver.c +SRCS+= receiver.c robustio.c SRCS+= sandbox.c sender.c subr.c SRCS+= token.l trail.c MAN= auditdistd.8 auditdistd.conf.5