-/*
- * Copyright 2011 JANET(UK)
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
*
- * 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
+ * UCAID licenses this file to you 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
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
*/
/**
* GSSAPIAttributeExtractor.cpp
*
- * AttributeExtractor for a base64-encoded GSS-API context.
+ * AttributeExtractor for a base64-encoded GSS-API context or name.
*/
#include "internal.h"
#include <shibsp/exceptions.h>
#include <shibsp/Application.h>
#include <shibsp/SPConfig.h>
+#include <shibsp/attribute/BinaryAttribute.h>
#include <shibsp/attribute/ScopedAttribute.h>
#include <shibsp/attribute/SimpleAttribute.h>
#include <shibsp/attribute/resolver/AttributeExtractor.h>
#include <xmltooling/util/XMLHelper.h>
#include <xercesc/util/Base64.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
+#include <boost/algorithm/string.hpp>
+
+#ifdef SHIBSP_HAVE_GSSGNU
+# include <gss.h>
+#elif defined SHIBSP_HAVE_GSSMIT
+# include <gssapi/gssapi_ext.h>
+#else
+# include <gssapi.h>
+#endif
-#include <gssapi/gssapi_ext.h>
using namespace shibsp;
using namespace opensaml::saml2md;
using namespace opensaml;
using namespace xmltooling;
+using namespace xercesc;
+using namespace boost;
using namespace std;
namespace shibsp {
m_document = doc;
}
- void extractAttributes(
- gss_name_t initiatorName, gss_buffer_t namingAttribute, vector<Attribute*>& attributes
- ) const;
+ void extractAttributes(gss_name_t initiatorName, vector<Attribute*>& attributes) const;
+ void extractAttributes(gss_name_t initiatorName, gss_buffer_t namingAttribute, vector<Attribute*>& attributes) const;
void getAttributeIds(vector<string>& attributes) const {
attributes.insert(attributes.end(), m_attributeIds.begin(), m_attributeIds.end());
private:
struct Rule {
- Rule() : authenticated(true), scopeDelimiter(0) {}
+ Rule() : authenticated(true), binary(false), scopeDelimiter(0) {}
vector<string> ids;
- bool authenticated;
+ bool authenticated,binary;
char scopeDelimiter;
};
{
public:
GSSAPIExtractor(const DOMElement* e)
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.GSSAPI")), m_impl(nullptr) {
+ : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT ".AttributeExtractor.GSSAPI")) {
background_load();
}
~GSSAPIExtractor() {
shutdown();
- delete m_impl;
}
void extractAttributes(
pair<bool,DOMElement*> background_load();
private:
- GSSAPIExtractorImpl* m_impl;
+ scoped_ptr<GSSAPIExtractorImpl> m_impl;
};
#if defined (_MSC_VER)
#pragma warning( pop )
#endif
- AttributeExtractor* GSSAPIAttributeExtractorFactory(const DOMElement* const & e)
+ AttributeExtractor* GSSAPIExtractorFactory(const DOMElement* const & e)
{
return new GSSAPIExtractor(e);
}
static const XMLCh _aliases[] = UNICODE_LITERAL_7(a,l,i,a,s,e,s);
static const XMLCh Attributes[] = UNICODE_LITERAL_10(A,t,t,r,i,b,u,t,e,s);
static const XMLCh _authenticated[] = UNICODE_LITERAL_13(a,u,t,h,e,n,t,i,c,a,t,e,d);
+ static const XMLCh _binary[] = UNICODE_LITERAL_6(b,i,n,a,r,y);
static const XMLCh GSSAPIAttribute[] = UNICODE_LITERAL_15(G,S,S,A,P,I,A,t,t,r,i,b,u,t,e);
static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
static const XMLCh _name[] = UNICODE_LITERAL_4(n,a,m,e);
name = child->getAttributeNS(nullptr, _aliases);
if (name && *name) {
auto_ptr_char aliases(name);
- char* pos;
- char* start = const_cast<char*>(aliases.get());
- while (start && *start) {
- while (*start && isspace(*start))
- start++;
- if (!*start)
- break;
- pos = strchr(start,' ');
- if (pos)
- *pos=0;
- if (strcmp(start, "REMOTE_USER")) {
- decl.ids.push_back(start);
- m_attributeIds.push_back(start);
- }
- else {
- m_log.warn("skipping alias, REMOTE_USER is a reserved name");
- }
- start = pos ? pos+1 : nullptr;
+ string dup(aliases.get());
+ trim(dup);
+ set<string> new_aliases;
+ split(new_aliases, dup, is_space(), algorithm::token_compress_on);
+ set<string>::iterator ru = new_aliases.find("REMOTE_USER");
+ if (ru != new_aliases.end()) {
+ m_log.warn("skipping alias, REMOTE_USER is a reserved name");
+ new_aliases.erase(ru);
}
+ m_attributeIds.insert(m_attributeIds.end(), new_aliases.begin(), new_aliases.end());
}
decl.authenticated = XMLHelper::getAttrBool(child, true, _authenticated);
+ decl.binary = XMLHelper::getAttrBool(child, false, _binary);
string delim = XMLHelper::getAttrString(child, "", _scopeDelimiter);
if (!delim.empty())
decl.scopeDelimiter = delim[0];
}
}
+void GSSAPIExtractorImpl::extractAttributes(gss_name_t initiatorName, vector<Attribute*>& attributes) const
+{
+ OM_uint32 minor;
+ gss_buffer_set_t attrnames = GSS_C_NO_BUFFER_SET;
+ OM_uint32 major = gss_inquire_name(&minor, initiatorName, nullptr, nullptr, &attrnames);
+ if (major == GSS_S_COMPLETE) {
+ for (size_t i = 0; i < attrnames->count; ++i) {
+ extractAttributes(initiatorName, &attrnames->elements[i], attributes);
+ }
+ gss_release_buffer_set(&minor, &attrnames);
+ }
+ else {
+ m_log.warn("unable to extract attributes, GSS name attribute inquiry failed (%u:%u)", major, minor);
+ }
+}
+
void GSSAPIExtractorImpl::extractAttributes(
gss_name_t initiatorName, gss_buffer_t namingAttribute, vector<Attribute*>& attributes
) const
gss_release_buffer(&minor, &buf);
return;
}
- if (buf.length)
+ if (buf.length) {
values.push_back(string(reinterpret_cast<char*>(buf.value), buf.length));
+ }
gss_release_buffer(&minor, &buf);
}
else {
if (values.empty())
return;
- if (rule->second.scopeDelimiter) {
+ if (rule->second.scopeDelimiter && !rule->second.binary) {
auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(rule->second.ids, rule->second.scopeDelimiter));
vector< pair<string,string> >& dest = scoped->getValues();
for (vector<string>::const_iterator v = values.begin(); v != values.end(); ++v) {
m_log.warn("ignoring unscoped value");
}
}
- if (!scoped->getValues().empty())
- attributes.push_back(scoped.release());
+ if (!scoped->getValues().empty()) {
+ attributes.push_back(scoped.get());
+ scoped.release();
+ }
+ }
+ else if (rule->second.binary) {
+ auto_ptr<BinaryAttribute> binary(new BinaryAttribute(rule->second.ids));
+ binary->getValues() = values;
+ attributes.push_back(binary.get());
+ binary.release();
}
else {
- // If unscoped, just copy over the values.
auto_ptr<SimpleAttribute> simple(new SimpleAttribute(rule->second.ids));
simple->getValues() = values;
- attributes.push_back(simple.release());
+ attributes.push_back(simple.get());
+ simple.release();
}
}
if (!m_impl)
return;
- static const XMLCh _GSSAPI[] = UNICODE_LITERAL_6(G,S,S,A,P,I);
- if (!XMLString::equals(xmlObject.getElementQName().getLocalPart(), _GSSAPI)) {
+ static const XMLCh _GSSAPIContext[] = UNICODE_LITERAL_13(G,S,S,A,P,I,C,o,n,t,e,x,t);
+ static const XMLCh _GSSAPIName[] = UNICODE_LITERAL_10(G,S,S,A,P,I,N,a,m,e);
+
+ if (!XMLString::equals(xmlObject.getElementQName().getLocalPart(), _GSSAPIContext)
+ && !XMLString::equals(xmlObject.getElementQName().getLocalPart(), _GSSAPIName)
+ ) {
m_log.debug("unable to extract attributes, unknown XML object type: %s", xmlObject.getElementQName().toString().c_str());
return;
}
return;
}
- gss_ctx_id_t gss = GSS_C_NO_CONTEXT;
-
xsecsize_t x;
OM_uint32 major,minor;
auto_ptr_char encoded(encodedWide);
+
+ gss_name_t srcname;
+ gss_ctx_id_t gss = GSS_C_NO_CONTEXT;
+
XMLByte* decoded=Base64::decode(reinterpret_cast<const XMLByte*>(encoded.get()), &x);
if (decoded) {
gss_buffer_desc importbuf;
importbuf.length = x;
importbuf.value = decoded;
- major = gss_import_sec_context(&minor, &importbuf, &gss);
- if (major != GSS_S_COMPLETE) {
- m_log.warn("unable to extract attributes, GSS context import failed (%u:%u)", major, minor);
- gss = GSS_C_NO_CONTEXT;
+ if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), _GSSAPIName)) {
+#ifdef HAVE_GSSAPI_COMPOSITE_NAME
+ major = gss_import_name(&minor, &importbuf, GSS_C_NT_EXPORT_NAME_COMPOSITE, &srcname);
+#else
+ major = gss_import_name(&minor, &importbuf, GSS_C_NT_EXPORT_NAME, &srcname);
+#endif
+ if (major == GSS_S_COMPLETE) {
+ m_impl->extractAttributes(srcname, attributes);
+ gss_release_name(&minor, &srcname);
+ }
+ else {
+ m_log.warn("unable to extract attributes, GSS name import failed (%u:%u)", major, minor);
+ }
+ // We fall through here down to the GSS context check, which will exit us.
+ }
+ else {
+ major = gss_import_sec_context(&minor, &importbuf, &gss);
+ if (major != GSS_S_COMPLETE) {
+ m_log.warn("unable to extract attributes, GSS context import failed (%u:%u)", major, minor);
+ gss = GSS_C_NO_CONTEXT;
+ }
}
#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
XMLString::release(&decoded);
#endif
}
else {
- m_log.warn("unable to extract attributes, base64 decode of GSSAPI context failed");
+ m_log.warn("unable to extract attributes, base64 decode of GSSAPI context or name failed");
}
if (gss == GSS_C_NO_CONTEXT) {
return;
}
+
// Extract the initiator name from the context.
- gss_name_t srcname;
major = gss_inquire_context(&minor, gss, &srcname, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
if (major == GSS_S_COMPLETE) {
-
- gss_buffer_set_t attrnames = GSS_C_NO_BUFFER_SET;
- major = gss_inquire_name(&minor, srcname, nullptr, nullptr, &attrnames);
- if (major == GSS_S_COMPLETE) {
- for (size_t i = 0; i < attrnames->count; ++i) {
- m_impl->extractAttributes(srcname, &attrnames->elements[i], attributes);
- }
- gss_release_buffer_set(&minor, &attrnames);
- }
- else {
- m_log.warn("unable to extract attributes, GSS name attribute inquiry failed (%u:%u)", major, minor);
- }
+ m_impl->extractAttributes(srcname, attributes);
gss_release_name(&minor, &srcname);
}
else {
// If we own it, wrap it.
XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
- GSSAPIExtractorImpl* impl = new GSSAPIExtractorImpl(raw.second, m_log);
+ scoped_ptr<GSSAPIExtractorImpl> impl(new GSSAPIExtractorImpl(raw.second, m_log));
// If we held the document, transfer it to the impl. If we didn't, it's a no-op.
impl->setDocument(docjanitor.release());
if (m_lock)
m_lock->wrlock();
SharedLock locker(m_lock, false);
- delete m_impl;
- m_impl = impl;
+ m_impl.swap(impl);
return make_pair(false,(DOMElement*)nullptr);
}