aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/lib/netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/lib/netlink.c')
-rw-r--r--framework/src/audit/lib/netlink.c299
1 files changed, 0 insertions, 299 deletions
diff --git a/framework/src/audit/lib/netlink.c b/framework/src/audit/lib/netlink.c
deleted file mode 100644
index 6c80c30c..00000000
--- a/framework/src/audit/lib/netlink.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* netlink.c --
- * Copyright 2004, 2005, 2009, 2013 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:
- * Steve Grubb <sgrubb@redhat.com>
- * Rickard E. (Rik) Faith <faith@redhat.com>
- */
-
-#include "config.h"
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <time.h>
-#include <sys/poll.h>
-#include "libaudit.h"
-#include "private.h"
-
-#ifndef NETLINK_AUDIT
-#define NETLINK_AUDIT 9
-#endif
-
-static int adjust_reply(struct audit_reply *rep, int len);
-static int check_ack(int fd, int seq);
-
-/*
- * 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;
-}
-
-
-void audit_close(int fd)
-{
- if (fd >= 0)
- close(fd);
-}
-
-
-/*
- * 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;
-}
-hidden_def(audit_get_reply)
-
-
-/*
- * 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->ruledata = NULL;
- rep->login = NULL;
- rep->message = NULL;
- rep->error = NULL;
- rep->signal_info = NULL;
- rep->conf = NULL;
-#if HAVE_DECL_AUDIT_FEATURE_VERSION
- rep->features = NULL;
-#endif
- 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;
-#if HAVE_DECL_AUDIT_FEATURE_VERSION
- case AUDIT_GET_FEATURE:
- rep->features = NLMSG_DATA(rep->nlh);
- break;
-#endif
- 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;
-}
-
-
-/*
- * Return values: success: positive non-zero sequence number
- * error: -errno
- * short: 0
- */
-int audit_send(int fd, int type, const void *data, unsigned int size)
-{
- static int sequence = 0;
- struct audit_message req;
- int retval;
- struct sockaddr_nl addr;
-
- /* Due to user space library callbacks, there's a chance that
- a -1 for the fd could be passed. Just check for and handle it. */
- if (fd < 0) {
- errno = EBADF;
- return -errno;
- }
-
- if (NLMSG_SPACE(size) > MAX_AUDIT_MESSAGE_LENGTH) {
- errno = EINVAL;
- return -errno;
- }
-
- if (++sequence < 0)
- sequence = 1;
-
- memset(&req, 0, sizeof(req));
- req.nlh.nlmsg_len = NLMSG_SPACE(size);
- req.nlh.nlmsg_type = type;
- req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
- req.nlh.nlmsg_seq = sequence;
- if (size && data)
- memcpy(NLMSG_DATA(&req.nlh), data, size);
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
- addr.nl_pid = 0;
- addr.nl_groups = 0;
-
- do {
- retval = sendto(fd, &req, req.nlh.nlmsg_len, 0,
- (struct sockaddr*)&addr, sizeof(addr));
- } while (retval < 0 && errno == EINTR);
- if (retval == (int)req.nlh.nlmsg_len) {
- if ((retval = check_ack(fd, sequence)) == 0)
- return sequence;
- else
- return retval;
- }
- if (retval < 0)
- return -errno;
-
- return 0;
-}
-hidden_def(audit_send)
-
-/*
- * This function will take a peek into the next packet and see if there's
- * an error. If so, the error is returned and its non-zero. Otherwise a
- * zero is returned indicating that we don't know of any problems.
- */
-static int check_ack(int fd, int seq)
-{
- int rc, retries = 80;
- struct audit_reply rep;
- struct pollfd pfd[1];
-
-retry:
- pfd[0].fd = fd;
- pfd[0].events = POLLIN;
- do {
- rc = poll(pfd, 1, 500); /* .5 second */
- } while (rc < 0 && errno == EINTR);
-
- /* We don't look at rc from above as it doesn't matter. We are
- * going to try to read nonblocking just in case packet shows up. */
-
- /* NOTE: whatever is returned is treated as the errno */
- rc = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, MSG_PEEK);
- if (rc == -EAGAIN && retries) {
- retries--;
- goto retry;
- } else if (rc < 0)
- return rc;
- else if (rc == 0)
- return -EINVAL; /* This can't happen anymore */
- else if (rc > 0 && rep.type == NLMSG_ERROR) {
- int error = rep.error->error;
- /* Eat the message */
- (void)audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);
-
- /* NLMSG_ERROR can indicate success, only report nonzero */
- if (error) {
- errno = -error;
- return error;
- }
- }
- return 0;
-}
-