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 <string>
00034 #include <iostream>
00035 #include <sstream>
00036
00037 using std::string ;
00038 using std::cerr ;
00039 using std::cout ;
00040 using std::endl ;
00041 using std::ostringstream ;
00042
00043 #include "PPTClient.h"
00044 #include "TcpSocket.h"
00045 #include "UnixSocket.h"
00046 #include "PPTProtocol.h"
00047 #include "BESInternalError.h"
00048 #include "TheBESKeys.h"
00049
00050 #include "config.h"
00051 #ifdef HAVE_OPENSSL
00052 #include "SSLClient.h"
00053 #endif
00054
00055 PPTClient::PPTClient( const string &hostStr, int portVal, int timeout )
00056 : PPTConnection( timeout ),
00057 _connected( false ),
00058 _host( hostStr )
00059 {
00060
00061
00062 _mySock = new TcpSocket( hostStr, portVal ) ;
00063 _mySock->connect() ;
00064 _connected = _mySock->isConnected();
00065 }
00066
00067 PPTClient::PPTClient( const string &unix_socket, int timeout )
00068 : PPTConnection( timeout ),
00069 _connected( false )
00070 {
00071
00072 _mySock = new UnixSocket( unix_socket ) ;
00073 _mySock->connect() ;
00074 _connected = true ;
00075 }
00076
00077 void
00078 PPTClient::get_secure_files()
00079 {
00080 bool found = false ;
00081 _cfile = TheBESKeys::TheKeys()->get_key( "BES.ClientCertFile", found ) ;
00082 if( !found || _cfile.empty() )
00083 {
00084 string err = "Unable to determine client certificate file." ;
00085 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00086 }
00087
00088 _kfile = TheBESKeys::TheKeys()->get_key( "BES.ClientKeyFile", found ) ;
00089 if( !found || _kfile.empty() )
00090 {
00091 string err = "Unable to determine client key file." ;
00092 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00093 }
00094 }
00095
00096 PPTClient::~PPTClient()
00097 {
00098 if( _mySock )
00099 {
00100 if( _connected )
00101 {
00102 closeConnection() ;
00103 }
00104 delete _mySock ;
00105 _mySock = 0 ;
00106 }
00107 }
00108
00109 void
00110 PPTClient::initConnection()
00111 {
00112 try
00113 {
00114 send( PPTProtocol::PPTCLIENT_TESTING_CONNECTION ) ;
00115 }
00116 catch( BESInternalError &e )
00117 {
00118 string msg = "Failed to initialize connection to server\n" ;
00119 msg += e.get_message() ;
00120 throw BESInternalError( msg, __FILE__, __LINE__ ) ;
00121 }
00122
00123 char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00124 int bytesRead = readBufferNonBlocking( inBuff ) ;
00125 if( bytesRead < 1 )
00126 {
00127 delete [] inBuff ;
00128 string err = "Could not connect to server, server may be down or busy" ;
00129 throw BESInternalError( err, __FILE__, __LINE__) ;
00130 }
00131
00132 if( bytesRead > PPT_PROTOCOL_BUFFER_SIZE )
00133 bytesRead = PPT_PROTOCOL_BUFFER_SIZE ;
00134 inBuff[bytesRead] = '\0' ;
00135 string status( inBuff, 0, bytesRead ) ;
00136 delete [] inBuff ;
00137
00138 if( status == PPTProtocol::PPT_PROTOCOL_UNDEFINED )
00139 {
00140 string err = "Could not connect to server, server may be down or busy" ;
00141 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00142 }
00143
00144 if( status == PPTProtocol::PPTSERVER_AUTHENTICATE )
00145 {
00146 authenticateWithServer() ;
00147 }
00148 else if( status != PPTProtocol::PPTSERVER_CONNECTION_OK )
00149 {
00150 string err = "Server reported an invalid connection, \""
00151 + status + "\"" ;
00152 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00153 }
00154 }
00155
00156 void
00157 PPTClient::authenticateWithServer()
00158 {
00159 #ifdef HAVE_OPENSSL
00160
00161 get_secure_files() ;
00162
00163
00164 send( PPTProtocol::PPTCLIENT_REQUEST_AUTHPORT ) ;
00165
00166
00167 char *inBuff = new char[PPT_PROTOCOL_BUFFER_SIZE+1] ;
00168 int bytesRead = readBufferNonBlocking( inBuff ) ;
00169 if( bytesRead < 1 )
00170 {
00171 delete [] inBuff ;
00172 string err = "Expecting secure port number response" ;
00173 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00174 }
00175
00176 if( bytesRead > PPT_PROTOCOL_BUFFER_SIZE )
00177 {
00178 bytesRead = PPT_PROTOCOL_BUFFER_SIZE ;
00179 }
00180 inBuff[bytesRead] = '\0' ;
00181 ostringstream portResponse( inBuff ) ;
00182 delete [] inBuff ;
00183
00184 int portVal = atoi( portResponse.str().c_str() ) ;
00185 if( portVal == 0 )
00186 {
00187 string err = "Expecting valid secure port number response" ;
00188 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00189 }
00190
00191
00192 SSLClient client( _host, portVal, _cfile, _kfile ) ;
00193 client.initConnection() ;
00194 client.closeConnection() ;
00195
00196
00197
00198 #else
00199 string err = "Server has requested authentication "
00200 + "but OpenSSL is not built into this client" ;
00201 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00202 #endif
00203 }
00204
00205 void
00206 PPTClient::closeConnection()
00207 {
00208 if( _connected )
00209 {
00210 if( !_brokenPipe )
00211 {
00212 try
00213 {
00214 sendExit() ;
00215 }
00216 catch( BESInternalError e )
00217 {
00218 cerr << "Failed to inform server that the client is exiting, "
00219 << "continuing" << endl ;
00220 cerr << e.get_message() << endl ;
00221 }
00222 }
00223
00224 _mySock->close() ;
00225
00226 _connected = false ;
00227 _brokenPipe = false ;
00228 }
00229 }
00230
00237 void
00238 PPTClient::dump( ostream &strm ) const
00239 {
00240 strm << BESIndent::LMarg << "PPTClient::dump - ("
00241 << (void *)this << ")" << endl ;
00242 BESIndent::Indent() ;
00243 strm << BESIndent::LMarg << "connected? " << _connected << endl ;
00244 strm << BESIndent::LMarg << "host: " << _host << endl ;
00245 PPTConnection::dump( strm ) ;
00246 BESIndent::UnIndent() ;
00247 }
00248