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 "sysemu.h"
     28 #include "acl.h"
     29 
     30 #ifdef HAVE_FNMATCH_H
     31 #include <fnmatch.h>
     32 #endif
     33 
     34 
     35 static unsigned int nacls = 0;
     36 static qemu_acl **acls = NULL;
     37 
     38 
     39 
     40 qemu_acl *qemu_acl_find(const char *aclname)
     41 {
     42     int i;
     43     for (i = 0 ; i < nacls ; i++) {
     44         if (strcmp(acls[i]->aclname, aclname) == 0)
     45             return acls[i];
     46     }
     47 
     48     return NULL;
     49 }
     50 
     51 qemu_acl *qemu_acl_init(const char *aclname)
     52 {
     53     qemu_acl *acl;
     54 
     55     acl = qemu_acl_find(aclname);
     56     if (acl)
     57         return acl;
     58 
     59     acl = qemu_malloc(sizeof(*acl));
     60     acl->aclname = qemu_strdup(aclname);
     61     /* Deny by default, so there is no window of "open
     62      * access" between QEMU starting, and the user setting
     63      * up ACLs in the monitor */
     64     acl->defaultDeny = 1;
     65 
     66     acl->nentries = 0;
     67     QTAILQ_INIT(&acl->entries);
     68 
     69     acls = qemu_realloc(acls, sizeof(*acls) * (nacls +1));
     70     acls[nacls] = acl;
     71     nacls++;
     72 
     73     return acl;
     74 }
     75 
     76 int qemu_acl_party_is_allowed(qemu_acl *acl,
     77                               const char *party)
     78 {
     79     qemu_acl_entry *entry;
     80 
     81     QTAILQ_FOREACH(entry, &acl->entries, next) {
     82 #ifdef HAVE_FNMATCH_H
     83         if (fnmatch(entry->match, party, 0) == 0)
     84             return entry->deny ? 0 : 1;
     85 #else
     86         /* No fnmatch, so fallback to exact string matching
     87          * instead of allowing wildcards */
     88         if (strcmp(entry->match, party) == 0)
     89             return entry->deny ? 0 : 1;
     90 #endif
     91     }
     92 
     93     return acl->defaultDeny ? 0 : 1;
     94 }
     95 
     96 
     97 void qemu_acl_reset(qemu_acl *acl)
     98 {
     99     qemu_acl_entry *entry;
    100 
    101     /* Put back to deny by default, so there is no window
    102      * of "open access" while the user re-initializes the
    103      * access control list */
    104     acl->defaultDeny = 1;
    105     QTAILQ_FOREACH(entry, &acl->entries, next) {
    106         QTAILQ_REMOVE(&acl->entries, entry, next);
    107         free(entry->match);
    108         free(entry);
    109     }
    110     acl->nentries = 0;
    111 }
    112 
    113 
    114 int qemu_acl_append(qemu_acl *acl,
    115                     int deny,
    116                     const char *match)
    117 {
    118     qemu_acl_entry *entry;
    119 
    120     entry = qemu_malloc(sizeof(*entry));
    121     entry->match = qemu_strdup(match);
    122     entry->deny = deny;
    123 
    124     QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
    125     acl->nentries++;
    126 
    127     return acl->nentries;
    128 }
    129 
    130 
    131 int qemu_acl_insert(qemu_acl *acl,
    132                     int deny,
    133                     const char *match,
    134                     int index)
    135 {
    136     qemu_acl_entry *entry;
    137     qemu_acl_entry *tmp;
    138     int i = 0;
    139 
    140     if (index <= 0)
    141         return -1;
    142     if (index >= acl->nentries)
    143         return qemu_acl_append(acl, deny, match);
    144 
    145 
    146     entry = qemu_malloc(sizeof(*entry));
    147     entry->match = qemu_strdup(match);
    148     entry->deny = deny;
    149 
    150     QTAILQ_FOREACH(tmp, &acl->entries, next) {
    151         i++;
    152         if (i == index) {
    153             QTAILQ_INSERT_BEFORE(tmp, entry, next);
    154             acl->nentries++;
    155             break;
    156         }
    157     }
    158 
    159     return i;
    160 }
    161 
    162 int qemu_acl_remove(qemu_acl *acl,
    163                     const char *match)
    164 {
    165     qemu_acl_entry *entry;
    166     int i = 0;
    167 
    168     QTAILQ_FOREACH(entry, &acl->entries, next) {
    169         i++;
    170         if (strcmp(entry->match, match) == 0) {
    171             QTAILQ_REMOVE(&acl->entries, entry, next);
    172             return i;
    173         }
    174     }
    175     return -1;
    176 }
    177 
    178 
    179 /*
    180  * Local variables:
    181  *  c-indent-level: 4
    182  *  c-basic-offset: 4
    183  *  tab-width: 8
    184  * End:
    185  */
    186