diff --git a/configure.ac b/configure.ac index 1c601d277e..5acba9b1c9 100644 --- a/configure.ac +++ b/configure.ac @@ -1025,30 +1025,62 @@ CFLAGS="$old_cflags" LIBS="$old_libs" dnl GnuTLS library -GNUTLS_CFLAGS= -GNUTLS_LIBS= -GNUTLS_FOUND=no -if test -x "$PKG_CONFIG" ; then - PKG_CHECK_MODULES(GNUTLS, gnutls >= $GNUTLS_REQUIRED, - [GNUTLS_FOUND=yes], [GNUTLS_FOUND=no]) -fi -if test "$GNUTLS_FOUND" = "no"; then +AC_ARG_WITH([gnutls], + AC_HELP_STRING([--with-gnutls], [use GNUTLS for encryption @<:@default=check@:>@]), + [], + [with_gnutls=check]) + + +if test "x$with_gnutls" != "xno"; then + if test "x$with_gnutls" != "xyes" && test "x$with_gnutls" != "xcheck"; then + GNUTLS_CFLAGS="-I$with_gnutls/include" + GNUTLS_LIBS="-L$with_gnutls/lib" + fi fail=0 + old_cflags="$CFLAGS" old_libs="$LIBS" - AC_CHECK_HEADER([gnutls/gnutls.h], [], [fail=1]) - AC_CHECK_LIB([gnutls], [gnutls_handshake],[], [fail=1], [-lgcrypt]) + CFLAGS="$CFLAGS $GNUTLS_CFLAGS" + LIBS="$LIBS $GNUTLS_LIBS" - test $fail = 1 && - AC_MSG_ERROR([You must install the GnuTLS library in order to compile and run libvirt]) + GNUTLS_FOUND=no + if test -x "$PKG_CONFIG" ; then + PKG_CHECK_MODULES(GNUTLS, gnutls >= $GNUTLS_REQUIRED, + [GNUTLS_FOUND=yes], [GNUTLS_FOUND=no]) + fi + if test "$GNUTLS_FOUND" = "no"; then + fail=0 + AC_CHECK_HEADER([gnutls/gnutls.h], [], [fail=1]) + AC_CHECK_LIB([gnutls], [gnutls_handshake],[], [fail=1], [-lgcrypt]) + + test $fail = 0 && GNUTLS_FOUND=yes + + GNUTLS_LIBS="$GNUTLS_LIBS -lgnutls" + fi + if test "$GNUTLS_FOUND" = "no"; then + if test "$with_gnutls" = "check"; then + with_gnutls=no + GNUTLS_LIBS= + GNUTLS_CFLAGS= + else + AC_MSG_ERROR([You must install the GnuTLS library in order to compile and run libvirt]) + fi + else + dnl Not all versions of gnutls include -lgcrypt, and so we add + dnl it explicitly for the calls to gcry_control/check_version + GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt" + + with_gnutls=yes + fi - dnl Not all versions of gnutls include -lgcrypt, and so we add - dnl it explicitly for the calls to gcry_control/check_version - GNUTLS_LIBS="$LIBS -lgcrypt" LIBS="$old_libs" -else - GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt" + CFLAGS="$old_CFLAGS" fi +if test "x$with_gnutls" = "xyes" ; then + AC_DEFINE_UNQUOTED([HAVE_GNUTLS], 1, + [whether GNUTLS is available for encryption]) +fi +AM_CONDITIONAL([HAVE_GNUTLS], [test "x$with_gnutls" = "xyes"]) AC_SUBST([GNUTLS_CFLAGS]) AC_SUBST([GNUTLS_LIBS]) @@ -3168,7 +3200,11 @@ AC_MSG_NOTICE([ libssh2: $LIBSSH2_CFLAGS $LIBSSH2_LIBS]) else AC_MSG_NOTICE([ libssh2: no]) fi +if test "$with_gnutls" != "no" ; then AC_MSG_NOTICE([ gnutls: $GNUTLS_CFLAGS $GNUTLS_LIBS]) +else +AC_MSG_NOTICE([ gnutls: no]) +fi if test "$with_sasl" != "no" ; then AC_MSG_NOTICE([ sasl: $SASL_CFLAGS $SASL_LIBS]) else diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index fa4d129633..ff54af38b4 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -449,7 +449,9 @@ static int daemonSetupNetworking(virNetServerPtr srv, virNetServerServicePtr svc = NULL; virNetServerServicePtr svcRO = NULL; virNetServerServicePtr svcTCP = NULL; +#if HAVE_GNUTLS virNetServerServicePtr svcTLS = NULL; +#endif gid_t unix_sock_gid = 0; int unix_sock_ro_mask = 0; int unix_sock_rw_mask = 0; @@ -474,9 +476,11 @@ static int daemonSetupNetworking(virNetServerPtr srv, unix_sock_rw_mask, unix_sock_gid, config->auth_unix_rw, +#if HAVE_GNUTLS + NULL, +#endif false, - config->max_client_requests, - NULL))) + config->max_client_requests))) goto error; if (sock_path_ro) { VIR_DEBUG("Registering unix socket %s", sock_path_ro); @@ -484,9 +488,11 @@ static int daemonSetupNetworking(virNetServerPtr srv, unix_sock_ro_mask, unix_sock_gid, config->auth_unix_ro, +#if HAVE_GNUTLS + NULL, +#endif true, - config->max_client_requests, - NULL))) + config->max_client_requests))) goto error; } @@ -507,9 +513,11 @@ static int daemonSetupNetworking(virNetServerPtr srv, if (!(svcTCP = virNetServerServiceNewTCP(config->listen_addr, config->tcp_port, config->auth_tcp, +#if HAVE_GNUTLS + NULL, +#endif false, - config->max_client_requests, - NULL))) + config->max_client_requests))) goto error; if (virNetServerAddService(srv, svcTCP, @@ -517,6 +525,7 @@ static int daemonSetupNetworking(virNetServerPtr srv, goto error; } +#if HAVE_GNUTLS if (config->listen_tls) { virNetTLSContextPtr ctxt = NULL; @@ -546,9 +555,9 @@ static int daemonSetupNetworking(virNetServerPtr srv, virNetServerServiceNewTCP(config->listen_addr, config->tls_port, config->auth_tls, + ctxt, false, - config->max_client_requests, - ctxt))) { + config->max_client_requests))) { virObjectUnref(ctxt); goto error; } @@ -559,13 +568,23 @@ static int daemonSetupNetworking(virNetServerPtr srv, virObjectUnref(ctxt); } +#else + (void)privileged; + if (config->listen_tls) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This libvirtd build does not support TLS")); + goto error; + } +#endif } #if HAVE_SASL if (config->auth_unix_rw == REMOTE_AUTH_SASL || config->auth_unix_ro == REMOTE_AUTH_SASL || - config->auth_tcp == REMOTE_AUTH_SASL || - config->auth_tls == REMOTE_AUTH_SASL) { +# if HAVE_GNUTLS + config->auth_tls == REMOTE_AUTH_SASL || +# endif + config->auth_tcp == REMOTE_AUTH_SASL) { saslCtxt = virNetSASLContextNewServer( (const char *const*)config->sasl_allowed_username_list); if (!saslCtxt) @@ -576,7 +595,9 @@ static int daemonSetupNetworking(virNetServerPtr srv, return 0; error: +#if HAVE_GNUTLS virObjectUnref(svcTLS); +#endif virObjectUnref(svcTCP); virObjectUnref(svc); virObjectUnref(svcRO); diff --git a/daemon/remote.c b/daemon/remote.c index 8767c1884e..67fe33500a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2464,6 +2464,7 @@ remoteDispatchAuthSaslInit(virNetServerPtr server ATTRIBUTE_UNUSED, if (!sasl) goto authfail; +# if HAVE_GNUTLS /* Inform SASL that we've got an external SSF layer from TLS */ if (virNetServerClientHasTLSSession(client)) { int ssf; @@ -2477,6 +2478,7 @@ remoteDispatchAuthSaslInit(virNetServerPtr server ATTRIBUTE_UNUSED, if (virNetSASLSessionExtKeySize(sasl, ssf) < 0) goto authfail; } +# endif if (virNetServerClientIsSecure(client)) /* If we've got TLS or UNIX domain sock, we don't care about SSF */ diff --git a/src/Makefile.am b/src/Makefile.am index e8648ce04a..da571c7b97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1771,7 +1771,6 @@ libvirt_net_rpc_la_SOURCES = \ rpc/virnetmessage.h rpc/virnetmessage.c \ rpc/virnetprotocol.h rpc/virnetprotocol.c \ rpc/virnetsocket.h rpc/virnetsocket.c \ - rpc/virnettlscontext.h rpc/virnettlscontext.c \ rpc/virkeepaliveprotocol.h rpc/virkeepaliveprotocol.c \ rpc/virkeepalive.h rpc/virkeepalive.c if HAVE_LIBSSH2 @@ -1781,6 +1780,13 @@ else EXTRA_DIST += \ rpc/virnetsshsession.h rpc/virnetsshsession.c endif +if HAVE_GNUTLS +libvirt_net_rpc_la_SOURCES += \ + rpc/virnettlscontext.h rpc/virnettlscontext.c +else +EXTRA_DIST += \ + rpc/virnettlscontext.h rpc/virnettlscontext.c +endif if HAVE_SASL libvirt_net_rpc_la_SOURCES += \ rpc/virnetsaslcontext.h rpc/virnetsaslcontext.c diff --git a/src/libvirt.c b/src/libvirt.c index 83aeb23086..a783fa6df8 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -55,7 +55,9 @@ #include "configmake.h" #include "intprops.h" #include "virconf.h" -#include "rpc/virnettlscontext.h" +#if HAVE_GNUTLS +# include "rpc/virnettlscontext.h" +#endif #include "vircommand.h" #include "virrandom.h" #include "viruri.h" @@ -268,6 +270,8 @@ winsock_init(void) } #endif + +#ifdef HAVE_GNUTLS static int virTLSMutexInit(void **priv) { virMutexPtr lock = NULL; @@ -308,11 +312,11 @@ static int virTLSMutexUnlock(void **priv) static struct gcry_thread_cbs virTLSThreadImpl = { /* GCRY_THREAD_OPTION_VERSION was added in gcrypt 1.4.2 */ -#ifdef GCRY_THREAD_OPTION_VERSION +# ifdef GCRY_THREAD_OPTION_VERSION (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)), -#else +# else GCRY_THREAD_OPTION_PTHREAD, -#endif +# endif NULL, virTLSMutexInit, virTLSMutexDestroy, @@ -320,6 +324,7 @@ static struct gcry_thread_cbs virTLSThreadImpl = { virTLSMutexUnlock, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; +#endif /* Helper macros to implement VIR_DOMAIN_DEBUG using just C99. This * assumes you pass fewer than 15 arguments to VIR_DOMAIN_DEBUG, but @@ -403,12 +408,16 @@ virGlobalInit(void) virErrorInitialize() < 0) goto error; +#ifdef HAVE_GNUTLS gcry_control(GCRYCTL_SET_THREAD_CBS, &virTLSThreadImpl); gcry_check_version(NULL); +#endif virLogSetFromEnv(); +#ifdef HAVE_GNUTLS virNetTLSInit(); +#endif #if HAVE_LIBCURL curl_global_init(CURL_GLOBAL_DEFAULT); diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c index 7288f7a5be..ba42c00ff6 100644 --- a/src/locking/lock_daemon.c +++ b/src/locking/lock_daemon.c @@ -654,7 +654,11 @@ virLockDaemonSetupNetworkingSystemD(virNetServerPtr srv) /* Systemd passes FDs, starting immediately after stderr, * so the first FD we'll get is '3'. */ - if (!(svc = virNetServerServiceNewFD(3, 0, false, 1, NULL))) + if (!(svc = virNetServerServiceNewFD(3, 0, +#if HAVE_GNUTLS + NULL, +#endif + false, 1))) return -1; if (virNetServerAddService(srv, svc, NULL) < 0) { @@ -672,7 +676,11 @@ virLockDaemonSetupNetworkingNative(virNetServerPtr srv, const char *sock_path) VIR_DEBUG("Setting up networking natively"); - if (!(svc = virNetServerServiceNewUNIX(sock_path, 0700, 0, 0, false, 1, NULL))) + if (!(svc = virNetServerServiceNewUNIX(sock_path, 0700, 0, 0, +#if HAVE_GNUTLS + NULL, +#endif + false, 1))) return -1; if (virNetServerAddService(srv, svc, NULL) < 0) { diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 43cbad5aa6..3190d8a272 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -631,9 +631,11 @@ static int virLXCControllerSetupServer(virLXCControllerPtr ctrl) 0700, 0, 0, +#if HAVE_GNUTLS + NULL, +#endif false, - 5, - NULL))) + 5))) goto error; if (virNetServerAddService(ctrl->server, svc, NULL) < 0) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 9c7247bf76..e235677f96 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -23,8 +23,10 @@ #include #include -#include -#include +#ifdef HAVE_GNUTLS +# include +# include +#endif #include #include @@ -196,6 +198,7 @@ static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig) } +#ifdef HAVE_GNUTLS static char * qemuDomainExtractTLSSubject(const char *certdir) { @@ -254,7 +257,7 @@ error: VIR_FREE(pemdata); return NULL; } - +#endif static qemuMigrationCookieGraphicsPtr qemuMigrationCookieGraphicsAlloc(virQEMUDriverPtr driver, @@ -273,9 +276,11 @@ qemuMigrationCookieGraphicsAlloc(virQEMUDriverPtr driver, if (!listenAddr) listenAddr = driver->vncListen; +#ifdef HAVE_GNUTLS if (driver->vncTLS && !(mig->tlsSubject = qemuDomainExtractTLSSubject(driver->vncTLSx509certdir))) goto error; +#endif } else { mig->port = def->data.spice.port; if (driver->spiceTLS) @@ -286,9 +291,11 @@ qemuMigrationCookieGraphicsAlloc(virQEMUDriverPtr driver, if (!listenAddr) listenAddr = driver->spiceListen; +#ifdef HAVE_GNUTLS if (driver->spiceTLS && !(mig->tlsSubject = qemuDomainExtractTLSSubject(driver->spiceTLSx509certdir))) goto error; +#endif } if (!(mig->listen = strdup(listenAddr))) goto no_memory; @@ -297,7 +304,9 @@ qemuMigrationCookieGraphicsAlloc(virQEMUDriverPtr driver, no_memory: virReportOOMError(); +#ifdef HAVE_GNUTLS error: +#endif qemuMigrationCookieGraphicsFree(mig); return NULL; } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 65fcc5b9fa..43c118645a 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -80,7 +80,9 @@ struct private_data { int counter; /* Serial number for RPC */ +#ifdef HAVE_GNUTLS virNetTLSContextPtr tls; +#endif int is_secure; /* Secure if TLS or SASL or UNIX sockets */ char *type; /* Cached return from remoteType. */ @@ -596,12 +598,19 @@ doRemoteOpen(virConnectPtr conn, /* Connect to the remote service. */ switch (transport) { case trans_tls: +#ifdef HAVE_GNUTLS priv->tls = virNetTLSContextNewClientPath(pkipath, geteuid() != 0 ? true : false, sanity, verify); if (!priv->tls) goto failed; priv->is_secure = 1; +#else + (void)sanity; + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("GNUTLS support not available in this build")); + goto failed; +#endif /*FALLTHROUGH*/ case trans_tcp: @@ -609,11 +618,13 @@ doRemoteOpen(virConnectPtr conn, if (!priv->client) goto failed; +#ifdef HAVE_GNUTLS if (priv->tls) { VIR_DEBUG("Starting TLS session"); if (virNetClientSetTLSSession(priv->client, priv->tls) < 0) goto failed; } +#endif break; @@ -1001,8 +1012,10 @@ doRemoteClose(virConnectPtr conn, struct private_data *priv) (xdrproc_t) xdr_void, (char *) NULL) == -1) ret = -1; +#ifdef HAVE_GNUTLS virObjectUnref(priv->tls); priv->tls = NULL; +#endif virNetClientSetCloseCallback(priv->client, NULL, NULL, @@ -3880,6 +3893,7 @@ remoteAuthSASL(virConnectPtr conn, struct private_data *priv, saslcb))) goto cleanup; +# ifdef HAVE_GNUTLS /* Initialize some connection props we care about */ if (priv->tls) { if ((ssf = virNetClientGetTLSKeySize(priv->client)) < 0) @@ -3891,6 +3905,7 @@ remoteAuthSASL(virConnectPtr conn, struct private_data *priv, if (virNetSASLSessionExtKeySize(sasl, ssf) < 0) goto cleanup; } +# endif /* If we've got a secure channel (TLS or UNIX sock), we don't care about SSF */ /* If we're not secure, then forbid any anonymous or trivially crackable auth */ diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index bdceccfbb1..a79b79b330 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -70,7 +70,9 @@ struct _virNetClient { virNetSocketPtr sock; bool asyncIO; +#if HAVE_GNUTLS virNetTLSSessionPtr tls; +#endif char *hostname; virNetClientProgramPtr *programs; @@ -627,7 +629,9 @@ void virNetClientDispose(void *obj) if (client->sock) virNetSocketRemoveIOCallback(client->sock); virObjectUnref(client->sock); +#if HAVE_GNUTLS virObjectUnref(client->tls); +#endif #if HAVE_SASL virObjectUnref(client->sasl); #endif @@ -663,8 +667,10 @@ virNetClientCloseLocked(virNetClientPtr client) virObjectUnref(client->sock); client->sock = NULL; +#if HAVE_GNUTLS virObjectUnref(client->tls); client->tls = NULL; +#endif #if HAVE_SASL virObjectUnref(client->sasl); client->sasl = NULL; @@ -745,6 +751,7 @@ void virNetClientSetSASLSession(virNetClientPtr client, #endif +#if HAVE_GNUTLS int virNetClientSetTLSSession(virNetClientPtr client, virNetTLSContextPtr tls) { @@ -755,12 +762,12 @@ int virNetClientSetTLSSession(virNetClientPtr client, sigset_t oldmask, blockedsigs; sigemptyset(&blockedsigs); -#ifdef SIGWINCH +# ifdef SIGWINCH sigaddset(&blockedsigs, SIGWINCH); -#endif -#ifdef SIGCHLD +# endif +# ifdef SIGCHLD sigaddset(&blockedsigs, SIGCHLD); -#endif +# endif sigaddset(&blockedsigs, SIGPIPE); virNetClientLock(client); @@ -847,13 +854,16 @@ error: virNetClientUnlock(client); return -1; } +#endif bool virNetClientIsEncrypted(virNetClientPtr client) { bool ret = false; virNetClientLock(client); +#if HAVE_GNUTLS if (client->tls) ret = true; +#endif #if HAVE_SASL if (client->sasl) ret = true; @@ -956,6 +966,7 @@ const char *virNetClientRemoteAddrString(virNetClientPtr client) return virNetSocketRemoteAddrString(client->sock); } +#if HAVE_GNUTLS int virNetClientGetTLSKeySize(virNetClientPtr client) { int ret = 0; @@ -965,6 +976,7 @@ int virNetClientGetTLSKeySize(virNetClientPtr client) virNetClientUnlock(client); return ret; } +#endif static int virNetClientCallDispatchReply(virNetClientPtr client) diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h index 139cf32dad..d594addf44 100644 --- a/src/rpc/virnetclient.h +++ b/src/rpc/virnetclient.h @@ -23,7 +23,9 @@ #ifndef __VIR_NET_CLIENT_H__ # define __VIR_NET_CLIENT_H__ -# include "virnettlscontext.h" +# ifdef HAVE_GNUTLS +# include "virnettlscontext.h" +# endif # include "virnetmessage.h" # ifdef HAVE_SASL # include "virnetsaslcontext.h" @@ -107,8 +109,10 @@ void virNetClientSetSASLSession(virNetClientPtr client, virNetSASLSessionPtr sasl); # endif +# ifdef HAVE_GNUTLS int virNetClientSetTLSSession(virNetClientPtr client, virNetTLSContextPtr tls); +# endif bool virNetClientIsEncrypted(virNetClientPtr client); bool virNetClientIsOpen(virNetClientPtr client); @@ -116,7 +120,9 @@ bool virNetClientIsOpen(virNetClientPtr client); const char *virNetClientLocalAddrString(virNetClientPtr client); const char *virNetClientRemoteAddrString(virNetClientPtr client); +# ifdef HAVE_GNUTLS int virNetClientGetTLSKeySize(virNetClientPtr client); +# endif void virNetClientClose(virNetClientPtr client); diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 5674309873..b9df71b93f 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -98,7 +98,9 @@ struct _virNetServer { unsigned int quit :1; +#ifdef HAVE_GNUTLS virNetTLSContextPtr tls; +#endif unsigned int autoShutdownTimeout; size_t autoShutdownInhibitions; @@ -309,7 +311,9 @@ static int virNetServerDispatchNewClient(virNetServerServicePtr svc, virNetServerServiceGetAuth(svc), virNetServerServiceIsReadonly(svc), virNetServerServiceGetMaxRequests(svc), +#if HAVE_GNUTLS virNetServerServiceGetTLSContext(svc), +#endif srv->clientPrivNew, srv->clientPrivPreExecRestart, srv->clientPrivFree, @@ -1034,12 +1038,14 @@ no_memory: return -1; } +#if HAVE_GNUTLS int virNetServerSetTLSContext(virNetServerPtr srv, virNetTLSContextPtr tls) { srv->tls = virObjectRef(tls); return 0; } +#endif static void virNetServerAutoShutdownTimer(int timerid ATTRIBUTE_UNUSED, diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h index da7dc9e9b6..d906dd173c 100644 --- a/src/rpc/virnetserver.h +++ b/src/rpc/virnetserver.h @@ -26,7 +26,9 @@ # include -# include "virnettlscontext.h" +# ifdef HAVE_GNUTLS +# include "virnettlscontext.h" +# endif # include "virnetserverprogram.h" # include "virnetserverclient.h" # include "virnetserverservice.h" @@ -79,8 +81,10 @@ int virNetServerAddService(virNetServerPtr srv, int virNetServerAddProgram(virNetServerPtr srv, virNetServerProgramPtr prog); +# if HAVE_GNUTLS int virNetServerSetTLSContext(virNetServerPtr srv, virNetTLSContextPtr tls); +# endif void virNetServerUpdateServices(virNetServerPtr srv, bool enabled); diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index aefc5116f6..bf23d24030 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -66,8 +66,10 @@ struct _virNetServerClient int auth; bool readonly; char *identity; +#if HAVE_GNUTLS virNetTLSContextPtr tlsCtxt; virNetTLSSessionPtr tls; +#endif #if HAVE_SASL virNetSASLSessionPtr sasl; #endif @@ -147,13 +149,18 @@ virNetServerClientCalculateHandleMode(virNetServerClientPtr client) { VIR_DEBUG("tls=%p hs=%d, rx=%p tx=%p", +#ifdef HAVE_GNUTLS client->tls, client->tls ? virNetTLSSessionGetHandshakeStatus(client->tls) : -1, +#else + NULL, -1, +#endif client->rx, client->tx); if (!client->sock || client->wantClose) return 0; +#if HAVE_GNUTLS if (client->tls) { switch (virNetTLSSessionGetHandshakeStatus(client->tls)) { case VIR_NET_TLS_HANDSHAKE_RECVING: @@ -170,6 +177,7 @@ virNetServerClientCalculateHandleMode(virNetServerClientPtr client) { mode |= VIR_EVENT_HANDLE_WRITABLE; } } else { +#endif /* If there is a message on the rx queue, and * we're not in middle of a delayedClose, then * we're wanting more input */ @@ -180,7 +188,9 @@ virNetServerClientCalculateHandleMode(virNetServerClientPtr client) { then monitor for writability on socket */ if (client->tx) mode |= VIR_EVENT_HANDLE_WRITABLE; +#if HAVE_GNUTLS } +#endif VIR_DEBUG("mode=%o", mode); return mode; } @@ -287,6 +297,7 @@ void virNetServerClientRemoveFilter(virNetServerClientPtr client, } +#ifdef HAVE_GNUTLS /* Check the client's access. */ static int virNetServerClientCheckAccess(virNetServerClientPtr client) @@ -322,6 +333,8 @@ virNetServerClientCheckAccess(virNetServerClientPtr client) return 0; } +#endif + static void virNetServerClientSockTimerFunc(int timer, void *opaque) @@ -340,9 +353,11 @@ static void virNetServerClientSockTimerFunc(int timer, static virNetServerClientPtr virNetServerClientNewInternal(virNetSocketPtr sock, int auth, +#ifdef HAVE_GNUTLS + virNetTLSContextPtr tls, +#endif bool readonly, - size_t nrequests_max, - virNetTLSContextPtr tls) + size_t nrequests_max) { virNetServerClientPtr client; @@ -360,7 +375,9 @@ virNetServerClientNewInternal(virNetSocketPtr sock, client->sock = virObjectRef(sock); client->auth = auth; client->readonly = readonly; +#ifdef HAVE_GNUTLS client->tlsCtxt = virObjectRef(tls); +#endif client->nrequests_max = nrequests_max; client->sockTimer = virEventAddTimeout(-1, virNetServerClientSockTimerFunc, @@ -394,7 +411,9 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, int auth, bool readonly, size_t nrequests_max, +#ifdef HAVE_GNUTLS virNetTLSContextPtr tls, +#endif virNetServerClientPrivNew privNew, virNetServerClientPrivPreExecRestart privPreExecRestart, virFreeCallback privFree, @@ -402,9 +421,19 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, { virNetServerClientPtr client; - VIR_DEBUG("sock=%p auth=%d tls=%p", sock, auth, tls); + VIR_DEBUG("sock=%p auth=%d tls=%p", sock, auth, +#ifdef HAVE_GNUTLS + tls +#else + NULL +#endif + ); - if (!(client = virNetServerClientNewInternal(sock, auth, readonly, nrequests_max, tls))) + if (!(client = virNetServerClientNewInternal(sock, auth, +#ifdef HAVE_GNUTLS + tls, +#endif + readonly, nrequests_max))) return NULL; if (privNew) { @@ -470,9 +499,11 @@ virNetServerClientPtr virNetServerClientNewPostExecRestart(virJSONValuePtr objec if (!(client = virNetServerClientNewInternal(sock, auth, +#ifdef HAVE_GNUTLS + NULL, +#endif readonly, - nrequests_max, - NULL))) { + nrequests_max))) { virObjectUnref(sock); return NULL; } @@ -571,6 +602,7 @@ bool virNetServerClientGetReadonly(virNetServerClientPtr client) } +#ifdef HAVE_GNUTLS bool virNetServerClientHasTLSSession(virNetServerClientPtr client) { bool has; @@ -589,6 +621,7 @@ int virNetServerClientGetTLSKeySize(virNetServerClientPtr client) virNetServerClientUnlock(client); return size; } +#endif int virNetServerClientGetFD(virNetServerClientPtr client) { @@ -615,8 +648,10 @@ bool virNetServerClientIsSecure(virNetServerClientPtr client) { bool secure = false; virNetServerClientLock(client); +#if HAVE_GNUTLS if (client->tls) secure = true; +#endif #if HAVE_SASL if (client->sasl) secure = true; @@ -628,6 +663,7 @@ bool virNetServerClientIsSecure(virNetServerClientPtr client) } + #if HAVE_SASL void virNetServerClientSetSASLSession(virNetServerClientPtr client, virNetSASLSessionPtr sasl) @@ -730,8 +766,10 @@ void virNetServerClientDispose(void *obj) #endif if (client->sockTimer > 0) virEventRemoveTimeout(client->sockTimer); +#if HAVE_GNUTLS virObjectUnref(client->tls); virObjectUnref(client->tlsCtxt); +#endif virObjectUnref(client->sock); virNetServerClientUnlock(client); virMutexDestroy(&client->lock); @@ -784,10 +822,12 @@ void virNetServerClientClose(virNetServerClientPtr client) if (client->sock) virNetSocketRemoveIOCallback(client->sock); +#if HAVE_GNUTLS if (client->tls) { virObjectUnref(client->tls); client->tls = NULL; } +#endif client->wantClose = true; while (client->rx) { @@ -847,10 +887,13 @@ int virNetServerClientInit(virNetServerClientPtr client) { virNetServerClientLock(client); +#if HAVE_GNUTLS if (!client->tlsCtxt) { +#endif /* Plain socket, so prepare to read first message */ if (virNetServerClientRegisterEvent(client) < 0) goto error; +#if HAVE_GNUTLS } else { int ret; @@ -879,6 +922,7 @@ int virNetServerClientInit(virNetServerClientPtr client) goto error; } } +#endif virNetServerClientUnlock(client); return 0; @@ -1180,6 +1224,8 @@ virNetServerClientDispatchWrite(virNetServerClientPtr client) } } + +#if HAVE_GNUTLS static void virNetServerClientDispatchHandshake(virNetServerClientPtr client) { @@ -1202,6 +1248,7 @@ virNetServerClientDispatchHandshake(virNetServerClientPtr client) client->wantClose = true; } } +#endif static void virNetServerClientDispatchEvent(virNetSocketPtr sock, int events, void *opaque) @@ -1218,17 +1265,21 @@ virNetServerClientDispatchEvent(virNetSocketPtr sock, int events, void *opaque) if (events & (VIR_EVENT_HANDLE_WRITABLE | VIR_EVENT_HANDLE_READABLE)) { +#if HAVE_GNUTLS if (client->tls && virNetTLSSessionGetHandshakeStatus(client->tls) != VIR_NET_TLS_HANDSHAKE_COMPLETE) { virNetServerClientDispatchHandshake(client); } else { +#endif if (events & VIR_EVENT_HANDLE_WRITABLE) virNetServerClientDispatchWrite(client); if (events & VIR_EVENT_HANDLE_READABLE && client->rx) virNetServerClientDispatchRead(client); +#if HAVE_GNUTLS } +#endif } /* NB, will get HANGUP + READABLE at same time upon diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h index 65084e21f4..b11b9a9f47 100644 --- a/src/rpc/virnetserverclient.h +++ b/src/rpc/virnetserverclient.h @@ -52,7 +52,9 @@ virNetServerClientPtr virNetServerClientNew(virNetSocketPtr sock, int auth, bool readonly, size_t nrequests_max, +# ifdef HAVE_GNUTLS virNetTLSContextPtr tls, +# endif virNetServerClientPrivNew privNew, virNetServerClientPrivPreExecRestart privPreExecRestart, virFreeCallback privFree, @@ -76,8 +78,10 @@ void virNetServerClientRemoveFilter(virNetServerClientPtr client, int virNetServerClientGetAuth(virNetServerClientPtr client); bool virNetServerClientGetReadonly(virNetServerClientPtr client); +# ifdef HAVE_GNUTLS bool virNetServerClientHasTLSSession(virNetServerClientPtr client); int virNetServerClientGetTLSKeySize(virNetServerClientPtr client); +# endif # ifdef HAVE_SASL void virNetServerClientSetSASLSession(virNetServerClientPtr client, diff --git a/src/rpc/virnetserverservice.c b/src/rpc/virnetserverservice.c index 7d671f0ce8..61dd682aae 100644 --- a/src/rpc/virnetserverservice.c +++ b/src/rpc/virnetserverservice.c @@ -41,7 +41,9 @@ struct _virNetServerService { bool readonly; size_t nrequests_client_max; +#if HAVE_GNUTLS virNetTLSContextPtr tls; +#endif virNetServerServiceDispatchFunc dispatchFunc; void *dispatchOpaque; @@ -90,9 +92,11 @@ cleanup: virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename, const char *service, int auth, +#if HAVE_GNUTLS + virNetTLSContextPtr tls, +#endif bool readonly, - size_t nrequests_client_max, - virNetTLSContextPtr tls) + size_t nrequests_client_max) { virNetServerServicePtr svc; size_t i; @@ -106,7 +110,9 @@ virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename, svc->auth = auth; svc->readonly = readonly; svc->nrequests_client_max = nrequests_client_max; +#if HAVE_GNUTLS svc->tls = virObjectRef(tls); +#endif if (virNetSocketNewListenTCP(nodename, service, @@ -144,9 +150,11 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path, mode_t mask, gid_t grp, int auth, +#if HAVE_GNUTLS + virNetTLSContextPtr tls, +#endif bool readonly, - size_t nrequests_client_max, - virNetTLSContextPtr tls) + size_t nrequests_client_max) { virNetServerServicePtr svc; int i; @@ -160,7 +168,9 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path, svc->auth = auth; svc->readonly = readonly; svc->nrequests_client_max = nrequests_client_max; +#if HAVE_GNUTLS svc->tls = virObjectRef(tls); +#endif svc->nsocks = 1; if (VIR_ALLOC_N(svc->socks, svc->nsocks) < 0) @@ -202,9 +212,11 @@ error: virNetServerServicePtr virNetServerServiceNewFD(int fd, int auth, +#if HAVE_GNUTLS + virNetTLSContextPtr tls, +#endif bool readonly, - size_t nrequests_client_max, - virNetTLSContextPtr tls) + size_t nrequests_client_max) { virNetServerServicePtr svc; int i; @@ -218,7 +230,9 @@ virNetServerServicePtr virNetServerServiceNewFD(int fd, svc->auth = auth; svc->readonly = readonly; svc->nrequests_client_max = nrequests_client_max; +#if HAVE_GNUTLS svc->tls = virObjectRef(tls); +#endif svc->nsocks = 1; if (VIR_ALLOC_N(svc->socks, svc->nsocks) < 0) @@ -401,11 +415,12 @@ size_t virNetServerServiceGetMaxRequests(virNetServerServicePtr svc) return svc->nrequests_client_max; } +#if HAVE_GNUTLS virNetTLSContextPtr virNetServerServiceGetTLSContext(virNetServerServicePtr svc) { return svc->tls; } - +#endif void virNetServerServiceSetDispatcher(virNetServerServicePtr svc, virNetServerServiceDispatchFunc func, @@ -425,7 +440,9 @@ void virNetServerServiceDispose(void *obj) virObjectUnref(svc->socks[i]); VIR_FREE(svc->socks); +#if HAVE_GNUTLS virObjectUnref(svc->tls); +#endif } void virNetServerServiceToggle(virNetServerServicePtr svc, diff --git a/src/rpc/virnetserverservice.h b/src/rpc/virnetserverservice.h index 615b572c1a..934b8d3965 100644 --- a/src/rpc/virnetserverservice.h +++ b/src/rpc/virnetserverservice.h @@ -40,21 +40,27 @@ typedef int (*virNetServerServiceDispatchFunc)(virNetServerServicePtr svc, virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename, const char *service, int auth, +# if HAVE_GNUTLS + virNetTLSContextPtr tls, +# endif bool readonly, - size_t nrequests_client_max, - virNetTLSContextPtr tls); + size_t nrequests_client_max); virNetServerServicePtr virNetServerServiceNewUNIX(const char *path, mode_t mask, gid_t grp, int auth, +# if HAVE_GNUTLS + virNetTLSContextPtr tls, +# endif bool readonly, - size_t nrequests_client_max, - virNetTLSContextPtr tls); + size_t nrequests_client_max); virNetServerServicePtr virNetServerServiceNewFD(int fd, int auth, +# if HAVE_GNUTLS + virNetTLSContextPtr tls, +# endif bool readonly, - size_t nrequests_client_max, - virNetTLSContextPtr tls); + size_t nrequests_client_max); virNetServerServicePtr virNetServerServiceNewPostExecRestart(virJSONValuePtr object); @@ -65,7 +71,9 @@ int virNetServerServiceGetPort(virNetServerServicePtr svc); int virNetServerServiceGetAuth(virNetServerServicePtr svc); bool virNetServerServiceIsReadonly(virNetServerServicePtr svc); size_t virNetServerServiceGetMaxRequests(virNetServerServicePtr svc); +# ifdef HAVE_GNUTLS virNetTLSContextPtr virNetServerServiceGetTLSContext(virNetServerServicePtr svc); +# endif void virNetServerServiceSetDispatcher(virNetServerServicePtr svc, virNetServerServiceDispatchFunc func, diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index ef938924d7..a8179999ce 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -79,7 +79,9 @@ struct _virNetSocket { char *localAddrStr; char *remoteAddrStr; +#if HAVE_GNUTLS virNetTLSSessionPtr tlsSession; +#endif #if HAVE_SASL virNetSASLSessionPtr saslSession; @@ -948,11 +950,13 @@ virJSONValuePtr virNetSocketPreExecRestart(virNetSocketPtr sock) goto error; } #endif +#if HAVE_GNUTLS if (sock->tlsSession) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Unable to save socket state when TLS session is active")); goto error; } +#endif if (!(object = virJSONValueNewObject())) goto error; @@ -1011,10 +1015,12 @@ void virNetSocketDispose(void *obj) unlink(sock->localAddr.data.un.sun_path); #endif +#if HAVE_GNUTLS /* Make sure it can't send any more I/O during shutdown */ if (sock->tlsSession) virNetTLSSessionSetIOCallbacks(sock->tlsSession, NULL, NULL, NULL); virObjectUnref(sock->tlsSession); +#endif #if HAVE_SASL virObjectUnref(sock->saslSession); #endif @@ -1178,6 +1184,7 @@ const char *virNetSocketRemoteAddrString(virNetSocketPtr sock) } +#if HAVE_GNUTLS static ssize_t virNetSocketTLSSessionWrite(const char *buf, size_t len, void *opaque) @@ -1208,7 +1215,7 @@ void virNetSocketSetTLSSession(virNetSocketPtr sock, sock); virMutexUnlock(&sock->lock); } - +#endif #if HAVE_SASL void virNetSocketSetSASLSession(virNetSocketPtr sock, @@ -1280,13 +1287,17 @@ static ssize_t virNetSocketReadWire(virNetSocketPtr sock, char *buf, size_t len) #endif reread: +#if HAVE_GNUTLS if (sock->tlsSession && virNetTLSSessionGetHandshakeStatus(sock->tlsSession) == VIR_NET_TLS_HANDSHAKE_COMPLETE) { ret = virNetTLSSessionRead(sock->tlsSession, buf, len); } else { +#endif ret = read(sock->fd, buf, len); +#if HAVE_GNUTLS } +#endif if ((ret < 0) && (errno == EINTR)) goto reread; @@ -1335,13 +1346,17 @@ static ssize_t virNetSocketWriteWire(virNetSocketPtr sock, const char *buf, size #endif rewrite: +#if HAVE_GNUTLS if (sock->tlsSession && virNetTLSSessionGetHandshakeStatus(sock->tlsSession) == VIR_NET_TLS_HANDSHAKE_COMPLETE) { ret = virNetTLSSessionWrite(sock->tlsSession, buf, len); } else { +#endif ret = write(sock->fd, buf, len); +#if HAVE_GNUTLS } +#endif if (ret < 0) { if (errno == EINTR) diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h index 7016c09e30..ce15bb8cf6 100644 --- a/src/rpc/virnetsocket.h +++ b/src/rpc/virnetsocket.h @@ -26,7 +26,9 @@ # include "virsocketaddr.h" # include "vircommand.h" -# include "virnettlscontext.h" +# ifdef HAVE_GNUTLS +# include "virnettlscontext.h" +# endif # include "virobject.h" # ifdef HAVE_SASL # include "virnetsaslcontext.h" @@ -122,8 +124,10 @@ ssize_t virNetSocketWrite(virNetSocketPtr sock, const char *buf, size_t len); int virNetSocketSendFD(virNetSocketPtr sock, int fd); int virNetSocketRecvFD(virNetSocketPtr sock, int *fd); +# ifdef HAVE_GNUTLS void virNetSocketSetTLSSession(virNetSocketPtr sock, virNetTLSSessionPtr sess); +# endif # ifdef HAVE_SASL void virNetSocketSetSASLSession(virNetSocketPtr sock, diff --git a/tests/Makefile.am b/tests/Makefile.am index b603ea3128..9c7c6fb14e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -91,7 +91,7 @@ test_programs = virshtest sockettest \ commandtest seclabeltest \ virhashtest virnetmessagetest virnetsockettest \ viratomictest \ - utiltest virnettlscontexttest shunloadtest \ + utiltest shunloadtest \ virtimetest viruritest virkeyfiletest \ virauthconfigtest \ virbitmaptest \ @@ -100,6 +100,10 @@ test_programs = virshtest sockettest \ sysinfotest \ $(NULL) +if HAVE_GNUTLS +test_programs += virnettlscontexttest +endif + if WITH_SECDRIVER_SELINUX test_programs += securityselinuxtest endif @@ -526,6 +530,7 @@ virnetsockettest_SOURCES = \ virnetsockettest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS) virnetsockettest_LDADD = $(LDADDS) +if HAVE_GNUTLS virnettlscontexttest_SOURCES = \ virnettlscontexttest.c testutils.h testutils.c virnettlscontexttest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS) @@ -536,6 +541,10 @@ virnettlscontexttest_LDADD += -ltasn1 else EXTRA_DIST += pkix_asn1_tab.c endif +else +EXTRA_DIST += \ + virnettlscontexttest.c testutils.h testutils.c pkix_asn1_tab.c +endif virtimetest_SOURCES = \ virtimetest.c testutils.h testutils.c