Index: auparse/auparse-defs.h =================================================================== --- auparse/auparse-defs.h (revision 108) +++ auparse/auparse-defs.h (working copy) @@ -77,7 +77,7 @@ AUPARSE_TYPE_SOCKADDR, AUPARSE_TYPE_FLAGS, AUPARSE_TYPE_PROMISC, AUPARSE_TYPE_CAPABILITY, AUPARSE_TYPE_SUCCESS, AUPARSE_TYPE_A0, AUPARSE_TYPE_A1, AUPARSE_TYPE_A2, AUPARSE_TYPE_SIGNAL, - AUPARSE_TYPE_LIST } auparse_type_t; + AUPARSE_TYPE_LIST, AUPARSE_TYPE_TTY_DATA } auparse_type_t; #ifdef __cplusplus } Index: auparse/interpret.c =================================================================== --- auparse/interpret.c (revision 108) +++ auparse/interpret.c (working copy) @@ -79,7 +79,7 @@ * This function will take a pointer to a 2 byte Ascii character buffer and * return the actual hex value. */ -static unsigned char x2c(unsigned char *buf) +static unsigned char x2c(const unsigned char *buf) { static const char AsciiArray[17] = "0123456789ABCDEF"; char *ptr; @@ -95,8 +95,18 @@ return total; } +static int is_hex_string(const char *str) +{ + while (*str) { + if (!isxdigit(*str)) + return 0; + str++; + } + return 1; +} + /* returns a freshly malloc'ed and converted buffer */ -const char *au_unescape(char *buf) +char *au_unescape(char *buf) { int len, i; char saved, *str, *ptr = buf; @@ -852,6 +862,134 @@ return out; } +struct string_buf { + char *buf; /* NULL if was ever out of memory */ + size_t allocated; + size_t pos; +}; + +/* Append c to buf. */ +static void append_char(struct string_buf *buf, char c) +{ + if (buf->buf == NULL) + return; + if (buf->pos == buf->allocated) { + char *p; + + buf->allocated *= 2; + p = realloc(buf->buf, buf->allocated); + if (p == NULL) { + free(buf->buf); + buf->buf = NULL; + return; + } + buf->buf = p; + } + buf->buf[buf->pos] = c; + buf->pos++; +} + +/* Represent c as a character within a quoted string, and append it to buf. */ +static void tty_append_printable_char(struct string_buf *buf, unsigned char c) +{ + if (c < 0x20 || c > 0x7E) { + append_char(buf, '\\'); + append_char(buf, '0' + ((c >> 6) & 07)); + append_char(buf, '0' + ((c >> 3) & 07)); + append_char(buf, '0' + (c & 07)); + } else { + if (c == '\\' || c == '"') + append_char(buf, '\\'); + append_char(buf, c); + } +} + +/* Search for a name of a sequence of TTY bytes. + If found, return the name and advance *INPUT. Return NULL otherwise. */ +static const char *tty_find_named_key(unsigned char **input, size_t input_len) +{ + /* NUL-terminated list of (sequence, NUL, name, NUL) entries. + First match wins, even if a longer match were possible later */ + static const unsigned char named_keys[] = +#define E(SEQ, NAME) SEQ "\0" NAME "\0" +#include "tty_named_keys.h" +#undef E + "\0"; + + unsigned char *src; + const unsigned char *nk; + + src = *input; + if (*src >= ' ' && *src != 0x7F) + return NULL; /* Fast path */ + nk = named_keys; + do { + const unsigned char *p; + size_t nk_len; + + p = strchr(nk, '\0'); + nk_len = p - nk; + if (nk_len <= input_len && memcmp(src, nk, nk_len) == 0) { + *input += nk_len; + return p + 1; + } + nk = strchr(p + 1, '\0') + 1; + } while (*nk != '\0'); + return NULL; +} + +static const char *print_tty_data(const char *raw_data) +{ + struct string_buf buf; + int in_printable; + unsigned char *data, *data_pos, *data_end; + + if (!is_hex_string(raw_data)) + return strdup(raw_data); + data = au_unescape((char *)raw_data); + if (data == NULL) + return NULL; + data_end = data + strlen(raw_data) / 2; + + buf.allocated = 10; + buf.buf = malloc(buf.allocated); /* NULL handled in append_char() */ + buf.pos = 0; + in_printable = 0; + data_pos = data; + while (data_pos < data_end) { + /* FIXME: Unicode */ + const char *desc; + + desc = tty_find_named_key(&data_pos, data_end - data_pos); + if (desc != NULL) { + if (in_printable != 0) { + append_char(&buf, '"'); + in_printable = 0; + } + if (buf.pos != 0) + append_char(&buf, ','); + while (*desc != '\0') { + append_char(&buf, *desc); + desc++; + } + } else { + if (in_printable == 0) { + if (buf.pos != 0) + append_char(&buf, ','); + append_char(&buf, '"'); + in_printable = 1; + } + tty_append_printable_char(&buf, *data_pos); + data_pos++; + } + } + if (in_printable != 0) + append_char(&buf, '"'); + append_char(&buf, '\0'); + free(data); + return buf.buf; +} + int lookup_type(const char *name) { int i; @@ -861,16 +999,6 @@ return AUPARSE_TYPE_UNCLASSIFIED; } -static int is_hex_string(const char *str) -{ - while (*str) { - if (!isxdigit(*str)) - return 0; - str++; - } - return 1; -} - const char *interpret(const rnode *r) { const nvlist *nv = &r->nv; @@ -885,6 +1013,8 @@ type = AUPARSE_TYPE_ESCAPED; else if (r->type == AUDIT_AVC && strcmp(name, "saddr") == 0) type = -1; + else if (r->type == AUDIT_USER_TTY && strcmp(name, "msg") == 0) + type = AUPARSE_TYPE_ESCAPED; else if (strcmp(name, "acct") == 0) { if (val[0] == '"') type = AUPARSE_TYPE_ESCAPED; @@ -949,7 +1079,10 @@ break; case AUPARSE_TYPE_LIST: out = print_list(val); - break; + break; + case AUPARSE_TYPE_TTY_DATA: + out = print_tty_data(val); + break; case AUPARSE_TYPE_UNCLASSIFIED: default: { char *out2; Index: auparse/typetab.h =================================================================== --- auparse/typetab.h (revision 108) +++ auparse/typetab.h (working copy) @@ -69,3 +69,4 @@ _S(AUPARSE_TYPE_A1, "a1" ) _S(AUPARSE_TYPE_A2, "a2" ) _S(AUPARSE_TYPE_SIGNAL, "sig" ) +_S(AUPARSE_TYPE_TTY_DATA, "data" ) Index: auparse/interpret.h =================================================================== --- auparse/interpret.h (revision 108) +++ auparse/interpret.h (working copy) @@ -37,7 +37,7 @@ const char *interpret(const rnode *r); void aulookup_destroy_uid_list(void); void aulookup_destroy_gid_list(void); -const char *au_unescape(char *buf); +char *au_unescape(char *buf); /* Make these hidden to prevent conflicts */ hidden_proto(lookup_type); Index: auparse/tty_named_keys.h =================================================================== --- auparse/tty_named_keys.h (revision 0) +++ auparse/tty_named_keys.h (revision 0) @@ -0,0 +1,71 @@ +/* tty_named_keys.h -- + * Copyright 2008 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Miloslav Trmač + */ + +E("\x01", "^A") +E("\x02", "^B") +E("\x03", "^C") +E("\x04", "^D") +E("\x05", "^E") +E("\x06", "^F") +E("\x07", "^G") +E("\x08", "^H") +E("\t", "tab") +E("\n", "nl") +E("\x0B", "^K") +E("\x0C", "^L") +E("\r", "ret") +E("\x0E", "^N") +E("\x0F", "^O") +E("\x10", "^P") +E("\x11", "^Q") +E("\x12", "^R") +E("\x13", "^S") +E("\x14", "^T") +E("\x15", "^U") +E("\x16", "^V") +E("\x17", "^W") +E("\x18", "^X") +E("\x19", "^Y") +E("\x1A", "^Z") +/* \x1B handled only after all other escape sequences */ +E("\x7F", "backspace") + +E("\x1B[A", "up") +E("\x1B[B", "down") +E("\x1B[C", "right") +E("\x1B[D", "left") + +E("\x1B""OP", "F1") +E("\x1B""OQ", "F2") +E("\x1B""OR", "F3") +E("\x1B""OS", "F4") +E("\x1B[15~", "F5") +E("\x1B[17~", "F6") +E("\x1B[18~", "F7") +E("\x1B[19~", "F8") +E("\x1B[20~", "F9") +E("\x1B[21~", "F10") +E("\x1B[23~", "F11") +E("\x1B[24~", "F12") + +E("\x1B", "esc") +E("\x7F", "backspace") Index: auparse/Makefile.am =================================================================== --- auparse/Makefile.am (revision 108) +++ auparse/Makefile.am (working copy) @@ -32,7 +32,7 @@ auparse.c auditd-config.c message.c data_buf.c auparse-defs.h \ data_buf.h nvlist.h auparse.h ellist.h \ internal.h nvpair.h rnode.h interpret.h \ - private.h expression.c expression.h + private.h expression.c expression.h tty_named_keys.h nodist_libauparse_la_SOURCES = $(BUILT_SOURCES) libauparse_la_LIBADD = ${top_builddir}/lib/libaudit.la