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