static void log_to_audit_system(const char *login, const char *hostname, const char *tty, gboolean success) { struct passwd *pw; char buf[64]; int audit_fd; audit_fd = audit_open (); if (login) pw = getpwnam (login); else { login = "******"; pw = NULL; } if (pw) { snprintf (buf, sizeof (buf), "uid=%d", pw->pw_uid); audit_log_user_message (audit_fd, AUDIT_USER_LOGIN, buf, hostname, NULL, tty, (int)success); } else { snprintf (buf, sizeof (buf), "acct=%s", login); audit_log_user_message (audit_fd, AUDIT_USER_LOGIN, buf, hostname, NULL, tty, (int)success); } close (audit_fd); }
static int on_reboot(Context *c) { int r = 0, q; usec_t t; assert(c); /* We finished start-up, so let's write the utmp * record and send the audit msg */ #ifdef HAVE_AUDIT if (c->audit_fd >= 0) if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "init", NULL, NULL, NULL, 1) < 0 && errno != EPERM) { log_error("Failed to send audit message: %m"); r = -errno; } #endif /* If this call fails it will return 0, which * utmp_put_reboot() will then fix to the current time */ t = get_startup_time(c); q = utmp_put_reboot(t); if (q < 0) { log_error("Failed to write utmp record: %s", strerror(-q)); r = q; } return r; }
static int on_shutdown(Context *c) { int r = 0, q; assert(c); /* We started shut-down, so let's write the utmp * record and send the audit msg */ #ifdef HAVE_AUDIT if (c->audit_fd >= 0) if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "init", NULL, NULL, NULL, 1) < 0 && errno != EPERM) { log_error("Failed to send audit message: %m"); r = -errno; } #endif q = utmp_put_shutdown(); if (q < 0) { log_error("Failed to write utmp record: %s", strerror(-q)); r = q; } return r; }
static void nm_audit_log (NMAuditManager *self, GPtrArray *fields, const char *file, guint line, const char *func, gboolean success) { #if HAVE_LIBAUDIT NMAuditManagerPrivate *priv; #endif char *msg; g_return_if_fail (NM_IS_AUDIT_MANAGER (self)); #if HAVE_LIBAUDIT priv = NM_AUDIT_MANAGER_GET_PRIVATE (self); if (priv->auditd_fd >= 0) { msg = build_message (fields, BACKEND_AUDITD); audit_log_user_message (priv->auditd_fd, AUDIT_USYS_CONFIG, msg, NULL, NULL, NULL, success); g_free (msg); } #endif if (nm_logging_enabled (AUDIT_LOG_LEVEL, LOGD_AUDIT)) { msg = build_message (fields, BACKEND_LOG); _NMLOG (AUDIT_LOG_LEVEL, LOGD_AUDIT, "%s", msg); g_free (msg); } }
static int audit_role_change(const security_context_t old_context, const security_context_t new_context, const char *ttyn, int result) { int au_fd, rc = -1; char *message; debug_decl(audit_role_change, SUDO_DEBUG_SELINUX) au_fd = audit_open(); if (au_fd == -1) { /* Kernel may not have audit support. */ if (errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT ) sudo_fatal(U_("unable to open audit system")); } else { /* audit role change using the same format as newrole(1) */ rc = asprintf(&message, "newrole: old-context=%s new-context=%s", old_context, new_context); if (rc == -1) sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, message, NULL, NULL, ttyn, result); if (rc <= 0) sudo_warn(U_("unable to send audit message")); free(message); close(au_fd); } debug_return_int(rc); }
static void maybe_audit_mass_relabel(int mass_relabel __attribute__((unused)), int mass_relabel_errs __attribute__((unused))) { #else static void maybe_audit_mass_relabel(int mass_relabel, int mass_relabel_errs) { int audit_fd = -1; int rc = 0; if (!mass_relabel) /* only audit a forced full relabel */ return; audit_fd = audit_open(); if (audit_fd < 0) { fprintf(stderr, "Error connecting to audit system.\n"); exit(-1); } rc = audit_log_user_message(audit_fd, AUDIT_FS_RELABEL, "op=mass relabel", NULL, NULL, NULL, !mass_relabel_errs); if (rc <= 0) { fprintf(stderr, "Error sending audit message: %s.\n", strerror(errno)); /* exit(-1); -- don't exit atm. as fix for eff_cap isn't in most kernels */ } audit_close(audit_fd); #endif }
static int on_runlevel(Context *c) { int r = 0, q, previous, runlevel; assert(c); /* We finished changing runlevel, so let's write the * utmp record and send the audit msg */ /* First, get last runlevel */ q = utmp_get_runlevel(&previous, NULL); if (q < 0) { if (q != -ESRCH && q != -ENOENT) { log_error("Failed to get current runlevel: %s", strerror(-q)); return q; } previous = 0; } /* Secondly, get new runlevel */ runlevel = get_current_runlevel(c); if (runlevel < 0) return runlevel; if (previous == runlevel) return 0; #ifdef HAVE_AUDIT if (c->audit_fd >= 0) { _cleanup_free_ char *s = NULL; if (asprintf(&s, "old-level=%c new-level=%c", previous > 0 ? previous : 'N', runlevel > 0 ? runlevel : 'N') < 0) return log_oom(); if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, NULL, NULL, NULL, 1) < 0 && errno != EPERM) { log_error("Failed to send audit message: %m"); r = -errno; } } #endif q = utmp_put_runlevel(runlevel, previous); if (q < 0 && q != -ESRCH && q != -ENOENT) { log_error("Failed to write utmp record: %s", strerror(-q)); r = q; } return r; }
static int on_runlevel(Context *c) { int r = 0, q, previous, runlevel; assert(c); /* We finished changing runlevel, so let's write the * utmp record and send the audit msg */ /* First, get last runlevel */ if ((q = utmp_get_runlevel(&previous, NULL)) < 0) { if (q != -ESRCH && q != -ENOENT) { log_error("Failed to get current runlevel: %s", strerror(-q)); return q; } /* Hmm, we didn't find any runlevel, that means we * have been rebooted */ r = on_reboot(c); previous = 0; } /* Secondly, get new runlevel */ if ((runlevel = get_current_runlevel(c)) < 0) return runlevel; if (previous == runlevel) return 0; #ifdef HAVE_AUDIT if (c->audit_fd >= 0) { char *s = NULL; if (asprintf(&s, "old-level=%c new-level=%c", previous > 0 ? previous : 'N', runlevel > 0 ? runlevel : 'N') < 0) return -ENOMEM; if (audit_log_user_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, NULL, NULL, NULL, 1) < 0) { log_error("Failed to send audit message: %m"); r = -errno; } free(s); } #endif if ((q = utmp_put_runlevel(0, runlevel, previous)) < 0) { log_error("Failed to write utmp record: %s", strerror(-q)); r = q; } return r; }
void audit_logger_message (const char *message, shadow_audit_result result) { if (audit_fd < 0) { return; } else { audit_log_user_message (audit_fd, AUDIT_USYS_CONFIG, message, NULL, /* hostname */ NULL, /* addr */ NULL, /* tty */ (int) result); } }
/* Send audit message */ static int send_audit_message(pam_handle_t *pamh, int success, security_context_t default_context, security_context_t selected_context) { int rc=0; #ifdef HAVE_LIBAUDIT char *msg = NULL; int audit_fd = audit_open(); security_context_t default_raw=NULL; security_context_t selected_raw=NULL; rc = -1; if (audit_fd < 0) { if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) return 0; /* No audit support in kernel */ pam_syslog(pamh, LOG_ERR, "Error connecting to audit system."); return rc; } if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { pam_syslog(pamh, LOG_ERR, "Error translating default context."); default_raw = NULL; } if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { pam_syslog(pamh, LOG_ERR, "Error translating selected context."); selected_raw = NULL; } if (asprintf(&msg, "pam: default-context=%s selected-context=%s", default_raw ? default_raw : (default_context ? default_context : "?"), selected_raw ? selected_raw : (selected_context ? selected_context : "?")) < 0) { pam_syslog(pamh, LOG_ERR, "Error allocating memory."); goto out; } if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, msg, NULL, NULL, NULL, success) <= 0) { pam_syslog(pamh, LOG_ERR, "Error sending audit message."); goto out; } rc = 0; out: free(msg); freecon(default_raw); freecon(selected_raw); close(audit_fd); #else pam_syslog(pamh, LOG_NOTICE, "pam: default-context=%s selected-context=%s success %d", default_context, selected_context, success); #endif return rc; }
int linux_audit_role_change(const char *old_context, const char *new_context, const char *ttyn) { int au_fd, rc; char *message; if ((au_fd = linux_audit_open()) == -1) return -1; /* audit role change using the same format as newrole(1) */ easprintf(&message, "newrole: old-context=%s new-context=%s", old_context, new_context); rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, message, NULL, NULL, ttyn, 1); if (rc <= 0) warning("unable to send audit message"); efree(message); return rc; }
/* * returns: -3 deprecated, -2 success - no reply, -1 error - noreply, * 0 success - reply, > 0 success - rule */ static int setopt(int count, int lineno, char *vars[]) { int c; int retval = 0, rc; optind = 0; opterr = 0; key[0] = 0; keylen = AUDIT_MAX_KEY_LEN; while ((retval >= 0) && (c = getopt(count, vars, "hicslDvtC:e:f:r:b:a:A:d:S:F:m:R:w:W:k:p:q:")) != EOF) { int flags = AUDIT_FILTER_UNSET; rc = 10; // Init to something impossible to see if unused. switch (c) { case 'h': usage(); retval = -1; break; case 'i': ignore = 1; retval = -2; break; case 'c': ignore = 1; continue_error = 1; retval = -2; break; case 's': retval = audit_request_status(fd); if (retval <= 0) retval = -1; else retval = 0; /* success - just get the reply */ break; case 'e': if (optarg && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "1") == 0) || (strcmp(optarg, "2") == 0))) { if (audit_set_enabled(fd, strtoul(optarg,NULL,0)) > 0) audit_request_status(fd); else retval = -1; } else { fprintf(stderr, "Enable must be 0, 1, or 2 was %s\n", optarg); retval = -1; } break; case 'f': if (optarg && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "1") == 0) || (strcmp(optarg, "2") == 0))) { if (audit_set_failure(fd, strtoul(optarg,NULL,0)) > 0) audit_request_status(fd); else return -1; } else { fprintf(stderr, "Failure must be 0, 1, or 2 was %s\n", optarg); retval = -1; } break; case 'r': if (optarg && isdigit(optarg[0])) { uint32_t rate; errno = 0; rate = strtoul(optarg,NULL,0); if (errno) { fprintf(stderr, "Error converting rate\n"); return -1; } if (audit_set_rate_limit(fd, rate) > 0) audit_request_status(fd); else return -1; } else { fprintf(stderr, "Rate must be a numeric value was %s\n", optarg); retval = -1; } break; case 'b': if (optarg && isdigit(optarg[0])) { uint32_t limit; errno = 0; limit = strtoul(optarg,NULL,0); if (errno) { fprintf(stderr, "Error converting backlog\n"); return -1; } if (audit_set_backlog_limit(fd, limit) > 0) audit_request_status(fd); else return -1; } else { fprintf(stderr, "Backlog must be a numeric value was %s\n", optarg); retval = -1; } break; case 'l': if (count > 4 || count == 3) { fprintf(stderr, "Wrong number of options for list request\n"); retval = -1; break; } if (count == 4) { if (strcmp(vars[optind], "-k") == 0) { strncat(key, vars[3], keylen); count -= 2; } else { fprintf(stderr, "Only the -k option is allowed\n"); retval = -1; break; } } if (audit_request_rule_list(fd)) retval = -2; else retval = -1; break; case 'a': if (strstr(optarg, "task") && _audit_syscalladded) { fprintf(stderr, "Syscall auditing requested for task list\n"); retval = -1; } else { rc = audit_rule_setup(optarg, &add, &action, lineno); if (rc == 3) { fprintf(stderr, "Multiple rule insert/delete operations are not allowed\n"); retval = -1; } else if (rc == 2) { fprintf(stderr, "Append rule - bad keyword %s\n", optarg); retval = -1; } else if (rc == 1) { fprintf(stderr, "Append rule - possible is deprecated\n"); return -3; /* deprecated - eat it */ } else retval = 1; /* success - please send */ } break; case 'A': if (strstr(optarg, "task") && _audit_syscalladded) { fprintf(stderr, "Error: syscall auditing requested for task list\n"); retval = -1; } else { rc = audit_rule_setup(optarg, &add, &action, lineno); if (rc == 3) { fprintf(stderr, "Multiple rule insert/delete operations are not allowed\n"); retval = -1; } else if (rc == 2) { fprintf(stderr, "Add rule - bad keyword %s\n", optarg); retval = -1; } else if (rc == 1) { fprintf(stderr, "Append rule - possible is deprecated\n"); return -3; /* deprecated - eat it */ } else { add |= AUDIT_FILTER_PREPEND; retval = 1; /* success - please send */ } } break; case 'd': rc = audit_rule_setup(optarg, &del, &action, lineno); if (rc == 3) { fprintf(stderr, "Multiple rule insert/delete operations are not allowed\n"); retval = -1; } else if (rc == 2) { fprintf(stderr, "Delete rule - bad keyword %s\n", optarg); retval = -1; } else if (rc == 1) { fprintf(stderr, "Delete rule - possible is deprecated\n"); return -3; /* deprecated - eat it */ } else retval = 1; /* success - please send */ break; case 'S': { int unknown_arch = !_audit_elf; /* Do some checking to make sure that we are not adding a * syscall rule to a list that does not make sense. */ if (((add & (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == AUDIT_FILTER_TASK || (del & (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == AUDIT_FILTER_TASK)) { fprintf(stderr, "Error: syscall auditing being added to task list\n"); return -1; } else if (((add & (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == AUDIT_FILTER_USER || (del & (AUDIT_FILTER_MASK|AUDIT_FILTER_UNSET)) == AUDIT_FILTER_USER)) { fprintf(stderr, "Error: syscall auditing being added to user list\n"); return -1; } else if (exclude) { fprintf(stderr, "Error: syscall auditing cannot be put on exclude list\n"); return -1; } else { if (unknown_arch) { int machine; unsigned int elf; machine = audit_detect_machine(); if (machine < 0) { fprintf(stderr, "Error detecting machine type\n"); return -1; } elf = audit_machine_to_elf(machine); if (elf == 0) { fprintf(stderr, "Error looking up elf type\n"); return -1; } _audit_elf = elf; } } rc = audit_rule_syscallbyname_data(rule_new, optarg); switch (rc) { case 0: _audit_syscalladded = 1; if (unknown_arch && add != AUDIT_FILTER_UNSET) check_rule_mismatch(lineno, optarg); break; case -1: fprintf(stderr, "Syscall name unknown: %s\n", optarg); retval = -1; break; case -2: fprintf(stderr, "Elf type unknown: 0x%x\n", _audit_elf); retval = -1; break; }} break; case 'F': if (add != AUDIT_FILTER_UNSET) flags = add & AUDIT_FILTER_MASK; else if (del != AUDIT_FILTER_UNSET) flags = del & AUDIT_FILTER_MASK; // if the field is arch & there is a -t option...we // can allow it else if ((optind >= count) || (strstr(optarg, "arch=") == NULL) || (strcmp(vars[optind], "-t") != 0)) { fprintf(stderr, "List must be given before field\n"); retval = -1; break; } rc = audit_rule_fieldpair_data(&rule_new,optarg,flags); if (rc != 0) { audit_number_to_errmsg(rc, optarg); retval = -1; } else { if (rule_new->fields[rule_new->field_count-1] == AUDIT_PERM) _audit_permadded = 1; } break; case 'C': if (add != AUDIT_FILTER_UNSET) flags = add & AUDIT_FILTER_MASK; else if (del != AUDIT_FILTER_UNSET) flags = del & AUDIT_FILTER_MASK; rc = audit_rule_interfield_comp_data(&rule_new, optarg, flags); if (rc != 0) { audit_number_to_errmsg(rc, optarg); retval = -1; } else { if (rule_new->fields[rule_new->field_count - 1] == AUDIT_PERM) _audit_permadded = 1; } break; case 'm': if (count > 3) { fprintf(stderr, "The -m option must be only the only option and takes 1 parameter\n"); retval = -1; } else if (audit_log_user_message( fd, AUDIT_USER, optarg, NULL, NULL, NULL, 1) <= 0) retval = -1; else return -2; // success - no reply for this break; case 'R': fprintf(stderr, "Error - nested rule files not supported\n"); retval = -1; break; case 'D': if (count > 4 || count == 3) { fprintf(stderr, "Wrong number of options for Delete all request\n"); retval = -1; break; } if (count == 4) { if (strcmp(vars[optind], "-k") == 0) { strncat(key, vars[3], keylen); count -= 2; } else { fprintf(stderr, "Only the -k option is allowed\n"); retval = -1; break; } } retval = delete_all_rules(fd); if (retval == 0) { (void)audit_request_rule_list(fd); key[0] = 0; retval = -2; } break; case 'w': if (add != AUDIT_FILTER_UNSET || del != AUDIT_FILTER_UNSET) { fprintf(stderr, "watch option can't be given with a syscall\n"); retval = -1; } else if (optarg) { add = AUDIT_FILTER_EXIT; action = AUDIT_ALWAYS; _audit_syscalladded = 1; retval = audit_setup_watch_name(&rule_new, optarg); } else { fprintf(stderr, "watch option needs a path\n"); retval = -1; } break; case 'W': if (optarg) { del = AUDIT_FILTER_EXIT; action = AUDIT_ALWAYS; _audit_syscalladded = 1; retval = audit_setup_watch_name(&rule_new, optarg); } else { fprintf(stderr, "watch option needs a path\n"); retval = -1; } break; case 'k': if (!(_audit_syscalladded || _audit_permadded ) || (add==AUDIT_FILTER_UNSET && del==AUDIT_FILTER_UNSET)) { fprintf(stderr, "key option needs a watch or syscall given prior to it\n"); retval = -1; } else if (!optarg) { fprintf(stderr, "key option needs a value\n"); retval = -1; } else if ((strlen(optarg)+strlen(key)+(!!key[0])) > AUDIT_MAX_KEY_LEN) { fprintf(stderr, "key option exceeds size limit\n"); retval = -1; } else { if (strncmp(optarg, "ids-", 4) == 0) { if (check_ids_key(optarg)) { retval = -1; break; } } if (strchr(optarg, AUDIT_KEY_SEPARATOR)) fprintf(stderr, "key %s has illegal character\n", optarg); if (key[0]) { // Add the separator if we need to strcat(key, key_sep); keylen--; } strncat(key, optarg, keylen); keylen = AUDIT_MAX_KEY_LEN - strlen(key); } break; case 'p': if (!add && !del) { fprintf(stderr, "permission option needs a watch given prior to it\n"); retval = -1; } else if (!optarg) { fprintf(stderr, "permission option needs a filter\n"); retval = -1; } else retval = audit_setup_perms(rule_new, optarg); break; case 'q': if (_audit_syscalladded) { fprintf(stderr, "Syscall auditing requested for make equivalent\n"); retval = -1; } else { char *mp, *sub; retval = equiv_parse(optarg, &mp, &sub); if (retval < 0) { fprintf(stderr, "Error parsing equivalent parts\n"); retval = -1; } else { retval = audit_make_equivalent(fd, mp, sub); if (retval <= 0) { retval = -1; } else return -2; // success - no reply needed } } break; case 't': retval = audit_trim_subtrees(fd); if (retval <= 0) retval = -1; else return -2; // success - no reply for this break; case 'v': printf("auditctl version %s\n", VERSION); retval = -2; break; default: usage(); retval = -1; break; } } /* catch extra args or errors where the user types "- s" */ if (optind == 1) retval = -1; else if ((optind < count) && (retval != -1)) { fprintf(stderr, "parameter passed without an option given\n"); retval = -1; } /* See if we were adding a key */ if (key[0] && list_requested == 0) { int flags = 0; char *cmd=NULL; /* Get the flag */ if (add != AUDIT_FILTER_UNSET) flags = add & AUDIT_FILTER_MASK; else if (del != AUDIT_FILTER_UNSET) flags = del & AUDIT_FILTER_MASK; /* Build the command */ asprintf(&cmd, "key=%s", key); if (cmd) { /* Add this to the rule */ int ret = audit_rule_fieldpair_data(&rule_new, cmd, flags); if (ret < 0) retval = -1; free(cmd); } else { fprintf(stderr, "Out of memory adding key\n"); retval = -1; } } if (retval == -1 && errno == ECONNREFUSED) fprintf(stderr, "The audit system is disabled\n"); return retval; }