2 * Copyright 2001-2010 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 * Handler for dumping information about an active session.
24 #include "Application.h"
25 #include "exceptions.h"
26 #include "ServiceProvider.h"
27 #include "SessionCache.h"
28 #include "SPRequest.h"
29 #include "attribute/Attribute.h"
30 #include "handler/AbstractHandler.h"
34 using namespace shibsp;
35 using namespace xmltooling;
40 #if defined (_MSC_VER)
41 #pragma warning( push )
42 #pragma warning( disable : 4250 )
45 class SHIBSP_DLLLOCAL Blocker : public DOMNodeFilter
48 #ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
53 acceptNode(const DOMNode* node) const {
58 static SHIBSP_DLLLOCAL Blocker g_Blocker;
60 class SHIBSP_API SessionHandler : public AbstractHandler
63 SessionHandler(const DOMElement* e, const char* appId);
64 virtual ~SessionHandler() {}
66 pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
73 #if defined (_MSC_VER)
74 #pragma warning( pop )
77 Handler* SHIBSP_DLLLOCAL SessionHandlerFactory(const pair<const DOMElement*,const char*>& p)
79 return new SessionHandler(p.first, p.second);
84 SessionHandler::SessionHandler(const DOMElement* e, const char* appId)
85 : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionHandler"), &g_Blocker), m_values(false)
87 pair<bool,const char*> acl = getString("acl");
89 string aclbuf=acl.second;
91 for (unsigned int i=0; i < aclbuf.length(); i++) {
92 if (aclbuf.at(i)==' ') {
93 m_acl.insert(aclbuf.substr(j, i-j));
97 m_acl.insert(aclbuf.substr(j, aclbuf.length()-j));
100 pair<bool,bool> flag = getBool("showAttributeValues");
102 m_values = flag.second;
105 pair<bool,long> SessionHandler::run(SPRequest& request, bool isHandler) const
107 if (!m_acl.empty() && m_acl.count(request.getRemoteAddr()) == 0) {
108 m_log.error("session handler request blocked from invalid address (%s)", request.getRemoteAddr().c_str());
109 istringstream msg("Session Handler Blocked");
110 return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
114 s << "<html><head><title>Session Summary</title></head><body><pre>" << endl;
116 Session* session = nullptr;
118 session = request.getSession();
120 s << "A valid session was not found.</pre></body></html>" << endl;
121 request.setContentType("text/html");
122 request.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
123 request.setResponseHeader("Cache-Control","private,no-store,no-cache");
124 return make_pair(true, request.sendResponse(s));
127 catch (exception& ex) {
128 s << "Exception while retrieving active session:" << endl
129 << '\t' << ex.what() << "</pre></body></html>" << endl;
130 request.setContentType("text/html");
131 request.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
132 request.setResponseHeader("Cache-Control","private,no-store,no-cache");
133 return make_pair(true, request.sendResponse(s));
136 s << "<u>Miscellaneous</u>" << endl;
138 s << "<strong>Client Address:</strong> " << (session->getClientAddress() ? session->getClientAddress() : "(none)") << endl;
139 s << "<strong>Identity Provider:</strong> " << (session->getEntityID() ? session->getEntityID() : "(none)") << endl;
140 s << "<strong>SSO Protocol:</strong> " << (session->getProtocol() ? session->getProtocol() : "(none)") << endl;
141 s << "<strong>Authentication Time:</strong> " << (session->getAuthnInstant() ? session->getAuthnInstant() : "(none)") << endl;
142 s << "<strong>Authentication Context Class:</strong> " << (session->getAuthnContextClassRef() ? session->getAuthnContextClassRef() : "(none)") << endl;
143 s << "<strong>Authentication Context Decl:</strong> " << (session->getAuthnContextDeclRef() ? session->getAuthnContextDeclRef() : "(none)") << endl;
144 s << "<strong>Session Expiration (barring inactivity):</strong> ";
145 if (session->getExpiration())
146 s << ((session->getExpiration() - time(nullptr)) / 60) << " minute(s)" << endl;
148 s << "Infinite" << endl;
150 s << endl << "<u>Attributes</u>" << endl;
153 vector<string>::size_type count=0;
154 const multimap<string,const Attribute*>& attributes = session->getIndexedAttributes();
155 for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a) {
156 if (a->first != key) {
157 if (a != attributes.begin()) {
161 s << count << " value(s)" << endl;
165 s << "<strong>" << a->first << "</strong>: ";
169 const vector<string>& vals = a->second->getSerializedValues();
170 for (vector<string>::const_iterator v = vals.begin(); v!=vals.end(); ++v) {
171 if (v != vals.begin() || a->first == key)
173 string::size_type pos = v->find_first_of(';',string::size_type(0));
174 if (pos!=string::npos) {
176 for (; pos != string::npos; pos = value.find_first_of(';',pos)) {
177 value.insert(pos, "\\");
188 count += a->second->getSerializedValues().size();
192 if (!m_values && !attributes.empty())
193 s << count << " value(s)" << endl;
195 s << "</pre></body></html>";
196 request.setContentType("text/html; charset=UTF-8");
197 request.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
198 request.setResponseHeader("Cache-Control","private,no-store,no-cache");
199 return make_pair(true, request.sendResponse(s));