/*
 * Copyright 2012, Samsung Telecommunications of America
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Written by William Roberts <w.roberts@sta.samsung.com>
 *
 */

#include <errno.h>
#include <string.h>
#include <unistd.h>

#define LOG_TAG "libaudit"
#include <log/log.h>

#include "libaudit.h"

/**
 * Waits for an ack from the kernel
 * @param fd
 *  The netlink socket fd
 * @param seq
 *  The current sequence number were acking on
 * @return
 *  This function returns 0 on success, else -errno.
 */
static int get_ack(int fd, int16_t seq)
{
    int rc;
    struct audit_message rep;

    /* Sanity check, this is an internal interface this shouldn't happen */
    if (fd < 0) {
        return -EINVAL;
    }

    rc = audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, MSG_PEEK);
    if (rc < 0) {
        return rc;
    }

    if (rep.nlh.nlmsg_type == NLMSG_ERROR) {
        audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, 0);
        rc = ((struct nlmsgerr *)rep.data)->error;
        if (rc) {
            return -rc;
        }
    }

    if ((int16_t)rep.nlh.nlmsg_seq != seq) {
        SLOGW("Expected sequence number between user space and kernel space is out of skew, "
          "expected %u got %u", seq, rep.nlh.nlmsg_seq);
    }

    return 0;
}

/**
 *
 * @param fd
 *  The netlink socket fd
 * @param type
 *  The type of netlink message
 * @param data
 *  The data to send
 * @param size
 *  The length of the data in bytes
 * @return
 *  This function returns a positive sequence number on success, else -errno.
 */
static int audit_send(int fd, int type, const void *data, size_t size)
{
    int rc;
    static int16_t sequence = 0;
    struct audit_message req;
    struct sockaddr_nl addr;

    memset(&req, 0, sizeof(req));
    memset(&addr, 0, sizeof(addr));

    /* We always send netlink messaged */
    addr.nl_family = AF_NETLINK;

    /* Set up the netlink headers */
    req.nlh.nlmsg_type = type;
    req.nlh.nlmsg_len = NLMSG_SPACE(size);
    req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;

    /*
     * Check for a valid fd, even though sendto would catch this, its easier
     * to always blindly increment the sequence number
     */
    if (fd < 0) {
        return -EBADF;
    }

    /* Ensure the message is not too big */
    if (NLMSG_SPACE(size) > MAX_AUDIT_MESSAGE_LENGTH) {
        SLOGE("netlink message is too large");
        return -EINVAL;
    }

    /* Only memcpy in the data if it was specified */
    if (size && data) {
        memcpy(NLMSG_DATA(&req.nlh), data, size);
    }

    /*
     * Only increment the sequence number on a guarantee
     * you will send it to the kernel.
     *
     * Also, the sequence is defined as a u32 in the kernel
     * struct. Using an int here might not work on 32/64 bit splits. A
     * signed 64 bit value can overflow a u32..but a u32
     * might not fit in the response, so we need to use s32.
     * Which is still kind of hackish since int could be 16 bits
     * in size. The only safe type to use here is a signed 16
     * bit value.
     */
    req.nlh.nlmsg_seq = ++sequence;

    /* While failing and its due to interrupts */

    rc = TEMP_FAILURE_RETRY(sendto(fd, &req, req.nlh.nlmsg_len, 0,
                                   (struct sockaddr*) &addr, sizeof(addr)));

    /* Not all the bytes were sent */
    if (rc < 0) {
        rc = -errno;
        SLOGE("Error sending data over the netlink socket: %s", strerror(-errno));
        goto out;
    } else if ((uint32_t) rc != req.nlh.nlmsg_len) {
        rc = -EPROTO;
        goto out;
    }

    /* We sent all the bytes, get the ack */
    rc = get_ack(fd, sequence);

    /* If the ack failed, return the error, else return the sequence number */
    rc = (rc == 0) ? (int) sequence : rc;

out:
    /* Don't let sequence roll to negative */
    if (sequence < 0) {
        SLOGW("Auditd to Kernel sequence number has rolled over");
        sequence = 0;
    }

    return rc;
}

int audit_setup(int fd, uint32_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 | AUDIT_STATUS_RATE_LIMIT;
    status.rate_limit = 20; // audit entries per second

    /* Let the kernel know this pid will be registering for audit events */
    rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
    if (rc < 0) {
        SLOGE("Could net set pid for audit events, error: %s", strerror(-rc));
        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;
}

int audit_open()
{
    return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT);
}

int audit_get_reply(int fd, struct audit_message *rep, reply_t block, int peek)
{
    ssize_t len;
    int flags;
    int rc = 0;

    struct sockaddr_nl nladdr;
    socklen_t nladdrlen = sizeof(nladdr);

    if (fd < 0) {
        return -EBADF;
    }

    /* Set up the flags for recv from */
    flags = (block == GET_REPLY_NONBLOCKING) ? MSG_DONTWAIT : 0;
    flags |= peek;

    /*
     * Get the data from the netlink socket but on error we need to be carefull,
     * the interface shows that EINTR can never be returned, other errors,
     * however, can be returned.
     */
    len = TEMP_FAILURE_RETRY(recvfrom(fd, rep, sizeof(*rep), flags,
                                      (struct sockaddr*) &nladdr, &nladdrlen));

    /*
     * EAGAIN should be re-tried until success or another error manifests.
     */
    if (len < 0) {
        rc = -errno;
        if (block == GET_REPLY_NONBLOCKING && rc == -EAGAIN) {
            /* If request is non blocking and errno is EAGAIN, just return 0 */
            return 0;
        }
        SLOGE("Error receiving from netlink socket, error: %s", strerror(-rc));
        return rc;
    }

    if (nladdrlen != sizeof(nladdr)) {
        SLOGE("Protocol fault, error: %s", strerror(EPROTO));
        return -EPROTO;
    }

    /* Make sure the netlink message was not spoof'd */
    if (nladdr.nl_pid) {
        SLOGE("Invalid netlink pid received, expected 0 got: %d", nladdr.nl_pid);
        return -EINVAL;
    }

    /* Check if the reply from the kernel was ok */
    if (!NLMSG_OK(&rep->nlh, (size_t)len)) {
        rc = (len == sizeof(*rep)) ? -EFBIG : -EBADE;
        SLOGE("Bad kernel response %s", strerror(-rc));
    }

    return rc;
}

void audit_close(int fd)
{
    int rc = close(fd);
    if (rc < 0) {
        SLOGE("Attempting to close invalid fd %d, error: %s", fd, strerror(errno));
    }
    return;
}
