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