Move token validation into SAML library, first draft SAML 1 SSO handler.
[shibboleth/sp.git] / shibsp / handler / impl / AbstractHandler.cpp
1 /*
2  *  Copyright 2001-2007 Internet2
3  * 
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * AbstractHandler.cpp
19  * 
20  * Base class for handlers based on a DOMPropertySet. 
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "handler/AbstractHandler.h"
26
27 #include <saml/saml1/core/Protocols.h>
28 #include <saml/saml2/core/Protocols.h>
29 #include <saml/util/SAMLConstants.h>
30
31 using namespace shibsp;
32 using namespace samlconstants;
33 using namespace opensaml;
34 using namespace xmltooling;
35 using namespace xercesc;
36 using namespace std;
37
38 namespace shibsp {
39     SHIBSP_DLLLOCAL PluginManager<Handler,const DOMElement*>::Factory SAML1ConsumerFactory;
40 };
41
42 void SHIBSP_API shibsp::registerHandlers()
43 {
44     SPConfig& conf=SPConfig::getConfig();
45     conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);
46     conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);
47 }
48
49 AbstractHandler::AbstractHandler(
50     const DOMElement* e, log4cpp::Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
51     ) : m_log(log) {
52     load(e,log,filter,remapper);
53 }
54
55 void AbstractHandler::checkError(const XMLObject* response) const
56 {
57     const saml2p::StatusResponseType* r2 = dynamic_cast<const saml2p::StatusResponseType*>(response);
58     if (r2) {
59         const saml2p::Status* status = r2->getStatus();
60         if (status) {
61             const saml2p::StatusCode* sc = status->getStatusCode();
62             const XMLCh* code = sc ? sc->getValue() : NULL;
63             if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {
64                 FatalProfileException ex("SAML Response message contained an error.");
65                 auto_ptr_char c1(code);
66                 ex.addProperty("code", c1.get());
67                 if (sc->getStatusCode()) {
68                     code = sc->getStatusCode()->getValue();
69                     auto_ptr_char c2(code);
70                     ex.addProperty("code2", c2.get());
71                 }
72                 if (status->getStatusMessage()) {
73                     auto_ptr_char msg(status->getStatusMessage()->getMessage());
74                     ex.addProperty("message", msg.get());
75                 }
76             }
77         }
78     }
79
80     const saml1p::Response* r1 = dynamic_cast<const saml1p::Response*>(response);
81     if (r1) {
82         const saml1p::Status* status = r1->getStatus();
83         if (status) {
84             const saml1p::StatusCode* sc = status->getStatusCode();
85             const QName* code = sc ? sc->getValue() : NULL;
86             if (code && *code != saml1p::StatusCode::SUCCESS) {
87                 FatalProfileException ex("SAML Response message contained an error.");
88                 ex.addProperty("code", code->toString().c_str());
89                 if (sc->getStatusCode()) {
90                     code = sc->getStatusCode()->getValue();
91                     if (code)
92                         ex.addProperty("code2", code->toString().c_str());
93                 }
94                 if (status->getStatusMessage()) {
95                     auto_ptr_char msg(status->getStatusMessage()->getMessage());
96                     ex.addProperty("message", msg.get());
97                 }
98             }
99         }
100     }
101 }