]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/openssl.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / lib / openssl.c
index 8650ca8956d56bcad73df7f288c95b7d3b491eab..558868b5205a0c23bafa2be501ab8e5ca3af990d 100644 (file)
@@ -1,37 +1,26 @@
 /*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
-
-   The main author of Bacula is Kern Sibbald, with contributions from
-   many others, a complete list can be found in the file AUTHORS.
-   This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
-   License as published by the Free Software Foundation plus additions
-   that are listed in the file LICENSE.
-
-   This program 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
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Bacula® is a registered trademark of John Walker.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2016 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  * openssl.c OpenSSL support functions
  *
  * Author: Landon Fuller <landonf@opendarwin.org>
  *
- * Version $Id$
- *
  * This file was contributed to the Bacula project by Landon Fuller.
  *
  * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
 
 #ifdef HAVE_OPENSSL
 
-/* Array of mutexes for use with OpenSSL static locking */
-static pthread_mutex_t *mutexes;
-
-/* OpenSSL dynamic locking structure */
-struct CRYPTO_dynlock_value {
-   pthread_mutex_t mutex;
-};
-
+/* Are we initialized? */
+static int crypto_initialized = false;
+/*
+ * ***FIXME*** this is a sort of dummy to avoid having to
+ *   change all the existing code to pass either a jcr or
+ *   a NULL.  Passing a NULL causes the messages to be
+ *   printed by the daemon -- not very good :-(
+ */
 void openssl_post_errors(int code, const char *errstring)
 {
    openssl_post_errors(NULL, code, errstring);
 }
 
-
 /*
  * Post all per-thread openssl errors
  */
@@ -75,20 +63,39 @@ void openssl_post_errors(JCR *jcr, int code, const char *errstring)
    /* Pop errors off of the per-thread queue */
    while((sslerr = ERR_get_error()) != 0) {
       /* Acquire the human readable string */
-      ERR_error_string_n(sslerr, (char *) &buf, sizeof(buf));
-      Jmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
+      ERR_error_string_n(sslerr, buf, sizeof(buf));
+      Dmsg3(50, "jcr=%p %s: ERR=%s\n", jcr, errstring, buf);
+      Qmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
    }
 }
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+/* Array of mutexes for use with OpenSSL static locking */
+static pthread_mutex_t *mutexes;
+
+/* OpenSSL dynamic locking structure */
+struct CRYPTO_dynlock_value {
+   pthread_mutex_t mutex;
+};
+
 /*
  * Return an OpenSSL thread ID
  *  Returns: thread ID
  *
  */
-static unsigned long get_openssl_thread_id (void)
+static unsigned long get_openssl_thread_id(void)
 {
-   /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
-   return ((unsigned long) pthread_self());
+#ifdef HAVE_WIN32
+   return (unsigned long)GetCurrentThreadId();
+#else
+   /*
+    * Comparison without use of pthread_equal() is mandated by the OpenSSL API
+    *
+    * Note: this creates problems with the new Win32 pthreads
+    *   emulation code, which defines pthread_t as a structure.
+    */
+   return ((unsigned long)pthread_self());
+#endif
 }
 
 /*
@@ -99,16 +106,17 @@ static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *fi
    struct CRYPTO_dynlock_value *dynlock;
    int stat;
 
-   dynlock = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
+   dynlock = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
 
    if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
-      Emsg1(M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
+      berrno be;
+      Jmsg1(NULL, M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
    }
 
    return dynlock;
 }
 
-static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
+static void openssl_update_dynamic_mutex(int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
 {
    if (mode & CRYPTO_LOCK) {
       P(dynlock->mutex);
@@ -117,12 +125,13 @@ static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value
    }
 }
 
-static void openssl_destroy_dynamic_mutex (struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
+static void openssl_destroy_dynamic_mutex(struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
 {
    int stat;
 
    if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
-      Emsg1(M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
+      berrno be;
+      Jmsg1(NULL, M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), be.bstrerror(stat));
    }
 
    free(dynlock);
@@ -145,12 +154,11 @@ static void openssl_update_static_mutex (int mode, int i, const char *file, int
  *  Returns: 0 on success
  *           errno on failure
  */
-int openssl_init_threads (void)
+static int openssl_init_threads (void)
 {
    int i, numlocks;
    int stat;
 
-
    /* Set thread ID callback */
    CRYPTO_set_id_callback(get_openssl_thread_id);
 
@@ -159,7 +167,8 @@ int openssl_init_threads (void)
    mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
    for (i = 0; i < numlocks; i++) {
       if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
-         Emsg1(M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
+         berrno be;
+         Jmsg1(NULL, M_FATAL, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
          return stat;
       }
    }
@@ -178,20 +187,22 @@ int openssl_init_threads (void)
 /*
  * Clean up OpenSSL threading support
  */
-void openssl_cleanup_threads (void)
+static void openssl_cleanup_threads(void)
 {
    int i, numlocks;
    int stat;
 
    /* Unset thread ID callback */
    CRYPTO_set_id_callback(NULL);
-  
+
    /* Deallocate static lock mutexes */
    numlocks = CRYPTO_num_locks();
    for (i = 0; i < numlocks; i++) {
       if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
+         berrno be;
          /* We don't halt execution, reporting the error should be sufficient */
-         Emsg1(M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
+         Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
+               be.bstrerror(stat));
       }
    }
 
@@ -207,13 +218,14 @@ void openssl_cleanup_threads (void)
    CRYPTO_set_dynlock_destroy_callback(NULL);
 }
 
+#endif
 
 /*
  * Seed OpenSSL PRNG
  *  Returns: 1 on success
  *           0 on failure
  */
-int openssl_seed_prng (void)
+static int openssl_seed_prng (void)
 {
    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
    int i;
@@ -238,11 +250,92 @@ int openssl_seed_prng (void)
  *  Returns: 1 on success
  *           0 on failure
  */
-int openssl_save_prng (void)
+static int openssl_save_prng (void)
 {
    // ***FIXME***
    // Implement PRNG state save
    return 1;
 }
 
+/*
+ * Perform global initialization of OpenSSL
+ * This function is not thread safe.
+ *  Returns: 0 on success
+ *           errno on failure
+ */
+int init_crypto (void)
+{
+   int stat = 0;
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+   if ((stat = openssl_init_threads()) != 0) {
+      berrno be;
+      Jmsg1(NULL, M_ABORT, 0,
+        _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat));
+   }
+
+   /* Load libssl and libcrypto human-readable error strings */
+   SSL_load_error_strings();
+
+   /* Initialize OpenSSL SSL  library */
+   SSL_library_init();
+
+   /* Register OpenSSL ciphers and digests */
+   OpenSSL_add_all_algorithms();
+#endif
+
+   if (!openssl_seed_prng()) {
+      Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
+   }
+
+   crypto_initialized = true;
+
+   return stat;
+}
+
+/*
+ * Perform global cleanup of OpenSSL
+ * All cryptographic operations must be completed before calling this function.
+ * This function is not thread safe.
+ *  Returns: 0 on success
+ *           errno on failure
+ */
+int cleanup_crypto (void)
+{
+   /*
+    * Ensure that we've actually been initialized; Doing this here decreases the
+    * complexity of client's termination/cleanup code.
+    */
+   if (!crypto_initialized) {
+      return 0;
+   }
+
+   if (!openssl_save_prng()) {
+      Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
+   }
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+   openssl_cleanup_threads();
+
+   /* Free libssl and libcrypto error strings */
+   ERR_free_strings();
+
+   /* Free all ciphers and digests */
+   EVP_cleanup();
+
+   /* Free memory used by PRNG */
+   RAND_cleanup();
+#endif
+
+   crypto_initialized = false;
+
+   return 0;
+}
+
+#else
+
+/* Dummy routines */
+int init_crypto (void) { return 0; }
+int cleanup_crypto (void) { return 0; }
+
 #endif /* HAVE_OPENSSL */