00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <openssl/ssl.h>
00034 #include <openssl/err.h>
00035 #include <sys/socket.h>
00036 #include <netinet/in.h>
00037 #include <arpa/inet.h>
00038 #include <netdb.h>
00039 #include <unistd.h>
00040
00041 #include <iostream>
00042
00043 using std::endl ;
00044
00045 #include "SSLClient.h"
00046 #include "PPTException.h"
00047 #include "BESDebug.h"
00048
00049 SSLClient::SSLClient( const string &hostStr, int portVal,
00050 const string &cert_file, const string &key_file )
00051 : SSLConnection(),
00052 _host( hostStr ),
00053 _port( portVal ),
00054 _cfile( cert_file ),
00055 _kfile( key_file )
00056 {
00057 }
00058
00059 SSLClient::~SSLClient()
00060 {
00061 }
00062
00063 void
00064 SSLClient::initConnection()
00065 {
00066 BESDEBUG( "Loading SSL error strings ... " )
00067 SSL_load_error_strings() ;
00068 BESDEBUG( "OK" << endl )
00069
00070 BESDEBUG( "Initializing SSL library ... " )
00071 SSL_library_init() ;
00072 BESDEBUG( "OK" << endl )
00073
00074 SSL_METHOD *method = NULL ;
00075 SSL_CTX *context = NULL ;
00076
00077 BESDEBUG( "Creating method and context ... " )
00078 method = SSLv3_client_method() ;
00079 if( method )
00080 {
00081 context = SSL_CTX_new( method ) ;
00082 }
00083 if( !context )
00084 {
00085 string msg = "Failed to create SSL context\n" ;
00086 msg += ERR_error_string( ERR_get_error(), NULL ) ;
00087 throw PPTException( msg ) ;
00088 }
00089 else
00090 {
00091 BESDEBUG( "OK" << endl )
00092 }
00093
00094 bool ok_2_continue = false ;
00095 string err_msg ;
00096 BESDEBUG( "Setting certificate and key ... " )
00097 if( SSL_CTX_use_certificate_file( context, _cfile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
00098 {
00099 err_msg = "FAILED to use certificate file " + _cfile + "\n" ;
00100 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00101 }
00102 else if( SSL_CTX_use_PrivateKey_file( context, _kfile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
00103 {
00104 err_msg = "FAILED to use private key file " + _kfile + "\n" ;
00105 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00106 }
00107 else if( !SSL_CTX_check_private_key( context ) )
00108 {
00109 err_msg = "FAILED to authenticate private key\n" ;
00110 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00111 }
00112 else
00113 {
00114 ok_2_continue = true ;
00115 }
00116
00117 if( ok_2_continue )
00118 {
00119 BESDEBUG( "OK" << endl )
00120 BESDEBUG( "Certificate setup ... " )
00121 SSL_CTX_set_verify( context, SSL_VERIFY_PEER, SSLClient::verify_server ) ;
00122 SSL_CTX_set_client_CA_list( context, SSL_load_client_CA_file( _cfile.c_str() ));
00123 if( ( !SSL_CTX_load_verify_locations( context, _cfile.c_str(), NULL )) ||
00124 ( !SSL_CTX_set_default_verify_paths( context ) ) )
00125 {
00126 err_msg = "Certificate setup failed\n" ;
00127 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00128 ok_2_continue = false ;
00129 }
00130 }
00131
00132 int sock_fd = -1 ;
00133 if( ok_2_continue )
00134 {
00135 BESDEBUG( "OK" << endl )
00136
00137 BESDEBUG( "Establishing TCP connection to " << _host << ":" << _port << " ... " )
00138 sock_fd = connect_to_server() ;
00139 if( sock_fd < 0 )
00140 {
00141 err_msg = "Failed to establish TCP connection" ;
00142 ok_2_continue = false ;
00143 }
00144 }
00145
00146 if( ok_2_continue )
00147 {
00148 BESDEBUG( "OK" << endl )
00149
00150 BESDEBUG( "Establishing secure connection ... " )
00151 int ssl_ret = 0 ;
00152 _connection = SSL_new( context ) ;
00153 if( !_connection )
00154 {
00155 err_msg = "FAILED to create new connection\n" ;
00156 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00157 ok_2_continue = false ;
00158 }
00159 else if( ( ssl_ret = SSL_set_fd( _connection, sock_fd ) ) < 0 )
00160 {
00161 err_msg = "FAILED to set the socket descriptor\n" ;
00162 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00163 ok_2_continue = false ;
00164 }
00165 else if( ( ssl_ret = SSL_connect( _connection ) ) < 0 )
00166 {
00167 err_msg = "FAILED to create SSL connection\n" ;
00168 err_msg += ERR_error_string( SSL_get_error( _connection, ssl_ret ), NULL ) ;
00169 ok_2_continue = false ;
00170 }
00171 else if( verify_connection() < 0 )
00172 {
00173 err_msg = "FAILED to verify SSL connection\n" ;
00174 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00175 ok_2_continue = false ;
00176 }
00177 }
00178
00179 if( ok_2_continue )
00180 {
00181 BESDEBUG( "OK" << endl )
00182 }
00183 else
00184 {
00185 BESDEBUG( "FAILED" << endl )
00186 if( _context ) SSL_CTX_free( _context ) ; _context = NULL ;
00187 throw PPTException( err_msg ) ;
00188 }
00189
00190 _connected = true ;
00191 }
00192
00193 int
00194 SSLClient::connect_to_server( )
00195 {
00196 int fd = -1 ;
00197 struct sockaddr_in addr ;
00198 struct sockaddr *mapped_addr ;
00199
00200 fd = socket( PF_INET, SOCK_STREAM, 0 ) ;
00201 if( fd < 0 ) return -1 ;
00202
00203 memset( &addr, 0, sizeof( addr ) ) ;
00204 addr.sin_family = AF_INET ;
00205 addr.sin_port = htons( _port ) ;
00206 if( isdigit( (int)*_host.c_str() ) )
00207 {
00208 addr.sin_addr.s_addr = inet_addr( _host.c_str() ) ;
00209 }
00210 else
00211 {
00212 struct hostent *hostEntry ;
00213 if( ( hostEntry = gethostbyname( _host.c_str() ) ) != 0 )
00214 {
00215 memcpy( &addr.sin_addr, hostEntry->h_addr, hostEntry->h_length ) ;
00216 }
00217 else
00218 {
00219 close( fd ) ;
00220 return -1 ;
00221 }
00222 }
00223 if( connect( fd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 )
00224 {
00225 close( fd ) ;
00226 return -1 ;
00227 }
00228
00229 return fd ;
00230 }
00231
00232 int
00233 SSLClient::verify_connection( )
00234 {
00235 X509 *server_cert = NULL ;
00236 char *str = NULL ;
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 return 1 ;
00247 }
00248
00249 int
00250 SSLClient::verify_server( int ok, X509_STORE_CTX *ctx )
00251 {
00252 if( ok )
00253 {
00254 BESDEBUG( "VERIFIED " )
00255 }
00256 else
00257 {
00258 char mybuf[256] ;
00259 X509 *err_cert ;
00260 int err ;
00261
00262 err_cert = X509_STORE_CTX_get_current_cert( ctx ) ;
00263 err = X509_STORE_CTX_get_error( ctx ) ;
00264 X509_NAME_oneline( X509_get_subject_name( err_cert ), mybuf, 256 ) ;
00265 BESDEBUG( "FAILED for " << mybuf << endl )
00266 BESDEBUG( " " << X509_verify_cert_error_string( err ) << endl )
00267 switch( ctx->error )
00268 {
00269 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00270 {
00271 X509_NAME_oneline( X509_get_issuer_name( err_cert ), mybuf, 256 ) ;
00272 BESDEBUG( " issuer = " << mybuf << endl )
00273 break ;
00274 }
00275
00276 case X509_V_ERR_CERT_NOT_YET_VALID:
00277 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00278 {
00279 BESDEBUG( " not yet valid!" << endl )
00280 break ;
00281 }
00282
00283 case X509_V_ERR_CERT_HAS_EXPIRED:
00284 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00285 {
00286 BESDEBUG( " expired!" << endl )
00287 break ;
00288 }
00289 }
00290 }
00291
00292 return 1 ;
00293 }
00294
00301 void
00302 SSLClient::dump( ostream &strm ) const
00303 {
00304 strm << BESIndent::LMarg << "SSLClient::dump - ("
00305 << (void *)this << ")" << endl ;
00306 BESIndent::Indent() ;
00307 strm << BESIndent::LMarg << "host: " << _host << endl ;
00308 strm << BESIndent::LMarg << "port: " << _port << endl ;
00309 strm << BESIndent::LMarg << "certificate file: " << _cfile << endl ;
00310 strm << BESIndent::LMarg << "key file: " << _kfile << endl ;
00311 SSLConnection::dump( strm ) ;
00312 BESIndent::UnIndent() ;
00313 }
00314