From: cantor Date: Wed, 4 Nov 2009 15:18:00 +0000 (+0000) Subject: Tagging 1.3 release. X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fxmltooling.git;a=commitdiff_plain;h=43240ac200886072f2162ece8fabe8d67e6b42c2 Tagging 1.3 release. git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/tags/1.3@677 de75baf8-a10c-0410-a50a-987c0e22f00f --- diff --git a/xmltooling/XMLToolingConfig.cpp b/xmltooling/XMLToolingConfig.cpp index 9a43921..cadf7bc 100644 --- a/xmltooling/XMLToolingConfig.cpp +++ b/xmltooling/XMLToolingConfig.cpp @@ -27,6 +27,7 @@ #include "encryption/Encryption.h" #include "encryption/Encrypter.h" #include "impl/UnknownElement.h" +#include "io/HTTPResponse.h" #include "security/TrustEngine.h" #include "security/OpenSSLCryptoX509CRL.h" #include "security/CredentialResolver.h" @@ -56,6 +57,7 @@ # include #endif #include +#include #ifndef XMLTOOLING_NO_XMLSEC # include # include @@ -352,6 +354,9 @@ bool XMLToolingInternalConfig::init() m_pathResolver = new PathResolver(); m_urlEncoder = new URLEncoder(); + HTTPResponse::getAllowedSchemes().push_back("https"); + HTTPResponse::getAllowedSchemes().push_back("http"); + // Register xml:id as an ID attribute. static const XMLCh xmlid[] = UNICODE_LITERAL_2(i,d); AttributeExtensibleXMLObject::registerIDAttribute(QName(xmlconstants::XML_NS, xmlid)); diff --git a/xmltooling/io/HTTPResponse.cpp b/xmltooling/io/HTTPResponse.cpp index ab2255a..63a3dfc 100644 --- a/xmltooling/io/HTTPResponse.cpp +++ b/xmltooling/io/HTTPResponse.cpp @@ -24,7 +24,7 @@ #include "HTTPResponse.h" using namespace xmltooling; -using std::istream; +using namespace std; GenericResponse::GenericResponse() { @@ -34,6 +34,37 @@ GenericResponse::~GenericResponse() { } +vector HTTPResponse::m_allowedSchemes; + +vector& HTTPResponse::getAllowedSchemes() +{ + return m_allowedSchemes; +} + +void HTTPResponse::sanitizeURL(const char* url) +{ + const char* ch; + for (ch=url; *ch; ++ch) { + if (iscntrl(*ch)) + throw IOException("URL contained a control character."); + } + + ch = strchr(url, ':'); + if (!ch) + throw IOException("URL is malformed."); + string s(url, ch - url); + for (vector::const_iterator i = m_allowedSchemes.begin(); i != m_allowedSchemes.end(); ++i) { +#ifdef HAVE_STRCASECMP + if (!strcasecmp(s.c_str(), i->c_str())) +#else + if (!stricmp(s.c_str(), i->c_str())) +#endif + return; + } + + throw IOException("URL contains invalid scheme ($1).", params(1, s.c_str())); +} + HTTPResponse::HTTPResponse() { } @@ -49,11 +80,30 @@ void HTTPResponse::setContentType(const char* type) void HTTPResponse::setCookie(const char* name, const char* value) { - std::string cookie(name); + string cookie(name); cookie = cookie + '=' + value; setResponseHeader("Set-Cookie", cookie.c_str()); } +void HTTPResponse::setResponseHeader(const char* name, const char* value) +{ + for (const char* ch=name; *ch; ++ch) { + if (iscntrl(*ch)) + throw IOException("Response header name contained a control character."); + } + + for (const char* ch=value; *ch; ++ch) { + if (iscntrl(*ch)) + throw IOException("Value for response header ($1) contained a control character.", params(1,name)); + } +} + +long HTTPResponse::sendRedirect(const char* url) +{ + sanitizeURL(url); + return XMLTOOLING_HTTP_STATUS_MOVED; +} + long HTTPResponse::sendError(istream& inputStream) { return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_ERROR); diff --git a/xmltooling/io/HTTPResponse.h b/xmltooling/io/HTTPResponse.h index 6c38321..912c0f8 100644 --- a/xmltooling/io/HTTPResponse.h +++ b/xmltooling/io/HTTPResponse.h @@ -25,8 +25,16 @@ #include +#include +#include + namespace xmltooling { - + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4251 ) +#endif + /** * Interface to HTTP response. * @@ -50,7 +58,7 @@ namespace xmltooling { * @param name header name * @param value value to set, or NULL to clear */ - virtual void setResponseHeader(const char* name, const char* value)=0; + virtual void setResponseHeader(const char* name, const char* value); /** * Sets a client cookie. @@ -62,12 +70,15 @@ namespace xmltooling { /** * Redirect the client to the specified URL and complete the response. - * Any headers previously set will be sent ahead of the redirect. * + *

Any headers previously set will be sent ahead of the redirect. + * + *

The URL will be validated with the sanitizeURL method below. + * * @param url location to redirect client * @return a result code to return from the calling MessageEncoder */ - virtual long sendRedirect(const char* url)=0; + virtual long sendRedirect(const char* url); /** Some common HTTP status codes. */ enum status_t { @@ -83,7 +94,31 @@ namespace xmltooling { using GenericResponse::sendResponse; long sendResponse(std::istream& inputStream); + + /** + * Returns a modifiable array of schemes to permit in sanitized URLs. + * + *

Updates to this array must be externally synchronized with any use + * of this class or its subclasses. + * + * @return a mutable array of strings containing the schemes to permit + */ + static std::vector& getAllowedSchemes(); + + /** + * Manually check for unsafe URLs vulnerable to injection attacks. + * + * @param url location to check + */ + static void sanitizeURL(const char* url); + + private: + static std::vector m_allowedSchemes; }; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif }; #endif /* __xmltooling_httpres_h__ */