#ifndef XMLTOOLING_NO_XMLSEC
m_cred(NULL), m_trustEngine(NULL), m_peerResolver(NULL), m_mandatory(false),
#endif
- m_ssl_callback(NULL), m_ssl_userptr(NULL), m_chunked(true), m_authenticated(false), m_cacheTag(NULL) {
+ m_openssl_ops(SSL_OP_ALL|SSL_OP_NO_SSLv2), m_ssl_callback(NULL), m_ssl_userptr(NULL),
+ m_chunked(true), m_authenticated(false), m_cacheTag(NULL) {
m_handle = g_CURLPool->get(addr);
curl_easy_setopt(m_handle,CURLOPT_URL,addr.m_endpoint);
curl_easy_setopt(m_handle,CURLOPT_CONNECTTIMEOUT,15);
return true;
}
- bool setProviderOption(const char* provider, const char* option, const char* value) {
- if (!provider || strcmp(provider, "CURL"))
- return false;
- // For libcurl, the option is an enum and the value type depends on the option.
- CURLoption opt = static_cast<CURLoption>(strtol(option, NULL, 10));
- if (opt < CURLOPTTYPE_OBJECTPOINT)
- return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK);
-#ifdef CURLOPTTYPE_OFF_T
- else if (opt < CURLOPTTYPE_OFF_T) {
- if (value)
- m_saved_options.push_back(value);
- return (curl_easy_setopt(m_handle, opt, value ? m_saved_options.back().c_str() : NULL) == CURLE_OK);
- }
-# ifdef HAVE_CURL_OFF_T
- else if (sizeof(curl_off_t) == sizeof(long))
- return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK);
-# else
- else if (sizeof(off_t) == sizeof(long))
- return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK);
-# endif
- return false;
-#else
- else {
- if (value)
- m_saved_options.push_back(value);
- return (curl_easy_setopt(m_handle, opt, value ? m_saved_options.back().c_str() : NULL) == CURLE_OK);
- }
-#endif
- }
+ bool setProviderOption(const char* provider, const char* option, const char* value);
void send(istream& in) {
send(&in);
CredentialCriteria* m_criteria;
bool m_mandatory;
#endif
+ int m_openssl_ops;
ssl_ctx_callback_fn m_ssl_callback;
void* m_ssl_userptr;
bool m_chunked;
return (curl_easy_setopt(m_handle,CURLOPT_USERPWD,m_simplecreds.c_str())==CURLE_OK);
}
+bool CURLSOAPTransport::setProviderOption(const char* provider, const char* option, const char* value)
+{
+ if (!provider || !option || !value) {
+ return false;
+ }
+ else if (!strcmp(provider, "OpenSSL")) {
+ if (!strcmp(option, "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION") && (*value=='1' || *value=='t')) {
+ // If the new option to enable buggy rengotiation is available, set it.
+ // Otherwise, signal false if this is newer than 0.9.8k, because that
+ // means it's 0.9.8l, which blocks renegotiation, and therefore will
+ // not honor this request. Older versions are buggy, so behave as though
+ // the flag was set anyway, so we signal true.
+#if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
+ m_openssl_ops |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+ return true;
+#elif (OPENSSL_VERSION_NUMBER > 0x009080bfL)
+ return false;
+#else
+ return true;
+#endif
+ }
+ return false;
+ }
+ else if (strcmp(provider, "CURL")) {
+ return false;
+ }
+
+ // For libcurl, the option is an enum and the value type depends on the option.
+ CURLoption opt = static_cast<CURLoption>(strtol(option, NULL, 10));
+ if (opt < CURLOPTTYPE_OBJECTPOINT)
+ return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK);
+#ifdef CURLOPTTYPE_OFF_T
+ else if (opt < CURLOPTTYPE_OFF_T) {
+ if (value)
+ m_saved_options.push_back(value);
+ return (curl_easy_setopt(m_handle, opt, value ? m_saved_options.back().c_str() : NULL) == CURLE_OK);
+ }
+# ifdef HAVE_CURL_OFF_T
+ else if (sizeof(curl_off_t) == sizeof(long))
+ return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK);
+# else
+ else if (sizeof(off_t) == sizeof(long))
+ return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK);
+# endif
+ return false;
+#else
+ else {
+ if (value)
+ m_saved_options.push_back(value);
+ return (curl_easy_setopt(m_handle, opt, value ? m_saved_options.back().c_str() : NULL) == CURLE_OK);
+ }
+#endif
+}
+
const vector<string>& CURLSOAPTransport::getResponseHeader(const char* name) const
{
static vector<string> emptyVector;
{
CURLSOAPTransport* conf = reinterpret_cast<CURLSOAPTransport*>(userptr);
- // Manually disable SSLv2 so we're not dependent on libcurl to do it.
+ // Default flags manually disable SSLv2 so we're not dependent on libcurl to do it.
// Also disable the ticket option where implemented, since this breaks a variety
// of servers. Newer libcurl also does this for us.
#ifdef SSL_OP_NO_TICKET
- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET);
+ SSL_CTX_set_options(ssl_ctx, conf->m_openssl_ops|SSL_OP_NO_TICKET);
#else
- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
+ SSL_CTX_set_options(ssl_ctx, conf->m_openssl_ops);
#endif
#ifndef XMLTOOLING_NO_XMLSEC
using namespace std;
namespace {
- static const XMLCh _CURL[] = UNICODE_LITERAL_4(C,U,R,L);
+ static const XMLCh _CURL[] = UNICODE_LITERAL_4(C,U,R,L);
+ static const XMLCh _OpenSSL[] = UNICODE_LITERAL_7(O,p,e,n,S,S,L);
static const XMLCh _option[] = UNICODE_LITERAL_6(o,p,t,i,o,n);
static const XMLCh _provider[] = UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);
static const XMLCh TransportOption[] = UNICODE_LITERAL_15(T,r,a,n,s,p,o,r,t,O,p,t,i,o,n);
// callback to invoke a caller-defined SSL callback
CURLcode ssl_ctx_callback(CURL* curl, SSL_CTX* ssl_ctx, void* userptr)
{
- // Manually disable SSLv2 so we're not dependent on libcurl to do it.
+ CurlURLInputStream* str = reinterpret_cast<CurlURLInputStream*>(userptr);
+
+ // Default flags manually disable SSLv2 so we're not dependent on libcurl to do it.
// Also disable the ticket option where implemented, since this breaks a variety
// of servers. Newer libcurl also does this for us.
#ifdef SSL_OP_NO_TICKET
- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET);
+ SSL_CTX_set_options(ssl_ctx, str->getOpenSSLOps()|SSL_OP_NO_TICKET);
#else
- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
+ SSL_CTX_set_options(ssl_ctx, str->getOpenSSLOps());
#endif
return CURLE_OK;
CurlURLInputStream::CurlURLInputStream(const char* url, string* cacheTag)
: fLog(logging::Category::getInstance(XMLTOOLING_LOGCAT".libcurl.InputStream"))
, fCacheTag(cacheTag)
+ , fOpenSSLOps(SSL_OP_ALL|SSL_OP_NO_SSLv2)
, fURL(url ? url : "")
, fMulti(0)
, fEasy(0)
CurlURLInputStream::CurlURLInputStream(const XMLCh* url, string* cacheTag)
: fLog(logging::Category::getInstance(XMLTOOLING_LOGCAT".libcurl.InputStream"))
, fCacheTag(cacheTag)
+ , fOpenSSLOps(SSL_OP_ALL|SSL_OP_NO_SSLv2)
, fMulti(0)
, fEasy(0)
, fHeaders(0)
CurlURLInputStream::CurlURLInputStream(const DOMElement* e, string* cacheTag)
: fLog(logging::Category::getInstance(XMLTOOLING_LOGCAT".libcurl.InputStream"))
, fCacheTag(cacheTag)
+ , fOpenSSLOps(SSL_OP_ALL|SSL_OP_NO_SSLv2)
, fMulti(0)
, fEasy(0)
, fHeaders(0)
// Install SSL callback.
curl_easy_setopt(fEasy, CURLOPT_SSL_CTX_FUNCTION, ssl_ctx_callback);
+ curl_easy_setopt(fEasy, CURLOPT_SSL_CTX_DATA, this);
fError[0] = 0;
curl_easy_setopt(fEasy, CURLOPT_ERRORBUFFER, fError);
bool success;
DOMElement* child = XMLHelper::getLastChildElement(e, TransportOption);
while (child) {
- if (child->hasChildNodes() && XMLString::equals(child->getAttributeNS(NULL,_provider), _CURL)) {
+ if (child->hasChildNodes() && XMLString::equals(child->getAttributeNS(NULL,_provider), _OpenSSL)) {
+ auto_ptr_char option(child->getAttributeNS(NULL,_option));
+ auto_ptr_char value(child->getFirstChild()->getNodeValue());
+ if (option.get() && value.get() && !strcmp(option.get(), "SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION") &&
+ (*value.get()=='1' || *value.get()=='t')) {
+ // If the new option to enable buggy rengotiation is available, set it.
+ // Otherwise, signal false if this is newer than 0.9.8k, because that
+ // means it's 0.9.8l, which blocks renegotiation, and therefore will
+ // not honor this request. Older versions are buggy, so behave as though
+ // the flag was set anyway, so we signal true.
+#if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
+ fOpenSSLOps |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+ success = true;
+#elif (OPENSSL_VERSION_NUMBER > 0x009080bfL)
+ success = false;
+#else
+ success = true;
+#endif
+ }
+ else {
+ success = false;
+ }
+ if (!success)
+ fLog.error("failed to set OpenSSL transport option (%s)", option.get());
+ }
+ else if (child->hasChildNodes() && XMLString::equals(child->getAttributeNS(NULL,_provider), _CURL)) {
auto_ptr_char option(child->getAttributeNS(NULL,_option));
auto_ptr_char value(child->getFirstChild()->getNodeValue());
if (option.get() && *option.get() && value.get() && *value.get()) {
}
#endif
if (!success)
- fLog.error("failed to set transport option (%s)", option.get());
+ fLog.error("failed to set CURL transport option (%s)", option.get());
}
}
child = XMLHelper::getPreviousSiblingElement(child, TransportOption);