From db46f3cefef204aa13a9078e2856417a9223c1a9 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 4 Apr 2012 13:09:09 +0100 Subject: [PATCH] Split libvirtd config file loading out into separate files To enable creation of unit tests, split the libvirtd config file loading code out into separate files. * daemon/libvirtd.c: Delete config loading code / structs * daemon/libvirtd-config.c, daemon/libvirtd-config.h: Config file loading APIs Signed-off-by: Daniel P. Berrange --- daemon/Makefile.am | 1 + daemon/libvirtd-config.c | 456 +++++++++++++++++++++++++++++++++++++ daemon/libvirtd-config.h | 91 ++++++++ daemon/libvirtd.c | 479 +-------------------------------------- 4 files changed, 549 insertions(+), 478 deletions(-) create mode 100644 daemon/libvirtd-config.c create mode 100644 daemon/libvirtd-config.h diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 391cd99955..5d9f5d75e5 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -21,6 +21,7 @@ DAEMON_GENERATED = \ DAEMON_SOURCES = \ libvirtd.c libvirtd.h \ + libvirtd-config.c libvirtd-config.h \ remote.c remote.h \ stream.c stream.h \ ../src/remote/remote_protocol.c \ diff --git a/daemon/libvirtd-config.c b/daemon/libvirtd-config.c new file mode 100644 index 0000000000..bfb70842f8 --- /dev/null +++ b/daemon/libvirtd-config.c @@ -0,0 +1,456 @@ +/* + * libvirtd.c: daemon start of day, guest process & i/o management + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * Copyright (C) 2006 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ + +#include + +#include "libvirtd-config.h" +#include "conf.h" +#include "memory.h" +#include "virterror_internal.h" +#include "logging.h" +#include "virnetserver.h" +#include "configmake.h" +#include "remote_protocol.h" +#include "remote_driver.h" + +#define VIR_FROM_THIS VIR_FROM_CONF + +/* Allocate an array of malloc'd strings from the config file, filename + * (used only in diagnostics), using handle "conf". Upon error, return -1 + * and free any allocated memory. Otherwise, save the array in *list_arg + * and return 0. + */ +static int +remoteConfigGetStringList(virConfPtr conf, const char *key, char ***list_arg, + const char *filename) +{ + char **list; + virConfValuePtr p = virConfGetValue (conf, key); + if (!p) + return 0; + + switch (p->type) { + case VIR_CONF_STRING: + if (VIR_ALLOC_N(list, 2) < 0) { + VIR_ERROR(_("failed to allocate memory for %s config list"), key); + return -1; + } + list[0] = strdup (p->str); + list[1] = NULL; + if (list[0] == NULL) { + VIR_ERROR(_("failed to allocate memory for %s config list value"), + key); + VIR_FREE(list); + return -1; + } + break; + + case VIR_CONF_LIST: { + int i, len = 0; + virConfValuePtr pp; + for (pp = p->list; pp; pp = pp->next) + len++; + if (VIR_ALLOC_N(list, 1+len) < 0) { + VIR_ERROR(_("failed to allocate memory for %s config list"), key); + return -1; + } + for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { + if (pp->type != VIR_CONF_STRING) { + VIR_ERROR(_("remoteReadConfigFile: %s: %s:" + " must be a string or list of strings"), + filename, key); + VIR_FREE(list); + return -1; + } + list[i] = strdup (pp->str); + if (list[i] == NULL) { + int j; + for (j = 0 ; j < i ; j++) + VIR_FREE(list[j]); + VIR_FREE(list); + VIR_ERROR(_("failed to allocate memory for %s config list value"), + key); + return -1; + } + + } + list[i] = NULL; + break; + } + + default: + VIR_ERROR(_("remoteReadConfigFile: %s: %s:" + " must be a string or list of strings"), + filename, key); + return -1; + } + + *list_arg = list; + return 0; +} + +/* A helper function used by each of the following macros. */ +static int +checkType (virConfValuePtr p, const char *filename, + const char *key, virConfType required_type) +{ + if (p->type != required_type) { + VIR_ERROR(_("remoteReadConfigFile: %s: %s: invalid type:" + " got %s; expected %s"), filename, key, + virConfTypeName (p->type), + virConfTypeName (required_type)); + return -1; + } + return 0; +} + +/* If there is no config data for the key, #var_name, then do nothing. + If there is valid data of type VIR_CONF_STRING, and strdup succeeds, + store the result in var_name. Otherwise, (i.e. invalid type, or strdup + failure), give a diagnostic and "goto" the cleanup-and-fail label. */ +#define GET_CONF_STR(conf, filename, var_name) \ + do { \ + virConfValuePtr p = virConfGetValue (conf, #var_name); \ + if (p) { \ + if (checkType (p, filename, #var_name, VIR_CONF_STRING) < 0) \ + goto error; \ + VIR_FREE(data->var_name); \ + if (!(data->var_name = strdup (p->str))) { \ + virReportOOMError(); \ + goto error; \ + } \ + } \ + } while (0) + +/* Like GET_CONF_STR, but for integral values. */ +#define GET_CONF_INT(conf, filename, var_name) \ + do { \ + virConfValuePtr p = virConfGetValue (conf, #var_name); \ + if (p) { \ + if (checkType (p, filename, #var_name, VIR_CONF_LONG) < 0) \ + goto error; \ + data->var_name = p->l; \ + } \ + } while (0) + + +static int remoteConfigGetAuth(virConfPtr conf, const char *key, int *auth, const char *filename) { + virConfValuePtr p; + + p = virConfGetValue (conf, key); + if (!p) + return 0; + + if (checkType (p, filename, key, VIR_CONF_STRING) < 0) + return -1; + + if (!p->str) + return 0; + + if (STREQ(p->str, "none")) { + *auth = VIR_NET_SERVER_SERVICE_AUTH_NONE; +#if HAVE_SASL + } else if (STREQ(p->str, "sasl")) { + *auth = VIR_NET_SERVER_SERVICE_AUTH_SASL; +#endif + } else if (STREQ(p->str, "polkit")) { + *auth = VIR_NET_SERVER_SERVICE_AUTH_POLKIT; + } else { + VIR_ERROR(_("remoteReadConfigFile: %s: %s: unsupported auth %s"), + filename, key, p->str); + return -1; + } + + return 0; +} + +int +daemonConfigFilePath(bool privileged, char **configfile) +{ + if (privileged) { + if (!(*configfile = strdup(SYSCONFDIR "/libvirt/libvirtd.conf"))) + goto no_memory; + } else { + char *userdir = NULL; + + if (!(userdir = virGetUserDirectory(geteuid()))) + goto error; + + if (virAsprintf(configfile, "%s/.libvirt/libvirtd.conf", userdir) < 0) { + VIR_FREE(userdir); + goto no_memory; + } + VIR_FREE(userdir); + } + + return 0; + +no_memory: + virReportOOMError(); +error: + return -1; +} + +struct daemonConfig* +daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) +{ + struct daemonConfig *data; + char *localhost; + int ret; + + if (VIR_ALLOC(data) < 0) { + virReportOOMError(); + return NULL; + } + + data->listen_tls = 1; + data->listen_tcp = 0; + + if (!(data->tls_port = strdup(LIBVIRTD_TLS_PORT))) + goto no_memory; + if (!(data->tcp_port = strdup(LIBVIRTD_TCP_PORT))) + goto no_memory; + + /* Only default to PolicyKit if running as root */ +#if HAVE_POLKIT + if (privileged) { + data->auth_unix_rw = REMOTE_AUTH_POLKIT; + data->auth_unix_ro = REMOTE_AUTH_POLKIT; + } else { +#endif + data->auth_unix_rw = REMOTE_AUTH_NONE; + data->auth_unix_ro = REMOTE_AUTH_NONE; +#if HAVE_POLKIT + } +#endif + + if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) + data->unix_sock_rw_perms = strdup("0777"); /* Allow world */ + else + data->unix_sock_rw_perms = strdup("0700"); /* Allow user only */ + data->unix_sock_ro_perms = strdup("0777"); /* Always allow world */ + if (!data->unix_sock_ro_perms || + !data->unix_sock_rw_perms) + goto no_memory; + +#if HAVE_SASL + data->auth_tcp = REMOTE_AUTH_SASL; +#else + data->auth_tcp = REMOTE_AUTH_NONE; +#endif + data->auth_tls = REMOTE_AUTH_NONE; + + data->mdns_adv = 0; + + data->min_workers = 5; + data->max_workers = 20; + data->max_clients = 20; + + data->prio_workers = 5; + + data->max_requests = 20; + data->max_client_requests = 5; + + data->log_buffer_size = 64; + + data->audit_level = 1; + data->audit_logging = 0; + + data->keepalive_interval = 5; + data->keepalive_count = 5; + data->keepalive_required = 0; + + localhost = virGetHostname(NULL); + if (localhost == NULL) { + /* we couldn't resolve the hostname; assume that we are + * running in disconnected operation, and report a less + * useful Avahi string + */ + ret = virAsprintf(&data->mdns_name, "Virtualization Host"); + } else { + char *tmp; + /* Extract the host part of the potentially FQDN */ + if ((tmp = strchr(localhost, '.'))) + *tmp = '\0'; + ret = virAsprintf(&data->mdns_name, "Virtualization Host %s", + localhost); + } + VIR_FREE(localhost); + if (ret < 0) + goto no_memory; + + return data; + +no_memory: + virReportOOMError(); + daemonConfigFree(data); + return NULL; +} + +void +daemonConfigFree(struct daemonConfig *data) +{ + char **tmp; + + if (!data) + return; + + VIR_FREE(data->listen_addr); + VIR_FREE(data->tls_port); + VIR_FREE(data->tcp_port); + + VIR_FREE(data->unix_sock_ro_perms); + VIR_FREE(data->unix_sock_rw_perms); + VIR_FREE(data->unix_sock_group); + VIR_FREE(data->unix_sock_dir); + VIR_FREE(data->mdns_name); + + tmp = data->tls_allowed_dn_list; + while (tmp && *tmp) { + VIR_FREE(*tmp); + tmp++; + } + VIR_FREE(data->tls_allowed_dn_list); + + tmp = data->sasl_allowed_username_list; + while (tmp && *tmp) { + VIR_FREE(*tmp); + tmp++; + } + VIR_FREE(data->sasl_allowed_username_list); + + VIR_FREE(data->key_file); + VIR_FREE(data->ca_file); + VIR_FREE(data->cert_file); + VIR_FREE(data->crl_file); + + VIR_FREE(data->log_filters); + VIR_FREE(data->log_outputs); + + VIR_FREE(data); +} + + +/* Read the config file if it exists. + * Only used in the remote case, hence the name. + */ +int +daemonConfigLoad(struct daemonConfig *data, + const char *filename, + bool allow_missing) +{ + virConfPtr conf; + + if (allow_missing && + access(filename, R_OK) == -1 && + errno == ENOENT) + return 0; + + conf = virConfReadFile (filename, 0); + if (!conf) + return -1; + + GET_CONF_INT (conf, filename, listen_tcp); + GET_CONF_INT (conf, filename, listen_tls); + GET_CONF_STR (conf, filename, tls_port); + GET_CONF_STR (conf, filename, tcp_port); + GET_CONF_STR (conf, filename, listen_addr); + + if (remoteConfigGetAuth(conf, "auth_unix_rw", &data->auth_unix_rw, filename) < 0) + goto error; +#if HAVE_POLKIT + /* Change default perms to be wide-open if PolicyKit is enabled. + * Admin can always override in config file + */ + if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) { + VIR_FREE(data->unix_sock_rw_perms); + if (!(data->unix_sock_rw_perms = strdup("0777"))) { + virReportOOMError(); + goto error; + } + } +#endif + if (remoteConfigGetAuth(conf, "auth_unix_ro", &data->auth_unix_ro, filename) < 0) + goto error; + if (remoteConfigGetAuth(conf, "auth_tcp", &data->auth_tcp, filename) < 0) + goto error; + if (remoteConfigGetAuth(conf, "auth_tls", &data->auth_tls, filename) < 0) + goto error; + + GET_CONF_STR (conf, filename, unix_sock_group); + GET_CONF_STR (conf, filename, unix_sock_ro_perms); + GET_CONF_STR (conf, filename, unix_sock_rw_perms); + + GET_CONF_STR (conf, filename, unix_sock_dir); + + GET_CONF_INT (conf, filename, mdns_adv); + GET_CONF_STR (conf, filename, mdns_name); + + GET_CONF_INT (conf, filename, tls_no_sanity_certificate); + GET_CONF_INT (conf, filename, tls_no_verify_certificate); + + GET_CONF_STR (conf, filename, key_file); + GET_CONF_STR (conf, filename, cert_file); + GET_CONF_STR (conf, filename, ca_file); + GET_CONF_STR (conf, filename, crl_file); + + if (remoteConfigGetStringList(conf, "tls_allowed_dn_list", + &data->tls_allowed_dn_list, filename) < 0) + goto error; + + + if (remoteConfigGetStringList(conf, "sasl_allowed_username_list", + &data->sasl_allowed_username_list, filename) < 0) + goto error; + + + GET_CONF_INT (conf, filename, min_workers); + GET_CONF_INT (conf, filename, max_workers); + GET_CONF_INT (conf, filename, max_clients); + + GET_CONF_INT (conf, filename, prio_workers); + + GET_CONF_INT (conf, filename, max_requests); + GET_CONF_INT (conf, filename, max_client_requests); + + GET_CONF_INT (conf, filename, audit_level); + GET_CONF_INT (conf, filename, audit_logging); + + GET_CONF_STR (conf, filename, host_uuid); + + GET_CONF_INT (conf, filename, log_level); + GET_CONF_STR (conf, filename, log_filters); + GET_CONF_STR (conf, filename, log_outputs); + GET_CONF_INT (conf, filename, log_buffer_size); + + GET_CONF_INT (conf, filename, keepalive_interval); + GET_CONF_INT (conf, filename, keepalive_count); + GET_CONF_INT (conf, filename, keepalive_required); + + virConfFree (conf); + return 0; + +error: + virConfFree (conf); + return -1; +} diff --git a/daemon/libvirtd-config.h b/daemon/libvirtd-config.h new file mode 100644 index 0000000000..00e8d1cc94 --- /dev/null +++ b/daemon/libvirtd-config.h @@ -0,0 +1,91 @@ +/* + * libvirtd.c: daemon start of day, guest process & i/o management + * + * Copyright (C) 2006-2012 Red Hat, Inc. + * Copyright (C) 2006 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Daniel P. Berrange + */ + +#ifndef __LIBVIRTD_CONFIG_H__ +# define __LIBVIRTD_CONFIG_H__ + +# include "internal.h" + +struct daemonConfig { + char *host_uuid; + + int listen_tls; + int listen_tcp; + char *listen_addr; + char *tls_port; + char *tcp_port; + + char *unix_sock_ro_perms; + char *unix_sock_rw_perms; + char *unix_sock_group; + char *unix_sock_dir; + + int auth_unix_rw; + int auth_unix_ro; + int auth_tcp; + int auth_tls; + + int mdns_adv; + char *mdns_name; + + int tls_no_verify_certificate; + int tls_no_sanity_certificate; + char **tls_allowed_dn_list; + char **sasl_allowed_username_list; + + char *key_file; + char *cert_file; + char *ca_file; + char *crl_file; + + int min_workers; + int max_workers; + int max_clients; + + int prio_workers; + + int max_requests; + int max_client_requests; + + int log_level; + char *log_filters; + char *log_outputs; + int log_buffer_size; + + int audit_level; + int audit_logging; + + int keepalive_interval; + unsigned int keepalive_count; + int keepalive_required; +}; + + +int daemonConfigFilePath(bool privileged, char **configfile); +struct daemonConfig* daemonConfigNew(bool privileged); +void daemonConfigFree(struct daemonConfig *data); +int daemonConfigLoad(struct daemonConfig *data, + const char *filename, + bool allow_missing); + +#endif /* __LIBVIRTD_CONFIG_H__ */ diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index af07e840bc..f1487772bd 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -40,11 +40,11 @@ #define VIR_FROM_THIS VIR_FROM_QEMU #include "libvirtd.h" +#include "libvirtd-config.h" #include "util.h" #include "uuid.h" #include "remote_driver.h" -#include "conf.h" #include "memory.h" #include "conf.h" #include "virnetlink.h" @@ -99,60 +99,6 @@ virNetSASLContextPtr saslCtxt = NULL; virNetServerProgramPtr remoteProgram = NULL; virNetServerProgramPtr qemuProgram = NULL; -struct daemonConfig { - char *host_uuid; - - int listen_tls; - int listen_tcp; - char *listen_addr; - char *tls_port; - char *tcp_port; - - char *unix_sock_ro_perms; - char *unix_sock_rw_perms; - char *unix_sock_group; - char *unix_sock_dir; - - int auth_unix_rw; - int auth_unix_ro; - int auth_tcp; - int auth_tls; - - int mdns_adv; - char *mdns_name; - - int tls_no_verify_certificate; - int tls_no_sanity_certificate; - char **tls_allowed_dn_list; - char **sasl_allowed_username_list; - - char *key_file; - char *cert_file; - char *ca_file; - char *crl_file; - - int min_workers; - int max_workers; - int max_clients; - - int prio_workers; - - int max_requests; - int max_client_requests; - - int log_level; - char *log_filters; - char *log_outputs; - int log_buffer_size; - - int audit_level; - int audit_logging; - - int keepalive_interval; - unsigned int keepalive_count; - int keepalive_required; -}; - enum { VIR_DAEMON_ERR_NONE = 0, VIR_DAEMON_ERR_PIDFILE, @@ -592,155 +538,6 @@ static int daemonShutdownCheck(virNetServerPtr srv ATTRIBUTE_UNUSED, } -/* Allocate an array of malloc'd strings from the config file, filename - * (used only in diagnostics), using handle "conf". Upon error, return -1 - * and free any allocated memory. Otherwise, save the array in *list_arg - * and return 0. - */ -static int -remoteConfigGetStringList(virConfPtr conf, const char *key, char ***list_arg, - const char *filename) -{ - char **list; - virConfValuePtr p = virConfGetValue (conf, key); - if (!p) - return 0; - - switch (p->type) { - case VIR_CONF_STRING: - if (VIR_ALLOC_N(list, 2) < 0) { - VIR_ERROR(_("failed to allocate memory for %s config list"), key); - return -1; - } - list[0] = strdup (p->str); - list[1] = NULL; - if (list[0] == NULL) { - VIR_ERROR(_("failed to allocate memory for %s config list value"), - key); - VIR_FREE(list); - return -1; - } - break; - - case VIR_CONF_LIST: { - int i, len = 0; - virConfValuePtr pp; - for (pp = p->list; pp; pp = pp->next) - len++; - if (VIR_ALLOC_N(list, 1+len) < 0) { - VIR_ERROR(_("failed to allocate memory for %s config list"), key); - return -1; - } - for (i = 0, pp = p->list; pp; ++i, pp = pp->next) { - if (pp->type != VIR_CONF_STRING) { - VIR_ERROR(_("remoteReadConfigFile: %s: %s:" - " must be a string or list of strings"), - filename, key); - VIR_FREE(list); - return -1; - } - list[i] = strdup (pp->str); - if (list[i] == NULL) { - int j; - for (j = 0 ; j < i ; j++) - VIR_FREE(list[j]); - VIR_FREE(list); - VIR_ERROR(_("failed to allocate memory for %s config list value"), - key); - return -1; - } - - } - list[i] = NULL; - break; - } - - default: - VIR_ERROR(_("remoteReadConfigFile: %s: %s:" - " must be a string or list of strings"), - filename, key); - return -1; - } - - *list_arg = list; - return 0; -} - -/* A helper function used by each of the following macros. */ -static int -checkType (virConfValuePtr p, const char *filename, - const char *key, virConfType required_type) -{ - if (p->type != required_type) { - VIR_ERROR(_("remoteReadConfigFile: %s: %s: invalid type:" - " got %s; expected %s"), filename, key, - virConfTypeName (p->type), - virConfTypeName (required_type)); - return -1; - } - return 0; -} - -/* If there is no config data for the key, #var_name, then do nothing. - If there is valid data of type VIR_CONF_STRING, and strdup succeeds, - store the result in var_name. Otherwise, (i.e. invalid type, or strdup - failure), give a diagnostic and "goto" the cleanup-and-fail label. */ -#define GET_CONF_STR(conf, filename, var_name) \ - do { \ - virConfValuePtr p = virConfGetValue (conf, #var_name); \ - if (p) { \ - if (checkType (p, filename, #var_name, VIR_CONF_STRING) < 0) \ - goto error; \ - VIR_FREE(data->var_name); \ - if (!(data->var_name = strdup (p->str))) { \ - virReportOOMError(); \ - goto error; \ - } \ - } \ - } while (0) - -/* Like GET_CONF_STR, but for integral values. */ -#define GET_CONF_INT(conf, filename, var_name) \ - do { \ - virConfValuePtr p = virConfGetValue (conf, #var_name); \ - if (p) { \ - if (checkType (p, filename, #var_name, VIR_CONF_LONG) < 0) \ - goto error; \ - data->var_name = p->l; \ - } \ - } while (0) - - -static int remoteConfigGetAuth(virConfPtr conf, const char *key, int *auth, const char *filename) { - virConfValuePtr p; - - p = virConfGetValue (conf, key); - if (!p) - return 0; - - if (checkType (p, filename, key, VIR_CONF_STRING) < 0) - return -1; - - if (!p->str) - return 0; - - if (STREQ(p->str, "none")) { - *auth = VIR_NET_SERVER_SERVICE_AUTH_NONE; -#if HAVE_SASL - } else if (STREQ(p->str, "sasl")) { - *auth = VIR_NET_SERVER_SERVICE_AUTH_SASL; -#endif - } else if (STREQ(p->str, "polkit")) { - *auth = VIR_NET_SERVER_SERVICE_AUTH_POLKIT; - } else { - VIR_ERROR(_("remoteReadConfigFile: %s: %s: unsupported auth %s"), - filename, key, p->str); - return -1; - } - - return 0; -} - /* * Set up the logging environment * By default if daemonized all errors go to the logfile libvirtd.log, @@ -830,280 +627,6 @@ error: } -static int -daemonConfigFilePath(bool privileged, char **configfile) -{ - if (privileged) { - if (!(*configfile = strdup(SYSCONFDIR "/libvirt/libvirtd.conf"))) - goto no_memory; - } else { - char *userdir = NULL; - - if (!(userdir = virGetUserDirectory(geteuid()))) - goto error; - - if (virAsprintf(configfile, "%s/.libvirt/libvirtd.conf", userdir) < 0) { - VIR_FREE(userdir); - goto no_memory; - } - VIR_FREE(userdir); - } - - return 0; - -no_memory: - virReportOOMError(); -error: - return -1; -} - -static void -daemonConfigFree(struct daemonConfig *data); - -static struct daemonConfig* -daemonConfigNew(bool privileged ATTRIBUTE_UNUSED) -{ - struct daemonConfig *data; - char *localhost; - int ret; - - if (VIR_ALLOC(data) < 0) { - virReportOOMError(); - return NULL; - } - - data->listen_tls = 1; - data->listen_tcp = 0; - - if (!(data->tls_port = strdup(LIBVIRTD_TLS_PORT))) - goto no_memory; - if (!(data->tcp_port = strdup(LIBVIRTD_TCP_PORT))) - goto no_memory; - - /* Only default to PolicyKit if running as root */ -#if HAVE_POLKIT - if (privileged) { - data->auth_unix_rw = REMOTE_AUTH_POLKIT; - data->auth_unix_ro = REMOTE_AUTH_POLKIT; - } else { -#endif - data->auth_unix_rw = REMOTE_AUTH_NONE; - data->auth_unix_ro = REMOTE_AUTH_NONE; -#if HAVE_POLKIT - } -#endif - - if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) - data->unix_sock_rw_perms = strdup("0777"); /* Allow world */ - else - data->unix_sock_rw_perms = strdup("0700"); /* Allow user only */ - data->unix_sock_ro_perms = strdup("0777"); /* Always allow world */ - if (!data->unix_sock_ro_perms || - !data->unix_sock_rw_perms) - goto no_memory; - -#if HAVE_SASL - data->auth_tcp = REMOTE_AUTH_SASL; -#else - data->auth_tcp = REMOTE_AUTH_NONE; -#endif - data->auth_tls = REMOTE_AUTH_NONE; - - data->mdns_adv = 0; - - data->min_workers = 5; - data->max_workers = 20; - data->max_clients = 20; - - data->prio_workers = 5; - - data->max_requests = 20; - data->max_client_requests = 5; - - data->log_buffer_size = 64; - - data->audit_level = 1; - data->audit_logging = 0; - - data->keepalive_interval = 5; - data->keepalive_count = 5; - data->keepalive_required = 0; - - localhost = virGetHostname(NULL); - if (localhost == NULL) { - /* we couldn't resolve the hostname; assume that we are - * running in disconnected operation, and report a less - * useful Avahi string - */ - ret = virAsprintf(&data->mdns_name, "Virtualization Host"); - } else { - char *tmp; - /* Extract the host part of the potentially FQDN */ - if ((tmp = strchr(localhost, '.'))) - *tmp = '\0'; - ret = virAsprintf(&data->mdns_name, "Virtualization Host %s", - localhost); - } - VIR_FREE(localhost); - if (ret < 0) - goto no_memory; - - return data; - -no_memory: - virReportOOMError(); - daemonConfigFree(data); - return NULL; -} - -static void -daemonConfigFree(struct daemonConfig *data) -{ - char **tmp; - - if (!data) - return; - - VIR_FREE(data->listen_addr); - VIR_FREE(data->tls_port); - VIR_FREE(data->tcp_port); - - VIR_FREE(data->unix_sock_ro_perms); - VIR_FREE(data->unix_sock_rw_perms); - VIR_FREE(data->unix_sock_group); - VIR_FREE(data->unix_sock_dir); - VIR_FREE(data->mdns_name); - - tmp = data->tls_allowed_dn_list; - while (tmp && *tmp) { - VIR_FREE(*tmp); - tmp++; - } - VIR_FREE(data->tls_allowed_dn_list); - - tmp = data->sasl_allowed_username_list; - while (tmp && *tmp) { - VIR_FREE(*tmp); - tmp++; - } - VIR_FREE(data->sasl_allowed_username_list); - - VIR_FREE(data->key_file); - VIR_FREE(data->ca_file); - VIR_FREE(data->cert_file); - VIR_FREE(data->crl_file); - - VIR_FREE(data->log_filters); - VIR_FREE(data->log_outputs); - - VIR_FREE(data); -} - - -/* Read the config file if it exists. - * Only used in the remote case, hence the name. - */ -static int -daemonConfigLoad(struct daemonConfig *data, - const char *filename, - bool allow_missing) -{ - virConfPtr conf; - - if (allow_missing && - access(filename, R_OK) == -1 && - errno == ENOENT) - return 0; - - conf = virConfReadFile (filename, 0); - if (!conf) - return -1; - - GET_CONF_INT (conf, filename, listen_tcp); - GET_CONF_INT (conf, filename, listen_tls); - GET_CONF_STR (conf, filename, tls_port); - GET_CONF_STR (conf, filename, tcp_port); - GET_CONF_STR (conf, filename, listen_addr); - - if (remoteConfigGetAuth(conf, "auth_unix_rw", &data->auth_unix_rw, filename) < 0) - goto error; -#if HAVE_POLKIT - /* Change default perms to be wide-open if PolicyKit is enabled. - * Admin can always override in config file - */ - if (data->auth_unix_rw == REMOTE_AUTH_POLKIT) { - VIR_FREE(data->unix_sock_rw_perms); - if (!(data->unix_sock_rw_perms = strdup("0777"))) { - virReportOOMError(); - goto error; - } - } -#endif - if (remoteConfigGetAuth(conf, "auth_unix_ro", &data->auth_unix_ro, filename) < 0) - goto error; - if (remoteConfigGetAuth(conf, "auth_tcp", &data->auth_tcp, filename) < 0) - goto error; - if (remoteConfigGetAuth(conf, "auth_tls", &data->auth_tls, filename) < 0) - goto error; - - GET_CONF_STR (conf, filename, unix_sock_group); - GET_CONF_STR (conf, filename, unix_sock_ro_perms); - GET_CONF_STR (conf, filename, unix_sock_rw_perms); - - GET_CONF_STR (conf, filename, unix_sock_dir); - - GET_CONF_INT (conf, filename, mdns_adv); - GET_CONF_STR (conf, filename, mdns_name); - - GET_CONF_INT (conf, filename, tls_no_sanity_certificate); - GET_CONF_INT (conf, filename, tls_no_verify_certificate); - - GET_CONF_STR (conf, filename, key_file); - GET_CONF_STR (conf, filename, cert_file); - GET_CONF_STR (conf, filename, ca_file); - GET_CONF_STR (conf, filename, crl_file); - - if (remoteConfigGetStringList(conf, "tls_allowed_dn_list", - &data->tls_allowed_dn_list, filename) < 0) - goto error; - - - if (remoteConfigGetStringList(conf, "sasl_allowed_username_list", - &data->sasl_allowed_username_list, filename) < 0) - goto error; - - - GET_CONF_INT (conf, filename, min_workers); - GET_CONF_INT (conf, filename, max_workers); - GET_CONF_INT (conf, filename, max_clients); - - GET_CONF_INT (conf, filename, prio_workers); - - GET_CONF_INT (conf, filename, max_requests); - GET_CONF_INT (conf, filename, max_client_requests); - - GET_CONF_INT (conf, filename, audit_level); - GET_CONF_INT (conf, filename, audit_logging); - - GET_CONF_STR (conf, filename, host_uuid); - - GET_CONF_INT (conf, filename, log_level); - GET_CONF_STR (conf, filename, log_filters); - GET_CONF_STR (conf, filename, log_outputs); - GET_CONF_INT (conf, filename, log_buffer_size); - - GET_CONF_INT (conf, filename, keepalive_interval); - GET_CONF_INT (conf, filename, keepalive_count); - GET_CONF_INT (conf, filename, keepalive_required); - - virConfFree (conf); - return 0; - -error: - virConfFree (conf); - return -1; -} - /* Display version information. */ static void daemonVersion(const char *argv0)