(file) Return to CIMServer.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Server

File: [Pegasus] / pegasus / src / Pegasus / Server / CIMServer.cpp (download)
Revision: 1.152, Sun Oct 17 19:40:12 2004 UTC (19 years, 8 months ago) by karl
Branch: MAIN
CVS Tags: RELEASE_2_4_1-BETA3, RELEASE_2_4_1-BETA2, RELEASE_2_4_1-BETA1, RELEASE_2_4_1, RELEASE_2_4_0-RC3, RELEASE_2_4_0-RC2, RELEASE_2_4_0, RELEASE_2_4-root, PEP213_SIZE_OPTIMIZATIONS, IBM_241_April1405, CHUNKTESTDONE_PEP140
Branch point for: RELEASE_2_4-branch
Changes since 1.151: +6 -4 lines
BUG#: 2196
TITLE: Copyright update

DESCRIPTION: Update all .cpp and .h files for new license and
update the doc/license.txt file.  Note that there were also
a couple of files that had to be fixed because they had violated
the comments rules (ex. blank line at head of file or in the case of
xmlwriter.cpp a comment line //=========  which drove the strip
function nuts.  These were fixed.  This has been compiled and tested
on windows.

//%2004////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation, The Open Group.
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Mike Brasher (mbrasher@bmc.com)
//
// Modified By:
//         Mike Day (mdday@us.ibm.com)s
//         Nitin Upasani, Hewlett-Packard Company (Nitin_Upasani@hp.com)
//         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
//         Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
//         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
//         Sushma Fernandes, Hewlett-Packard Company (sushma_fernandes@hp.com)
//         Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
//         Bapu Patil, Hewlett-Packard Company (bapu_patil@hp.com)
//         Dan Gorey, IBM (djgorey@us.ibm.com)
//         Heather Sterling, IBM (hsterl@us.ibm.com)
//         Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
//
//%/////////////////////////////////////////////////////////////////////////////

#include <Pegasus/Common/Config.h>

#include <cstdio>
#include <cctype>
#include <ctime>
#if defined(PEGASUS_OS_HPUX) && defined(PEGASUS_USE_RELEASE_DIRS)
#include <unistd.h>
#endif
#include <Pegasus/Common/Constants.h>
#include <Pegasus/Common/FileSystem.h>
#include <Pegasus/Common/HTTPAcceptor.h>
#include <Pegasus/Common/Tracer.h>
#include <Pegasus/Common/Cimom.h>
#include <Pegasus/Common/PegasusVersion.h>
#include <Pegasus/Common/Signal.h>

#include <Pegasus/Repository/CIMRepository.h>
#include "ProviderMessageFacade.h"
#include <Pegasus/ExportServer/CIMExportRequestDispatcher.h>
#include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
#include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
#include <Pegasus/Config/ConfigManager.h>
#include <Pegasus/Security/UserManager/UserManager.h>
#include <Pegasus/HandlerService/IndicationHandlerService.h>
#include <Pegasus/IndicationService/IndicationService.h>

#ifdef PEGASUS_ENABLE_SLP
#include <Pegasus/Client/CIMClient.h>
#endif

#ifdef PEGASUS_USE_23PROVIDER_MANAGER
#include <Pegasus/ProviderManager/ProviderManagerService.h>
#include <Pegasus/ProviderManager/ProviderManager.h>
#else
#include <Pegasus/ProviderManager2/ProviderManagerService.h>
#endif

#include "CIMServer.h"
#include "CIMOperationRequestDispatcher.h"
#include "CIMOperationResponseEncoder.h"
#include "CIMOperationRequestDecoder.h"
#include "CIMOperationRequestAuthorizer.h"
#include "HTTPAuthenticatorDelegator.h"
#include "ShutdownProvider.h"
#include "ShutdownService.h"
#include "BinaryMessageHandler.h"
#include <Pegasus/Common/ModuleController.h>
#include <Pegasus/ControlProviders/ConfigSettingProvider/ConfigSettingProvider.h>
#include <Pegasus/ControlProviders/UserAuthProvider/UserAuthProvider.h>
#include <Pegasus/ControlProviders/ProviderRegistrationProvider/ProviderRegistrationProvider.h>
#include <Pegasus/ControlProviders/NamespaceProvider/NamespaceProvider.h>

#ifdef PEGASUS_HAS_PERFINST
#include <Pegasus/ControlProviders/Statistic/CIMOMStatDataProvider.h>
#endif


#if defined(PEGASUS_HAS_PERFINST) ||  defined(PEGASUS_ENABLE_SLP)
#include <Pegasus/ControlProviders/InteropProvider/InteropProvider.h>
#endif

// l10n
#include <Pegasus/Common/MessageLoader.h>


PEGASUS_NAMESPACE_BEGIN

static CIMServer *_cimserver = NULL;

// Need a static method to act as a callback for the control provider.
// This doesn't belong here, but I don't have a better place to put it.
static Message * controlProviderReceiveMessageCallback(
    Message * message,
    void * instance)
{
    ProviderMessageFacade * mpf =
        reinterpret_cast<ProviderMessageFacade *>(instance);
    return mpf->handleRequestMessage(message);
}

//
// Linux signal handler for SIGCHLD
//
#if defined(PEGASUS_OS_LINUX) && defined(PEGASUS_HAS_SIGNALS)
#include <sys/types.h>
#include <sys/wait.h>
void childSignalHandler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
{
    PEG_METHOD_ENTER(TRC_SERVER, "childSignalHandler");

    if (s_n == PEGASUS_SIGCHLD)
    {
        PEG_TRACE_STRING(TRC_SERVER, Tracer::LEVEL4, "Caught SIGCHLD");
        pid_t cpid = 0;

#if GCC_VERSION > 30200
        while ((cpid = waitpid(0, NULL, WNOHANG | __WCLONE)) > 0);
#else
        while ((cpid = waitpid(0, NULL, WNOHANG)) > 0);
#endif
        if (cpid < 0)
        {
            Tracer::trace(TRC_SERVER, Tracer::LEVEL2,
                "waitpid error: %d", errno);
        }
    }
    PEG_METHOD_EXIT();
}
#endif

//
// Signal handler for shutdown signals, currently SIGHUP and SIGTERM
//
Boolean handleShutdownSignal = false;
void shutdownSignalHandler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
{
    PEG_METHOD_ENTER(TRC_SERVER, "shutdownSignalHandler");
    Tracer::trace(TRC_SERVER, Tracer::LEVEL2, "Signal %d received.", s_n);

    CIMServer::shutdownSignal();

    PEG_METHOD_EXIT();
}

void CIMServer::shutdownSignal()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::shutdownSignal()");
    handleShutdownSignal = true;
    _cimserver->tickle_monitor();
    PEG_METHOD_EXIT();
}


CIMServer::CIMServer(Monitor* monitor)
  : _dieNow(false), _monitor(monitor), monitor2(0), _type(OLD)
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::CIMServer()");
    _init();
    _cimserver = this;
    PEG_METHOD_EXIT();
}


CIMServer::CIMServer(monitor_2* m2)
  : _dieNow(false), _monitor(0), monitor2(m2), _type(NEW)
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::CIMServer()");
    _init();

    monitor2->set_accept_dispatch(pegasus_acceptor::accept_dispatch);
    monitor2->set_session_dispatch(HTTPConnection2::connection_dispatch);
    monitor2->set_idle_dispatch(_monitor_idle_routine);
    monitor2->set_idle_parm((void*)this);
    
    PEG_METHOD_EXIT();
}

void CIMServer::tickle_monitor(){
    _monitor->tickle();
}
void CIMServer::_init(void)
{

    String repositoryRootPath = String::EMPTY;

#ifdef PEGASUS_ENABLE_SLP
    _runSLP = true;         // Boolean cannot be set in definition.

#endif

#if defined(PEGASUS_OS_HPUX) && defined(PEGASUS_USE_RELEASE_DIRS)
    chdir( PEGASUS_CORE_DIR );
#endif
    // -- Save the monitor or create a new one:
    repositoryRootPath =
	    ConfigManager::getHomedPath(ConfigManager::getInstance()->getCurrentValue("repositoryDir"));

    // -- Create a repository:

#ifdef DO_NOT_CREATE_REPOSITORY_ON_STARTUP
    // If this code is enable, the CIMServer will fail to start
    // if the repository directory does not exit. If called,
    // the Repository will create an empty repository.

    // This check has been disabled to allow cimmof to call
    // the CIMServer to build the initial repository.
    if (!FileSystem::isDirectory(repositoryRootPath))
    {
        PEG_METHOD_EXIT();
	throw NoSuchDirectory(repositoryRootPath);

    }
#endif

    _repository = new CIMRepository(repositoryRootPath);

    // -- Create a UserManager object:

    UserManager* userManager = UserManager::getInstance(_repository);

    // -- Create a CIMServerState object:

    _serverState.reset(new CIMServerState());

    _providerRegistrationManager = new ProviderRegistrationManager(_repository);

    // -- Create queue inter-connections:

#ifdef PEGASUS_USE_23PROVIDER_MANAGER
    _providerManager = new ProviderManagerService(_providerRegistrationManager);
#else
    _providerManager = new ProviderManagerService(_providerRegistrationManager,_repository);
#endif
    _handlerService = new IndicationHandlerService(_repository);

    // Create the control service
    _controlService = new ModuleController(PEGASUS_QUEUENAME_CONTROLSERVICE);

    // Create the Configuration control provider
    ProviderMessageFacade * configProvider =
        new ProviderMessageFacade(new ConfigSettingProvider());
    ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                      PEGASUS_MODULENAME_CONFIGPROVIDER,
                                      configProvider,
                                      controlProviderReceiveMessageCallback,
                                      0, 0);

    // Create the User/Authorization control provider
    ProviderMessageFacade * userAuthProvider =
        new ProviderMessageFacade(new UserAuthProvider(_repository));
    ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                      PEGASUS_MODULENAME_USERAUTHPROVIDER,
                                      userAuthProvider,
                                      controlProviderReceiveMessageCallback,
                                      0, 0);

    // Create the Provider Registration control provider
    ProviderMessageFacade * provRegProvider = new ProviderMessageFacade(
        new ProviderRegistrationProvider(_providerRegistrationManager));
    ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                      PEGASUS_MODULENAME_PROVREGPROVIDER,
                                      provRegProvider,
                                      controlProviderReceiveMessageCallback,
                                      0, 0);

     // Create the Shutdown control provider
     ProviderMessageFacade * shutdownProvider =
         new ProviderMessageFacade(new ShutdownProvider(this));
     ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                       PEGASUS_MODULENAME_SHUTDOWNPROVIDER,
                                       shutdownProvider,
                                       controlProviderReceiveMessageCallback,
                                       0, 0);

     // Create the namespace control provider
     ProviderMessageFacade * namespaceProvider =
         new ProviderMessageFacade(new NamespaceProvider(_repository));
     ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                       PEGASUS_MODULENAME_NAMESPACEPROVIDER,
                                       namespaceProvider,
                                       controlProviderReceiveMessageCallback,
                                       0, 0);

#ifdef PEGASUS_HAS_PERFINST
                                                                                
   // Create the Statistical Data control provider
     ProviderMessageFacade * cimomstatdataProvider =
         new ProviderMessageFacade(new CIMOMStatDataProvider());
     ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                       PEGASUS_MODULENAME_CIMOMSTATDATAPROVIDER,                                       cimomstatdataProvider,
                                       controlProviderReceiveMessageCallback,
                                       0, 0);
#endif


#if defined(PEGASUS_HAS_PERFINST) ||  defined(PEGASUS_ENABLE_SLP)

// Create the interop control provider
     ProviderMessageFacade * interopProvider =
         new ProviderMessageFacade(new InteropProvider(_repository));
     ModuleController::register_module(PEGASUS_QUEUENAME_CONTROLSERVICE,
                                       PEGASUS_MODULENAME_INTEROPPROVIDER,
                                       interopProvider,
                                       controlProviderReceiveMessageCallback,
                                       0, 0);
#endif

    _cimOperationRequestDispatcher
	= new CIMOperationRequestDispatcher(_repository,
                                            _providerRegistrationManager);
    _binaryMessageHandler =
       new BinaryMessageHandler(_cimOperationRequestDispatcher);

    _cimOperationResponseEncoder
	= new CIMOperationResponseEncoder;

    //
    // get the configured authentication and authorization flags
    //
    ConfigManager* configManager = ConfigManager::getInstance();

    Boolean enableAuthentication = false;

    if (String::equalNoCase(
        configManager->getCurrentValue("enableAuthentication"), "true"))
    {
        enableAuthentication = true;
    }

    //
    // Create Authorization queue only if authentication is enabled
    //
    if ( enableAuthentication )
    {
        _cimOperationRequestAuthorizer = new CIMOperationRequestAuthorizer(
            _cimOperationRequestDispatcher);

        _cimOperationRequestDecoder = new CIMOperationRequestDecoder(
            _cimOperationRequestAuthorizer,
            _cimOperationResponseEncoder->getQueueId());
    }
    else
    {
        _cimOperationRequestAuthorizer = 0;

        _cimOperationRequestDecoder = new CIMOperationRequestDecoder(
            _cimOperationRequestDispatcher,
            _cimOperationResponseEncoder->getQueueId());

    }

    _cimExportRequestDispatcher
	= new CIMExportRequestDispatcher();

    _cimExportResponseEncoder
	= new CIMExportResponseEncoder;

    _cimExportRequestDecoder = new CIMExportRequestDecoder(
	_cimExportRequestDispatcher,
	_cimExportResponseEncoder->getQueueId());

    _httpAuthenticatorDelegator = new HTTPAuthenticatorDelegator(
        _cimOperationRequestDecoder->getQueueId(),
        _cimExportRequestDecoder->getQueueId());

    // IMPORTANT-NU-20020513: Indication service must start after ExportService
    // otherwise HandlerService started by indicationService will never
    // get ExportQueue to export indications for existing subscriptions

    _indicationService = 0;
    if (String::equal(
        configManager->getCurrentValue("enableIndicationService"), "true"))
    {
        _indicationService = new IndicationService
            (_repository, _providerRegistrationManager);
    }

    // Enable the signal handler to shutdown gracefully on SIGHUP and SIGTERM
    getSigHandle()->registerHandler(PEGASUS_SIGHUP, shutdownSignalHandler);
    getSigHandle()->activate(PEGASUS_SIGHUP);
    getSigHandle()->registerHandler(PEGASUS_SIGTERM, shutdownSignalHandler);
    getSigHandle()->activate(PEGASUS_SIGTERM);

    // Configure the signal handling behavior for SIGCHLD
#if defined (PEGASUS_OS_LINUX)
    // From signal manpage on Linux:
    //
    // "According to POSIX (3.3.1.3) it is unspecified what happens when
    // SIGCHLD is set to SIG_IGN.  Here the BSD and SYSV behaviours differ,
    // causing BSD software that sets the action for SIGCHLD to SIG_IGN to
    // fail on Linux."
    //
    // On Linux, when you perform a "system" it calls wait().  If you have
    // ignored SIGCHLD, a POSIX-conformant system is allowed to collect
    // zombies immediately rather than holding them for you to wait for.
    // And you end up with "system" returning non-zero return code instead
    // of zero return code for successful calls.
    getSigHandle()->registerHandler(PEGASUS_SIGCHLD, childSignalHandler);
    getSigHandle()->activate(PEGASUS_SIGCHLD);
#else
    SignalHandler::ignore(PEGASUS_SIGCHLD);  // Allows child death
#endif

    // Load and initialize providers registed with AutoStart = true
    _providerRegistrationManager->initializeProviders();

}




CIMServer::~CIMServer()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::~CIMServer()");

    // Note: do not delete the acceptor because it belongs to the Monitor
    // which takes care of disposing of it.

    if (_providerRegistrationManager)
    {
        delete _providerRegistrationManager;
    }

    if(_type != OLD)
    {
       pegasus_acceptor::close_all_acceptors();
    }
    

    PEG_METHOD_EXIT();
}

void CIMServer::addAcceptor(
    Boolean localConnection,
    Uint32 portNumber,
    Boolean useSSL,
    Boolean exportConnection)
{
  if(_type == OLD ){
    HTTPAcceptor* acceptor;
    if (exportConnection)
    {
      //
      // On export connection, create SSLContext with a indication
      // trust store.
      //
      acceptor = new HTTPAcceptor(_monitor,
                                _httpAuthenticatorDelegator,
                                localConnection,
                                portNumber,
                                useSSL ? _getExportSSLContext() : 0,
                                exportConnection);
    }
    else
    {
      acceptor = new HTTPAcceptor(_monitor,
                                _httpAuthenticatorDelegator,
                                localConnection,
                                portNumber,
                                useSSL ? _getSSLContext() : 0,
                                exportConnection);
    }
    _acceptors.append(acceptor);
  }
  else {
    pegasus_acceptor* acceptor =
      new pegasus_acceptor(monitor2,
			   _httpAuthenticatorDelegator,
			   localConnection,
			   portNumber,
			   useSSL ? _getSSLContext() : 0);
    acceptor->bind();
  }
}

void CIMServer::bind()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::bind()");

    if(_type == OLD) {

      if (_acceptors.size() == 0)
	{
	  // l10n

	  // throw BindFailedException("No CIM Server connections are enabled.");

	  MessageLoaderParms mlp = MessageLoaderParms("Server.CIMServer.BIND_FAILED","No CIM Server connections are enabled.");

	  throw BindFailedException(mlp);
	}

      for (Uint32 i=0; i<_acceptors.size(); i++)
	{
	  _acceptors[i]->bind();
	}
    }

    PEG_METHOD_EXIT();
}


void CIMServer::_monitor_idle_routine(void *parm)
{
   CIMServer* myself = static_cast<CIMServer* >(parm);
   
   try
   {
      MessageQueueService::_check_idle_flag = 1;
      MessageQueueService::_polling_sem.signal();
      
#ifdef PEGASUS_USE_23PROVIDER_MANAGER
      ProviderManagerService::getProviderManager()->unload_idle_providers();
#else
      myself->_providerManager->unloadIdleProviders();
#endif
      
   }
   catch(...)
   {
   }
   if (handleShutdownSignal)
   {
      Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
		    "CIMServer::runForever - signal received.  Shutting down.");
      myself->monitor2->stop();
      
      ShutdownService::getInstance(myself)->shutdown(true, 10, false);
//      MessageQueueService::force_shutdown(true);
      
      handleShutdownSignal = false;
   }
}

monitor_2* CIMServer::get_monitor2(void)
{
   return monitor2;
}


void CIMServer::runForever()
{
  if(_type == OLD) {

    // Note: Trace code in this method will be invoked frequently.

    if(!_dieNow)
      {
#ifdef PEGASUS_ENABLE_SLP
	// Note - this func prevents multiple starting of slp provider
	startSLPProvider();
#endif

	if(false == _monitor->run(500000))
	{
	  try
	  {
	    MessageQueueService::_check_idle_flag = 1;
	    MessageQueueService::_polling_sem.signal();
		
#ifdef PEGASUS_USE_23PROVIDER_MANAGER
	    ProviderManagerService::getProviderManager()->unload_idle_providers();
#else
	    _providerManager->unloadIdleProviders();
#endif
	  }
	  catch(...)
	  {
	  }
	}

	if (handleShutdownSignal)
	{
	  Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
			"CIMServer::runForever - signal received.  Shutting down.");
	  ShutdownService::getInstance(this)->shutdown(true, 10, false);
	  // Set to false must be after call to shutdown.  See
	  // stopClientConnection.
	  handleShutdownSignal = false;
	}
      }
  }
  else {
    monitor2->run();
//    MessageQueueService::force_shutdown(true);
  }

}

void CIMServer::stopClientConnection()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::stopClientConnection()");

    if(_type == OLD) 
    {
        // tell Monitor to stop listening for client connections
        if (handleShutdownSignal)
	  // If shutting down, this is in the same thread as runForever.
	  // No need to wait for the thread to see the stop flag.
	  _monitor->stopListeningForConnections(false);
	else
	  // If not shutting down, this is not in the same thread as runForever.
	  // Need to wait for the thread to see the stop flag.
	  _monitor->stopListeningForConnections(true);

        //
        // Wait 150 milliseconds to allow time for the Monitor to stop 
        // listening for client connections.  
        //
        // This wait time is the timeout value for the select() call
        // in the Monitor's run() method (currently set to 100 
        // milliseconds) plus a delta of 50 milliseconds.  The reason
        // for the wait here is to make sure that the Monitor entries
        // are updated before closing the connection sockets.
        //
        // PEG_TRACE_STRING(TRC_SERVER, Tracer::LEVEL4, "Wait 150 milliseconds.");
	//  pegasus_sleep(150);  not needed anymore due to the semaphore
	// in the monitor

        for (Uint32 i=0; i<_acceptors.size(); i++)
	{
	  _acceptors[i]->closeConnectionSocket();
	}
    }

    PEG_METHOD_EXIT();
}

void CIMServer::shutdown()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::shutdown()");

    _dieNow = true;
    if(_type == OLD) {
      _cimserver->tickle_monitor();
    }

    PEG_METHOD_EXIT();
}

void CIMServer::resume()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::resume()");

    for (Uint32 i=0; i<_acceptors.size(); i++)
    {
        _acceptors[i]->reopenConnectionSocket();
    }

    PEG_METHOD_EXIT();
}

void CIMServer::setState(Uint32 state)
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::setState()");

    _serverState->setState(state);

    //
    // get the configured authentication and authorization flags
    //
    ConfigManager* configManager = ConfigManager::getInstance();

    Boolean enableAuthentication = false;
    Boolean enableNamespaceAuthorization = false;

    if (String::equal(
        configManager->getCurrentValue("enableAuthentication"), "true"))
    {
        enableAuthentication = true;
    }

    if (String::equal(
        configManager->getCurrentValue("enableNamespaceAuthorization"), "true"))
    {
        enableNamespaceAuthorization = true;
    }

    if (state == CIMServerState::TERMINATING)
    {
        // tell decoder that CIMServer is terminating
        _cimOperationRequestDecoder->setServerTerminating(true);
        _cimExportRequestDecoder->setServerTerminating(true);

        // tell authorizer that CIMServer is terminating ONLY if
        // authentication and authorization are enabled
        //
        if ( enableAuthentication && enableNamespaceAuthorization )
        {
            _cimOperationRequestAuthorizer->setServerTerminating(true);
        }
    }
    else
    {
        // tell decoder that CIMServer is not terminating
        _cimOperationRequestDecoder->setServerTerminating(false);
        _cimExportRequestDecoder->setServerTerminating(false);

        // tell authorizer that CIMServer is terminating ONLY if
        // authentication and authorization are enabled
        //
        if ( enableAuthentication && enableNamespaceAuthorization )
        {
            _cimOperationRequestAuthorizer->setServerTerminating(false);
        }
    }
    PEG_METHOD_EXIT();
}

Uint32 CIMServer::getOutstandingRequestCount()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::getOutstandingRequestCount()");

    Uint32 requestCount = 0;

    if(_type == OLD) {
      for (Uint32 i=0; i<_acceptors.size(); i++)
	{
	  requestCount += _acceptors[i]->getOutstandingRequestCount();
	}
    }

    PEG_METHOD_EXIT();
    return requestCount;
}


Boolean verifyClientOptionalCallback(SSLCertificateInfo &certInfo)
{
    // SSL callback for the "optional" client verification setting
    // By always returning true, we allow the handshake to continue
    // even if the client sent no certificate or sent an untrusted certificate.
    return true;
}


SSLContext* CIMServer::_getSSLContext()
{
    static String PROPERTY_NAME__SSL_CERT_FILEPATH = "sslCertificateFilePath";
    static String PROPERTY_NAME__SSL_KEY_FILEPATH  = "sslKeyFilePath";
    static String PROPERTY_NAME__SSL_TRUST_STORE  = "sslTrustStore";
    static String PROPERTY_NAME__SSL_CLIENT_VERIFICATION = "sslClientVerificationMode";
    static String PROPERTY_NAME__SSL_AUTO_TRUST_STORE_UPDATE = "enableSSLTrustStoreAutoUpdate";
    static String PROPERTY_NAME__SSL_TRUST_STORE_USERNAME = "sslTrustStoreUserName";
	static String PROPERTY_NAME__HTTP_ENABLED = "enableHttpConnection";

    if (_sslcontext.get() == 0)
    {
        // Note that if invalid values were set for either sslKeyFilePath, sslCertificateFilePath, or sslTrustStore,
        // the invalid paths would have been detected in SecurityPropertyOwner and terminated the server startup.
        // This happens regardless of whether or not HTTPS is enabled (not a great design, but that seems to be
        // how other properties are validated as well)

        //
        // Get the sslClientVerificationMode property from the Config Manager.
        //
        String verifyClient = String::EMPTY;
        verifyClient = ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSL_CLIENT_VERIFICATION);

        //
        // Get the sslTrustStore property from the Config Manager.
        //
        String trustStore = String::EMPTY;
        trustStore = ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSL_TRUST_STORE);

        if (trustStore != String::EMPTY) 
        {
            trustStore = ConfigManager::getHomedPath(trustStore);
        }

        //
        // Get the enableSSLAutoTrustStoreUpdate property from the Config Manager.
		// Note that this feature is only exposed via the compile-time flag PEGASUS_USE_AUTOMATIC_TRUSTSTORE_UPDATE
		// It will be deprecated in the future in favor of better certificate management.  See PEP165.
        //
        String autoUpdate = "false";

#ifdef PEGASUS_USE_AUTOMATIC_TRUSTSTORE_UPDATE
        autoUpdate = ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSL_AUTO_TRUST_STORE_UPDATE);
#endif

        //
        // Get the sslTrustStoreUserName property from the Config Manager.
        //
        String trustStoreUserName = String::EMPTY;
        trustStoreUserName = ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSL_TRUST_STORE_USERNAME);

		if (!String::equal(verifyClient, "disabled")) 
		{
			//
			// 'required' setting must have a valid truststore
			// 'optional' setting can be used with or without a truststore; log a warning if a truststore is not specified
			//
			if (trustStore == String::EMPTY) 
			{
				if (String::equal(verifyClient, "required")) 
				{
					MessageLoaderParms parms("Server.CIMServer.SSL_CLIENT_VERIFICATION_EMPTY_TRUSTSTORE",
											 "The \"sslTrustStore\" configuration property must be set if \"sslClientVerificationMode\" is 'required'. cimserver not started.");
                    throw SSLException(parms);
                }
				else if (String::equal(verifyClient, "optional")) 
				{
					Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING, 
								"SSL client verification is enabled but no truststore was specified.");
				}
			}
	
			//
			// ATTN: 'required' setting must have http port enabled.  
			// If only https is enabled, and a call to shutdown the cimserver is given, the call will hang
			// and a forced shutdown will ensue.  This is because the CIMClient::connectLocal call cannot
			// (and should not) specify a truststore to validate the local server against.  This limitation
			// is being investigated.
			//
			if (String::equal(verifyClient, "required")) 
			{
				String httpEnabled = ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__HTTP_ENABLED);
				if (!String::equal(httpEnabled, "true")) 
				{
					MessageLoaderParms parms("Server.CIMServer.SSL_CLIENT_VERIFICATION_HTTP_NOT_ENABLED_WITH_REQUIRED",
											 "The HTTP port must be enabled if \"sslClientVerificationMode\" is 'required' in order for the cimserver to properly shutdown. cimserver not started.");
                    throw SSLException(parms);
                }
			} 
	
    	    //
            // a truststore username must be specified if sslClientVerificationMode is required OR
    		// sslClientVerificationMode is optional and a truststore is specified.
    		//
            if (String::equal(verifyClient, "required") || (String::equal(verifyClient, "optional") && trustStore != String::EMPTY))
    		{
                if (trustStoreUserName == String::EMPTY)
                {
                    MessageLoaderParms parms("Server.CIMServer.SSL_CLIENT_VERIFICATION_EMPTY_USERNAME",
                                             "The \"sslTrustStoreUserName\" property must specify a truststore username to associate with the trusted certificates if \"sslClientVerificationMode\" is 'required' or 'optional', and a truststore is specified. cimserver not started.");
                    throw SSLException(parms);
                }
            }
		}
	
		//
        // 'autoUpdate' must be used in conjunction with an 'optional' verification mode
		//
        if (String::equal(autoUpdate, "true") && !(String::equal(verifyClient, "optional")))
        {
			MessageLoaderParms parms("Server.CIMServer.SSL_CLIENT_VERIFICATION_INVALID_AUTO_UPDATE_MODE",
									 "The \"enableSSLTrustStoreAutoUpdate\" property can only be 'true' if \"sslClientVerificationMode\" is 'optional'. cimserver not started.");
            throw SSLException(parms);
        }

		//
        // 'autoUpdate' must be used in conjunction with a truststore DIRECTORY
		//
        FileSystem::translateSlashes(trustStore);                              
        if (String::equal(autoUpdate, "true") && !FileSystem::isDirectory(trustStore)) 
        {
			MessageLoaderParms parms("Server.CIMServer.SSL_CLIENT_VERIFICATION_INVALID_AUTO_UPDATE_DIRECTORY",
									 "The \"sslTrustStore\" value must be a valid directory if \"enableSSLTrustStoreAutoUpdate\" is 'true'. cimserver not started.");
            throw SSLException(parms);
        }
        
        //
        // Get the sslCertificateFilePath property from the Config Manager.
        //
        String certPath;
		certPath = ConfigManager::getHomedPath(
			ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSL_CERT_FILEPATH));

		//
        // Get the sslKeyFilePath property from the Config Manager.
        //
        String keyPath;
        keyPath = ConfigManager::getHomedPath(
			ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSL_KEY_FILEPATH));

        String randFile = String::EMPTY;

#ifdef PEGASUS_SSL_RANDOMFILE
        // NOTE: It is technically not necessary to set up a random file on
        // the server side, but it is easier to use a consistent interface
        // on the client and server than to optimize out the random file on
        // the server side.
        randFile = ConfigManager::getHomedPath(PEGASUS_SSLSERVER_RANDOMFILE);
#endif

        Boolean trustStoreAutoUpdate =  (String::equal(autoUpdate, "true") ? true : false);   

        if (String::equal(verifyClient, "required"))
        {
            Tracer::trace(TRC_SSL, Tracer::LEVEL2,
                "SSL Client verification REQUIRED.");

#ifdef PEGASUS_USE_AUTOMATIC_TRUSTSTORE_UPDATE
            _sslcontext.reset(new SSLContext(trustStore, certPath, keyPath, 0, false, trustStoreUserName, randFile));        
#else
            _sslcontext.reset(new SSLContext(trustStore, certPath, keyPath, 0, trustStoreUserName, randFile));
#endif
        } 
        else if (String::equal(verifyClient, "optional"))
        {
            Tracer::trace(TRC_SSL, Tracer::LEVEL2,
                "SSL Client verification OPTIONAL.");

#ifdef PEGASUS_USE_AUTOMATIC_TRUSTSTORE_UPDATE
            _sslcontext.reset(new SSLContext(trustStore, certPath, keyPath, (SSLCertificateVerifyFunction*)verifyClientOptionalCallback, trustStoreAutoUpdate, trustStoreUserName, randFile));
#else
            _sslcontext.reset(new SSLContext(trustStore, certPath, keyPath, (SSLCertificateVerifyFunction*)verifyClientOptionalCallback, trustStoreUserName, randFile));
#endif
        }
        else if (String::equal(verifyClient, "disabled") || verifyClient == String::EMPTY)
        {
            Tracer::trace(TRC_SSL, Tracer::LEVEL2,
                "SSL Client verification DISABLED.");

#ifdef PEGASUS_USE_AUTOMATIC_TRUSTSTORE_UPDATE
            _sslcontext.reset(new SSLContext(String::EMPTY, certPath, keyPath, 0, false, String::EMPTY, randFile));       
#else
            _sslcontext.reset(new SSLContext(String::EMPTY, certPath, keyPath, 0, String::EMPTY, randFile));
#endif
        }
    }

    return _sslcontext.release();
}

SSLContext* CIMServer::_getExportSSLContext()
{
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::_getExportSSLContext()");

    static const String PROPERTY_NAME__EXPORT_SSLTRUST_STORE = "exportSSLTrustStore";
    static const String PROPERTY_NAME__SSLCERT_FILEPATH = "sslCertificateFilePath";
    static const String PROPERTY_NAME__SSLKEY_FILEPATH  = "sslKeyFilePath";

    if (_exportSSLContext.get() == 0)
    {
        //
        // Get the exportSSLTrustStore property from the Config Manager.
        //
        String trustStore = ConfigManager::getInstance()->getCurrentValue(
                                      PROPERTY_NAME__EXPORT_SSLTRUST_STORE);

        if (trustStore == String::EMPTY)
        {
            MessageLoaderParms parms("Server.CIMServer.EXPORT_TRUST_EMPTY",
                "The \"exportSSLTrustStore\" configuration property must be set when \"enableSSLExportClientVerification\" is true. cimserver not started.");

            PEG_METHOD_EXIT();
            throw Exception(parms);
        }

        String trustPath = ConfigManager::getHomedPath(trustStore);

        PEG_TRACE_STRING(TRC_SERVER, Tracer::LEVEL2,
            "Using the export trust store : " + trustPath);

        //
        // Get the sslCertificateFilePath property from the Config Manager.
        //
        String certPath = String::EMPTY;
        certPath = ConfigManager::getHomedPath(
            ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSLCERT_FILEPATH));

        //
        // Get the sslKeyFilePath property from the Config Manager.
        //
        String keyPath = String::EMPTY;
        keyPath = ConfigManager::getHomedPath(
            ConfigManager::getInstance()->getCurrentValue(PROPERTY_NAME__SSLKEY_FILEPATH));

        String randFile = String::EMPTY;

#ifdef PEGASUS_SSL_RANDOMFILE
        // NOTE: It is technically not necessary to set up a random file on
        // the server side, but it is easier to use a consistent interface
        // on the client and server than to optimize out the random file on
        // the server side.
        randFile = ConfigManager::getHomedPath(PEGASUS_SSLSERVER_RANDOMFILE);
#endif

        //
        // Note: Trust store is used by default on Export connections,
        // verification callback function is not used.
        //
        _exportSSLContext.reset(new SSLContext(trustPath, certPath, keyPath, 0, randFile));
    }

    PEG_METHOD_EXIT();
    return _exportSSLContext.release();
}

#ifdef PEGASUS_ENABLE_SLP
PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _callSLPProvider(void *parm);


// This is a control function that starts a new thread which issues a
// cim operation to start the slp provider.
void CIMServer::startSLPProvider()
{

   PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, "CIMServer::startSLPProvider");

    
    // This is a onetime function.  If already issued, or config is not to use simply
    // return
    if (!_runSLP)
    {
        return;
    }

    // Get Config parameter to determine if we should start SLP.
    ConfigManager* configManager = ConfigManager::getInstance();
    _runSLP = String::equal(
         configManager->getCurrentValue("slp"), "true");

    // If false, do not start slp provider
    if (!_runSLP)
    {
        return;
    }
    //SLP startup is onetime function; reset the switch so this
    // function does not get called a second time.
    _runSLP = false;

    // Create a separate thread, detach and call function to execute the startup.
    Thread t( _callSLPProvider, 0, true );
    t.run();

    PEG_METHOD_EXIT();
    return;
}


// startSLPProvider is a function to get the slp provider kicked off
// during startup.  It is placed in the provider manager simply because 
// the provider manager is the only component of the system is
// driven by a timer after startup.  It should never be here and must be
// moved to somewhere more logical or really replaced. We simply needed
// something that was run shortly after system startup.
// This function is assumed to operate in a separate thread and 
// KS 15 February 2004.

PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _callSLPProvider(void* parm )
{
    //
    PEG_METHOD_ENTER(TRC_SERVER, "CIMServer::_callSLPProvider()");
    // Create CIMClient object
    //
    CIMClient client;
    //
    // open connection to CIMOM 
    //
    String hostStr = System::getHostName();

    try
    {
        //
        client.connectLocal();

        //
        // set client timeout to 2 seconds
        //
        client.setTimeout(40000);
        // construct CIMObjectPath
        //
        String referenceStr = "//";
        referenceStr.append(hostStr);
        referenceStr.append("/");  
        referenceStr.append(PEGASUS_NAMESPACENAME_INTERNAL.getString());
        referenceStr.append(":");
        referenceStr.append(PEGASUS_CLASSNAME_WBEMSLPTEMPLATE.getString());
        CIMObjectPath reference(referenceStr);

        //
        // issue the invokeMethod request on the register method
        //
        Array<CIMParamValue> inParams;
        Array<CIMParamValue> outParams;

        CIMValue retValue = client.invokeMethod(
            PEGASUS_NAMESPACENAME_INTERNAL,
            reference,
            CIMName("register"),
            inParams,
            outParams
            );
    }

    catch(CIMException& e)
    {
        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
            "SLP Registration Failed. CIMException. $0", e.getMessage());
    }

    catch(Exception& e)
    {
        Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
            "SLP Registration Failed Startup: CIMServer exception. $0", e.getMessage());
    }

    client.disconnect();

    Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
        "SLP Registration Initiated");

    PEG_METHOD_EXIT();
    return( (PEGASUS_THREAD_RETURN)32 );
}
#endif

PEGASUS_NAMESPACE_END




No CVS admin address has been configured
Powered by
ViewCVS 0.9.2