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