virtaudit.c 3.9 KB
Newer Older
1
/*
2
 * virtaudit.c: auditing support
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
 *
 * Copyright (C) 2010 Red Hat, Inc.
 *
 * 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
 *
 */

#include <config.h>

#ifdef HAVE_AUDIT
# include <libaudit.h>
#endif
#include <stdio.h>
#include <unistd.h>

#include "virterror_internal.h"
#include "logging.h"
#include "virtaudit.h"

/* Provide the macros in case the header file is old.
   FIXME: should be removed. */
#ifndef AUDIT_VIRT_CONTROL
# define AUDIT_VIRT_CONTROL              2500 /* Start, Pause, Stop VM */
#endif
#ifndef AUDIT_VIRT_RESOURCE
# define AUDIT_VIRT_RESOURCE             2501 /* Resource assignment */
#endif
#ifndef AUDIT_VIRT_MACHINE_ID
# define AUDIT_VIRT_MACHINE_ID           2502 /* Binding of label to VM */
#endif

#define VIR_FROM_THIS VIR_FROM_AUDIT

#if HAVE_AUDIT
static int auditfd = -1;
#endif
static int auditlog = 0;

int virAuditOpen(void)
{
#if HAVE_AUDIT
    if ((auditfd = audit_open()) < 0) {
        virReportSystemError(errno, "%s", _("Unable to initialize audit layer"));
        return -1;
    }

    return 0;
#else
    return -1;
#endif
}


void virAuditLog(int logging)
{
    auditlog = logging;
}


E
Eric Blake 已提交
74 75
void virAuditSend(const char *file ATTRIBUTE_UNUSED, const char *func,
                  size_t linenr,
76 77
                  const char *clienttty ATTRIBUTE_UNUSED,
                  const char *clientaddr ATTRIBUTE_UNUSED,
78
                  enum virAuditRecordType type ATTRIBUTE_UNUSED, bool success,
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
                  const char *fmt, ...)
{
    char *str = NULL;
    va_list args;

    /* Duplicate later checks, to short circuit & avoid printf overhead
     * when nothing is enabled */
#if HAVE_AUDIT
    if (!auditlog && auditfd < 0)
        return;
#else
    if (!auditlog)
        return;
#endif

    va_start(args, fmt);
    if (vasprintf(&str, fmt, args) < 0) {
        VIR_WARN0("Out of memory while formatting audit message");
        str = NULL;
    }
    va_end(args);

    if (auditlog && str) {
        if (success)
            virLogMessage("audit", VIR_LOG_INFO, func, linenr, 0,
                          "success=yes %s", str);
        else
            virLogMessage("audit", VIR_LOG_WARN, func, linenr, 0,
                          "success=no %s", str);
    }

#if HAVE_AUDIT
    if (auditfd < 0)
        return;

    if (str) {
        static const int record_types[] = {
            [VIR_AUDIT_RECORD_MACHINE_CONTROL] = AUDIT_VIRT_CONTROL,
            [VIR_AUDIT_RECORD_MACHINE_ID] = AUDIT_VIRT_MACHINE_ID,
            [VIR_AUDIT_RECORD_RESOURCE] = AUDIT_VIRT_RESOURCE,
        };

        if (type > ARRAY_CARDINALITY(record_types) || record_types[type] == 0)
            VIR_WARN("Unknown audit record type %d", type);
        else if (audit_log_user_message(auditfd, record_types[type], str, NULL,
                                        clientaddr, clienttty, success) < 0) {
            char ebuf[1024];
            VIR_WARN("Failed to send audit message %s: %s",
                     NULLSTR(str), virStrerror(errno, ebuf, sizeof ebuf));
        }
    }
#endif
}

void virAuditClose(void)
{
#if HAVE_AUDIT
    close(auditfd);
#endif
}
139 140 141 142 143 144 145 146 147 148 149 150

char *virAuditEncode(const char *key, const char *value)
{
#if HAVE_AUDIT
    return audit_encode_nv_string(key, value, 0);
#else
    char *str;
    if (virAsprintf(&str, "%s=%s", key, value) < 0)
        return NULL;
    return str;
#endif
}