File: | conf.c |
Location: | line 270, column 8 |
Description: | Dereference of null pointer (loaded from variable 'dst') |
1 | /*- | |||
2 | * Copyright (c) 2007 Aaron L. Meihm | |||
3 | * Copyright (c) 2007 Christian S.J. Peron | |||
4 | * All rights reserved. | |||
5 | * | |||
6 | * $Id: conf.c,v 1.15 2007/04/13 14:45:12 csjp Exp $ | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions | |||
10 | * are met: | |||
11 | * | |||
12 | * 1. Redistributions of source code must retain the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer. | |||
14 | * 2. Redistributions in binary form must reproduce the above copyright | |||
15 | * notice, this list of conditions and the following disclaimer in the | |||
16 | * documentation and/or other materials provided with the distribution. | |||
17 | * | |||
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
22 | * FOR 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, STRICT | |||
26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
28 | * SUCH DAMAGE. | |||
29 | */ | |||
30 | #include "includes.h" | |||
31 | ||||
32 | static const struct _settype_tab { | |||
33 | char *stt_str; | |||
34 | int stt_val; | |||
35 | } settype_tab[] = { | |||
36 | { "auditclass", SET_TYPE_AUCLASS }, | |||
37 | { "auditevent", SET_TYPE_AUEVENT }, | |||
38 | { "auid", SET_TYPE_AUID }, | |||
39 | { "egid", SET_TYPE_EGID }, | |||
40 | { "euid", SET_TYPE_EUID }, | |||
41 | { "path", SET_TYPE_PATH }, | |||
42 | #ifdef PCRE | |||
43 | { "pcre", SET_TYPE_PCRE }, | |||
44 | #endif | |||
45 | { "rgid", SET_TYPE_RGID }, | |||
46 | { "ruid", SET_TYPE_RUID }, | |||
47 | { "logchannel", SET_TYPE_LOGCHANNEL }, | |||
48 | { NULL((void *)0), 0 } | |||
49 | }; | |||
50 | ||||
51 | extern FILE *yyin; | |||
52 | extern char *yytext; | |||
53 | extern int yyparse(void); | |||
54 | bsm_set_head_t bsm_set_head; | |||
55 | int lineno = 1; | |||
56 | char *conffile; | |||
57 | ||||
58 | /* | |||
59 | * Return BSM set named str, or NULL if the set was not found in the BSM set | |||
60 | * queue. | |||
61 | */ | |||
62 | struct bsm_set * | |||
63 | conf_get_bsm_set(char *str) | |||
64 | { | |||
65 | struct bsm_set *ptr; | |||
66 | ||||
67 | TAILQ_FOREACH(ptr, &bsm_set_head, bss_glue)for ((ptr) = (((&bsm_set_head))->tqh_first); (ptr); (ptr ) = (((ptr))->bss_glue.tqe_next)) { | |||
68 | if (strcmp(str, ptr->bss_name) == 0) | |||
69 | return (ptr); | |||
70 | } | |||
71 | return (NULL((void *)0)); | |||
72 | } | |||
73 | ||||
74 | /* | |||
75 | * Return sequence with name str from parent queue, or NULL if sequence is not | |||
76 | * found. | |||
77 | */ | |||
78 | struct bsm_sequence * | |||
79 | conf_get_parent_sequence(char *str) | |||
80 | { | |||
81 | ||||
82 | return (NULL((void *)0)); | |||
83 | } | |||
84 | ||||
85 | /* | |||
86 | * Load configuration file from path. | |||
87 | */ | |||
88 | void | |||
89 | conf_load(char *path) | |||
90 | { | |||
91 | FILE *f; | |||
92 | ||||
93 | f = fopen(path, "r"); | |||
94 | if (f == NULL((void *)0)) | |||
95 | bsmtrace_error(1, "%s: %s", path, strerror(errno(* __error()))); | |||
96 | conffile = path; | |||
97 | yyin = f; | |||
98 | TAILQ_INIT(&bsm_set_head)do { (((&bsm_set_head))->tqh_first) = ((void *)0); (& bsm_set_head)->tqh_last = &(((&bsm_set_head))-> tqh_first);; } while (0); | |||
99 | yyparse(); | |||
100 | (void) fclose(f); | |||
101 | } | |||
102 | ||||
103 | /* | |||
104 | * Configuration file error reporting, non-zero ln overrides lineno. | |||
105 | */ | |||
106 | void | |||
107 | conf_detail(int ln, const char *fmt, ...) | |||
108 | { | |||
109 | char buf[1024]; | |||
110 | va_list ap; | |||
111 | ||||
112 | if (ln == 0) | |||
113 | ln = lineno; | |||
114 | va_start(ap, fmt)__builtin_va_start(ap, fmt); | |||
115 | (void) vsnprintf(buf, sizeof(buf), fmt, ap); | |||
116 | va_end(ap)__builtin_va_end(ap); | |||
117 | bsmtrace_error(1, "%s:%d: %s", conffile, ln, buf); | |||
118 | } | |||
119 | ||||
120 | /* | |||
121 | * Add value str to array a. We verify the value str points at is suitable for | |||
122 | * an insertion into an array of type. | |||
123 | */ | |||
124 | void | |||
125 | conf_array_add(const char *str, struct array *a, int type) | |||
126 | { | |||
127 | int e, value; | |||
128 | char *ptr, *r, *estring; | |||
129 | struct au_event_ent *aue; | |||
130 | struct au_class_ent *auc; | |||
131 | struct passwd *pwd; | |||
132 | struct group *gr; | |||
133 | #ifdef PCRE | |||
134 | const char *error; | |||
135 | int erroffset; | |||
136 | pcre *re; | |||
137 | #endif | |||
138 | ||||
139 | e = 0; | |||
140 | switch (type) { | |||
141 | case SET_TYPE_AUCLASS: | |||
142 | auc = getauclassnam(str); | |||
143 | if (auc == NULL((void *)0)) { | |||
144 | estring = "audit class"; | |||
145 | e++; | |||
146 | break; | |||
147 | } | |||
148 | value = auc->ac_class; | |||
149 | break; | |||
150 | case SET_TYPE_AUEVENT: | |||
151 | aue = getauevnam(str); | |||
152 | if (aue == NULL((void *)0)) { | |||
153 | estring = "audit event"; | |||
154 | e++; | |||
155 | break; | |||
156 | } | |||
157 | value = aue->ae_number; | |||
158 | break; | |||
159 | case SET_TYPE_AUID: | |||
160 | case SET_TYPE_EUID: | |||
161 | case SET_TYPE_RUID: | |||
162 | pwd = getpwnam(str); | |||
163 | endpwent(); | |||
164 | if (pwd == NULL((void *)0)) { | |||
165 | estring = "user"; | |||
166 | e++; | |||
167 | break; | |||
168 | } | |||
169 | value = pwd->pw_uid; | |||
170 | break; | |||
171 | case SET_TYPE_EGID: | |||
172 | case SET_TYPE_RGID: | |||
173 | gr = getgrnam(str); | |||
174 | endgrent(); | |||
175 | if (gr == NULL((void *)0)) { | |||
176 | estring = "group"; | |||
177 | e++; | |||
178 | break; | |||
179 | } | |||
180 | value = gr->gr_gid; | |||
181 | break; | |||
182 | #ifdef PCRE | |||
183 | case SET_TYPE_PCRE: | |||
184 | re = pcre_compile(str, 0, &error, &erroffset, NULL((void *)0)); | |||
185 | if (error != 0) | |||
186 | bsmtrace_error(1, "%s: pcre_compile failed", __func__); | |||
187 | break; | |||
188 | #endif | |||
189 | case SET_TYPE_PATH: | |||
190 | case SET_TYPE_LOGCHANNEL: | |||
191 | ptr = strdup(str); | |||
192 | if (ptr == NULL((void *)0)) | |||
193 | bsmtrace_error(1, "%s: strdup failed", __func__); | |||
194 | break; | |||
195 | } | |||
196 | if (e != 0) { | |||
197 | value = strtoul(str, &r, 10); | |||
198 | /* XXX look for overflows */ | |||
199 | if (*r != '\0') | |||
200 | conf_detail(0, "%s: invalid %s name\n", str, estring); | |||
201 | } | |||
202 | if (type == SET_TYPE_PATH || type == SET_TYPE_LOGCHANNEL) { | |||
203 | a->a_data.string[a->a_cnt++] = ptr; | |||
204 | a->a_type = STRING_ARRAY2; | |||
205 | #ifdef PCRE | |||
206 | } else if (type == SET_TYPE_PCRE) { | |||
207 | a->a_data.pcre[a->a_cnt++] = re; | |||
208 | a->a_type = PCRE_ARRAY; | |||
209 | #endif | |||
210 | } else { | |||
211 | a->a_data.value[a->a_cnt++] = value; | |||
212 | a->a_type = INTEGER_ARRAY1; | |||
213 | } | |||
214 | } | |||
215 | ||||
216 | /* | |||
217 | * Set subject for parent sequence seq to subj. | |||
218 | */ | |||
219 | void | |||
220 | conf_sequence_set_subj(struct bsm_sequence *seq, struct bsm_set *subj, | |||
221 | int negate) | |||
222 | { | |||
223 | struct array *src, *dst; | |||
224 | ||||
225 | /* | |||
226 | * Make sure the passed subj actually contains subject information. | |||
227 | */ | |||
228 | if (subj->bss_type != SET_TYPE_AUID && | |||
229 | subj->bss_type != SET_TYPE_RUID && | |||
230 | subj->bss_type != SET_TYPE_EUID && | |||
231 | subj->bss_type != SET_TYPE_RGID && | |||
232 | subj->bss_type != SET_TYPE_EGID) | |||
233 | conf_detail(0, "supplied set does not contain subjects\n"); | |||
234 | src = &subj->bss_data; | |||
235 | dst = &seq->bs_subj.bs_par_subj; | |||
236 | *dst = *src; | |||
237 | seq->bs_subj.bs_par_subj.a_negated = negate; | |||
238 | seq->bs_subj_type = subj->bss_type; | |||
239 | } | |||
240 | ||||
241 | /* | |||
242 | * Return set type token from string str. | |||
243 | */ | |||
244 | int | |||
245 | conf_set_type(char *str) | |||
246 | { | |||
247 | const struct _settype_tab *setptr; | |||
248 | ||||
249 | for (setptr = settype_tab; setptr->stt_str != NULL((void *)0); setptr++) { | |||
250 | if (strcmp(setptr->stt_str, str) == 0) | |||
251 | return (setptr->stt_val); | |||
252 | } | |||
253 | return (-1); | |||
254 | } | |||
255 | ||||
256 | void | |||
257 | conf_handle_multiplier(struct bsm_sequence *bs, struct bsm_state *bm) | |||
258 | { | |||
259 | struct bsm_state *vec, *dst; | |||
260 | int i; | |||
261 | ||||
262 | assert(bm != NULL)((bm != ((void *)0)) ? (void)0 : __assert(__func__, "conf.c", 262, "bm != NULL")); | |||
263 | if (bm->bm_multiplier == 0) | |||
| ||||
264 | bm->bm_multiplier = 1; | |||
265 | vec = calloc(bm->bm_multiplier, sizeof(*bm)); | |||
266 | if (vec == NULL((void *)0)) | |||
267 | bsmtrace_error(1, "%s: calloc failed", __func__); | |||
268 | for (i = 0; i < bm->bm_multiplier; i++) { | |||
269 | dst = &vec[i]; | |||
270 | *dst = *bm; | |||
| ||||
271 | TAILQ_INSERT_TAIL(&bs->bs_mhead, dst, bm_glue)do {; (((dst))->bm_glue.tqe_next) = ((void *)0); (dst)-> bm_glue.tqe_prev = (&bs->bs_mhead)->tqh_last; *(& bs->bs_mhead)->tqh_last = (dst); (&bs->bs_mhead) ->tqh_last = &(((dst))->bm_glue.tqe_next);;; } while (0); | |||
272 | } | |||
273 | } | |||
274 | ||||
275 | void | |||
276 | yyerror(const char *str) | |||
277 | { | |||
278 | ||||
279 | conf_detail(0, "syntax error near '%s'", yytext); | |||
280 | } | |||
281 | ||||
282 | int | |||
283 | yywrap() | |||
284 | { | |||
285 | ||||
286 | return (1); | |||
287 | } | |||
288 | ||||
289 | void | |||
290 | conf_set_log_channel(struct bsm_set *bss, struct bsm_sequence *bs) | |||
291 | { | |||
292 | struct array *a; | |||
293 | int i; | |||
294 | struct logchannel *lc; | |||
295 | ||||
296 | a = &bss->bss_data; | |||
297 | for (i = 0; i < a->a_cnt; i++) { | |||
298 | lc = log_lookup_channel(a->a_data.string[i]); | |||
299 | if (lc == NULL((void *)0)) | |||
300 | conf_detail(0, "unable to lookup channel"); | |||
301 | TAILQ_INSERT_HEAD(&bs->bs_log_channel, lc, log_glue)do {; if (((((lc))->log_glue.tqe_next) = (((&bs->bs_log_channel ))->tqh_first)) != ((void *)0)) (((&bs->bs_log_channel ))->tqh_first)->log_glue.tqe_prev = &(((lc))->log_glue .tqe_next); else (&bs->bs_log_channel)->tqh_last = & (((lc))->log_glue.tqe_next); (((&bs->bs_log_channel ))->tqh_first) = (lc); (lc)->log_glue.tqe_prev = &( ((&bs->bs_log_channel))->tqh_first);;; } while (0); | |||
302 | } | |||
303 | } | |||
304 | ||||
305 | int | |||
306 | conf_return_scope(char *scopestr) | |||
307 | { | |||
308 | ||||
309 | if (strcmp(scopestr, "global") == 0) | |||
310 | return (BSM_SCOPE_GLOBAL); | |||
311 | else if (strcmp(scopestr, "process") == 0) | |||
312 | return (BSM_SCOPE_PROCESS); | |||
313 | else if (strcmp(scopestr, "session") == 0) | |||
314 | return (BSM_SCOPE_SESSION); | |||
315 | else if (strcmp(scopestr, "thread") == 0) | |||
316 | return (BSM_SCOPE_THREAD); | |||
317 | return (-1); | |||
318 | } |