/*
- 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 and included
- 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
openssl_post_errors(NULL, code, errstring);
}
-
/*
* Post all per-thread openssl errors
*/
}
}
+#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)
{
-#ifdef HAVE_WIN32
- return (unsigned long)getpid();
-#else
/*
- * Comparison without use of pthread_equal() is mandated by the OpenSSL API */
+ * 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
}
/*
* 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);
/*
* 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 */
- Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
+ Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
be.bstrerror(stat));
}
}
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;
* 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 */