X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=shibsp%2Fhandler%2Fimpl%2FRemotedHandler.cpp;h=272f6671697d720f1973bb294ceb0531c7c30b9b;hb=a0af8ed86ab481af4605daf5cf837fdaa4544bdd;hp=a4a88aed873994ca840d7c84ac9c346787d62d44;hpb=7ca3247bfb360f7f0e0829ca904ba6c2bbfd0581;p=shibboleth%2Fsp.git diff --git a/shibsp/handler/impl/RemotedHandler.cpp b/shibsp/handler/impl/RemotedHandler.cpp index a4a88ae..272f667 100644 --- a/shibsp/handler/impl/RemotedHandler.cpp +++ b/shibsp/handler/impl/RemotedHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Internet2 + * Copyright 2001-2010 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,15 +22,18 @@ #include "internal.h" #include "exceptions.h" +#include "Application.h" +#include "GSSRequest.h" #include "ServiceProvider.h" +#include "SPRequest.h" #include "handler/RemotedHandler.h" #include -#include #include +#include #ifndef SHIBSP_LITE -# include +# include "util/CGIParser.h" # include # include # include @@ -40,28 +43,49 @@ using namespace shibsp; using namespace opensaml; using namespace xmltooling; -using namespace log4cpp; using namespace xercesc; using namespace std; #ifndef SHIBSP_LITE namespace shibsp { - class SHIBSP_DLLLOCAL RemotedRequest : public virtual HTTPRequest + class SHIBSP_DLLLOCAL RemotedRequest : +#ifdef HAVE_GSSAPI + public GSSRequest, +#endif + public HTTPRequest { DDF& m_input; mutable CGIParser* m_parser; mutable vector m_certs; +#ifdef HAVE_GSSAPI + mutable gss_ctx_id_t m_gss; +#endif public: - RemotedRequest(DDF& input) : m_input(input), m_parser(NULL) {} + RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr) +#ifdef HAVE_GSSAPI + , m_gss(GSS_C_NO_CONTEXT) +#endif + { + } + virtual ~RemotedRequest() { for_each(m_certs.begin(), m_certs.end(), xmltooling::cleanup()); delete m_parser; +#ifdef HAVE_GSSAPI + if (m_gss != GSS_C_NO_CONTEXT) { + OM_uint32 minor; + gss_delete_sec_context(&minor, &m_gss, GSS_C_NO_BUFFER); + } +#endif } // GenericRequest const char* getScheme() const { return m_input["scheme"].string(); } + bool isSecure() const { + return HTTPRequest::isSecure(); + } const char* getHostname() const { return m_input["hostname"].string(); } @@ -93,6 +117,11 @@ namespace shibsp { const std::vector& getClientCertificates() const; +#ifdef HAVE_GSSAPI + // GSSRequest + gss_ctx_id_t getGSSContext() const; +#endif + // HTTPRequest const char* getMethod() const { return m_input["method"].string(); @@ -134,7 +163,7 @@ const char* RemotedRequest::getParameter(const char* name) const m_parser=new CGIParser(*this); pair bounds=m_parser->getParameters(name); - return (bounds.first==bounds.second) ? NULL : bounds.first->second; + return (bounds.first==bounds.second) ? nullptr : bounds.first->second; } std::vector::size_type RemotedRequest::getParameters(const char* name, std::vector& values) const @@ -153,11 +182,15 @@ std::vector::size_type RemotedRequest::getParameters(const char* na const std::vector& RemotedRequest::getClientCertificates() const { if (m_certs.empty()) { - DDF cert = m_input["certificates"].first(); - while (cert.isstring()) { + DDF certs = m_input["certificates"]; + DDF cert = certs.first(); + while (cert.string()) { try { auto_ptr x509(XSECPlatformUtils::g_cryptoProvider->X509()); - x509->loadX509Base64Bin(cert.string(), cert.strlen()); + if (strstr(cert.string(), "BEGIN")) + x509->loadX509PEM(cert.string(), cert.strlen()); + else + x509->loadX509Base64Bin(cert.string(), cert.strlen()); m_certs.push_back(x509.release()); } catch(XSECException& e) { @@ -167,12 +200,40 @@ const std::vector& RemotedRequest::getClientCertificates() cons catch(XSECCryptoException& e) { Category::getInstance(SHIBSP_LOGCAT".SPRequest").error("XML-Security exception loading client certificate: %s", e.getMsg()); } - cert = cert.next(); + cert = certs.next(); } } return m_certs; } +#ifdef HAVE_GSSAPI +gss_ctx_id_t RemotedRequest::getGSSContext() const +{ + if (m_gss == GSS_C_NO_CONTEXT) { + const char* encoded = m_input["gss_context"].string(); + if (encoded) { + xsecsize_t x; + XMLByte* decoded=Base64::decode(reinterpret_cast(encoded), &x); + if (decoded) { + gss_buffer_desc importbuf; + importbuf.length = x; + importbuf.value = decoded; + OM_uint32 minor; + OM_uint32 major = gss_import_sec_context(&minor, &importbuf, &m_gss); + if (major != GSS_S_COMPLETE) + m_gss = GSS_C_NO_CONTEXT; +#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE + XMLString::release(&decoded); +#else + XMLString::release((char**)&decoded); +#endif + } + } + } + return m_gss; +} +#endif + long RemotedResponse::sendResponse(std::istream& in, long status) { string msg; @@ -194,15 +255,16 @@ void RemotedResponse::setResponseHeader(const char* name, const char* value) m_output.structure(); DDF hdrs = m_output["headers"]; if (hdrs.isnull()) - hdrs = m_output.addmember("headers").structure(); - hdrs.addmember(name).string(value); + hdrs = m_output.addmember("headers").list(); + DDF h = DDF(name).string(value); + hdrs.add(h); } long RemotedResponse::sendRedirect(const char* url) { if (!m_output.isstruct()) m_output.structure(); - m_output.addmember("redirect").string(url); + m_output.addmember("redirect").unsafe_string(url); return HTTPResponse::XMLTOOLING_HTTP_STATUS_MOVED; } @@ -214,7 +276,7 @@ void RemotedHandler::setAddress(const char* address) throw ConfigurationException("Cannot register a remoting address twice for the same Handler."); m_address = address; SPConfig& conf = SPConfig::getConfig(); - if (conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) { + if (!conf.isEnabled(SPConfig::InProcess)) { ListenerService* listener = conf.getServiceProvider()->getListenerService(false); if (listener) listener->regListener(m_address.c_str(),this); @@ -223,6 +285,12 @@ void RemotedHandler::setAddress(const char* address) } } +set RemotedHandler::m_remotedHeaders; + +RemotedHandler::RemotedHandler() +{ +} + RemotedHandler::~RemotedHandler() { SPConfig& conf = SPConfig::getConfig(); @@ -231,11 +299,17 @@ RemotedHandler::~RemotedHandler() listener->unregListener(m_address.c_str(),this); } +void RemotedHandler::addRemotedHeader(const char* header) +{ + m_remotedHeaders.insert(header); +} + DDF RemotedHandler::wrap(const SPRequest& request, const vector* headers, bool certs) const { DDF in = DDF(m_address.c_str()).structure(); + in.addmember("application_id").string(request.getApplication().getId()); in.addmember("scheme").string(request.getScheme()); - in.addmember("hostname").string(request.getHostname()); + in.addmember("hostname").unsafe_string(request.getHostname()); in.addmember("port").integer(request.getPort()); in.addmember("content_type").string(request.getContentType().c_str()); in.addmember("content_length").integer(request.getContentLength()); @@ -243,17 +317,24 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector* headers in.addmember("remote_user").string(request.getRemoteUser().c_str()); in.addmember("client_addr").string(request.getRemoteAddr().c_str()); in.addmember("method").string(request.getMethod()); - in.addmember("uri").string(request.getRequestURI()); - in.addmember("url").string(request.getRequestURL()); + in.addmember("uri").unsafe_string(request.getRequestURI()); + in.addmember("url").unsafe_string(request.getRequestURL()); in.addmember("query").string(request.getQueryString()); - if (headers) { + if (headers || !m_remotedHeaders.empty()) { string hdr; DDF hin = in.addmember("headers").structure(); - for (vector::const_iterator h = headers->begin(); h!=headers->end(); ++h) { - hdr = request.getHeader(h->c_str()); + if (headers) { + for (vector::const_iterator h = headers->begin(); h!=headers->end(); ++h) { + hdr = request.getHeader(h->c_str()); + if (!hdr.empty()) + hin.addmember(h->c_str()).unsafe_string(hdr.c_str()); + } + } + for (set::const_iterator hh = m_remotedHeaders.begin(); hh != m_remotedHeaders.end(); ++hh) { + hdr = request.getHeader(hh->c_str()); if (!hdr.empty()) - hin.addmember(h->c_str()).string(hdr.c_str()); + hin.addmember(hh->c_str()).unsafe_string(hdr.c_str()); } } @@ -263,7 +344,7 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector* headers if (!xvec.empty()) { DDF clist = in.addmember("certificates").list(); for (vector::const_iterator x = xvec.begin(); x!=xvec.end(); ++x) { - DDF x509 = DDF(NULL).string((*x)->getDEREncodingSB().rawCharBuffer()); + DDF x509 = DDF(nullptr).string((*x)->getDEREncodingSB().rawCharBuffer()); clist.add(x509); } } @@ -272,23 +353,64 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector* headers if (!xvec.empty()) { DDF clist = in.addmember("certificates").list(); for (vector::const_iterator x = xvec.begin(); x!=xvec.end(); ++x) { - DDF x509 = DDF(NULL).string(x->c_str()); + DDF x509 = DDF(nullptr).string(x->c_str()); clist.add(x509); } } #endif } +#ifdef HAVE_GSSAPI + const GSSRequest* gss = dynamic_cast(&request); + if (gss) { + gss_ctx_id_t ctx = gss->getGSSContext(); + if (ctx != GSS_C_NO_CONTEXT) { + OM_uint32 minor; + gss_buffer_desc contextbuf; + contextbuf.length = 0; + contextbuf.value = nullptr; + OM_uint32 major = gss_export_sec_context(&minor, &ctx, &contextbuf); + if (major == GSS_S_COMPLETE) { + xsecsize_t len=0; + XMLByte* out=Base64::encode(reinterpret_cast(contextbuf.value), contextbuf.length, &len); + if (out) { + string ctx; + ctx.append(reinterpret_cast(out), len); +#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE + XMLString::release(&out); +#else + XMLString::release((char**)&out); +#endif + in.addmember("gss_context").string(ctx.c_str()); + } + else { + request.log(SPRequest::SPError, "error while base64-encoding GSS context"); + } + } + else { + request.log(SPRequest::SPError, "error while exporting GSS context"); + } + } + } +#endif + return in; } pair RemotedHandler::unwrap(SPRequest& request, DDF& out) const { DDF h = out["headers"]; - h = h.first(); - while (h.isstring()) { - request.setResponseHeader(h.name(), h.string()); - h = h.next(); + DDF hdr = h.first(); + while (hdr.isstring()) { +#ifdef HAVE_STRCASECMP + if (!strcasecmp(hdr.name(), "Content-Type")) +#else + if (!stricmp(hdr.name(), "Content-Type")) +#endif + request.setContentType(hdr.string()); + else + request.setResponseHeader(hdr.name(), hdr.string()); + hdr = h.next(); } h = out["redirect"]; if (h.isstring()) @@ -298,7 +420,7 @@ pair RemotedHandler::unwrap(SPRequest& request, DDF& out) const istringstream s(h["data"].string()); return make_pair(true, request.sendResponse(s, h["status"].integer())); } - return make_pair(false,0); + return make_pair(false,0L); } HTTPRequest* RemotedHandler::getRequest(DDF& in) const