Check scheme part in redirected URI more strictly.

The previous implementation mistakenly sees '/abspath?uri=http://foo'
as an absolute URI because it contains '://', but actually it is not.
This change checks scheme part is constructed in the allowed character
set described in RFC 3986 Section 3.1.
pull/12/head
Tatsuhiro Tsujikawa 2012-02-15 01:40:12 +09:00
parent 9e302b86df
commit b7dbcea58b
3 changed files with 42 additions and 16 deletions

View File

@ -114,7 +114,26 @@ bool Request::redirectUri(const std::string& uri) {
redirectedUri = getProtocol(); redirectedUri = getProtocol();
redirectedUri += ":"; redirectedUri += ":";
redirectedUri += uri; redirectedUri += uri;
} else if(uri.find("://") == std::string::npos) { } else {
std::string::size_type schemeEnd = uri.find("://");
bool absUri;
if(schemeEnd == std::string::npos) {
absUri = false;
} else {
absUri = true;
// Check that scheme is acceptable one.
for(size_t i = 0; i < schemeEnd; ++i) {
char c = uri[i];
if(!util::isAlpha(c) && !util::isDigit(c) &&
c != '+' && c != '-' && c != '.') {
absUri = false;
break;
}
}
}
if(absUri) {
redirectedUri = uri;
} else {
// rfc2616 requires absolute URI should be provided by Location header // rfc2616 requires absolute URI should be provided by Location header
// field, but some servers don't obey this rule. // field, but some servers don't obey this rule.
// UPDATE: draft-ietf-httpbis-p2-semantics-18 now allows this. // UPDATE: draft-ietf-httpbis-p2-semantics-18 now allows this.
@ -129,8 +148,7 @@ bool Request::redirectUri(const std::string& uri) {
} }
redirectedUri = uri::construct(rus); redirectedUri = uri::construct(rus);
redirectedUri.append(uri.begin()+offset, uri.end()); redirectedUri.append(uri.begin()+offset, uri.end());
} else { }
redirectedUri = uri;
} }
return parseUri(redirectedUri); return parseUri(redirectedUri);
} }

View File

@ -358,6 +358,8 @@ bool isNumber(InputIterator first, InputIterator last)
return true; return true;
} }
bool isAlpha(const char c);
bool isDigit(const char c); bool isDigit(const char c);
bool isHexDigit(const char c); bool isHexDigit(const char c);

View File

@ -142,6 +142,12 @@ void RequestTest::testRedirectUri()
CPPUNIT_ASSERT(req.redirectUri("//host/to/file")); CPPUNIT_ASSERT(req.redirectUri("//host/to/file"));
CPPUNIT_ASSERT_EQUAL(std::string("http://host/to/file"), req.getCurrentUri()); CPPUNIT_ASSERT_EQUAL(std::string("http://host/to/file"), req.getCurrentUri());
CPPUNIT_ASSERT_EQUAL(5, req.getRedirectCount()); CPPUNIT_ASSERT_EQUAL(5, req.getRedirectCount());
// http:// in query part
CPPUNIT_ASSERT(req.redirectUri("/abspath?uri=http://foo"));
CPPUNIT_ASSERT_EQUAL(std::string("http://host/abspath?uri=http://foo"),
req.getCurrentUri());
CPPUNIT_ASSERT_EQUAL(6, req.getRedirectCount());
} }
void RequestTest::testRedirectUri2() void RequestTest::testRedirectUri2()