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

Generated on Tue Mar 4 23:13:37 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.1