2 * shib-rpcerror.cpp -- RPC Error class
4 * Created by: Derek Atkins <derek@ihtfp.com>
13 #include "shib-target.h"
19 #include <log4cpp/Category.hh>
22 using namespace shibtarget;
23 using namespace shibboleth;
29 const type_info* type_MalformedException = NULL;
30 const type_info* type_UnsupportedExtensionException = NULL;
31 const type_info* type_InvalidCryptoException = NULL;
32 const type_info* type_TrustException = NULL;
33 const type_info* type_BindingException = NULL;
34 const type_info* type_SOAPException = NULL;
35 const type_info* type_ContentTypeException = NULL;
37 const type_info* type_ProfileException = NULL;
38 const type_info* type_FatalProfileException = NULL;
39 const type_info* type_RetryableProfileException = NULL;
40 const type_info* type_ExpiredAssertionException = NULL;
41 const type_info* type_InvalidAssertionException = NULL;
42 const type_info* type_ReplayedAssertionException = NULL;
44 const XMLCh code_InvalidHandle[] = // InvalidHandle
45 { chLatin_I, chLatin_n, chLatin_v, chLatin_a, chLatin_l, chLatin_i, chLatin_d,
46 chLatin_H, chLatin_a, chLatin_n, chLatin_d, chLatin_l, chLatin_e,
51 void rpcerror_init (void)
61 type_MalformedException = &typeid(MalformedException);
62 type_UnsupportedExtensionException = &typeid(UnsupportedExtensionException);
63 type_InvalidCryptoException = &typeid(InvalidCryptoException);
64 type_TrustException = &typeid(TrustException);
65 type_BindingException = &typeid(BindingException);
66 type_SOAPException = &typeid(SOAPException);
67 type_ContentTypeException = &typeid(ContentTypeException);
69 type_ProfileException = &typeid(ProfileException);
70 type_FatalProfileException = &typeid(FatalProfileException);
71 type_RetryableProfileException = &typeid(RetryableProfileException);
72 type_ExpiredAssertionException = &typeid(ExpiredAssertionException);
73 type_InvalidAssertionException = &typeid(InvalidAssertionException);
74 type_ReplayedAssertionException = &typeid(ReplayedAssertionException);
79 #define TEST_TYPE(type,str) { if (type && *type == info) return str; }
80 const char* rpcerror_exception_type(SAMLException* e)
83 return "Invalid (NULL) exception";
85 const type_info& info = typeid(*e);
87 TEST_TYPE(type_MalformedException, "Exception: XML object is malformed");
88 TEST_TYPE(type_UnsupportedExtensionException,
89 "Exception: an unsupported extention was accessed");
90 TEST_TYPE(type_InvalidCryptoException, "Exception: cryptographic check failed");
91 TEST_TYPE(type_TrustException, "Exception: trust failed");
92 TEST_TYPE(type_BindingException,
93 "Exception: an error occurred in binding to the AA");
94 TEST_TYPE(type_SOAPException, "Exception: SOAP error");
95 TEST_TYPE(type_ContentTypeException, "Exception: Content Type Failure");
97 TEST_TYPE(type_ProfileException, "Exception: Profile Error");
98 TEST_TYPE(type_FatalProfileException, "Exception: Fatal Profile Error");
99 TEST_TYPE(type_RetryableProfileException, "Exception: Retryable Profile Error");
100 TEST_TYPE(type_ExpiredAssertionException, "Exception: Expired Assertion");
101 TEST_TYPE(type_InvalidAssertionException, "Exception: Invalid Assertion");
102 TEST_TYPE(type_ReplayedAssertionException, "Exception: Replayed Assertion");
104 return "Unknown SAML Exception";
108 class shibtarget::RPCErrorPriv {
110 RPCErrorPriv(int stat, const char* msg, const XMLCh* originSite);
116 SAMLException* except;
119 RPCErrorPriv::RPCErrorPriv(int stat, const char* msg, const XMLCh* originSite)
122 string ctx = "shibtarget.RPCErrorPriv";
123 log4cpp::Category& log = log4cpp::Category::getInstance(ctx);
127 if (originSite) origin = originSite;
129 if (status == SHIBRPC_SAML_EXCEPTION) {
130 istringstream estr(msg);
133 except = SAMLException::getInstance(estr);
134 } catch (SAMLException& e) {
135 log.error ("Caught SAML Exception while building the SAMLException: %s",
137 log.error ("XML: %s", msg);
138 } catch (XMLException& e) {
139 log.error ("Caught XML Exception building SAMLException: %s",
141 log.error ("XML: %s", msg);
143 log.error ("Caught exception building SAMLException!");
144 log.error ("XML: %s", msg);
146 if (dynaptr(ContentTypeException, except)!=NULL)
148 "We were unable to contact your identity provider and cannot grant "
149 "access at this time. Please contact your provider's help desk or "
150 "administrator so that the appropriate steps can be taken. "
151 "Be sure to describe what you're trying to access and useful "
152 "context like the current time.";
154 error_msg = (except ? except->what() : msg);
161 RPCErrorPriv::~RPCErrorPriv()
167 RPCError::RPCError(ShibRpcError* error)
169 if (!error || !error->status)
172 auto_ptr<XMLCh> origin(XMLString::transcode(error->ShibRpcError_u.e.origin));
173 init(error->status, error->ShibRpcError_u.e.error, origin.get());
177 void RPCError::init(int stat, char const* msg, const XMLCh* origin)
179 m_priv = new RPCErrorPriv(stat,msg,origin);
182 RPCError::~RPCError()
187 bool RPCError::isError() { return (m_priv->status != 0); }
189 #define TEST_TYPE(type) { if (type && *type == info) return true; }
190 bool RPCError::isRetryable()
192 switch (m_priv->status) {
193 case SHIBRPC_NO_SESSION:
194 case SHIBRPC_SESSION_EXPIRED:
197 case SHIBRPC_SAML_EXCEPTION:
198 if (m_priv->except) {
199 const type_info& info = typeid(*m_priv->except);
201 TEST_TYPE(type_RetryableProfileException);
202 TEST_TYPE(type_ExpiredAssertionException);
204 Iterator<saml::QName> codes = m_priv->except->getCodes();
205 while (codes.hasNext()) {
206 saml::QName name = codes.next();
208 if (!XMLString::compareString(name.getNamespaceURI(),
209 shibboleth::XML::SHIB_NS)) {
210 if (!XMLString::compareString(name.getLocalName(), code_InvalidHandle)) {
224 const char* RPCError::getType()
226 switch (m_priv->status) {
227 case SHIBRPC_OK: return "No Error";
228 case SHIBRPC_UNKNOWN_ERROR: return "Unknown error";
229 case SHIBRPC_INTERNAL_ERROR: return "Internal Error";
230 case SHIBRPC_XML_EXCEPTION: return "Xerces XML Exception";
231 case SHIBRPC_SAX_EXCEPTION: return "Xerces SAX Exception";
232 case SHIBRPC_SAML_EXCEPTION: return rpcerror_exception_type(m_priv->except);
234 case SHIBRPC_NO_SESSION: return "No Session";
235 case SHIBRPC_SESSION_EXPIRED: return "Session Expired";
236 case SHIBRPC_IPADDR_MISMATCH: return "IP Address Mismatch";
238 case SHIBRPC_IPADDR_MISSING: return "IP Address Missing";
239 case SHIBRPC_RESPONSE_MISSING: return "SAML Response Missing";
240 case SHIBRPC_ASSERTION_REPLAYED: return "SAML Assertion Replayed";
241 default: return "Unknown Shibboleth RPC error";
245 const char* RPCError::getText()
247 return m_priv->error_msg.c_str();
250 const char* RPCError::getDesc()
252 if (m_priv->except) {
253 Iterator<saml::QName> i=m_priv->except->getCodes();
255 XMLString::compareString(L(Responder),i.next().getLocalName()))
257 "An error occurred at the target system while processing your request";
259 return "An error occurred at your origin site while processing your request";
261 return "An error occurred processing your request";
264 int RPCError::getCode() { return m_priv->status; }
266 const char* RPCError::getOriginErrorURL()
268 const char* res="No URL Available";
269 if (!m_priv->origin.empty())
271 OriginSiteMapper mapper;
272 res=mapper.getErrorURL(m_priv->origin.c_str());
277 const char* RPCError::getOriginContactName()
279 const char* res="No Name Available";
280 if (!m_priv->origin.empty())
282 OriginSiteMapper mapper;
283 Iterator<const IContactInfo*> i=mapper.getContacts(m_priv->origin.c_str());
286 const IContactInfo* c=i.next();
287 if (c->getType()==IContactInfo::technical)
297 const char* RPCError::getOriginContactEmail()
299 const char* res="No Email Available";
300 if (!m_priv->origin.empty())
302 OriginSiteMapper mapper;
303 Iterator<const IContactInfo*> i=mapper.getContacts(m_priv->origin.c_str());
306 const IContactInfo* c=i.next();
307 if (c->getType()==IContactInfo::technical)