1
/* audispd-pconfig.c --
2
* Copyright 2007 Red Hat Inc., Durham, North Carolina.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* Steve Grubb <sgrubb@redhat.com>
33
#include "audispd-pconfig.h"
36
/* Local prototypes */
47
int (*parser)(struct nv_pair *, int, plugin_conf_t *);
57
static char *get_line(FILE *f, char *buf);
58
static int nv_split(char *buf, struct nv_pair *nv);
59
static const struct kw_pair *kw_lookup(const char *val);
60
static int active_parser(struct nv_pair *nv, int line,
61
plugin_conf_t *config);
62
static int direction_parser(struct nv_pair *nv, int line,
63
plugin_conf_t *config);
64
static int path_parser(struct nv_pair *nv, int line,
65
plugin_conf_t *config);
66
static int service_type_parser(struct nv_pair *nv, int line,
67
plugin_conf_t *config);
68
static int args_parser(struct nv_pair *nv, int line,
69
plugin_conf_t *config);
70
static int format_parser(struct nv_pair *nv, int line,
71
plugin_conf_t *config);
72
static int sanity_check(plugin_conf_t *config, const char *file);
74
static const struct kw_pair keywords[] =
76
{"active", active_parser, 0 },
77
{"direction", direction_parser, 0 },
78
{"path", path_parser, 0 },
79
{"type", service_type_parser, 0 },
80
{"args", args_parser, 2 },
81
{"format", format_parser, 0 },
85
static const struct nv_list active[] =
92
static const struct nv_list directions[] =
99
static const struct nv_list service_type[] =
101
{"ondemand", S_ONDEMAND },
102
{"builtin", S_BUILTIN },
103
{"always", S_ALWAYS },
107
static const struct nv_list formats[] =
109
{"binary", F_BINARY },
110
{"string", F_STRING },
115
* Set everything to its default value
117
void clear_pconfig(plugin_conf_t *config)
121
config->active = A_NO;
122
config->direction = D_UNSET;
124
config->type = S_ONDEMAND;
125
for (i=0; i< (MAX_PLUGIN_ARGS + 2); i++)
126
config->args[i] = NULL;
127
config->format = F_STRING;
130
int load_pconfig(plugin_conf_t *config, const char *file)
132
int fd, rc, mode, lineno = 1;
137
clear_pconfig(config);
141
rc = open(file, mode);
143
if (errno != ENOENT) {
144
audit_msg(LOG_ERR, "Error opening %s (%s)", file,
148
audit_msg(LOG_WARNING,
149
"Config file %s doesn't exist, skipping", file);
154
/* check the file's permissions: owned by root, not world writable,
157
audit_msg(LOG_DEBUG, "Config file %s opened for parsing",
159
if (fstat(fd, &st) < 0) {
160
audit_msg(LOG_ERR, "Error fstat'ing config file (%s)",
165
if (st.st_uid != 0) {
166
audit_msg(LOG_ERR, "Error - %s isn't owned by root",
171
if ((st.st_mode & S_IWOTH) == S_IWOTH) {
172
audit_msg(LOG_ERR, "Error - %s is world writable",
177
if (!S_ISREG(st.st_mode)) {
178
audit_msg(LOG_ERR, "Error - %s is not a regular file",
184
/* it's ok, read line by line */
187
audit_msg(LOG_ERR, "Error - fdopen failed (%s)",
193
while (get_line(f, buf)) {
194
// convert line into name-value pair
195
const struct kw_pair *kw;
197
rc = nv_split(buf, &nv);
201
case 1: // not the right number of tokens.
203
"Wrong number of arguments for line %d in %s",
206
case 2: // no '=' sign
208
"Missing equal sign for line %d in %s",
211
default: // something else went wrong...
213
"Unknown error for line %d in %s",
217
if (nv.name == NULL) {
221
if (nv.value == NULL) {
226
/* identify keyword or error */
227
kw = kw_lookup(nv.name);
228
if (kw->name == NULL) {
230
"Unknown keyword \"%s\" in line %d of %s",
231
nv.name, lineno, file);
236
/* Check number of options */
237
if (kw->max_options == 0 && nv.option != NULL) {
239
"Keyword \"%s\" has invalid option "
240
"\"%s\" in line %d of %s",
241
nv.name, nv.option, lineno, file);
246
/* dispatch to keyword's local parser */
247
rc = kw->parser(&nv, lineno, config);
250
return 1; // local parser puts message out
258
return sanity_check(config, file);
262
static char *get_line(FILE *f, char *buf)
264
if (fgets_unlocked(buf, 128, f)) {
266
char *ptr = strchr(buf, 0x0a);
274
static int nv_split(char *buf, struct nv_pair *nv)
276
/* Get the name part */
282
ptr = strtok(buf, " ");
284
return 0; /* If there's nothing, go to next line */
286
return 0; /* If there's a comment, go to next line */
289
/* Check for a '=' */
290
ptr = strtok(NULL, " ");
293
if (strcmp(ptr, "=") != 0)
297
ptr = strtok(NULL, " ");
302
/* See if there's an option */
303
ptr = strtok(NULL, " ");
307
/* Make sure there's nothing else */
308
ptr = strtok(NULL, " ");
313
/* Everything is OK */
317
static const struct kw_pair *kw_lookup(const char *val)
320
while (keywords[i].name != NULL) {
321
if (strcasecmp(keywords[i].name, val) == 0)
328
static int active_parser(struct nv_pair *nv, int line,
329
plugin_conf_t *config)
333
for (i=0; active[i].name != NULL; i++) {
334
if (strcasecmp(nv->value, active[i].name) == 0) {
335
config->active = active[i].option;
339
audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line);
343
static int direction_parser(struct nv_pair *nv, int line,
344
plugin_conf_t *config)
348
for (i=0; directions[i].name != NULL; i++) {
349
if (strcasecmp(nv->value, directions[i].name) == 0) {
350
config->direction = directions[i].option;
354
audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line);
358
static int path_parser(struct nv_pair *nv, int line,
359
plugin_conf_t *config)
361
char *dir = NULL, *tdir, *base;
365
if (nv->value == NULL) {
370
if (strncasecmp(nv->value, "builtin_", 8) == 0) {
371
config->path = strdup(nv->value);
375
/* split name into dir and basename. */
376
tdir = strdup(nv->value);
379
if (dir == NULL || strlen(dir) < 4) { // '/var' is shortest dirname
382
"The directory name: %s is too short - line %d",
388
base = basename((char *)nv->value);
389
if (base == 0 || strlen(base) == 0) {
390
audit_msg(LOG_ERR, "The file name: %s is too short - line %d",
394
/* if the file exists, see that its regular, owned by root,
395
* and not world anything */
396
fd = open(nv->value, O_RDONLY);
398
audit_msg(LOG_ERR, "Unable to open %s (%s)", nv->value,
402
if (fstat(fd, &buf) < 0) {
403
audit_msg(LOG_ERR, "Unable to stat %s (%s)", nv->value,
409
if (!S_ISREG(buf.st_mode)) {
410
audit_msg(LOG_ERR, "%s is not a regular file", nv->value);
413
if (buf.st_uid != 0) {
414
audit_msg(LOG_ERR, "%s is not owned by root", nv->value);
417
if ((buf.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)) !=
418
(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)) {
419
audit_msg(LOG_ERR, "%s permissions should be 0750", nv->value);
422
free((void *)config->path);
423
config->path = strdup(nv->value);
424
if (config->path == NULL)
429
static int service_type_parser(struct nv_pair *nv, int line,
430
plugin_conf_t *config)
434
for (i=0; service_type[i].name != NULL; i++) {
435
if (strcasecmp(nv->value, service_type[i].name) == 0) {
436
config->type = service_type[i].option;
440
audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line);
444
static int args_parser(struct nv_pair *nv, int line,
445
plugin_conf_t *config)
449
for (i=0; i < (MAX_PLUGIN_ARGS + 2); i++) {
450
free((void *)config->args[i]);
451
config->args[i] = NULL;
454
config->args[1] = strdup(nv->value);
456
config->args[2] = strdup(nv->option);
460
static int format_parser(struct nv_pair *nv, int line,
461
plugin_conf_t *config)
465
for (i=0; formats[i].name != NULL; i++) {
466
if (strcasecmp(nv->value, formats[i].name) == 0) {
467
config->format = formats[i].option;
471
audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line);
476
* This function is where we do the integrated check of the audispd config
477
* options. At this point, all fields have been read. Returns 0 if no
478
* problems and 1 if problems detected.
480
static int sanity_check(plugin_conf_t *config, const char *file)
483
if (config->active == A_YES && config->path == NULL) {
485
"Error - plugin (%s) is active but no path given", file);
491
void free_pconfig(plugin_conf_t *config)
495
for (i=0; i < (MAX_PLUGIN_ARGS + 2); i++)
496
free(config->args[i]);
497
free((void *)config->path);