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 
00037 #include "OW_config.h"
00038 #include "OW_HTTPServer.hpp"
00039 #include "OW_HTTPSvrConnection.hpp"
00040 #include "OW_ServerSocket.hpp"
00041 #include "OW_IOException.hpp"
00042 #include "OW_Socket.hpp"
00043 #include "OW_Format.hpp"
00044 #include "OW_SelectableIFC.hpp"
00045 #include "OW_Assertion.hpp"
00046 #include "OW_ConfigOpts.hpp"
00047 #include "OW_HTTPUtils.hpp"
00048 #ifndef OW_DISABLE_DIGEST
00049 #include "OW_DigestAuthentication.hpp"
00050 #endif
00051 #include "OW_CIMOMHandleIFC.hpp"
00052 #include "OW_SocketBaseImpl.hpp" 
00053 #include "OW_Runnable.hpp"
00054 #include "OW_ThreadCancelledException.hpp"
00055 #include "OW_ThreadPool.hpp"
00056 #include "OW_ExceptionIds.hpp"
00057 #ifndef OW_WIN32
00058 #include "OW_UnnamedPipe.hpp"
00059 #include "OW_LocalAuthentication.hpp"
00060 #endif
00061 #include "OW_SSLException.hpp"
00062 #include "OW_SSLCtxMgr.hpp"
00063 #include "OW_AuthenticationException.hpp"
00064 #include "OW_OperationContext.hpp"
00065 #include "OW_ServiceIFCNames.hpp"
00066 #include "OW_Thread.hpp" 
00067 
00068 namespace OW_NAMESPACE
00069 {
00070 
00071 OW_DEFINE_EXCEPTION_WITH_ID(HTTPServer)
00072 
00073 namespace
00074 {
00075    const String COMPONENT_NAME("ow.httpserver");
00076 
00077 #ifdef OW_HAVE_OPENSSL
00078    class X509Freer
00079    {
00080    public:
00081       X509Freer(X509* x509)
00082          : m_x509(x509)
00083       {
00084       }
00085       ~X509Freer()
00086       {
00087          if (m_x509 != 0)
00088          {
00089             X509_free(m_x509);
00090          }
00091       }
00092    private:
00093       X509* m_x509;
00094    };
00095 #endif
00096 
00097 }
00098 
00100 HTTPServer::HTTPServer()
00101 #ifdef OW_WIN32
00102    : m_event(NULL)
00103 #else
00104    : m_upipe(UnnamedPipe::createUnnamedPipe())
00105 #endif
00106    , m_allowAllUsers(false)
00107    , m_sslCtx(0)
00108    , m_shuttingDown(false)
00109 #ifndef OW_NO_SSL
00110    , m_trustStore(0)
00111 #endif
00112 {
00113 #ifdef OW_WIN32
00114    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00115 #else
00116    m_upipe->setBlocking(UnnamedPipe::E_NONBLOCKING);
00117 #endif
00118 }
00120 HTTPServer::~HTTPServer()
00121 {
00122 }
00123 
00124 
00126 String
00127 HTTPServer::getName() const
00128 {
00129    return ServiceIFCNames::HTTPServer;
00130 }
00131 
00133 StringArray
00134 HTTPServer::getDependencies() const
00135 {
00136    StringArray rv;
00137    rv.push_back(ServiceIFCNames::CIMServer);
00138    rv.push_back(ServiceIFCNames::AuthManager);
00139    return rv;
00140 }
00141 
00143 bool HTTPServer::isAllowedUser(const String& user) const
00144 {
00145    return m_allowedUsers.count(user) != 0 || m_allowAllUsers;
00146 }
00147 
00149 bool
00150 HTTPServer::authenticate(HTTPSvrConnection* pconn,
00151    String& userName, const String& info, OperationContext& context,
00152    const Socket& socket)
00153 {
00154    MutexLock lock(m_authGuard);
00155    String scheme; 
00156    if (!info.empty())
00157    {
00158       scheme = info.tokenize()[0]; 
00159       scheme.toLowerCase(); 
00160    }
00161 
00162    
00163    
00164 #ifndef OW_WIN32
00165    if (m_options.allowLocalAuthentication && scheme.equals("owlocal"))
00166    {
00167       OW_LOG_DEBUG(getEnvironment()->getLogger(COMPONENT_NAME), "HTTPServer::authenticate: processing OWLocal");
00168       bool rv = m_localAuthentication->authenticate(userName, info, pconn) && isAllowedUser(userName);
00169       if (rv)
00170       {
00171          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authenticated %1", userName));
00172       }
00173       else
00174       {
00175          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authentication failed for: %1", userName));
00176       }
00177       return rv;
00178    }
00179 #endif
00180 
00181 #ifndef OW_NO_SSL
00182    if (m_sslopts.verifyMode != SSLOpts::MODE_DISABLED)
00183    {
00184       if (socket.peerCertVerified())
00185       {
00186          SSL* ssl = socket.getSSL();
00187          OW_ASSERT(ssl);
00188          X509* cert = SSL_get_peer_certificate(ssl);
00189          OW_ASSERT(cert);
00190          X509Freer x509Freer(cert);
00191          String hash = SSLTrustStore::getCertMD5Fingerprint(cert);
00192          String uid;
00193          if (!m_trustStore->getUser(hash, userName, uid))
00194          {
00195             OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authentication failed for: %1.  (Cert verified, but unknown user)", userName));
00196             return false;
00197          }
00198          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authenticated %1", userName));
00199          if (!uid.empty())
00200          {
00201             context.setStringData(OperationContext::CURUSER_UIDKEY, uid);
00202          }
00203          return true;
00204       }
00205    }
00206 #endif
00207    bool rv = false;
00208    if (m_options.allowDigestAuthentication && scheme.equals("digest"))
00209    {
00210 #ifndef OW_DISABLE_DIGEST
00211       OW_LOG_DEBUG(getEnvironment()->getLogger(COMPONENT_NAME), "HTTPServer::authenticate: processing Digest");
00212       rv = m_digestAuthentication->authenticate(userName, info, pconn) && isAllowedUser(userName);
00213       if (rv)
00214       {
00215          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authenticated %1", userName));
00216       }
00217       else
00218       {
00219          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authentication failed for: %1", userName));
00220       }
00221 #endif
00222    }
00223    else if (m_options.allowBasicAuthentication && scheme.equals("basic"))
00224    {
00225       OW_LOG_DEBUG(getEnvironment()->getLogger(COMPONENT_NAME), "HTTPServer::authenticate: processing Basic");
00226       String authChallenge = "Basic realm=\"" + pconn->getHostName() + "\"";
00227       String password;
00228       
00229       try
00230       {
00231          HTTPUtils::decodeBasicCreds(info, userName, password);
00232       }
00233       catch (const AuthenticationException& e)
00234       {
00235          
00236          pconn->setErrorDetails("Problem decoding credentials");
00237          pconn->addHeader("WWW-Authenticate", authChallenge);
00238          OW_LOG_DEBUG(getEnvironment()->getLogger(COMPONENT_NAME), "HTTPServer::authenticate: Problem decoding credentials");
00239          return false;
00240       }
00241       String details;
00242       rv = m_options.env->authenticate(userName, password, details, context) && isAllowedUser(userName);
00243       if (!rv)
00244       {
00245          pconn->setErrorDetails(details);
00246          pconn->addHeader("WWW-Authenticate", authChallenge);
00247          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: failed: %1", details));
00248       }
00249       else
00250       {
00251          OW_LOG_INFO(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: authenticated %1", userName));
00252       }
00253    }
00254    else
00255    {
00256       
00257       String hostname = pconn->getHostName();
00258       pconn->setErrorDetails("You must authenticate to access this"
00259          " resource");
00260       String authChallenge;
00261       switch (m_options.defaultAuthChallenge)
00262       {
00263 #ifndef OW_DISABLE_DIGEST
00264          case E_DIGEST:
00265             authChallenge = m_digestAuthentication->getChallenge(hostname);
00266             break;
00267 #endif
00268          case E_BASIC:
00269             authChallenge = "Basic realm=\"" + pconn->getHostName() + "\"";
00270             break;
00271 
00272          default:
00273             OW_ASSERT("Internal implementation error! m_options.defaultAuthChallenge is invalid!" == 0);
00274       }
00275       OW_LOG_DEBUG(getEnvironment()->getLogger(COMPONENT_NAME), Format("HTTPServer::authenticate: Returning WWW-Authenticate: %1", authChallenge));
00276       pconn->addHeader("WWW-Authenticate", authChallenge);
00277       return false;
00278    }
00279 
00280 #ifndef OW_NO_SSL
00281    if (rv && m_sslopts.verifyMode == SSLOpts::MODE_AUTOUPDATE)
00282    {
00283       SSL* ssl = socket.getSSL();
00284       if (ssl)
00285       {
00286          X509* cert = SSL_get_peer_certificate(ssl);
00287          if (cert)
00288          {
00289             X509Freer x509Freer(cert);
00290             try
00291             {
00292                String uid = context.getStringDataWithDefault(OperationContext::CURUSER_UIDKEY);
00293                m_trustStore->addCertificate(cert, userName, uid);
00294             }
00295             catch (SSLException& e)
00296             {
00297                OW_LOG_ERROR(getEnvironment()->getLogger(COMPONENT_NAME), e.getMessage());
00298             }
00299          }
00300       }
00301    }
00302 #endif
00303    return rv;
00304 }
00305 
00307 void
00308 HTTPServer::init(const ServiceEnvironmentIFCRef& env)
00309 {
00310    try
00311    {
00312       String item = env->getConfigItem(ConfigOpts::HTTP_SERVER_HTTP_PORT_opt, OW_DEFAULT_HTTP_SERVER_HTTP_PORT);
00313       m_options.httpPort = item.toInt32();
00314       
00315       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_HTTPS_PORT_opt, OW_DEFAULT_HTTP_SERVER_HTTPS_PORT);
00316       m_options.httpsPort = item.toInt32();
00317 
00318       m_options.defaultContentLanguage = env->getConfigItem(
00319          ConfigOpts::HTTP_SERVER_DEFAULT_CONTENT_LANGUAGE_opt, OW_DEFAULT_HTTP_SERVER_DEFAULT_CONTENT_LANGUAGE);
00320    
00321 #ifndef OW_WIN32
00322       m_options.UDSFilename = env->getConfigItem(ConfigOpts::HTTP_SERVER_UDS_FILENAME_opt, OW_DEFAULT_HTTP_SERVER_UDS_FILENAME);
00323 #endif
00324       
00325       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_USE_UDS_opt, OW_DEFAULT_HTTP_SERVER_USE_UDS);
00326       m_options.useUDS = item.equalsIgnoreCase("true");
00327       
00328       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_MAX_CONNECTIONS_opt, OW_DEFAULT_HTTP_SERVER_MAX_CONNECTIONS);
00329       m_options.maxConnections = item.toInt32();
00330       
00331       m_threadPool = ThreadPoolRef(new ThreadPool(ThreadPool::DYNAMIC_SIZE, m_options.maxConnections, m_options.maxConnections * 100, env->getLogger(COMPONENT_NAME), "HTTPServer"));
00332       
00333       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_SINGLE_THREAD_opt, OW_DEFAULT_HTTP_SERVER_SINGLE_THREAD);
00334       m_options.isSepThread = !item.equalsIgnoreCase("true");
00335       
00336       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_ENABLE_DEFLATE_opt, OW_DEFAULT_HTTP_SERVER_ENABLE_DEFLATE);
00337       m_options.enableDeflate = !item.equalsIgnoreCase("false");
00338       
00339       item = env->getConfigItem(ConfigOpts::ALLOW_ANONYMOUS_opt, OW_DEFAULT_ALLOW_ANONYMOUS);
00340       m_options.allowAnonymous = item.equalsIgnoreCase("true");
00341       m_options.env = env;
00342       
00343       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_USE_DIGEST_opt, OW_DEFAULT_HTTP_SERVER_USE_DIGEST);
00344       m_options.allowDigestAuthentication = !item.equalsIgnoreCase("false");
00345       if (m_options.allowDigestAuthentication)
00346       {
00347 #ifndef OW_DISABLE_DIGEST
00348          String passwdFile = env->getConfigItem(
00349             ConfigOpts::HTTP_SERVER_DIGEST_PASSWORD_FILE_opt, OW_DEFAULT_HTTP_SERVER_DIGEST_PASSWORD_FILE);
00350          m_digestAuthentication = IntrusiveReference<DigestAuthentication>(
00351             new DigestAuthentication(passwdFile));
00352          m_options.defaultAuthChallenge = E_DIGEST;
00353 #else
00354          OW_THROW(HTTPServerException, "Unable to initialize HTTP Server because"
00355             " digest is enabled in the config file, but the digest code has been disabled");
00356 #endif
00357       }
00358       else
00359       {
00360          
00361          
00362          m_options.defaultAuthChallenge = E_BASIC;
00363       }
00364       
00365       
00366       m_options.allowBasicAuthentication = !m_options.allowDigestAuthentication;
00367    
00368 #ifndef OW_WIN32
00369       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_ALLOW_LOCAL_AUTHENTICATION_opt, OW_DEFAULT_HTTP_SERVER_ALLOW_LOCAL_AUTHENTICATION);
00370       m_options.allowLocalAuthentication = !item.equalsIgnoreCase("false");
00371       if (m_options.allowLocalAuthentication)
00372       {
00373          m_localAuthentication = IntrusiveReference<LocalAuthentication>(
00374             new LocalAuthentication(env->getLogger(COMPONENT_NAME)));
00375       }
00376 #endif
00377 
00378       String dumpPrefix = env->getConfigItem(ConfigOpts::DUMP_SOCKET_IO_opt);
00379       if (!dumpPrefix.empty())
00380       {
00381          SocketBaseImpl::setDumpFiles(
00382             dumpPrefix + "/owHTTPSockDumpIn",
00383             dumpPrefix + "/owHTTPSockDumpOut");
00384       }
00385       
00386       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_REUSE_ADDR_opt, OW_DEFAULT_HTTP_SERVER_REUSE_ADDR);
00387       m_options.reuseAddr = !item.equalsIgnoreCase("false");
00388       
00389       item = env->getConfigItem(ConfigOpts::HTTP_SERVER_TIMEOUT_opt, OW_DEFAULT_HTTP_SERVER_TIMEOUT);
00390       m_options.timeout = item.toInt32();
00391 
00392       StringArray users = env->getMultiConfigItem(ConfigOpts::ALLOWED_USERS_opt, 
00393          String(OW_DEFAULT_ALLOWED_USERS).tokenize(" \t"),
00394          " \t");
00395       if (users.size() == 1 && users[0] == "*")
00396       {
00397          m_allowAllUsers = true;
00398       }
00399       else
00400       {
00401          m_allowAllUsers = false;
00402          m_allowedUsers.insert(users.begin(), users.end());
00403       }
00404    }
00405    catch (const StringConversionException& e)
00406    {
00407       OW_THROW(HTTPServerException, Format("Unable to initialize HTTP Server because"
00408          " of invalid config item. %1", e.getMessage()).c_str());
00409    }
00410 }
00412 class HTTPServerSelectableCallback : public SelectableCallbackIFC
00413 {
00414 public:
00415    HTTPServerSelectableCallback(bool isHTTPS,
00416       HTTPServer* httpServer, bool isIPC)
00417       : SelectableCallbackIFC()
00418       , m_isHTTPS(isHTTPS)
00419       , m_HTTPServer(httpServer)
00420       , m_isIPC(isIPC)
00421    {
00422    }
00423    virtual ~HTTPServerSelectableCallback() {}
00424    virtual void doSelected(SelectableIFCRef& selectedObject)
00425    {
00426       try
00427       {
00428          IntrusiveReference<ServerSocket> pServerSocket;
00429          if (m_isIPC)
00430          {
00431             pServerSocket = m_HTTPServer->m_pUDSServerSocket;
00432          }
00433          else if (m_isHTTPS)
00434          {
00435             pServerSocket = m_HTTPServer->m_pHttpsServerSocket;
00436          }
00437          else
00438          {
00439             pServerSocket = m_HTTPServer->m_pHttpServerSocket;
00440          }
00441          Socket socket = pServerSocket->accept(2);
00442          LoggerRef logger = m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME);
00443          OW_LOG_INFO(logger,
00444              Format("Received connection on %1 from %2",
00445              socket.getLocalAddress().toString(),
00446              socket.getPeerAddress().toString()));
00447          HTTPServer::Options newOpts = m_HTTPServer->m_options;
00448          if (m_isIPC)
00449          {
00450             newOpts.enableDeflate = false;
00451          }
00452 #ifdef OW_WIN32
00453          RunnableRef rref(new HTTPSvrConnection(socket,
00454              m_HTTPServer, m_HTTPServer->m_event, newOpts));
00455 #else
00456          RunnableRef rref(new HTTPSvrConnection(socket,
00457              m_HTTPServer, m_HTTPServer->m_upipe, newOpts));
00458 #endif
00459          if (!m_HTTPServer->m_threadPool->tryAddWork(rref))
00460          {
00461             OW_LOG_INFO(logger, "Server too busy, closing connection");
00462             
00463             socket.setTimeouts(0);
00464             std::ostream& socketOstr(socket.getOutputStream());
00465             socketOstr << "HTTP/1.1 503 Service unavailable: connection queue full\r\n";
00466             socketOstr << "Connection: close\r\n";
00467             socketOstr << "Content-Length: 0\r\n\r\n";
00468             socketOstr.flush();
00469             socket.disconnect();
00470          }
00471       }
00472       catch (SSLException& se)
00473       {
00474          OW_LOG_INFO(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME),
00475             Format("SSL Handshake failed: %1", se.getMessage()).c_str());
00476       }
00477       catch (SocketTimeoutException &e)
00478       {
00479          OW_LOG_INFO(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME), Format(
00480             "Socket TimeOut in HTTPServer: %1", e));
00481       }
00482       catch (SocketException &e)
00483       {
00484          OW_LOG_INFO(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME), Format(
00485             "Socket Exception in HTTPServer: %1", e));
00486       }
00487       catch (IOException &e)
00488       {
00489          OW_LOG_ERROR(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME), Format(
00490             "IO Exception in HTTPServer: %1", e));
00491       }
00492       catch (ThreadException& e)
00493       {
00494          OW_LOG_ERROR(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME), Format(
00495             "ThreadException in HTTPServer: %1", e));
00496       }
00497       catch (Exception& e)
00498       {
00499          OW_LOG_ERROR(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME), Format(
00500             "Exception in HTTPServer: %1", e));
00501          
00502          
00503          throw;
00504       }
00505       catch (ThreadCancelledException&)
00506       {
00507          throw;
00508       }
00509       catch (...)
00510       {
00511          OW_LOG_ERROR(m_HTTPServer->m_options.env->getLogger(COMPONENT_NAME),
00512             "Unknown exception in HTTPServer.");
00513          throw;
00514       }
00515    }
00516 private:
00517    bool m_isHTTPS;
00518    HTTPServer* m_HTTPServer;
00519    bool m_isIPC;
00520 };
00522 void
00523 HTTPServer::start()
00524 {
00525    ServiceEnvironmentIFCRef env = m_options.env;
00526    LoggerRef lgr = env->getLogger(COMPONENT_NAME);
00527    OW_LOG_DEBUG(lgr, "HTTP Service is starting...");
00528    if (m_options.httpPort < 0 && m_options.httpsPort < 0 && !m_options.useUDS)
00529    {
00530       OW_THROW(SocketException, "No ports to listen on and use_UDS set to false");
00531    }
00532 #ifndef OW_WIN32
00533    if (m_options.useUDS)
00534    {
00535       try
00536       {
00537          m_pUDSServerSocket = new ServerSocket;
00538          m_pUDSServerSocket->doListen(m_options.UDSFilename, 1000, m_options.reuseAddr);
00539          OW_LOG_INFO(lgr, "HTTP server listening on Unix Domain Socket");
00540          String theURL = "ipc://localhost/cimom";
00541          addURL(URL(theURL));
00542          
00543          SelectableCallbackIFCRef cb(new HTTPServerSelectableCallback(
00544             false, this, true));
00545          env->addSelectable(m_pUDSServerSocket, cb);
00546       }
00547       catch (SocketException& e)
00548       {
00549          OW_LOG_ERROR(lgr, Format("HTTP Server failed to listen on UDS: %1", e));
00550          throw;
00551       }
00552    }
00553 #endif
00554    StringArray listenAddresses = env->getMultiConfigItem(
00555       ConfigOpts::HTTP_SERVER_LISTEN_ADDRESSES_opt, 
00556       String(OW_DEFAULT_HTTP_SERVER_LISTEN_ADDRESSES).tokenize(" \t"),
00557       " \t");
00558 
00559    if (listenAddresses.empty())
00560    {
00561       OW_THROW(HTTPServerException, "http_server.listen_addresses config item malformed");
00562    }
00563    for (size_t i = 0; i < listenAddresses.size(); ++i)
00564    {
00565       const String& curAddress = listenAddresses[i];
00566       if (m_options.httpPort >= 0)
00567       {
00568          try
00569          {
00570             UInt16 lport = static_cast<UInt16>(m_options.httpPort);
00571             m_pHttpServerSocket = new ServerSocket;
00572             m_pHttpServerSocket->doListen(lport,
00573                1000, curAddress,
00574                m_options.reuseAddr ? SocketFlags::E_REUSE_ADDR : SocketFlags::E_DONT_REUSE_ADDR);
00575             m_options.httpPort = m_pHttpServerSocket->getLocalAddress().getPort();
00576             OW_LOG_INFO(lgr, Format("HTTP server listening on: %1:%2",
00577                curAddress, m_options.httpPort));
00578             String theURL = "http://" + SocketAddress::getAnyLocalHost().getName()
00579                + ":" + String(m_options.httpPort) + "/cimom";
00580             addURL(URL(theURL));
00581 
00582             SelectableCallbackIFCRef cb(new HTTPServerSelectableCallback(
00583                false, this, false));
00584             env->addSelectable(m_pHttpServerSocket, cb);
00585          }
00586          catch (SocketException& e)
00587          {
00588             OW_LOG_ERROR(lgr, Format("HTTP Server failed to listen on: %1:%2.  Msg: %3", curAddress, m_options.httpPort, e));
00589             throw;
00590          }
00591       }
00592       if (m_options.httpsPort >= 0)
00593       {
00594 #ifdef OW_NO_SSL
00595          if (m_options.httpPort < 0 && !m_options.useUDS)
00596          {
00597             OW_THROW(HTTPServerException, "No ports to listen on.  "
00598                   "SSL unavailable (OpenWBEM not built with SSL support) "
00599                   "and no http port defined.");
00600          }
00601          else
00602          {
00603             String msg = Format("Unable to listen on %1:%2.  "
00604                   "OpenWBEM not built with SSL support.", curAddress, m_options.httpsPort);
00605             OW_LOG_ERROR(lgr, msg);
00606             OW_THROW(HTTPServerException, msg.c_str());
00607          }
00608 #else
00609          try
00610          {
00611             m_sslopts.certfile = env->getConfigItem(ConfigOpts::HTTP_SERVER_SSL_CERT_opt);
00612             m_sslopts.keyfile = env->getConfigItem(ConfigOpts::HTTP_SERVER_SSL_KEY_opt);
00613             if (m_sslopts.keyfile.empty())
00614             {
00615                m_sslopts.keyfile = m_sslopts.certfile;
00616             }
00617             m_sslopts.trustStore = env->getConfigItem(ConfigOpts::HTTP_SERVER_SSL_TRUST_STORE,
00618                                           OW_DEFAULT_HTTP_SERVER_SSL_TRUST_STORE);
00619             String verifyMode = env->getConfigItem(ConfigOpts::HTTP_SERVER_SSL_CLIENT_VERIFICATION_opt,
00620                                           OW_DEFAULT_HTTP_SERVER_SSL_CLIENT_VERIFICATION);
00621             verifyMode.toLowerCase();
00622             if (verifyMode == "disabled")
00623             {
00624                m_sslopts.verifyMode = SSLOpts::MODE_DISABLED;
00625             }
00626             else if (verifyMode == "optional")
00627             {
00628                m_sslopts.verifyMode = SSLOpts::MODE_OPTIONAL;
00629             }
00630             else if (verifyMode == "required")
00631             {
00632                m_sslopts.verifyMode = SSLOpts::MODE_REQUIRED;
00633             }
00634             else if (verifyMode == "autoupdate")
00635             {
00636                m_sslopts.verifyMode = SSLOpts::MODE_AUTOUPDATE;
00637             }
00638             else
00639             {
00640                OW_THROW(HTTPServerException, Format("Bad value (%1) for configuration item %2",
00641                                            verifyMode,
00642                                            ConfigOpts::HTTP_SERVER_SSL_CLIENT_VERIFICATION_opt).c_str());
00643             }
00644             
00645             m_sslCtx = SSLServerCtxRef(new SSLServerCtx(m_sslopts));
00646             if (m_sslopts.verifyMode != SSLOpts::MODE_DISABLED)
00647             {
00648                m_trustStore = SSLTrustStoreRef(new SSLTrustStore(m_sslopts.trustStore));
00649             }
00650          }
00651          catch (SSLException& e)
00652          {
00653             OW_LOG_ERROR(lgr, Format("HTTP Service: Error initializing SSL: %1",
00654                e.getMessage()));
00655             throw;
00656          }
00657 
00658          UInt16 lport = static_cast<UInt16>(m_options.httpsPort);
00659          
00660          if (m_sslCtx)
00661          {
00662             try
00663             {
00664                m_pHttpsServerSocket = new ServerSocket(m_sslCtx);
00665                m_pHttpsServerSocket->doListen(lport,
00666                   1000, curAddress,
00667                   m_options.reuseAddr ? SocketFlags::E_REUSE_ADDR : SocketFlags::E_DONT_REUSE_ADDR);
00668                m_options.httpsPort =
00669                   m_pHttpsServerSocket->getLocalAddress().getPort();
00670                OW_LOG_INFO(lgr, Format("HTTPS server listening on: %1:%2",
00671                   curAddress, m_options.httpsPort));
00672                String theURL = "https://" +
00673                   SocketAddress::getAnyLocalHost().getName() + ":" +
00674                   String(m_options.httpsPort) + "/cimom";
00675                addURL(URL(theURL));
00676                SelectableCallbackIFCRef cb(new HTTPServerSelectableCallback(
00677                   true, this, false));
00678                env->addSelectable(m_pHttpsServerSocket, cb);
00679             }
00680             catch (SocketException& e)
00681             {
00682                OW_LOG_ERROR(lgr, Format("HTTP Server failed to listen on: %1:%2.  Msg: %3", curAddress, m_options.httpPort, e));
00683                throw;
00684             }
00685          }
00686          else
00687 #endif // #ifndef OW_NO_SSL
00688          {
00689             if (m_options.httpPort < 0 && !m_options.useUDS)
00690             {
00691                OW_THROW(HTTPServerException, "No ports to listen on.  "
00692                   "SSL unavailable (SSL not initialized in server mode) "
00693                   "and no http port defined.");
00694             }
00695             String msg = Format("Unable to listen on: %1:%2.  "
00696                "SSL not initialized in server mode.", curAddress, m_options.httpsPort);
00697             OW_LOG_ERROR(lgr, msg);
00698             OW_THROW(HTTPServerException, msg.c_str());
00699 
00700          }
00701       } 
00702    }
00703    OW_LOG_DEBUG(lgr, "HTTP Service has started");
00704 }
00706 void
00707 HTTPServer::addURL(const URL& url)
00708 {
00709    m_urls.push_back(url);
00710 }
00712 Array<URL>
00713 HTTPServer::getURLs() const
00714 {
00715    return m_urls;
00716 }
00718 SocketAddress
00719 HTTPServer::getLocalHTTPAddress()
00720 {
00721    if (m_pHttpServerSocket)
00722    {
00723       return m_pHttpServerSocket->getLocalAddress();
00724    }
00725    else
00726    {
00727       return SocketAddress::allocEmptyAddress(SocketAddress::INET);
00728    }
00729 }
00731 SocketAddress
00732 HTTPServer::getLocalHTTPSAddress()
00733 {
00734    if (m_pHttpsServerSocket)
00735    {
00736       return m_pHttpsServerSocket->getLocalAddress();
00737    }
00738    else
00739    {
00740       return SocketAddress::allocEmptyAddress(SocketAddress::INET);
00741    }
00742 }
00744 bool
00745 HTTPServer::isShuttingDown()
00746 {
00747    MutexLock lock(m_shutdownGuard);
00748    return m_shuttingDown;
00749 }
00751 void
00752 HTTPServer::shutdown()
00753 {
00754    {
00755       MutexLock lock(m_shutdownGuard);
00756       m_shuttingDown = true;
00757    }
00758    OW_LOG_DEBUG(m_options.env->getLogger(COMPONENT_NAME), "HTTP Service is shutting down...");
00759    
00760    m_options.env->removeSelectable(m_pHttpServerSocket);
00761    m_options.env->removeSelectable(m_pHttpsServerSocket);
00762    m_options.env->removeSelectable(m_pUDSServerSocket);
00763 
00764    
00765 #ifdef OW_WIN32
00766    if (!::SetEvent(m_event))
00767    {
00768       OW_THROW(IOException,
00769          "Failed signaling event for HTTP server shutdown");
00770    }
00771 #else
00772    if (m_upipe->writeString("shutdown") == -1)
00773    {
00774       OW_THROW_ERRNO_MSG(IOException, "Failed writing to HTTPServer shutdown pipe");
00775    }
00776 #endif
00777    
00778    m_threadPool->shutdown(ThreadPool::E_DISCARD_WORK_IN_QUEUE, 60);
00779    m_pHttpServerSocket = 0;
00780    m_pHttpsServerSocket = 0;
00781    m_pUDSServerSocket = 0;
00782    OW_LOG_DEBUG(m_options.env->getLogger(COMPONENT_NAME), "HTTP Service has shut down");
00783 
00784    
00785    m_options.env = 0;
00786 }
00787 
00788 } 
00789 
00791 
00792 OW_SERVICE_FACTORY(OW_NAMESPACE::HTTPServer,HTTPServer)
00793