1243730Srwatson/*- 2243730Srwatson * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net> 3243730Srwatson * All rights reserved. 4243730Srwatson * 5243730Srwatson * Redistribution and use in source and binary forms, with or without 6243730Srwatson * modification, are permitted provided that the following conditions 7243730Srwatson * are met: 8243730Srwatson * 1. Redistributions of source code must retain the above copyright 9243730Srwatson * notice, this list of conditions and the following disclaimer. 10243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11243730Srwatson * notice, this list of conditions and the following disclaimer in the 12243730Srwatson * documentation and/or other materials provided with the distribution. 13243730Srwatson * 14243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24243730Srwatson * SUCH DAMAGE. 25243730Srwatson * 26243734Srwatson * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/subr.c#3 $ 27243730Srwatson */ 28243730Srwatson 29243734Srwatson#include <config/config.h> 30243730Srwatson 31243730Srwatson#ifdef HAVE_KQUEUE 32243730Srwatson#include <sys/types.h> 33243730Srwatson#include <sys/event.h> 34243730Srwatson#include <sys/time.h> 35243730Srwatson#endif 36243730Srwatson 37243730Srwatson#include <errno.h> 38243730Srwatson#include <stdarg.h> 39243730Srwatson#include <stdio.h> 40243730Srwatson#include <string.h> 41243730Srwatson#include <unistd.h> 42243730Srwatson 43243730Srwatson#ifndef HAVE_ARC4RANDOM 44243730Srwatson#include <openssl/rand.h> 45243730Srwatson#endif 46243730Srwatson 47243730Srwatson#ifndef HAVE_STRLCAT 48243730Srwatson#include <compat/strlcat.h> 49243730Srwatson#endif 50243730Srwatson 51243730Srwatson#include "auditdistd.h" 52243734Srwatson#include "pjdlog.h" 53243730Srwatson#include "subr.h" 54243730Srwatson 55243730Srwatsonint 56243730Srwatsonvsnprlcat(char *str, size_t size, const char *fmt, va_list ap) 57243730Srwatson{ 58243730Srwatson size_t len; 59243730Srwatson 60243730Srwatson len = strlen(str); 61243730Srwatson return (vsnprintf(str + len, size - len, fmt, ap)); 62243730Srwatson} 63243730Srwatson 64243730Srwatsonint 65243730Srwatsonsnprlcat(char *str, size_t size, const char *fmt, ...) 66243730Srwatson{ 67243730Srwatson va_list ap; 68243730Srwatson int result; 69243730Srwatson 70243730Srwatson va_start(ap, fmt); 71243730Srwatson result = vsnprlcat(str, size, fmt, ap); 72243730Srwatson va_end(ap); 73243730Srwatson return (result); 74243730Srwatson} 75243730Srwatson 76243730Srwatsonconst char * 77243730Srwatsonrole2str(int role) 78243730Srwatson{ 79243730Srwatson 80243730Srwatson switch (role) { 81243730Srwatson case ADIST_ROLE_SENDER: 82243730Srwatson return ("sender"); 83243730Srwatson case ADIST_ROLE_RECEIVER: 84243730Srwatson return ("receiver"); 85243730Srwatson } 86243730Srwatson return ("unknown"); 87243730Srwatson} 88243730Srwatson 89243730Srwatsonconst char * 90243730Srwatsonadist_errstr(int error) 91243730Srwatson{ 92243730Srwatson 93243730Srwatson switch (error) { 94243730Srwatson case ADIST_ERROR_WRONG_ORDER: 95243730Srwatson return ("wrong operations order"); 96243730Srwatson case ADIST_ERROR_INVALID_NAME: 97243730Srwatson return ("invalid trail file name"); 98243730Srwatson case ADIST_ERROR_OPEN_OLD: 99243730Srwatson return ("attempt to open an old trail file"); 100243730Srwatson case ADIST_ERROR_CREATE: 101243730Srwatson return ("creation of new trail file failed"); 102243730Srwatson case ADIST_ERROR_OPEN: 103243730Srwatson return ("open of existing trail file failed"); 104243730Srwatson case ADIST_ERROR_READ: 105243730Srwatson return ("read failed"); 106243730Srwatson case ADIST_ERROR_WRITE: 107243730Srwatson return ("write failed"); 108243730Srwatson case ADIST_ERROR_RENAME: 109243730Srwatson return ("rename of a trail file failed"); 110243730Srwatson default: 111243730Srwatson return ("unknown error"); 112243730Srwatson } 113243730Srwatson} 114243730Srwatson 115243730Srwatsonvoid 116243730Srwatsonadreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, 117243730Srwatson const char *fmt, ...) 118243730Srwatson{ 119243730Srwatson char msg[1024]; 120243730Srwatson va_list ap; 121243730Srwatson 122243730Srwatson va_start(ap, fmt); 123243730Srwatson (void)vsnprintf(msg, sizeof(msg), fmt, ap); 124243730Srwatson va_end(ap); 125243730Srwatson (void)snprlcat(msg, sizeof(msg), "(seq=%ju) ", 126243730Srwatson (uintmax_t)adreq->adr_seq); 127243730Srwatson switch (adreq->adr_cmd) { 128243730Srwatson case ADIST_CMD_OPEN: 129243730Srwatson (void)snprlcat(msg, sizeof(msg), "OPEN(%s)", 130243730Srwatson adreq->adr_data); 131243730Srwatson break; 132243730Srwatson case ADIST_CMD_APPEND: 133243730Srwatson (void)snprlcat(msg, sizeof(msg), "APPEND(%ju)", 134243730Srwatson (uintmax_t)adreq->adr_datasize); 135243730Srwatson break; 136243730Srwatson case ADIST_CMD_CLOSE: 137243730Srwatson (void)snprlcat(msg, sizeof(msg), "CLOSE(%s)", 138243730Srwatson adreq->adr_data); 139243730Srwatson break; 140243730Srwatson case ADIST_CMD_KEEPALIVE: 141243730Srwatson (void)snprlcat(msg, sizeof(msg), "KEEPALIVE"); 142243730Srwatson break; 143243730Srwatson case ADIST_CMD_ERROR: 144243730Srwatson (void)snprlcat(msg, sizeof(msg), "ERROR"); 145243730Srwatson break; 146243730Srwatson default: 147243730Srwatson (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)", 148243730Srwatson adreq->adr_cmd); 149243730Srwatson break; 150243730Srwatson } 151243730Srwatson if (error != -1) 152243730Srwatson (void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error)); 153243730Srwatson (void)strlcat(msg, ".", sizeof(msg)); 154243730Srwatson pjdlog_common(loglevel, debuglevel, -1, "%s", msg); 155243730Srwatson} 156243730Srwatson 157243730Srwatsonint 158243730Srwatsonadist_random(unsigned char *buf, size_t size) 159243730Srwatson{ 160243730Srwatson#ifdef HAVE_ARC4RANDOM_BUF 161243730Srwatson arc4random_buf(buf, size); 162243730Srwatson return (0); 163243730Srwatson#elif defined(HAVE_ARC4RANDOM) 164243730Srwatson uint32_t val; 165243730Srwatson 166243730Srwatson PJDLOG_ASSERT(size > 0); 167243730Srwatson PJDLOG_ASSERT((size % sizeof(val)) == 0); 168243730Srwatson 169243730Srwatson do { 170243730Srwatson val = arc4random(); 171243730Srwatson bcopy(&val, buf, sizeof(val)); 172243730Srwatson buf += sizeof(val); 173243730Srwatson size -= sizeof(val); 174243730Srwatson } while (size > 0); 175243730Srwatson 176243730Srwatson return (0); 177243730Srwatson#else 178243730Srwatson if (RAND_bytes(buf, (int)size) == 0) 179243730Srwatson return (-1); 180243730Srwatson return (0); 181243730Srwatson#endif 182243730Srwatson} 183243730Srwatson 184243730Srwatsonstatic int wait_for_dir_kq = -1; 185243730Srwatsonstatic int wait_for_file_kq = -1; 186243730Srwatson 187243730Srwatsonint 188243730Srwatsonwait_for_dir_init(int fd) 189243730Srwatson{ 190243730Srwatson#ifdef HAVE_KQUEUE 191243730Srwatson struct kevent ev; 192243730Srwatson int error, kq; 193243730Srwatson 194243730Srwatson PJDLOG_ASSERT(wait_for_dir_kq == -1); 195243730Srwatson#endif 196243730Srwatson 197243730Srwatson PJDLOG_ASSERT(fd != -1); 198243730Srwatson 199243730Srwatson#ifdef HAVE_KQUEUE 200243730Srwatson kq = kqueue(); 201243730Srwatson if (kq == -1) { 202243730Srwatson pjdlog_errno(LOG_WARNING, "kqueue() failed"); 203243730Srwatson return (-1); 204243730Srwatson } 205243730Srwatson EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 206243730Srwatson NOTE_WRITE, 0, 0); 207243730Srwatson if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { 208243730Srwatson error = errno; 209243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 210243730Srwatson (void)close(kq); 211243730Srwatson errno = error; 212243730Srwatson return (-1); 213243730Srwatson } 214243730Srwatson wait_for_dir_kq = kq; 215243730Srwatson#endif 216243730Srwatson 217243730Srwatson return (0); 218243730Srwatson} 219243730Srwatson 220243730Srwatsonint 221243730Srwatsonwait_for_file_init(int fd) 222243730Srwatson{ 223243730Srwatson#ifdef HAVE_KQUEUE 224243730Srwatson struct kevent ev[2]; 225243730Srwatson int error, kq; 226243730Srwatson#endif 227243730Srwatson 228243730Srwatson PJDLOG_ASSERT(fd != -1); 229243730Srwatson 230243730Srwatson#ifdef HAVE_KQUEUE 231243730Srwatson kq = kqueue(); 232243730Srwatson if (kq == -1) { 233243730Srwatson pjdlog_errno(LOG_WARNING, "kqueue() failed"); 234243730Srwatson return (-1); 235243730Srwatson } 236243730Srwatson EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 237243730Srwatson NOTE_RENAME, 0, 0); 238243730Srwatson EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 239243730Srwatson 0, 0, 0); 240243730Srwatson if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) { 241243730Srwatson error = errno; 242243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 243243730Srwatson (void)close(kq); 244243730Srwatson errno = error; 245243730Srwatson return (-1); 246243730Srwatson } 247243730Srwatson wait_for_file_kq = kq; 248243730Srwatson#endif 249243730Srwatson 250243730Srwatson return (0); 251243730Srwatson} 252243730Srwatson 253243730Srwatson/* 254243730Srwatson * Wait for new file to appear in directory. 255243730Srwatson */ 256243730Srwatsonvoid 257243730Srwatsonwait_for_dir(void) 258243730Srwatson{ 259243730Srwatson#ifdef HAVE_KQUEUE 260243730Srwatson struct kevent ev; 261243730Srwatson#endif 262243730Srwatson 263243730Srwatson if (wait_for_dir_kq == -1) { 264243730Srwatson sleep(1); 265243730Srwatson return; 266243730Srwatson } 267243730Srwatson 268243730Srwatson#ifdef HAVE_KQUEUE 269243730Srwatson PJDLOG_ASSERT(wait_for_dir_kq != -1); 270243730Srwatson 271243730Srwatson if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) { 272243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 273243730Srwatson sleep(1); 274243730Srwatson } 275243730Srwatson#endif 276243730Srwatson} 277243730Srwatson 278243730Srwatson/* 279243730Srwatson * Wait for file growth or rename. 280243730Srwatson */ 281243730Srwatsonvoid 282243730Srwatsonwait_for_file(void) 283243730Srwatson{ 284243730Srwatson#ifdef HAVE_KQUEUE 285243730Srwatson struct kevent ev[2]; 286243730Srwatson#endif 287243730Srwatson 288243730Srwatson if (wait_for_file_kq == -1) { 289243730Srwatson sleep(1); 290243730Srwatson return; 291243730Srwatson } 292243730Srwatson 293243730Srwatson#ifdef HAVE_KQUEUE 294243730Srwatson PJDLOG_ASSERT(wait_for_file_kq != -1); 295243730Srwatson 296243730Srwatson if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) { 297243730Srwatson pjdlog_errno(LOG_WARNING, "kevent() failed"); 298243730Srwatson sleep(1); 299243730Srwatson } 300243730Srwatson#endif 301243730Srwatson} 302