/*
- * 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.
* You may obtain a copy of the License at
/**
* StatusHandler.cpp
- *
+ *
* Handler for exposing information about the internals of the SP.
*/
#include "Application.h"
#include "exceptions.h"
#include "ServiceProvider.h"
+#include "SPRequest.h"
#include "handler/AbstractHandler.h"
#include "handler/RemotedHandler.h"
#include "util/CGIParser.h"
+#include <xmltooling/version.h>
+#include <xmltooling/util/DateTime.h>
+
+#ifdef HAVE_SYS_UTSNAME_H
+# include <sys/utsname.h>
+#endif
+
using namespace shibsp;
#ifndef SHIBSP_LITE
# include "SessionCache.h"
+# include "metadata/MetadataProviderCriteria.h"
# include <saml/version.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/security/CredentialCriteria.h>
using namespace opensaml::saml2md;
using namespace opensaml;
using namespace xmlsignature;
class SHIBSP_DLLLOCAL Blocker : public DOMNodeFilter
{
public:
- short acceptNode(const DOMNode* node) const {
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
+ short
+#else
+ FilterAction
+#endif
+ acceptNode(const DOMNode* node) const {
return FILTER_REJECT;
}
};
private:
pair<bool,long> processMessage(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse) const;
+ ostream& systemInfo(ostream& os) const;
set<string> m_acl;
};
vector<string> g_NoCerts;
#endif
+ static char _x2c(const char *what)
+ {
+ register char digit;
+
+ digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
+ digit *= 16;
+ digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
+ return(digit);
+ }
+
class DummyRequest : public HTTPRequest
{
public:
- DummyRequest(const char* url) : m_parser(NULL), m_url(url), m_scheme(NULL), m_query(NULL), m_port(0) {
+ DummyRequest(const char* url) : m_parser(nullptr), m_url(url), m_scheme(nullptr), m_query(nullptr), m_port(0) {
#ifdef HAVE_STRCASECMP
if (url && !strncasecmp(url,"http://",7)) {
m_scheme="http";
else {
m_hostname.assign(url, slash - url);
}
- m_uri = slash;
+
+ while (*slash) {
+ if (*slash == '?') {
+ m_uri += slash;
+ break;
+ }
+ else if (*slash != '%') {
+ m_uri += *slash;
+ }
+ else {
+ ++slash;
+ if (!isxdigit(*slash) || !isxdigit(*(slash+1)))
+ throw invalid_argument("Bad request, contained unsupported encoded characters.");
+ m_uri += _x2c(slash);
+ ++slash;
+ }
+ ++slash;
+ }
}
~DummyRequest() {
return "";
}
const char* getRequestBody() const {
- return NULL;
+ return nullptr;
}
const char* getQueryString() const {
return m_query;
{
if (!m_parser)
m_parser=new CGIParser(*this);
-
+
pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
- return (bounds.first==bounds.second) ? NULL : bounds.first->second;
+ return (bounds.first==bounds.second) ? nullptr : bounds.first->second;
}
vector<const char*>::size_type getParameters(const char* name, vector<const char*>& values) const
{
#ifndef XMLTOOLING_NO_XMLSEC
std::vector<XSECCryptoX509*>&
#else
- std::vector<std::string>&
+ std::vector<std::string>&
#endif
getClientCertificates() const {
return g_NoCerts;
map<string,const char*> props;
settings.first->getAll(props);
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
request.setContentType("text/xml");
stringstream msg;
- msg << "<StatusHandler>";
+ msg << "<StatusHandler time='" << timestamp.get() << "'>";
msg << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
#ifndef SHIBSP_LITE
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
#endif
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- msg << "<RequestSettings";
+ systemInfo(msg) << "<RequestSettings";
for (map<string,const char*>::const_iterator p = props.begin(); p != props.end(); ++p)
msg << ' ' << p->first << "='" << p->second << "'";
msg << '>' << target << "</RequestSettings>";
msg << "</StatusHandler>";
return make_pair(true,request.sendResponse(msg));
}
-
+
try {
if (conf.isEnabled(SPConfig::OutOfProcess)) {
// When out of process, we run natively and directly process the message.
else {
// When not out of process, we remote all the message processing.
DDF out,in = wrap(request);
- DDFJanitor jin(in), jout(out);
+ DDFJanitor jin(in), jout(out);
out=request.getServiceProvider().getListenerService()->send(in);
return unwrap(request, out);
}
}
catch (XMLToolingException& ex) {
m_log.error("error while processing request: %s", ex.what());
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
request.setContentType("text/xml");
stringstream msg;
- msg << "<StatusHandler>";
+ msg << "<StatusHandler time='" << timestamp.get() << "'>";
msg << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
#ifndef SHIBSP_LITE
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
#endif
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- msg << "<Status><Exception type='" << ex.getClassName() << "'>" << ex.what() << "</Exception></Status>";
+ systemInfo(msg) << "<Status><Exception type='" << ex.getClassName() << "'>" << ex.what() << "</Exception></Status>";
msg << "</StatusHandler>";
return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
}
catch (exception& ex) {
m_log.error("error while processing request: %s", ex.what());
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
request.setContentType("text/xml");
stringstream msg;
- msg << "<StatusHandler>";
+ msg << "<StatusHandler time='" << timestamp.get() << "'>";
msg << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
#ifndef SHIBSP_LITE
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
#endif
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- msg << "<Status><Exception type='std::exception'>" << ex.what() << "</Exception></Status>";
+ systemInfo(msg) << "<Status><Exception type='std::exception'>" << ex.what() << "</Exception></Status>";
msg << "</StatusHandler>";
return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
}
{
// Find application.
const char* aid=in["application_id"].string();
- const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : NULL;
+ const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
if (!app) {
// Something's horribly wrong.
m_log.error("couldn't find application (%s) for status request", aid ? aid : "(missing)");
throw ConfigurationException("Unable to locate application for status request, deleted?");
}
-
+
// Wrap a response shim.
- DDF ret(NULL);
+ DDF ret(nullptr);
DDFJanitor jout(ret);
auto_ptr<HTTPRequest> req(getRequest(in));
auto_ptr<HTTPResponse> resp(getResponse(ret));
-
+
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
// which we capture in the facade and send back.
#ifndef SHIBSP_LITE
m_log.debug("processing status request");
+ DateTime now(time(nullptr));
+ now.parseDateTime();
+ auto_ptr_char timestamp(now.getFormattedString());
+
stringstream s;
- s << "<StatusHandler>";
+ s << "<StatusHandler time='" << timestamp.get() << "'>";
const char* status = "<OK/>";
s << "<Version Xerces-C='" << XERCES_FULLVERSIONDOT
+ << "' XML-Tooling-C='" << XMLTOOLING_FULLVERSIONDOT
<< "' XML-Security-C='" << XSEC_FULLVERSIONDOT
<< "' OpenSAML-C='" << OPENSAML_FULLVERSIONDOT
<< "' Shibboleth='" << PACKAGE_VERSION << "'/>";
- const char* param = NULL;
+ systemInfo(s);
+
+ const char* param = nullptr;
if (param) {
}
else {
status = "<Partial/>";
}
- s << "<Application id='" << application.getId() << "' entityID='" << application.getString("entityID").second << "'/>";
+ const PropertySet* relyingParty=nullptr;
+ param=httpRequest.getParameter("entityID");
+ if (param) {
+ MetadataProvider* m = application.getMetadataProvider();
+ Locker mlock(m);
+ relyingParty = application.getRelyingParty(m->getEntityDescriptor(MetadataProviderCriteria(application, param)).first);
+ }
+ else {
+ relyingParty = &application;
+ }
+
+ s << "<Application id='" << application.getId() << "' entityID='" << relyingParty->getString("entityID").second << "'/>";
s << "<Handlers>";
vector<const Handler*> handlers;
}
s << "</Handlers>";
- const PropertySet* relyingParty=NULL;
- param=httpRequest.getParameter("entityID");
- if (param) {
- Locker mlock(application.getMetadataProvider());
- relyingParty = application.getRelyingParty(application.getMetadataProvider()->getEntityDescriptor(param));
- }
- if (!relyingParty)
- relyingParty = application.getRelyingParty(NULL);
CredentialResolver* credResolver=application.getCredentialResolver();
if (credResolver) {
Locker credLocker(credResolver);
httpResponse.setContentType("text/xml");
return make_pair(true, httpResponse.sendResponse(s));
#else
- return make_pair(false,0);
+ return make_pair(false,0L);
+#endif
+}
+
+#ifdef WIN32
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+#endif
+
+ostream& StatusHandler::systemInfo(ostream& os) const
+{
+#if defined(HAVE_SYS_UTSNAME_H)
+ struct utsname sysinfo;
+ if (uname(&sysinfo) == 0) {
+ os << "<NonWindows";
+ if (*sysinfo.sysname)
+ os << " sysname='" << sysinfo.sysname << "'";
+ if (*sysinfo.nodename)
+ os << " nodename='" << sysinfo.nodename << "'";
+ if (*sysinfo.release)
+ os << " release='" << sysinfo.release << "'";
+ if (*sysinfo.version)
+ os << " version='" << sysinfo.version << "'";
+ if (*sysinfo.machine)
+ os << " machine='" << sysinfo.machine << "'";
+ os << "/>";
+ }
+#elif defined(WIN32)
+ OSVERSIONINFOEX osvi;
+ memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if(GetVersionEx((OSVERSIONINFO*)&osvi)) {
+ os << "<Windows"
+ << " version='" << osvi.dwMajorVersion << "." << osvi.dwMinorVersion << "'"
+ << " build='" << osvi.dwBuildNumber << "'";
+ if (osvi.wServicePackMajor > 0)
+ os << " servicepack='" << osvi.wServicePackMajor << "." << osvi.wServicePackMinor << "'";
+ switch (osvi.wProductType) {
+ case VER_NT_WORKSTATION:
+ os << " producttype='Workstation'";
+ break;
+ case VER_NT_SERVER:
+ case VER_NT_DOMAIN_CONTROLLER:
+ os << " producttype='Server'";
+ break;
+ }
+
+ SYSTEM_INFO si;
+ memset(&si, 0, sizeof(SYSTEM_INFO));
+ PGNSI pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
+ if(pGNSI)
+ pGNSI(&si);
+ else
+ GetSystemInfo(&si);
+ switch (si.dwProcessorType) {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ os << " arch='i386'";
+ break;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ os << " arch='x86_64'";
+ break;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ os << " arch='IA64'";
+ break;
+ }
+ os << " cpucount='" << si.dwNumberOfProcessors << "'";
+
+ MEMORYSTATUSEX ms;
+ memset(&ms, 0, sizeof(MEMORYSTATUSEX));
+ ms.dwLength = sizeof(MEMORYSTATUSEX);
+ if (GlobalMemoryStatusEx(&ms)) {
+ os << " memory='" << (ms.ullTotalPhys / (1024 * 1024)) << "M'";
+ }
+
+ os << "/>";
+ }
#endif
+ return os;
}