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