1185573Srwatson/*- 2185573Srwatson * Copyright (c) 2004 Apple Inc. 3155131Srwatson * Copyright (c) 2006 Robert N. M. Watson 4155131Srwatson * All rights reserved. 5155131Srwatson * 6155131Srwatson * Redistribution and use in source and binary forms, with or without 7155131Srwatson * modification, are permitted provided that the following conditions 8155131Srwatson * are met: 9155131Srwatson * 1. Redistributions of source code must retain the above copyright 10155131Srwatson * notice, this list of conditions and the following disclaimer. 11155131Srwatson * 2. Redistributions in binary form must reproduce the above copyright 12155131Srwatson * notice, this list of conditions and the following disclaimer in the 13155131Srwatson * documentation and/or other materials provided with the distribution. 14185573Srwatson * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15155131Srwatson * its contributors may be used to endorse or promote products derived 16155131Srwatson * from this software without specific prior written permission. 17155131Srwatson * 18155131Srwatson * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21155131Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22155131Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26155131Srwatson * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27155131Srwatson * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28155131Srwatson * POSSIBILITY OF SUCH DAMAGE. 29155131Srwatson */ 30155131Srwatson 31185573Srwatson#include <config/config.h> 32185573Srwatson 33155131Srwatson#include <bsm/libbsm.h> 34155131Srwatson 35155131Srwatson#include <errno.h> 36155131Srwatson#include <stdio.h> 37155131Srwatson#include <string.h> 38155131Srwatson 39185573Srwatson#ifndef HAVE_STRLCPY 40185573Srwatson#include <compat/strlcpy.h> 41185573Srwatson#endif 42185573Srwatson 43155131Srwatsonstatic const char *flagdelim = ","; 44155131Srwatson 45155131Srwatson/* 46155131Srwatson * Convert the character representation of audit values into the au_mask_t 47155131Srwatson * field. 48155131Srwatson */ 49155131Srwatsonint 50155131Srwatsongetauditflagsbin(char *auditstr, au_mask_t *masks) 51155131Srwatson{ 52155131Srwatson char class_ent_name[AU_CLASS_NAME_MAX]; 53155131Srwatson char class_ent_desc[AU_CLASS_DESC_MAX]; 54155131Srwatson struct au_class_ent c; 55155131Srwatson char *tok; 56155131Srwatson char sel, sub; 57155131Srwatson char *last; 58155131Srwatson 59155131Srwatson bzero(&c, sizeof(c)); 60155131Srwatson bzero(class_ent_name, sizeof(class_ent_name)); 61155131Srwatson bzero(class_ent_desc, sizeof(class_ent_desc)); 62155131Srwatson c.ac_name = class_ent_name; 63155131Srwatson c.ac_desc = class_ent_desc; 64155131Srwatson 65155131Srwatson masks->am_success = 0; 66155131Srwatson masks->am_failure = 0; 67155131Srwatson 68155131Srwatson tok = strtok_r(auditstr, flagdelim, &last); 69155131Srwatson while (tok != NULL) { 70155131Srwatson /* Check for the events that should not be audited. */ 71155131Srwatson if (tok[0] == '^') { 72155131Srwatson sub = 1; 73155131Srwatson tok++; 74155131Srwatson } else 75155131Srwatson sub = 0; 76155131Srwatson 77155131Srwatson /* Check for the events to be audited for success. */ 78155131Srwatson if (tok[0] == '+') { 79155131Srwatson sel = AU_PRS_SUCCESS; 80155131Srwatson tok++; 81155131Srwatson } else if (tok[0] == '-') { 82155131Srwatson sel = AU_PRS_FAILURE; 83155131Srwatson tok++; 84155131Srwatson } else 85155131Srwatson sel = AU_PRS_BOTH; 86155131Srwatson 87155131Srwatson if ((getauclassnam_r(&c, tok)) != NULL) { 88155131Srwatson if (sub) 89155131Srwatson SUB_FROM_MASK(masks, c.ac_class, sel); 90155131Srwatson else 91155131Srwatson ADD_TO_MASK(masks, c.ac_class, sel); 92155131Srwatson } else { 93155131Srwatson errno = EINVAL; 94155131Srwatson return (-1); 95155131Srwatson } 96155131Srwatson 97155131Srwatson /* Get the next class. */ 98155131Srwatson tok = strtok_r(NULL, flagdelim, &last); 99155131Srwatson } 100155131Srwatson return (0); 101155131Srwatson} 102155131Srwatson 103155131Srwatson/* 104155131Srwatson * Convert the au_mask_t fields into a string value. If verbose is non-zero 105155131Srwatson * the long flag names are used else the short (2-character)flag names are 106155131Srwatson * used. 107155131Srwatson * 108155131Srwatson * XXXRW: If bits are specified that are not matched by any class, they are 109155131Srwatson * omitted rather than rejected with EINVAL. 110155131Srwatson * 111155131Srwatson * XXXRW: This is not thread-safe as it relies on atomicity between 112155131Srwatson * setauclass() and sequential calls to getauclassent(). This could be 113155131Srwatson * fixed by iterating through the bitmask fields rather than iterating 114155131Srwatson * through the classes. 115155131Srwatson */ 116155131Srwatsonint 117155131Srwatsongetauditflagschar(char *auditstr, au_mask_t *masks, int verbose) 118155131Srwatson{ 119155131Srwatson char class_ent_name[AU_CLASS_NAME_MAX]; 120155131Srwatson char class_ent_desc[AU_CLASS_DESC_MAX]; 121155131Srwatson struct au_class_ent c; 122155131Srwatson char *strptr = auditstr; 123155131Srwatson u_char sel; 124155131Srwatson 125155131Srwatson bzero(&c, sizeof(c)); 126155131Srwatson bzero(class_ent_name, sizeof(class_ent_name)); 127155131Srwatson bzero(class_ent_desc, sizeof(class_ent_desc)); 128155131Srwatson c.ac_name = class_ent_name; 129155131Srwatson c.ac_desc = class_ent_desc; 130155131Srwatson 131155131Srwatson /* 132155131Srwatson * Enumerate the class entries, check if each is selected in either 133155131Srwatson * the success or failure masks. 134155131Srwatson */ 135155131Srwatson setauclass(); 136155131Srwatson while ((getauclassent_r(&c)) != NULL) { 137155131Srwatson sel = 0; 138155131Srwatson 139155131Srwatson /* Dont do anything for class = no. */ 140155131Srwatson if (c.ac_class == 0) 141155131Srwatson continue; 142155131Srwatson 143155131Srwatson sel |= ((c.ac_class & masks->am_success) == c.ac_class) ? 144155131Srwatson AU_PRS_SUCCESS : 0; 145155131Srwatson sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ? 146155131Srwatson AU_PRS_FAILURE : 0; 147155131Srwatson 148155131Srwatson /* 149155131Srwatson * No prefix should be attached if both success and failure 150155131Srwatson * are selected. 151155131Srwatson */ 152155131Srwatson if ((sel & AU_PRS_BOTH) == 0) { 153155131Srwatson if ((sel & AU_PRS_SUCCESS) != 0) { 154155131Srwatson *strptr = '+'; 155155131Srwatson strptr = strptr + 1; 156155131Srwatson } else if ((sel & AU_PRS_FAILURE) != 0) { 157155131Srwatson *strptr = '-'; 158155131Srwatson strptr = strptr + 1; 159155131Srwatson } 160155131Srwatson } 161155131Srwatson 162155131Srwatson if (sel != 0) { 163155131Srwatson if (verbose) { 164185573Srwatson strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX); 165155131Srwatson strptr += strlen(c.ac_desc); 166155131Srwatson } else { 167185573Srwatson strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX); 168155131Srwatson strptr += strlen(c.ac_name); 169155131Srwatson } 170155131Srwatson *strptr = ','; /* delimiter */ 171155131Srwatson strptr = strptr + 1; 172155131Srwatson } 173155131Srwatson } 174155131Srwatson 175155131Srwatson /* Overwrite the last delimiter with the string terminator. */ 176155131Srwatson if (strptr != auditstr) 177155131Srwatson *(strptr-1) = '\0'; 178155131Srwatson 179155131Srwatson return (0); 180155131Srwatson} 181