GNU TLS and OpenSSL need to be told to be thread-safe #3461

Closed
michaelrsweet opened this Issue Dec 24, 2009 · 17 comments

Comments

Projects
None yet
1 participant
Collaborator

michaelrsweet commented Dec 24, 2009

Version: 1.4.2
CUPS.org User: twaugh.redhat

The gnutls library needs to be explicitly told to be thread-safe:

http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html

Original report:
https://bugzilla.redhat.com/show_bug.cgi?id=550302

Collaborator

michaelrsweet commented Dec 24, 2009

CUPS.org User: twaugh.redhat

Original report should be:
https://bugzilla.redhat.com/show_bug.cgi?id=544619

Collaborator

michaelrsweet commented Jan 14, 2010

CUPS.org User: mike

Hmm, need to work on this to make it work when configured without threading...

Collaborator

michaelrsweet commented Feb 15, 2010

CUPS.org User: twaugh.redhat

Here is another go at this patch.

  1. Don't initialize gcrypt threading in cupsd if threading is disabled in the build-time configuration.
  2. Explicitly add -lgcrypt to the libraries required for linking with gnutls (required with newer linkers).
Collaborator

michaelrsweet commented Apr 12, 2010

CUPS.org User: mike

Tim,

See the attached patches - I also implemented the OpenSSL threading stuff and moved things around so that only httpInitialize deals with the initialization (doing it in two places is probably not safe, and to be honest I'm not too happy with this implementation since another library or app might end up overriding this stuff...)

Collaborator

michaelrsweet commented Apr 12, 2010

CUPS.org User: mike

Also, I updated the gcrypt library stuff to look for the libraries using pkg-config and libgcrypt-config...

Collaborator

michaelrsweet commented May 5, 2010

CUPS.org User: mike

Fixed in Subversion repository.

Collaborator

michaelrsweet commented May 5, 2010

CUPS.org User: twaugh.redhat

Actually I've had to reluctantly back this patch out. Full explanation and analysis of the situation is here:

https://bugzilla.redhat.com/show_bug.cgi?id=553834#c43

Collaborator

michaelrsweet commented May 5, 2010

CUPS.org User: mike

Re-opening for the moment. I know that Firefox wants to be cross-platform/cross-distro, but to dlopen libcups when libcups is on every Linux distribution seems a bit crazy.

We clearly need something in here. Is there a way to have Linux dlclose run a cleanup function when an object is unloaded? I know that the Mac OS X version does...

Alternately, can we get Firefox to use the RTLD_NODELETE mode when they dlopen libcups? It isn't POSIX, but is available on Linux, Mac OS X, and Solaris for sure and would avoid this particular issue.

Clearly libgcrypt is not prepared for this kind of usage - if we can't resolve this I'm prepared to just disable support for GNUTLS if threading is enabled...

Collaborator

michaelrsweet commented May 5, 2010

CUPS.org User: twaugh.redhat

Yes, gcc understands attribute((constructor)) and attribute((destructor)) function attributes for just that purpose.

The problem is libgcrypt. It doesn't provide a way for a client to remove its accessor functions, or to query the existing ones prior to install its own in order to restore them on dlclose().

I think the solution is for the libgcrypt developers to fix that so that we can restore the default accessor functions in an attribute((destructor)) function in libcups.

Collaborator

michaelrsweet commented Jun 16, 2010

CUPS.org User: mike

OK, final patch (to be added to the previous ones for 1.4 and 1.5) which errors out if you try to build CUPS with GNU TLS and threading enabled.

Tracking improved GNU TLS changes with new STR #3605.

Collaborator

michaelrsweet commented Jun 24, 2010

CUPS.org User: mike

Submitted bugs to both OpenSSL and GNU TLS about their lack of built-in threading support...

Collaborator

michaelrsweet commented Jun 24, 2010

CUPS.org User: mike

The GNU TLS bug is here:

https://savannah.gnu.org/support/index.php?107409

I'll post a link to the OpenSSL bug when it becomes visible...

Collaborator

michaelrsweet commented Jun 24, 2010

"cups-gnutls-gcrypt-threads.patch":

diff -up cups-1.4.2/cups/http.c.gnutls-gcrypt-threads cups-1.4.2/cups/http.c
--- cups-1.4.2/cups/http.c.gnutls-gcrypt-threads 2009-12-21 16:50:58.931552118 +0000
+++ cups-1.4.2/cups/http.c 2009-12-21 16:51:15.047552357 +0000
@@ -1161,6 +1161,9 @@ httpHead(http_t http, / I - Conne
return (http_send(http, HTTP_HEAD, uri));
}

+#ifdef HAVE_GNUTLS
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+#endif

/*

  • 'httpInitialize()' - Initialize the HTTP interface library and set the
    @@ -1205,6 +1208,7 @@ httpInitialize(void)
    #endif /* WIN32 */

    #ifdef HAVE_GNUTLS

    • gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
      gnutls_global_init();
      #endif /* HAVE_GNUTLS */

diff -up cups-1.4.2/cups/http-private.h.gnutls-gcrypt-threads cups-1.4.2/cups/http-private.h
--- cups-1.4.2/cups/http-private.h.gnutls-gcrypt-threads 2009-04-07 16:48:14.000000000 +0100
+++ cups-1.4.2/cups/http-private.h 2009-12-21 16:51:15.049552624 +0000
@@ -98,6 +98,8 @@ extern BIO_METHOD *_httpBIOMethods(void)

  • The GNU TLS library is more of a "bare metal" SSL/TLS library...
    */

    include <gnutls/gnutls.h>

    +# include <gcrypt.h>
    +# include <pthread.h>

    typedef struct
    {
    diff -up cups-1.4.2/scheduler/server.c.gnutls-gcrypt-threads cups-1.4.2/scheduler/server.c
    --- cups-1.4.2/scheduler/server.c.gnutls-gcrypt-threads 2008-09-10 23:05:29.000000000 +0100
    +++ cups-1.4.2/scheduler/server.c 2009-12-21 16:51:15.048553044 +0000
    @@ -35,7 +35,9 @@
    */

    static int started = 0;

    +#if !defined(HAVE_LIBSSL) && defined(HAVE_GNUTLS)
    +GCRY_THREAD_OPTION_PTHREAD_IMPL;
    +#endif

    /*

  • 'cupsdStartServer()' - Start the server.
    @@ -75,7 +77,7 @@ cupsdStartServer(void)
    /*

    • Initialize the encryption libraries...
      */

    • gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
      gnutls_global_init();
      #endif /* HAVE_LIBSSL */
Collaborator

michaelrsweet commented Jun 24, 2010

"0001-Tell-gnutls-library-to-be-thread-safe-when-required.patch":

From fb6c23de1ad4f9f1cefa8b0c0fb4672b1ca899ee Mon Sep 17 00:00:00 2001
From: Tim Waugh twaugh@redhat.com
Date: Mon, 15 Feb 2010 10:10:10 +0000
Subject: [PATCH] Tell gnutls library to be thread-safe when required.

The gnutls library needs to be explicitly told to be thread-safe:

http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applicati
ons.html

For cupsd we only need to do this when threading is not disabled. For
libcups we always need to do it.

Fixes STR #3461.

config-scripts/cups-ssl.m4 | 2 +-
cups/http-private.h | 2 ++
cups/http.c | 7 +++++++
scheduler/server.c | 8 ++++++--
4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/config-scripts/cups-ssl.m4 b/config-scripts/cups-ssl.m4
index 64da6b8..259a1f8 100644
--- a/config-scripts/cups-ssl.m4
+++ b/config-scripts/cups-ssl.m4
@@ -61,7 +61,7 @@ if test x$enable_ssl != xno; then
if test "x${SSLLIBS}" = "x" -a "x${enable_gnutls}" != "xno" -a "x$PKGCONFIG" != x; then
AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config)
if $PKGCONFIG --exists gnutls; then

  •   SSLLIBS=`$PKGCONFIG --libs gnutls`
    
  •   SSLLIBS="`$PKGCONFIG --libs gnutls` -lgcrypt"
    SSLFLAGS=`$PKGCONFIG --cflags gnutls`
    AC_DEFINE(HAVE_SSL)
    AC_DEFINE(HAVE_GNUTLS)
    

    diff --git a/cups/http-private.h b/cups/http-private.h
    index adf34fb..1985daa 100644
    --- a/cups/http-private.h
    +++ b/cups/http-private.h
    @@ -98,6 +98,8 @@ extern BIO_METHOD *_httpBIOMethods(void);

    • The GNU TLS library is more of a "bare metal" SSL/TLS library...
      */

      include <gnutls/gnutls.h>

      +# include <gcrypt.h>
      +# include <pthread.h>

    typedef struct
    {
    diff --git a/cups/http.c b/cups/http.c
    index 012758b..19508d5 100644
    --- a/cups/http.c
    +++ b/cups/http.c
    @@ -1161,6 +1161,12 @@ httpHead(http_t http, / I - Connection to server */
    return (http_send(http, HTTP_HEAD, uri));
    }

+#ifdef HAVE_GNUTLS
+/* We always have to initialize threading in gcrypt here in libcups

  • * even if cupsd is configured without threading, because an

    • application using libcups may be using threads itself. */
      +GCRY_THREAD_OPTION_PTHREAD_IMPL;
      +#endif

    /*

    • 'httpInitialize()' - Initialize the HTTP interface library and set the
      @@ -1205,6 +1211,7 @@ httpInitialize(void)
      #endif /* WIN32 */

    #ifdef HAVE_GNUTLS

  • gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
    gnutls_global_init();
    #endif /* HAVE_GNUTLS */

diff --git a/scheduler/server.c b/scheduler/server.c
index a829f91..463f100 100644
--- a/scheduler/server.c
+++ b/scheduler/server.c
@@ -35,7 +35,9 @@
*/

static int started = 0;

+#if !defined(HAVE_LIBSSL) && defined(HAVE_GNUTLS) && defined(HAVE_PTHREAD_H)
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+#endif

/*

  • 'cupsdStartServer()' - Start the server.
    @@ -75,7 +77,9 @@ cupsdStartServer(void)
    /*
    • Initialize the encryption libraries...
      */

      +#ifdef HAVE_PTHREAD_H
    • gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
      +#endif /* HAVE_PTHREAD_H /
      gnutls_global_init();
      #endif /
      HAVE_LIBSSL */

1.6.6

Collaborator

michaelrsweet commented Jun 24, 2010

"str3461.patch":

Index: config-scripts/cups-ssl.m4

--- config-scripts/cups-ssl.m4 (revision 9099)
+++ config-scripts/cups-ssl.m4 (working copy)
@@ -61,13 +61,30 @@
dnl Then look for GNU TLS...
if test $have_ssl = 0 -a "x${enable_gnutls}" != "xno" -a "x$PKGCONFIG" != x; then
AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config)

  •   AC_PATH_PROG(LIBGCRYPTCONFIG,libgcrypt-config)
    
    if $PKGCONFIG --exists gnutls; then
    have_ssl=1
    SSLLIBS=$PKGCONFIG --libs gnutls
    SSLFLAGS=$PKGCONFIG --cflags gnutls
    AC_DEFINE(HAVE_SSL)
    AC_DEFINE(HAVE_GNUTLS)
  • elif "x$LIBGNUTLSCONFIG" != x; then
  •   have_ssl=1
    
  •   SSLLIBS=`$LIBGNUTLSCONFIG --libs`
    
  •   SSLFLAGS=`$LIBGNUTLSCONFIG --cflags`
    
  •   AC_DEFINE(HAVE_SSL)
    
  •   AC_DEFINE(HAVE_GNUTLS)
    
    fi
    +
  • if test $have_ssl = 1; then
  •        if $PKGCONFIG --exists gcrypt; then
    
  •       SSLLIBS="$SSLLIBS `$PKGCONFIG --libs gcrypt`"
    
  •       SSLFLAGS="$SSLFLAGS `$PKGCONFIG --cflags gcrypt`"
    
  •   elif "x$LIBGCRYPTCONFIG" != x; then
    
  •       SSLLIBS="$SSLLIBS `$LIBGCRYPTCONFIG --libs`"
    
  •       SSLFLAGS="$SSLFLAGS `$LIBGCRYPTCONFIG --cflags`"
    
  •   fi
    
  • fi
    fi

dnl Check for the OpenSSL library last...

Index: cups/http.c

--- cups/http.c (revision 9099)
+++ cups/http.c (working copy)
@@ -25,7 +25,7 @@

  •                      server.
    
  • httpClearCookie() - Clear the cookie value(s).
  • httpClearFields() - Clear HTTP request fields.
  • * httpClose() - Close an HTTP connection...
  • * httpClose() - Close an HTTP connection.
    • httpConnect() - Connect to a HTTP server.
    • httpConnectEncrypt() - Connect to a HTTP server using encryption.
    • _httpCreate() - Create an unconnected HTTP connection.
      @@ -64,7 +64,7 @@
    • _httpReadGNUTLS() - Read function for the GNU TLS library.
    • httpReconnect() - Reconnect to a HTTP server.
    • httpSetAuthString() - Set the current authorization string.
  • * httpSetCookie() - Set the cookie value(s)...
  • * httpSetCookie() - Set the cookie value(s).
    • httpSetExpect() - Set the Expect: header in a request.
    • httpSetField() - Set the value of an HTTP header.
    • httpSetLength() - Set the content-length and content-encoding.
      @@ -85,10 +85,12 @@
    • http_debug_hex() - Do a hex dump of a buffer.
    • http_field() - Return the field index for a field name.
    • http_read_ssl() - Read from a SSL/TLS connection.
  • * http_locking_cb() - Lock/unlock a thread's mutex.
    • http_send() - Send a request with all fields and the trailing
    •                      blank line.
      
    • http_setup_ssl() - Set up SSL/TLS support on a connection.
    • http_shutdown_ssl() - Shut down SSL/TLS on a connection.
  • * http_threadid_cb() - Return the current thread ID.
    • http_upgrade() - Force upgrade to TLS encryption.
    • http_write() - Write a buffer to a HTTP connection.
    • http_write_chunk() - Write a chunked buffer.
      @@ -142,6 +144,19 @@
      static void http_shutdown_ssl(http_t _http);
      static int http_upgrade(http_t *http);
      static int http_write_ssl(http_t *http, const char *buf, int len);
    +# ifdef HAVE_GNUTLS
    +# ifdef HAVE_PTHREAD_H
    +GCRY_THREAD_OPTION_PTHREAD_IMPL;
    +# endif /_ HAVE_PTHREAD_H _/
    +
    +# elif defined(HAVE_LIBSSL)
    +static cups_mutex_t *http_locks; / OpenSSL lock mutexes */
    +
    +static void http_locking_cb(int mode, int type, const char *file,
  •               int line);
    
    +static unsigned long http_threadid_cb(void);
    +# endif /* HAVE_GNUTLS /
    #endif /
    HAVE_SSL */

@@ -310,7 +325,7 @@

/*

  • * 'httpClose()' - Close an HTTP connection...

    • 'httpClose()' - Close an HTTP connection.
      */

    void
    @@ -1202,21 +1217,26 @@
    void
    httpInitialize(void)
    {

  • static int initialized = 0; /* Have we been called before? */
    +#ifdef WIN32

  • WSADATA winsockdata; /* WinSock data /
    +#endif /
    WIN32 */
    #ifdef HAVE_LIBSSL
    -# ifndef WIN32

  • struct timeval curtime; /* Current time in microseconds /
    -# endif /
    !WIN32 */

  • int i; /* Looping var */

  • unsigned char data[1024]; /* Seed data */

  • int i; /* Looping var */

  • unsigned char data[1024]; /* Seed data /
    #endif /
    HAVE_LIBSSL */

  • _cupsGlobalLock();
  • if (initialized)
  • {
  • _cupsGlobalUnlock();
  • return;
  • }

#ifdef WIN32

  • WSADATA winsockdata; /* WinSock data */
  • static int initialized = 0; /* Has WinSock been initialized? */
  • WSAStartup(MAKEWORD(1,1), &winsockdata);

  • if (!initialized)
  • WSAStartup(MAKEWORD(1,1), &winsockdata);
    #elif !defined(SO_NOSIGPIPE)
    /*
  • Ignore SIGPIPE signals...
    @@ -1224,6 +1244,7 @@

ifdef HAVE_SIGSET

sigset(SIGPIPE, SIG_IGN);
+

elif defined(HAVE_SIGACTION)

struct sigaction action; /* POSIX sigaction data */

@@ -1231,35 +1252,63 @@
memset(&action, 0, sizeof(action));
action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &action, NULL);
+

else

signal(SIGPIPE, SIG_IGN);

endif /* !SO_NOSIGPIPE _/

#endif /_ WIN32 */

#ifdef HAVE_GNUTLS

  • /*
  • * Make sure we handle threading properly...
  • */

+# ifdef HAVE_PTHREAD_H

  • gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
    +# endif /* HAVE_PTHREAD_H */
  • /*
  • * Initialize GNU TLS...
  • _/

gnutls_global_init();
-#endif /_ HAVE_GNUTLS */

-#ifdef HAVE_LIBSSL
+#elif defined(HAVE_LIBSSL)

  • /*
  • * Initialize OpenSSL...
  • */

SSL_load_error_strings();
SSL_library_init();

/*

  • * Set the threading callbacks...
  • */
  • http_locks = calloc(CRYPTO_num_locks(), sizeof(_cups_mutex_t));
    +# ifdef HAVE_PTHREAD_H
  • for (i = 0; i < CRYPTO_num_locks(); i ++)
  • pthread_mutex_init(http_locks + i, NULL);
    +# endif /* HAVE_PTHREAD_H */
  • CRYPTO_set_id_callback(http_threadid_cb);
  • CRYPTO_set_locking_callback(http_locking_cb);
  • /*
    • Using the current time is a dubious random seed, but on some systems
    • it is the best we can do (on others, this seed isn't even used...)
      */

-# ifdef WIN32
-# else

  • gettimeofday(&curtime, NULL);
  • srand(curtime.tv_sec + curtime.tv_usec);
    -# endif /* WIN32 */
  • CUPS_SRAND(time(NULL));

for (i = 0; i < sizeof(data); i ++)

  • data[i] = rand();
  • data[i] = CUPS_RAND();

RAND_seed(data, sizeof(data));
-#endif /* HAVE_LIBSSL /
+#endif /
HAVE_GNUTLS */
+

  • initialized = 1;
  • _cupsGlobalUnlock();
    }

@@ -2017,7 +2066,7 @@

/*

  • * 'httpSetCookie()' - Set the cookie value(s)...
  • * 'httpSetCookie()' - Set the cookie value(s).
    *
    • @SInCE CUPS 1.1.19/Mac OS X 10.3@
      /
      @@ -3003,7 +3052,26 @@
      #endif /
      HAVE_SSL */

+#ifdef HAVE_LIBSSL
/*

  • * 'http_locking_cb()' - Lock/unlock a thread's mutex.
  • /
    +
    +static void
    +http_locking_cb(int mode, /
    I - Lock mode */
  •   int        type,    /\* I - Lock type */
    
  •   const char _file,   /_ I - Source file */
    
  •   int        line)    /\* I - Line number */
    
    +{
  • if (mode & CRYPTO_LOCK)
  • _cupsMutexLock(http_locks + type);
  • else
  • _cupsMutexUnlock(http_locks + type);
    +}
    +#endif /* HAVE_LIBSSL _/

+/_

  • 'http_send()' - Send a request with all fields and the trailing blank line.
    */

@@ -3374,6 +3442,23 @@
#endif /* HAVE_SSL */

+#ifdef HAVE_LIBSSL
+/*

  • * 'http_threadid_cb()' - Return the current thread ID.
  • /
    +
    +static unsigned long /
    O - Thread ID */
    +http_threadid_cb(void)
    +{
    +# ifdef HAVE_PTHREAD_H
  • return ((unsigned long)pthread_self());
    +# else
  • return (0);
    +# endif /* HAVE_PTHREAD_H /
    +}
    +#endif /
    HAVE_LIBSSL _/

#ifdef HAVE_SSL
/_

  • 'http_upgrade()' - Force upgrade to TLS encryption.
    Index: cups/http-private.h

    --- cups/http-private.h (revision 9099)
    +++ cups/http-private.h (working copy)
    @@ -99,6 +99,7 @@
  • The GNU TLS library is more of a "bare metal" SSL/TLS library...
    */

    include <gnutls/gnutls.h>

    +# include <gcrypt.h>

typedef struct
{

Index: scheduler/server.c

--- scheduler/server.c (revision 9099)
+++ scheduler/server.c (working copy)
@@ -1,9 +1,9 @@
/*

  • "$Id$"
    *
  • * Server start/stop routines for the Common UNIX Printing System (CUPS).
  • * Server start/stop routines for the CUPS scheduler.
    *
  • * Copyright 2007-2008 by Apple Inc.
  • * Copyright 2007-2010 by Apple Inc.
    • Copyright 1997-2006 by Easy Software Products, all rights reserved.
    • These coded instructions, statements, and computer programs are the
      @@ -44,42 +44,7 @@
      void
      cupsdStartServer(void)
      {
      -#ifdef HAVE_LIBSSL
  • int i; /* Looping var */
  • struct timeval curtime; /* Current time in microseconds */
  • unsigned char data[1024]; /* Seed data /
    -#endif /
    HAVE_LIBSSL _/

-#ifdef HAVE_LIBSSL
/_

  • * Initialize the encryption libraries...

- */

  • SSL_library_init();

- SSL_load_error_strings();

  • /*
  • * Using the current time is a dubious random seed, but on some systems
  • * it is the best we can do (on others, this seed isn't even used...)

- */

  • gettimeofday(&curtime, NULL);

- srand(curtime.tv_sec + curtime.tv_usec);

  • for (i = 0; i < sizeof(data); i ++)

- data[i] = rand(); /* Yes, this is a poor source of random data... */

  • RAND_seed(&data, sizeof(data));
    -#elif defined(HAVE_GNUTLS)
  • /*
  • * Initialize the encryption libraries...

- */

  • gnutls_global_init();
    -#endif /* HAVE_LIBSSL */
  • /*
    • Create the default security profile...
      */

Index: scheduler/main.c

--- scheduler/main.c (revision 9099)
+++ scheduler/main.c (working copy)
@@ -1,7 +1,7 @@
/*

  • "$Id$"
    *
    • * Scheduler main loop for the Common UNIX Printing System (CUPS).
    • * Main loop for the CUPS scheduler.
      *
  • Copyright 2007-2010 by Apple Inc.
  • Copyright 1997-2007 by Easy Software Products, all rights reserved.
    @@ -527,6 +527,8 @@
  • Startup the server...
    */
  • httpInitialize();

cupsdStartServer();

/*

Collaborator

michaelrsweet commented Jun 24, 2010

"str3461-1.4.patch":

Index: config-scripts/cups-ssl.m4

--- config-scripts/cups-ssl.m4 (revision 9101)
+++ config-scripts/cups-ssl.m4 (working copy)
@@ -1,9 +1,9 @@
dnl
dnl "$Id$"
dnl
-dnl OpenSSL/GNUTLS stuff for the Common UNIX Printing System (CUPS).
+dnl OpenSSL/GNUTLS stuff for CUPS.
dnl
-dnl Copyright 2007-2009 by Apple Inc.
+dnl Copyright 2007-2010 by Apple Inc.
dnl Copyright 1997-2007 by Easy Software Products, all rights reserved.
dnl
dnl These coded instructions, statements, and computer programs are the
@@ -26,13 +26,15 @@

SSLFLAGS=""
SSLLIBS=""
+have_ssl=0

if test x$enable_ssl != xno; then
dnl Look for CDSA...

  • if test "x${SSLLIBS}" = "x" -a "x${enable_cdsassl}" != "xno"; then
  • if test $have_ssl = 0 -a "x${enable_cdsassl}" != "xno"; then
    if test $uname = Darwin; then
    AC_CHECK_HEADER(Security/SecureTransport.h, [
  •   SSLLIBS="-framework CoreFoundation -framework Security"
    
  •       have_ssl=1
    
  •   SSLLIBS="-framework Security"
    AC_DEFINE(HAVE_SSL)
    AC_DEFINE(HAVE_CDSASSL)
    

@@ -58,18 +60,36 @@
fi

 dnl Then look for GNU TLS...
  • if test "x${SSLLIBS}" = "x" -a "x${enable_gnutls}" != "xno" -a "x$PKGCONFIG" != x; then
  • if test $have_ssl = 0 -a "x${enable_gnutls}" != "xno" -a "x$PKGCONFIG" != x; then
    AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config)
  •   AC_PATH_PROG(LIBGCRYPTCONFIG,libgcrypt-config)
    
    if $PKGCONFIG --exists gnutls; then
  •   have_ssl=1
    SSLLIBS=`$PKGCONFIG --libs gnutls`
    SSLFLAGS=`$PKGCONFIG --cflags gnutls`
    AC_DEFINE(HAVE_SSL)
    AC_DEFINE(HAVE_GNUTLS)
    
  • elif "x$LIBGNUTLSCONFIG" != x; then
  •   have_ssl=1
    
  •   SSLLIBS=`$LIBGNUTLSCONFIG --libs`
    
  •   SSLFLAGS=`$LIBGNUTLSCONFIG --cflags`
    
  •   AC_DEFINE(HAVE_SSL)
    
  •   AC_DEFINE(HAVE_GNUTLS)
    
    fi
    +
  • if test $have_ssl = 1; then
  •        if $PKGCONFIG --exists gcrypt; then
    
  •       SSLLIBS="$SSLLIBS `$PKGCONFIG --libs gcrypt`"
    
  •       SSLFLAGS="$SSLFLAGS `$PKGCONFIG --cflags gcrypt`"
    
  •   elif "x$LIBGCRYPTCONFIG" != x; then
    
  •       SSLLIBS="$SSLLIBS `$LIBGCRYPTCONFIG --libs`"
    
  •       SSLFLAGS="$SSLFLAGS `$LIBGCRYPTCONFIG --cflags`"
    
  •   fi
    
  • fi
    fi

dnl Check for the OpenSSL library last...

  • if test "x${SSLLIBS}" = "x" -a "x${enable_openssl}" != "xno"; then
  • if test $have_ssl = 0 -a "x${enable_openssl}" != "xno"; then
    AC_CHECK_HEADER(openssl/ssl.h,
    dnl Save the current libraries so the crypto stuff isn't always
    dnl included...
    @@ -87,7 +107,8 @@
    "-lcrypto -lRSAglue -lrsaref"
    do
    AC_CHECK_LIB(ssl,SSL_new,
  •       [SSLFLAGS="-DOPENSSL_DISABLE_OLD_DES_SUPPORT"
    
  •       [have_ssl=1
    
  •        SSLFLAGS="-DOPENSSL_DISABLE_OLD_DES_SUPPORT"
         SSLLIBS="-lssl $libcrypto"
         AC_DEFINE(HAVE_SSL)
         AC_DEFINE(HAVE_LIBSSL)],,
    
    @@ -102,7 +123,7 @@
    fi
    fi

-if test "x$SSLLIBS" != x; then
+if test $have_ssl = 1; then
AC_MSG_RESULT([ Using SSLLIBS="$SSLLIBS"])
AC_MSG_RESULT([ Using SSLFLAGS="$SSLFLAGS"])
fi
@@ -113,7 +134,6 @@
EXPORT_SSLLIBS="$SSLLIBS"
AC_SUBST(EXPORT_SSLLIBS)

dnl
dnl End of "$Id$".
dnl

Index: cups/http.c

--- cups/http.c (revision 9101)
+++ cups/http.c (working copy)
@@ -1,9 +1,9 @@
/*

  • "$Id$"
    *
    • * HTTP routines for the Common UNIX Printing System (CUPS).
    • * HTTP routines for CUPS.
      *
    • * Copyright 2007-2009 by Apple Inc.
    • * Copyright 2007-2010 by Apple Inc.
  • Copyright 1997-2007 by Easy Software Products, all rights reserved.
  • This file contains Kerberos support code, copyright 2006 by
    @@ -25,7 +25,8 @@
  •                      server.
    
  • httpClearCookie() - Clear the cookie value(s).
  • httpClearFields() - Clear HTTP request fields.
  • * httpClose() - Close an HTTP connection...
  • * httpClose() - Close an HTTP connection.
  • * httpConnect() - Connect to a HTTP server.
  • httpConnectEncrypt() - Connect to a HTTP server using encryption.
  • _httpCreate() - Create an unconnected HTTP connection.
  • httpDelete() - Send a DELETE request to the server.
    @@ -61,7 +62,7 @@
  • _httpReadGNUTLS() - Read function for the GNU TLS library.
  • httpReconnect() - Reconnect to a HTTP server.
  • httpSetAuthString() - Set the current authorization string.
  • * httpSetCookie() - Set the cookie value(s)...
  • * httpSetCookie() - Set the cookie value(s).
  • httpSetExpect() - Set the Expect: header in a request.
  • httpSetField() - Set the value of an HTTP header.
  • httpSetLength() - Set the content-length and content-encoding.
    @@ -82,10 +83,12 @@
  • http_debug_hex() - Do a hex dump of a buffer.
  • http_field() - Return the field index for a field name.
  • http_read_ssl() - Read from a SSL/TLS connection.
  • * http_locking_cb() - Lock/unlock a thread's mutex.
  • http_send() - Send a request with all fields and the trailing
  •                      blank line.
    
  • http_setup_ssl() - Set up SSL/TLS support on a connection.
  • http_shutdown_ssl() - Shut down SSL/TLS on a connection.
  • * http_threadid_cb() - Return the current thread ID.
  • http_upgrade() - Force upgrade to TLS encryption.
  • http_write() - Write a buffer to a HTTP connection.
  • http_write_chunk() - Write a chunked buffer.
    @@ -143,6 +146,19 @@
    static void http_shutdown_ssl(http_t _http);
    static int http_upgrade(http_t *http);
    static int http_write_ssl(http_t *http, const char *buf, int len);

+# ifdef HAVE_GNUTLS
+# ifdef HAVE_PTHREAD_H
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif /_ HAVE_PTHREAD_H /
+
+# elif defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
+static pthread_mutex_t *http_locks; /
OpenSSL lock mutexes */
+
+static void http_locking_cb(int mode, int type, const char *file,

  •               int line);
    
    +static unsigned long http_threadid_cb(void);
    +# endif /* HAVE_GNUTLS /
    #endif /
    HAVE_SSL */

@@ -311,7 +327,7 @@

/*

  • * 'httpClose()' - Close an HTTP connection...

    • 'httpClose()' - Close an HTTP connection.
      */

    void
    @@ -1172,21 +1188,22 @@
    void
    httpInitialize(void)
    {

  • static int initialized = 0; /* Have we been called before? */
    +#ifdef WIN32

  • WSADATA winsockdata; /* WinSock data /
    +#endif /
    WIN32 */
    #ifdef HAVE_LIBSSL
    -# ifndef WIN32

  • struct timeval curtime; /* Current time in microseconds /
    -# endif /
    !WIN32 */

  • int i; /* Looping var */

  • unsigned char data[1024]; /* Seed data */

  • int i; /* Looping var */

  • unsigned char data[1024]; /* Seed data /
    #endif /
    HAVE_LIBSSL */

  • if (initialized)
  • return;

#ifdef WIN32

  • WSADATA winsockdata; /* WinSock data */
  • static int initialized = 0; /* Has WinSock been initialized? */
  • WSAStartup(MAKEWORD(1,1), &winsockdata);

  • if (!initialized)
  • WSAStartup(MAKEWORD(1,1), &winsockdata);
    #elif !defined(SO_NOSIGPIPE)
    /*
  • Ignore SIGPIPE signals...
    @@ -1194,6 +1211,7 @@

ifdef HAVE_SIGSET

sigset(SIGPIPE, SIG_IGN);
+

elif defined(HAVE_SIGACTION)

struct sigaction action; /* POSIX sigaction data */

@@ -1201,35 +1219,63 @@
memset(&action, 0, sizeof(action));
action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &action, NULL);
+

else

signal(SIGPIPE, SIG_IGN);

endif /* !SO_NOSIGPIPE _/

#endif /_ WIN32 */

#ifdef HAVE_GNUTLS

  • /*
  • * Make sure we handle threading properly...
  • */

+# ifdef HAVE_PTHREAD_H

  • gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
    +# endif /* HAVE_PTHREAD_H */
  • /*
  • * Initialize GNU TLS...
  • _/

gnutls_global_init();
-#endif /_ HAVE_GNUTLS */

-#ifdef HAVE_LIBSSL
+#elif defined(HAVE_LIBSSL)

  • /*
  • * Initialize OpenSSL...
  • */

SSL_load_error_strings();
SSL_library_init();

/*

  • * Set the threading callbacks...
  • */

+# ifdef HAVE_PTHREAD_H

  • http_locks = calloc(CRYPTO_num_locks(), sizeof(pthread_mutex_t));
  • for (i = 0; i < CRYPTO_num_locks(); i ++)
  • pthread_mutex_init(http_locks + i, NULL);
  • CRYPTO_set_id_callback(http_threadid_cb);
  • CRYPTO_set_locking_callback(http_locking_cb);
    +# endif /* HAVE_PTHREAD_H */
  • /*
    • Using the current time is a dubious random seed, but on some systems
    • it is the best we can do (on others, this seed isn't even used...)
      */

-# ifdef WIN32
-# else

  • gettimeofday(&curtime, NULL);
  • srand(curtime.tv_sec + curtime.tv_usec);
    -# endif /* WIN32 */
  • CUPS_SRAND(time(NULL));

for (i = 0; i < sizeof(data); i ++)

  • data[i] = rand();
  • data[i] = CUPS_RAND();

RAND_seed(data, sizeof(data));
-#endif /* HAVE_LIBSSL /
+#endif /
HAVE_GNUTLS */
+

  • initialized = 1;
    }

@@ -1817,7 +1863,7 @@

/*

  • * 'httpSetCookie()' - Set the cookie value(s)...
  • * 'httpSetCookie()' - Set the cookie value(s).
    *
    • @SInCE CUPS 1.1.19/Mac OS X 10.3@
      /
      @@ -2788,7 +2834,26 @@
      #endif /
      HAVE_SSL */

+#if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
/*

  • * 'http_locking_cb()' - Lock/unlock a thread's mutex.
  • /
    +
    +static void
    +http_locking_cb(int mode, /
    I - Lock mode */
  •   int        type,    /\* I - Lock type */
    
  •   const char _file,   /_ I - Source file */
    
  •   int        line)    /\* I - Line number */
    
    +{
  • if (mode & CRYPTO_LOCK)
  • pthread_mutex_lock(http_locks + type);
  • else
  • pthread_mutex_unlock(http_locks + type);
    +}
    +#endif /* HAVE_LIBSSL && HAVE_PTHREAD_H _/

+/_

  • 'http_send()' - Send a request with all fields and the trailing blank line.
    */

@@ -3159,6 +3224,19 @@
#endif /* HAVE_SSL */

+#if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
+/*

  • * 'http_threadid_cb()' - Return the current thread ID.
  • /
    +
    +static unsigned long /
    O - Thread ID */
    +http_threadid_cb(void)
    +{
  • return ((unsigned long)pthread_self());
    +}
    +#endif /* HAVE_LIBSSL && HAVE_PTHREAD_H _/

#ifdef HAVE_SSL
/_

  • 'http_upgrade()' - Force upgrade to TLS encryption.
    Index: cups/http-private.h

    --- cups/http-private.h (revision 9101)
    +++ cups/http-private.h (working copy)
    @@ -98,6 +98,7 @@
  • The GNU TLS library is more of a "bare metal" SSL/TLS library...
    */

    include <gnutls/gnutls.h>

    +# include <gcrypt.h>

typedef struct
{

Index: scheduler/server.c

--- scheduler/server.c (revision 9101)
+++ scheduler/server.c (working copy)
@@ -1,9 +1,9 @@
/*

  • "$Id$"
    *
  • * Server start/stop routines for the Common UNIX Printing System (CUPS).
  • * Server start/stop routines for the CUPS scheduler.
    *
  • * Copyright 2007-2008 by Apple Inc.
  • * Copyright 2007-2010 by Apple Inc.
    • Copyright 1997-2006 by Easy Software Products, all rights reserved.
    • These coded instructions, statements, and computer programs are the
      @@ -44,42 +44,7 @@
      void
      cupsdStartServer(void)
      {
      -#ifdef HAVE_LIBSSL
  • int i; /* Looping var */
  • struct timeval curtime; /* Current time in microseconds */
  • unsigned char data[1024]; /* Seed data /
    -#endif /
    HAVE_LIBSSL _/

-#ifdef HAVE_LIBSSL
/_

  • * Initialize the encryption libraries...

- */

  • SSL_library_init();

- SSL_load_error_strings();

  • /*
  • * Using the current time is a dubious random seed, but on some systems
  • * it is the best we can do (on others, this seed isn't even used...)

- */

  • gettimeofday(&curtime, NULL);

- srand(curtime.tv_sec + curtime.tv_usec);

  • for (i = 0; i < sizeof(data); i ++)

- data[i] = rand(); /* Yes, this is a poor source of random data... */

  • RAND_seed(&data, sizeof(data));
    -#elif defined(HAVE_GNUTLS)
  • /*
  • * Initialize the encryption libraries...

- */

  • gnutls_global_init();
    -#endif /* HAVE_LIBSSL */
  • /*
    • Create the default security profile...
      */

Index: scheduler/main.c

--- scheduler/main.c (revision 9101)
+++ scheduler/main.c (working copy)
@@ -1,7 +1,7 @@
/*

  • "$Id$"
    *
    • * Scheduler main loop for the Common UNIX Printing System (CUPS).
    • * Main loop for the CUPS scheduler.
      *
  • Copyright 2007-2009 by Apple Inc.
  • Copyright 1997-2007 by Easy Software Products, all rights reserved.
    @@ -572,6 +572,8 @@
  • Startup the server...
    */
  • httpInitialize();

cupsdStartServer();

/*

Collaborator

michaelrsweet commented Jun 24, 2010

"str3461p2.patch":

Index: config-scripts/cups-ssl.m4

--- config-scripts/cups-ssl.m4 (revision 9144)
+++ config-scripts/cups-ssl.m4 (working copy)
@@ -84,6 +84,10 @@
SSLLIBS="$SSLLIBS $LIBGCRYPTCONFIG --libs"
SSLFLAGS="$SSLFLAGS $LIBGCRYPTCONFIG --cflags"
fi
+

  •   if test "x$have_pthread" = xyes; then
    
  •       AC_MSG_ERROR([The current version of GNU TLS cannot be made thread-safe.])
    
  •   fi
    
    fi
    fi

Index: configure.in

--- configure.in (revision 9144)
+++ configure.in (working copy)
@@ -31,9 +31,9 @@
sinclude(config-scripts/cups-slp.m4)
sinclude(config-scripts/cups-gssapi.m4)
sinclude(config-scripts/cups-ldap.m4)
+sinclude(config-scripts/cups-threads.m4)
sinclude(config-scripts/cups-ssl.m4)
sinclude(config-scripts/cups-pam.m4)
-sinclude(config-scripts/cups-threads.m4)
sinclude(config-scripts/cups-largefile.m4)
sinclude(config-scripts/cups-dnssd.m4)
sinclude(config-scripts/cups-launchd.m4)

michaelrsweet added this to the Stable milestone Mar 17, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment