PPTServer.cc

Go to the documentation of this file.
00001 // PPTServer.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-2009 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 <config.h>
00034 
00035 #include <string>
00036 #include <sstream>
00037 #include <cstdlib>
00038 
00039 using std::string ;
00040 using std::ostringstream ;
00041 
00042 #include "PPTServer.h"
00043 #include "BESInternalError.h"
00044 #include "PPTProtocol.h"
00045 #include "SocketListener.h"
00046 #include "ServerHandler.h"
00047 #include "Socket.h"
00048 #include "TheBESKeys.h"
00049 #include "BESDebug.h"
00050 
00051 #include "config.h"
00052 #ifdef HAVE_OPENSSL
00053 #include "SSLServer.h"
00054 #endif
00055 
00056 #define PPT_SERVER_DEFAULT_TIMEOUT 1
00057 
00058 PPTServer::PPTServer( ServerHandler *handler,
00059                       SocketListener *listener,
00060                       bool isSecure )
00061     : PPTConnection( PPT_SERVER_DEFAULT_TIMEOUT),
00062       _handler( handler ),
00063       _listener( listener ),
00064       _secure( isSecure )
00065 {
00066     if( !handler )
00067     {
00068         string err( "Null handler passed to PPTServer" ) ;
00069         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00070     }
00071     if( !listener )
00072     {
00073         string err( "Null listener passed to PPTServer" ) ;
00074         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00075     }
00076 #ifndef HAVE_OPENSSL
00077     if( _secure )
00078     {
00079         string err("Server requested to be secure but OpenSSL is not built in");
00080         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00081     }
00082 #endif
00083 
00084     // get the certificate and key file information
00085     if( _secure )
00086     {
00087         get_secure_files() ;
00088     }
00089 }
00090 
00091 PPTServer::~PPTServer()
00092 {
00093 }
00094 
00095 void
00096 PPTServer::get_secure_files()
00097 {
00098     bool found = false ;
00099     _cfile = TheBESKeys::TheKeys()->get_key( "BES.ServerCertFile", found ) ;
00100     if( !found || _cfile.empty() )
00101     {
00102         string err = "Unable to determine server certificate file." ;
00103         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00104     }
00105 
00106     found = false ;
00107     _cafile = TheBESKeys::TheKeys()->get_key( "BES.ServerCertAuthFile", found );
00108     if( !found || _cafile.empty() )
00109     {
00110         string err = "Unable to determine server certificate authority file." ;
00111         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00112     }
00113 
00114     _kfile = TheBESKeys::TheKeys()->get_key( "BES.ServerKeyFile", found ) ;
00115     if( !found || _kfile.empty() )
00116     {
00117         string err = "Unable to determine server key file." ;
00118         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00119     }
00120 
00121     string portstr =
00122         TheBESKeys::TheKeys()->get_key( "BES.ServerSecurePort", found ) ;
00123     if( !found || portstr.empty() )
00124     {
00125         string err = "Unable to determine secure connection port." ;
00126         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00127     }
00128     _securePort = atoi( portstr.c_str() ) ;
00129     if( !_securePort )
00130     {
00131         string err = (string)"Unable to determine secure connection port "
00132                      + "from string " + portstr ;
00133         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00134     }
00135 }
00136 
00142 void
00143 PPTServer::initConnection()
00144 {
00145     for(;;)
00146     {
00147         _mySock = _listener->accept() ;
00148         if( _mySock )
00149         {
00150             if( _mySock->allowConnection() == true )
00151             {
00152                 // welcome the client
00153                 if( welcomeClient( ) != -1 )
00154                 {
00155                     // now hand it off to the handler
00156                     _handler->handle( this ) ;
00157                 }
00158             }
00159             else
00160             {
00161                _mySock->close();
00162             }
00163         }
00164     }
00165 }
00166 
00167 void
00168 PPTServer::closeConnection()
00169 {
00170     if( _mySock ) _mySock->close() ;
00171 }
00172 
00173 int
00174 PPTServer::welcomeClient()
00175 {
00176     // Doing a non blocking read in case the connection is being initiated
00177     // by a non-bes client. Don't want this to block. pcw - 3/5/07
00178     // int bytesRead = _mySock->receive( inBuff, ppt_buffer_size ) ;
00179     //
00180     // We are receiving handshaking tokens, so the buffer doesn't need to be
00181     // all that big. pcw - 05/31/08
00182     unsigned int ppt_buffer_size = 64 ;
00183     char *inBuff = new char[ppt_buffer_size+1] ;
00184     int bytesRead = readBufferNonBlocking( inBuff, ppt_buffer_size ) ;
00185 
00186     // if the read of the initial connection fails or blocks, then return
00187     if( bytesRead == -1 )
00188     {
00189         _mySock->close() ;
00190         delete [] inBuff ;
00191         return -1 ;
00192     }
00193 
00194     string status( inBuff, bytesRead ) ;
00195     delete [] inBuff ;
00196 
00197     if( status != PPTProtocol::PPTCLIENT_TESTING_CONNECTION )
00198     {
00199         /* If cannot negotiate with the client then we don't want to exit
00200          * by throwing an exception, we want to return and let the caller
00201          * clean up the connection
00202          */
00203         string err( "PPT cannot negotiate, " ) ;
00204         err += " client started the connection with " + status ;
00205         BESDEBUG( "ppt", err << endl )
00206         //throw BESInternalError( err, __FILE__, __LINE__ ) ;
00207         send( err ) ;
00208         _mySock->close() ;
00209         return -1 ;
00210     }
00211 
00212     if( !_secure )
00213     {
00214         send( PPTProtocol::PPTSERVER_CONNECTION_OK ) ;
00215     }
00216     else
00217     {
00218         authenticateClient() ;
00219     }
00220 
00221     return  0 ;
00222 }
00223 
00224 void
00225 PPTServer::authenticateClient()
00226 {
00227 #ifdef HAVE_OPENSSL
00228     BESDEBUG( "ppt", "requiring secure connection: port = " << _securePort << endl )
00229     // let the client know that it needs to authenticate
00230     send( PPTProtocol::PPTSERVER_AUTHENTICATE ) ;
00231 
00232     // wait for the client request for the secure port
00233     // We are waiting for a ppt tocken requesting the secure port number.
00234     // The buffer doesn't need to be all that big. pcw - 05/31/08
00235     unsigned int ppt_buffer_size = 64 ;
00236     char *inBuff = new char[ppt_buffer_size] ;
00237     int bytesRead = _mySock->receive( inBuff, ppt_buffer_size ) ;
00238     string portRequest( inBuff, bytesRead ) ;
00239     delete [] inBuff ;
00240     if( portRequest != PPTProtocol::PPTCLIENT_REQUEST_AUTHPORT )
00241     {
00242         string err( "Secure connection ... expecting request for port" ) ;
00243         err += " client requested " + portRequest ;
00244         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00245     }
00246 
00247     // send the secure port number back to the client
00248     ostringstream portResponse ;
00249     portResponse << _securePort << PPTProtocol::PPT_COMPLETE_DATA_TRANSMITION ;
00250     send( portResponse.str() ) ;
00251 
00252     // create a secure server object and authenticate
00253     SSLServer server( _securePort, _cfile, _cafile, _kfile ) ;
00254     server.initConnection() ;
00255     server.closeConnection() ;
00256 
00257     // if it authenticates, good, if not, an exception is thrown, no need to
00258     // do anything else here.
00259 #else
00260     string err = (string)"Authentication requested for this server "
00261                  + "but OpenSSL is not built into the server" ;
00262     throw BESInternalError( err, __FILE__, __LINE__ ) ;
00263 #endif
00264 }
00265 
00272 void
00273 PPTServer::dump( ostream &strm ) const
00274 {
00275     strm << BESIndent::LMarg << "PPTServer::dump - ("
00276                              << (void *)this << ")" << endl ;
00277     BESIndent::Indent() ;
00278     if( _handler )
00279     {
00280         strm << BESIndent::LMarg << "server handler:" << endl ;
00281         BESIndent::Indent() ;
00282         _handler->dump( strm ) ;
00283         BESIndent::UnIndent() ;
00284     }
00285     else
00286     {
00287         strm << BESIndent::LMarg << "server handler: null" << endl ;
00288     }
00289     if( _listener )
00290     {
00291         strm << BESIndent::LMarg << "listener:" << endl ;
00292         BESIndent::Indent() ;
00293         _listener->dump( strm ) ;
00294         BESIndent::UnIndent() ;
00295     }
00296     else
00297     {
00298         strm << BESIndent::LMarg << "listener: null" << endl ;
00299     }
00300     strm << BESIndent::LMarg << "secure? " << _secure << endl ;
00301     if( _secure )
00302     {
00303         BESIndent::Indent() ;
00304         strm << BESIndent::LMarg << "cert file: " << _cfile << endl ;
00305         strm << BESIndent::LMarg << "cert authority file: " << _cafile << endl ;
00306         strm << BESIndent::LMarg << "key file: " << _kfile << endl ;
00307         strm << BESIndent::LMarg << "secure port: " << _securePort << endl ;
00308         BESIndent::UnIndent() ;
00309     }
00310     PPTConnection::dump( strm ) ;
00311     BESIndent::UnIndent() ;
00312 }
00313 

Generated on Sat Aug 22 06:04:40 2009 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.6.0