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] ;
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 string status( inBuff, 0, bytesRead ) ;
00133 delete [] inBuff ;
00134
00135 if( status == PPTProtocol::PPT_PROTOCOL_UNDEFINED )
00136 {
00137 throw PPTException( "Could not connect to server, server may be down or busy", __FILE__, __LINE__ ) ;
00138 }
00139
00140 if( status == PPTProtocol::PPTSERVER_AUTHENTICATE )
00141 {
00142 authenticateWithServer() ;
00143 }
00144 else if( status != PPTProtocol::PPTSERVER_CONNECTION_OK )
00145 {
00146 throw PPTException( "Server reported an invalid connection, \"" + status + "\"", __FILE__, __LINE__ ) ;
00147 }
00148 }
00149
00150 void
00151 PPTClient::authenticateWithServer()
00152 {
00153 #ifdef HAVE_OPENSSL
00154
00155 get_secure_files() ;
00156
00157
00158 writeBuffer( PPTProtocol::PPTCLIENT_REQUEST_AUTHPORT ) ;
00159
00160
00161 ostringstream portResponse ;
00162 bool isDone = receive( &portResponse ) ;
00163 if( isDone )
00164 {
00165 throw PPTException( "Expecting secure port number response", __FILE__, __LINE__ ) ;
00166 }
00167 int portVal = atoi( portResponse.str().c_str() ) ;
00168 if( portVal == 0 )
00169 {
00170 throw PPTException( "Expecting valid secure port number response", __FILE__, __LINE__ ) ;
00171 }
00172
00173
00174 SSLClient client( _host, portVal, _cfile, _kfile ) ;
00175 client.initConnection() ;
00176 client.closeConnection() ;
00177
00178
00179
00180 #else
00181 throw PPTException( "Server has requested authentication but OpenSSL is not built into this client", __FILE__, __LINE__ ) ;
00182 #endif
00183 }
00184
00185 void
00186 PPTClient::closeConnection()
00187 {
00188 if( _connected )
00189 {
00190 if( !_brokenPipe )
00191 {
00192 try
00193 {
00194 sendExit() ;
00195 }
00196 catch( SocketException e )
00197 {
00198 cerr << "Failed to inform server that the client is exiting, "
00199 << "continuing" << endl ;
00200 cerr << e.getMessage() << endl ;
00201 }
00202 }
00203
00204 _mySock->close() ;
00205
00206 _connected = false ;
00207 _brokenPipe = false ;
00208 }
00209 }
00210
00217 void
00218 PPTClient::dump( ostream &strm ) const
00219 {
00220 strm << BESIndent::LMarg << "PPTClient::dump - ("
00221 << (void *)this << ")" << endl ;
00222 BESIndent::Indent() ;
00223 strm << BESIndent::LMarg << "connected? " << _connected << endl ;
00224 strm << BESIndent::LMarg << "host: " << _host << endl ;
00225 PPTConnection::dump( strm ) ;
00226 BESIndent::UnIndent() ;
00227 }
00228