NetSSL_OpenSSL: complete merge to 1.4.2

This commit is contained in:
Marian Krivos
2011-09-14 18:17:35 +00:00
parent bcf1d5b6a7
commit 56c6a4f758
79 changed files with 16086 additions and 10265 deletions

View File

@@ -1,90 +1,91 @@
//
// CertificateHandlerFactoryMgr.cpp
//
//
// CertificateHandlerFactoryMgr.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/CertificateHandlerFactoryMgr.cpp#10 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: CertificateHandlerFactoryMgr
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/CertificateHandlerFactoryMgr.h"
#include "Poco/Net/ConsoleCertificateHandler.h"
#include "Poco/Net/AcceptCertificateHandler.h"
namespace Poco {
namespace Net {
CertificateHandlerFactoryMgr::CertificateHandlerFactoryMgr()
{
setFactory("ConsoleCertificateHandler", new CertificateHandlerFactoryImpl<ConsoleCertificateHandler>());
setFactory("AcceptCertificateHandler", new CertificateHandlerFactoryImpl<AcceptCertificateHandler>());
}
CertificateHandlerFactoryMgr::~CertificateHandlerFactoryMgr()
{
}
void CertificateHandlerFactoryMgr::setFactory(const std::string& name, CertificateHandlerFactory* pFactory)
{
bool success = _factories.insert(make_pair(name, Poco::SharedPtr<CertificateHandlerFactory>(pFactory))).second;
if (!success)
delete pFactory;
poco_assert(success);
}
bool CertificateHandlerFactoryMgr::hasFactory(const std::string& name) const
{
return _factories.find(name) != _factories.end();
}
const CertificateHandlerFactory* CertificateHandlerFactoryMgr::getFactory(const std::string& name) const
{
FactoriesMap::const_iterator it = _factories.find(name);
if (it != _factories.end())
return it->second;
else
return 0;
}
void CertificateHandlerFactoryMgr::removeFactory(const std::string& name)
{
_factories.erase(name);
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: CertificateHandlerFactoryMgr
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/CertificateHandlerFactoryMgr.h"
#include "Poco/Net/ConsoleCertificateHandler.h"
#include "Poco/Net/AcceptCertificateHandler.h"
#include "Poco/Net/RejectCertificateHandler.h"
namespace Poco {
namespace Net {
CertificateHandlerFactoryMgr::CertificateHandlerFactoryMgr()
{
setFactory("ConsoleCertificateHandler", new CertificateHandlerFactoryImpl<ConsoleCertificateHandler>());
setFactory("AcceptCertificateHandler", new CertificateHandlerFactoryImpl<AcceptCertificateHandler>());
setFactory("RejectCertificateHandler", new CertificateHandlerFactoryImpl<RejectCertificateHandler>());
}
CertificateHandlerFactoryMgr::~CertificateHandlerFactoryMgr()
{
}
void CertificateHandlerFactoryMgr::setFactory(const std::string& name, CertificateHandlerFactory* pFactory)
{
bool success = _factories.insert(make_pair(name, Poco::SharedPtr<CertificateHandlerFactory>(pFactory))).second;
if (!success)
delete pFactory;
poco_assert(success);
}
bool CertificateHandlerFactoryMgr::hasFactory(const std::string& name) const
{
return _factories.find(name) != _factories.end();
}
const CertificateHandlerFactory* CertificateHandlerFactoryMgr::getFactory(const std::string& name) const
{
FactoriesMap::const_iterator it = _factories.find(name);
if (it != _factories.end())
return it->second;
else
return 0;
}
void CertificateHandlerFactoryMgr::removeFactory(const std::string& name)
{
_factories.erase(name);
}
} } // namespace Poco::Net

View File

@@ -1,139 +1,354 @@
//
// Context.cpp
//
//
// Context.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/Context.cpp#18 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: Context
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/Context.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/Utility.h"
#include "Poco/File.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
namespace Poco {
namespace Net {
Context::Context(
Usage usage,
const std::string& privateKeyFile,
const std::string& certificateFile,
const std::string& caLocation,
VerificationMode verificationMode,
int verificationDepth,
bool loadDefaultCAs,
const std::string& cypherList):
_usage(usage),
_mode(verificationMode),
_pSSLContext(0)
{
_pSSLContext = SSL_CTX_new(SSLv23_method());
if (!_pSSLContext)
{
unsigned long err = ERR_get_error();
throw SSLException("Cannot create SSL_CTX object", ERR_error_string(err, 0));
}
SSL_CTX_set_default_passwd_cb(_pSSLContext, &SSLManager::privateKeyPasswdCallback);
Utility::clearErrorStack();
int errCode = 0;
if (!caLocation.empty())
{
Poco::File aFile(caLocation);
if (aFile.isDirectory())
errCode = SSL_CTX_load_verify_locations(_pSSLContext, 0, caLocation.c_str());
else
errCode = SSL_CTX_load_verify_locations(_pSSLContext, caLocation.c_str(), 0);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Cannot load CA file/directory at ") + caLocation, msg);
}
}
if (loadDefaultCAs)
{
errCode = SSL_CTX_set_default_verify_paths(_pSSLContext);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException("Cannot load default CA certificates", msg);
}
}
if (!privateKeyFile.empty())
{
errCode = SSL_CTX_use_PrivateKey_file(_pSSLContext, privateKeyFile.c_str(), SSL_FILETYPE_PEM);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Error loading private key from file ") + privateKeyFile, msg);
}
}
if (!certificateFile.empty())
{
errCode = SSL_CTX_use_certificate_chain_file(_pSSLContext, certificateFile.c_str());
if (errCode != 1)
{
std::string errMsg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Error loading certificate from file ") + privateKeyFile, errMsg);
}
}
if (usage == SERVER_USE)
SSL_CTX_set_verify(_pSSLContext, verificationMode, &SSLManager::verifyServerCallback);
else
SSL_CTX_set_verify(_pSSLContext, verificationMode, &SSLManager::verifyClientCallback);
SSL_CTX_set_verify_depth(_pSSLContext, verificationDepth);
SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY);
}
Context::~Context()
{
SSL_CTX_free(_pSSLContext);
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: Context
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/Context.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/Utility.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include "Poco/Timestamp.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
namespace Poco {
namespace Net {
Context::Context(
Usage usage,
const std::string& privateKeyFile,
const std::string& certificateFile,
const std::string& caLocation,
VerificationMode verificationMode,
int verificationDepth,
bool loadDefaultCAs,
const std::string& cipherList):
_usage(usage),
_mode(verificationMode),
_pSSLContext(0),
_extendedCertificateVerification(true)
{
Poco::Crypto::OpenSSLInitializer::initialize();
if (SSLManager::isFIPSEnabled())
{
_pSSLContext = SSL_CTX_new(TLSv1_method());
}
else
{
_pSSLContext = SSL_CTX_new(SSLv23_method());
}
if (!_pSSLContext)
{
unsigned long err = ERR_get_error();
throw SSLException("Cannot create SSL_CTX object", ERR_error_string(err, 0));
}
SSL_CTX_set_default_passwd_cb(_pSSLContext, &SSLManager::privateKeyPassphraseCallback);
Utility::clearErrorStack();
SSL_CTX_set_options(_pSSLContext, SSL_OP_ALL);
int errCode = 0;
if (!caLocation.empty())
{
Poco::File aFile(caLocation);
if (aFile.isDirectory())
errCode = SSL_CTX_load_verify_locations(_pSSLContext, 0, Poco::Path::transcode(caLocation).c_str());
else
errCode = SSL_CTX_load_verify_locations(_pSSLContext, Poco::Path::transcode(caLocation).c_str(), 0);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Cannot load CA file/directory at ") + caLocation, msg);
}
}
if (loadDefaultCAs)
{
errCode = SSL_CTX_set_default_verify_paths(_pSSLContext);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException("Cannot load default CA certificates", msg);
}
}
if (!privateKeyFile.empty())
{
errCode = SSL_CTX_use_PrivateKey_file(_pSSLContext, Poco::Path::transcode(privateKeyFile).c_str(), SSL_FILETYPE_PEM);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Error loading private key from file ") + privateKeyFile, msg);
}
}
if (!certificateFile.empty())
{
errCode = SSL_CTX_use_certificate_chain_file(_pSSLContext, Poco::Path::transcode(certificateFile).c_str());
if (errCode != 1)
{
std::string errMsg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Error loading certificate from file ") + certificateFile, errMsg);
}
}
if (usage == SERVER_USE)
SSL_CTX_set_verify(_pSSLContext, verificationMode, &SSLManager::verifyServerCallback);
else
SSL_CTX_set_verify(_pSSLContext, verificationMode, &SSLManager::verifyClientCallback);
SSL_CTX_set_cipher_list(_pSSLContext, cipherList.c_str());
SSL_CTX_set_verify_depth(_pSSLContext, verificationDepth);
SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
}
Context::Context(
Usage usage,
const std::string& caLocation,
VerificationMode verificationMode,
int verificationDepth,
bool loadDefaultCAs,
const std::string& cipherList):
_usage(usage),
_mode(verificationMode),
_pSSLContext(0),
_extendedCertificateVerification(true)
{
Poco::Crypto::OpenSSLInitializer::initialize();
if (SSLManager::isFIPSEnabled())
{
_pSSLContext = SSL_CTX_new(TLSv1_method());
}
else
{
_pSSLContext = SSL_CTX_new(SSLv23_method());
}
if (!_pSSLContext)
{
unsigned long err = ERR_get_error();
throw SSLException("Cannot create SSL_CTX object", ERR_error_string(err, 0));
}
SSL_CTX_set_default_passwd_cb(_pSSLContext, &SSLManager::privateKeyPassphraseCallback);
Utility::clearErrorStack();
SSL_CTX_set_options(_pSSLContext, SSL_OP_ALL);
int errCode = 0;
if (!caLocation.empty())
{
Poco::File aFile(caLocation);
if (aFile.isDirectory())
errCode = SSL_CTX_load_verify_locations(_pSSLContext, 0, Poco::Path::transcode(caLocation).c_str());
else
errCode = SSL_CTX_load_verify_locations(_pSSLContext, Poco::Path::transcode(caLocation).c_str(), 0);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException(std::string("Cannot load CA file/directory at ") + caLocation, msg);
}
}
if (loadDefaultCAs)
{
errCode = SSL_CTX_set_default_verify_paths(_pSSLContext);
if (errCode != 1)
{
std::string msg = Utility::getLastError();
SSL_CTX_free(_pSSLContext);
throw SSLContextException("Cannot load default CA certificates", msg);
}
}
if (usage == SERVER_USE)
SSL_CTX_set_verify(_pSSLContext, verificationMode, &SSLManager::verifyServerCallback);
else
SSL_CTX_set_verify(_pSSLContext, verificationMode, &SSLManager::verifyClientCallback);
SSL_CTX_set_cipher_list(_pSSLContext, cipherList.c_str());
SSL_CTX_set_verify_depth(_pSSLContext, verificationDepth);
SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
}
Context::~Context()
{
SSL_CTX_free(_pSSLContext);
Poco::Crypto::OpenSSLInitializer::uninitialize();
}
void Context::useCertificate(const Poco::Crypto::X509Certificate& certificate)
{
int errCode = SSL_CTX_use_certificate(_pSSLContext, const_cast<X509*>(certificate.certificate()));
if (errCode != 1)
{
std::string msg = Utility::getLastError();
throw SSLContextException("Cannot set certificate for Context", msg);
}
}
void Context::addChainCertificate(const Poco::Crypto::X509Certificate& certificate)
{
int errCode = SSL_CTX_add_extra_chain_cert(_pSSLContext, certificate.certificate());
if (errCode != 1)
{
std::string msg = Utility::getLastError();
throw SSLContextException("Cannot add chain certificate to Context", msg);
}
}
void Context::usePrivateKey(const Poco::Crypto::RSAKey& key)
{
int errCode = SSL_CTX_use_RSAPrivateKey(_pSSLContext, key.impl()->getRSA());
if (errCode != 1)
{
std::string msg = Utility::getLastError();
throw SSLContextException("Cannot set private key for Context", msg);
}
}
void Context::enableSessionCache(bool flag)
{
if (flag)
{
SSL_CTX_set_session_cache_mode(_pSSLContext, _usage == SERVER_USE ? SSL_SESS_CACHE_SERVER : SSL_SESS_CACHE_CLIENT);
}
else
{
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
}
}
void Context::enableSessionCache(bool flag, const std::string& sessionIdContext)
{
poco_assert (_usage == SERVER_USE);
if (flag)
{
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_SERVER);
}
else
{
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
}
unsigned length = static_cast<unsigned>(sessionIdContext.length());
if (length > SSL_MAX_SSL_SESSION_ID_LENGTH) length = SSL_MAX_SSL_SESSION_ID_LENGTH;
int rc = SSL_CTX_set_session_id_context(_pSSLContext, reinterpret_cast<const unsigned char*>(sessionIdContext.data()), length);
if (rc != 1) throw SSLContextException("cannot set session ID context");
}
bool Context::sessionCacheEnabled() const
{
return SSL_CTX_get_session_cache_mode(_pSSLContext) != SSL_SESS_CACHE_OFF;
}
void Context::setSessionCacheSize(std::size_t size)
{
poco_assert (_usage == SERVER_USE);
SSL_CTX_sess_set_cache_size(_pSSLContext, static_cast<long>(size));
}
std::size_t Context::getSessionCacheSize() const
{
poco_assert (_usage == SERVER_USE);
return static_cast<std::size_t>(SSL_CTX_sess_get_cache_size(_pSSLContext));
}
void Context::setSessionTimeout(long seconds)
{
poco_assert (_usage == SERVER_USE);
SSL_CTX_set_timeout(_pSSLContext, seconds);
}
long Context::getSessionTimeout() const
{
poco_assert (_usage == SERVER_USE);
return SSL_CTX_get_timeout(_pSSLContext);
}
void Context::flushSessionCache()
{
poco_assert (_usage == SERVER_USE);
Poco::Timestamp now;
SSL_CTX_flush_sessions(_pSSLContext, static_cast<long>(now.epochTime()));
}
void Context::enableExtendedCertificateVerification(bool flag)
{
_extendedCertificateVerification = flag;
}
void Context::disableStatelessSessionResumption()
{
#if defined(SSL_OP_NO_TICKET)
SSL_CTX_set_options(_pSSLContext, SSL_OP_NO_TICKET);
#endif
}
} } // namespace Poco::Net

View File

@@ -1,147 +1,215 @@
//
// HTTPSClientSession.cpp
//
//
// HTTPSClientSession.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/HTTPSClientSession.cpp#13 $
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSClientSession
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
using Poco::NumberFormatter;
using Poco::IllegalStateException;
namespace Poco {
namespace Net {
HTTPSClientSession::HTTPSClientSession():
HTTPClientSession(SecureStreamSocket()),
_pContext(SSLManager::instance().defaultClientContext())
{
setPort(HTTPS_PORT);
}
HTTPSClientSession::HTTPSClientSession(const SecureStreamSocket& socket):
HTTPClientSession(socket),
_pContext(socket.context())
{
setPort(HTTPS_PORT);
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port):
HTTPClientSession(SecureStreamSocket()),
_pContext(SSLManager::instance().defaultClientContext())
{
setHost(host);
setPort(port);
SecureStreamSocket sss(socket());
sss.setPeerHostName(host);
}
HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext):
HTTPClientSession(SecureStreamSocket(pContext)),
_pContext(pContext)
{
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext):
HTTPClientSession(SecureStreamSocket(pContext)),
_pContext(pContext)
{
setHost(host);
setPort(port);
SecureStreamSocket sss(socket());
sss.setPeerHostName(host);
}
HTTPSClientSession::~HTTPSClientSession()
{
}
X509Certificate HTTPSClientSession::serverCertificate()
{
SecureStreamSocket sss(socket());
return sss.peerCertificate();
}
std::string HTTPSClientSession::proxyRequestPrefix() const
{
return std::string();
}
void HTTPSClientSession::connect(const SocketAddress& address)
{
if (getProxyHost().empty())
{
HTTPSession::connect(address);
}
else
{
HTTPClientSession proxySession(address);
proxySession.setHost(getProxyHost());
proxySession.setPort(getProxyPort());
SocketAddress targetAddress(getHost(), getPort());
HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress.toString(), HTTPMessage::HTTP_1_1);
HTTPResponse proxyResponse;
proxyRequest.set("Proxy-Connection", "keep-alive");
proxyRequest.set("Host", getHost());
proxySession.setKeepAlive(true);
proxySession.sendRequest(proxyRequest);
proxySession.receiveResponse(proxyResponse);
if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason());
StreamSocket proxySocket(proxySession.detachSocket());
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext);
attachSocket(secureSocket);
}
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSClientSession
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
using Poco::NumberFormatter;
using Poco::IllegalStateException;
namespace Poco {
namespace Net {
HTTPSClientSession::HTTPSClientSession():
HTTPClientSession(SecureStreamSocket()),
_pContext(SSLManager::instance().defaultClientContext())
{
setPort(HTTPS_PORT);
}
HTTPSClientSession::HTTPSClientSession(const SecureStreamSocket& socket):
HTTPClientSession(socket),
_pContext(socket.context())
{
setPort(HTTPS_PORT);
}
HTTPSClientSession::HTTPSClientSession(const SecureStreamSocket& socket, Session::Ptr pSession):
HTTPClientSession(socket),
_pContext(socket.context()),
_pSession(pSession)
{
setPort(HTTPS_PORT);
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port):
HTTPClientSession(SecureStreamSocket()),
_pContext(SSLManager::instance().defaultClientContext())
{
setHost(host);
setPort(port);
SecureStreamSocket sss(socket());
sss.setPeerHostName(host);
}
HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext):
HTTPClientSession(SecureStreamSocket(pContext)),
_pContext(pContext)
{
}
HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext, Session::Ptr pSession):
HTTPClientSession(SecureStreamSocket(pContext, pSession)),
_pContext(pContext),
_pSession(pSession)
{
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext):
HTTPClientSession(SecureStreamSocket(pContext)),
_pContext(pContext)
{
setHost(host);
setPort(port);
SecureStreamSocket sss(socket());
sss.setPeerHostName(host);
}
HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext, Session::Ptr pSession):
HTTPClientSession(SecureStreamSocket(pContext, pSession)),
_pContext(pContext),
_pSession(pSession)
{
setHost(host);
setPort(port);
SecureStreamSocket sss(socket());
sss.setPeerHostName(host);
}
HTTPSClientSession::~HTTPSClientSession()
{
}
bool HTTPSClientSession::secure() const
{
return true;
}
void HTTPSClientSession::abort()
{
SecureStreamSocket sss(socket());
sss.abort();
}
X509Certificate HTTPSClientSession::serverCertificate()
{
SecureStreamSocket sss(socket());
return sss.peerCertificate();
}
std::string HTTPSClientSession::proxyRequestPrefix() const
{
return std::string();
}
void HTTPSClientSession::proxyAuthenticate(HTTPRequest& request)
{
}
void HTTPSClientSession::connect(const SocketAddress& address)
{
if (getProxyHost().empty())
{
SecureStreamSocket sss(socket());
if (_pContext->sessionCacheEnabled())
{
sss.useSession(_pSession);
}
HTTPSession::connect(address);
if (_pContext->sessionCacheEnabled())
{
_pSession = sss.currentSession();
}
}
else
{
HTTPClientSession proxySession(address);
proxySession.setHost(getProxyHost());
proxySession.setPort(getProxyPort());
proxySession.setTimeout(getTimeout());
SocketAddress targetAddress(getHost(), getPort());
HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress.toString(), HTTPMessage::HTTP_1_1);
HTTPResponse proxyResponse;
proxyRequest.set("Proxy-Connection", "keep-alive");
proxyRequest.set("Host", getHost());
proxyAuthenticateImpl(proxyRequest);
proxySession.setKeepAlive(true);
proxySession.sendRequest(proxyRequest);
proxySession.receiveResponse(proxyResponse);
if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason());
StreamSocket proxySocket(proxySession.detachSocket());
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext, _pSession);
attachSocket(secureSocket);
if (_pContext->sessionCacheEnabled())
{
_pSession = secureSocket.currentSession();
}
}
}
Session::Ptr HTTPSClientSession::sslSession()
{
return _pSession;
}
} } // namespace Poco::Net

View File

@@ -1,77 +1,78 @@
//
// HTTPSSessionInstantiator.cpp
//
//
// HTTPSSessionInstantiator.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/HTTPSSessionInstantiator.cpp#9 $
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSSessionInstantiator
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSSessionInstantiator.h"
#include "Poco/Net/HTTPSessionFactory.h"
#include "Poco/Net/HTTPSClientSession.h"
namespace Poco {
namespace Net {
HTTPSSessionInstantiator::HTTPSSessionInstantiator()
{
}
HTTPSSessionInstantiator::~HTTPSSessionInstantiator()
{
}
HTTPClientSession* HTTPSSessionInstantiator::createClientSession(const Poco::URI& uri)
{
poco_assert (uri.getScheme() == "https");
HTTPSClientSession* pSession = new HTTPSClientSession(uri.getHost(), uri.getPort());
pSession->setProxy(proxyHost(), proxyPort());
return pSession;
}
void HTTPSSessionInstantiator::registerInstantiator()
{
HTTPSessionFactory::defaultFactory().registerProtocol("https", new HTTPSSessionInstantiator);
}
void HTTPSSessionInstantiator::unregisterInstantiator()
{
HTTPSessionFactory::defaultFactory().unregisterProtocol("https");
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSSessionInstantiator
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSSessionInstantiator.h"
#include "Poco/Net/HTTPSessionFactory.h"
#include "Poco/Net/HTTPSClientSession.h"
namespace Poco {
namespace Net {
HTTPSSessionInstantiator::HTTPSSessionInstantiator()
{
}
HTTPSSessionInstantiator::~HTTPSSessionInstantiator()
{
}
HTTPClientSession* HTTPSSessionInstantiator::createClientSession(const Poco::URI& uri)
{
poco_assert (uri.getScheme() == "https");
HTTPSClientSession* pSession = new HTTPSClientSession(uri.getHost(), uri.getPort());
pSession->setProxy(proxyHost(), proxyPort());
pSession->setProxyCredentials(proxyUsername(), proxyPassword());
return pSession;
}
void HTTPSSessionInstantiator::registerInstantiator()
{
HTTPSessionFactory::defaultFactory().registerProtocol("https", new HTTPSSessionInstantiator);
}
void HTTPSSessionInstantiator::unregisterInstantiator()
{
HTTPSessionFactory::defaultFactory().unregisterProtocol("https");
}
} } // namespace Poco::Net

View File

@@ -1,154 +1,164 @@
//
// HTTPSStreamFactory.cpp
//
//
// HTTPSStreamFactory.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp#10 $
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSStreamFactory
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPIOStream.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h"
using Poco::URIStreamFactory;
using Poco::URI;
using Poco::URIStreamOpener;
using Poco::UnbufferedStreamBuf;
namespace Poco {
namespace Net {
HTTPSStreamFactory::HTTPSStreamFactory():
_proxyPort(HTTPSession::HTTP_PORT)
{
}
HTTPSStreamFactory::HTTPSStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort):
_proxyHost(proxyHost),
_proxyPort(proxyPort)
{
}
HTTPSStreamFactory::~HTTPSStreamFactory()
{
}
std::istream* HTTPSStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "https" || uri.getScheme() == "http");
URI resolvedURI(uri);
URI proxyUri;
HTTPClientSession* pSession = 0;
try
{
bool retry = false;
int redirects = 0;
do
{
if (resolvedURI.getScheme() != "http")
pSession = new HTTPSClientSession(resolvedURI.getHost(), resolvedURI.getPort());
else
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
if (proxyUri.empty())
pSession->setProxy(_proxyHost, _proxyPort);
else
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
std::string path = resolvedURI.getPathAndQuery();
if (path.empty()) path = "/";
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
pSession->sendRequest(req);
HTTPResponse res;
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER ||
res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT);
if (moved)
{
resolvedURI.resolve(res.get("Location"));
//throw URIRedirection(resolvedURI.toString());
delete pSession; pSession = 0;
++redirects;
retry = true;
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
{
return new HTTPResponseStream(rs, pSession);
}
else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry)
{
// The requested resource MUST be accessed through the proxy
// given by the Location field. The Location field gives the
// URI of the proxy. The recipient is expected to repeat this
// single request via the proxy. 305 responses MUST only be generated by origin servers.
// only use for one single request!
proxyUri.resolve(res.get("Location"));
delete pSession; pSession = 0;
retry = true; // only allow useproxy once
}
else
{
delete pSession; pSession = 0;
throw HTTPException(res.getReason(), uri.toString());
}
}
while (retry && redirects < MAX_REDIRECTS);
throw HTTPException("Too many redirects", uri.toString());
}
catch (...)
{
delete pSession;
throw;
}
}
void HTTPSStreamFactory::registerFactory()
{
std::string https("https");
URIStreamOpener::defaultOpener().registerStreamFactory(https, new HTTPSStreamFactory);
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: HTTPSClient
// Module: HTTPSStreamFactory
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPIOStream.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h"
using Poco::URIStreamFactory;
using Poco::URI;
using Poco::URIStreamOpener;
using Poco::UnbufferedStreamBuf;
namespace Poco {
namespace Net {
HTTPSStreamFactory::HTTPSStreamFactory():
_proxyPort(HTTPSession::HTTP_PORT)
{
}
HTTPSStreamFactory::HTTPSStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort):
_proxyHost(proxyHost),
_proxyPort(proxyPort)
{
}
HTTPSStreamFactory::HTTPSStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword):
_proxyHost(proxyHost),
_proxyPort(proxyPort),
_proxyUsername(proxyUsername),
_proxyPassword(proxyPassword)
{
}
HTTPSStreamFactory::~HTTPSStreamFactory()
{
}
std::istream* HTTPSStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "https" || uri.getScheme() == "http");
URI resolvedURI(uri);
URI proxyUri;
HTTPClientSession* pSession = 0;
try
{
bool retry = false;
int redirects = 0;
do
{
if (resolvedURI.getScheme() != "http")
pSession = new HTTPSClientSession(resolvedURI.getHost(), resolvedURI.getPort());
else
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
if (proxyUri.empty())
pSession->setProxy(_proxyHost, _proxyPort);
else
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
std::string path = resolvedURI.getPathAndQuery();
if (path.empty()) path = "/";
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
pSession->sendRequest(req);
HTTPResponse res;
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER ||
res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT);
if (moved)
{
resolvedURI.resolve(res.get("Location"));
//throw URIRedirection(resolvedURI.toString());
delete pSession; pSession = 0;
++redirects;
retry = true;
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
{
return new HTTPResponseStream(rs, pSession);
}
else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry)
{
// The requested resource MUST be accessed through the proxy
// given by the Location field. The Location field gives the
// URI of the proxy. The recipient is expected to repeat this
// single request via the proxy. 305 responses MUST only be generated by origin servers.
// only use for one single request!
proxyUri.resolve(res.get("Location"));
delete pSession; pSession = 0;
retry = true; // only allow useproxy once
}
else
{
delete pSession; pSession = 0;
throw HTTPException(res.getReason(), uri.toString());
}
}
while (retry && redirects < MAX_REDIRECTS);
throw HTTPException("Too many redirects", uri.toString());
}
catch (...)
{
delete pSession;
throw;
}
}
void HTTPSStreamFactory::registerFactory()
{
std::string https("https");
URIStreamOpener::defaultOpener().registerStreamFactory(https, new HTTPSStreamFactory);
}
} } // namespace Poco::Net

View File

@@ -1,75 +1,83 @@
//
// KeyFileHandler.cpp
//
//
// KeyFileHandler.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/KeyFileHandler.cpp#12 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: KeyFileHandler
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/KeyFileHandler.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/File.h"
#include "Poco/Util/LayeredConfiguration.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/OptionException.h"
namespace Poco {
namespace Net {
const std::string KeyFileHandler::CFG_PRIV_KEY_FILE("privateKeyPassphraseHandler.options.password");
KeyFileHandler::KeyFileHandler(bool server):PrivateKeyPassphraseHandler(server)
{
}
KeyFileHandler::~KeyFileHandler()
{
}
void KeyFileHandler::onPrivateKeyRequested(const void* pSender, std::string& privateKey)
{
Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
std::string prefix = serverSide() ? SSLManager::CFG_SERVER_PREFIX : SSLManager::CFG_CLIENT_PREFIX;
if (!config.hasProperty(prefix + CFG_PRIV_KEY_FILE))
{
throw Poco::Util::EmptyOptionException(std::string("Missing Configuration Entry: ") + prefix + CFG_PRIV_KEY_FILE);
}
privateKey = config.getString(prefix + CFG_PRIV_KEY_FILE);
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: KeyFileHandler
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/KeyFileHandler.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/File.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/OptionException.h"
namespace Poco {
namespace Net {
const std::string KeyFileHandler::CFG_PRIV_KEY_FILE("privateKeyPassphraseHandler.options.password");
KeyFileHandler::KeyFileHandler(bool server):PrivateKeyPassphraseHandler(server)
{
}
KeyFileHandler::~KeyFileHandler()
{
}
void KeyFileHandler::onPrivateKeyRequested(const void* pSender, std::string& privateKey)
{
try
{
Poco::Util::AbstractConfiguration& config = Poco::Util::Application::instance().config();
std::string prefix = serverSide() ? SSLManager::CFG_SERVER_PREFIX : SSLManager::CFG_CLIENT_PREFIX;
if (!config.hasProperty(prefix + CFG_PRIV_KEY_FILE))
throw Poco::Util::EmptyOptionException(std::string("Missing Configuration Entry: ") + prefix + CFG_PRIV_KEY_FILE);
privateKey = config.getString(prefix + CFG_PRIV_KEY_FILE);
}
catch (Poco::NullPointerException&)
{
throw Poco::IllegalStateException(
"An application configuration is required to obtain the private key passphrase, "
"but no Poco::Util::Application instance is available."
);
}
}
} } // namespace Poco::Net

View File

@@ -1,61 +1,61 @@
//
// PrivateKeyPassphraseHandler.cpp
//
//
// PrivateKeyPassphraseHandler.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/PrivateKeyPassphraseHandler.cpp#8 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: PrivateKeyPassphraseHandler
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Delegate.h"
using Poco::Delegate;
namespace Poco {
namespace Net {
PrivateKeyPassphraseHandler::PrivateKeyPassphraseHandler(bool onServerSide): _serverSide(onServerSide)
{
SSLManager::instance().PrivateKeyPassPhrase += Delegate<PrivateKeyPassphraseHandler, std::string>(this, &PrivateKeyPassphraseHandler::onPrivateKeyRequested);
}
PrivateKeyPassphraseHandler::~PrivateKeyPassphraseHandler()
{
SSLManager::instance().PrivateKeyPassPhrase -= Delegate<PrivateKeyPassphraseHandler, std::string>(this, &PrivateKeyPassphraseHandler::onPrivateKeyRequested);
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: PrivateKeyPassphraseHandler
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Delegate.h"
using Poco::Delegate;
namespace Poco {
namespace Net {
PrivateKeyPassphraseHandler::PrivateKeyPassphraseHandler(bool onServerSide): _serverSide(onServerSide)
{
SSLManager::instance().PrivateKeyPassphraseRequired += Delegate<PrivateKeyPassphraseHandler, std::string>(this, &PrivateKeyPassphraseHandler::onPrivateKeyRequested);
}
PrivateKeyPassphraseHandler::~PrivateKeyPassphraseHandler()
{
SSLManager::instance().PrivateKeyPassphraseRequired -= Delegate<PrivateKeyPassphraseHandler, std::string>(this, &PrivateKeyPassphraseHandler::onPrivateKeyRequested);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,60 @@
//
// RejectCertificateHandler.cpp
//
// $Id: //poco/1.4/NetSSL_OpenSSL/src/RejectCertificateHandler.cpp#1 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: RejectCertificateHandler
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/RejectCertificateHandler.h"
namespace Poco {
namespace Net {
RejectCertificateHandler::RejectCertificateHandler(bool server): InvalidCertificateHandler(server)
{
}
RejectCertificateHandler::~RejectCertificateHandler()
{
}
void RejectCertificateHandler::onInvalidCertificate(const void*, VerificationErrorArgs& errorCert)
{
errorCert.setIgnoreError(false);
}
} } // namespace Poco::Net

View File

@@ -1,51 +1,52 @@
//
// SSLException.cpp
//
//
// SSLException.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SSLException.cpp#10 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: SSLException
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SSLException.h"
#include <typeinfo>
namespace Poco {
namespace Net {
POCO_IMPLEMENT_EXCEPTION(SSLException, NetException, "SSL Exception")
POCO_IMPLEMENT_EXCEPTION(SSLContextException, SSLException, "SSL context exception")
POCO_IMPLEMENT_EXCEPTION(InvalidCertificateException, SSLException, "Invalid certficate")
POCO_IMPLEMENT_EXCEPTION(CertificateValidationException, SSLException, "Certificate validation error")
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: SSLException
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SSLException.h"
#include <typeinfo>
namespace Poco {
namespace Net {
POCO_IMPLEMENT_EXCEPTION(SSLException, NetException, "SSL Exception")
POCO_IMPLEMENT_EXCEPTION(SSLContextException, SSLException, "SSL context exception")
POCO_IMPLEMENT_EXCEPTION(InvalidCertificateException, SSLException, "Invalid certficate")
POCO_IMPLEMENT_EXCEPTION(CertificateValidationException, SSLException, "Certificate validation error")
POCO_IMPLEMENT_EXCEPTION(SSLConnectionUnexpectedlyClosedException, SSLException, "SSL connection unexpectedly closed")
} } // namespace Poco::Net

View File

@@ -1,300 +1,395 @@
//
// SSLManager.cpp
//
//
// SSLManager.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SSLManager.cpp#15 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: SSLManager
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Utility.h"
#include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/Net/SSLException.h"
#include "Poco/SingletonHolder.h"
#include "Poco/Delegate.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/OptionException.h"
#include "Poco/Util/LayeredConfiguration.h"
namespace Poco {
namespace Net {
const std::string SSLManager::CFG_PRIV_KEY_FILE("privateKeyFile");
const std::string SSLManager::CFG_CERTIFICATE_FILE("certificateFile");
const std::string SSLManager::CFG_CA_LOCATION("caConfig");
const std::string SSLManager::CFG_VER_MODE("verificationMode");
const Context::VerificationMode SSLManager::VAL_VER_MODE(Context::VERIFY_STRICT);
const std::string SSLManager::CFG_VER_DEPTH("verificationDepth");
const int SSLManager::VAL_VER_DEPTH(9);
const std::string SSLManager::CFG_ENABLE_DEFAULT_CA("loadDefaultCAFile");
const bool SSLManager::VAL_ENABLE_DEFAULT_CA(false);
const std::string SSLManager::CFG_CYPHER_LIST("cypherList");
const std::string SSLManager::VAL_CYPHER_LIST("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
const std::string SSLManager::CFG_DELEGATE_HANDLER("privateKeyPassphraseHandler.name");
const std::string SSLManager::VAL_DELEGATE_HANDLER("KeyConsoleHandler");
const std::string SSLManager::CFG_CERTIFICATE_HANDLER("invalidCertificateHandler.name");
const std::string SSLManager::VAL_CERTIFICATE_HANDLER("ConsoleCertificateHandler");
const std::string SSLManager::CFG_SERVER_PREFIX("openSSL.server.");
const std::string SSLManager::CFG_CLIENT_PREFIX("openSSL.client.");
SSLManager::SSLManager()
{
Poco::Crypto::OpenSSLInitializer::initialize();
}
SSLManager::~SSLManager()
{
PrivateKeyPassPhrase.clear();
ClientVerificationError.clear();
ServerVerificationError.clear();
_ptrDefaultServerContext = 0; // ensure all Context objects go away before we uninitialize OpenSSL.
_ptrDefaultClientContext = 0;
Poco::Crypto::OpenSSLInitializer::uninitialize();
}
SSLManager& SSLManager::instance()
{
static Poco::SingletonHolder<SSLManager> singleton;
return *singleton.get();
}
void SSLManager::initializeServer(PrivateKeyPassphraseHandlerPtr ptrPassPhraseHandler, InvalidCertificateHandlerPtr ptrHandler, Context::Ptr ptrContext)
{
_ptrServerPassPhraseHandler = ptrPassPhraseHandler;
_ptrServerCertificateHandler = ptrHandler;
_ptrDefaultServerContext = ptrContext;
}
void SSLManager::initializeClient(PrivateKeyPassphraseHandlerPtr ptrPassPhraseHandler, InvalidCertificateHandlerPtr ptrHandler, Context::Ptr ptrContext)
{
_ptrClientPassPhraseHandler = ptrPassPhraseHandler;
_ptrClientCertificateHandler = ptrHandler;
_ptrDefaultClientContext = ptrContext;
}
Context::Ptr SSLManager::defaultServerContext()
{
if (!_ptrDefaultServerContext)
initDefaultContext(true);
return _ptrDefaultServerContext;
}
Context::Ptr SSLManager::defaultClientContext()
{
if (!_ptrDefaultClientContext)
initDefaultContext(false);
return _ptrDefaultClientContext;
}
SSLManager::PrivateKeyPassphraseHandlerPtr SSLManager::serverPassPhraseHandler()
{
if (!_ptrServerPassPhraseHandler)
initPassPhraseHandler(true);
return _ptrServerPassPhraseHandler;
}
SSLManager::PrivateKeyPassphraseHandlerPtr SSLManager::clientPassPhraseHandler()
{
if (!_ptrClientPassPhraseHandler)
initPassPhraseHandler(false);
return _ptrClientPassPhraseHandler;
}
SSLManager::InvalidCertificateHandlerPtr SSLManager::serverCertificateHandler()
{
if (!_ptrServerCertificateHandler)
initCertificateHandler(true);
return _ptrServerCertificateHandler;
}
SSLManager::InvalidCertificateHandlerPtr SSLManager::clientCertificateHandler()
{
if (!_ptrClientCertificateHandler)
initCertificateHandler(false);
return _ptrClientCertificateHandler;
}
int SSLManager::verifyCallback(bool server, int ok, X509_STORE_CTX* pStore)
{
if (!ok)
{
X509* pCert = X509_STORE_CTX_get_current_cert(pStore);
X509Certificate x509(pCert);
int depth = X509_STORE_CTX_get_error_depth(pStore);
int err = X509_STORE_CTX_get_error(pStore);
std::string error(X509_verify_cert_error_string(err));
VerificationErrorArgs args(x509, depth, err, error);
if (server)
SSLManager::instance().ServerVerificationError.notify(&SSLManager::instance(), args);
else
SSLManager::instance().ClientVerificationError.notify(&SSLManager::instance(), args);
ok = args.getIgnoreError() ? 1 : 0;
}
return ok;
}
int SSLManager::privateKeyPasswdCallback(char* pBuf, int size, int flag, void* userData)
{
std::string pwd;
SSLManager::instance().PrivateKeyPassPhrase.notify(&SSLManager::instance(), pwd);
strncpy(pBuf, (char *)(pwd.c_str()), size);
pBuf[size - 1] = '\0';
if (size > pwd.length())
size = (int) pwd.length();
return size;
}
void SSLManager::initDefaultContext(bool server)
{
if (server && _ptrDefaultServerContext) return;
if (!server && _ptrDefaultClientContext) return;
initEvents(server);
Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
// mandatory options
std::string privKeyFile = config.getString(prefix + CFG_PRIV_KEY_FILE, "");
std::string certFile = config.getString(prefix + CFG_CERTIFICATE_FILE, privKeyFile);
std::string caLocation = config.getString(prefix + CFG_CA_LOCATION, "");
if (certFile.empty() && privKeyFile.empty())
throw SSLException("Configuration error: no certificate file has been specified.");
// optional options for which we have defaults defined
Context::VerificationMode verMode = VAL_VER_MODE;
if (config.hasProperty(prefix + CFG_VER_MODE))
{
// either: none, relaxed, strict, once
std::string mode = config.getString(prefix + CFG_VER_MODE);
verMode = Utility::convertVerificationMode(mode);
}
int verDepth = config.getInt(prefix + CFG_VER_DEPTH, VAL_VER_DEPTH);
bool loadDefCA = config.getBool(prefix + CFG_ENABLE_DEFAULT_CA, VAL_ENABLE_DEFAULT_CA);
std::string cypherList = config.getString(prefix + CFG_CYPHER_LIST, VAL_CYPHER_LIST);
if (server)
_ptrDefaultServerContext = new Context(Context::SERVER_USE, privKeyFile, certFile, caLocation, verMode, verDepth, loadDefCA, cypherList);
else
_ptrDefaultClientContext = new Context(Context::CLIENT_USE, privKeyFile, certFile, caLocation, verMode, verDepth, loadDefCA, cypherList);
}
void SSLManager::initEvents(bool server)
{
initPassPhraseHandler(server);
initCertificateHandler(server);
}
void SSLManager::initPassPhraseHandler(bool server)
{
if (server && _ptrServerPassPhraseHandler) return;
if (!server && _ptrClientPassPhraseHandler) return;
std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
std::string className(config.getString(prefix + CFG_DELEGATE_HANDLER, VAL_DELEGATE_HANDLER));
const PrivateKeyFactory* pFactory = 0;
if (privateKeyFactoryMgr().hasFactory(className))
{
pFactory = privateKeyFactoryMgr().getFactory(className);
}
if (pFactory)
{
if (server)
_ptrServerPassPhraseHandler = pFactory->create(server);
else
_ptrClientPassPhraseHandler = pFactory->create(server);
}
else throw Poco::Util::UnknownOptionException(std::string("No PassPhrasehandler known with the name ") + className);
}
void SSLManager::initCertificateHandler(bool server)
{
if (server && _ptrServerCertificateHandler) return;
if (!server && _ptrClientCertificateHandler) return;
std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
std::string className(config.getString(prefix+CFG_CERTIFICATE_HANDLER, VAL_CERTIFICATE_HANDLER));
const CertificateHandlerFactory* pFactory = 0;
if (certificateHandlerFactoryMgr().hasFactory(className))
{
pFactory = certificateHandlerFactoryMgr().getFactory(className);
}
if (pFactory)
{
if (server)
_ptrServerCertificateHandler = pFactory->create(true);
else
_ptrClientCertificateHandler = pFactory->create(false);
}
else throw Poco::Util::UnknownOptionException(std::string("No InvalidCertificate handler known with the name ") + className);
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: SSLManager
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Utility.h"
#include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/Net/SSLException.h"
#include "Poco/SingletonHolder.h"
#include "Poco/Delegate.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/OptionException.h"
namespace Poco {
namespace Net {
const std::string SSLManager::CFG_PRIV_KEY_FILE("privateKeyFile");
const std::string SSLManager::CFG_CERTIFICATE_FILE("certificateFile");
const std::string SSLManager::CFG_CA_LOCATION("caConfig");
const std::string SSLManager::CFG_VER_MODE("verificationMode");
const Context::VerificationMode SSLManager::VAL_VER_MODE(Context::VERIFY_STRICT);
const std::string SSLManager::CFG_VER_DEPTH("verificationDepth");
const int SSLManager::VAL_VER_DEPTH(9);
const std::string SSLManager::CFG_ENABLE_DEFAULT_CA("loadDefaultCAFile");
const bool SSLManager::VAL_ENABLE_DEFAULT_CA(false);
const std::string SSLManager::CFG_CIPHER_LIST("cipherList");
const std::string SSLManager::CFG_CYPHER_LIST("cypherList");
const std::string SSLManager::VAL_CIPHER_LIST("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
const std::string SSLManager::CFG_DELEGATE_HANDLER("privateKeyPassphraseHandler.name");
const std::string SSLManager::VAL_DELEGATE_HANDLER("KeyConsoleHandler");
const std::string SSLManager::CFG_CERTIFICATE_HANDLER("invalidCertificateHandler.name");
const std::string SSLManager::VAL_CERTIFICATE_HANDLER("ConsoleCertificateHandler");
const std::string SSLManager::CFG_SERVER_PREFIX("openSSL.server.");
const std::string SSLManager::CFG_CLIENT_PREFIX("openSSL.client.");
const std::string SSLManager::CFG_CACHE_SESSIONS("cacheSessions");
const std::string SSLManager::CFG_SESSION_ID_CONTEXT("sessionIdContext");
const std::string SSLManager::CFG_SESSION_CACHE_SIZE("sessionCacheSize");
const std::string SSLManager::CFG_SESSION_TIMEOUT("sessionTimeout");
const std::string SSLManager::CFG_EXTENDED_VERIFICATION("extendedVerification");
#ifdef OPENSSL_FIPS
const std::string SSLManager::CFG_FIPS_MODE("openSSL.fips");
const bool SSLManager::VAL_FIPS_MODE(false);
#endif
SSLManager::SSLManager()
{
}
SSLManager::~SSLManager()
{
shutdown();
}
void SSLManager::shutdown()
{
PrivateKeyPassphraseRequired.clear();
ClientVerificationError.clear();
ServerVerificationError.clear();
_ptrDefaultServerContext = 0;
_ptrDefaultClientContext = 0;
}
namespace
{
static Poco::SingletonHolder<SSLManager> singleton;
}
SSLManager& SSLManager::instance()
{
return *singleton.get();
}
void SSLManager::initializeServer(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr ptrHandler, Context::Ptr ptrContext)
{
_ptrServerPassphraseHandler = ptrPassphraseHandler;
_ptrServerCertificateHandler = ptrHandler;
_ptrDefaultServerContext = ptrContext;
}
void SSLManager::initializeClient(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr ptrHandler, Context::Ptr ptrContext)
{
_ptrClientPassphraseHandler = ptrPassphraseHandler;
_ptrClientCertificateHandler = ptrHandler;
_ptrDefaultClientContext = ptrContext;
}
Context::Ptr SSLManager::defaultServerContext()
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_ptrDefaultServerContext)
initDefaultContext(true);
return _ptrDefaultServerContext;
}
Context::Ptr SSLManager::defaultClientContext()
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_ptrDefaultClientContext)
initDefaultContext(false);
return _ptrDefaultClientContext;
}
SSLManager::PrivateKeyPassphraseHandlerPtr SSLManager::serverPassphraseHandler()
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_ptrServerPassphraseHandler)
initPassphraseHandler(true);
return _ptrServerPassphraseHandler;
}
SSLManager::PrivateKeyPassphraseHandlerPtr SSLManager::clientPassphraseHandler()
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_ptrClientPassphraseHandler)
initPassphraseHandler(false);
return _ptrClientPassphraseHandler;
}
SSLManager::InvalidCertificateHandlerPtr SSLManager::serverCertificateHandler()
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_ptrServerCertificateHandler)
initCertificateHandler(true);
return _ptrServerCertificateHandler;
}
SSLManager::InvalidCertificateHandlerPtr SSLManager::clientCertificateHandler()
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_ptrClientCertificateHandler)
initCertificateHandler(false);
return _ptrClientCertificateHandler;
}
int SSLManager::verifyCallback(bool server, int ok, X509_STORE_CTX* pStore)
{
if (!ok)
{
X509* pCert = X509_STORE_CTX_get_current_cert(pStore);
X509Certificate x509(pCert, true);
int depth = X509_STORE_CTX_get_error_depth(pStore);
int err = X509_STORE_CTX_get_error(pStore);
std::string error(X509_verify_cert_error_string(err));
VerificationErrorArgs args(x509, depth, err, error);
if (server)
SSLManager::instance().ServerVerificationError.notify(&SSLManager::instance(), args);
else
SSLManager::instance().ClientVerificationError.notify(&SSLManager::instance(), args);
ok = args.getIgnoreError() ? 1 : 0;
}
return ok;
}
int SSLManager::privateKeyPassphraseCallback(char* pBuf, int size, int flag, void* userData)
{
std::string pwd;
SSLManager::instance().PrivateKeyPassphraseRequired.notify(&SSLManager::instance(), pwd);
strncpy(pBuf, (char *)(pwd.c_str()), size);
pBuf[size - 1] = '\0';
if (size > pwd.length())
size = (int) pwd.length();
return size;
}
void SSLManager::initDefaultContext(bool server)
{
if (server && _ptrDefaultServerContext) return;
if (!server && _ptrDefaultClientContext) return;
Poco::Crypto::OpenSSLInitializer openSSLInitializer;
initEvents(server);
Poco::Util::AbstractConfiguration& config = appConfig();
#ifdef OPENSSL_FIPS
bool fipsEnabled = config.getBool(CFG_FIPS_MODE, VAL_FIPS_MODE);
if (fipsEnabled && !Poco::Crypto::OpenSSLInitializer::isFIPSEnabled())
{
Poco::Crypto::OpenSSLInitializer::enableFIPSMode(true);
}
#endif
std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
// mandatory options
std::string privKeyFile = config.getString(prefix + CFG_PRIV_KEY_FILE, "");
std::string certFile = config.getString(prefix + CFG_CERTIFICATE_FILE, privKeyFile);
std::string caLocation = config.getString(prefix + CFG_CA_LOCATION, "");
if (server && certFile.empty() && privKeyFile.empty())
throw SSLException("Configuration error: no certificate file has been specified");
// optional options for which we have defaults defined
Context::VerificationMode verMode = VAL_VER_MODE;
if (config.hasProperty(prefix + CFG_VER_MODE))
{
// either: none, relaxed, strict, once
std::string mode = config.getString(prefix + CFG_VER_MODE);
verMode = Utility::convertVerificationMode(mode);
}
int verDepth = config.getInt(prefix + CFG_VER_DEPTH, VAL_VER_DEPTH);
bool loadDefCA = config.getBool(prefix + CFG_ENABLE_DEFAULT_CA, VAL_ENABLE_DEFAULT_CA);
std::string cipherList = config.getString(prefix + CFG_CIPHER_LIST, VAL_CIPHER_LIST);
cipherList = config.getString(prefix + CFG_CYPHER_LIST, cipherList); // for backwards compatibility
if (server)
_ptrDefaultServerContext = new Context(Context::SERVER_USE, privKeyFile, certFile, caLocation, verMode, verDepth, loadDefCA, cipherList);
else
_ptrDefaultClientContext = new Context(Context::CLIENT_USE, privKeyFile, certFile, caLocation, verMode, verDepth, loadDefCA, cipherList);
bool cacheSessions = config.getBool(prefix + CFG_CACHE_SESSIONS, false);
if (server)
{
std::string sessionIdContext = config.getString(prefix + CFG_SESSION_ID_CONTEXT, config.getString("application.name", ""));
_ptrDefaultServerContext->enableSessionCache(cacheSessions, sessionIdContext);
if (config.hasProperty(prefix + CFG_SESSION_CACHE_SIZE))
{
int cacheSize = config.getInt(prefix + CFG_SESSION_CACHE_SIZE);
_ptrDefaultServerContext->setSessionCacheSize(cacheSize);
}
if (config.hasProperty(prefix + CFG_SESSION_TIMEOUT))
{
int timeout = config.getInt(prefix + CFG_SESSION_TIMEOUT);
_ptrDefaultServerContext->setSessionTimeout(timeout);
}
}
else
{
_ptrDefaultClientContext->enableSessionCache(cacheSessions);
}
bool extendedVerification = config.getBool(prefix + CFG_EXTENDED_VERIFICATION, false);
if (server)
_ptrDefaultServerContext->enableExtendedCertificateVerification(extendedVerification);
else
_ptrDefaultClientContext->enableExtendedCertificateVerification(extendedVerification);
}
void SSLManager::initEvents(bool server)
{
initPassphraseHandler(server);
initCertificateHandler(server);
}
void SSLManager::initPassphraseHandler(bool server)
{
if (server && _ptrServerPassphraseHandler) return;
if (!server && _ptrClientPassphraseHandler) return;
std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
Poco::Util::AbstractConfiguration& config = appConfig();
std::string className(config.getString(prefix + CFG_DELEGATE_HANDLER, VAL_DELEGATE_HANDLER));
const PrivateKeyFactory* pFactory = 0;
if (privateKeyFactoryMgr().hasFactory(className))
{
pFactory = privateKeyFactoryMgr().getFactory(className);
}
if (pFactory)
{
if (server)
_ptrServerPassphraseHandler = pFactory->create(server);
else
_ptrClientPassphraseHandler = pFactory->create(server);
}
else throw Poco::Util::UnknownOptionException(std::string("No passphrase handler known with the name ") + className);
}
void SSLManager::initCertificateHandler(bool server)
{
if (server && _ptrServerCertificateHandler) return;
if (!server && _ptrClientCertificateHandler) return;
std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
Poco::Util::AbstractConfiguration& config = appConfig();
std::string className(config.getString(prefix+CFG_CERTIFICATE_HANDLER, VAL_CERTIFICATE_HANDLER));
const CertificateHandlerFactory* pFactory = 0;
if (certificateHandlerFactoryMgr().hasFactory(className))
{
pFactory = certificateHandlerFactoryMgr().getFactory(className);
}
if (pFactory)
{
if (server)
_ptrServerCertificateHandler = pFactory->create(true);
else
_ptrClientCertificateHandler = pFactory->create(false);
}
else throw Poco::Util::UnknownOptionException(std::string("No InvalidCertificate handler known with the name ") + className);
}
Poco::Util::AbstractConfiguration& SSLManager::appConfig()
{
try
{
return Poco::Util::Application::instance().config();
}
catch (Poco::NullPointerException&)
{
throw Poco::IllegalStateException(
"An application configuration is required to initialize the Poco::Net::SSLManager, "
"but no Poco::Util::Application instance is available."
);
}
}
void initializeSSL()
{
Poco::Crypto::initializeCrypto();
}
void uninitializeSSL()
{
SSLManager::instance().shutdown();
Poco::Crypto::uninitializeCrypto();
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,85 @@
//
// SecureSMTPClientSession.h
//
// $Id: //poco/1.4/NetSSL_OpenSSL/src/SecureSMTPClientSession.cpp#1 $
//
// Library: NetSSL_OpenSSL
// Package: Mail
// Module: SecureSMTPClientSession
//
// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureSMTPClientSession.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/DialogSocket.h"
namespace Poco {
namespace Net {
SecureSMTPClientSession::SecureSMTPClientSession(const StreamSocket& socket):
SMTPClientSession(socket)
{
}
SecureSMTPClientSession::SecureSMTPClientSession(const std::string& host, Poco::UInt16 port):
SMTPClientSession(host, port)
{
}
SecureSMTPClientSession::~SecureSMTPClientSession()
{
}
bool SecureSMTPClientSession::startTLS()
{
return startTLS(SSLManager::instance().defaultClientContext());
}
bool SecureSMTPClientSession::startTLS(Context::Ptr pContext)
{
int status = 0;
std::string response;
status = sendCommand("STARTTLS", response);
if (!isPositiveCompletion(status)) return false;
SecureStreamSocket sss(SecureStreamSocket::attach(socket(), pContext));
socket() = sss;
return true;
}
} } // namespace Poco::Net

View File

@@ -1,130 +1,136 @@
//
// SecureServerSocketImpl.cpp
//
//
// SecureServerSocketImpl.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SecureServerSocketImpl.cpp#9 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureServerSocketImpl
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureServerSocketImpl.h"
namespace Poco {
namespace Net {
SecureServerSocketImpl::SecureServerSocketImpl(Context::Ptr pContext):
_impl(new ServerSocketImpl, pContext)
{
}
SecureServerSocketImpl::~SecureServerSocketImpl()
{
}
SocketImpl* SecureServerSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
return _impl.acceptConnection(clientAddr);
}
void SecureServerSocketImpl::connect(const SocketAddress& address)
{
throw Poco::InvalidAccessException("Cannot connect() a SecureServerSocket");
}
void SecureServerSocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout)
{
throw Poco::InvalidAccessException("Cannot connect() a SecureServerSocket");
}
void SecureServerSocketImpl::connectNB(const SocketAddress& address)
{
throw Poco::InvalidAccessException("Cannot connect() a SecureServerSocket");
}
void SecureServerSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
_impl.bind(address, reuseAddress);
reset(_impl.sockfd());
}
void SecureServerSocketImpl::listen(int backlog)
{
_impl.listen(backlog);
reset(_impl.sockfd());
}
void SecureServerSocketImpl::close()
{
reset();
_impl.close();
}
int SecureServerSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
throw Poco::InvalidAccessException("Cannot sendBytes() on a SecureServerSocket");
}
int SecureServerSocketImpl::receiveBytes(void* buffer, int length, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveBytes() on a SecureServerSocket");
}
int SecureServerSocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot sendTo() on a SecureServerSocket");
}
int SecureServerSocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveFrom() on a SecureServerSocket");
}
void SecureServerSocketImpl::sendUrgent(unsigned char data)
{
throw Poco::InvalidAccessException("Cannot sendUrgent() on a SecureServerSocket");
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureServerSocketImpl
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureServerSocketImpl.h"
namespace Poco {
namespace Net {
SecureServerSocketImpl::SecureServerSocketImpl(Context::Ptr pContext):
_impl(new ServerSocketImpl, pContext)
{
}
SecureServerSocketImpl::~SecureServerSocketImpl()
{
}
SocketImpl* SecureServerSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
return _impl.acceptConnection(clientAddr);
}
void SecureServerSocketImpl::connect(const SocketAddress& address)
{
throw Poco::InvalidAccessException("Cannot connect() a SecureServerSocket");
}
void SecureServerSocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout)
{
throw Poco::InvalidAccessException("Cannot connect() a SecureServerSocket");
}
void SecureServerSocketImpl::connectNB(const SocketAddress& address)
{
throw Poco::InvalidAccessException("Cannot connect() a SecureServerSocket");
}
void SecureServerSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
_impl.bind(address, reuseAddress);
reset(_impl.sockfd());
}
void SecureServerSocketImpl::listen(int backlog)
{
_impl.listen(backlog);
reset(_impl.sockfd());
}
void SecureServerSocketImpl::close()
{
reset();
_impl.close();
}
int SecureServerSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
throw Poco::InvalidAccessException("Cannot sendBytes() on a SecureServerSocket");
}
int SecureServerSocketImpl::receiveBytes(void* buffer, int length, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveBytes() on a SecureServerSocket");
}
int SecureServerSocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot sendTo() on a SecureServerSocket");
}
int SecureServerSocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveFrom() on a SecureServerSocket");
}
void SecureServerSocketImpl::sendUrgent(unsigned char data)
{
throw Poco::InvalidAccessException("Cannot sendUrgent() on a SecureServerSocket");
}
bool SecureServerSocketImpl::secure() const
{
return true;
}
} } // namespace Poco::Net

View File

@@ -1,386 +1,495 @@
//
// SecureSocketImpl.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SecureSocketImpl.cpp#30 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureSocketImpl
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureSocketImpl.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/X509Certificate.h"
#include "Poco/Net/Utility.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/DNS.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
#include <openssl/x509v3.h>
#include <openssl/err.h>
using Poco::IOException;
using Poco::TimeoutException;
using Poco::InvalidArgumentException;
using Poco::NumberFormatter;
using Poco::Timespan;
// workaround for C++-incompatible macro
#define POCO_BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(void*)((n)?"a":NULL))
namespace Poco {
namespace Net {
SecureSocketImpl::SecureSocketImpl(Poco::AutoPtr<SocketImpl> pSocketImpl, Context::Ptr pContext):
_pSSL(0),
_pSocket(pSocketImpl),
_pContext(pContext)
{
poco_check_ptr (_pSocket);
poco_check_ptr (_pContext);
}
SecureSocketImpl::~SecureSocketImpl()
{
close();
}
SocketImpl* SecureSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
poco_assert (!_pSSL);
StreamSocket ss = _pSocket->acceptConnection(clientAddr);
Poco::AutoPtr<SecureStreamSocketImpl> pSecureStreamSocketImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(ss.impl()), _pContext);
pSecureStreamSocketImpl->acceptSSL();
pSecureStreamSocketImpl->duplicate();
return pSecureStreamSocketImpl;
}
void SecureSocketImpl::acceptSSL()
{
poco_assert (!_pSSL);
BIO* pBIO = BIO_new(BIO_s_socket());
if (!pBIO) throw SSLException("Cannot create BIO object");
BIO_set_fd(pBIO, _pSocket->sockfd(), BIO_NOCLOSE);
_pSSL = SSL_new(_pContext->sslContext());
if (!_pSSL)
{
BIO_free(pBIO);
throw SSLException("Cannot create SSL object");
}
SSL_set_bio(_pSSL, pBIO, pBIO);
try
{
if (_pSocket->getBlocking())
{
int err = SSL_accept(_pSSL);
if (err > 0)
{
std::string clientName = _pSocket->peerAddress().host().toString();
long certErr = verifyCertificate(clientName);
if (certErr != X509_V_OK)
{
std::string msg = Utility::convertCertificateError(certErr);
throw CertificateValidationException("Unacceptable certificate from " + clientName, msg);
}
}
else
{
handleError(err);
}
}
else
{
SSL_set_accept_state(_pSSL);
}
}
catch (...)
{
SSL_shutdown(_pSSL);
SSL_free(_pSSL);
_pSSL = 0;
throw;
}
}
void SecureSocketImpl::connect(const SocketAddress& address, const std::string& hostName)
{
poco_assert (!_pSSL);
_pSocket->connect(address);
connectSSL(hostName);
}
void SecureSocketImpl::connect(const SocketAddress& address, const std::string& hostName, const Poco::Timespan& timeout)
{
poco_assert (!_pSSL);
_pSocket->connect(address, timeout);
connectSSL(hostName);
}
void SecureSocketImpl::connectNB(const SocketAddress& address, const std::string& hostName)
{
poco_assert (!_pSSL);
_pSocket->connectNB(address);
connectSSL(hostName);
}
void SecureSocketImpl::connectSSL(const std::string& hostName)
{
poco_assert (!_pSSL);
poco_assert (_pSocket->initialized());
BIO* pBIO = BIO_new(BIO_s_socket());
if (!pBIO) throw SSLException("Cannot create SSL BIO object");
BIO_set_fd(pBIO, _pSocket->sockfd(), BIO_NOCLOSE);
_pSSL = SSL_new(_pContext->sslContext());
if (!_pSSL)
{
BIO_free(pBIO);
throw SSLException("Cannot create SSL object");
}
SSL_set_bio(_pSSL, pBIO, pBIO);
try
{
if (_pSocket->getBlocking())
{
int ret = SSL_connect(_pSSL);
handleError(ret);
long certErr = verifyCertificate(hostName);
if (certErr != X509_V_OK)
{
std::string msg = Utility::convertCertificateError(certErr);
throw InvalidCertificateException(msg);
}
}
else
{
SSL_set_connect_state(_pSSL);
}
}
catch (...)
{
SSL_free(_pSSL);
_pSSL = 0;
throw;
}
}
void SecureSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
poco_check_ptr (_pSocket);
_pSocket->bind(address, reuseAddress);
}
void SecureSocketImpl::listen(int backlog)
{
poco_check_ptr (_pSocket);
_pSocket->listen(backlog);
}
void SecureSocketImpl::shutdown()
{
if (_pSSL)
{
// A proper clean shutdown would require us to
// retry the shutdown if we get a zero return
// value, until SSL_shutdown() returns 1.
// However, this will lead to problems with
// most web browsers, so we just set the shutdown
// flag by calling SSL_shutdown() once and be
// done with it.
int rc = SSL_shutdown(_pSSL);
if (rc < 0) handleError(rc);
SSL_clear(_pSSL);
SSL_free(_pSSL);
_pSSL = 0;
}
}
void SecureSocketImpl::close()
{
shutdown();
_pSocket->close();
}
int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
poco_assert (_pSocket->initialized());
poco_check_ptr (_pSSL);
int rc;
do
{
rc = SSL_write(_pSSL, buffer, length);
}
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
if (rc <= 0)
{
return handleError(rc);
}
return rc;
}
int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
{
poco_assert (_pSocket->initialized());
poco_check_ptr (_pSSL);
int rc;
do
{
rc = SSL_read(_pSSL, buffer, length);
}
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
if (rc <= 0)
{
return handleError(rc);
}
return rc;
}
long SecureSocketImpl::verifyCertificate(const std::string& hostName)
{
Context::VerificationMode mode = _pContext->verificationMode();
if (mode == Context::VERIFY_NONE || (isLocalHost(hostName) && mode != Context::VERIFY_STRICT))
{
return X509_V_OK;
}
X509* pCert = SSL_get_peer_certificate(_pSSL);
if (pCert)
{
X509Certificate cert(pCert);
return cert.verify(hostName);
}
else return X509_V_OK;
}
bool SecureSocketImpl::isLocalHost(const std::string& hostName)
{
SocketAddress addr(hostName, 0);
return addr.host().isLoopback();
}
X509* SecureSocketImpl::peerCertificate() const
{
if (_pSSL)
return SSL_get_peer_certificate(_pSSL);
else
return 0;
}
int SecureSocketImpl::handleError(int rc)
{
if (rc > 0) return rc;
int sslError = SSL_get_error(_pSSL, rc);
switch (sslError)
{
case SSL_ERROR_ZERO_RETURN:
return 0;
case SSL_ERROR_WANT_READ:
return SecureStreamSocket::ERR_SSL_WANT_READ;
case SSL_ERROR_WANT_WRITE:
return SecureStreamSocket::ERR_SSL_WANT_WRITE;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
// these should not occur
poco_bugcheck();
return rc;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
{
long lastError = ERR_get_error();
if (lastError == 0)
{
if (rc == 0)
{
throw SSLException("The underlying socket connection has been unexpectedly closed");
}
else if (rc == -1)
{
SecureStreamSocketImpl::error("The BIO reported an error");
}
}
else
{
char buffer[256];
ERR_error_string_n(lastError, buffer, sizeof(buffer));
std::string msg(buffer);
throw SSLException(msg);
}
}
break;
default:
break;
}
return rc;
}
} } // namespace Poco::Net
//
// SecureSocketImpl.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SecureSocketImpl.cpp#30 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureSocketImpl
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureSocketImpl.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/X509Certificate.h"
#include "Poco/Net/Utility.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/DNS.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
#include "Poco/Format.h"
#include <openssl/x509v3.h>
#include <openssl/err.h>
using Poco::IOException;
using Poco::TimeoutException;
using Poco::InvalidArgumentException;
using Poco::NumberFormatter;
using Poco::Timespan;
// workaround for C++-incompatible macro
#define POCO_BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(void*)((n)?"a":NULL))
namespace Poco {
namespace Net {
SecureSocketImpl::SecureSocketImpl(Poco::AutoPtr<SocketImpl> pSocketImpl, Context::Ptr pContext):
_pSSL(0),
_pSocket(pSocketImpl),
_pContext(pContext),
_needHandshake(false)
{
poco_check_ptr (_pSocket);
poco_check_ptr (_pContext);
}
SecureSocketImpl::~SecureSocketImpl()
{
try
{
reset();
}
catch (...)
{
}
}
SocketImpl* SecureSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
poco_assert (!_pSSL);
StreamSocket ss = _pSocket->acceptConnection(clientAddr);
Poco::AutoPtr<SecureStreamSocketImpl> pSecureStreamSocketImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(ss.impl()), _pContext);
pSecureStreamSocketImpl->acceptSSL();
pSecureStreamSocketImpl->duplicate();
return pSecureStreamSocketImpl;
}
void SecureSocketImpl::acceptSSL()
{
poco_assert (!_pSSL);
BIO* pBIO = BIO_new(BIO_s_socket());
if (!pBIO) throw SSLException("Cannot create BIO object");
BIO_set_fd(pBIO, static_cast<int>(_pSocket->sockfd()), BIO_NOCLOSE);
_pSSL = SSL_new(_pContext->sslContext());
if (!_pSSL)
{
BIO_free(pBIO);
throw SSLException("Cannot create SSL object");
}
SSL_set_bio(_pSSL, pBIO, pBIO);
SSL_set_accept_state(_pSSL);
_needHandshake = true;
}
void SecureSocketImpl::connect(const SocketAddress& address, bool performHandshake)
{
if (_pSSL) reset();
poco_assert (!_pSSL);
_pSocket->connect(address);
connectSSL(performHandshake);
}
void SecureSocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout, bool performHandshake)
{
if (_pSSL) reset();
poco_assert (!_pSSL);
_pSocket->connect(address, timeout);
connectSSL(performHandshake);
}
void SecureSocketImpl::connectNB(const SocketAddress& address)
{
if (_pSSL) reset();
poco_assert (!_pSSL);
_pSocket->connectNB(address);
connectSSL(false);
}
void SecureSocketImpl::connectSSL(bool performHandshake)
{
poco_assert (!_pSSL);
poco_assert (_pSocket->initialized());
BIO* pBIO = BIO_new(BIO_s_socket());
if (!pBIO) throw SSLException("Cannot create SSL BIO object");
BIO_set_fd(pBIO, static_cast<int>(_pSocket->sockfd()), BIO_NOCLOSE);
_pSSL = SSL_new(_pContext->sslContext());
if (!_pSSL)
{
BIO_free(pBIO);
throw SSLException("Cannot create SSL object");
}
SSL_set_bio(_pSSL, pBIO, pBIO);
if (_pSession)
{
SSL_set_session(_pSSL, _pSession->sslSession());
}
try
{
if (performHandshake && _pSocket->getBlocking())
{
int ret = SSL_connect(_pSSL);
handleError(ret);
verifyPeerCertificate();
}
else
{
SSL_set_connect_state(_pSSL);
_needHandshake = true;
}
}
catch (...)
{
SSL_free(_pSSL);
_pSSL = 0;
throw;
}
}
void SecureSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
poco_check_ptr (_pSocket);
_pSocket->bind(address, reuseAddress);
}
void SecureSocketImpl::listen(int backlog)
{
poco_check_ptr (_pSocket);
_pSocket->listen(backlog);
}
void SecureSocketImpl::shutdown()
{
if (_pSSL)
{
// Don't shut down the socket more than once.
int shutdownState = SSL_get_shutdown(_pSSL);
bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN;
if (!shutdownSent)
{
// A proper clean shutdown would require us to
// retry the shutdown if we get a zero return
// value, until SSL_shutdown() returns 1.
// However, this will lead to problems with
// most web browsers, so we just set the shutdown
// flag by calling SSL_shutdown() once and be
// done with it.
int rc = SSL_shutdown(_pSSL);
if (rc < 0) handleError(rc);
SSL_clear(_pSSL);
SSL_free(_pSSL);
_pSSL = 0;
}
}
}
void SecureSocketImpl::close()
{
shutdown();
_pSocket->close();
}
int SecureSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
poco_assert (_pSocket->initialized());
poco_check_ptr (_pSSL);
int rc;
if (_needHandshake)
{
rc = completeHandshake();
if (rc == 1)
verifyPeerCertificate();
else if (rc == 0)
throw SSLConnectionUnexpectedlyClosedException();
else
return rc;
}
do
{
rc = SSL_write(_pSSL, buffer, length);
}
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
if (rc <= 0)
{
rc = handleError(rc);
if (rc == 0) throw SSLConnectionUnexpectedlyClosedException();
}
return rc;
}
int SecureSocketImpl::receiveBytes(void* buffer, int length, int flags)
{
poco_assert (_pSocket->initialized());
poco_check_ptr (_pSSL);
int rc;
if (_needHandshake)
{
rc = completeHandshake();
if (rc == 1)
verifyPeerCertificate();
else
return rc;
}
do
{
rc = SSL_read(_pSSL, buffer, length);
}
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
if (rc <= 0)
{
return handleError(rc);
}
return rc;
}
int SecureSocketImpl::available() const
{
poco_check_ptr (_pSSL);
return SSL_pending(_pSSL);
}
int SecureSocketImpl::completeHandshake()
{
poco_assert (_pSocket->initialized());
poco_check_ptr (_pSSL);
int rc;
do
{
rc = SSL_do_handshake(_pSSL);
}
while (rc <= 0 && _pSocket->lastError() == POCO_EINTR);
if (rc <= 0)
{
return handleError(rc);
}
_needHandshake = false;
return rc;
}
void SecureSocketImpl::verifyPeerCertificate()
{
if (_peerHostName.empty())
_peerHostName = _pSocket->peerAddress().host().toString();
verifyPeerCertificate(_peerHostName);
}
void SecureSocketImpl::verifyPeerCertificate(const std::string& hostName)
{
long certErr = verifyPeerCertificateImpl(hostName);
if (certErr != X509_V_OK)
{
std::string msg = Utility::convertCertificateError(certErr);
throw CertificateValidationException("Unacceptable certificate from " + hostName, msg);
}
}
long SecureSocketImpl::verifyPeerCertificateImpl(const std::string& hostName)
{
Context::VerificationMode mode = _pContext->verificationMode();
if (mode == Context::VERIFY_NONE || !_pContext->extendedCertificateVerificationEnabled() ||
(isLocalHost(hostName) && mode != Context::VERIFY_STRICT))
{
return X509_V_OK;
}
X509* pCert = SSL_get_peer_certificate(_pSSL);
if (pCert)
{
X509Certificate cert(pCert);
return cert.verify(hostName) ? X509_V_OK : X509_V_ERR_APPLICATION_VERIFICATION;
}
else return X509_V_OK;
}
bool SecureSocketImpl::isLocalHost(const std::string& hostName)
{
SocketAddress addr(hostName, 0);
return addr.host().isLoopback();
}
X509* SecureSocketImpl::peerCertificate() const
{
if (_pSSL)
return SSL_get_peer_certificate(_pSSL);
else
return 0;
}
int SecureSocketImpl::handleError(int rc)
{
if (rc > 0) return rc;
int sslError = SSL_get_error(_pSSL, rc);
switch (sslError)
{
case SSL_ERROR_ZERO_RETURN:
return 0;
case SSL_ERROR_WANT_READ:
return SecureStreamSocket::ERR_SSL_WANT_READ;
case SSL_ERROR_WANT_WRITE:
return SecureStreamSocket::ERR_SSL_WANT_WRITE;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
case SSL_ERROR_WANT_X509_LOOKUP:
// these should not occur
poco_bugcheck();
return rc;
default:
{
long lastError = ERR_get_error();
if (lastError == 0)
{
if (rc == 0)
{
throw SSLConnectionUnexpectedlyClosedException();
}
else
{
SecureStreamSocketImpl::error(Poco::format("The BIO reported an error: %d", rc));
}
}
else
{
char buffer[256];
ERR_error_string_n(lastError, buffer, sizeof(buffer));
std::string msg(buffer);
throw SSLException(msg);
}
}
break;
}
return rc;
}
void SecureSocketImpl::setPeerHostName(const std::string& peerHostName)
{
_peerHostName = peerHostName;
}
void SecureSocketImpl::reset()
{
close();
if (_pSSL)
{
SSL_free(_pSSL);
_pSSL = 0;
}
}
void SecureSocketImpl::abort()
{
_pSocket->shutdown();
}
Session::Ptr SecureSocketImpl::currentSession()
{
if (_pSSL)
{
SSL_SESSION* pSession = SSL_get1_session(_pSSL);
if (pSession)
{
if (_pSession && pSession == _pSession->sslSession())
{
SSL_SESSION_free(pSession);
return _pSession;
}
else return new Session(pSession);
}
}
return 0;
}
void SecureSocketImpl::useSession(Session::Ptr pSession)
{
_pSession = pSession;
}
bool SecureSocketImpl::sessionWasReused()
{
if (_pSSL)
return SSL_session_reused(_pSSL) != 0;
else
return false;
}
} } // namespace Poco::Net

View File

@@ -1,186 +1,291 @@
//
// SecureStreamSocket.cpp
//
//
// SecureStreamSocket.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SecureStreamSocket.cpp#11 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureStreamSocket
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SocketImpl.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
SecureStreamSocket::SecureStreamSocket():
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
}
SecureStreamSocket::SecureStreamSocket(Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address):
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName):
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const Socket& socket):
StreamSocket(socket)
{
if (!dynamic_cast<SecureStreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
SecureStreamSocket::SecureStreamSocket(SocketImpl* pImpl):
StreamSocket(pImpl)
{
if (!dynamic_cast<SecureStreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
SecureStreamSocket::~SecureStreamSocket()
{
}
SecureStreamSocket& SecureStreamSocket::operator = (const Socket& socket)
{
if (dynamic_cast<SecureStreamSocketImpl*>(socket.impl()))
StreamSocket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
X509Certificate SecureStreamSocket::peerCertificate() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->peerCertificate();
}
void SecureStreamSocket::setPeerHostName(const std::string& hostName)
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
}
const std::string& SecureStreamSocket::getPeerHostName() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->getPeerHostName();
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), SSLManager::instance().defaultClientContext());
SecureStreamSocket result(pImpl);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, Context::Ptr pContext)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), SSLManager::instance().defaultClientContext());
SecureStreamSocket result(pImpl);
result.setPeerHostName(peerHostName);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
result.setPeerHostName(peerHostName);
pImpl->connectSSL();
return result;
}
Context::Ptr SecureStreamSocket::context() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->context();
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureStreamSocket
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SocketImpl.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
SecureStreamSocket::SecureStreamSocket():
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
}
SecureStreamSocket::SecureStreamSocket(Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
}
SecureStreamSocket::SecureStreamSocket(Context::Ptr pContext, Session::Ptr pSession):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
useSession(pSession);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address):
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName):
StreamSocket(new SecureStreamSocketImpl(SSLManager::instance().defaultClientContext()))
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext, Session::Ptr pSession):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
useSession(pSession);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext, Session::Ptr pSession):
StreamSocket(new SecureStreamSocketImpl(pContext))
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
useSession(pSession);
connect(address);
}
SecureStreamSocket::SecureStreamSocket(const Socket& socket):
StreamSocket(socket)
{
if (!dynamic_cast<SecureStreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
SecureStreamSocket::SecureStreamSocket(SocketImpl* pImpl):
StreamSocket(pImpl)
{
if (!dynamic_cast<SecureStreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
SecureStreamSocket::~SecureStreamSocket()
{
}
SecureStreamSocket& SecureStreamSocket::operator = (const Socket& socket)
{
if (dynamic_cast<SecureStreamSocketImpl*>(socket.impl()))
StreamSocket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
bool SecureStreamSocket::havePeerCertificate() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->havePeerCertificate();
}
X509Certificate SecureStreamSocket::peerCertificate() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->peerCertificate();
}
void SecureStreamSocket::setPeerHostName(const std::string& hostName)
{
static_cast<SecureStreamSocketImpl*>(impl())->setPeerHostName(hostName);
}
const std::string& SecureStreamSocket::getPeerHostName() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->getPeerHostName();
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), SSLManager::instance().defaultClientContext());
SecureStreamSocket result(pImpl);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, Context::Ptr pContext)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, Context::Ptr pContext, Session::Ptr pSession)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
result.useSession(pSession);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), SSLManager::instance().defaultClientContext());
SecureStreamSocket result(pImpl);
result.setPeerHostName(peerHostName);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
result.setPeerHostName(peerHostName);
pImpl->connectSSL();
return result;
}
SecureStreamSocket SecureStreamSocket::attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext, Session::Ptr pSession)
{
SecureStreamSocketImpl* pImpl = new SecureStreamSocketImpl(static_cast<StreamSocketImpl*>(streamSocket.impl()), pContext);
SecureStreamSocket result(pImpl);
result.setPeerHostName(peerHostName);
result.useSession(pSession);
pImpl->connectSSL();
return result;
}
Context::Ptr SecureStreamSocket::context() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->context();
}
void SecureStreamSocket::setLazyHandshake(bool flag)
{
static_cast<SecureStreamSocketImpl*>(impl())->setLazyHandshake(flag);
}
bool SecureStreamSocket::getLazyHandshake() const
{
return static_cast<SecureStreamSocketImpl*>(impl())->getLazyHandshake();
}
void SecureStreamSocket::verifyPeerCertificate()
{
static_cast<SecureStreamSocketImpl*>(impl())->verifyPeerCertificate();
}
void SecureStreamSocket::verifyPeerCertificate(const std::string& hostName)
{
static_cast<SecureStreamSocketImpl*>(impl())->verifyPeerCertificate(hostName);
}
int SecureStreamSocket::completeHandshake()
{
return static_cast<SecureStreamSocketImpl*>(impl())->completeHandshake();
}
Session::Ptr SecureStreamSocket::currentSession()
{
return static_cast<SecureStreamSocketImpl*>(impl())->currentSession();
}
void SecureStreamSocket::useSession(Session::Ptr pSession)
{
static_cast<SecureStreamSocketImpl*>(impl())->useSession(pSession);
}
bool SecureStreamSocket::sessionWasReused()
{
return static_cast<SecureStreamSocketImpl*>(impl())->sessionWasReused();
}
void SecureStreamSocket::abort()
{
static_cast<SecureStreamSocketImpl*>(impl())->abort();
}
} } // namespace Poco::Net

View File

@@ -1,197 +1,258 @@
//
// SecureStreamSocketImpl.cpp
//
//
// SecureStreamSocketImpl.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/SecureStreamSocketImpl.cpp#9 $
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureStreamSocketImpl
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SSLException.h"
namespace Poco {
namespace Net {
SecureStreamSocketImpl::SecureStreamSocketImpl(Context::Ptr pContext):
_impl(new StreamSocketImpl, pContext)
{
}
SecureStreamSocketImpl::SecureStreamSocketImpl(StreamSocketImpl* pStreamSocket, Context::Ptr pContext):
_impl(pStreamSocket, pContext)
{
pStreamSocket->duplicate();
reset(_impl.sockfd());
}
SecureStreamSocketImpl::~SecureStreamSocketImpl()
{
reset();
}
SocketImpl* SecureStreamSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
throw Poco::InvalidAccessException("Cannot acceptConnection() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::acceptSSL()
{
_impl.acceptSSL();
}
void SecureStreamSocketImpl::connect(const SocketAddress& address)
{
if (_peerHostName.empty()) _peerHostName = address.host().toString();
_impl.connect(address, _peerHostName);
reset(_impl.sockfd());
}
void SecureStreamSocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout)
{
if (_peerHostName.empty()) _peerHostName = address.host().toString();
_impl.connect(address, _peerHostName, timeout);
reset(_impl.sockfd());
}
void SecureStreamSocketImpl::connectNB(const SocketAddress& address)
{
if (_peerHostName.empty()) _peerHostName = address.host().toString();
_impl.connectNB(address, _peerHostName);
reset(_impl.sockfd());
}
void SecureStreamSocketImpl::connectSSL()
{
if (_peerHostName.empty()) _peerHostName = peerAddress().host().toString();
_impl.connectSSL(_peerHostName);
}
void SecureStreamSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
throw Poco::InvalidAccessException("Cannot bind() a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::listen(int backlog)
{
throw Poco::InvalidAccessException("Cannot listen() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::close()
{
reset();
_impl.close();
}
int SecureStreamSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
const char* p = reinterpret_cast<const char*>(buffer);
int remaining = length;
while (remaining > 0)
{
int n = _impl.sendBytes(p, length, flags);
p += n;
remaining -= n;
}
return length;
}
int SecureStreamSocketImpl::receiveBytes(void* buffer, int length, int flags)
{
return _impl.receiveBytes(buffer, length, flags);
}
int SecureStreamSocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot sendTo() on a SecureStreamSocketImpl");
}
int SecureStreamSocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveFrom() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::sendUrgent(unsigned char data)
{
throw Poco::InvalidAccessException("Cannot sendUrgent() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::shutdownReceive()
{
}
void SecureStreamSocketImpl::shutdownSend()
{
}
void SecureStreamSocketImpl::shutdown()
{
_impl.shutdown();
}
void SecureStreamSocketImpl::setPeerHostName(const std::string& peerHostName)
{
_peerHostName = peerHostName;
}
X509Certificate SecureStreamSocketImpl::peerCertificate() const
{
X509* pCert = _impl.peerCertificate();
if (pCert)
return X509Certificate(pCert);
else
throw SSLException("No certificate available yet");
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLSockets
// Module: SecureStreamSocketImpl
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Thread.h"
namespace Poco {
namespace Net {
SecureStreamSocketImpl::SecureStreamSocketImpl(Context::Ptr pContext):
_impl(new StreamSocketImpl, pContext),
_lazyHandshake(false)
{
}
SecureStreamSocketImpl::SecureStreamSocketImpl(StreamSocketImpl* pStreamSocket, Context::Ptr pContext):
_impl(pStreamSocket, pContext),
_lazyHandshake(false)
{
pStreamSocket->duplicate();
reset(_impl.sockfd());
}
SecureStreamSocketImpl::~SecureStreamSocketImpl()
{
}
SocketImpl* SecureStreamSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
throw Poco::InvalidAccessException("Cannot acceptConnection() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::acceptSSL()
{
_impl.acceptSSL();
}
void SecureStreamSocketImpl::connect(const SocketAddress& address)
{
_impl.connect(address, !_lazyHandshake);
reset(_impl.sockfd());
}
void SecureStreamSocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout)
{
_impl.connect(address, timeout, !_lazyHandshake);
reset(_impl.sockfd());
}
void SecureStreamSocketImpl::connectNB(const SocketAddress& address)
{
_impl.connectNB(address);
reset(_impl.sockfd());
}
void SecureStreamSocketImpl::connectSSL()
{
_impl.connectSSL(!_lazyHandshake);
}
void SecureStreamSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
throw Poco::InvalidAccessException("Cannot bind() a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::listen(int backlog)
{
throw Poco::InvalidAccessException("Cannot listen() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::close()
{
reset();
_impl.close();
}
void SecureStreamSocketImpl::abort()
{
reset();
_impl.abort();
}
int SecureStreamSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
const char* p = reinterpret_cast<const char*>(buffer);
int remaining = length;
int sent = 0;
bool blocking = getBlocking();
while (remaining > 0)
{
int n = _impl.sendBytes(p, remaining, flags);
if (n < 0 && !blocking) return n;
p += n;
sent += n;
remaining -= n;
if (blocking && remaining > 0)
Poco::Thread::yield();
else
break;
}
return sent;
}
int SecureStreamSocketImpl::receiveBytes(void* buffer, int length, int flags)
{
return _impl.receiveBytes(buffer, length, flags);
}
int SecureStreamSocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot sendTo() on a SecureStreamSocketImpl");
}
int SecureStreamSocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveFrom() on a SecureStreamSocketImpl");
}
void SecureStreamSocketImpl::sendUrgent(unsigned char data)
{
throw Poco::InvalidAccessException("Cannot sendUrgent() on a SecureStreamSocketImpl");
}
int SecureStreamSocketImpl::available()
{
return _impl.available();
}
void SecureStreamSocketImpl::shutdownReceive()
{
}
void SecureStreamSocketImpl::shutdownSend()
{
}
void SecureStreamSocketImpl::shutdown()
{
_impl.shutdown();
}
bool SecureStreamSocketImpl::secure() const
{
return true;
}
bool SecureStreamSocketImpl::havePeerCertificate() const
{
X509* pCert = _impl.peerCertificate();
if (pCert)
{
X509_free(pCert);
return true;
}
else return false;
}
X509Certificate SecureStreamSocketImpl::peerCertificate() const
{
X509* pCert = _impl.peerCertificate();
if (pCert)
return X509Certificate(pCert);
else
throw SSLException("No certificate available");
}
void SecureStreamSocketImpl::setLazyHandshake(bool flag)
{
_lazyHandshake = flag;
}
bool SecureStreamSocketImpl::getLazyHandshake() const
{
return _lazyHandshake;
}
void SecureStreamSocketImpl::verifyPeerCertificate()
{
_impl.verifyPeerCertificate();
}
void SecureStreamSocketImpl::verifyPeerCertificate(const std::string& hostName)
{
_impl.verifyPeerCertificate(hostName);
}
int SecureStreamSocketImpl::completeHandshake()
{
return _impl.completeHandshake();
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,62 @@
//
// Session.cpp
//
// $Id: //poco/1.4/NetSSL_OpenSSL/src/Session.cpp#2 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: Session
//
// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#if defined(__APPLE__)
// Some OpenSSL functions are deprecated in OS X 10.7
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "Poco/Net/Session.h"
namespace Poco {
namespace Net {
Session::Session(SSL_SESSION* pSession):
_pSession(pSession)
{
}
Session::~Session()
{
SSL_SESSION_free(_pSession);
}
} } // namespace Poco::Net

View File

@@ -1,187 +1,195 @@
//
// X509Certificate.cpp
//
//
// X509Certificate.cpp
//
// $Id: //poco/Main/NetSSL_OpenSSL/src/X509Certificate.cpp#14 $
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: X509Certificate
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/X509Certificate.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/DNS.h"
#include "Poco/TemporaryFile.h"
#include "Poco/FileStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h"
#include "Poco/RegularExpression.h"
#include "Poco/DateTimeParser.h"
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
namespace Poco {
namespace Net {
X509Certificate::X509Certificate(std::istream& istr):
Poco::Crypto::X509Certificate(istr)
{
}
X509Certificate::X509Certificate(const std::string& path):
Poco::Crypto::X509Certificate(path)
{
}
X509Certificate::X509Certificate(X509* pCert):
Poco::Crypto::X509Certificate(pCert)
{
}
X509Certificate::X509Certificate(const Poco::Crypto::X509Certificate& cert):
Poco::Crypto::X509Certificate(cert)
{
}
X509Certificate& X509Certificate::operator = (const Poco::Crypto::X509Certificate& cert)
{
X509Certificate tmp(cert);
swap(tmp);
return *this;
}
X509Certificate::~X509Certificate()
{
}
long X509Certificate::verify(const std::string& hostName) const
{
return verify(*this, hostName);
}
long X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, const std::string& hostName)
{
std::string commonName;
std::set<std::string> dnsNames;
certificate.extractNames(commonName, dnsNames);
bool ok = (dnsNames.find(hostName) != dnsNames.end());
char buffer[NAME_BUFFER_SIZE];
X509_NAME* subj = 0;
if (!ok && (subj = X509_get_subject_name(const_cast<X509*>(certificate.certificate()))) && X509_NAME_get_text_by_NID(subj, NID_commonName, buffer, sizeof(buffer)) > 0)
{
buffer[NAME_BUFFER_SIZE - 1] = 0;
std::string commonName(buffer); // commonName can contain wildcards like *.appinf.com
try
{
// two cases: strData contains wildcards or not
if (containsWildcards(commonName))
{
// a compare by IPAddress is not possible with wildcards
// only allow compare by name
const HostEntry& heData = DNS::resolve(hostName);
ok = matchByAlias(commonName, heData);
}
else
{
// it depends on hostName if we compare by IP or by alias
IPAddress ip;
if (IPAddress::tryParse(hostName, ip))
{
// compare by IP
const HostEntry& heData = DNS::resolve(commonName);
const HostEntry::AddressList& addr = heData.addresses();
HostEntry::AddressList::const_iterator it = addr.begin();
HostEntry::AddressList::const_iterator itEnd = addr.end();
for (; it != itEnd && !ok; ++it)
{
ok = (*it == ip);
}
}
else
{
// compare by name
const HostEntry& heData = DNS::resolve(hostName);
ok = matchByAlias(commonName, heData);
}
}
}
catch (HostNotFoundException&)
{
return X509_V_ERR_APPLICATION_VERIFICATION;
}
}
// we already have a verify callback registered so no need to ask twice SSL_get_verify_result(pSSL);
if (ok)
return X509_V_OK;
else
return X509_V_ERR_APPLICATION_VERIFICATION;
}
bool X509Certificate::containsWildcards(const std::string& commonName)
{
return (commonName.find('*') != std::string::npos || commonName.find('?') != std::string::npos);
}
bool X509Certificate::matchByAlias(const std::string& alias, const HostEntry& heData)
{
// fix wildcards
std::string aliasRep = Poco::replace(alias, "*", ".*");
Poco::replaceInPlace(aliasRep, "..*", ".*");
Poco::replaceInPlace(aliasRep, "?", ".?");
Poco::replaceInPlace(aliasRep, "..?", ".?");
// compare by name
Poco::RegularExpression expr(aliasRep);
bool found = false;
const HostEntry::AliasList& aliases = heData.aliases();
HostEntry::AliasList::const_iterator it = aliases.begin();
HostEntry::AliasList::const_iterator itEnd = aliases.end();
for (; it != itEnd && !found; ++it)
{
found = expr.match(*it);
}
return found;
}
} } // namespace Poco::Net
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: X509Certificate
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/X509Certificate.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/DNS.h"
#include "Poco/TemporaryFile.h"
#include "Poco/FileStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h"
#include "Poco/RegularExpression.h"
#include "Poco/DateTimeParser.h"
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
namespace Poco {
namespace Net {
X509Certificate::X509Certificate(std::istream& istr):
Poco::Crypto::X509Certificate(istr)
{
}
X509Certificate::X509Certificate(const std::string& path):
Poco::Crypto::X509Certificate(path)
{
}
X509Certificate::X509Certificate(X509* pCert):
Poco::Crypto::X509Certificate(pCert)
{
}
X509Certificate::X509Certificate(X509* pCert, bool shared):
Poco::Crypto::X509Certificate(pCert, shared)
{
}
X509Certificate::X509Certificate(const Poco::Crypto::X509Certificate& cert):
Poco::Crypto::X509Certificate(cert)
{
}
X509Certificate& X509Certificate::operator = (const Poco::Crypto::X509Certificate& cert)
{
X509Certificate tmp(cert);
swap(tmp);
return *this;
}
X509Certificate::~X509Certificate()
{
}
bool X509Certificate::verify(const std::string& hostName) const
{
return verify(*this, hostName);
}
bool X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, const std::string& hostName)
{
std::string commonName;
std::set<std::string> dnsNames;
certificate.extractNames(commonName, dnsNames);
bool ok = (dnsNames.find(hostName) != dnsNames.end());
char buffer[NAME_BUFFER_SIZE];
X509_NAME* subj = 0;
if (!ok && (subj = X509_get_subject_name(const_cast<X509*>(certificate.certificate()))) && X509_NAME_get_text_by_NID(subj, NID_commonName, buffer, sizeof(buffer)) > 0)
{
buffer[NAME_BUFFER_SIZE - 1] = 0;
std::string commonName(buffer); // commonName can contain wildcards like *.appinf.com
try
{
// two cases: strData contains wildcards or not
if (containsWildcards(commonName))
{
// a compare by IPAddress is not possible with wildcards
// only allow compare by name
const HostEntry& heData = DNS::resolve(hostName);
ok = matchByAlias(commonName, heData);
}
else
{
// it depends on hostName if we compare by IP or by alias
IPAddress ip;
if (IPAddress::tryParse(hostName, ip))
{
// compare by IP
const HostEntry& heData = DNS::resolve(commonName);
const HostEntry::AddressList& addr = heData.addresses();
HostEntry::AddressList::const_iterator it = addr.begin();
HostEntry::AddressList::const_iterator itEnd = addr.end();
for (; it != itEnd && !ok; ++it)
{
ok = (*it == ip);
}
}
else
{
// compare by name
const HostEntry& heData = DNS::resolve(hostName);
ok = matchByAlias(commonName, heData);
}
}
}
catch (HostNotFoundException&)
{
return false;
}
}
return ok;
}
bool X509Certificate::containsWildcards(const std::string& commonName)
{
return (commonName.find('*') != std::string::npos || commonName.find('?') != std::string::npos);
}
bool X509Certificate::matchByAlias(const std::string& alias, const HostEntry& heData)
{
// fix wildcards
std::string aliasRep = Poco::replace(alias, ".", "\\.");
Poco::replaceInPlace(aliasRep, "*", ".*");
Poco::replaceInPlace(aliasRep, "..*", ".*");
Poco::replaceInPlace(aliasRep, "?", ".?");
Poco::replaceInPlace(aliasRep, "..?", ".?");
// compare by name
Poco::RegularExpression expr(aliasRep);
bool found = false;
const HostEntry::AliasList& aliases = heData.aliases();
HostEntry::AliasList::const_iterator it = aliases.begin();
HostEntry::AliasList::const_iterator itEnd = aliases.end();
for (; it != itEnd && !found; ++it)
{
found = expr.match(*it);
}
// Handle the case where the list of aliases is empty.
if (aliases.empty())
{
// Compare the host name against the wildcard host name in the certificate.
found = expr.match(heData.name());
}
return found;
}
} } // namespace Poco::Net