Main Page   Class Hierarchy   Compound List   File List   Compound Members  

C_TransIPTLS.cpp

00001 /*
00002  *  This program is free software; you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License as published by
00004  *  the Free Software Foundation; either version 2 of the License, or
00005  *  (at your option) any later version.
00006  *
00007  *  This program is distributed in the hope that it will be useful,
00008  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  *  GNU General Public License for more details.
00011  *
00012  *  You should have received a copy of the GNU General Public License
00013  *  along with this program; if not, write to the Free Software
00014  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015  *
00016  * (c)Copyright 2006 Hewlett-Packard Development Company, LP.
00017  *
00018  */
00019 
00020 #include "C_TransIPTLS.hpp"
00021 #include "C_SecureSocket.hpp"
00022 #include "Utils.hpp"
00023 
00024 #define CALL_BACK_USER_DATA "ksgr"
00025 
00026 #ifdef DEBUG_MODE
00027 #define GEN_DEBUG(l,a) iostream_error << a << iostream_endl << iostream_flush ; 
00028 #else
00029 #define GEN_DEBUG(l,a) 
00030 #endif
00031 
00032 #define GEN_ERROR(l,a) iostream_error << a << iostream_endl << iostream_flush ; 
00033 
00034 static C_TransIPTLS::T_supported_methods m_methods [] = {
00035   { "SSLv23", SSLv23_method }
00036 } ;
00037 static int m_nb_methods = 1 ;
00038 
00039 static char *password ;
00040 static int passwd_call_back(char *buf,int num,
00041                             int rwflag,void *userdata) {
00042     if(num<(int)strlen(password)+1)
00043       return(0);
00044 
00045     strcpy(buf,password);
00046     return(strlen(password));
00047 }
00048 
00049 static int verify_callback(int P_ok , X509_STORE_CTX *P_store)
00050 {
00051   char L_data[512];
00052  
00053   if (!P_ok) {
00054 
00055      X509 *L_cert = X509_STORE_CTX_get_current_cert(P_store);
00056      //     int   L_depth = X509_STORE_CTX_get_error_depth(P_store);
00057      //     int   L_err   = X509_STORE_CTX_get_error(P_store);
00058 
00059      X509_NAME_oneline(X509_get_issuer_name(L_cert),
00060                                    L_data,512);
00061      GEN_ERROR(1, "TLS verification error for issuer [" << L_data << "]");
00062      X509_NAME_oneline(X509_get_subject_name(L_cert),
00063                                    L_data,512);
00064      GEN_ERROR(1, "TLS verification error for subject [" << L_data << "]");
00065   }
00066   return P_ok;
00067 }
00068 
00069 
00070 int C_TransIPTLS::load_crls(char *P_crlfile)
00071 {
00072   X509_STORE          *L_store;
00073   X509_LOOKUP         *L_lookup;
00074 
00075   /*  Get the X509_STORE from SSL context */
00076   if (!(L_store = SSL_CTX_get_cert_store(m_ssl_ctx))) {
00077     return (-1);
00078   }
00079 
00080   /* Add lookup file to X509_STORE */
00081   if (!(L_lookup = X509_STORE_add_lookup(L_store,X509_LOOKUP_file()))) {
00082     return (-1);
00083   }
00084 
00085   /* Add the CRLS to the lookpup object */
00086   if (X509_load_crl_file(L_lookup,m_crl_file,X509_FILETYPE_PEM) != 1) {
00087     return (-1);
00088   }
00089 
00090   /* Set the flags of the store so that CRLS's are consulted */
00091 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
00092   X509_STORE_set_flags( L_store,X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
00093 #else
00094   GEN_ERROR(1, "version OpenSSL (<0.9.7) cannot handle CRL files in capath");
00095 #endif
00096 
00097   return (1);
00098 }
00099 
00100 
00101 
00102 C_TransIPTLS::T_SSLMethodType C_TransIPTLS::find_method(char *P_name) {
00103 
00104   int L_i ;
00105   T_SSLMethodType L_ret = NULL ;
00106 
00107   for (L_i = 0 ; L_i < m_nb_methods ; L_i++) {
00108     if (strcmp(P_name, m_methods[L_i].m_name) == 0){
00109       L_ret = m_methods[L_i].m_method ;
00110       break ;
00111     }
00112   }
00113   return (L_ret);
00114 }
00115 
00116 int C_TransIPTLS::config (T_pConfigValueList P_config_param_list) {
00117   GEN_DEBUG(1, "C_TransIP::config  ()");
00118   m_logInfo = NULL ;
00119   m_logError = NULL ;
00120 
00121   int                           L_ret = 0       ;
00122   T_ConfigValueList::iterator   L_config_it     ;
00123 
00124   if (!P_config_param_list->empty()) {
00125     for (L_config_it = P_config_param_list->begin() ;
00126          L_config_it != P_config_param_list->end();
00127          L_config_it++) {
00128       L_ret = analyze_config(*L_config_it) ;
00129       if (L_ret != 0) break ;
00130     }
00131   }
00132 
00133   return (L_ret);
00134 }
00135 
00136 bool C_TransIPTLS::analyze_init_string (char *P_buf) {
00137 
00138   bool             L_ret = false  ;
00139   char             L_tmp  [255]   ;
00140 
00141   analyze_optional_init_string(P_buf);
00142   
00143   L_tmp[0] = '\0' ;
00144   if (analyze_string_value (P_buf,
00145                            (char*)"cert_chain_file=",
00146                            L_tmp)) {
00147     ALLOC_TABLE(m_cert_chain_file,
00148                 char*,
00149                 sizeof(char),
00150                 strlen(L_tmp)+1);
00151     sprintf(m_cert_chain_file, "%s", L_tmp);
00152     L_ret = true ;
00153   } else {
00154     // mandatory
00155     GEN_ERROR(1, "[cert_chain_file] value madatory for TLS transport");
00156     L_ret = false ;
00157   }
00158 
00159   L_tmp[0] = '\0' ;
00160   if (L_ret && analyze_string_value (P_buf,
00161                                      (char*)"private_key_file=",
00162                                      L_tmp)) {
00163     ALLOC_TABLE(m_private_key_file,
00164                 char*,
00165                 sizeof(char),
00166                 strlen(L_tmp)+1);
00167     sprintf(m_private_key_file, "%s", L_tmp);
00168     L_ret = true ;
00169   } else {
00170     // mandatory
00171     GEN_ERROR(1, "[private_key_file] value madatory for secure transport");
00172     L_ret = false ;
00173   } 
00174 
00175   L_tmp[0] = '\0' ;
00176   if (L_ret && analyze_string_value (P_buf,
00177                                      (char*)"passwd=",
00178                                      L_tmp)) {
00179     ALLOC_TABLE(m_passwd,
00180                 char*,
00181                 sizeof(char),
00182                 strlen(L_tmp)+1);
00183     sprintf(m_passwd, "%s", L_tmp);
00184     password = m_passwd ;
00185     L_ret = true ;
00186   } else {
00187     // mandatory
00188     GEN_ERROR(1, "[passwd] value madatory for secure transport");
00189     L_ret = false ;
00190   }
00191 
00192   L_tmp[0] = '\0' ;
00193   if (L_ret && analyze_string_value (P_buf,
00194                                      (char*)"method=",
00195                                      L_tmp)) {
00196 
00197     m_method = find_method(L_tmp) ;
00198     if (m_method == NULL) {
00199       GEN_ERROR(1, "unknown [method] value for secure transport");
00200       L_ret = false ;
00201     } else {
00202       L_ret = true ;
00203     }
00204   } else {
00205     // mandatory
00206     GEN_ERROR(1, "[method] value madatory for secure transport");
00207     L_ret = false ;
00208   }
00209 
00210   L_tmp[0] = '\0' ;
00211   if (L_ret && analyze_string_value (P_buf,
00212                                      (char*)"crl_file=",
00213                                      L_tmp)) {
00214     ALLOC_TABLE(m_crl_file,
00215                 char*,
00216                 sizeof(char),
00217                 strlen(L_tmp)+1);
00218     sprintf(m_crl_file, "%s", L_tmp);
00219     L_ret = true ;
00220   } 
00221 
00222   L_tmp[0] = '\0' ;
00223   if (L_ret && analyze_string_value (P_buf,
00224                                      (char*)"secure=",
00225                                      L_tmp)) {
00226 
00227     if (strcmp(L_tmp, (char*)"no") == 0){
00228       m_start_secure_mode = false ;
00229     }
00230     L_ret = true ;
00231   } 
00232 
00233   return (L_ret);
00234 }
00235 
00236 
00237 int C_TransIPTLS::analyze_config(T_ConfigValue& P_config) {
00238   int                           L_ret = 0       ;
00239   return (L_ret);
00240 }
00241 
00242 C_TransIPTLS::C_TransIPTLS() : C_TransIP()  {
00243   m_ssl_ctx = NULL ;
00244   m_passwd = NULL ;
00245   m_cert_chain_file = NULL ;
00246   m_private_key_file = NULL ;
00247   m_crl_file = NULL ;
00248   m_method = NULL ;
00249   m_start_secure_mode = true ;
00250 }
00251 
00252 C_TransIPTLS::~C_TransIPTLS() {
00253   if (m_ssl_ctx) {
00254     SSL_CTX_free(m_ssl_ctx);
00255   }
00256   FREE_TABLE(m_passwd);
00257   FREE_TABLE(m_cert_chain_file);
00258   FREE_TABLE(m_private_key_file);
00259   FREE_TABLE(m_crl_file);
00260 }
00261 
00262 
00263 
00264 int C_TransIPTLS::init (char *P_buf,
00265                         T_logFunction P_logError,
00266                         T_logFunction P_logInfo) {
00267 
00268   int L_ret = 0 ;
00269 
00270   L_ret = C_TransIP::init(P_buf, P_logError, P_logInfo) ;    
00271   if (L_ret != -1 ) {
00272     // init SSL library
00273     SSL_library_init();
00274     SSL_load_error_strings() ;
00275 
00276     if ((m_ssl_ctx = SSL_CTX_new(((*m_method)()))) == NULL ) {
00277       GEN_ERROR(1, "SSL_CTX_new failed");
00278       L_ret = -1 ;
00279     } else {
00280       m_trans_type = E_SOCKET_TCP_MODE ;
00281       SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx,
00282                                              (void *)m_passwd);
00283       SSL_CTX_set_default_passwd_cb(m_ssl_ctx,
00284                                     passwd_call_back);
00285       
00286       if (SSL_CTX_use_certificate_chain_file(m_ssl_ctx,
00287                                              m_cert_chain_file) != 1) {
00288         GEN_ERROR(1, "SSL_CTX_use_certificate_file failed");
00289         L_ret = -1 ;
00290       }
00291       
00292       if (L_ret != -1) {
00293         if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx,
00294                                           m_private_key_file,
00295                                           SSL_FILETYPE_PEM))) {
00296           GEN_ERROR(1, "SSL_CTX_use_PrivateKey_file failed");
00297           L_ret = -1 ;
00298         }
00299       
00300         if (L_ret != -1) {
00301           
00302           if (!(SSL_CTX_load_verify_locations(m_ssl_ctx, m_cert_chain_file, 0))) {
00303             GEN_ERROR(1, "Cannot load CA");
00304               L_ret = -1 ;
00305           }
00306 
00307           if (L_ret != -1) {
00308           
00309             if (m_crl_file != NULL) {
00310               if(load_crls(m_crl_file) == -1) {
00311                 GEN_ERROR(1, "Unable to load CRL file [" << m_crl_file << "]" );
00312                 L_ret = -1 ;
00313               }
00314               
00315               /* The following call forces to process the certificates with the */
00316               /* initialised SSL_CTX                                            */
00317               SSL_CTX_set_verify(m_ssl_ctx,
00318                                  SSL_VERIFY_PEER |
00319                                  SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
00320                                  verify_callback);
00321             }
00322           }
00323         }
00324       }
00325     }
00326   }
00327   
00328   return (L_ret);
00329 
00330 }
00331 
00332 
00333 C_Socket* C_TransIPTLS::open (int              P_channel_id, 
00334                               T_pIpAddr        P_Addr,
00335                               T_pOpenStatus    P_status,
00336                               C_ProtocolBinaryFrame *P_protocol) {
00337 
00338   C_Socket          *L_socket_created = NULL ;
00339 
00340   if (m_start_secure_mode == true) {
00341     
00342     int                L_rc ;
00343     
00344     GEN_DEBUG(1, "C_TransIPTLS::open ()");
00345     
00346     switch (P_Addr->m_umode) {
00347     case E_IP_USAGE_MODE_SERVER: {
00348       
00349       C_SecureSocketListen *L_Socket ;
00350     
00351       NEW_VAR(L_Socket, C_SecureSocketListen(m_ssl_ctx,
00352                                              m_trans_type, 
00353                                              P_Addr, 
00354                                              P_channel_id, 
00355                                              m_read_buffer_size, 
00356                                              m_decode_buffer_size));
00357       // std::cerr << "m_trans_type " << m_trans_type << std::endl;
00358       L_rc = L_Socket->_open(m_buffer_size, P_protocol) ;
00359       if (L_rc == 0) {
00360         L_socket_created = L_Socket ;
00361         *P_status = E_OPEN_OK ;
00362       } else {
00363         DELETE_VAR(L_Socket) ;
00364         *P_status = E_OPEN_FAILED ;
00365       }
00366     }
00367       break ;
00368     
00369     case E_IP_USAGE_MODE_CLIENT: {
00370       C_SecureSocketClient *L_Socket ;
00371       
00372       NEW_VAR(L_Socket, C_SecureSocketClient(m_ssl_ctx,
00373                                              m_trans_type, 
00374                                              P_Addr, 
00375                                              P_channel_id, 
00376                                              m_read_buffer_size, 
00377                                              m_decode_buffer_size));
00378 
00379       // std::cerr << "m_trans_type Client" << m_trans_type << std::endl;
00380       L_rc = L_Socket->_open(P_status, m_buffer_size, P_protocol) ;
00381       if (L_rc == 0) {
00382         L_socket_created = L_Socket ;
00383       } else {
00384         DELETE_VAR(L_Socket) ;
00385         *P_status = E_OPEN_FAILED ;
00386       }
00387     }
00388       
00389       break ;
00390 
00391     case E_IP_USAGE_MODE_UNKNOWN:
00392       
00393       GEN_ERROR(1, "OPEN failed: Unsupported mode");
00394       *P_status = E_OPEN_FAILED ;
00395       break ;
00396     }
00397 
00398   } else {
00399     L_socket_created = C_TransIP::open(P_channel_id, 
00400                                        P_Addr,
00401                                        P_status,
00402                                        P_protocol) ;
00403   }
00404 
00405   return (L_socket_created);
00406 }
00407 
00408 C_Socket* C_TransIPTLS::make_secure (C_Socket *P_Socket) {
00409   
00410   C_Socket *L_new = NULL ;
00411   
00412   {
00413     C_SocketClient *L_socket = NULL ;
00414 
00415     L_socket = dynamic_cast<C_SocketClient*>(P_Socket) ;
00416     if (L_socket != NULL) {
00417       NEW_VAR(L_new,
00418               C_SecureSocketClient(m_ssl_ctx,*L_socket));
00419     }
00420   }
00421 
00422   if (L_new == NULL) {
00423     C_SocketServer *L_socket = NULL ;
00424 
00425     L_socket = dynamic_cast<C_SocketServer*>(P_Socket) ;
00426     if (L_socket != NULL) {
00427       NEW_VAR(L_new,
00428               C_SecureSocketServer(m_ssl_ctx,*L_socket));
00429     }
00430   }
00431 
00432   // making secure a listen socket is not possible
00433   
00434   return (L_new);
00435 }
00436 
00437 int C_TransIPTLS::set_option (int P_Channel_Id, char *P_buf) {
00438 
00439   C_Socket             *L_socket = NULL;
00440   T_SocketMap::iterator L_it ;
00441   int                   L_ret = 0 ;
00442 
00443   L_it = m_socket_map.find(T_SocketMap::key_type(P_Channel_Id));
00444   if (L_it != m_socket_map.end()) {
00445     L_socket = make_secure (L_it->second);
00446     if (L_socket != NULL) {
00447       m_socket_map.erase(L_it);
00448       m_socket_map.insert(T_SocketMap::value_type(L_socket->get_id(),
00449                                                   L_socket));
00450     } else {
00451       
00452       L_ret = -1 ;
00453     }
00454     //DELETE_VAR(L_it->second) ;
00455   } else {
00456     L_ret = -1 ;
00457   }
00458 
00459   return (L_ret);
00460 }
00461 
00462 
00463 // External interface
00464 
00465 T_pTransport create_ciptlsio_instance () {
00466   C_TransIPTLS* L_inst ;
00467   NEW_VAR(L_inst, C_TransIPTLS());
00468   return (L_inst);
00469 }
00470 
00471 void delete_ciptlsio_instance (T_ppTransport P_inst) {
00472   if (P_inst != NULL) {
00473     C_TransIPTLS* L_inst = (C_TransIPTLS*) *P_inst ;
00474     DELETE_VAR(L_inst);
00475     *P_inst = NULL ;
00476   }
00477 }

Generated on Wed Mar 7 14:44:59 2007 for Seagull by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002