Skip to content

Commit 8a2502b

Browse files
author
Peter Schojer
committed
added https->http redirect, improved redirect support in streamfactory, fixed client cert validation error
1 parent f84e094 commit 8a2502b

5 files changed

Lines changed: 92 additions & 47 deletions

File tree

‎NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp‎

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,25 @@ HTTPSStreamFactory::~HTTPSStreamFactory()
7575

7676
std::istream* HTTPSStreamFactory::open(const URI& uri)
7777
{
78-
poco_assert (uri.getScheme() == "https");
78+
poco_assert (uri.getScheme() == "https" || uri.getScheme() == "http");
7979

8080
URI resolvedURI(uri);
81+
URI proxyUri;
8182
HTTPClientSession* pSession = 0;
8283
try
8384
{
85+
bool retry = false;
8486
int redirects = 0;
8587
do
8688
{
87-
pSession = new HTTPSClientSession(resolvedURI.getHost(), resolvedURI.getPort());
88-
pSession->setProxy(_proxyHost, _proxyPort);
89+
if (resolvedURI.getScheme() != "http")
90+
pSession = new HTTPSClientSession(resolvedURI.getHost(), resolvedURI.getPort());
91+
else
92+
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
93+
if (proxyUri.empty())
94+
pSession->setProxy(_proxyHost, _proxyPort);
95+
else
96+
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
8997
std::string path = resolvedURI.getPathAndQuery();
9098
if (path.empty()) path = "/";
9199
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
@@ -94,20 +102,38 @@ std::istream* HTTPSStreamFactory::open(const URI& uri)
94102
std::istream& rs = pSession->receiveResponse(res);
95103
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
96104
res.getStatus() == HTTPResponse::HTTP_FOUND ||
97-
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER);
105+
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER ||
106+
res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT);
98107
if (moved)
99108
{
100109
resolvedURI.resolve(res.get("Location"));
101-
delete pSession;
110+
//throw URIRedirection(resolvedURI.toString());
111+
delete pSession; pSession = 0;
102112
++redirects;
113+
retry = true;
103114
}
104115
else if (res.getStatus() == HTTPResponse::HTTP_OK)
105116
{
106117
return new HTTPResponseStream(rs, pSession);
107118
}
108-
else throw HTTPException(res.getReason(), uri.toString());
119+
else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry)
120+
{
121+
//The requested resource MUST be accessed through the proxy
122+
//given by the Location field. The Location field gives the
123+
//URI of the proxy. The recipient is expected to repeat this
124+
//single request via the proxy. 305 responses MUST only be generated by origin servers.
125+
// only use for one single request!
126+
proxyUri.resolve(res.get("Location"));
127+
delete pSession; pSession = 0;
128+
retry = true; //only allow useproxy once
129+
}
130+
else
131+
{
132+
delete pSession; pSession = 0;
133+
throw HTTPException(res.getReason(), uri.toString());
134+
}
109135
}
110-
while (redirects < MAX_REDIRECTS);
136+
while (retry && redirects < MAX_REDIRECTS);
111137
throw HTTPException("Too many redirects", uri.toString());
112138
}
113139
catch (...)

‎NetSSL_OpenSSL/src/SecureSocketImpl.cpp‎

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "Poco/RegularExpression.h"
4949
#include <openssl/x509v3.h>
5050
#include <openssl/err.h>
51+
#include <set>
5152

5253

5354
using Poco::IOException;
@@ -66,6 +67,9 @@ namespace Poco {
6667
namespace Net {
6768

6869

70+
static void getCertNames (X509*, std::string& commonName, std::set<std::string>& DNSNames);
71+
72+
6973
SecureSocketImpl::SecureSocketImpl():_pBIO(0), _pSSL(0)
7074
{
7175
}
@@ -420,43 +424,10 @@ long SecureSocketImpl::postConnectionCheck(SSLManager::ContextPtr pContext, X509
420424
return X509_V_ERR_APPLICATION_VERIFICATION;
421425
}
422426

423-
bool ok = false;
424-
425-
if ((extcount = X509_get_ext_count(cert)) > 0)
426-
{
427-
for (int i = 0; i < extcount && !ok; ++i)
428-
{
429-
const char* extstr = 0;
430-
X509_EXTENSION* ext;
431-
ext = X509_get_ext(cert, i);
432-
extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
433-
434-
if (!strcmp(extstr, "subjectAltName"))
435-
{
436-
X509V3_EXT_METHOD* meth = X509V3_EXT_get(ext);
437-
if (!meth)
438-
break;
439-
440-
#if OPENSSL_VERSION_NUMBER >= 0x00908000
441-
const unsigned char* pData = ext->value->data;
442-
const unsigned char** ppData = &pData;
443-
#else
444-
unsigned char* pData = ext->value->data;
445-
unsigned char** ppData = &pData;
446-
#endif
447-
STACK_OF(CONF_VALUE)* val = meth->i2v(meth, meth->d2i(0, ppData, ext->value->length), 0);
448-
449-
for (int j = 0; j < sk_CONF_VALUE_num(val) && !ok; ++j)
450-
{
451-
CONF_VALUE* nval = sk_CONF_VALUE_value(val, j);
452-
if (!strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
453-
{
454-
ok = true;
455-
}
456-
}
457-
}
458-
}
459-
}
427+
std::string commonName;
428+
std::set<std::string> dnsNames;
429+
getCertNames(cert, commonName, dnsNames);
430+
bool ok = (dnsNames.find(hostName) != dnsNames.end());
460431

461432
char data[256];
462433
if (!ok && (subj = X509_get_subject_name(cert)) && X509_NAME_get_text_by_NID(subj, NID_commonName, data, 256) > 0)
@@ -618,4 +589,48 @@ bool SecureSocketImpl::matchByAlias(const std::string& alias, const HostEntry& h
618589
}
619590

620591

592+
static void
593+
getCertNames (X509 *certificate,
594+
std::string& common_name,
595+
std::set<std::string>& DNS_names)
596+
{
597+
DNS_names.clear ();
598+
common_name.clear ();
599+
if (certificate == 0)
600+
{
601+
return;
602+
}
603+
604+
if (STACK_OF (GENERAL_NAME) * names = static_cast<STACK_OF (GENERAL_NAME)
605+
*>
606+
(X509_get_ext_d2i (certificate, NID_subject_alt_name, 0, 0)))
607+
{
608+
for (int i = 0; i < sk_GENERAL_NAME_num (names); ++i)
609+
{
610+
const GENERAL_NAME *name = sk_GENERAL_NAME_value (names, i);
611+
if (name->type == GEN_DNS)
612+
{
613+
const char *data = reinterpret_cast<char *>
614+
(ASN1_STRING_data (name->d.ia5));
615+
size_t len = ASN1_STRING_length (name->d.ia5);
616+
DNS_names.insert (std::string (data, len));
617+
}
618+
}
619+
GENERAL_NAMES_free (names);
620+
}
621+
622+
if (X509_NAME * subj = X509_get_subject_name (certificate))
623+
{
624+
char buffer[256];
625+
X509_NAME_get_text_by_NID (subj, NID_commonName,
626+
buffer, sizeof buffer);
627+
common_name = std::string (buffer);
628+
if (DNS_names.empty ())
629+
{
630+
DNS_names.insert (common_name);
631+
}
632+
}
633+
}
634+
635+
621636
} } // namespace Poco::Net

‎NetSSL_OpenSSL/testsuite/src/HTTPSClientSessionTest.cpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232

3333
#include "HTTPSClientSessionTest.h"
34+
#include "HTTPSClientTestSuite.h"
3435
#include "CppUnit/TestCaller.h"
3536
#include "CppUnit/TestSuite.h"
3637
#include "Poco/Net/HTTPSClientSession.h"
@@ -336,7 +337,7 @@ void HTTPSClientSessionTest::testKeepAlive()
336337
void HTTPSClientSessionTest::testProxy()
337338
{
338339
HTTPSTestServer srv;
339-
HTTPSClientSession s("wwws.appinf.com");
340+
HTTPSClientSession s(TESTSERVERNAME);
340341
s.setProxy("proxy.aon.at", 8080);
341342
HTTPRequest request(HTTPRequest::HTTP_GET, "/");
342343
s.sendRequest(request);
@@ -351,7 +352,7 @@ void HTTPSClientSessionTest::testProxy()
351352
void HTTPSClientSessionTest::testConnectNB()
352353
{
353354
SecureStreamSocket sock;
354-
sock.connectNB(SocketAddress("server.com", 443));
355+
sock.connectNB(SocketAddress(TESTSERVERNAME, 443));
355356
char buf[512];
356357
std::string msg("GET / HTTP/1.0\r\n\r\n");
357358
sock.sendBytes(msg.c_str(), (int)msg.length());

‎NetSSL_OpenSSL/testsuite/src/HTTPSClientTestSuite.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "CppUnit/TestSuite.h"
4040

4141

42+
#define TESTSERVERNAME "secure.appinf.com"
43+
4244
class HTTPSClientTestSuite
4345
{
4446
public:

‎NetSSL_OpenSSL/testsuite/src/HTTPSStreamFactoryTest.cpp‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232

3333
#include "HTTPSStreamFactoryTest.h"
34+
#include "HTTPSClientTestSuite.h"
3435
#include "CppUnit/TestCaller.h"
3536
#include "CppUnit/TestSuite.h"
3637
#include "Poco/Net/HTTPSStreamFactory.h"
@@ -103,7 +104,7 @@ void HTTPSStreamFactoryTest::testProxy()
103104
{
104105
HTTPSTestServer server;
105106
HTTPSStreamFactory factory("proxy.aon.at", 8080);
106-
URI uri("https://wwws.appinf.com/");
107+
URI uri(std::string("https://") + TESTSERVERNAME + "/");
107108
std::auto_ptr<std::istream> pStr(factory.open(uri));
108109
std::ostringstream ostr;
109110
StreamCopier::copyStream(*pStr.get(), ostr);

0 commit comments

Comments
 (0)