Back to index

nordugrid-arc-nox  1.1.0~rc6
OpenSSL.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #include <openssl/ssl.h>
00008 #include <openssl/err.h>
00009 
00010 #include <arc/Thread.h>
00011 #include <arc/Logger.h>
00012 #include <arc/Utils.h>
00013 
00014 #include "OpenSSL.h"
00015 
00016 namespace Arc {
00017 
00018   static Glib::Mutex lock;
00019   static bool initialized = false;
00020   static Glib::Mutex* ssl_locks = NULL;
00021   static int ssl_locks_num = 0;
00022 
00023   static Logger& logger(void) {
00024     static Logger* logger_ = new Logger(Logger::getRootLogger(), "OpenSSL");
00025     return *logger_;
00026   }
00027 
00028   void HandleOpenSSLError(void) {
00029     HandleOpenSSLError(SSL_ERROR_NONE);
00030   }
00031 
00032   void HandleOpenSSLError(int code) {
00033     unsigned long e = (code==SSL_ERROR_NONE)?ERR_get_error():code;
00034     while(e != SSL_ERROR_NONE) {
00035       if(e == SSL_ERROR_SYSCALL) {
00036         // Hiding system errors
00037         //logger().msg(ERROR, "SSL error: %d - system call failed",e);
00038       } else {
00039         const char* lib = ERR_lib_error_string(e);
00040         const char* func = ERR_func_error_string(e);
00041         const char* reason = ERR_reason_error_string(e);
00042         logger().msg(ERROR, "SSL error: %d - %s:%s:%s",
00043                           e,
00044                           lib?lib:"",
00045                           func?func:"",
00046                           reason?reason:"");
00047       };
00048       e = ERR_get_error();
00049     };
00050   }
00051 
00052   static void ssl_locking_cb(int mode, int n, const char * s_, int n_){
00053     if(!ssl_locks) {
00054       logger().msg(ERROR, "FATAL: SSL locks not initialized");
00055       _exit(-1);
00056     };
00057     if((n < 0) || (n >= ssl_locks_num)) {
00058       logger().msg(ERROR, "FATAL: wrong SSL lock requested: %i of %i: %i - %s",n,ssl_locks_num,n_,s_);
00059       _exit(-1);
00060     };
00061     if(mode & CRYPTO_LOCK) {
00062       ssl_locks[n].lock();
00063     } else {
00064       ssl_locks[n].unlock();
00065     };
00066   }
00067 
00068   static unsigned long ssl_id_cb(void) {
00069     return (unsigned long)(Glib::Thread::self());
00070   }
00071 
00072   //static void* ssl_idptr_cb(void) {
00073   //  return (void*)(Glib::Thread::self());
00074   //}
00075 
00076   bool OpenSSLInit(void) {
00077     Glib::Mutex::Lock flock(lock);
00078     if(!initialized) {
00079       if(!PersistentLibraryInit("modcrypto")) {
00080         logger().msg(WARNING, "Failed to lock arccrypto library in memory");
00081       };  
00082       SSL_load_error_strings();
00083       if(!SSL_library_init()){
00084         logger().msg(ERROR, "Failed to initialize OpenSSL library");
00085         HandleOpenSSLError();
00086         ERR_free_strings();
00087         return false;
00088       };
00089       // We could RAND_seed() here. But since 0.9.7 OpenSSL
00090       // knows how to make use of OS specific source of random
00091       // data. I think it's better to let OpenSSL do a job.
00092       // Here we could also generate ephemeral DH key to avoid
00093       // time consuming genaration during connection handshake.
00094       // But is not clear if it is needed for curently used
00095       // connections types at all. Needs further investigation.
00096       // Using RSA key violates TLS (according to OpenSSL
00097       // documentation) hence we do not use it.
00098       //  A.K.
00099     };
00100     // Always make sure our own locks are installed
00101     int num_locks = CRYPTO_num_locks();
00102     if(num_locks > 0) {
00103       if(num_locks != ssl_locks_num) {
00104         if(ssl_locks_num > 0) {
00105           logger().msg(ERROR, "Number of OpenSSL locks changed - reinitializing");
00106           ssl_locks_num=0;
00107           ssl_locks=NULL;
00108         };
00109       };
00110       if((!ssl_locks) || (!initialized)) {
00111         ssl_locks_num=0;
00112         ssl_locks=new Glib::Mutex[num_locks];
00113       };
00114       if(!ssl_locks) return false;
00115       ssl_locks_num=num_locks;
00116       CRYPTO_set_locking_callback(&ssl_locking_cb);
00117       CRYPTO_set_id_callback(&ssl_id_cb);
00118       //CRYPTO_set_idptr_callback(&ssl_idptr_cb);
00119     }
00120     if(!initialized) {
00121       OpenSSL_add_all_algorithms();
00122     }
00123     initialized=true;
00124   }
00125 
00126 } // namespace Arc
00127