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 * 30185573Srwatson * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_flags.c#16 $ 31155131Srwatson */ 32155131Srwatson 33185573Srwatson#include <config/config.h> 34185573Srwatson 35155131Srwatson#include <bsm/libbsm.h> 36155131Srwatson 37155131Srwatson#include <errno.h> 38155131Srwatson#include <stdio.h> 39155131Srwatson#include <string.h> 40155131Srwatson 41185573Srwatson#ifndef HAVE_STRLCPY 42185573Srwatson#include <compat/strlcpy.h> 43185573Srwatson#endif 44185573Srwatson 45155131Srwatsonstatic const char *flagdelim = ","; 46155131Srwatson 47155131Srwatson/* 48155131Srwatson * Convert the character representation of audit values into the au_mask_t 49155131Srwatson * field. 50155131Srwatson */ 51155131Srwatsonint 52155131Srwatsongetauditflagsbin(char *auditstr, au_mask_t *masks) 53155131Srwatson{ 54155131Srwatson char class_ent_name[AU_CLASS_NAME_MAX]; 55155131Srwatson char class_ent_desc[AU_CLASS_DESC_MAX]; 56155131Srwatson struct au_class_ent c; 57155131Srwatson char *tok; 58155131Srwatson char sel, sub; 59155131Srwatson char *last; 60155131Srwatson 61155131Srwatson bzero(&c, sizeof(c)); 62155131Srwatson bzero(class_ent_name, sizeof(class_ent_name)); 63155131Srwatson bzero(class_ent_desc, sizeof(class_ent_desc)); 64155131Srwatson c.ac_name = class_ent_name; 65155131Srwatson c.ac_desc = class_ent_desc; 66155131Srwatson 67155131Srwatson masks->am_success = 0; 68155131Srwatson masks->am_failure = 0; 69155131Srwatson 70155131Srwatson tok = strtok_r(auditstr, flagdelim, &last); 71155131Srwatson while (tok != NULL) { 72155131Srwatson /* Check for the events that should not be audited. */ 73155131Srwatson if (tok[0] == '^') { 74155131Srwatson sub = 1; 75155131Srwatson tok++; 76155131Srwatson } else 77155131Srwatson sub = 0; 78155131Srwatson 79155131Srwatson /* Check for the events to be audited for success. */ 80155131Srwatson if (tok[0] == '+') { 81155131Srwatson sel = AU_PRS_SUCCESS; 82155131Srwatson tok++; 83155131Srwatson } else if (tok[0] == '-') { 84155131Srwatson sel = AU_PRS_FAILURE; 85155131Srwatson tok++; 86155131Srwatson } else 87155131Srwatson sel = AU_PRS_BOTH; 88155131Srwatson 89155131Srwatson if ((getauclassnam_r(&c, tok)) != NULL) { 90155131Srwatson if (sub) 91155131Srwatson SUB_FROM_MASK(masks, c.ac_class, sel); 92155131Srwatson else 93155131Srwatson ADD_TO_MASK(masks, c.ac_class, sel); 94155131Srwatson } else { 95155131Srwatson errno = EINVAL; 96155131Srwatson return (-1); 97155131Srwatson } 98155131Srwatson 99155131Srwatson /* Get the next class. */ 100155131Srwatson tok = strtok_r(NULL, flagdelim, &last); 101155131Srwatson } 102155131Srwatson return (0); 103155131Srwatson} 104155131Srwatson 105155131Srwatson/* 106155131Srwatson * Convert the au_mask_t fields into a string value. If verbose is non-zero 107155131Srwatson * the long flag names are used else the short (2-character)flag names are 108155131Srwatson * used. 109155131Srwatson * 110155131Srwatson * XXXRW: If bits are specified that are not matched by any class, they are 111155131Srwatson * omitted rather than rejected with EINVAL. 112155131Srwatson * 113155131Srwatson * XXXRW: This is not thread-safe as it relies on atomicity between 114155131Srwatson * setauclass() and sequential calls to getauclassent(). This could be 115155131Srwatson * fixed by iterating through the bitmask fields rather than iterating 116155131Srwatson * through the classes. 117155131Srwatson */ 118155131Srwatsonint 119155131Srwatsongetauditflagschar(char *auditstr, au_mask_t *masks, int verbose) 120155131Srwatson{ 121155131Srwatson char class_ent_name[AU_CLASS_NAME_MAX]; 122155131Srwatson char class_ent_desc[AU_CLASS_DESC_MAX]; 123155131Srwatson struct au_class_ent c; 124155131Srwatson char *strptr = auditstr; 125155131Srwatson u_char sel; 126155131Srwatson 127155131Srwatson bzero(&c, sizeof(c)); 128155131Srwatson bzero(class_ent_name, sizeof(class_ent_name)); 129155131Srwatson bzero(class_ent_desc, sizeof(class_ent_desc)); 130155131Srwatson c.ac_name = class_ent_name; 131155131Srwatson c.ac_desc = class_ent_desc; 132155131Srwatson 133155131Srwatson /* 134155131Srwatson * Enumerate the class entries, check if each is selected in either 135155131Srwatson * the success or failure masks. 136155131Srwatson */ 137155131Srwatson setauclass(); 138155131Srwatson while ((getauclassent_r(&c)) != NULL) { 139155131Srwatson sel = 0; 140155131Srwatson 141155131Srwatson /* Dont do anything for class = no. */ 142155131Srwatson if (c.ac_class == 0) 143155131Srwatson continue; 144155131Srwatson 145155131Srwatson sel |= ((c.ac_class & masks->am_success) == c.ac_class) ? 146155131Srwatson AU_PRS_SUCCESS : 0; 147155131Srwatson sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ? 148155131Srwatson AU_PRS_FAILURE : 0; 149155131Srwatson 150155131Srwatson /* 151155131Srwatson * No prefix should be attached if both success and failure 152155131Srwatson * are selected. 153155131Srwatson */ 154155131Srwatson if ((sel & AU_PRS_BOTH) == 0) { 155155131Srwatson if ((sel & AU_PRS_SUCCESS) != 0) { 156155131Srwatson *strptr = '+'; 157155131Srwatson strptr = strptr + 1; 158155131Srwatson } else if ((sel & AU_PRS_FAILURE) != 0) { 159155131Srwatson *strptr = '-'; 160155131Srwatson strptr = strptr + 1; 161155131Srwatson } 162155131Srwatson } 163155131Srwatson 164155131Srwatson if (sel != 0) { 165155131Srwatson if (verbose) { 166185573Srwatson strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX); 167155131Srwatson strptr += strlen(c.ac_desc); 168155131Srwatson } else { 169185573Srwatson strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX); 170155131Srwatson strptr += strlen(c.ac_name); 171155131Srwatson } 172155131Srwatson *strptr = ','; /* delimiter */ 173155131Srwatson strptr = strptr + 1; 174155131Srwatson } 175155131Srwatson } 176155131Srwatson 177155131Srwatson /* Overwrite the last delimiter with the string terminator. */ 178155131Srwatson if (strptr != auditstr) 179155131Srwatson *(strptr-1) = '\0'; 180155131Srwatson 181155131Srwatson return (0); 182155131Srwatson} 183