Beispiel #1
0
/*
 * This function will send a user space message to the kernel.
 * It returns the sequence number which is > 0 on success  
 * or <= 0 on error. (pam uses this) This is the main audit sending
 * function now.
 */
int audit_send_user_message(int fd, int type, hide_t hide_error,
	const char *message)
{
	int retry_cnt = 0;
	int rc;
retry:
	rc = audit_send(fd, type, message, strlen(message)+1);
	if (rc == -ECONNREFUSED) {
		/* This is here to let people that build their own kernel
		   and disable the audit system get in. ECONNREFUSED is
		   issued by the kernel when there is "no on listening". */
		return 0;
	} else if (rc == -EPERM && getuid() != 0 && hide_error == HIDE_IT) {
		/* If we get this, then the kernel supports auditing
		 * but we don't have enough privilege to write to the
		 * socket. Therefore, we have already been authenticated
		 * and we are a common user. Just act as though auditing
		 * is not enabled. Any other error we take seriously.
		 * This is here basically to satisfy Xscreensaver. */
		return 0;
	} else if (rc == -EINVAL) {
		/* If we get this, the kernel doesn't understand the
		 * netlink message type. This is most likely due to
		 * being an old kernel. Use the old message type. */
		if (type >= AUDIT_FIRST_USER_MSG && 
				type <= AUDIT_LAST_USER_MSG && !retry_cnt) {

			/* do retry */
			type = AUDIT_USER;
			retry_cnt++;
			goto retry;
		} 
	}
	return rc;
}
Beispiel #2
0
/*
 * This function returns -1 on error and 1 on success.
 */
int audit_set_pid(int fd, uint32_t pid, rep_wait_t wmode)
{
	struct audit_status s;
	struct audit_reply rep;
	struct pollfd pfd[1];
	int rc;

	memset(&s, 0, sizeof(s));
	s.mask    = AUDIT_STATUS_PID;
	s.pid     = pid;
	rc = audit_send(fd, AUDIT_SET, &s, sizeof(s));
	if (rc < 0) {
		audit_msg(audit_priority(errno), 
			"Error setting audit daemon pid (%s)", 
			strerror(-rc));
		return rc;
	}
	if (wmode == WAIT_NO)
		return 1;

	/* Now we'll see if there's any reply message. This only
           happens on error. It is not fatal if there is no message.
	   As a matter of fact, we don't do anything with the message
	   besides gobble it. */
	pfd[0].fd = fd;
	pfd[0].events = POLLIN;
	do {
		rc = poll(pfd, 1, 100);	/* .1 second */
	} while (rc < 0 && errno == EINTR);

	(void)audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);
	return 1;
}
int audit_setup(int fd, pid_t pid) {
    int rc;
    struct audit_message rep;
    struct audit_status status;

    memset(&status, 0, sizeof(status));

    /*
     * In order to set the auditd PID we send an audit message over the netlink
     * socket with the pid field of the status struct set to our current pid,
     * and the the mask set to AUDIT_STATUS_PID
     */
    status.pid = pid;
    status.mask = AUDIT_STATUS_PID;

    /* Let the kernel know this pid will be registering for audit events */
    rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
    if (rc < 0) {
        return rc;
    }

    /*
     * In a request where we need to wait for a response, wait for the message
     * and discard it. This message confirms and sync's us with the kernel.
     * This daemon is now registered as the audit logger.
     *
     * TODO
     * If the daemon dies and restarts the message didn't come back,
     * so I went to non-blocking and it seemed to fix the bug.
     * Need to investigate further.
     */
    audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);

    return 0;
}
Beispiel #4
0
/*
 * This function is part of the directory auditing code
 */
int audit_make_equivalent(int fd, const char *mount_point,
			 const char *subtree)
{
	int rc;
	size_t len1 = strlen(mount_point);
	size_t len2 = strlen(subtree);
 	struct {
 		uint32_t sizes[2];
 		unsigned char buf[];
 	} *cmd = malloc(sizeof(*cmd) + len1 + len2);

 	memset(cmd, 0, sizeof(*cmd) + len1 + len2);

 	cmd->sizes[0] = len1;
 	cmd->sizes[1] = len2;
 	memcpy(&cmd->buf[0], mount_point, len1);
 	memcpy(&cmd->buf[len1], subtree, len2);

 	rc = audit_send(fd, AUDIT_MAKE_EQUIV, cmd, sizeof(*cmd) + len1 + len2);
	if (rc < 0) 
		audit_msg(audit_priority(errno),
			"Error sending make_equivalent command (%s)",
			strerror(-rc));
	free(cmd);
	return rc;
}
Beispiel #5
0
int audit_request_status(int fd)
{
	int rc = audit_send(fd, AUDIT_GET, NULL, 0);
	if (rc < 0) 
		audit_msg(audit_priority(errno),
			"Error sending status request (%s)", strerror(-rc));
	return rc;
}
Beispiel #6
0
int audit_request_signal_info(int fd)
{
	int rc = audit_send(fd, AUDIT_SIGNAL_INFO, NULL, 0);
	if (rc < 0)
		audit_msg(LOG_WARNING,
			"Error sending signal_info request (%s)",
			strerror(-rc));
	return rc;
}
Beispiel #7
0
int audit_request_rules_list_data(int fd)
{
	int rc = audit_send(fd, AUDIT_LIST_RULES, NULL, 0);
	if (rc < 0 && rc != -EINVAL)
		audit_msg(audit_priority(errno),
			"Error sending rule list data request (%s)", 
			strerror(-rc));
	return rc;
}
Beispiel #8
0
/*
 * This function is part of the directory auditing code
 */
int audit_trim_subtrees(int fd)
{
	int rc = audit_send(fd, AUDIT_TRIM, NULL, 0);
	if (rc < 0) 
		audit_msg(audit_priority(errno),
			"Error sending trim subtrees command (%s)",
			strerror(-rc));
	return rc;
}
Beispiel #9
0
int audit_request_rules_list(int fd)
{
	int rc = audit_send(fd, AUDIT_LIST, NULL, 0);
	if (rc < 0)
		audit_msg(audit_priority(errno),
			"Error sending rule list request (%s)", 
			strerror(-rc));
	return rc;
}
Beispiel #10
0
int audit_add_rule(int fd, struct audit_rule *rule, int flags, int action)
{
	int rc;

	rule->flags  = flags;
	rule->action = action;
	rc = audit_send(fd, AUDIT_ADD, rule, sizeof(struct audit_rule));
	if (rc < 0)
		audit_msg(audit_priority(errno),
			"Error sending add rule request (%s)",
				errno == EEXIST ?
				"Rule exists" :	strerror(-rc));
	return rc;
}
Beispiel #11
0
int audit_set_enabled(int fd, uint32_t enabled)
{
	int rc;
	struct audit_status s;

	memset(&s, 0, sizeof(s));
	s.mask    = AUDIT_STATUS_ENABLED;
	s.enabled = enabled;
	rc = audit_send(fd, AUDIT_SET, &s, sizeof(s));
	if (rc < 0)
		audit_msg(audit_priority(errno),
			"Error sending enable request (%s)", strerror(-rc));
	return rc;
}
Beispiel #12
0
int audit_set_failure(int fd, uint32_t failure)
{
	int rc;
	struct audit_status s;

	memset(&s, 0, sizeof(s));
	s.mask    = AUDIT_STATUS_FAILURE;
	s.failure = failure;
	rc = audit_send(fd, AUDIT_SET, &s, sizeof(s));
	if (rc < 0)
		audit_msg(audit_priority(errno), 
			"Error sending failure mode request (%s)", 
			strerror(-rc));
	return rc;
}
Beispiel #13
0
int audit_set_backlog_limit(int fd, uint32_t limit)
{
	int rc;
	struct audit_status s;

	memset(&s, 0, sizeof(s));
	s.mask          = AUDIT_STATUS_BACKLOG_LIMIT;
	s.backlog_limit = limit;
	rc = audit_send(fd, AUDIT_SET, &s, sizeof(s));
	if (rc < 0)
		audit_msg(audit_priority(errno),
			"Error sending backlog limit request (%s)", 
			strerror(-rc));
	return rc;
}
Beispiel #14
0
int audit_delete_rule(int fd, struct audit_rule *rule, int flags, int action)
{
	int rc;

	rule->flags  = flags;
	rule->action = action;
	rc = audit_send(fd, AUDIT_DEL, rule, sizeof(struct audit_rule));
	if (rc < 0) {
		if (rc == -ENOENT)
			audit_msg(LOG_WARNING,
			"Error sending delete rule request (No rule matches)");
		else
			audit_msg(audit_priority(errno),
				"Error sending delete rule request (%s)",
				strerror(-rc));
	}
	return rc;
}
int audit_rate_limit(int fd, unsigned rate_limit) {
    int rc;
    struct audit_message rep;
    struct audit_status status;

    memset(&status, 0, sizeof(status));

    status.mask = AUDIT_STATUS_RATE_LIMIT;
    status.rate_limit = rate_limit; /* audit entries per second */

    rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
    if (rc < 0) {
        return rc;
    }

    audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);

    return 0;
}
Beispiel #16
0
int audit_add_rule_data(int fd, struct audit_rule_data *rule,
                        int flags, int action)
{
	int rc;

	if (flags == AUDIT_FILTER_ENTRY) {
		audit_msg(LOG_WARNING, "Use of entry filter is deprecated");
		return -2;
	}
	rule->flags  = flags;
	rule->action = action;
	rc = audit_send(fd, AUDIT_ADD_RULE, rule, 
			sizeof(struct audit_rule_data) + rule->buflen);
	if (rc < 0)
		audit_msg(audit_priority(errno),
			"Error sending add rule data request (%s)",
				errno == EEXIST ? 
				"Rule exists" : strerror(-rc));
	return rc;
}
Beispiel #17
0
int audit_delete_rule_data(int fd, struct audit_rule_data *rule,
                           int flags, int action)
{
	int rc;

	if (flags == AUDIT_FILTER_ENTRY) {
		audit_msg(LOG_WARNING, "Use of entry filter is deprecated");
		return -2;
	}
	rule->flags  = flags;
	rule->action = action;
	rc = audit_send(fd, AUDIT_DEL_RULE, rule, 
			sizeof(struct audit_rule_data) + rule->buflen);
	if (rc < 0) {
		if (rc == -ENOENT)
			audit_msg(LOG_WARNING,
			"Error sending delete rule request (No rule matches)");
		else
			audit_msg(audit_priority(errno),
				"Error sending delete rule data request (%s)",
				strerror(-rc));
	}
	return rc;
}
static int audit_rules_parse_and_add(int audit_fd, char *line)
{
    char *argv[AUDIT_MAX_FIELDS];
    int argc;
    int rc = 0;
    int added_rule = 0;
    char p;
    int opt;
    size_t len;
    struct audit_rule_data *rule;

    /* Strip crlf */
    line[strlen(line) -1] = '\0';

    argv[0] = "auditd";

    for (argc=1; argc < AUDIT_MAX_FIELDS - 1; argc++) {
        argv[argc] = strsep(&line, " \n\r");
        if (argv[argc] == NULL) {
            break;
        }
    }

    optind = 0;
    char *field;
    char *oper;
    size_t length;
    int audit_field;
    int oper_field;
    int i;

    while ((opt = getopt(argc, argv, "w:e:p:F:")) != -1) {
        switch(opt) {
        case 'w':
            if (audit_add_dir(&rule, optarg)) {
                SLOGE("Error adding rule");
                return -1;
            }
            added_rule = 1;
            break;
        case 'e':
            if (audit_set_enabled(audit_fd, strtoul(optarg, NULL, 10))) {
                return -1;
            }
            break;
        case 'F':
            if (added_rule == 0) {
                SLOGE("Specify rule type before permissions");
                return -1;
            }

            length = strcspn(optarg, OPERS);
            field = strndup(optarg, length);
            if (field == NULL) {
                SLOGE("Out of memory!");
                return -1;
            }
            audit_field = string_to_audit_field(field);
            if (audit_field == 0) {
                SLOGE("Invalid field: %s", field);
                free(field);
                return -1;
            }
            free(field);

            optarg = &optarg[length];
            length = strspn(optarg, OPERS);
            oper = strndup(optarg, length);
            oper_field = string_to_oper(oper);
            if (oper_field == -1) {
                SLOGE("Invalid operator: %s", oper);
                free(oper);
                return -1;
            }
            free(oper);
            optarg = &optarg[length];
            if (audit_add_field(rule, audit_field, oper_field, optarg) < 0) {
                SLOGE("Adding field failed");
                return -1;
            }
            break;
        case 'p':
            if (added_rule == 0) {
                SLOGE("Specify rule type before permissions");
                return -1;
            }
            uint32_t perms = 0;
            for (len=0; len < strlen(optarg); len++) {
                 switch(optarg[len]) {
                 case 'w':
                     perms |= AUDIT_PERM_WRITE;
                     break;
                 case 'e':
                     perms |= AUDIT_PERM_EXEC;
                     break;
                 case 'r':
                     perms |= AUDIT_PERM_READ;
                     break;
                 case 'a':
                     perms |= AUDIT_PERM_ATTR;
                     break;
                 default:
                     SLOGE("Unknown permission %c", optarg[len]);
                     break;
                 }
            }
            if (audit_update_watch_perms(rule, perms)) {
                SLOGE("Could not set perms on rule");
                return -1;
            }
            break;
        case '?':
            SLOGE("Unsupported option: %c", optopt);
            break;
        }
    }

    if (added_rule) {
        rc = audit_send(audit_fd, AUDIT_ADD_RULE, rule, sizeof(*rule) + rule->buflen);
        free(rule);
    }

    return rc;
}