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