2 * Copyright (c) 2010, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright 2001-2009 Internet2
35 * Licensed under the Apache License, Version 2.0 (the "License");
36 * you may not use this file except in compliance with the License.
37 * You may obtain a copy of the License at
39 * http://www.apache.org/licenses/LICENSE-2.0
41 * Unless required by applicable law or agreed to in writing, software
42 * distributed under the License is distributed on an "AS IS" BASIS,
43 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44 * See the License for the specific language governing permissions and
45 * limitations under the License.
48 #include <gssapi/gssapi.h>
49 #include <gssapi/gssapi_ext.h>
52 #include <shibsp/Application.h>
53 #include <shibsp/exceptions.h>
54 #include <shibsp/SPConfig.h>
55 #include <shibsp/ServiceProvider.h>
56 #include <shibsp/attribute/Attribute.h>
57 #include <shibsp/attribute/resolver/ResolutionContext.h>
58 #include <shibsp/handler/AssertionConsumerService.h>
59 #include <shibsp/metadata/MetadataProviderCriteria.h>
60 #include <shibsp/util/SPConstants.h>
62 #include <saml/saml1/core/Assertions.h>
63 #include <saml/saml2/core/Assertions.h>
64 #include <saml/saml2/metadata/Metadata.h>
65 #include <xercesc/util/XMLUniDefs.hpp>
66 #include <xmltooling/XMLToolingConfig.h>
67 #include <xmltooling/util/XMLHelper.h>
69 using namespace shibsp;
70 using namespace opensaml::saml2md;
71 using namespace opensaml;
72 using namespace xmltooling::logging;
73 using namespace xmltooling;
74 using namespace xercesc;
77 class GSSEAPResolver : public shibsp::AssertionConsumerService
80 GSSEAPResolver(const DOMElement *e, const char *appId)
81 : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT".GSSEAPResolver")) {
83 virtual ~GSSEAPResolver() {}
85 ResolutionContext* resolveAttributes (
86 const Application& application,
87 const RoleDescriptor* issuer,
88 const XMLCh* protocol,
89 const saml1::NameIdentifier* v1nameid,
90 const saml2::NameID* nameid,
91 const XMLCh* authncontext_class,
92 const XMLCh* authncontext_decl,
93 const vector<const Assertion*>* tokens
95 return shibsp::AssertionConsumerService::resolveAttributes(
96 application, issuer, protocol, v1nameid,
97 nameid, authncontext_class, authncontext_decl, tokens
102 void implementProtocol(
103 const Application& application,
104 const HTTPRequest& httpRequest,
105 HTTPResponse& httpResponse,
106 SecurityPolicy& policy,
107 const PropertySet* settings,
108 const XMLObject& xmlObject
110 throw FatalProfileException("Should never be called.");
114 class SHIBSP_DLLLOCAL DummyContext : public ResolutionContext
117 DummyContext(const vector<Attribute*>& attributes) : m_attributes(attributes) {
120 virtual ~DummyContext() {
121 for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<Attribute>());
124 vector<Attribute*>& getResolvedAttributes() {
127 vector<Assertion*>& getResolvedAssertions() {
132 vector<Attribute*> m_attributes;
133 static vector<Assertion*> m_tokens; // never any tokens, so just share an empty vector
136 struct eap_gss_saml_attr_ctx {
137 ResolutionContext *resCtx;
138 gss_buffer_desc assertion;
142 samlAllocAttrContext(OM_uint32 *minor,
143 struct eap_gss_saml_attr_ctx **pCtx)
145 struct eap_gss_saml_attr_ctx *ctx;
147 ctx = (struct eap_gss_saml_attr_ctx *)GSSEAP_CALLOC(1, sizeof(*ctx));
150 return GSS_S_FAILURE;
155 return GSS_S_COMPLETE;
159 samlImportAssertion(OM_uint32 *minor,
161 saml2::Assertion **pAssertion)
167 const XMLObjectBuilder *b;
170 string samlBuf((char *)buffer->value, buffer->length);
171 istringstream samlIn(samlBuf);
173 doc = XMLToolingConfig::getConfig().getParser().parse(samlIn);
174 b = XMLObjectBuilder::getDefaultBuilder();
175 elem = doc->getDocumentElement();
176 xobj = b->buildOneFromElement(elem, true);
178 *pAssertion = dynamic_cast<saml2::Assertion *>(xobj);
179 if (*pAssertion == NULL) {
180 /* TODO minor_status */
181 return GSS_S_BAD_NAME;
183 } catch (exception &e){
184 /* TODO minor_status */
185 return GSS_S_BAD_NAME;
189 return GSS_S_COMPLETE;
193 samlDuplicateAttrContext(OM_uint32 *minor,
194 const struct eap_gss_saml_attr_ctx *in,
195 struct eap_gss_saml_attr_ctx **out)
197 OM_uint32 major, tmpMinor;
198 struct eap_gss_saml_attr_ctx *ctx;
200 major = samlAllocAttrContext(minor, &ctx);
201 if (GSS_ERROR(major))
204 major = duplicateBuffer(minor, (gss_buffer_t)&in->assertion, &ctx->assertion);
205 if (GSS_ERROR(major))
208 ctx->resCtx = new DummyContext(in->resCtx->getResolvedAttributes());
211 if (GSS_ERROR(major))
212 samlReleaseAttrContext(&tmpMinor, &ctx);
218 samlReleaseAttrContext(OM_uint32 *minor,
219 struct eap_gss_saml_attr_ctx **pCtx)
221 struct eap_gss_saml_attr_ctx *ctx = *pCtx;
225 gss_release_buffer(minor, &ctx->assertion);
231 return GSS_S_COMPLETE;
235 samlCreateAttrContext(OM_uint32 *minor,
237 gss_name_t acceptorName,
238 struct eap_gss_saml_attr_ctx **pCtx)
240 OM_uint32 major, tmpMinor;
241 struct eap_gss_saml_attr_ctx *ctx;
242 SPConfig &conf = SPConfig::getConfig();
244 const Application *app;
246 gss_buffer_desc nameBuf;
247 const XMLCh *issuer = NULL;
248 saml2::NameID *subjectName = NULL;
249 saml2::Assertion *assertion;
252 nameBuf.value = NULL;
254 conf.setFeatures(SPConfig::Metadata |
256 SPConfig::AttributeResolution |
257 SPConfig::Credentials |
258 SPConfig::OutOfProcess);
260 return GSS_S_FAILURE;
261 if (!conf.instantiate())
262 return GSS_S_FAILURE;
264 sp = conf.getServiceProvider();
267 major = gss_display_name(minor, acceptorName, &nameBuf, NULL);
268 if (GSS_ERROR(major))
271 app = sp->getApplication((const char *)nameBuf.value);
273 major = GSS_S_FAILURE;
277 major = samlAllocAttrContext(minor, &ctx);
278 if (GSS_ERROR(major))
281 major = duplicateBuffer(minor, buffer, &ctx->assertion);
282 if (GSS_ERROR(major))
285 major = samlImportAssertion(minor, &ctx->assertion, &assertion);
286 if (GSS_ERROR(major))
289 if (assertion->getIssuer() != NULL)
290 issuer = assertion->getIssuer()->getName();
291 if (assertion->getSubject() != NULL)
292 subjectName = assertion->getSubject()->getNameID();
295 m = app->getMetadataProvider();
296 xmltooling::Locker mlocker(m);
297 MetadataProviderCriteria mc(*app, issuer,
298 &IDPSSODescriptor::ELEMENT_QNAME,
299 samlconstants::SAML20P_NS);
300 pair<const EntityDescriptor *, const RoleDescriptor *> site =
301 m->getEntityDescriptor(mc);
303 auto_ptr_char temp(issuer);
304 throw MetadataException("Unable to locate metadata for IdP ($1).",
305 params(1,temp.get()));
307 vector<const Assertion*> tokens(1, assertion);
308 GSSEAPResolver gssResolver(NULL, (const char *)nameBuf.value);
309 ctx->resCtx = gssResolver.resolveAttributes(*app, site.second,
310 samlconstants::SAML20P_NS,
311 NULL, subjectName, NULL,
313 } catch (exception &ex) {
314 major = GSS_S_BAD_NAME;
318 major = GSS_S_COMPLETE;
325 if (GSS_ERROR(major))
326 samlReleaseAttrContext(&tmpMinor, &ctx);
327 gss_release_buffer(&tmpMinor, &nameBuf);
333 samlGetAttributeTypes(OM_uint32 *minor,
334 const struct eap_gss_saml_attr_ctx *ctx,
336 OM_uint32 (*addAttribute)(OM_uint32 *, void *, gss_buffer_t))
338 OM_uint32 major = GSS_S_COMPLETE;
341 return GSS_S_COMPLETE;
343 for (vector<Attribute*>::const_iterator a = ctx->resCtx->getResolvedAttributes().begin();
344 a != ctx->resCtx->getResolvedAttributes().end();
347 gss_buffer_desc attribute;
349 attribute.value = (void *)((*a)->getId());
350 attribute.length = strlen((char *)attribute.value);
352 major = addAttribute(minor, data, &attribute);
353 if (GSS_ERROR(major))
361 samlGetAttribute(OM_uint32 *minor,
362 const struct eap_gss_saml_attr_ctx *ctx,
367 gss_buffer_t display_value,
371 Attribute *shibAttr = NULL;
375 return GSS_S_UNAVAILABLE;
377 for (vector<Attribute *>::const_iterator a = ctx->resCtx->getResolvedAttributes().begin();
378 a != ctx->resCtx->getResolvedAttributes().end();
380 for (vector<string>::const_iterator s = (*a)->getAliases().begin();
381 s != (*a)->getAliases().end();
383 if (attr->length == strlen((*s).c_str()) &&
384 memcmp((*s).c_str(), attr->value, attr->length) == 0) {
389 if (shibAttr != NULL)
393 if (shibAttr == NULL)
394 return GSS_S_UNAVAILABLE;
398 } else if (*more >= (int)shibAttr->valueCount()) {
400 return GSS_S_COMPLETE;
403 buf.value = (void *)shibAttr->getString(*more);
404 buf.length = strlen((char *)buf.value);
406 major = duplicateBuffer(minor, &buf, value);
407 if (GSS_ERROR(major))
410 *authenticated = TRUE;
413 return GSS_S_COMPLETE;
417 samlSetAttribute(OM_uint32 *minor,
418 struct eap_gss_saml_attr_ctx *ctx,
423 return GSS_S_UNAVAILABLE;
427 samlGetAssertion(OM_uint32 *minor,
428 struct eap_gss_saml_attr_ctx *ctx,
432 return GSS_S_UNAVAILABLE;
434 return duplicateBuffer(minor, &ctx->assertion, buffer);
438 samlExportAttrContext(OM_uint32 *minor,
439 struct eap_gss_saml_attr_ctx *ctx,
442 GSSEAP_NOT_IMPLEMENTED;
446 samlImportAttrContext(OM_uint32 *minor,
448 struct eap_gss_saml_attr_ctx **ppCtx)
450 GSSEAP_NOT_IMPLEMENTED;