added NetSSL_Win library, a port of NetSSL_OpenSSL to Windows Schannel. See doc/README.txt for more info.

This commit is contained in:
Günter Obiltschnig
2014-09-05 00:17:09 +02:00
parent 8ae1a7e8ab
commit b7f050db70
217 changed files with 39946 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
//
// AcceptCertificateHandler.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/AcceptCertificateHandler.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: AcceptCertificateHandler
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/AcceptCertificateHandler.h"
namespace Poco {
namespace Net {
AcceptCertificateHandler::AcceptCertificateHandler(bool server): InvalidCertificateHandler(server)
{
}
AcceptCertificateHandler::~AcceptCertificateHandler()
{
}
void AcceptCertificateHandler::onInvalidCertificate(const void*, VerificationErrorArgs& errorCert)
{
errorCert.setIgnoreError(true);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,46 @@
//
// CertificateHandlerFactory.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/CertificateHandlerFactory.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: CertificateHandlerFactory
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/CertificateHandlerFactory.h"
#include "Poco/Net/SSLManager.h"
namespace Poco {
namespace Net {
CertificateHandlerFactory::CertificateHandlerFactory()
{
}
CertificateHandlerFactory::~CertificateHandlerFactory()
{
}
CertificateHandlerFactoryRegistrar::CertificateHandlerFactoryRegistrar(const std::string& name, CertificateHandlerFactory* pFactory)
{
SSLManager::instance().certificateHandlerFactoryMgr().setFactory(name, pFactory);
}
CertificateHandlerFactoryRegistrar::~CertificateHandlerFactoryRegistrar()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,71 @@
//
// CertificateHandlerFactoryMgr.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/CertificateHandlerFactoryMgr.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: CertificateHandlerFactoryMgr
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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

@@ -0,0 +1,55 @@
//
// ConsoleCertificateHandler.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/ConsoleCertificateHandler.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: ConsoleCertificateHandler
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/ConsoleCertificateHandler.h"
#include <iostream>
namespace Poco {
namespace Net {
ConsoleCertificateHandler::ConsoleCertificateHandler(bool server): InvalidCertificateHandler(server)
{
}
ConsoleCertificateHandler::~ConsoleCertificateHandler()
{
}
void ConsoleCertificateHandler::onInvalidCertificate(const void*, VerificationErrorArgs& errorCert)
{
const X509Certificate& aCert = errorCert.certificate();
std::cout << "\n";
std::cout << "WARNING: Certificate verification failed\n";
std::cout << "----------------------------------------\n";
std::cout << "Issuer Name: " << aCert.issuerName() << "\n";
std::cout << "Subject Name: " << aCert.subjectName() << "\n\n";
std::cout << "The certificate yielded the error: " << errorCert.errorMessage() << "\n\n";
std::cout << "The error occurred in the certificate chain at position " << errorCert.errorDepth() << "\n";
std::cout << "Accept the certificate (y,n)? ";
char c;
std::cin >> c;
if (c == 'y' || c == 'Y')
errorCert.setIgnoreError(true);
else
errorCert.setIgnoreError(false);
}
} } // namespace Poco::Net

104
NetSSL_Win/src/Context.cpp Normal file
View File

@@ -0,0 +1,104 @@
//
// Context.cpp
//
// $Id: //poco/1.4/NetSSL_Schannel/src/Context.cpp#1 $
//
// Library: NetSSL_Schannel
// Package: SSLCore
// Module: Context
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/Context.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/SSLException.h"
#include "Poco/UnicodeConverter.h"
namespace Poco {
namespace Net {
const std::string Context::CERT_STORE_MY("MY");
const std::string Context::CERT_STORE_ROOT("ROOT");
const std::string Context::CERT_STORE_TRUST("TRUST");
const std::string Context::CERT_STORE_CA("CA");
const std::string Context::CERT_STORE_USERDS("USERDS");
Context::Context(Usage usage,
const std::string& certName,
VerificationMode verMode,
int options,
const std::string& certStore):
_usage(usage),
_mode(verMode),
_options(options),
_certificateName(certName),
_certificateStoreName(certStore),
_hMemCertStore(0),
_hCollectionCertStore(0),
_hRootCertStore(0),
_mutex()
{
_hMemCertStore = CertOpenStore(
CERT_STORE_PROV_MEMORY, // The memory provider type
0, // The encoding type is not needed
NULL, // Use the default provider
0, // Accept the default dwFlags
NULL); // pvPara is not used
if (!_hMemCertStore)
throw SSLException("Failed to create memory certificate store", GetLastError());
_hCollectionCertStore = CertOpenStore(
CERT_STORE_PROV_COLLECTION, // A collection store
0, // Encoding type; not used with a collection store
NULL, // Use the default provider
0, // No flags
NULL); // Not needed
if (!_hCollectionCertStore)
throw SSLException("Failed to create collection store", GetLastError());
if (!CertAddStoreToCollection(_hCollectionCertStore, _hMemCertStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 1))
throw SSLException("Failed to add memory certificate store to collection store", GetLastError());
if (_options & OPT_TRUST_ROOTS_WIN_CERT_STORE)
{
// add root certificates
std::wstring rootStore;
Poco::UnicodeConverter::convert(CERT_STORE_ROOT, rootStore);
_hRootCertStore = CertOpenSystemStoreW(0, rootStore.c_str());
if (!_hRootCertStore)
throw SSLException("Failed to open root certificate store", GetLastError());
if (!CertAddStoreToCollection(_hCollectionCertStore, _hRootCertStore, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 1))
throw SSLException("Failed to add root certificate store to collection store", GetLastError());
}
}
Context::~Context()
{
CertCloseStore(_hCollectionCertStore, 0);
CertCloseStore(_hMemCertStore, 0);
if (_hRootCertStore)
{
CertCloseStore(_hRootCertStore, 0);
}
}
void Context::addTrustedCert(const Poco::Net::X509Certificate& cert)
{
Poco::FastMutex::ScopedLock lock(_mutex);
CertAddCertificateContextToStore(_hMemCertStore, cert.system(), CERT_STORE_ADD_REPLACE_EXISTING, 0);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,192 @@
//
// HTTPSClientSession.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/HTTPSClientSession.cpp#3 $
//
// Library: NetSSL_Win
// Package: HTTPSClient
// Module: HTTPSClientSession
//
// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/SSLException.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
{
StreamSocket proxySocket(proxyConnect());
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext, _pSession);
attachSocket(secureSocket);
if (_pContext->sessionCacheEnabled())
{
_pSession = secureSocket.currentSession();
}
}
}
int HTTPSClientSession::read(char* buffer, std::streamsize length)
{
try
{
return HTTPSession::read(buffer, length);
} catch(SSLConnectionUnexpectedlyClosedException&)
{
return 0;
}
}
Session::Ptr HTTPSClientSession::sslSession()
{
return _pSession;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,70 @@
//
// HTTPSSessionInstantiator.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/HTTPSSessionInstantiator.cpp#2 $
//
// Library: NetSSL_Win
// Package: HTTPSClient
// Module: HTTPSSessionInstantiator
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/HTTPSSessionInstantiator.h"
#include "Poco/Net/HTTPSessionFactory.h"
#include "Poco/Net/HTTPSClientSession.h"
namespace Poco {
namespace Net {
HTTPSSessionInstantiator::HTTPSSessionInstantiator()
{
}
HTTPSSessionInstantiator::HTTPSSessionInstantiator(Context::Ptr pContext) :
_pContext(pContext)
{
}
HTTPSSessionInstantiator::~HTTPSSessionInstantiator()
{
}
HTTPClientSession* HTTPSSessionInstantiator::createClientSession(const Poco::URI& uri)
{
poco_assert (uri.getScheme() == "https");
HTTPSClientSession* pSession = _pContext.isNull() ? new HTTPSClientSession(uri.getHost(), uri.getPort()) : new HTTPSClientSession(uri.getHost(), uri.getPort(), _pContext);
pSession->setProxy(proxyHost(), proxyPort());
pSession->setProxyCredentials(proxyUsername(), proxyPassword());
return pSession;
}
void HTTPSSessionInstantiator::registerInstantiator()
{
HTTPSessionFactory::defaultFactory().registerProtocol("https", new HTTPSSessionInstantiator);
}
void HTTPSSessionInstantiator::registerInstantiator(Context::Ptr context)
{
HTTPSessionFactory::defaultFactory().registerProtocol("https", new HTTPSSessionInstantiator(context));
}
void HTTPSSessionInstantiator::unregisterInstantiator()
{
HTTPSessionFactory::defaultFactory().unregisterProtocol("https");
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,174 @@
//
// HTTPSStreamFactory.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/HTTPSStreamFactory.cpp#2 $
//
// Library: NetSSL_Win
// Package: HTTPSClient
// Module: HTTPSStreamFactory
//
// Copyright (c) 2006-2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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/HTTPCredentials.h"
#include "Poco/Net/NetException.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.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;
HTTPResponse res;
try
{
bool retry = false;
bool authorize = false;
int redirects = 0;
std::string username;
std::string password;
do
{
if (!pSession)
{
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);
if (authorize)
{
HTTPCredentials::extractCredentials(uri, username, password);
HTTPCredentials cred(username, password);
cred.authenticate(req, res);
}
pSession->sendRequest(req);
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"));
if (!username.empty())
{
resolvedURI.setUserInfo(username + ":" + password);
authorize = false;
}
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 if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize)
{
authorize = true;
retry = true;
Poco::NullOutputStream null;
Poco::StreamCopier::copyStream(rs, null);
}
else 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()
{
URIStreamOpener::defaultOpener().registerStreamFactory("https", new HTTPSStreamFactory);
}
void HTTPSStreamFactory::unregisterFactory()
{
URIStreamOpener::defaultOpener().unregisterStreamFactory("https");
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,47 @@
//
// InvalidCertificateHandler.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/InvalidCertificateHandler.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: InvalidCertificateHandler
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/InvalidCertificateHandler.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Delegate.h"
using Poco::Delegate;
namespace Poco {
namespace Net {
InvalidCertificateHandler::InvalidCertificateHandler(bool handleErrorsOnServerSide): _handleErrorsOnServerSide(handleErrorsOnServerSide)
{
if (_handleErrorsOnServerSide)
SSLManager::instance().ServerVerificationError += Delegate<InvalidCertificateHandler, VerificationErrorArgs>(this, &InvalidCertificateHandler::onInvalidCertificate);
else
SSLManager::instance().ClientVerificationError += Delegate<InvalidCertificateHandler, VerificationErrorArgs>(this, &InvalidCertificateHandler::onInvalidCertificate);
}
InvalidCertificateHandler::~InvalidCertificateHandler()
{
if (_handleErrorsOnServerSide)
SSLManager::instance().ServerVerificationError -= Delegate<InvalidCertificateHandler, VerificationErrorArgs>(this, &InvalidCertificateHandler::onInvalidCertificate);
else
SSLManager::instance().ClientVerificationError -= Delegate<InvalidCertificateHandler, VerificationErrorArgs>(this, &InvalidCertificateHandler::onInvalidCertificate);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,40 @@
//
// RejectCertificateHandler.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/RejectCertificateHandler.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: RejectCertificateHandler
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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

@@ -0,0 +1,32 @@
//
// SSLException.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/SSLException.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: SSLException
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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

@@ -0,0 +1,256 @@
//
// SSLManager.cpp
//
// $Id: //poco/1.4/NetSSL_Schannel/src/SSLManager.cpp#1 $
//
// Library: NetSSL_Schannel
// Package: SSLCore
// Module: SSLManager
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/Utility.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_CERT_NAME("certificateName");
const std::string SSLManager::VAL_CERT_NAME("");
const std::string SSLManager::CFG_CERT_STORE("certificateStore");
const std::string SSLManager::VAL_CERT_STORE("MY");
const std::string SSLManager::CFG_VER_MODE("verificationMode");
const Context::VerificationMode SSLManager::VAL_VER_MODE(Context::VERIFY_RELAXED);
const std::string SSLManager::CFG_REVOCATION_CHECK("revocationChecking");
const bool SSLManager::VAL_REVOCATION_CHECK(true);
const std::string SSLManager::CFG_TRUST_ROOTS("trustRoots");
const bool SSLManager::VAL_TRUST_ROOTS(true);
const std::string SSLManager::CFG_USE_MACHINE_STORE("useMachineStore");
const bool SSLManager::VAL_USE_MACHINE_STORE(false);
const std::string SSLManager::CFG_USE_STRONG_CRYPTO("useStrongCrypto");
const bool SSLManager::VAL_USE_STRONG_CRYPTO(true);
const std::string SSLManager::CFG_CERTIFICATE_HANDLER("invalidCertificateHandler.name");
const std::string SSLManager::VAL_CERTIFICATE_HANDLER("ConsoleCertificateHandler");
const std::string SSLManager::CFG_SERVER_PREFIX("schannel.server.");
const std::string SSLManager::CFG_CLIENT_PREFIX("schannel.client.");
const std::string SSLManager::CFG_REQUIRE_TLSV1("requireTLSv1");
const std::string SSLManager::CFG_REQUIRE_TLSV1_1("requireTLSv1_1");
const std::string SSLManager::CFG_REQUIRE_TLSV1_2("requireTLSv1_2");
SSLManager::SSLManager()
{
}
SSLManager::~SSLManager()
{
ClientVerificationError.clear();
ServerVerificationError.clear();
_ptrServerCertificateHandler = 0;
_ptrDefaultServerContext = 0;
_ptrClientCertificateHandler = 0;
_ptrDefaultClientContext = 0;
}
namespace
{
static Poco::SingletonHolder<SSLManager> singleton;
}
SSLManager& SSLManager::instance()
{
return *singleton.get();
}
void SSLManager::initializeServer(InvalidCertificateHandlerPtr& ptrHandler, Context::Ptr ptrContext)
{
_ptrServerCertificateHandler = ptrHandler;
_ptrDefaultServerContext = ptrContext;
}
void SSLManager::initializeClient(InvalidCertificateHandlerPtr& ptrHandler, Context::Ptr ptrContext)
{
_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::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;
}
void SSLManager::initDefaultContext(bool server)
{
if (server && _ptrDefaultServerContext) return;
if (!server && _ptrDefaultClientContext) return;
initEvents(server);
const std::string prefix = server ? CFG_SERVER_PREFIX : CFG_CLIENT_PREFIX;
Poco::Util::LayeredConfiguration& config = Poco::Util::Application::instance().config();
std::string certName = config.getString(prefix + CFG_CERT_NAME, VAL_CERT_NAME);
std::string certStore = config.getString(prefix + CFG_CERT_STORE, VAL_CERT_STORE);
bool requireTLSv1 = config.getBool(prefix + CFG_REQUIRE_TLSV1, false);
bool requireTLSv1_1 = config.getBool(prefix + CFG_REQUIRE_TLSV1_1, false);
bool requireTLSv1_2 = config.getBool(prefix + CFG_REQUIRE_TLSV1_2, false);
// 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);
}
bool revocChecking = config.getBool(prefix + CFG_REVOCATION_CHECK, VAL_REVOCATION_CHECK);
bool trustRoots = config.getBool(prefix + CFG_TRUST_ROOTS, VAL_TRUST_ROOTS);
bool useMachineStore = config.getBool(prefix + CFG_USE_MACHINE_STORE, VAL_USE_MACHINE_STORE);
bool useStrongCrypto = config.getBool(prefix + CFG_USE_STRONG_CRYPTO, VAL_USE_STRONG_CRYPTO);
int options = 0;
if (revocChecking) options |= Context::OPT_PERFORM_REVOCATION_CHECK;
if (trustRoots) options |= Context::OPT_TRUST_ROOTS_WIN_CERT_STORE;
if (useMachineStore) options |= Context::OPT_USE_MACHINE_STORE;
if (useStrongCrypto) options |= Context::OPT_USE_STRONG_CRYPTO;
Context::Usage usage;
if (server)
{
if (requireTLSv1_2)
usage = Context::TLSV1_2_SERVER_USE;
else if (requireTLSv1_1)
usage = Context::TLSV1_1_SERVER_USE;
else if (requireTLSv1)
usage = Context::TLSV1_SERVER_USE;
else
usage = Context::SERVER_USE;
_ptrDefaultServerContext = new Context(usage, certName, verMode, options, certStore);
}
else
{
if (requireTLSv1_2)
usage = Context::TLSV1_2_CLIENT_USE;
else if (requireTLSv1_1)
usage = Context::TLSV1_1_CLIENT_USE;
else if (requireTLSv1)
usage = Context::TLSV1_CLIENT_USE;
else
usage = Context::CLIENT_USE;
_ptrDefaultClientContext = new Context(usage, certName, verMode, options, certStore);
}
}
void SSLManager::initEvents(bool server)
{
initCertificateHandler(server);
}
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("No InvalidCertificate handler known with the name", className);
}
void SSLManager::shutdown()
{
ClientVerificationError.clear();
ServerVerificationError.clear();
_ptrDefaultServerContext = 0;
_ptrDefaultClientContext = 0;
}
void initializeSSL()
{
}
void uninitializeSSL()
{
SSLManager::instance().shutdown();
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,66 @@
//
// SecureSMTPClientSession.h
//
// $Id: //poco/1.4/NetSSL_Win/src/SecureSMTPClientSession.cpp#1 $
//
// Library: NetSSL_Win
// Package: Mail
// Module: SecureSMTPClientSession
//
// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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),
_host(host)
{
}
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(), _host, pContext));
socket() = sss;
return true;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,123 @@
//
// SecureServerSocket.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/SecureServerSocket.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLSockets
// Module: SecureServerSocket
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Net/SecureServerSocketImpl.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
SecureServerSocket::SecureServerSocket():
ServerSocket(new SecureServerSocketImpl(SSLManager::instance().defaultServerContext()), true)
{
}
SecureServerSocket::SecureServerSocket(Context::Ptr pContext):
ServerSocket(new SecureServerSocketImpl(pContext), true)
{
}
SecureServerSocket::SecureServerSocket(const Socket& socket):
ServerSocket(socket)
{
if (!dynamic_cast<SecureServerSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
SecureServerSocket::SecureServerSocket(const SocketAddress& address, int backlog):
ServerSocket(new SecureServerSocketImpl(SSLManager::instance().defaultServerContext()), true)
{
impl()->bind(address, true);
impl()->listen(backlog);
}
SecureServerSocket::SecureServerSocket(const SocketAddress& address, int backlog, Context::Ptr pContext):
ServerSocket(new SecureServerSocketImpl(pContext), true)
{
impl()->bind(address, true);
impl()->listen(backlog);
}
SecureServerSocket::SecureServerSocket(Poco::UInt16 port, int backlog):
ServerSocket(new SecureServerSocketImpl(SSLManager::instance().defaultServerContext()), true)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, true);
impl()->listen(backlog);
}
SecureServerSocket::SecureServerSocket(Poco::UInt16 port, int backlog, Context::Ptr pContext):
ServerSocket(new SecureServerSocketImpl(pContext), true)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, true);
impl()->listen(backlog);
}
SecureServerSocket::~SecureServerSocket()
{
}
SecureServerSocket& SecureServerSocket::operator = (const Socket& socket)
{
if (&socket != this)
{
if (dynamic_cast<SecureServerSocketImpl*>(socket.impl()))
ServerSocket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
}
return *this;
}
StreamSocket SecureServerSocket::acceptConnection(SocketAddress& clientAddr)
{
return SecureStreamSocket(impl()->acceptConnection(clientAddr));
}
StreamSocket SecureServerSocket::acceptConnection()
{
SocketAddress clientAddr;
return SecureStreamSocket(impl()->acceptConnection(clientAddr));
}
Context::Ptr SecureServerSocket::context() const
{
return static_cast<SecureServerSocketImpl*>(impl())->context();
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,117 @@
//
// SecureServerSocketImpl.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/SecureServerSocketImpl.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLSockets
// Module: SecureServerSocketImpl
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/SecureServerSocketImpl.h"
namespace Poco {
namespace Net {
SecureServerSocketImpl::SecureServerSocketImpl(Context::Ptr pContext):
_impl(new ServerSocketImpl, pContext)
{
}
SecureServerSocketImpl::~SecureServerSocketImpl()
{
reset();
}
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
//
// SecureStreamSocket.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/SecureStreamSocket.cpp#2 $
//
// Library: NetSSL_Win
// Package: SSLSockets
// Module: SecureStreamSocket
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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

@@ -0,0 +1,221 @@
//
// SecureStreamSocketImpl.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/SecureStreamSocketImpl.cpp#6 $
//
// Library: NetSSL_Win
// Package: SSLSockets
// Module: SecureStreamSocketImpl
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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()
{
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)
{
_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)
{
return _impl.sendBytes(buffer, length, flags);
}
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 0; // TODO _impl.available();
}
void SecureStreamSocketImpl::shutdownReceive()
{
}
void SecureStreamSocketImpl::shutdownSend()
{
}
void SecureStreamSocketImpl::shutdown()
{
_impl.shutdown();
}
bool SecureStreamSocketImpl::secure() const
{
return true;
}
bool SecureStreamSocketImpl::havePeerCertificate() const
{
return _impl.peerCertificate() != 0;
}
X509Certificate SecureStreamSocketImpl::peerCertificate() const
{
if (havePeerCertificate())
{
return X509Certificate(_impl.peerCertificate(), true);
}
else throw SSLException("No certificate available");
}
void SecureStreamSocketImpl::setLazyHandshake(bool flag)
{
_lazyHandshake = flag;
}
bool SecureStreamSocketImpl::getLazyHandshake() const
{
return _lazyHandshake;
}
void SecureStreamSocketImpl::verifyPeerCertificate()
{
// TODO
// _impl.verifyPeerCertificate();
}
void SecureStreamSocketImpl::verifyPeerCertificate(const std::string& hostName)
{
// TODO
// _impl.verifyPeerCertificate(hostName);
}
int SecureStreamSocketImpl::completeHandshake()
{
// TODO
// return _impl.completeHandshake();
return 0;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,40 @@
//
// Session.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/Session.cpp#2 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: Session
//
// Copyright (c) 2010-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#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()
{
}
Session::~Session()
{
}
} } // namespace Poco::Net

205
NetSSL_Win/src/Utility.cpp Normal file
View File

@@ -0,0 +1,205 @@
//
// Utility.cpp
//
// $Id: //poco/1.4/NetSSL_Schannel/src/Utility.cpp#1 $
//
// Library: NetSSL_Schannel
// Package: SSLCore
// Module: Utility
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/Utility.h"
#include "Poco/String.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Util/OptionException.h"
#include <windows.h>
#include <winerror.h>
namespace Poco {
namespace Net {
Poco::FastMutex Utility::_mutex;
Context::VerificationMode Utility::convertVerificationMode(const std::string& vMode)
{
std::string mode = Poco::toLower(vMode);
Context::VerificationMode verMode = Context::VERIFY_STRICT;
if (mode == "none")
verMode = Context::VERIFY_NONE;
else if (mode == "relaxed")
verMode = Context::VERIFY_RELAXED;
else if (mode == "strict")
verMode = Context::VERIFY_STRICT;
else
throw Poco::Util::OptionException(std::string("Wrong value >") + vMode + std::string("< for a verificationMode. Can only be none, relaxed, strict or once."));
return verMode;
}
inline void add(std::map<long, const std::string>& messageMap, long key, const std::string& val)
{
messageMap.insert(std::make_pair(key, val));
}
std::map<long, const std::string> Utility::initSSPIErr()
{
std::map<long, const std::string> messageMap;
add(messageMap, NTE_BAD_UID, "Bad UID");
add(messageMap, NTE_BAD_HASH, "Bad Hash");
add(messageMap, NTE_BAD_KEY, "Bad Key");
add(messageMap, NTE_BAD_LEN, "Bad Length");
add(messageMap, NTE_BAD_DATA, "Bad Data");
add(messageMap, NTE_BAD_SIGNATURE, "Invalid signature");
add(messageMap, NTE_BAD_VER, "Bad Version of provider");
add(messageMap, NTE_BAD_ALGID, "Invalid algorithm specified");
add(messageMap, NTE_BAD_FLAGS, "Invalid flags specified");
add(messageMap, NTE_BAD_TYPE, "Invalid type specified");
add(messageMap, NTE_BAD_KEY_STATE, "Key not valid for use in specified state");
add(messageMap, NTE_BAD_HASH_STATE, "Hash not valid for use in specified state");
add(messageMap, NTE_NO_KEY, "Key does not exist");
add(messageMap, NTE_NO_MEMORY, "Insufficient memory available for the operation");
add(messageMap, NTE_EXISTS, "Object already exists");
add(messageMap, NTE_PERM, "Permission denied");
add(messageMap, NTE_NOT_FOUND, "Object was not found");
add(messageMap, NTE_DOUBLE_ENCRYPT, "Data already encrypted");
add(messageMap, NTE_BAD_PROVIDER, "Invalid provider specified");
add(messageMap, NTE_BAD_PROV_TYPE, "Invalid provider type specified");
add(messageMap, NTE_BAD_PUBLIC_KEY, "Provider's public key is invalid");
add(messageMap, NTE_BAD_KEYSET, "Keyset does not exist");
add(messageMap, NTE_PROV_TYPE_NOT_DEF, "Provider type not defined");
add(messageMap, NTE_PROV_TYPE_ENTRY_BAD, "Provider type as registered is invalid");
add(messageMap, NTE_KEYSET_NOT_DEF, "The keyset is not defined");
add(messageMap, NTE_KEYSET_ENTRY_BAD, "Keyset as registered is invalid");
add(messageMap, NTE_PROV_TYPE_NO_MATCH, "Provider type does not match registered value");
add(messageMap, NTE_SIGNATURE_FILE_BAD, "The digital signature file is corrupt");
add(messageMap, NTE_PROVIDER_DLL_FAIL, "Provider DLL failed to initialize correctly");
add(messageMap, NTE_PROV_DLL_NOT_FOUND, "Provider DLL could not be found");
add(messageMap, NTE_BAD_KEYSET_PARAM, "The Keyset parameter is invalid");
add(messageMap, NTE_FAIL, "NTE_FAIL: An internal error occurred");
add(messageMap, NTE_SYS_ERR, "NTE_SYS_ERR: A base error occurred");
add(messageMap, NTE_SILENT_CONTEXT, "Provider could not perform the action since the context was acquired as silent");
add(messageMap, NTE_TOKEN_KEYSET_STORAGE_FULL, "The security token does not have storage space available for an additional container");
add(messageMap, NTE_TEMPORARY_PROFILE, "The profile for the user is a temporary profile");
add(messageMap, NTE_FIXEDPARAMETER, "The key parameters could not be set because the CSP uses fixed parameters");
add(messageMap, SEC_E_INSUFFICIENT_MEMORY, "Not enough memory is available to complete this request");
add(messageMap, SEC_E_INVALID_HANDLE, "The handle specified is invalid");
add(messageMap, SEC_E_UNSUPPORTED_FUNCTION, "The function requested is not supported");
add(messageMap, SEC_E_TARGET_UNKNOWN, "The specified target is unknown or unreachable");
add(messageMap, SEC_E_INTERNAL_ERROR, "The Local Security Authority cannot be contacted");
add(messageMap, SEC_E_SECPKG_NOT_FOUND, "The requested security package does not exist");
add(messageMap, SEC_E_NOT_OWNER, "The caller is not the owner of the desired credentials");
add(messageMap, SEC_E_CANNOT_INSTALL, "The security package failed to initialize, and cannot be installed");
add(messageMap, SEC_E_INVALID_TOKEN, "The token supplied to the function is invalid");
add(messageMap, SEC_E_CANNOT_PACK, "The security package is not able to marshall the logon buffer, so the logon attempt has failed");
add(messageMap, SEC_E_QOP_NOT_SUPPORTED, "The per-message Quality of Protection is not supported by the security package");
add(messageMap, SEC_E_NO_IMPERSONATION, "The security context does not allow impersonation of the client");
add(messageMap, SEC_E_LOGON_DENIED, "The logon attempt failed");
add(messageMap, SEC_E_UNKNOWN_CREDENTIALS, "The credentials supplied to the package were not recognized");
add(messageMap, SEC_E_NO_CREDENTIALS, "No credentials are available in the security package");
add(messageMap, SEC_E_MESSAGE_ALTERED, "The message or signature supplied for verification has been altered");
add(messageMap, SEC_E_OUT_OF_SEQUENCE, "The message supplied for verification is out of sequence");
add(messageMap, SEC_E_NO_AUTHENTICATING_AUTHORITY, "No authority could be contacted for authentication");
add(messageMap, SEC_I_CONTINUE_NEEDED, "The function completed successfully, but must be called again to complete the context");
add(messageMap, SEC_I_COMPLETE_NEEDED, "The function completed successfully, but CompleteToken must be called");
add(messageMap, SEC_I_COMPLETE_AND_CONTINUE, "The function completed successfully, but both CompleteToken and this function must be called to complete the context");
add(messageMap, SEC_I_LOCAL_LOGON, "The logon was completed, but no network authority was available. The logon was made using locally known information");
add(messageMap, SEC_E_BAD_PKGID, "The requested security package does not exist");
add(messageMap, SEC_E_CONTEXT_EXPIRED, "The context has expired and can no longer be used");
add(messageMap, SEC_E_INCOMPLETE_MESSAGE, "The supplied message is incomplete. The signature was not verified");
add(messageMap, SEC_E_INCOMPLETE_CREDENTIALS, "The credentials supplied were not complete, and could not be verified. The context could not be initialized");
add(messageMap, SEC_E_BUFFER_TOO_SMALL, "The buffers supplied to a function was too small");
add(messageMap, SEC_I_RENEGOTIATE, "The context data must be renegotiated with the peer");
add(messageMap, SEC_E_WRONG_PRINCIPAL, "The target principal name is incorrect");
add(messageMap, SEC_I_NO_LSA_CONTEXT, "There is no LSA mode context associated with this context");
add(messageMap, SEC_E_TIME_SKEW, "The clocks on the client and server machines are skewed");
add(messageMap, SEC_E_UNTRUSTED_ROOT, "The certificate chain was issued by an authority that is not trusted");
add(messageMap, SEC_E_ILLEGAL_MESSAGE, "The message received was unexpected or badly formatted");
add(messageMap, SEC_E_CERT_UNKNOWN, "An unknown error occurred while processing the certificate");
add(messageMap, SEC_E_CERT_EXPIRED, "The received certificate has expired");
add(messageMap, SEC_E_ENCRYPT_FAILURE, "The specified data could not be encrypted");
add(messageMap, SEC_E_DECRYPT_FAILURE, "The specified data could not be decrypted");
add(messageMap, SEC_E_ALGORITHM_MISMATCH, "The client and server cannot communicate, because they do not possess a common algorithm");
add(messageMap, SEC_E_SECURITY_QOS_FAILED, "The security context could not be established due to a failure in the requested quality of service (e.g. mutual authentication or delegation)");
add(messageMap, SEC_E_UNFINISHED_CONTEXT_DELETED, "A security context was deleted before the context was completed. This is considered a logon failure");
add(messageMap, SEC_E_NO_TGT_REPLY, "The client is trying to negotiate a context and the server requires user-to-user but didn't send a TGT reply");
add(messageMap, SEC_E_NO_IP_ADDRESSES, "Unable to accomplish the requested task because the local machine does not have any IP addresses");
add(messageMap, SEC_E_WRONG_CREDENTIAL_HANDLE, "The supplied credential handle does not match the credential associated with the security context");
add(messageMap, SEC_E_CRYPTO_SYSTEM_INVALID, "The crypto system or checksum function is invalid because a required function is unavailable");
add(messageMap, SEC_E_MAX_REFERRALS_EXCEEDED, "The number of maximum ticket referrals has been exceeded");
add(messageMap, SEC_E_MUST_BE_KDC, "The local machine must be a Kerberos KDC (domain controller) and it is not");
add(messageMap, SEC_E_STRONG_CRYPTO_NOT_SUPPORTED, "The other end of the security negotiation is requires strong crypto but it is not supported on the local machine");
add(messageMap, SEC_E_TOO_MANY_PRINCIPALS, "The KDC reply contained more than one principal name");
add(messageMap, SEC_E_NO_PA_DATA, "Expected to find PA data for a hint of what type to use, but it was not found");
//80092001
add(messageMap, CRYPT_E_SELF_SIGNED, "The specified certificate is self signed");
add(messageMap, CRYPT_E_DELETED_PREV, "The previous certificate or CRL context was deleted");
add(messageMap, CRYPT_E_NO_MATCH, "Cannot find the requested object");
add(messageMap, CRYPT_E_UNEXPECTED_MSG_TYPE, "The certificate does not have a property that references a private key");
add(messageMap, CRYPT_E_NO_KEY_PROPERTY, "Cannot find the certificate and private key for decryption");
add(messageMap, CRYPT_E_NO_DECRYPT_CERT, "Cannot find the certificate and private key to use for decryption");
add(messageMap, CRYPT_E_BAD_MSG, "Not a cryptographic message or the cryptographic message is not formatted correctly");
add(messageMap, CRYPT_E_NO_SIGNER, "The signed cryptographic message does not have a signer for the specified signer index");
add(messageMap, CRYPT_E_PENDING_CLOSE, "Final closure is pending until additional frees or closes");
add(messageMap, CRYPT_E_REVOKED, "The certificate is revoked");
add(messageMap, CRYPT_E_NO_REVOCATION_DLL, "No Dll or exported function was found to verify revocation");
add(messageMap, CRYPT_E_NO_REVOCATION_CHECK, "The revocation function was unable to check revocation for the certificate");
add(messageMap, CRYPT_E_REVOCATION_OFFLINE, "The revocation function was unable to check revocation because the revocation server was offline");
add(messageMap, CRYPT_E_NOT_IN_REVOCATION_DATABASE, "The certificate is not in the revocation server's database");
add(messageMap, CRYPT_E_INVALID_NUMERIC_STRING, "The string contains a non-numeric character");
add(messageMap, CRYPT_E_INVALID_PRINTABLE_STRING, "The string contains a non-printable character");
add(messageMap, CRYPT_E_INVALID_IA5_STRING, "The string contains a character not in the 7 bit ASCII character set");
add(messageMap, CRYPT_E_INVALID_X500_STRING, "The string contains an invalid X500 name attribute key, oid, value or delimiter");
add(messageMap, CRYPT_E_NOT_CHAR_STRING, "The dwValueType for the CERT_NAME_VALUE is not one of the character strings. Most likely it is either a CERT_RDN_ENCODED_BLOB or CERT_TDN_OCTED_STRING");
add(messageMap, CRYPT_E_FILERESIZED, "The Put operation can not continue. The file needs to be resized. However, there is already a signature present. A complete signing operation must be done");
add(messageMap, CRYPT_E_SECURITY_SETTINGS, "The cryptographic operation failed due to a local security option setting");
add(messageMap, CRYPT_E_NO_VERIFY_USAGE_DLL, "No DLL or exported function was found to verify subject usage");
add(messageMap, CRYPT_E_NO_VERIFY_USAGE_CHECK, "The called function was unable to do a usage check on the subject");
add(messageMap, CRYPT_E_VERIFY_USAGE_OFFLINE, "Since the server was offline, the called function was unable to complete the usage check");
add(messageMap, CRYPT_E_NOT_IN_CTL, "The subject was not found in a Certificate Trust List (CTL)");
add(messageMap, CRYPT_E_NO_TRUSTED_SIGNER, "None of the signers of the cryptographic message or certificate trust list is trusted");
add(messageMap, CRYPT_E_MISSING_PUBKEY_PARA, "The public key's algorithm parameters are missing");
add(messageMap, TRUST_E_CERT_SIGNATURE, "The signature of the certificate cannot be verified.");
add(messageMap, TRUST_E_BASIC_CONSTRAINTS, "The basic constraints of the certificate are not valid or missing");
add(messageMap, CERT_E_UNTRUSTEDROOT, "A certification chain processed correctly but terminated in a root certificate not trusted by the trust provider");
add(messageMap, CERT_E_UNTRUSTEDTESTROOT, "The root certificate is a testing certificate and policy settings disallow test certificates");
add(messageMap, CERT_E_CHAINING, "A chain of certificates was not correctly created");
add(messageMap, CERT_E_WRONG_USAGE, "The certificate is not valid for the requested usage");
add(messageMap, CERT_E_EXPIRED, "A required certificate is not within its validity period");
add(messageMap, CERT_E_VALIDITYPERIODNESTING, "The validity periods of the certification chain do not nest correctly");
add(messageMap, CERT_E_PURPOSE, "A certificate is being used for a purpose that is not supported");
add(messageMap, CERT_E_ROLE, "A certificate that can only be used as an end entity is being used as a CA or visa versa");
add(messageMap, CERT_E_CN_NO_MATCH, "The CN name of the certificate does not match the passed value");
add(messageMap, CERT_E_REVOKED, "A certificate in the chain has been explicitly revoked by its issuer");
add(messageMap, CERT_E_REVOCATION_FAILURE, "The revocation process could not continue. The certificates could not be checked");
return messageMap;
}
const std::string& Utility::formatError(long errCode)
{
Poco::FastMutex::ScopedLock lock(_mutex);
static const std::string def("Internal SSPI error");
static const std::map<long, const std::string> errs(initSSPIErr());
const std::map<long, const std::string>::const_iterator it = errs.find(errCode);
if (it != errs.end())
return it->second;
else
return def;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,39 @@
//
// VerificationErrorArgs.cpp
//
// $Id: //poco/1.4/NetSSL_Win/src/VerificationErrorArgs.cpp#1 $
//
// Library: NetSSL_Win
// Package: SSLCore
// Module: VerificationErrorArgs
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/VerificationErrorArgs.h"
namespace Poco {
namespace Net {
VerificationErrorArgs::VerificationErrorArgs(const X509Certificate& cert, int errDepth, int errNum, const std::string& errMsg):
_cert(cert),
_errorDepth(errDepth),
_errorNumber(errNum),
_errorMessage(errMsg),
_ignoreError(false)
{
}
VerificationErrorArgs::~VerificationErrorArgs()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,256 @@
//
// X509Certificate.cpp
//
// $Id: //poco/1.4/Crypto/src/X509Certificate.cpp#1 $
//
// Library: Crypto
// Package: Certificate
// Module: X509Certificate
//
// Copyright (c) 2006-2014, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/X509Certificate.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h"
#include "Poco/DateTimeParser.h"
#include "Poco/Base64Encoder.h"
#include "Poco/Base64Decoder.h"
#include "Poco/FileStream.h"
#include "Poco/UnicodeConverter.h"
#include <sstream>
namespace Poco {
namespace Net {
X509Certificate::X509Certificate(std::istream& istr):
_pCert(0)
{
load(istr);
}
X509Certificate::X509Certificate(const std::string& path):
_pCert(0)
{
load(path);
}
X509Certificate::X509Certificate(PCCERT_CONTEXT pCert):
_pCert(pCert)
{
poco_check_ptr(_pCert);
init();
}
X509Certificate::X509Certificate(const X509Certificate& cert):
_issuerName(cert._issuerName),
_subjectName(cert._subjectName),
_pCert(cert._pCert)
{
_pCert = CertDuplicateCertificateContext(_pCert);
}
X509Certificate::X509Certificate(PCCERT_CONTEXT pCert, bool shared):
_pCert(pCert)
{
poco_check_ptr(_pCert);
if (shared)
{
_pCert = CertDuplicateCertificateContext(_pCert);
}
init();
}
X509Certificate& X509Certificate::operator = (const X509Certificate& cert)
{
X509Certificate tmp(cert);
swap(tmp);
return *this;
}
void X509Certificate::swap(X509Certificate& cert)
{
using std::swap;
swap(cert._issuerName, _issuerName);
swap(cert._subjectName, _subjectName);
swap(cert._pCert, _pCert);
}
X509Certificate::~X509Certificate()
{
CertFreeCertificateContext(_pCert);
}
void X509Certificate::load(std::istream& istr)
{
poco_assert (!_pCert);
// TODO
init();
}
void X509Certificate::load(const std::string& path)
{
Poco::FileInputStream istr(path);
load(istr);
}
void X509Certificate::save(std::ostream& stream) const
{
// TODO
}
void X509Certificate::save(const std::string& path) const
{
Poco::FileOutputStream ostr(path);
save(ostr);
}
void X509Certificate::init()
{
wchar_t data[256];
CertGetNameStringW(_pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, data, 256);
Poco::UnicodeConverter::convert(data, _issuerName);
CertGetNameStringW(_pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, data, 256);
Poco::UnicodeConverter::convert(data, _subjectName);
}
std::string X509Certificate::commonName() const
{
return subjectName(NID_COMMON_NAME);
}
std::string X509Certificate::issuerName(NID nid) const
{
std::string result;
wchar_t data[256];
CertGetNameStringW(_pCert, CERT_NAME_ATTR_TYPE, CERT_NAME_ISSUER_FLAG, nid2oid(nid), data, 256);
Poco::UnicodeConverter::convert(data, result);
return result;
}
std::string X509Certificate::subjectName(NID nid) const
{
std::string result;
wchar_t data[256];
CertGetNameStringW(_pCert, CERT_NAME_ATTR_TYPE, 0, nid2oid(nid), data, 256);
Poco::UnicodeConverter::convert(data, result);
return result;
}
void X509Certificate::extractNames(std::string& cmnName, std::set<std::string>& domainNames) const
{
domainNames.clear();
// TODO: extract subject alternative names
cmnName = commonName();
if (!cmnName.empty() && domainNames.empty())
{
domainNames.insert(cmnName);
}
}
Poco::DateTime X509Certificate::validFrom() const
{
Poco::Timestamp ts = Poco::Timestamp::fromFileTimeNP(_pCert->pCertInfo->NotBefore.dwLowDateTime, _pCert->pCertInfo->NotBefore.dwHighDateTime);
return Poco::DateTime(ts);
}
Poco::DateTime X509Certificate::expiresOn() const
{
Poco::Timestamp ts = Poco::Timestamp::fromFileTimeNP(_pCert->pCertInfo->NotAfter.dwLowDateTime, _pCert->pCertInfo->NotAfter.dwHighDateTime);
return Poco::DateTime(ts);
}
bool X509Certificate::issuedBy(const X509Certificate& issuerCertificate) const
{
HCERTSTORE hCertStore = CertOpenSystemStoreW(NULL, L"CA");
if (!hCertStore) throw Poco::SystemException("Cannot open CA store");
// TODO
try
{
PCCERT_CONTEXT pIssuer = 0;
do
{
DWORD flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG;
pIssuer = CertGetIssuerCertificateFromStore(hCertStore, _pCert, 0, &flags);
if (pIssuer)
{
X509Certificate issuer(pIssuer);
if (flags & CERT_STORE_NO_CRL_FLAG)
flags &= ~(CERT_STORE_NO_CRL_FLAG | CERT_STORE_REVOCATION_FLAG);
if (flags)
break;
}
else break;
}
while (pIssuer);
}
catch (...)
{
}
return false;
}
void* X509Certificate::nid2oid(NID nid)
{
const char* result = 0;
switch (nid)
{
case NID_COMMON_NAME:
result = szOID_COMMON_NAME;
break;
case NID_COUNTRY:
result = szOID_COUNTRY_NAME;
break;
case NID_LOCALITY_NAME:
result = szOID_LOCALITY_NAME;
break;
case NID_STATE_OR_PROVINCE:
result = szOID_STATE_OR_PROVINCE_NAME;
break;
case NID_ORGANIZATION_NAME:
result = szOID_ORGANIZATION_NAME;
break;
case NID_ORGANIZATION_UNIT_NAME:
result = szOID_ORGANIZATIONAL_UNIT_NAME;
break;
default:
poco_bugcheck();
result = "";
break;
}
return const_cast<char*>(result);
}
} } // namespace Poco::Net