1/* 2 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include <config.h> 18 19#include <sys/types.h> 20#include <stdio.h> 21#ifdef STDC_HEADERS 22# include <stdlib.h> 23# include <stddef.h> 24#else 25# ifdef HAVE_STDLIB_H 26# include <stdlib.h> 27# endif 28#endif /* STDC_HEADERS */ 29#include <errno.h> 30#include <fcntl.h> 31#include <string.h> 32#include <libaudit.h> 33 34#include "missing.h" 35#include "error.h" 36#include "alloc.h" 37#include "linux_audit.h" 38 39/* 40 * Open audit connection if possible. 41 * Returns audit fd on success and -1 on failure. 42 */ 43static int 44linux_audit_open(void) 45{ 46 static int au_fd = -1; 47 48 if (au_fd != -1) 49 return au_fd; 50 au_fd = audit_open(); 51 if (au_fd == -1) { 52 /* Kernel may not have audit support. */ 53 if (errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) 54 error(1, "unable to open audit system"); 55 } else { 56 (void)fcntl(au_fd, F_SETFD, FD_CLOEXEC); 57 } 58 return au_fd; 59} 60 61int 62linux_audit_command(char *argv[], int result) 63{ 64 int au_fd, rc; 65 char *command, *cp, **av; 66 size_t size, n; 67 68 if ((au_fd = linux_audit_open()) == -1) 69 return -1; 70 71 /* Convert argv to a flat string. */ 72 for (size = 0, av = argv; *av != NULL; av++) 73 size += strlen(*av) + 1; 74 command = cp = emalloc(size); 75 for (av = argv; *av != NULL; av++) { 76 n = strlcpy(cp, *av, size - (cp - command)); 77 if (n >= size - (cp - command)) 78 errorx(1, "internal error, linux_audit_command() overflow"); 79 cp += n; 80 *cp++ = ' '; 81 } 82 *--cp = '\0'; 83 84 /* Log command, ignoring ECONNREFUSED on error. */ 85 rc = audit_log_user_command(au_fd, AUDIT_USER_CMD, command, NULL, result); 86 if (rc <= 0 && errno != ECONNREFUSED) 87 warning("unable to send audit message"); 88 89 efree(command); 90 91 return rc; 92} 93 94#ifdef HAVE_SELINUX 95int 96linux_audit_role_change(const char *old_context, 97 const char *new_context, const char *ttyn) 98{ 99 int au_fd, rc; 100 char *message; 101 102 if ((au_fd = linux_audit_open()) == -1) 103 return -1; 104 105 /* audit role change using the same format as newrole(1) */ 106 easprintf(&message, "newrole: old-context=%s new-context=%s", 107 old_context, new_context); 108 rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, 109 message, NULL, NULL, ttyn, 1); 110 if (rc <= 0) 111 warning("unable to send audit message"); 112 113 efree(message); 114 115 return rc; 116} 117#endif /* HAVE_SELINUX */ 118