PPTClient.cc

Go to the documentation of this file.
00001 // PPTClient.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 // 
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025  
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
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     // connect to the specified host at the specified socket to handle the
00062     // secure connection
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     // connect to the specified unix socket to handle the secure connection
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     // get the certificate and key file information
00155     get_secure_files() ;
00156 
00157     // send request for the authentication port
00158     writeBuffer( PPTProtocol::PPTCLIENT_REQUEST_AUTHPORT ) ;
00159 
00160     // receive response with port, terminated with TERMINATE token
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     // authenticate using SSLClient
00174     SSLClient client( _host, portVal, _cfile, _kfile ) ;
00175     client.initConnection() ;
00176     client.closeConnection() ;
00177 
00178     // If it authenticates, good, if not then an exception is thrown. We
00179     // don't need to do anything else here.
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 

Generated on Wed Aug 29 02:59:01 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2