Home | History | Annotate | Download | only in qemu
      1 /*
      2  * QEMU access control list management
      3  *
      4  * Copyright (C) 2009 Red Hat, Inc
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 
     26 #include "qemu-common.h"
     27 #include "acl.h"
     28 
     29 #ifdef CONFIG_FNMATCH
     30 #include <fnmatch.h>
     31 #endif
     32 
     33 
     34 static unsigned int nacls = 0;
     35 static qemu_acl **acls = NULL;
     36 
     37 
     38 
     39 qemu_acl *qemu_acl_find(const char *aclname)
     40 {
     41     int i;
     42     for (i = 0 ; i < nacls ; i++) {
     43         if (strcmp(acls[i]->aclname, aclname) == 0)
     44             return acls[i];
     45     }
     46 
     47     return NULL;
     48 }
     49 
     50 qemu_acl *qemu_acl_init(const char *aclname)
     51 {
     52     qemu_acl *acl;
     53 
     54     acl = qemu_acl_find(aclname);
     55     if (acl)
     56         return acl;
     57 
     58     acl = qemu_malloc(sizeof(*acl));
     59     acl->aclname = qemu_strdup(aclname);
     60     /* Deny by default, so there is no window of "open
     61      * access" between QEMU starting, and the user setting
     62      * up ACLs in the monitor */
     63     acl->defaultDeny = 1;
     64 
     65     acl->nentries = 0;
     66     QTAILQ_INIT(&acl->entries);
     67 
     68     acls = qemu_realloc(acls, sizeof(*acls) * (nacls +1));
     69     acls[nacls] = acl;
     70     nacls++;
     71 
     72     return acl;
     73 }
     74 
     75 int qemu_acl_party_is_allowed(qemu_acl *acl,
     76                               const char *party)
     77 {
     78     qemu_acl_entry *entry;
     79 
     80     QTAILQ_FOREACH(entry, &acl->entries, next) {
     81 #ifdef CONFIG_FNMATCH
     82         if (fnmatch(entry->match, party, 0) == 0)
     83             return entry->deny ? 0 : 1;
     84 #else
     85         /* No fnmatch, so fallback to exact string matching
     86          * instead of allowing wildcards */
     87         if (strcmp(entry->match, party) == 0)
     88             return entry->deny ? 0 : 1;
     89 #endif
     90     }
     91 
     92     return acl->defaultDeny ? 0 : 1;
     93 }
     94 
     95 
     96 void qemu_acl_reset(qemu_acl *acl)
     97 {
     98     qemu_acl_entry *entry;
     99 
    100     /* Put back to deny by default, so there is no window
    101      * of "open access" while the user re-initializes the
    102      * access control list */
    103     acl->defaultDeny = 1;
    104     QTAILQ_FOREACH(entry, &acl->entries, next) {
    105         QTAILQ_REMOVE(&acl->entries, entry, next);
    106         free(entry->match);
    107         free(entry);
    108     }
    109     acl->nentries = 0;
    110 }
    111 
    112 
    113 int qemu_acl_append(qemu_acl *acl,
    114                     int deny,
    115                     const char *match)
    116 {
    117     qemu_acl_entry *entry;
    118 
    119     entry = qemu_malloc(sizeof(*entry));
    120     entry->match = qemu_strdup(match);
    121     entry->deny = deny;
    122 
    123     QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
    124     acl->nentries++;
    125 
    126     return acl->nentries;
    127 }
    128 
    129 
    130 int qemu_acl_insert(qemu_acl *acl,
    131                     int deny,
    132                     const char *match,
    133                     int index)
    134 {
    135     qemu_acl_entry *entry;
    136     qemu_acl_entry *tmp;
    137     int i = 0;
    138 
    139     if (index <= 0)
    140         return -1;
    141     if (index >= acl->nentries)
    142         return qemu_acl_append(acl, deny, match);
    143 
    144 
    145     entry = qemu_malloc(sizeof(*entry));
    146     entry->match = qemu_strdup(match);
    147     entry->deny = deny;
    148 
    149     QTAILQ_FOREACH(tmp, &acl->entries, next) {
    150         i++;
    151         if (i == index) {
    152             QTAILQ_INSERT_BEFORE(tmp, entry, next);
    153             acl->nentries++;
    154             break;
    155         }
    156     }
    157 
    158     return i;
    159 }
    160 
    161 int qemu_acl_remove(qemu_acl *acl,
    162                     const char *match)
    163 {
    164     qemu_acl_entry *entry;
    165     int i = 0;
    166 
    167     QTAILQ_FOREACH(entry, &acl->entries, next) {
    168         i++;
    169         if (strcmp(entry->match, match) == 0) {
    170             QTAILQ_REMOVE(&acl->entries, entry, next);
    171             return i;
    172         }
    173     }
    174     return -1;
    175 }
    176 
    177 
    178 /*
    179  * Local variables:
    180  *  c-indent-level: 4
    181  *  c-basic-offset: 4
    182  *  tab-width: 8
    183  * End:
    184  */
    185