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