2 * ausearch-lookup.c - Lookup values to something more readable
3 * Copyright (c) 2005-06,2011-12 Red Hat Inc., Durham, North Carolina.
6 * This software may be freely redistributed and/or modified under the
7 * terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2, or (at your option) any
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Steve Grubb <sgrubb@redhat.com>
29 #include <linux/net.h>
30 #include "ausearch-lookup.h"
31 #include "ausearch-options.h"
32 #include "ausearch-nvpair.h"
34 /* This is the name/value pair used by search tables */
41 /* The machine based on elf type */
42 static int machine = 0;
43 static const char *Q = "?";
44 static const char *results[3]= { "unset", "denied", "granted" };
45 static const char *success[3]= { "unset", "no", "yes" };
46 static const char *aulookup_socketcall(long sc);
47 static const char *aulookup_ipccall(long ic);
49 const char *aulookup_result(avc_t result)
51 return results[result];
54 const char *aulookup_success(int s)
70 const char *aulookup_syscall(llist *l, char *buf, size_t size)
74 if (report_format <= RPT_DEFAULT) {
75 snprintf(buf, size, "%d", l->s.syscall);
78 machine = audit_elf_to_machine(l->s.arch);
81 sys = audit_syscall_to_name(l->s.syscall, machine);
83 const char *func = NULL;
84 if (strcmp(sys, "socketcall") == 0) {
85 if (list_find_item(l, AUDIT_SYSCALL))
86 func = aulookup_socketcall((long)l->cur->a0);
87 } else if (strcmp(sys, "ipc") == 0) {
88 if(list_find_item(l, AUDIT_SYSCALL))
89 func = aulookup_ipccall((long)l->cur->a0);
92 snprintf(buf, size, "%s(%s)", sys, func);
97 snprintf(buf, size, "%d", l->s.syscall);
101 // See include/linux/net.h
102 static struct nv_pair socktab[] = {
103 {SYS_SOCKET, "socket"},
105 {SYS_CONNECT, "connect"},
106 {SYS_LISTEN, "listen"},
107 {SYS_ACCEPT, "accept"},
108 {SYS_GETSOCKNAME, "getsockname"},
109 {SYS_GETPEERNAME, "getpeername"},
110 {SYS_SOCKETPAIR, "socketpair"},
113 {SYS_SENDTO, "sendto"},
114 {SYS_RECVFROM, "recvfrom"},
115 {SYS_SHUTDOWN, "shutdown"},
116 {SYS_SETSOCKOPT, "setsockopt"},
117 {SYS_GETSOCKOPT, "getsockopt"},
118 {SYS_SENDMSG, "sendmsg"},
119 {SYS_RECVMSG, "recvmsg"},
120 {SYS_ACCEPT4, "accept4"},
124 #define SOCK_NAMES (sizeof(socktab)/sizeof(socktab[0]))
126 static const char *aulookup_socketcall(long sc)
130 for (i = 0; i < SOCK_NAMES; i++)
131 if (socktab[i].value == sc)
132 return socktab[i].name;
137 /* This is from asm/ipc.h. Copying it for now as some platforms
138 * have broken headers. */
153 * This table maps ipc calls to their text name
155 static struct nv_pair ipctab[] = {
159 {SEMTIMEDOP, "semtimedop"},
169 #define IPC_NAMES (sizeof(ipctab)/sizeof(ipctab[0]))
171 static const char *aulookup_ipccall(long ic)
175 for (i = 0; i < IPC_NAMES; i++)
176 if (ipctab[i].value == ic)
177 return ipctab[i].name;
182 static nvlist uid_nvl;
183 static int uid_list_created=0;
184 const char *aulookup_uid(uid_t uid, char *buf, size_t size)
189 if (report_format <= RPT_DEFAULT) {
190 snprintf(buf, size, "%d", uid);
194 snprintf(buf, size, "unset");
198 // Check the cache first
199 if (uid_list_created == 0) {
200 nvlist_create(&uid_nvl);
201 nvlist_clear(&uid_nvl);
202 uid_list_created = 1;
204 rc = nvlist_find_val(&uid_nvl, uid);
206 name = uid_nvl.cur->name;
213 nv.name = strdup(pw->pw_name);
215 nvlist_append(&uid_nvl, &nv);
216 name = uid_nvl.cur->name;
220 snprintf(buf, size, "%s", name);
222 snprintf(buf, size, "unknown(%d)", uid);
226 void aulookup_destroy_uid_list(void)
228 if (uid_list_created == 0)
231 nvlist_clear(&uid_nvl);
232 uid_list_created = 0;
235 static nvlist gid_nvl;
236 static int gid_list_created=0;
237 const char *aulookup_gid(gid_t gid, char *buf, size_t size)
242 if (report_format <= RPT_DEFAULT) {
243 snprintf(buf, size, "%d", gid);
247 snprintf(buf, size, "unset");
251 // Check the cache first
252 if (gid_list_created == 0) {
253 nvlist_create(&gid_nvl);
254 nvlist_clear(&gid_nvl);
255 gid_list_created = 1;
257 rc = nvlist_find_val(&gid_nvl, gid);
259 name = gid_nvl.cur->name;
266 nv.name = strdup(gr->gr_name);
268 nvlist_append(&gid_nvl, &nv);
269 name = gid_nvl.cur->name;
273 snprintf(buf, size, "%s", name);
275 snprintf(buf, size, "unknown(%d)", gid);
279 void aulookup_destroy_gid_list(void)
281 if (gid_list_created == 0)
284 nvlist_clear(&gid_nvl);
285 gid_list_created = 0;
288 int is_hex_string(const char *str)
300 * This function will take a pointer to a 2 byte Ascii character buffer and
301 * return the actual hex value.
303 static unsigned char x2c(unsigned char *buf)
305 static const char AsciiArray[17] = "0123456789ABCDEF";
307 unsigned char total=0;
309 ptr = strchr(AsciiArray, (char)toupper(buf[0]));
311 total = (unsigned char)(((ptr-AsciiArray) & 0x0F)<<4);
312 ptr = strchr(AsciiArray, (char)toupper(buf[1]));
314 total += (unsigned char)((ptr-AsciiArray) & 0x0F);
319 /* returns a freshly malloc'ed and converted buffer */
320 char *unescape(const char *buf)
324 const char *ptr = buf;
326 /* Find the end of the name */
328 ptr = strchr(ptr, ')');
334 while (isxdigit(*ptr))
337 str = strndup(buf, ptr - buf);
342 /* We can get away with this since the buffer is 2 times
343 * bigger than what we are putting there.
351 for (i=0; i<len; i+=2) {
352 *strptr = x2c((unsigned char *)&str[i]);
359 /* Represent c as a character within a quoted string, and append it to buf. */
360 static void tty_printable_char(unsigned char c)
362 if (c < 0x20 || c > 0x7E) {
364 putchar('0' + ((c >> 6) & 07));
365 putchar('0' + ((c >> 3) & 07));
366 putchar('0' + (c & 07));
368 if (c == '\\' || c == '"')
374 /* Search for a name of a sequence of TTY bytes.
375 * If found, return the name and advance *INPUT.
376 * Return NULL otherwise.
378 static const char *tty_find_named_key(unsigned char **input, size_t input_len)
380 /* NUL-terminated list of (sequence, NUL, name, NUL) entries.
381 First match wins, even if a longer match were possible later */
382 static const unsigned char named_keys[] =
383 #define E(SEQ, NAME) SEQ "\0" NAME "\0"
384 #include "auparse/tty_named_keys.h"
389 const unsigned char *nk;
392 if (*src >= ' ' && (*src < 0x7F || *src >= 0xA0))
393 return NULL; /* Fast path */
396 const unsigned char *p;
399 p = strchr((const char *)nk, '\0');
401 if (nk_len <= input_len && memcmp(src, nk, nk_len) == 0) {
403 return (const char *)(p + 1);
405 nk = strchr((const char *)p + 1, '\0') + 1;
406 } while (*nk != '\0');
410 void print_tty_data(const char *val)
412 int need_comma, in_printable = 0;
413 unsigned char *data, *data_pos, *data_end;
415 if (!is_hex_string(val)) {
420 if ((data = unescape((char *)val)) == NULL) {
421 printf("conversion error(%s)", val);
425 data_end = data + strlen(val) / 2;
428 while (data_pos < data_end) {
432 desc = tty_find_named_key(&data_pos, data_end - data_pos);
434 if (in_printable != 0) {
440 printf("<%s>", desc);
442 if (in_printable == 0) {
448 tty_printable_char(*data_pos);
453 if (in_printable != 0)