1/*- 2 * Copyright (c) 2004 Apple Inc. 3 * Copyright (c) 2006 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 *
| 1/*- 2 * Copyright (c) 2004 Apple Inc. 3 * Copyright (c) 2006 Robert N. M. Watson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 *
|
30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#14 $
| 30 * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#15 $
|
31 */ 32 33#include <config/config.h> 34 35#include <bsm/libbsm.h> 36 37#include <string.h>
| 31 */ 32 33#include <config/config.h> 34 35#include <bsm/libbsm.h> 36 37#include <string.h>
|
| 38#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
38#include <pthread.h>
| 39#include <pthread.h>
|
| 40#endif
|
39#include <stdio.h> 40#include <stdlib.h> 41 42#ifndef HAVE_STRLCPY 43#include <compat/strlcpy.h> 44#endif 45 46/* 47 * Parse the contents of the audit_class file to return struct au_class_ent 48 * entries. 49 */ 50static FILE *fp = NULL; 51static char linestr[AU_LINE_MAX]; 52static const char *classdelim = ":"; 53
| 41#include <stdio.h> 42#include <stdlib.h> 43 44#ifndef HAVE_STRLCPY 45#include <compat/strlcpy.h> 46#endif 47 48/* 49 * Parse the contents of the audit_class file to return struct au_class_ent 50 * entries. 51 */ 52static FILE *fp = NULL; 53static char linestr[AU_LINE_MAX]; 54static const char *classdelim = ":"; 55
|
| 56#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
54static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
| 57static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
| 58#endif
|
55 56/* 57 * Parse a single line from the audit_class file passed in str to the struct 58 * au_class_ent elements; store the result in c. 59 */ 60static struct au_class_ent * 61classfromstr(char *str, struct au_class_ent *c) 62{ 63 char *classname, *classdesc, *classflag; 64 char *last; 65 66 /* Each line contains flag:name:desc. */ 67 classflag = strtok_r(str, classdelim, &last); 68 classname = strtok_r(NULL, classdelim, &last); 69 classdesc = strtok_r(NULL, classdelim, &last); 70 71 if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL)) 72 return (NULL); 73 74 /* 75 * Check for very large classnames. 76 */ 77 if (strlen(classname) >= AU_CLASS_NAME_MAX) 78 return (NULL); 79 strlcpy(c->ac_name, classname, AU_CLASS_NAME_MAX); 80 81 /* 82 * Check for very large class description. 83 */ 84 if (strlen(classdesc) >= AU_CLASS_DESC_MAX) 85 return (NULL); 86 strlcpy(c->ac_desc, classdesc, AU_CLASS_DESC_MAX); 87 c->ac_class = strtoul(classflag, (char **) NULL, 0); 88 89 return (c); 90} 91 92/* 93 * Return the next au_class_ent structure from the file setauclass should be 94 * called before invoking this function for the first time. 95 * 96 * Must be called with mutex held. 97 */ 98static struct au_class_ent * 99getauclassent_r_locked(struct au_class_ent *c) 100{ 101 char *tokptr, *nl; 102 103 if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL)) 104 return (NULL); 105 106 /* 107 * Read until next non-comment line is found, or EOF. 108 */ 109 while (1) { 110 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 111 return (NULL); 112 113 /* Skip comments. */ 114 if (linestr[0] == '#') 115 continue; 116 117 /* Remove trailing new line character. */ 118 if ((nl = strrchr(linestr, '\n')) != NULL) 119 *nl = '\0'; 120 121 /* Parse tokptr to au_class_ent components. */ 122 tokptr = linestr; 123 if (classfromstr(tokptr, c) == NULL) 124 return (NULL); 125 break; 126 } 127 128 return (c); 129} 130 131struct au_class_ent * 132getauclassent_r(struct au_class_ent *c) 133{ 134 struct au_class_ent *cp; 135
| 59 60/* 61 * Parse a single line from the audit_class file passed in str to the struct 62 * au_class_ent elements; store the result in c. 63 */ 64static struct au_class_ent * 65classfromstr(char *str, struct au_class_ent *c) 66{ 67 char *classname, *classdesc, *classflag; 68 char *last; 69 70 /* Each line contains flag:name:desc. */ 71 classflag = strtok_r(str, classdelim, &last); 72 classname = strtok_r(NULL, classdelim, &last); 73 classdesc = strtok_r(NULL, classdelim, &last); 74 75 if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL)) 76 return (NULL); 77 78 /* 79 * Check for very large classnames. 80 */ 81 if (strlen(classname) >= AU_CLASS_NAME_MAX) 82 return (NULL); 83 strlcpy(c->ac_name, classname, AU_CLASS_NAME_MAX); 84 85 /* 86 * Check for very large class description. 87 */ 88 if (strlen(classdesc) >= AU_CLASS_DESC_MAX) 89 return (NULL); 90 strlcpy(c->ac_desc, classdesc, AU_CLASS_DESC_MAX); 91 c->ac_class = strtoul(classflag, (char **) NULL, 0); 92 93 return (c); 94} 95 96/* 97 * Return the next au_class_ent structure from the file setauclass should be 98 * called before invoking this function for the first time. 99 * 100 * Must be called with mutex held. 101 */ 102static struct au_class_ent * 103getauclassent_r_locked(struct au_class_ent *c) 104{ 105 char *tokptr, *nl; 106 107 if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL)) 108 return (NULL); 109 110 /* 111 * Read until next non-comment line is found, or EOF. 112 */ 113 while (1) { 114 if (fgets(linestr, AU_LINE_MAX, fp) == NULL) 115 return (NULL); 116 117 /* Skip comments. */ 118 if (linestr[0] == '#') 119 continue; 120 121 /* Remove trailing new line character. */ 122 if ((nl = strrchr(linestr, '\n')) != NULL) 123 *nl = '\0'; 124 125 /* Parse tokptr to au_class_ent components. */ 126 tokptr = linestr; 127 if (classfromstr(tokptr, c) == NULL) 128 return (NULL); 129 break; 130 } 131 132 return (c); 133} 134 135struct au_class_ent * 136getauclassent_r(struct au_class_ent *c) 137{ 138 struct au_class_ent *cp; 139
|
| 140#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
136 pthread_mutex_lock(&mutex);
| 141 pthread_mutex_lock(&mutex);
|
| 142#endif
|
137 cp = getauclassent_r_locked(c);
| 143 cp = getauclassent_r_locked(c);
|
| 144#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
138 pthread_mutex_unlock(&mutex);
| 145 pthread_mutex_unlock(&mutex);
|
| 146#endif
|
139 return (cp); 140} 141 142struct au_class_ent * 143getauclassent(void) 144{ 145 static char class_ent_name[AU_CLASS_NAME_MAX]; 146 static char class_ent_desc[AU_CLASS_DESC_MAX]; 147 static struct au_class_ent c, *cp; 148 149 bzero(&c, sizeof(c)); 150 bzero(class_ent_name, sizeof(class_ent_name)); 151 bzero(class_ent_desc, sizeof(class_ent_desc)); 152 c.ac_name = class_ent_name; 153 c.ac_desc = class_ent_desc; 154
| 147 return (cp); 148} 149 150struct au_class_ent * 151getauclassent(void) 152{ 153 static char class_ent_name[AU_CLASS_NAME_MAX]; 154 static char class_ent_desc[AU_CLASS_DESC_MAX]; 155 static struct au_class_ent c, *cp; 156 157 bzero(&c, sizeof(c)); 158 bzero(class_ent_name, sizeof(class_ent_name)); 159 bzero(class_ent_desc, sizeof(class_ent_desc)); 160 c.ac_name = class_ent_name; 161 c.ac_desc = class_ent_desc; 162
|
| 163#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
155 pthread_mutex_lock(&mutex);
| 164 pthread_mutex_lock(&mutex);
|
| 165#endif
|
156 cp = getauclassent_r_locked(&c);
| 166 cp = getauclassent_r_locked(&c);
|
| 167#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
157 pthread_mutex_unlock(&mutex);
| 168 pthread_mutex_unlock(&mutex);
|
| 169#endif
|
158 return (cp); 159} 160 161/* 162 * Rewind to the beginning of the enumeration. 163 * 164 * Must be called with mutex held. 165 */ 166static void 167setauclass_locked(void) 168{ 169 170 if (fp != NULL) 171 fseek(fp, 0, SEEK_SET); 172} 173 174void 175setauclass(void) 176{ 177
| 170 return (cp); 171} 172 173/* 174 * Rewind to the beginning of the enumeration. 175 * 176 * Must be called with mutex held. 177 */ 178static void 179setauclass_locked(void) 180{ 181 182 if (fp != NULL) 183 fseek(fp, 0, SEEK_SET); 184} 185 186void 187setauclass(void) 188{ 189
|
| 190#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
178 pthread_mutex_lock(&mutex);
| 191 pthread_mutex_lock(&mutex);
|
| 192#endif
|
179 setauclass_locked();
| 193 setauclass_locked();
|
| 194#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
180 pthread_mutex_unlock(&mutex);
| 195 pthread_mutex_unlock(&mutex);
|
| 196#endif
|
181} 182 183/* 184 * Return the next au_class_entry having the given class name. 185 */ 186struct au_class_ent * 187getauclassnam_r(struct au_class_ent *c, const char *name) 188{ 189 struct au_class_ent *cp; 190 191 if (name == NULL) 192 return (NULL); 193
| 197} 198 199/* 200 * Return the next au_class_entry having the given class name. 201 */ 202struct au_class_ent * 203getauclassnam_r(struct au_class_ent *c, const char *name) 204{ 205 struct au_class_ent *cp; 206 207 if (name == NULL) 208 return (NULL); 209
|
| 210#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
194 pthread_mutex_lock(&mutex);
| 211 pthread_mutex_lock(&mutex);
|
| 212#endif
|
195 setauclass_locked(); 196 while ((cp = getauclassent_r_locked(c)) != NULL) { 197 if (strcmp(name, cp->ac_name) == 0) {
| 213 setauclass_locked(); 214 while ((cp = getauclassent_r_locked(c)) != NULL) { 215 if (strcmp(name, cp->ac_name) == 0) {
|
| 216#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
198 pthread_mutex_unlock(&mutex);
| 217 pthread_mutex_unlock(&mutex);
|
| 218#endif
|
199 return (cp); 200 } 201 }
| 219 return (cp); 220 } 221 }
|
| 222#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
202 pthread_mutex_unlock(&mutex);
| 223 pthread_mutex_unlock(&mutex);
|
| 224#endif
|
203 return (NULL); 204} 205 206struct au_class_ent * 207getauclassnam(const char *name) 208{ 209 static char class_ent_name[AU_CLASS_NAME_MAX]; 210 static char class_ent_desc[AU_CLASS_DESC_MAX]; 211 static struct au_class_ent c; 212 213 bzero(&c, sizeof(c)); 214 bzero(class_ent_name, sizeof(class_ent_name)); 215 bzero(class_ent_desc, sizeof(class_ent_desc)); 216 c.ac_name = class_ent_name; 217 c.ac_desc = class_ent_desc; 218 219 return (getauclassnam_r(&c, name)); 220} 221 222 223/* 224 * Return the next au_class_entry having the given class number. 225 * 226 * OpenBSM extension. 227 */ 228struct au_class_ent * 229getauclassnum_r(struct au_class_ent *c, au_class_t class_number) 230{ 231 struct au_class_ent *cp; 232
| 225 return (NULL); 226} 227 228struct au_class_ent * 229getauclassnam(const char *name) 230{ 231 static char class_ent_name[AU_CLASS_NAME_MAX]; 232 static char class_ent_desc[AU_CLASS_DESC_MAX]; 233 static struct au_class_ent c; 234 235 bzero(&c, sizeof(c)); 236 bzero(class_ent_name, sizeof(class_ent_name)); 237 bzero(class_ent_desc, sizeof(class_ent_desc)); 238 c.ac_name = class_ent_name; 239 c.ac_desc = class_ent_desc; 240 241 return (getauclassnam_r(&c, name)); 242} 243 244 245/* 246 * Return the next au_class_entry having the given class number. 247 * 248 * OpenBSM extension. 249 */ 250struct au_class_ent * 251getauclassnum_r(struct au_class_ent *c, au_class_t class_number) 252{ 253 struct au_class_ent *cp; 254
|
| 255#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
233 pthread_mutex_lock(&mutex);
| 256 pthread_mutex_lock(&mutex);
|
| 257#endif
|
234 setauclass_locked(); 235 while ((cp = getauclassent_r_locked(c)) != NULL) { 236 if (class_number == cp->ac_class) 237 return (cp); 238 }
| 258 setauclass_locked(); 259 while ((cp = getauclassent_r_locked(c)) != NULL) { 260 if (class_number == cp->ac_class) 261 return (cp); 262 }
|
| 263#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
239 pthread_mutex_unlock(&mutex);
| 264 pthread_mutex_unlock(&mutex);
|
| 265#endif
|
240 return (NULL); 241} 242 243struct au_class_ent * 244getauclassnum(au_class_t class_number) 245{ 246 static char class_ent_name[AU_CLASS_NAME_MAX]; 247 static char class_ent_desc[AU_CLASS_DESC_MAX]; 248 static struct au_class_ent c; 249 250 bzero(&c, sizeof(c)); 251 bzero(class_ent_name, sizeof(class_ent_name)); 252 bzero(class_ent_desc, sizeof(class_ent_desc)); 253 c.ac_name = class_ent_name; 254 c.ac_desc = class_ent_desc; 255 256 return (getauclassnum_r(&c, class_number)); 257} 258 259/* 260 * audit_class processing is complete; close any open files. 261 */ 262void 263endauclass(void) 264{ 265
| 266 return (NULL); 267} 268 269struct au_class_ent * 270getauclassnum(au_class_t class_number) 271{ 272 static char class_ent_name[AU_CLASS_NAME_MAX]; 273 static char class_ent_desc[AU_CLASS_DESC_MAX]; 274 static struct au_class_ent c; 275 276 bzero(&c, sizeof(c)); 277 bzero(class_ent_name, sizeof(class_ent_name)); 278 bzero(class_ent_desc, sizeof(class_ent_desc)); 279 c.ac_name = class_ent_name; 280 c.ac_desc = class_ent_desc; 281 282 return (getauclassnum_r(&c, class_number)); 283} 284 285/* 286 * audit_class processing is complete; close any open files. 287 */ 288void 289endauclass(void) 290{ 291
|
| 292#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
266 pthread_mutex_lock(&mutex);
| 293 pthread_mutex_lock(&mutex);
|
| 294#endif
|
267 if (fp != NULL) { 268 fclose(fp); 269 fp = NULL; 270 }
| 295 if (fp != NULL) { 296 fclose(fp); 297 fp = NULL; 298 }
|
| 299#ifdef HAVE_PTHREAD_MUTEX_LOCK
|
271 pthread_mutex_unlock(&mutex);
| 300 pthread_mutex_unlock(&mutex);
|
| 301#endif
|
272}
| 302}
|