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