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 "config.h"
00034
00035 #include <openssl/ssl.h>
00036 #include <openssl/err.h>
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041 #include <netdb.h>
00042
00043 #include <iostream>
00044 #include <cstring>
00045
00046 #ifndef HAVE_SYS_ERRLIST
00047 #include <cerrno>
00048 #endif
00049 #ifdef HAVE_UNISTD_H
00050 #include <unistd.h>
00051 #endif
00052
00053 using std::endl ;
00054
00055 #include "SSLServer.h"
00056 #include "BESInternalError.h"
00057 #include "BESDebug.h"
00058
00059 SSLServer::SSLServer( int portVal,
00060 const string &cert_file,
00061 const string &cert_auth_file,
00062 const string &key_file )
00063 : SSLConnection(),
00064 _port( portVal ),
00065 _cfile( cert_file ),
00066 _cafile( cert_auth_file ),
00067 _kfile( key_file )
00068 {
00069 }
00070
00071 SSLServer::~SSLServer()
00072 {
00073 }
00074
00075 void
00076 SSLServer::initConnection()
00077 {
00078 BESDEBUG( "ppt", "Loading SSL error strings ... " << endl )
00079 SSL_load_error_strings() ;
00080 BESDEBUG( "ppt", "OK" << endl )
00081
00082 BESDEBUG( "ppt", "Initializing SSL library ... " << endl )
00083 SSL_library_init() ;
00084 BESDEBUG( "ppt", "OK" << endl )
00085
00086 #if OPENSSL_VERSION_NUMBER < 0x10000000L
00087 SSL_METHOD *method = NULL ;
00088 #else
00089 const SSL_METHOD *method = NULL ;
00090 #endif
00091 SSL_CTX *context = NULL ;
00092 BESDEBUG( "ppt", "Creating method and context ... " << endl )
00093 method = SSLv3_server_method() ;
00094 if( method )
00095 {
00096 context = SSL_CTX_new( method ) ;
00097 }
00098 if( !context )
00099 {
00100 BESDEBUG( "ppt", "FAILED" << endl )
00101 string msg = "Failed to create SSL context\n" ;
00102 msg += ERR_error_string( ERR_get_error(), NULL ) ;
00103 throw BESInternalError( msg, __FILE__, __LINE__ ) ;
00104 }
00105 else
00106 {
00107 BESDEBUG( "ppt", "OK" << endl )
00108 }
00109
00110 bool ok_2_continue = false ;
00111 string err_msg ;
00112
00113 BESDEBUG( "ppt", "Setting certificate and key ... " << endl )
00114 if( SSL_CTX_use_certificate_file( context, _cfile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
00115 {
00116 BESDEBUG( "ppt", "FAILED" << endl )
00117 err_msg = "FAILED to use certificate file " + _cfile + "\n" ;
00118 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00119 }
00120 else if( SSL_CTX_use_PrivateKey_file( context, _kfile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
00121 {
00122 BESDEBUG( "ppt", "FAILED" << endl )
00123 err_msg = "FAILED to use private key file " + _kfile + "\n" ;
00124 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00125 }
00126 else if( !SSL_CTX_check_private_key( context ) )
00127 {
00128 BESDEBUG( "ppt", "FAILED" << endl )
00129 err_msg = "FAILED to authenticate private key\n" ;
00130 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00131 }
00132 else
00133 {
00134 ok_2_continue = true ;
00135 }
00136
00137 if( ok_2_continue )
00138 {
00139 BESDEBUG( "ppt", "OK" << endl )
00140 BESDEBUG( "ppt", "Certificate setup ... " << endl )
00141 SSL_CTX_set_verify( context, SSL_VERIFY_PEER, verify_client ) ;
00142 SSL_CTX_set_client_CA_list( context, SSL_load_client_CA_file( _cafile.c_str() ));
00143 if( ( !SSL_CTX_load_verify_locations( context, _cafile.c_str(), NULL )) ||
00144 ( !SSL_CTX_set_default_verify_paths( context ) ) )
00145 {
00146 BESDEBUG( "ppt", "FAILED" << endl )
00147 err_msg = "Certificate setup failed\n" ;
00148 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00149 ok_2_continue = false ;
00150 }
00151 }
00152
00153 int port_fd = -1 ;
00154 if( ok_2_continue )
00155 {
00156 BESDEBUG( "ppt", "OK" << endl )
00157
00158 BESDEBUG( "ppt", "Opening port " << _port << "... " << endl )
00159 port_fd = open_port( ) ;
00160 if( port_fd < 0 )
00161 {
00162 BESDEBUG( "ppt", "FAILED" << endl )
00163 err_msg = "Failed to open port: " ;
00164 #ifdef HAVE_SYS_ERRLIST
00165 err_msg += sys_errlist[errno] ;
00166 #else
00167 err_msg += strerror( errno ) ;
00168 #endif
00169 ok_2_continue = false ;
00170 }
00171 }
00172
00173 int sock_fd = -1 ;
00174 if( ok_2_continue )
00175 {
00176 BESDEBUG( "ppt", "OK" << endl )
00177
00178 BESDEBUG( "ppt", "Waiting for client connection ... " << endl )
00179 sock_fd = accept( port_fd, NULL, NULL ) ;
00180 if( sock_fd < 0 )
00181 {
00182 BESDEBUG( "ppt", "FAILED" << endl )
00183 err_msg = "Failed to accept connection: " ;
00184 #ifdef HAVE_SYS_ERRLIST
00185 err_msg += sys_errlist[errno] ;
00186 #else
00187 err_msg += strerror( errno ) ;
00188 #endif
00189 ok_2_continue = false ;
00190 }
00191 }
00192
00193 if( ok_2_continue )
00194 {
00195 BESDEBUG( "ppt", "OK" << endl )
00196
00197 BESDEBUG( "ppt", "Establishing secure connection ... " << endl )
00198 int ssl_ret = 0 ;
00199 _connection = SSL_new( context ) ;
00200 if( !_connection )
00201 {
00202 err_msg = "FAILED to create new connection\n" ;
00203 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00204 ok_2_continue = false ;
00205 }
00206 else if( SSL_set_fd( _connection, sock_fd ) < 0 )
00207 {
00208 err_msg = "FAILED to set the socket descriptor\n" ;
00209 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00210 ok_2_continue = false ;
00211 }
00212 else if( ( ssl_ret = SSL_accept( _connection ) ) < 0 )
00213 {
00214 err_msg = "FAILED to create SSL connection\n" ;
00215 err_msg += ERR_error_string( SSL_get_error( _connection, ssl_ret ), NULL ) ;
00216 ok_2_continue = false ;
00217 }
00218 else if( verify_connection( ) < 0 )
00219 {
00220 err_msg = "FAILED to verify SSL connection\n" ;
00221 err_msg += ERR_error_string( ERR_get_error(), NULL ) ;
00222 ok_2_continue = false ;
00223 }
00224 }
00225
00226 if( ok_2_continue )
00227 {
00228 BESDEBUG( "ppt", "OK" << endl )
00229 }
00230 else
00231 {
00232 BESDEBUG( "ppt", "FAILED" << endl )
00233 if( _context ) SSL_CTX_free( _context ) ; _context = NULL ;
00234 throw BESInternalError( err_msg, __FILE__, __LINE__ ) ;
00235 }
00236
00237 _connected = true ;
00238 }
00239
00240 int
00241 SSLServer::open_port( )
00242 {
00243 int fd = -1 ;
00244 struct sockaddr_in addr ;
00245 int on = 1 ;
00246
00247 fd = socket( PF_INET, SOCK_STREAM, 0 ) ;
00248 if( fd < 0 ) return fd ;
00249
00250 setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof( on ) ) ;
00251
00252 memset( &addr, 0, sizeof( addr ) ) ;
00253 addr.sin_family = AF_INET ;
00254 addr.sin_addr.s_addr = INADDR_ANY ;
00255 addr.sin_port = htons( _port ) ;
00256
00257 if( bind( fd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 )
00258 {
00259 close( fd ) ;
00260 return -1 ;
00261 }
00262 if( listen( fd, SOMAXCONN ) < 0 )
00263 {
00264 close( fd ) ;
00265 return -1 ;
00266 }
00267
00268 return fd ;
00269 }
00270
00271 int
00272 SSLServer::verify_connection( )
00273 {
00274 X509 *server_cert = NULL ;
00275 char *str = NULL ;
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 return 1 ;
00286 }
00287
00288 int
00289 SSLServer::verify_client( int ok, X509_STORE_CTX *ctx )
00290 {
00291 if( ok )
00292 {
00293 BESDEBUG( "ppt", "VERIFIED " << endl )
00294 X509 *user_cert = X509_STORE_CTX_get_current_cert( ctx ) ;
00295
00296 }
00297 else
00298 {
00299 char mybuf[256] ;
00300 X509 *err_cert ;
00301 int err ;
00302
00303 err_cert = X509_STORE_CTX_get_current_cert( ctx ) ;
00304 err = X509_STORE_CTX_get_error( ctx ) ;
00305 X509_NAME_oneline( X509_get_subject_name( err_cert ), mybuf, 256 ) ;
00306 BESDEBUG( "ppt", "FAILED for " << mybuf << endl )
00307 BESDEBUG( "ppt", " " << X509_verify_cert_error_string( err ) << endl )
00308 switch( ctx->error )
00309 {
00310 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
00311 {
00312 X509_NAME_oneline( X509_get_issuer_name( err_cert ), mybuf, 256 ) ;
00313 BESDEBUG( "ppt", " issuer = " << mybuf << endl )
00314 break ;
00315 }
00316
00317 case X509_V_ERR_CERT_NOT_YET_VALID:
00318 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
00319 {
00320 BESDEBUG( "ppt", " not yet valid!" << endl )
00321 break ;
00322 }
00323
00324 case X509_V_ERR_CERT_HAS_EXPIRED:
00325 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
00326 {
00327 BESDEBUG( "ppt", " expired!" << endl )
00328 break ;
00329 }
00330 default:
00331 {
00332 BESDEBUG( "ppt", " unknown!" << endl )
00333 break ;
00334 }
00335 }
00336 }
00337
00338 return 1 ;
00339 }
00340
00347 void
00348 SSLServer::dump( ostream &strm ) const
00349 {
00350 strm << BESIndent::LMarg << "SSLServer::dump - ("
00351 << (void *)this << ")" << endl ;
00352 BESIndent::Indent() ;
00353 strm << BESIndent::LMarg << "port: " << _port << endl ;
00354 strm << BESIndent::LMarg << "cert file: " << _cfile << endl ;
00355 strm << BESIndent::LMarg << "cert authority file: " << _cafile << endl ;
00356 strm << BESIndent::LMarg << "key file: " << _kfile << endl ;
00357 SSLConnection::dump( strm ) ;
00358 BESIndent::UnIndent() ;
00359 }
00360