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 #include "gssapiP_eap.h"
37 #include <xercesc/util/XMLUniDefs.hpp>
38 #include <xmltooling/XMLToolingConfig.h>
39 #include <xmltooling/util/XMLHelper.h>
41 #include <saml/saml1/core/Assertions.h>
42 #include <saml/saml2/core/Assertions.h>
43 #include <saml/saml2/metadata/Metadata.h>
45 using namespace xmltooling;
46 using namespace opensaml::saml2md;
47 using namespace opensaml;
48 using namespace xercesc;
52 * gss_eap_saml_assertion_provider is for retrieving the underlying
56 gss_eap_saml_assertion_provider::initFromExistingContext(const gss_eap_attr_ctx *manager,
57 const gss_eap_attr_provider *ctx)
59 /* Then we may be creating from an existing attribute context */
60 const gss_eap_saml_assertion_provider *saml;
62 assert(m_assertion == NULL);
64 if (!gss_eap_attr_provider::initFromExistingContext(manager, ctx))
67 saml = static_cast<const gss_eap_saml_assertion_provider *>(ctx);
68 setAssertion(saml->getAssertion());
74 gss_eap_saml_assertion_provider::initFromGssContext(const gss_eap_attr_ctx *manager,
75 const gss_cred_id_t gssCred,
76 const gss_ctx_id_t gssCtx)
78 const gss_eap_radius_attr_provider *radius;
79 gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
80 int authenticated, complete, more = -1;
83 assert(m_assertion == NULL);
85 if (!gss_eap_attr_provider::initFromGssContext(manager, gssCred, gssCtx))
88 radius = static_cast<const gss_eap_radius_attr_provider *>
89 (m_manager->getProvider(ATTR_TYPE_RADIUS));
91 radius->getAttribute(512 /* XXX */, &authenticated, &complete,
92 &value, NULL, &more)) {
93 m_assertion = parseAssertion(&value);
94 gss_release_buffer(&minor, &value);
102 gss_eap_saml_assertion_provider::~gss_eap_saml_assertion_provider(void)
108 gss_eap_saml_assertion_provider::setAssertion(const saml2::Assertion *assertion)
113 if (assertion != NULL)
114 m_assertion = dynamic_cast<saml2::Assertion*>(assertion->clone());
120 gss_eap_saml_assertion_provider::parseAssertion(const gss_buffer_t buffer)
122 string str((char *)buffer->value, buffer->length);
123 istringstream istream(str);
125 const XMLObjectBuilder *b;
127 doc = XMLToolingConfig::getConfig().getParser().parse(istream);
128 b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
130 return dynamic_cast<saml2::Assertion *>(b->buildFromDocument(doc));
134 gss_eap_saml_assertion_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
137 /* just add the prefix */
138 return addAttribute(this, GSS_C_NO_BUFFER, data);
142 gss_eap_saml_assertion_provider::setAttribute(int complete,
143 const gss_buffer_t attr,
144 const gss_buffer_t value)
146 if (attr == GSS_C_NO_BUFFER || attr->length == 0) {
147 saml2::Assertion *assertion = parseAssertion(value);
150 m_assertion = assertion;
155 gss_eap_saml_assertion_provider::deleteAttribute(const gss_buffer_t value)
162 gss_eap_saml_assertion_provider::getAttribute(const gss_buffer_t attr,
166 gss_buffer_t display_value,
171 if (attr != GSS_C_NO_BUFFER || attr->length != 0)
174 if (m_assertion == NULL)
180 *authenticated = true;
183 XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str);
185 duplicateBuffer(str, value);
192 gss_eap_saml_assertion_provider::mapToAny(int authenticated,
193 gss_buffer_t type_id) const
195 return (gss_any_t)m_assertion;
199 gss_eap_saml_assertion_provider::releaseAnyNameMapping(gss_buffer_t type_id,
200 gss_any_t input) const
202 delete ((saml2::Assertion *)input);
206 gss_eap_saml_assertion_provider::exportToBuffer(gss_buffer_t buffer) const
212 buffer->value = NULL;
214 if (m_assertion == NULL)
217 sink << *m_assertion;
220 duplicateBuffer(str, buffer);
224 gss_eap_saml_assertion_provider::initFromBuffer(const gss_eap_attr_ctx *ctx,
225 const gss_buffer_t buffer)
227 if (!gss_eap_attr_provider::initFromBuffer(ctx, buffer))
230 if (buffer->length == 0)
233 assert(m_assertion == NULL);
235 m_assertion = parseAssertion(buffer);
236 if (m_assertion == NULL)
243 gss_eap_saml_assertion_provider::init(void)
245 gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML_ASSERTION,
246 "urn:ietf:params:gss-eap:saml-aaa-assertion",
247 gss_eap_saml_assertion_provider::createAttrContext);
252 gss_eap_saml_assertion_provider::finalize(void)
254 gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_SAML_ASSERTION);
257 gss_eap_attr_provider *
258 gss_eap_saml_assertion_provider::createAttrContext(void)
260 return new gss_eap_saml_assertion_provider;
264 * gss_eap_saml_attr_provider is for retrieving the underlying attributes.
266 const saml2::Assertion *
267 gss_eap_saml_attr_provider::getAssertion(void) const
269 const gss_eap_saml_assertion_provider *saml;
271 saml = static_cast<const gss_eap_saml_assertion_provider *>
272 (m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
274 return saml->getAssertion();
279 gss_eap_saml_attr_provider::~gss_eap_saml_attr_provider(void)
281 /* Nothing to do, we're just a wrapper around the assertion provider. */
285 gss_eap_saml_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
288 const saml2::Assertion *assertion = getAssertion();
291 if (assertion == NULL)
294 const vector<saml2::Attribute*>& attrs2 =
295 const_cast<const saml2::AttributeStatement*>(assertion->getAttributeStatements().front())->getAttributes();
296 for (vector<saml2::Attribute*>::const_iterator a = attrs2.begin();
300 const XMLCh *attributeName = (*a)->getName();
301 const XMLCh *attributeNameFormat = (*a)->getNameFormat();
302 XMLCh *qualifiedName;
303 XMLCh space[2] = { ' ', 0 };
304 gss_buffer_desc utf8;
306 qualifiedName = new XMLCh[XMLString::stringLen(attributeName) + 1 +
307 XMLString::stringLen(attributeNameFormat) + 1];
308 XMLString::copyString(qualifiedName, attributeName);
309 XMLString::catString(qualifiedName, space);
310 XMLString::catString(qualifiedName, attributeNameFormat);
312 utf8.value = (void *)toUTF8(qualifiedName);
313 utf8.length = strlen((char *)utf8.value);
315 ret = addAttribute(this, &utf8, data);
317 delete qualifiedName;
318 delete qualifiedName;
328 gss_eap_saml_attr_provider::setAttribute(int complete,
329 const gss_buffer_t attr,
330 const gss_buffer_t value)
335 gss_eap_saml_attr_provider::deleteAttribute(const gss_buffer_t value)
339 static BaseRefVectorOf<XMLCh> *
340 decomposeAttributeName(const gss_buffer_t attr)
342 XMLCh *qualifiedAttr = new XMLCh[attr->length + 1];
343 XMLString::transcode((const char *)attr->value, qualifiedAttr, attr->length);
345 BaseRefVectorOf<XMLCh> *components = XMLString::tokenizeString(qualifiedAttr);
347 delete qualifiedAttr;
352 const saml2::Attribute *
353 gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr) const
355 /* Check we have an assertion */
356 const saml2::Assertion *assertion = getAssertion();
357 if (assertion == NULL ||
358 assertion->getAttributeStatements().size() == 0)
361 /* Check the attribute name consists of name format | whsp | name */
362 BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
363 if (components == NULL || components->size() != 2) {
368 /* For each attribute statement, look for an attribute match */
369 const vector <saml2::AttributeStatement *>&statements =
370 assertion->getAttributeStatements();
371 const saml2::Attribute *ret = NULL;
373 for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
374 s != statements.end();
376 const vector<saml2::Attribute*>& attrs =
377 const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
379 for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
380 if (XMLString::equals((*a)->getNameFormat(), components->elementAt(0)) &&
381 XMLString::equals((*a)->getName(), components->elementAt(1))) {
397 gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr,
401 gss_buffer_t display_value,
404 const saml2::Attribute *a;
405 const saml2::AttributeValue *av;
406 int nvalues, i = *more;
410 a = getAttribute(attr);
414 nvalues = a->getAttributeValues().size();
418 else if (i >= nvalues)
420 av = dynamic_cast<const saml2::AttributeValue *>(a->getAttributeValues().at(i)
425 *authenticated = TRUE;
428 value->value = toUTF8(av->getTextContent(), true);
429 value->length = strlen((char *)value->value);
431 if (display_value != NULL)
432 duplicateBuffer(*value, display_value);
441 gss_eap_saml_attr_provider::mapToAny(int authenticated,
442 gss_buffer_t type_id) const
444 return (gss_any_t)NULL;
448 gss_eap_saml_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id,
449 gss_any_t input) const
454 gss_eap_saml_attr_provider::exportToBuffer(gss_buffer_t buffer) const
457 buffer->value = NULL;
461 gss_eap_saml_attr_provider::initFromBuffer(const gss_eap_attr_ctx *ctx,
462 const gss_buffer_t buffer)
464 return gss_eap_attr_provider::initFromBuffer(ctx, buffer);
468 gss_eap_saml_attr_provider::init(void)
470 gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML,
471 "urn:ietf:params:gss-eap:saml-attr",
472 gss_eap_saml_attr_provider::createAttrContext);
477 gss_eap_saml_attr_provider::finalize(void)
479 gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_SAML);
482 gss_eap_attr_provider *
483 gss_eap_saml_attr_provider::createAttrContext(void)
485 return new gss_eap_saml_attr_provider;