qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

authz: delete existing ACL implementation

The 'qemu_acl' type was a previous non-QOM based attempt to provide an
authorization facility in QEMU. Because it is non-QOM based it cannot be
created via the command line and requires special monitor commands to
manipulate it.

The new QAuthZ subclasses provide a superset of the functionality in
qemu_acl, so the latter can now be deleted. The HMP 'acl_*' monitor
commands are converted to use the new QAuthZSimple data type instead
in order to provide temporary backwards compatibility.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>

+207 -376
-17
configure
··· 3205 3205 fi 3206 3206 fi 3207 3207 3208 - ########################################## 3209 - # fnmatch() probe, used for ACL routines 3210 - fnmatch="no" 3211 - cat > $TMPC << EOF 3212 - #include <fnmatch.h> 3213 - int main(void) 3214 - { 3215 - fnmatch("foo", "foo", 0); 3216 - return 0; 3217 - } 3218 - EOF 3219 - if compile_prog "" "" ; then 3220 - fnmatch="yes" 3221 - fi 3222 3208 3223 3209 ########################################## 3224 3210 # xfsctl() probe, used for file-posix.c ··· 6415 6401 if test "$xkbcommon" = "yes" ; then 6416 6402 echo "XKBCOMMON_CFLAGS=$xkbcommon_cflags" >> $config_host_mak 6417 6403 echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak 6418 - fi 6419 - if test "$fnmatch" = "yes" ; then 6420 - echo "CONFIG_FNMATCH=y" >> $config_host_mak 6421 6404 fi 6422 6405 if test "$xfs" = "yes" ; then 6423 6406 echo "CONFIG_XFS=y" >> $config_host_mak
+17 -18
crypto/tlssession.c
··· 24 24 #include "crypto/tlscredspsk.h" 25 25 #include "crypto/tlscredsx509.h" 26 26 #include "qapi/error.h" 27 - #include "qemu/acl.h" 27 + #include "authz/base.h" 28 28 #include "trace.h" 29 29 30 30 #ifdef CONFIG_GNUTLS ··· 37 37 QCryptoTLSCreds *creds; 38 38 gnutls_session_t handle; 39 39 char *hostname; 40 - char *aclname; 40 + char *authzid; 41 41 bool handshakeComplete; 42 42 QCryptoTLSSessionWriteFunc writeFunc; 43 43 QCryptoTLSSessionReadFunc readFunc; ··· 56 56 gnutls_deinit(session->handle); 57 57 g_free(session->hostname); 58 58 g_free(session->peername); 59 - g_free(session->aclname); 59 + g_free(session->authzid); 60 60 object_unref(OBJECT(session->creds)); 61 61 g_free(session); 62 62 } ··· 95 95 QCryptoTLSSession * 96 96 qcrypto_tls_session_new(QCryptoTLSCreds *creds, 97 97 const char *hostname, 98 - const char *aclname, 98 + const char *authzid, 99 99 QCryptoTLSCredsEndpoint endpoint, 100 100 Error **errp) 101 101 { ··· 105 105 session = g_new0(QCryptoTLSSession, 1); 106 106 trace_qcrypto_tls_session_new( 107 107 session, creds, hostname ? hostname : "<none>", 108 - aclname ? aclname : "<none>", endpoint); 108 + authzid ? authzid : "<none>", endpoint); 109 109 110 110 if (hostname) { 111 111 session->hostname = g_strdup(hostname); 112 112 } 113 - if (aclname) { 114 - session->aclname = g_strdup(aclname); 113 + if (authzid) { 114 + session->authzid = g_strdup(authzid); 115 115 } 116 116 session->creds = creds; 117 117 object_ref(OBJECT(creds)); ··· 262 262 unsigned int nCerts, i; 263 263 time_t now; 264 264 gnutls_x509_crt_t cert = NULL; 265 + Error *err = NULL; 265 266 266 267 now = time(NULL); 267 268 if (now == ((time_t)-1)) { ··· 349 350 gnutls_strerror(ret)); 350 351 goto error; 351 352 } 352 - if (session->aclname) { 353 - qemu_acl *acl = qemu_acl_find(session->aclname); 354 - int allow; 355 - if (!acl) { 356 - error_setg(errp, "Cannot find ACL %s", 357 - session->aclname); 353 + if (session->authzid) { 354 + bool allow; 355 + 356 + allow = qauthz_is_allowed_by_id(session->authzid, 357 + session->peername, &err); 358 + if (err) { 359 + error_propagate(errp, err); 358 360 goto error; 359 361 } 360 - 361 - allow = qemu_acl_party_is_allowed(acl, session->peername); 362 - 363 362 if (!allow) { 364 - error_setg(errp, "TLS x509 ACL check for %s is denied", 363 + error_setg(errp, "TLS x509 authz check for %s is denied", 365 364 session->peername); 366 365 goto error; 367 366 } ··· 555 554 QCryptoTLSSession * 556 555 qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED, 557 556 const char *hostname G_GNUC_UNUSED, 558 - const char *aclname G_GNUC_UNUSED, 557 + const char *authzid G_GNUC_UNUSED, 559 558 QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED, 560 559 Error **errp) 561 560 {
+1 -1
crypto/trace-events
··· 19 19 qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS creds x509 load cert list creds=%p file=%s" 20 20 21 21 # crypto/tlssession.c 22 - qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *aclname, int endpoint) "TLS session new session=%p creds=%p hostname=%s aclname=%s endpoint=%d" 22 + qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *authzid, int endpoint) "TLS session new session=%p creds=%p hostname=%s authzid=%s endpoint=%d" 23 23 qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s"
-66
include/qemu/acl.h
··· 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 - #ifndef QEMU_ACL_H 26 - #define QEMU_ACL_H 27 - 28 - #include "qemu/queue.h" 29 - 30 - typedef struct qemu_acl_entry qemu_acl_entry; 31 - typedef struct qemu_acl qemu_acl; 32 - 33 - struct qemu_acl_entry { 34 - char *match; 35 - int deny; 36 - 37 - QTAILQ_ENTRY(qemu_acl_entry) next; 38 - }; 39 - 40 - struct qemu_acl { 41 - char *aclname; 42 - unsigned int nentries; 43 - QTAILQ_HEAD(,qemu_acl_entry) entries; 44 - int defaultDeny; 45 - }; 46 - 47 - qemu_acl *qemu_acl_init(const char *aclname); 48 - 49 - qemu_acl *qemu_acl_find(const char *aclname); 50 - 51 - int qemu_acl_party_is_allowed(qemu_acl *acl, 52 - const char *party); 53 - 54 - void qemu_acl_reset(qemu_acl *acl); 55 - 56 - int qemu_acl_append(qemu_acl *acl, 57 - int deny, 58 - const char *match); 59 - int qemu_acl_insert(qemu_acl *acl, 60 - int deny, 61 - const char *match, 62 - int index); 63 - int qemu_acl_remove(qemu_acl *acl, 64 - const char *match); 65 - 66 - #endif /* QEMU_ACL_H */
+117 -58
monitor.c
··· 51 51 #include "sysemu/balloon.h" 52 52 #include "qemu/timer.h" 53 53 #include "sysemu/hw_accel.h" 54 - #include "qemu/acl.h" 54 + #include "authz/list.h" 55 + #include "qapi/util.h" 55 56 #include "sysemu/tpm.h" 56 57 #include "qapi/qmp/qdict.h" 57 58 #include "qapi/qmp/qerror.h" ··· 2016 2017 QLIST_INSERT_HEAD (&capture_head, s, entries); 2017 2018 } 2018 2019 2019 - static qemu_acl *find_acl(Monitor *mon, const char *name) 2020 + static QAuthZList *find_auth(Monitor *mon, const char *name) 2020 2021 { 2021 - qemu_acl *acl = qemu_acl_find(name); 2022 + Object *obj; 2023 + Object *container; 2022 2024 2023 - if (!acl) { 2025 + container = object_get_objects_root(); 2026 + obj = object_resolve_path_component(container, name); 2027 + if (!obj) { 2024 2028 monitor_printf(mon, "acl: unknown list '%s'\n", name); 2029 + return NULL; 2025 2030 } 2026 - return acl; 2031 + 2032 + return QAUTHZ_LIST(obj); 2027 2033 } 2028 2034 2029 2035 static void hmp_acl_show(Monitor *mon, const QDict *qdict) 2030 2036 { 2031 2037 const char *aclname = qdict_get_str(qdict, "aclname"); 2032 - qemu_acl *acl = find_acl(mon, aclname); 2033 - qemu_acl_entry *entry; 2034 - int i = 0; 2038 + QAuthZList *auth = find_auth(mon, aclname); 2039 + QAuthZListRuleList *rules; 2040 + size_t i = 0; 2041 + 2042 + if (!auth) { 2043 + return; 2044 + } 2045 + 2046 + monitor_printf(mon, "policy: %s\n", 2047 + QAuthZListPolicy_str(auth->policy)); 2035 2048 2036 - if (acl) { 2037 - monitor_printf(mon, "policy: %s\n", 2038 - acl->defaultDeny ? "deny" : "allow"); 2039 - QTAILQ_FOREACH(entry, &acl->entries, next) { 2040 - i++; 2041 - monitor_printf(mon, "%d: %s %s\n", i, 2042 - entry->deny ? "deny" : "allow", entry->match); 2043 - } 2049 + rules = auth->rules; 2050 + while (rules) { 2051 + QAuthZListRule *rule = rules->value; 2052 + i++; 2053 + monitor_printf(mon, "%zu: %s %s\n", i, 2054 + QAuthZListPolicy_str(rule->policy), 2055 + rule->match); 2056 + rules = rules->next; 2044 2057 } 2045 2058 } 2046 2059 2047 2060 static void hmp_acl_reset(Monitor *mon, const QDict *qdict) 2048 2061 { 2049 2062 const char *aclname = qdict_get_str(qdict, "aclname"); 2050 - qemu_acl *acl = find_acl(mon, aclname); 2063 + QAuthZList *auth = find_auth(mon, aclname); 2051 2064 2052 - if (acl) { 2053 - qemu_acl_reset(acl); 2054 - monitor_printf(mon, "acl: removed all rules\n"); 2065 + if (!auth) { 2066 + return; 2055 2067 } 2068 + 2069 + auth->policy = QAUTHZ_LIST_POLICY_DENY; 2070 + qapi_free_QAuthZListRuleList(auth->rules); 2071 + auth->rules = NULL; 2072 + monitor_printf(mon, "acl: removed all rules\n"); 2056 2073 } 2057 2074 2058 2075 static void hmp_acl_policy(Monitor *mon, const QDict *qdict) 2059 2076 { 2060 2077 const char *aclname = qdict_get_str(qdict, "aclname"); 2061 2078 const char *policy = qdict_get_str(qdict, "policy"); 2062 - qemu_acl *acl = find_acl(mon, aclname); 2079 + QAuthZList *auth = find_auth(mon, aclname); 2080 + int val; 2081 + Error *err = NULL; 2082 + 2083 + if (!auth) { 2084 + return; 2085 + } 2063 2086 2064 - if (acl) { 2065 - if (strcmp(policy, "allow") == 0) { 2066 - acl->defaultDeny = 0; 2087 + val = qapi_enum_parse(&QAuthZListPolicy_lookup, 2088 + policy, 2089 + QAUTHZ_LIST_POLICY_DENY, 2090 + &err); 2091 + if (err) { 2092 + error_free(err); 2093 + monitor_printf(mon, "acl: unknown policy '%s', " 2094 + "expected 'deny' or 'allow'\n", policy); 2095 + } else { 2096 + auth->policy = val; 2097 + if (auth->policy == QAUTHZ_LIST_POLICY_ALLOW) { 2067 2098 monitor_printf(mon, "acl: policy set to 'allow'\n"); 2068 - } else if (strcmp(policy, "deny") == 0) { 2069 - acl->defaultDeny = 1; 2070 - monitor_printf(mon, "acl: policy set to 'deny'\n"); 2071 2099 } else { 2072 - monitor_printf(mon, "acl: unknown policy '%s', " 2073 - "expected 'deny' or 'allow'\n", policy); 2100 + monitor_printf(mon, "acl: policy set to 'deny'\n"); 2074 2101 } 2075 2102 } 2076 2103 } 2077 2104 2105 + static QAuthZListFormat hmp_acl_get_format(const char *match) 2106 + { 2107 + if (strchr(match, '*')) { 2108 + return QAUTHZ_LIST_FORMAT_GLOB; 2109 + } else { 2110 + return QAUTHZ_LIST_FORMAT_EXACT; 2111 + } 2112 + } 2113 + 2078 2114 static void hmp_acl_add(Monitor *mon, const QDict *qdict) 2079 2115 { 2080 2116 const char *aclname = qdict_get_str(qdict, "aclname"); 2081 2117 const char *match = qdict_get_str(qdict, "match"); 2082 - const char *policy = qdict_get_str(qdict, "policy"); 2118 + const char *policystr = qdict_get_str(qdict, "policy"); 2083 2119 int has_index = qdict_haskey(qdict, "index"); 2084 2120 int index = qdict_get_try_int(qdict, "index", -1); 2085 - qemu_acl *acl = find_acl(mon, aclname); 2086 - int deny, ret; 2121 + QAuthZList *auth = find_auth(mon, aclname); 2122 + Error *err = NULL; 2123 + QAuthZListPolicy policy; 2124 + QAuthZListFormat format; 2125 + size_t i = 0; 2087 2126 2088 - if (acl) { 2089 - if (strcmp(policy, "allow") == 0) { 2090 - deny = 0; 2091 - } else if (strcmp(policy, "deny") == 0) { 2092 - deny = 1; 2093 - } else { 2094 - monitor_printf(mon, "acl: unknown policy '%s', " 2095 - "expected 'deny' or 'allow'\n", policy); 2096 - return; 2097 - } 2098 - if (has_index) 2099 - ret = qemu_acl_insert(acl, deny, match, index); 2100 - else 2101 - ret = qemu_acl_append(acl, deny, match); 2102 - if (ret < 0) 2103 - monitor_printf(mon, "acl: unable to add acl entry\n"); 2104 - else 2105 - monitor_printf(mon, "acl: added rule at position %d\n", ret); 2127 + if (!auth) { 2128 + return; 2129 + } 2130 + 2131 + policy = qapi_enum_parse(&QAuthZListPolicy_lookup, 2132 + policystr, 2133 + QAUTHZ_LIST_POLICY_DENY, 2134 + &err); 2135 + if (err) { 2136 + error_free(err); 2137 + monitor_printf(mon, "acl: unknown policy '%s', " 2138 + "expected 'deny' or 'allow'\n", policystr); 2139 + return; 2140 + } 2141 + 2142 + format = hmp_acl_get_format(match); 2143 + 2144 + if (has_index && index == 0) { 2145 + monitor_printf(mon, "acl: unable to add acl entry\n"); 2146 + return; 2147 + } 2148 + 2149 + if (has_index) { 2150 + i = qauthz_list_insert_rule(auth, match, policy, 2151 + format, index - 1, &err); 2152 + } else { 2153 + i = qauthz_list_append_rule(auth, match, policy, 2154 + format, &err); 2155 + } 2156 + if (err) { 2157 + monitor_printf(mon, "acl: unable to add rule: %s", 2158 + error_get_pretty(err)); 2159 + error_free(err); 2160 + } else { 2161 + monitor_printf(mon, "acl: added rule at position %zu\n", i + 1); 2106 2162 } 2107 2163 } 2108 2164 ··· 2110 2166 { 2111 2167 const char *aclname = qdict_get_str(qdict, "aclname"); 2112 2168 const char *match = qdict_get_str(qdict, "match"); 2113 - qemu_acl *acl = find_acl(mon, aclname); 2114 - int ret; 2169 + QAuthZList *auth = find_auth(mon, aclname); 2170 + ssize_t i = 0; 2171 + 2172 + if (!auth) { 2173 + return; 2174 + } 2115 2175 2116 - if (acl) { 2117 - ret = qemu_acl_remove(acl, match); 2118 - if (ret < 0) 2119 - monitor_printf(mon, "acl: no matching acl entry\n"); 2120 - else 2121 - monitor_printf(mon, "acl: removed rule at position %d\n", ret); 2176 + i = qauthz_list_delete_rule(auth, match); 2177 + if (i >= 0) { 2178 + monitor_printf(mon, "acl: removed rule at position %zu\n", i + 1); 2179 + } else { 2180 + monitor_printf(mon, "acl: no matching acl entry\n"); 2122 2181 } 2123 2182 } 2124 2183
+2 -2
tests/Makefile.include
··· 537 537 test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \ 538 538 tests/test-qapi-introspect.o \ 539 539 $(test-qom-obj-y) 540 - benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y) 541 - test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y) 540 + benchmark-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) 541 + test-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y) 542 542 test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y) 543 543 test-authz-obj-y = $(test-qom-obj-y) $(authz-obj-y) 544 544 test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
+10 -5
tests/test-crypto-tlssession.c
··· 28 28 #include "qom/object_interfaces.h" 29 29 #include "qapi/error.h" 30 30 #include "qemu/sockets.h" 31 - #include "qemu/acl.h" 31 + #include "authz/list.h" 32 32 33 33 #ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT 34 34 ··· 229 229 QCryptoTLSCreds *serverCreds; 230 230 QCryptoTLSSession *clientSess = NULL; 231 231 QCryptoTLSSession *serverSess = NULL; 232 - qemu_acl *acl; 232 + QAuthZList *auth; 233 233 const char * const *wildcards; 234 234 int channel[2]; 235 235 bool clientShake = false; ··· 285 285 SERVER_CERT_DIR); 286 286 g_assert(serverCreds != NULL); 287 287 288 - acl = qemu_acl_init("tlssessionacl"); 289 - qemu_acl_reset(acl); 288 + auth = qauthz_list_new("tlssessionacl", 289 + QAUTHZ_LIST_POLICY_DENY, 290 + &error_abort); 290 291 wildcards = data->wildcards; 291 292 while (wildcards && *wildcards) { 292 - qemu_acl_append(acl, 0, *wildcards); 293 + qauthz_list_append_rule(auth, *wildcards, 294 + QAUTHZ_LIST_POLICY_ALLOW, 295 + QAUTHZ_LIST_FORMAT_GLOB, 296 + &error_abort); 293 297 wildcards++; 294 298 } 295 299 ··· 377 381 378 382 object_unparent(OBJECT(serverCreds)); 379 383 object_unparent(OBJECT(clientCreds)); 384 + object_unparent(OBJECT(auth)); 380 385 381 386 qcrypto_tls_session_free(serverSess); 382 387 qcrypto_tls_session_free(clientSess);
+11 -5
tests/test-io-channel-tls.c
··· 29 29 #include "io-channel-helpers.h" 30 30 #include "crypto/init.h" 31 31 #include "crypto/tlscredsx509.h" 32 - #include "qemu/acl.h" 33 32 #include "qapi/error.h" 33 + #include "authz/list.h" 34 34 #include "qom/object_interfaces.h" 35 35 36 36 #ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT ··· 113 113 QIOChannelTLS *serverChanTLS; 114 114 QIOChannelSocket *clientChanSock; 115 115 QIOChannelSocket *serverChanSock; 116 - qemu_acl *acl; 116 + QAuthZList *auth; 117 117 const char * const *wildcards; 118 118 int channel[2]; 119 119 struct QIOChannelTLSHandshakeData clientHandshake = { false, false }; ··· 161 161 SERVER_CERT_DIR); 162 162 g_assert(serverCreds != NULL); 163 163 164 - acl = qemu_acl_init("channeltlsacl"); 165 - qemu_acl_reset(acl); 164 + auth = qauthz_list_new("channeltlsacl", 165 + QAUTHZ_LIST_POLICY_DENY, 166 + &error_abort); 166 167 wildcards = data->wildcards; 167 168 while (wildcards && *wildcards) { 168 - qemu_acl_append(acl, 0, *wildcards); 169 + qauthz_list_append_rule(auth, *wildcards, 170 + QAUTHZ_LIST_POLICY_ALLOW, 171 + QAUTHZ_LIST_FORMAT_GLOB, 172 + &error_abort); 169 173 wildcards++; 170 174 } 171 175 ··· 252 256 253 257 object_unref(OBJECT(serverChanSock)); 254 258 object_unref(OBJECT(clientChanSock)); 259 + 260 + object_unparent(OBJECT(auth)); 255 261 256 262 close(channel[0]); 257 263 close(channel[1]);
+16 -7
ui/vnc-auth-sasl.c
··· 24 24 25 25 #include "qemu/osdep.h" 26 26 #include "qapi/error.h" 27 + #include "authz/base.h" 27 28 #include "vnc.h" 28 29 #include "trace.h" 29 30 ··· 146 147 static int vnc_auth_sasl_check_access(VncState *vs) 147 148 { 148 149 const void *val; 149 - int err; 150 - int allow; 150 + int rv; 151 + Error *err = NULL; 152 + bool allow; 151 153 152 - err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val); 153 - if (err != SASL_OK) { 154 + rv = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val); 155 + if (rv != SASL_OK) { 154 156 trace_vnc_auth_fail(vs, vs->auth, "Cannot fetch SASL username", 155 - sasl_errstring(err, NULL, NULL)); 157 + sasl_errstring(rv, NULL, NULL)); 156 158 return -1; 157 159 } 158 160 if (val == NULL) { ··· 163 165 vs->sasl.username = g_strdup((const char*)val); 164 166 trace_vnc_auth_sasl_username(vs, vs->sasl.username); 165 167 166 - if (vs->vd->sasl.acl == NULL) { 168 + if (vs->vd->sasl.authzid == NULL) { 167 169 trace_vnc_auth_sasl_acl(vs, 1); 168 170 return 0; 169 171 } 170 172 171 - allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username); 173 + allow = qauthz_is_allowed_by_id(vs->vd->sasl.authzid, 174 + vs->sasl.username, &err); 175 + if (err) { 176 + trace_vnc_auth_fail(vs, vs->auth, "Error from authz", 177 + error_get_pretty(err)); 178 + error_free(err); 179 + return -1; 180 + } 172 181 173 182 trace_vnc_auth_sasl_acl(vs, allow); 174 183 return allow ? 0 : -1;
+3 -2
ui/vnc-auth-sasl.h
··· 30 30 typedef struct VncStateSASL VncStateSASL; 31 31 typedef struct VncDisplaySASL VncDisplaySASL; 32 32 33 - #include "qemu/acl.h" 34 33 #include "qemu/main-loop.h" 34 + #include "authz/base.h" 35 35 36 36 struct VncStateSASL { 37 37 sasl_conn_t *conn; ··· 60 60 }; 61 61 62 62 struct VncDisplaySASL { 63 - qemu_acl *acl; 63 + QAuthZ *authz; 64 + char *authzid; 64 65 }; 65 66 66 67 void vnc_sasl_client_cleanup(VncState *vs);
+1 -1
ui/vnc-auth-vencrypt.c
··· 109 109 tls = qio_channel_tls_new_server( 110 110 vs->ioc, 111 111 vs->vd->tlscreds, 112 - vs->vd->tlsaclname, 112 + vs->vd->tlsauthzid, 113 113 &err); 114 114 if (!tls) { 115 115 trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
+1 -1
ui/vnc-ws.c
··· 62 62 tls = qio_channel_tls_new_server( 63 63 vs->ioc, 64 64 vs->vd->tlscreds, 65 - vs->vd->tlsaclname, 65 + vs->vd->tlsauthzid, 66 66 &err); 67 67 if (!tls) { 68 68 VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
+25 -12
ui/vnc.c
··· 33 33 #include "qemu/option.h" 34 34 #include "qemu/sockets.h" 35 35 #include "qemu/timer.h" 36 - #include "qemu/acl.h" 36 + #include "authz/list.h" 37 37 #include "qemu/config-file.h" 38 38 #include "qapi/qapi-emit-events.h" 39 39 #include "qapi/qapi-events-ui.h" ··· 3229 3229 object_unparent(OBJECT(vd->tlscreds)); 3230 3230 vd->tlscreds = NULL; 3231 3231 } 3232 - g_free(vd->tlsaclname); 3233 - vd->tlsaclname = NULL; 3232 + if (vd->tlsauthz) { 3233 + object_unparent(OBJECT(vd->tlsauthz)); 3234 + vd->tlsauthz = NULL; 3235 + } 3236 + g_free(vd->tlsauthzid); 3237 + vd->tlsauthzid = NULL; 3234 3238 if (vd->lock_key_sync) { 3235 3239 qemu_remove_led_event_handler(vd->led); 3236 3240 vd->led = NULL; 3237 3241 } 3242 + #ifdef CONFIG_VNC_SASL 3243 + if (vd->sasl.authz) { 3244 + object_unparent(OBJECT(vd->sasl.authz)); 3245 + vd->sasl.authz = NULL; 3246 + } 3247 + g_free(vd->sasl.authzid); 3248 + vd->sasl.authzid = NULL; 3249 + #endif 3238 3250 } 3239 3251 3240 3252 int vnc_display_password(const char *id, const char *password) ··· 3887 3899 3888 3900 if (acl) { 3889 3901 if (strcmp(vd->id, "default") == 0) { 3890 - vd->tlsaclname = g_strdup("vnc.x509dname"); 3902 + vd->tlsauthzid = g_strdup("vnc.x509dname"); 3891 3903 } else { 3892 - vd->tlsaclname = g_strdup_printf("vnc.%s.x509dname", vd->id); 3904 + vd->tlsauthzid = g_strdup_printf("vnc.%s.x509dname", vd->id); 3893 3905 } 3894 - qemu_acl_init(vd->tlsaclname); 3906 + vd->tlsauthz = QAUTHZ(qauthz_list_new(vd->tlsauthzid, 3907 + QAUTHZ_LIST_POLICY_DENY, 3908 + &error_abort)); 3895 3909 } 3896 3910 #ifdef CONFIG_VNC_SASL 3897 3911 if (acl && sasl) { 3898 - char *aclname; 3899 - 3900 3912 if (strcmp(vd->id, "default") == 0) { 3901 - aclname = g_strdup("vnc.username"); 3913 + vd->sasl.authzid = g_strdup("vnc.username"); 3902 3914 } else { 3903 - aclname = g_strdup_printf("vnc.%s.username", vd->id); 3915 + vd->sasl.authzid = g_strdup_printf("vnc.%s.username", vd->id); 3904 3916 } 3905 - vd->sasl.acl = qemu_acl_init(aclname); 3906 - g_free(aclname); 3917 + vd->sasl.authz = QAUTHZ(qauthz_list_new(vd->sasl.authzid, 3918 + QAUTHZ_LIST_POLICY_DENY, 3919 + &error_abort)); 3907 3920 } 3908 3921 #endif 3909 3922
+3 -1
ui/vnc.h
··· 39 39 #include "io/channel-socket.h" 40 40 #include "io/channel-tls.h" 41 41 #include "io/net-listener.h" 42 + #include "authz/base.h" 42 43 #include <zlib.h> 43 44 44 45 #include "keymaps.h" ··· 178 179 bool lossy; 179 180 bool non_adaptive; 180 181 QCryptoTLSCreds *tlscreds; 181 - char *tlsaclname; 182 + QAuthZ *tlsauthz; 183 + char *tlsauthzid; 182 184 #ifdef CONFIG_VNC_SASL 183 185 VncDisplaySASL sasl; 184 186 #endif
-1
util/Makefile.objs
··· 20 20 util-obj-y += host-utils.o 21 21 util-obj-y += bitmap.o bitops.o hbitmap.o 22 22 util-obj-y += fifo8.o 23 - util-obj-y += acl.o 24 23 util-obj-y += cacheinfo.o 25 24 util-obj-y += error.o qemu-error.o 26 25 util-obj-y += id.o
-179
util/acl.c
··· 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/osdep.h" 27 - #include "qemu-common.h" 28 - #include "qemu/acl.h" 29 - 30 - #ifdef CONFIG_FNMATCH 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 = g_malloc(sizeof(*acl)); 60 - acl->aclname = g_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 = g_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 CONFIG_FNMATCH 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, *next_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_SAFE(entry, &acl->entries, next, next_entry) { 106 - QTAILQ_REMOVE(&acl->entries, entry, next); 107 - g_free(entry->match); 108 - g_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 = g_malloc(sizeof(*entry)); 121 - entry->match = g_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 *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 - QTAILQ_FOREACH(tmp, &acl->entries, next) { 146 - i++; 147 - if (i == index) { 148 - qemu_acl_entry *entry; 149 - entry = g_malloc(sizeof(*entry)); 150 - entry->match = g_strdup(match); 151 - entry->deny = deny; 152 - 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 - acl->nentries--; 173 - g_free(entry->match); 174 - g_free(entry); 175 - return i; 176 - } 177 - } 178 - return -1; 179 - }