Exemplo n.º 1
0
/*
 * This function opens a connection to the kernel's audit
 * subsystem. You must be root for the call to succeed. On error,
 * a negative value is returned. On success, the file descriptor is
 * returned - which can be 0 or higher.
 */
int audit_open(void)
{
	int saved_errno;
	int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_AUDIT);

	if (fd < 0) {
		saved_errno = errno;
		if (errno == EINVAL || errno == EPROTONOSUPPORT ||
				errno == EAFNOSUPPORT)
			audit_msg(LOG_ERR,
				"Error - audit support not in kernel"); 
		else
			audit_msg(LOG_ERR,
				"Error opening audit netlink socket (%s)", 
				strerror(errno));
		errno = saved_errno;
		return fd;
	}
	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
		saved_errno = errno;
		close(fd);
		audit_msg(LOG_ERR, 
			"Error setting audit netlink socket CLOEXEC flag (%s)", 
			strerror(errno));
		errno = saved_errno;
		return -1;
	}
	return fd;
}
Exemplo n.º 2
0
/*
 * This function returns 0 on success and 1 on failure
 */
int audit_setloginuid(uid_t uid)
{
	char loginuid[16];
	int o, count, rc = 0;

	errno = 0;
	count = snprintf(loginuid, sizeof(loginuid), "%u", uid);
	o = open("/proc/self/loginuid", O_NOFOLLOW|O_WRONLY|O_TRUNC);
	if (o >= 0) {
		int block, offset = 0;

		while (count > 0) {
			block = write(o, &loginuid[offset], (unsigned)count);

			if (block < 0) {
				if (errno == EINTR)
					continue;
				audit_msg(LOG_ERR, "Error writing loginuid");
				close(o);
				return 1;
			}
			offset += block;
			count -= block;
		}
		close(o);
	} else {
		audit_msg(LOG_ERR, "Error opening /proc/self/loginuid");
		rc = 1;
	}
	return rc;
}
Exemplo n.º 3
0
static int write_pid_file(void)
{
	int pidfd, len;
	char val[16];

	len = snprintf(val, sizeof(val), "%u\n", getpid());
	if (len <= 0) {
		audit_msg(LOG_ERR, "Pid error (%s)", strerror(errno));
		pidfile = 0;
		return 1;
	}
	pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
	if (pidfd < 0) {
		audit_msg(LOG_ERR, "Unable to set pidfile (%s)",
			strerror(errno));
		pidfile = 0;
		return 1;
	}
	if (write(pidfd, val, (unsigned int)len) != len) {
		audit_msg(LOG_ERR, "Unable to write pidfile (%s)",
			strerror(errno));
		close(pidfd);
		pidfile = 0;
		return 1;
	}
	close(pidfd);
	return 0;
}
Exemplo n.º 4
0
/* Returns -1 on err, 0 on success, and 1 if eagain occurred and not an err */
int dispatch_event(const struct audit_reply *rep, int is_err)
{
	int rc, count = 0;
	struct iovec vec[2];
	struct audit_dispatcher_header hdr;

	if (disp_pipe[1] == -1)
		return 0;

	// Don't send reconfig or rotate as they are purely internal to daemon
	if (rep->type == AUDIT_DAEMON_RECONFIG ||
					rep->type == AUDIT_DAEMON_ROTATE)
		return 0;

	hdr.ver = AUDISP_PROTOCOL_VER; /* Hard-coded to current protocol */
	hdr.hlen = sizeof(struct audit_dispatcher_header);
	hdr.type = rep->type;
	hdr.size = rep->len;

	vec[0].iov_base = (void*)&hdr;
	vec[0].iov_len = sizeof(hdr);
	vec[1].iov_base = (void*)rep->message;
	vec[1].iov_len = rep->len;

	do {
		rc = writev(disp_pipe[1], vec, 2);
	} while (rc < 0 && errno == EAGAIN && count++ < 8);

	// close pipe if no child or peer has been lost
	if (rc <= 0) {
		if (errno == EPIPE) {
			shutdown_dispatcher();
			n_errs = 0;
		} else if (errno == EAGAIN && !is_err) {
			return 1;
		} else {
			if (n_errs <= REPORT_LIMIT) {
				audit_msg(LOG_ERR, 
					"dispatch err (%s) event lost",
					errno == EAGAIN ? "pipe full" :
					strerror(errno));
				n_errs++;
			}
			if (n_errs == REPORT_LIMIT) {
				audit_msg(LOG_ERR, 
					"dispatch error reporting limit"
					" reached - ending report"
					" notification.");
				n_errs++;
			}
			return -1;
		}
	} else
		n_errs = 0;
	return 0;
}
Exemplo n.º 5
0
static int path_parser(struct nv_pair *nv, int line,
	plugin_conf_t *config)
{
	char *dir = NULL, *tdir;
	struct stat buf;

	if (nv->value == NULL) {
		config->path = NULL;
		return 0;
	}

	if (strncasecmp(nv->value, "builtin_", 8) == 0) {
		config->path = strdup(nv->value);
		return 0;
	}

	/* get dir form name. */
	tdir = strdup(nv->value);
	if (tdir)
		dir = dirname(tdir);
	if (dir == NULL || strlen(dir) < 4) { //  '/var' is shortest dirname
		audit_msg(LOG_ERR,
			"The directory name: %s is too short - line %d",
			dir, line);
		free(tdir);
		return 1;
	}

	free((void *)tdir);
	/* If the file exists, see that its regular, owned by root,
	 * and not world anything */
	if (stat(nv->value, &buf) < 0) {
		audit_msg(LOG_ERR, "Unable to stat %s (%s)", nv->value,
			strerror(errno));
		return 1;
	}
	if (!S_ISREG(buf.st_mode)) {
		audit_msg(LOG_ERR, "%s is not a regular file", nv->value);
		return 1;
	}
	if (buf.st_uid != 0) {
		audit_msg(LOG_ERR, "%s is not owned by root", nv->value);
		return 1;
	}
	if ((buf.st_mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)) !=
			   (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)) {
		audit_msg(LOG_ERR, "%s permissions should be 0750", nv->value);
		return 1;
	}
	free((void *)config->path);
	config->path = strdup(nv->value);
	config->inode = buf.st_ino;
	if (config->path == NULL)
		return 1;
	return 0;
}
Exemplo n.º 6
0
void audit_start(f_state *s, f_info *i)
{
	if (!get_mode(s, mode_quiet))
		{
		fprintf(stderr, "Processing: %s\n|", i->file_name);
		}

	audit_msg(s, FOREMOST_DIVIDER);
	audit_msg(s, "File: %s", i->file_name);
	audit_msg(s, "Start: %s", current_time());
}
Exemplo n.º 7
0
/* 
 * This function returns 0 on error and len on success.
 */
static int adjust_reply(struct audit_reply *rep, int len)
{
	rep->type     = rep->msg.nlh.nlmsg_type;
	rep->len      = rep->msg.nlh.nlmsg_len;
	rep->nlh      = &rep->msg.nlh;
	rep->status   = NULL;
	rep->rule     = NULL;
	rep->login    = NULL;
	rep->message  = NULL;
	rep->error    = NULL;
	rep->signal_info = NULL;
	rep->conf     = NULL;
	if (!NLMSG_OK(rep->nlh, (unsigned int)len)) {
		if (len == sizeof(rep->msg)) {
			audit_msg(LOG_ERR, 
				"Netlink event from kernel is too big");
			errno = EFBIG;
		} else {
			audit_msg(LOG_ERR, 
			"Netlink message from kernel was not OK");
			errno = EBADE;
		}
		return 0;
	}

	/* Next we'll set the data structure to point to msg.data. This is
	 * to avoid having to use casts later. */
	switch (rep->type) {
		case NLMSG_ERROR: 
			rep->error   = NLMSG_DATA(rep->nlh); 
			break;
		case AUDIT_GET:   
			rep->status  = NLMSG_DATA(rep->nlh); 
			break;
		case AUDIT_LIST:  
			rep->rule    = NLMSG_DATA(rep->nlh); 
			break;
		case AUDIT_LIST_RULES:  
			rep->ruledata = NLMSG_DATA(rep->nlh); 
			break;
		case AUDIT_USER:
		case AUDIT_LOGIN:
		case AUDIT_KERNEL:
		case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
		case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
		case AUDIT_FIRST_EVENT...AUDIT_INTEGRITY_LAST_MSG:
			rep->message = NLMSG_DATA(rep->nlh);
			break;
		case AUDIT_SIGNAL_INFO:
			rep->signal_info = NLMSG_DATA(rep->nlh);
			break;
	}
	return len;
}
Exemplo n.º 8
0
static int audit_failure_parser(const char *val, int line)
{
	int i;

	audit_msg(LOG_DEBUG, "audit_failure_parser called with: %s", val);
	for (i=0; failure_actions[i].name != NULL; i++) {
		if (strcasecmp(val, failure_actions[i].name) == 0) {
			config.failure_action = failure_actions[i].option;
			return 0;
		}
	}
	audit_msg(LOG_ERR, "Option %s not found - line %d", val, line);
	return 1;
}
Exemplo n.º 9
0
/* This function returns 1 on error & 0 on success */
int init_dispatcher(const struct daemon_conf *config)
{
	if (config->dispatcher == NULL) 
		return 0;

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, disp_pipe)) {
		audit_msg(LOG_ERR, "Failed creating disp_pipe");
		return 1;
	}

	/* Make both disp_pipe non-blocking */
	if (config->qos == QOS_NON_BLOCKING) {
		if (set_flags(disp_pipe[0], O_NONBLOCK) < 0 ||
			set_flags(disp_pipe[1], O_NONBLOCK) < 0) {
			audit_msg(LOG_ERR, "Failed to set O_NONBLOCK flag");
			return 1;
		}
	}

	// do the fork
	pid = fork();
	switch(pid) {
		case 0:	// child
			dup2(disp_pipe[0], 0);
			close(disp_pipe[0]);
			close(disp_pipe[1]);
			setsid();
			execl(config->dispatcher, config->dispatcher, NULL);
			audit_msg(LOG_ERR, "exec() failed");
			exit(1);
			break;
		case -1:	// error
			return 1;
			break;
		default:	// parent
			close(disp_pipe[0]);
			disp_pipe[0] = -1;
			/* Avoid leaking this */
			if (fcntl(disp_pipe[1], F_SETFD, FD_CLOEXEC) < 0) {
				audit_msg(LOG_ERR,
					"Failed to set FD_CLOEXEC flag");
				return 1;
			}
			audit_msg(LOG_INFO, "Started dispatcher: %s pid: %u",
					config->dispatcher, pid);
			break;
	}

	return 0;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
static char *get_line(FILE *f, char *buf, unsigned size, int *lineno,
	 const char *file)
{
	int too_long = 0;

	while (fgets_unlocked(buf, size, f)) {
		/* remove newline */
		char *ptr = strchr(buf, 0x0a);
		if (ptr) {
			if (!too_long) {
				*ptr = 0;
				return buf;
			}
			// Reset and start with the next line
			too_long = 0;
			*lineno = *lineno + 1;
		} else {
			// If a line is too long skip it.
			// Only output 1 warning
			if (!too_long)
				audit_msg(LOG_ERR,
					"Skipping line %d in %s: too long",
					*lineno, file);
			too_long = 1;
		}
	}
	return NULL;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 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;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
0
int audit_add_watch_dir(int type, struct audit_rule_data **rulep,
			const char *path)
{
	size_t len = strlen(path);
	struct audit_rule_data *rule = *rulep;

	if (rule && rule->field_count) {
		audit_msg(LOG_ERR, "Rule is not empty\n");
		return -1;
	}
	if (type != AUDIT_WATCH && type != AUDIT_DIR) {
		audit_msg(LOG_ERR, "Invalid type used\n");
		return -1;
	}

	*rulep = realloc(rule, len + sizeof(*rule));
	if (*rulep == NULL) {
		free(rule);
		audit_msg(LOG_ERR, "Cannot realloc memory!\n");
		return -1;
	}
	rule = *rulep;
	memset(rule, 0, len + sizeof(*rule));

	rule->flags = AUDIT_FILTER_EXIT;
	rule->action = AUDIT_ALWAYS;
	audit_rule_syscallbyname_data(rule, "all");
	rule->field_count = 2;
	rule->fields[0] = type;
	rule->values[0] = len;
	rule->fieldflags[0] = AUDIT_EQUAL;
	rule->buflen = len;
	memcpy(&rule->buf[0], path, len);

	// Default to all permissions
	rule->fields[1] = AUDIT_PERM;
	rule->fieldflags[1] = AUDIT_EQUAL;
	rule->values[1] = AUDIT_PERM_READ | AUDIT_PERM_WRITE |
				AUDIT_PERM_EXEC | AUDIT_PERM_ATTR;
	
	_audit_permadded = 1;

	return  0;
}
Exemplo n.º 20
0
/*
 * This function returns -1 on error, 0 if error response received,
 * and > 0 if packet OK.
 */
int audit_get_reply(int fd, struct audit_reply *rep, reply_t block, int peek)
{
	int len;
	struct sockaddr_nl nladdr;
	socklen_t nladdrlen = sizeof(nladdr);

	if (fd < 0)
		return -EBADF;

	if (block == GET_REPLY_NONBLOCKING)
		block = MSG_DONTWAIT;

retry:
	len = recvfrom(fd, &rep->msg, sizeof(rep->msg), block|peek,
		(struct sockaddr*)&nladdr, &nladdrlen);

	if (len < 0) {
		if (errno == EINTR)
			goto retry;
		if (errno != EAGAIN) {
			int saved_errno = errno;
			audit_msg(LOG_ERR, 
				"Error receiving audit netlink packet (%s)", 
				strerror(errno));
			errno = saved_errno;
		}
		return -errno;
	}
	if (nladdrlen != sizeof(nladdr)) {
		audit_msg(LOG_ERR, 
			"Bad address size reading audit netlink socket");
		return -EPROTO;
	}
	if (nladdr.nl_pid) {
		audit_msg(LOG_ERR, 
			"Spoofed packet received on audit netlink socket");
		return -EINVAL;
	}

	len = adjust_reply(rep, len);
	if (len == 0)
		len = -errno;
	return len; 
}
Exemplo n.º 21
0
/*
 * This function is where we do the integrated check of the audispd config
 * options. At this point, all fields have been read. Returns 0 if no
 * problems and 1 if problems detected.
 */
static int sanity_check(plugin_conf_t *config, const char *file)
{
	/* Error checking */
	if (config->active == A_YES && config->path == NULL) {
		audit_msg(LOG_ERR, 
		    "Error - plugin (%s) is active but no path given", file);
		return 1;
	}
	return 0;
}
Exemplo n.º 22
0
/*
 * A clean exit means : 
 * 1) we log that we are going down
 * 2) deregister with kernel
 * 3) close the netlink socket
 */
static void clean_exit(void)
{
	audit_msg(LOG_INFO, "The audit daemon is exiting.");
	if (fd >= 0) {
		audit_set_pid(fd, 0, WAIT_NO);
		audit_close(fd);
	}
	if (pidfile)
		unlink(pidfile);
	closelog();
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
0
void audit_layout(f_state *s)
{
	audit_msg(s,
			  "Num\t %s (bs=%d)\t %10s\t %s\t %s \n",
			  "Name",
			  s->block_size,
			  "Size",
			  "File Offset",
			  "Comment");

}
Exemplo n.º 25
0
int user_interrupt (f_state * s, f_info * i)
	{
	audit_msg(s, "Interrupt received at %s", current_time());

	/* RBF - Write user_interrupt */
	fclose(i->handle);
	free(s);
	free(i);
	cleanup_output(s);
	exit(-1);
	return FALSE;
	}
Exemplo n.º 26
0
void setup_stream(f_state *s, f_info *i)
{
	char	buffer[MAX_STRING_LENGTH];
	u_int64_t	skip = (((u_int64_t) s->skip) * ((u_int64_t) s->block_size));
#ifdef DEBUG
	printf("s->skip=%d s->block_size=%d total=%llu\n",
		   s->skip,
		   s->block_size,
		   (((u_int64_t) s->skip) * ((u_int64_t) s->block_size)));
#endif
	i->bytes_read = 0;
	i->total_megs = i->total_bytes / ONE_MEGABYTE;

	if (i->total_bytes != 0)
		{
		audit_msg(s,
				  "Length: %s (%llu bytes)",
				  human_readable(i->total_bytes, buffer),
				  i->total_bytes);
		}
	else
		audit_msg(s, "Length: Unknown");

	if (s->skip != 0)
		{
		audit_msg(s, "Skipping: %s (%llu bytes)", human_readable(skip, buffer), skip);
		fseeko(i->handle, skip, SEEK_SET);
		if (i->total_bytes != 0)
			i->total_bytes -= skip;
		}

	audit_msg(s, " ");

#ifdef __WIN32
	i->last_read = 0;
	i->overflow_count = 0;
#endif

}
Exemplo n.º 27
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;
}
Exemplo n.º 28
0
static int format_parser(struct nv_pair *nv, int line, 
		plugin_conf_t *config)
{
	int i;

	for (i=0; formats[i].name != NULL; i++) {
		if (strcasecmp(nv->value, formats[i].name) == 0) {
			config->format = formats[i].option;
			return 0;
		}
	}
	audit_msg(LOG_ERR, "Option %s not found - line %d", nv->value, line);
	return 1;
}
Exemplo n.º 29
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;
}
Exemplo n.º 30
0
/* set_flags: to set flags to file desc */
static int set_flags(int fn, int flags)
{
	int fl;

	if ((fl = fcntl(fn, F_GETFL, 0)) < 0) {
		audit_msg(LOG_ERR, "fcntl failed. Cannot get flags (%s)\n", 
			strerror(errno));
		return fl;
	}

	fl |= flags;

	return fcntl(fn, F_SETFL, fl);
}