#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"
# include <log4cpp/OstreamAppender.hh>
#endif
#include <xercesc/util/PlatformUtils.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
#ifndef XMLTOOLING_NO_XMLSEC
# include <curl/curl.h>
# include <openssl/err.h>
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));
#include "HTTPResponse.h"
using namespace xmltooling;
-using std::istream;
+using namespace std;
GenericResponse::GenericResponse()
{
{
}
+vector<string> HTTPResponse::m_allowedSchemes;
+
+vector<string>& 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<string>::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()
{
}
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);
#include <xmltooling/io/GenericResponse.h>
+#include <string>
+#include <vector>
+
namespace xmltooling {
-
+
+#if defined (_MSC_VER)
+ #pragma warning( push )
+ #pragma warning( disable : 4251 )
+#endif
+
/**
* Interface to HTTP response.
*
* @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.
/**
* Redirect the client to the specified URL and complete the response.
- * Any headers previously set will be sent ahead of the redirect.
*
+ * <p>Any headers previously set will be sent ahead of the redirect.
+ *
+ * <p>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 {
using GenericResponse::sendResponse;
long sendResponse(std::istream& inputStream);
+
+ /**
+ * Returns a modifiable array of schemes to permit in sanitized URLs.
+ *
+ * <p>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<std::string>& 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<std::string> m_allowedSchemes;
};
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
};
#endif /* __xmltooling_httpres_h__ */