X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fsoap%2Fimpl%2FCURLSOAPTransport.cpp;h=190d6a1a0e86f24c9445a4121838250bda73d047;hb=b168e43df6ae57e2eb28c83eea08eb48e6543daf;hp=796b313a60a913cdae1e752c3be62c8ab6fd967b;hpb=c68e81d839b97f0c936100b6330cc8a817ff6530;p=shibboleth%2Fxmltooling.git diff --git a/xmltooling/soap/impl/CURLSOAPTransport.cpp b/xmltooling/soap/impl/CURLSOAPTransport.cpp index 796b313..190d6a1 100644 --- a/xmltooling/soap/impl/CURLSOAPTransport.cpp +++ b/xmltooling/soap/impl/CURLSOAPTransport.cpp @@ -22,6 +22,7 @@ #include "internal.h" #include "exceptions.h" +#include "logging.h" #include "security/CredentialCriteria.h" #include "security/OpenSSLTrustEngine.h" #include "security/OpenSSLCredential.h" @@ -32,11 +33,10 @@ #include #include -#include #include +using namespace xmltooling::logging; using namespace xmltooling; -using namespace log4cpp; using namespace std; namespace xmltooling { @@ -49,8 +49,8 @@ namespace xmltooling { m_log(Category::getInstance(XMLTOOLING_LOGCAT".SOAPTransport.CURLPool")) {} ~CURLPool(); - CURL* get(const char* to, const char* endpoint); - void put(const char* to, const char* endpoint, CURL* handle); + CURL* get(const SOAPTransport::Address& addr); + void put(const char* from, const char* to, const char* endpoint, CURL* handle); private: typedef map > poolmap_t; @@ -66,18 +66,20 @@ namespace xmltooling { class XMLTOOL_DLLLOCAL CURLSOAPTransport : public HTTPSOAPTransport, public OpenSSLSOAPTransport { public: - CURLSOAPTransport(const char* peerName, const char* endpoint) - : m_peerName(peerName ? peerName : ""), m_endpoint(endpoint), m_handle(NULL), m_headers(NULL), + CURLSOAPTransport(const Address& addr) + : m_sender(addr.m_from ? addr.m_from : ""), m_peerName(addr.m_to ? addr.m_to : ""), m_endpoint(addr.m_endpoint), + m_handle(NULL), m_headers(NULL), #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_secure(false) { - m_handle = g_CURLPool->get(peerName, endpoint); - curl_easy_setopt(m_handle,CURLOPT_URL,endpoint); + m_ssl_callback(NULL), m_ssl_userptr(NULL), m_chunked(true), m_authenticated(false) { + m_handle = g_CURLPool->get(addr); + curl_easy_setopt(m_handle,CURLOPT_URL,addr.m_endpoint); curl_easy_setopt(m_handle,CURLOPT_CONNECTTIMEOUT,15); curl_easy_setopt(m_handle,CURLOPT_TIMEOUT,30); curl_easy_setopt(m_handle,CURLOPT_HTTPAUTH,0); curl_easy_setopt(m_handle,CURLOPT_USERPWD,NULL); + curl_easy_setopt(m_handle,CURLOPT_SSL_VERIFYHOST,2); curl_easy_setopt(m_handle,CURLOPT_HEADERDATA,this); m_headers=curl_slist_append(m_headers,"Content-Type: text/xml"); } @@ -85,8 +87,8 @@ namespace xmltooling { virtual ~CURLSOAPTransport() { curl_slist_free_all(m_headers); curl_easy_setopt(m_handle,CURLOPT_ERRORBUFFER,NULL); - curl_easy_setopt(m_handle,CURLOPT_PRIVATE,m_secure ? "secure" : NULL); // Save off security "state". - g_CURLPool->put(m_peerName.c_str(), m_endpoint.c_str(), m_handle); + curl_easy_setopt(m_handle,CURLOPT_PRIVATE,m_authenticated ? "secure" : NULL); // Save off security "state". + g_CURLPool->put(m_sender.c_str(), m_peerName.c_str(), m_endpoint.c_str(), m_handle); } bool isConfidential() const { @@ -103,6 +105,10 @@ namespace xmltooling { bool setAuth(transport_auth_t authType, const char* username=NULL, const char* password=NULL); + bool setVerifyHost(bool verify) { + return (curl_easy_setopt(m_handle,CURLOPT_SSL_VERIFYHOST,verify ? 2 : 0)==CURLE_OK); + } + #ifndef XMLTOOLING_NO_XMLSEC bool setCredential(const Credential* cred=NULL) { const OpenSSLCredential* down = dynamic_cast(cred); @@ -141,18 +147,32 @@ namespace xmltooling { 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(strtol(option, NULL, 10)); + if (opt < CURLOPTTYPE_OBJECTPOINT) + return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK); + else if (opt < CURLOPTTYPE_OFF_T) + return (curl_easy_setopt(m_handle, opt, value) == CURLE_OK); + else if (sizeof(curl_off_t) == sizeof(long)) + return (curl_easy_setopt(m_handle, opt, strtol(value, NULL, 10)) == CURLE_OK); + return false; + } + void send(istream& in); istream& receive() { return m_stream; } - bool isSecure() const { - return m_secure; + bool isAuthenticated() const { + return m_authenticated; } - void setSecure(bool secure) { - m_secure = secure; + void setAuthenticated(bool auth) { + m_authenticated = auth; } string getContentType() const; @@ -174,7 +194,7 @@ namespace xmltooling { private: // per-call state - string m_peerName,m_endpoint,m_simplecreds; + string m_sender,m_peerName,m_endpoint,m_simplecreds; CURL* m_handle; stringstream m_stream; struct curl_slist* m_headers; @@ -189,7 +209,7 @@ namespace xmltooling { ssl_ctx_callback_fn m_ssl_callback; void* m_ssl_userptr; bool m_chunked; - bool m_secure; + bool m_authenticated; friend size_t XMLTOOL_DLLLOCAL curl_header_hook(void* ptr, size_t size, size_t nmemb, void* stream); friend CURLcode XMLTOOL_DLLLOCAL xml_ssl_ctx_callback(CURL* curl, SSL_CTX* ssl_ctx, void* userptr); @@ -206,9 +226,9 @@ namespace xmltooling { int XMLTOOL_DLLLOCAL verify_callback(X509_STORE_CTX* x509_ctx, void* arg); #endif - SOAPTransport* CURLSOAPTransportFactory(const pair& dest) + SOAPTransport* CURLSOAPTransportFactory(const SOAPTransport::Address& addr) { - return new CURLSOAPTransport(dest.first, dest.second); + return new CURLSOAPTransport(addr); } }; @@ -239,14 +259,19 @@ CURLPool::~CURLPool() delete m_lock; } -CURL* CURLPool::get(const char* to, const char* endpoint) +CURL* CURLPool::get(const SOAPTransport::Address& addr) { #ifdef _DEBUG xmltooling::NDC("get"); #endif - m_log.debug("getting connection handle to %s", endpoint); + m_log.debug("getting connection handle to %s", addr.m_endpoint); + string key(addr.m_endpoint); + if (addr.m_from) + key = key + '|' + addr.m_from; + if (addr.m_to) + key = key + '|' + addr.m_to; m_lock->lock(); - poolmap_t::iterator i=m_bindingMap.find(string(to) + "|" + endpoint); + poolmap_t::iterator i=m_bindingMap.find(key); if (i!=m_bindingMap.end()) { // Move this pool to the front of the list. @@ -274,10 +299,10 @@ CURL* CURLPool::get(const char* to, const char* endpoint) curl_easy_setopt(handle,CURLOPT_NOPROGRESS,1); curl_easy_setopt(handle,CURLOPT_NOSIGNAL,1); curl_easy_setopt(handle,CURLOPT_FAILONERROR,1); - curl_easy_setopt(handle,CURLOPT_SSLVERSION,3); + curl_easy_setopt(handle,CURLOPT_SSLVERSION,CURL_SSLVERSION_SSLv3); + curl_easy_setopt(handle,CURLOPT_SSL_CIPHER_LIST,"ALL:!aNULL:!LOW:!EXPORT:!SSLv2"); // Verification of the peer is via TrustEngine only. curl_easy_setopt(handle,CURLOPT_SSL_VERIFYPEER,0); - curl_easy_setopt(handle,CURLOPT_SSL_VERIFYHOST,2); curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,&curl_header_hook); curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,&curl_write_hook); curl_easy_setopt(handle,CURLOPT_DEBUGFUNCTION,&curl_debug_hook); @@ -285,9 +310,13 @@ CURL* CURLPool::get(const char* to, const char* endpoint) return handle; } -void CURLPool::put(const char* to, const char* endpoint, CURL* handle) +void CURLPool::put(const char* from, const char* to, const char* endpoint, CURL* handle) { - string key = string(to) + "|" + endpoint; + string key(endpoint); + if (from) + key = key + '|' + from; + if (to) + key = key + '|' + to; m_lock->lock(); poolmap_t::iterator i=m_bindingMap.find(key); if (i==m_bindingMap.end()) @@ -412,7 +441,11 @@ void CURLSOAPTransport::send(istream& in) // Set request headers. curl_easy_setopt(m_handle,CURLOPT_HTTPHEADER,m_headers); +#ifndef XMLTOOLING_NO_XMLSEC if (m_ssl_callback || m_cred || m_trustEngine) { +#else + if (m_ssl_callback) { +#endif curl_easy_setopt(m_handle,CURLOPT_SSL_CTX_FUNCTION,xml_ssl_ctx_callback); curl_easy_setopt(m_handle,CURLOPT_SSL_CTX_DATA,this); @@ -421,7 +454,7 @@ void CURLSOAPTransport::send(istream& in) char* priv=NULL; curl_easy_getinfo(m_handle,CURLINFO_PRIVATE,&priv); if (priv) - m_secure=true; + m_authenticated=true; } else { curl_easy_setopt(m_handle,CURLOPT_SSL_CTX_FUNCTION,NULL); @@ -487,9 +520,8 @@ int xmltooling::curl_debug_hook(CURL* handle, curl_infotype type, char* data, si // *ptr is actually a logging object if (!ptr) return 0; CategoryStream log=reinterpret_cast(ptr)->debugStream(); - for (char* ch=data; len && (isprint(*ch) || isspace(*ch)); len--) + for (unsigned char* ch=(unsigned char*)data; len && (isprint(*ch) || isspace(*ch)); len--) log << *ch++; - log << CategoryStream::ENDLINE; return 0; } @@ -529,12 +561,12 @@ int xmltooling::verify_callback(X509_STORE_CTX* x509_ctx, void* arg) if (!success) { log.error("supplied TrustEngine failed to validate SSL/TLS server certificate"); x509_ctx->error=X509_V_ERR_APPLICATION_VERIFICATION; // generic error, check log for plugin specifics - ctx->setSecure(false); + ctx->setAuthenticated(false); return ctx->m_mandatory ? 0 : 1; } // Signal success. Hopefully it doesn't matter what's actually in the structure now. - ctx->setSecure(true); + ctx->setAuthenticated(true); return 1; } #endif