43fe83
From 59795aee1c0c049c5160457fcd91ca1150bff069 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <59795aee1c0c049c5160457fcd91ca1150bff069.1377873639.git.jdenemar@redhat.com>
43fe83
From: Eric Blake <eblake@redhat.com>
43fe83
Date: Mon, 12 Aug 2013 14:09:10 -0600
43fe83
Subject: [PATCH] build: avoid -lgcrypt with newer gnutls
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=951637
43fe83
43fe83
Newer gnutls uses nettle, rather than gcrypt, which is a lot nicer
43fe83
regarding initialization.  Yet we were unconditionally initializing
43fe83
gcrypt even when gnutls wouldn't be using it, and having two crypto
43fe83
libraries linked into libvirt.so is pointless, but mostly harmless
43fe83
(it doesn't crash, but does interfere with certification efforts).
43fe83
43fe83
There are three distinct version ranges to worry about when
43fe83
determining which crypto lib gnutls uses, per these gnutls mails:
43fe83
2.12: http://lists.gnu.org/archive/html/gnutls-devel/2011-03/msg00034.html
43fe83
3.0: http://lists.gnu.org/archive/html/gnutls-devel/2011-07/msg00035.html
43fe83
43fe83
If pkg-config can prove version numbers and/or list the crypto
43fe83
library used for static linking, we have our proof; if not, it
43fe83
is safer (even if pointless) to continue to use gcrypt ourselves.
43fe83
43fe83
* configure.ac (WITH_GNUTLS): Probe whether to add -lgcrypt, and
43fe83
define a witness WITH_GNUTLS_GCRYPT.
43fe83
* src/libvirt.c (virTLSMutexInit, virTLSMutexDestroy)
43fe83
(virTLSMutexLock, virTLSMutexUnlock, virTLSThreadImpl)
43fe83
(virGlobalInit): Honor the witness.
43fe83
* libvirt.spec.in (BuildRequires): Make gcrypt usage conditional,
43fe83
no longer needed in Fedora 19.
43fe83
43fe83
Signed-off-by: Eric Blake <eblake@redhat.com>
43fe83
(cherry picked from commit 6094b1ff1992e6c7c7b17a2e1a3ddbf29f7f6591)
43fe83
---
43fe83
 configure.ac    | 37 ++++++++++++++++++++++++++++++-------
43fe83
 libvirt.spec.in |  2 ++
43fe83
 src/libvirt.c   | 10 ++++++----
43fe83
 3 files changed, 38 insertions(+), 11 deletions(-)
43fe83
43fe83
diff --git a/configure.ac b/configure.ac
43fe83
index 084d864..917db6a 100644
43fe83
--- a/configure.ac
43fe83
+++ b/configure.ac
43fe83
@@ -1076,12 +1076,26 @@ if test "x$with_gnutls" != "xno"; then
43fe83
   LIBS="$LIBS $GNUTLS_LIBS"
43fe83
 
43fe83
   GNUTLS_FOUND=no
43fe83
+  GNUTLS_GCRYPT=unknown
43fe83
   if test -x "$PKG_CONFIG" ; then
43fe83
+    dnl Triple probe: gnutls < 2.12 only used gcrypt, gnutls >= 3.0 uses
43fe83
+    dnl only nettle, and versions in between had a configure option.
43fe83
+    dnl Our goal is to avoid gcrypt if we can prove gnutls uses nettle,
43fe83
+    dnl but it is a safe fallback to use gcrypt if we can't prove anything.
43fe83
+    if $PKG_CONFIG --exists 'gnutls >= 3.0'; then
43fe83
+      GNUTLS_GCRYPT=no
43fe83
+    elif $PKG_CONFIG --exists 'gnutls >= 2.12'; then
43fe83
+      GNUTLS_GCRYPT=probe
43fe83
+    else
43fe83
+      GNUTLS_GCRYPT=yes
43fe83
+    fi
43fe83
     PKG_CHECK_MODULES(GNUTLS, gnutls >= $GNUTLS_REQUIRED,
43fe83
       [GNUTLS_FOUND=yes], [GNUTLS_FOUND=no])
43fe83
   fi
43fe83
   if test "$GNUTLS_FOUND" = "no"; then
43fe83
+    dnl pkg-config couldn't help us, assume gcrypt is necessary
43fe83
     fail=0
43fe83
+    GNUTLS_GCRYPT=yes
43fe83
     AC_CHECK_HEADER([gnutls/gnutls.h], [], [fail=1])
43fe83
     AC_CHECK_LIB([gnutls], [gnutls_handshake],[], [fail=1], [-lgcrypt])
43fe83
 
43fe83
@@ -1098,13 +1112,22 @@ if test "x$with_gnutls" != "xno"; then
43fe83
       AC_MSG_ERROR([You must install the GnuTLS library in order to compile and run libvirt])
43fe83
     fi
43fe83
   else
43fe83
-    dnl Not all versions of gnutls include -lgcrypt, and so we add
43fe83
-    dnl it explicitly for the calls to gcry_control/check_version
43fe83
-    GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt"
43fe83
-
43fe83
-    dnl We're not using gcrypt deprecated features so define
43fe83
-    dnl GCRYPT_NO_DEPRECATED to avoid deprecated warnings
43fe83
-    GNUTLS_CFLAGS="$GNUTLS_CFLAGS -DGCRYPT_NO_DEPRECATED"
43fe83
+    dnl See comments above about when to use gcrypt.
43fe83
+    if test "$GNUTLS_GCRYPT" = probe; then
43fe83
+      case `$PKG_CONFIG --libs --static gnutls` in
43fe83
+        *gcrypt*) GNUTLS_GCRYPT=yes     ;;
43fe83
+        *nettle*) GNUTLS_GCRYPT=no      ;;
43fe83
+        *)        GNUTLS_GCRYPT=unknown ;;
43fe83
+      esac
43fe83
+    fi
43fe83
+    if test "$GNUTLS_GCRYPT" = yes || test "$GNUTLS_GCRYPT" = unknown; then
43fe83
+      GNUTLS_LIBS="$GNUTLS_LIBS -lgcrypt"
43fe83
+      dnl We're not using gcrypt deprecated features so define
43fe83
+      dnl GCRYPT_NO_DEPRECATED to avoid deprecated warnings
43fe83
+      GNUTLS_CFLAGS="$GNUTLS_CFLAGS -DGCRYPT_NO_DEPRECATED"
43fe83
+      AC_DEFINE_UNQUOTED([WITH_GNUTLS_GCRYPT], 1,
43fe83
+        [set to 1 if it is known or assumed that GNUTLS uses gcrypt])
43fe83
+    fi
43fe83
 
43fe83
     dnl gnutls 3.x moved some declarations to a new header
43fe83
     AC_CHECK_HEADERS([gnutls/crypto.h], [], [], [[
43fe83
diff --git a/src/libvirt.c b/src/libvirt.c
43fe83
index 8157488..66e8248 100644
43fe83
--- a/src/libvirt.c
43fe83
+++ b/src/libvirt.c
43fe83
@@ -55,7 +55,9 @@
43fe83
 #include "intprops.h"
43fe83
 #include "virconf.h"
43fe83
 #if WITH_GNUTLS
43fe83
-# include <gcrypt.h>
43fe83
+# if WITH_GNUTLS_GCRYPT
43fe83
+#  include <gcrypt.h>
43fe83
+# endif
43fe83
 # include "rpc/virnettlscontext.h"
43fe83
 #endif
43fe83
 #include "vircommand.h"
43fe83
@@ -270,7 +272,7 @@ winsock_init(void)
43fe83
 #endif
43fe83
 
43fe83
 
43fe83
-#ifdef WITH_GNUTLS
43fe83
+#ifdef WITH_GNUTLS_GCRYPT
43fe83
 static int virTLSMutexInit(void **priv)
43fe83
 {
43fe83
     virMutexPtr lock = NULL;
43fe83
@@ -323,7 +325,7 @@ static struct gcry_thread_cbs virTLSThreadImpl = {
43fe83
     virTLSMutexUnlock,
43fe83
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
43fe83
 };
43fe83
-#endif
43fe83
+#endif /* WITH_GNUTLS_GCRYPT */
43fe83
 
43fe83
 /* Helper macros to implement VIR_DOMAIN_DEBUG using just C99.  This
43fe83
  * assumes you pass fewer than 15 arguments to VIR_DOMAIN_DEBUG, but
43fe83
@@ -407,7 +409,7 @@ virGlobalInit(void)
43fe83
         virErrorInitialize() < 0)
43fe83
         goto error;
43fe83
 
43fe83
-#ifdef WITH_GNUTLS
43fe83
+#ifdef WITH_GNUTLS_GCRYPT
43fe83
     /*
43fe83
      * This sequence of API calls it copied exactly from
43fe83
      * gnutls 2.12.23 source lib/gcrypt/init.c, with
43fe83
-- 
43fe83
1.8.3.2
43fe83