/*
 * QEMU access control list management
 *
 * Copyright (C) 2009 Red Hat, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */


#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/acl.h"

#ifdef CONFIG_FNMATCH
#include <fnmatch.h>
#endif


static unsigned int nacls = 0;
static qemu_acl **acls = NULL;



qemu_acl *qemu_acl_find(const char *aclname)
{
    int i;
    for (i = 0 ; i < nacls ; i++) {
        if (strcmp(acls[i]->aclname, aclname) == 0)
            return acls[i];
    }

    return NULL;
}

qemu_acl *qemu_acl_init(const char *aclname)
{
    qemu_acl *acl;

    acl = qemu_acl_find(aclname);
    if (acl)
        return acl;

    acl = g_malloc(sizeof(*acl));
    acl->aclname = g_strdup(aclname);
    /* Deny by default, so there is no window of "open
     * access" between QEMU starting, and the user setting
     * up ACLs in the monitor */
    acl->defaultDeny = 1;

    acl->nentries = 0;
    QTAILQ_INIT(&acl->entries);

    acls = g_realloc(acls, sizeof(*acls) * (nacls +1));
    acls[nacls] = acl;
    nacls++;

    return acl;
}

int qemu_acl_party_is_allowed(qemu_acl *acl,
                              const char *party)
{
    qemu_acl_entry *entry;

    QTAILQ_FOREACH(entry, &acl->entries, next) {
#ifdef CONFIG_FNMATCH
        if (fnmatch(entry->match, party, 0) == 0)
            return entry->deny ? 0 : 1;
#else
        /* No fnmatch, so fallback to exact string matching
         * instead of allowing wildcards */
        if (strcmp(entry->match, party) == 0)
            return entry->deny ? 0 : 1;
#endif
    }

    return acl->defaultDeny ? 0 : 1;
}


void qemu_acl_reset(qemu_acl *acl)
{
    qemu_acl_entry *entry, *next_entry;

    /* Put back to deny by default, so there is no window
     * of "open access" while the user re-initializes the
     * access control list */
    acl->defaultDeny = 1;
    QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) {
        QTAILQ_REMOVE(&acl->entries, entry, next);
        g_free(entry->match);
        g_free(entry);
    }
    acl->nentries = 0;
}


int qemu_acl_append(qemu_acl *acl,
                    int deny,
                    const char *match)
{
    qemu_acl_entry *entry;

    entry = g_malloc(sizeof(*entry));
    entry->match = g_strdup(match);
    entry->deny = deny;

    QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
    acl->nentries++;

    return acl->nentries;
}


int qemu_acl_insert(qemu_acl *acl,
                    int deny,
                    const char *match,
                    int index)
{
    qemu_acl_entry *tmp;
    int i = 0;

    if (index <= 0)
        return -1;
    if (index > acl->nentries) {
        return qemu_acl_append(acl, deny, match);
    }

    QTAILQ_FOREACH(tmp, &acl->entries, next) {
        i++;
        if (i == index) {
            qemu_acl_entry *entry;
            entry = g_malloc(sizeof(*entry));
            entry->match = g_strdup(match);
            entry->deny = deny;

            QTAILQ_INSERT_BEFORE(tmp, entry, next);
            acl->nentries++;
            break;
        }
    }

    return i;
}

int qemu_acl_remove(qemu_acl *acl,
                    const char *match)
{
    qemu_acl_entry *entry;
    int i = 0;

    QTAILQ_FOREACH(entry, &acl->entries, next) {
        i++;
        if (strcmp(entry->match, match) == 0) {
            QTAILQ_REMOVE(&acl->entries, entry, next);
            acl->nentries--;
            g_free(entry->match);
            g_free(entry);
            return i;
        }
    }
    return -1;
}
