2 * Copyright 2001-2007 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 * Base class for handlers based on a DOMPropertySet.
24 #include "Application.h"
25 #include "exceptions.h"
26 #include "SPRequest.h"
27 #include "handler/AbstractHandler.h"
29 #include <saml/saml1/core/Protocols.h>
30 #include <saml/saml2/core/Protocols.h>
31 #include <saml/util/SAMLConstants.h>
32 #include <xmltooling/XMLToolingConfig.h>
33 #include <xmltooling/util/URLEncoder.h>
35 using namespace shibsp;
36 using namespace samlconstants;
37 using namespace opensaml;
38 using namespace xmltooling;
39 using namespace xercesc;
43 SHIBSP_DLLLOCAL PluginManager<Handler,const DOMElement*>::Factory SAML1ConsumerFactory;
46 void SHIBSP_API shibsp::registerHandlers()
48 SPConfig& conf=SPConfig::getConfig();
49 conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);
50 conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);
53 AbstractHandler::AbstractHandler(
54 const DOMElement* e, log4cpp::Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
56 load(e,log,filter,remapper);
59 void AbstractHandler::checkError(const XMLObject* response) const
61 const saml2p::StatusResponseType* r2 = dynamic_cast<const saml2p::StatusResponseType*>(response);
63 const saml2p::Status* status = r2->getStatus();
65 const saml2p::StatusCode* sc = status->getStatusCode();
66 const XMLCh* code = sc ? sc->getValue() : NULL;
67 if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {
68 FatalProfileException ex("SAML Response message contained an error.");
69 auto_ptr_char c1(code);
70 ex.addProperty("StatusCode", c1.get());
71 if (sc->getStatusCode()) {
72 code = sc->getStatusCode()->getValue();
73 auto_ptr_char c2(code);
74 ex.addProperty("StatusCode2", c2.get());
76 if (status->getStatusMessage()) {
77 auto_ptr_char msg(status->getStatusMessage()->getMessage());
78 ex.addProperty("StatusMessage", msg.get());
84 const saml1p::Response* r1 = dynamic_cast<const saml1p::Response*>(response);
86 const saml1p::Status* status = r1->getStatus();
88 const saml1p::StatusCode* sc = status->getStatusCode();
89 const QName* code = sc ? sc->getValue() : NULL;
90 if (code && *code != saml1p::StatusCode::SUCCESS) {
91 FatalProfileException ex("SAML Response message contained an error.");
92 ex.addProperty("StatusCode", code->toString().c_str());
93 if (sc->getStatusCode()) {
94 code = sc->getStatusCode()->getValue();
96 ex.addProperty("StatusCode2", code->toString().c_str());
98 if (status->getStatusMessage()) {
99 auto_ptr_char msg(status->getStatusMessage()->getMessage());
100 ex.addProperty("StatusMessage", msg.get());
107 void AbstractHandler::recoverRelayState(HTTPRequest& httpRequest, string& relayState) const
109 SPConfig& conf = SPConfig::getConfig();
110 if (conf.isEnabled(SPConfig::OutOfProcess)) {
111 // Out of process, we look for StorageService-backed state.
112 // TODO: something like ss:SSID:key?
115 if (conf.isEnabled(SPConfig::InProcess)) {
116 // In process, we should be able to cast down to a full SPRequest.
117 SPRequest& request = dynamic_cast<SPRequest&>(httpRequest);
118 if (relayState.empty() || relayState == "cookie") {
119 // Pull the value from the "relay state" cookie.
120 pair<string,const char*> relay_cookie = request.getApplication().getCookieNameProps("_shibstate_");
121 const char* state = request.getCookie(relay_cookie.first.c_str());
122 if (state && *state) {
123 // URL-decode the value.
124 char* rscopy=strdup(state);
125 XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);
130 request.setCookie(relay_cookie.first.c_str(),relay_cookie.second);
133 relayState = "default"; // fall through...
136 // Check for "default" value.
137 if (relayState == "default") {
138 pair<bool,const char*> homeURL=request.getApplication().getString("homeURL");
139 relayState=homeURL.first ? homeURL.second : "/";