2 * ellist.c - Minimal linked list library
3 * Copyright (c) 2006-08,2014 Red Hat Inc., Durham, North Carolina.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Steve Grubb <sgrubb@redhat.com>
30 #include "interpret.h"
32 static const char key_sep[2] = { AUDIT_KEY_SEPARATOR, 0 };
34 void aup_list_create(event_list_t *l)
45 static void aup_list_last(event_list_t *l)
47 register rnode* window;
54 window = window->next;
58 rnode *aup_list_next(event_list_t *l)
61 l->cur = l->cur->next;
66 * * This function does encoding of "untrusted" names just like the kernel
68 static char *_audit_c2x(char *final, const char *buf, unsigned int size)
72 const char *hex = "0123456789ABCDEF";
74 for (i=0; i<size; i++) {
75 *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */
76 *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */
82 static char *escape(const char *tmp)
85 const unsigned char *p = (unsigned char *)tmp;
87 if (*p == '"' || *p < 0x21 || *p > 0x7e) {
88 int len = strlen(tmp);
89 name = malloc((2*len)+1);
90 return _audit_c2x(name, tmp, len);
94 if (asprintf(&name, "\"%s\"", tmp) < 0)
99 /* This funtion does the heavy duty work of splitting a record into
100 * its little tiny pieces */
101 static int parse_up_record(rnode* r)
103 char *ptr, *buf, *saved=NULL;
106 buf = strdup(r->record);
107 ptr = audit_strsplit_r(buf, &saved);
113 do { // If there's an '=' sign, its a keeper
115 char *val = strchr(ptr, '=');
119 // If name is 'msg=audit' throw it away
120 if (*ptr == 'm' && strncmp(ptr, "msg=", 4) == 0) {
124 // If name is 'msg='' chop off and see
125 // if there is still a = in the string.
126 else if (ptr[4] == '\'') {
128 val = strchr(ptr, '=');
138 // Remove beginning cruft of name
141 n.name = strdup(ptr);
143 // Remove trailing punctuation
145 if (len && n.val[len-1] == ':') {
149 if (len && n.val[len-1] == ',') {
153 if (len && n.val[len-1] == '\'') {
157 if (len && n.val[len-1] == ')') {
158 if (strcmp(n.val, "(none)") &&
159 strcmp(n.val, "(null)")) {
164 // Make virtual keys or just store it
165 if (strcmp(n.name, "key") == 0 && *n.val != '(') {
167 nvlist_append(&r->nv, &n);
169 char *key, *ptr, *saved2 = NULL;
171 key = (char *)au_unescape(n.val);
173 // Malformed key - save as is
174 nvlist_append(&r->nv, &n);
177 ptr = strtok_r(key, key_sep, &saved2);
181 n.name = strdup("key");
183 nvlist_append(&r->nv, &n);
191 nvlist_append(&r->nv, &n);
193 // Do some info gathering for use later
194 if (r->nv.cnt == 1 && strcmp(n.name, "node") == 0)
195 offset = 1; // if node, some positions changes
196 else if (r->nv.cnt == (1 + offset) &&
197 strcmp(n.name, "type") == 0) {
198 r->type = audit_name_to_msg_type(n.val);
199 } else if (r->nv.cnt == (2 + offset) &&
200 strcmp(n.name, "arch")== 0){
203 ival = strtoul(n.val, NULL, 16);
207 r->machine = audit_elf_to_machine(ival);
208 } else if (r->nv.cnt == (3 + offset) &&
209 strcmp(n.name, "syscall") == 0){
211 r->syscall = strtoul(n.val, NULL, 10);
214 } else if (r->nv.cnt == (6 + offset) &&
215 strcmp(n.name, "a0") == 0){
217 r->a0 = strtoull(n.val, NULL, 16);
220 } else if (r->nv.cnt == (7 + offset) &&
221 strcmp(n.name, "a1") == 0){
223 r->a1 = strtoull(n.val, NULL, 16);
227 } else if (r->type == AUDIT_AVC || r->type == AUDIT_USER_AVC) {
228 // We special case these 2 fields because selinux
229 // avc messages do not label these fields.
231 if (nvlist_get_cnt(&r->nv) == (1 + offset)) {
233 if (strncmp(ptr, "avc", 3) == 0)
235 n.name = strdup("seresult");
236 } else if (nvlist_get_cnt(&r->nv) == (2 + offset)) {
237 // skip over open brace
240 char tmpctx[256], *to;
243 ptr = audit_strsplit_r(NULL, &saved);
244 while (ptr && *ptr != '}') {
246 if ((len+1) >= (256-total)) {
251 to = stpcpy(to, ",");
254 to = stpcpy(to, ptr);
256 ptr = audit_strsplit_r(NULL,
259 n.name = strdup("seperms");
260 n.val = strdup(tmpctx);
261 nvlist_append(&r->nv, &n);
267 nvlist_append(&r->nv, &n);
269 // FIXME: There should be an else here to catch ancillary data
270 } while((ptr = audit_strsplit_r(NULL, &saved)));
273 r->nv.cur = r->nv.head; // reset to beginning
277 int aup_list_append(event_list_t *l, char *record, int list_idx,
278 unsigned int line_number)
285 // First step is build rnode
286 r = malloc(sizeof(rnode));
297 r->list_idx = list_idx;
298 r->line_number = line_number;
300 nvlist_create(&r->nv);
302 // if we are at top, fix this up
305 else { // Otherwise add pointer to newnode
310 // make newnode current
314 // Then parse the record up into nvlist
315 return parse_up_record(r);
318 void aup_list_clear(event_list_t* l)
321 register rnode* current;
328 nextnode=current->next;
329 nvlist_clear(¤t->nv);
330 free(current->record);
340 free((char *)l->e.host);
344 /*int aup_list_get_event(event_list_t* l, au_event_t *e)
346 if (l == NULL || e == NULL)
350 e->milli = l->e.milli;
351 e->serial = l->e.serial;
353 e->host = strdup(l->e.host);
359 int aup_list_set_event(event_list_t* l, au_event_t *e)
361 if (l == NULL || e == NULL)
365 l->e.milli = e->milli;
366 l->e.serial = e->serial;
367 l->e.host = e->host; // Take custody of the memory
372 rnode *aup_list_find_rec(event_list_t *l, int i)
374 register rnode* window;
376 window = l->head; /* start at the beginning */
378 if (window->type == i) {
382 window = window->next;
387 rnode *aup_list_goto_rec(event_list_t *l, int i)
389 register rnode* window;
391 window = l->head; /* start at the beginning */
393 if (window->item == i) {
397 window = window->next;
402 rnode *aup_list_find_rec_range(event_list_t *l, int low, int high)
404 register rnode* window;
409 window = l->head; /* Start at the beginning */
411 if (window->type >= low && window->type <= high) {
415 window = window->next;
420 int aup_list_first_field(event_list_t *l)
423 nvlist_first(&l->cur->nv);