VS10 solution files, convert from NULL macro to nullptr.
[shibboleth/sp.git] / shibsp / handler / impl / SessionInitiator.cpp
1 /*
2  *  Copyright 2001-2010 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  * SessionInitiator.cpp
19  * 
20  * Pluggable runtime functionality that handles initiating sessions.
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "SPRequest.h"
26 #include "handler/SessionInitiator.h"
27
28 using namespace shibsp;
29 using namespace xmltooling;
30 using namespace std;
31
32 namespace shibsp {
33     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory ChainingSessionInitiatorFactory;
34     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory Shib1SessionInitiatorFactory;
35     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory SAML2SessionInitiatorFactory;
36     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory WAYFSessionInitiatorFactory;
37     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory SAMLDSSessionInitiatorFactory;
38     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory TransformSessionInitiatorFactory;
39     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory FormSessionInitiatorFactory;
40     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory CookieSessionInitiatorFactory;
41 };
42
43 map<string,string> SessionInitiator::m_remapper;
44
45 void SHIBSP_API shibsp::registerSessionInitiators()
46 {
47     SPConfig& conf=SPConfig::getConfig();
48     conf.SessionInitiatorManager.registerFactory(CHAINING_SESSION_INITIATOR, ChainingSessionInitiatorFactory);
49     conf.SessionInitiatorManager.registerFactory(SHIB1_SESSION_INITIATOR, Shib1SessionInitiatorFactory);
50     conf.SessionInitiatorManager.registerFactory(SAML2_SESSION_INITIATOR, SAML2SessionInitiatorFactory);
51     conf.SessionInitiatorManager.registerFactory(WAYF_SESSION_INITIATOR, WAYFSessionInitiatorFactory);
52     conf.SessionInitiatorManager.registerFactory(SAMLDS_SESSION_INITIATOR, SAMLDSSessionInitiatorFactory);
53     conf.SessionInitiatorManager.registerFactory(TRANSFORM_SESSION_INITIATOR, TransformSessionInitiatorFactory);
54     conf.SessionInitiatorManager.registerFactory(FORM_SESSION_INITIATOR, FormSessionInitiatorFactory);
55     conf.SessionInitiatorManager.registerFactory(COOKIE_SESSION_INITIATOR, CookieSessionInitiatorFactory);
56
57     SessionInitiator::m_remapper["defaultACSIndex"] = "acsIndex";
58 }
59
60 SessionInitiator::SessionInitiator()
61 {
62 }
63
64 SessionInitiator::~SessionInitiator()
65 {
66 }
67
68 #ifndef SHIBSP_LITE
69 const char* SessionInitiator::getType() const
70 {
71     return "SessionInitiator";
72 }
73 #endif
74
75 const set<string>& SessionInitiator::getSupportedOptions() const
76 {
77     return m_supportedOptions;
78 }
79
80 bool SessionInitiator::checkCompatibility(SPRequest& request, bool isHandler) const
81 {
82     bool isPassive = false;
83     if (isHandler) {
84         const char* flag = request.getParameter("isPassive");
85         if (flag) {
86             isPassive = (*flag=='1' || *flag=='t');
87         }
88         else {
89             pair<bool,bool> flagprop = getBool("isPassive");
90             isPassive = (flagprop.first && flagprop.second);
91         }
92     }
93     else {
94         // It doesn't really make sense to use isPassive with automated sessions, but...
95         pair<bool,bool> flagprop = request.getRequestSettings().first->getBool("isPassive");
96         if (!flagprop.first)
97             flagprop = getBool("isPassive");
98         isPassive = (flagprop.first && flagprop.second);
99     }
100
101     // Check for support of isPassive if it's used.
102     if (isPassive && getSupportedOptions().count("isPassive") == 0) {
103         if (getParent()) {
104             log(SPRequest::SPInfo, "handler does not support isPassive option");
105             return false;
106         }
107         throw ConfigurationException("Unsupported option (isPassive) supplied to SessionInitiator.");
108     }
109
110     return true;
111 }
112
113 pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
114 {
115     const char* entityID = nullptr;
116     pair<bool,const char*> param = getString("entityIDParam");
117     if (isHandler) {
118         entityID = request.getParameter(param.first ? param.second : "entityID");
119         if (!param.first && (!entityID || !*entityID))
120             entityID=request.getParameter("providerId");
121     }
122     if (!entityID || !*entityID) {
123         param = request.getRequestSettings().first->getString("entityID");
124         if (param.first)
125             entityID = param.second;
126     }
127     if (!entityID || !*entityID)
128         entityID = getString("entityID").second;
129
130     string copy(entityID ? entityID : "");
131
132     try {
133         return run(request, copy, isHandler);
134     }
135     catch (exception& ex) {
136         // If it's a handler operation, and isPassive is used or returnOnError is set, we trap the error.
137         if (isHandler) {
138             bool returnOnError = false;
139             const char* flag = request.getParameter("isPassive");
140             if (flag && (*flag == 't' || *flag == '1')) {
141                 returnOnError = true;
142             }
143             else {
144                 pair<bool,bool> flagprop = getBool("isPassive");
145                 if (flagprop.first && flagprop.second) {
146                     returnOnError = true;
147                 }
148                 else {
149                     flag = request.getParameter("returnOnError");
150                     if (flag) {
151                         returnOnError = (*flag=='1' || *flag=='t');
152                     }
153                     else {
154                         flagprop = getBool("returnOnError");
155                         returnOnError = (flagprop.first && flagprop.second);
156                     }
157                 }
158             }
159
160             if (returnOnError) {
161                 // Log it and attempt to recover relay state so we can get back.
162                 log(SPRequest::SPError, ex.what());
163                 log(SPRequest::SPInfo, "trapping SessionInitiator error condition and returning to target location");
164                 flag = request.getParameter("target");
165                 string target(flag ? flag : "");
166                 recoverRelayState(request.getApplication(), request, request, target, false);
167                 return make_pair(true, request.sendRedirect(target.c_str()));
168             }
169         }
170         throw;
171     }
172 }