/*
 * 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_set_pid(int fd, uint32_t pid, rep_wait_t wmode)
{
    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) {
        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. Only wait if the
     * wmode is != WAIT_NO
     */
    if (wmode != WAIT_NO) {
        /* 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, 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;
}
