AC_SUBST(KRB5_CFLAGS)
AC_SUBST(KRB5_LIBS)
AC_SUBST(COMPILE_ET)
- AC_CHECK_LIB(gssapi_krb5, GSS_C_NT_COMPOSITE_EXPORT, [AC_DEFINE_UNQUOTED([HAVE_GSS_C_NT_COMPOSITE_EXPORT], 1, [Define if GSS-API library supports recent naming extensions draft])], [], "$KRB5_LIBS")
- AC_CHECK_LIB(gssapi_krb5, gss_inquire_attrs_for_mech, [AC_DEFINE_UNQUOTED([HAVE_GSS_INQUIRE_ATTRS_FOR_MECH], 1, [Define if GSS-API library supports RFC 5587])], [], "$KRB5_LIBS")
- AC_CHECK_LIB(gssapi_krb5, gss_krb5_import_cred, [AC_DEFINE_UNQUOTED([HAVE_GSS_KRB5_IMPORT_CRED], 1, [Define if GSS-API library supports gss_krb5_import_cred])], [], "$KRB5_LIBS")
+ AC_CHECK_LIB(krb5, GSS_C_NT_COMPOSITE_EXPORT, [AC_DEFINE_UNQUOTED([HAVE_GSS_C_NT_COMPOSITE_EXPORT], 1, [Define if GSS-API library supports recent naming extensions draft])], [], "$KRB5_LIBS")
+ AC_CHECK_LIB(krb5, gss_inquire_attrs_for_mech, [AC_DEFINE_UNQUOTED([HAVE_GSS_INQUIRE_ATTRS_FOR_MECH], 1, [Define if GSS-API library supports RFC 5587])], [], "$KRB5_LIBS")
+ AC_CHECK_LIB(krb5, gss_krb5_import_cred, [AC_DEFINE_UNQUOTED([HAVE_GSS_KRB5_IMPORT_CRED], 1, [Define if GSS-API library supports gss_krb5_import_cred])], [], "$KRB5_LIBS")
AC_CHECK_LIB(krb5, heimdal_version, [AC_DEFINE_UNQUOTED([HAVE_HEIMDAL_VERSION], 1, [Define if building against Heimdal Kerberos implementation]), heimdal=yes], [heimdal=no], "$KRB5_LIBS")
AM_CONDITIONAL(HEIMDAL, test "x$heimdal" != "xno")
fi
--- /dev/null
+Notes on using Moonshot with Samba4. Replace paths as appropriate.
+
+Samba
+-----
+
+* Download Samba4 and apply patches for mechanism agnosticism which are
+ available at http://www.padl.com/~lukeh/samba/
+* Join Samba as a member server or domain controller (only tested former)
+* Extract local service principal key to keytab (currently there do not
+ appear to be tools to do this, but you can get the cleartext password
+ from /usr/local/samba/private/secrets.ldb)
+
+Shibboleth
+----------
+
+* Add a mapping from the PAC RADIUS attribute to urn:mspac: in the file
+ /usr/local/etc/shibboleth/attribute-map.xml:
+
+ <GSSAPIAttribute name="urn:ietf:params:gss-eap:radius-avp urn:x-radius:1679163525"
+ id="urn:mspac:" binary="true"/>
+
+FreeRADIUS
+----------
+
+Install the rlm_mspac module and configure per below.
+
+* Install dictionary.ukerna so MS-Windows-Auth-Data is defined
+* Create /usr/local/etc/raddb/modules/mspac with the following:
+
+ mspac {
+ keytab = /etc/krb5.keytab
+ spn = host/host.fqdn@KERBEROS.REALM
+ }
+
+* Add mspac to instantiate stanza in radiusd.conf
+* Add mspac to post-auth stanza in sites-enabled/inner-tunnel
+
+You will need to have a TGT for the host service principal before starting
+radiusd. It's easiest to do this with kinit -k.
+
+Testing
+-------
+
+The Samba server doesn't require any specific command line arguments, although
+on OS X it was necessary to start it with -M single to function under gdb.
+
+For the client, the GSS EAP mechanism can be specified on the command line:
+
+smbclient --password samba --mechanism 1.3.6.1.4.1.5322.22.1.18 '\\host\share'".
+
+There is no Moonshot SSPI implementation as yet, so it is not possible to test
+with a Windows client.
- test Heimdal port
- fix ABNF: no slash in the case where there is no host
-- specify anonymous behaviour: use empty name
- always intern OIDs so they never need to be freed
+
+- handle many-to-many Shibboleth attribute mappings; need to encode
+ both attribute and value index into more
+- proper acquire_cred_ext implementation
+- MIC on flags token
ATTRIBUTE GSS-Acceptor-Service-Specific 130 string
ATTRIBUTE GSS-Acceptor-Realm-Name 131 string
ATTRIBUTE SAML-AAA-Assertion 132 string
+ATTRIBUTE MS-Windows-Auth-Data 133 octets
END-VENDOR UKERNA
#endif
#include "gssapi_eap.h"
+#ifndef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
+typedef const gss_OID_desc *gss_const_OID;
+#endif
+
/* Kerberos headers */
#include <krb5.h>
#define MA_SUPPORTED(ma) MA_ADD((ma), mech_attrs)
#define MA_KNOWN(ma) MA_ADD((ma), known_mech_attrs)
-#ifndef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
-typedef const gss_OID_desc *gss_const_OID;
-#endif
-
OM_uint32
gss_inquire_attrs_for_mech(OM_uint32 *minor,
gss_const_OID mech_oid,
unsigned char *q;
q = data;
- for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+ p = str;
+
+ while (*p && *p && (*p == '=' || strchr(base64_chars, *p))) {
unsigned int val = token_decode(p);
unsigned int marker = (val >> 24) & 0xff;
if (val == DECODE_ERROR)
*q++ = (val >> 8) & 0xff;
if (marker < 1)
*q++ = val & 0xff;
+ p += 4;
+ if (*p == '\n')
+ p++;
}
return q - (unsigned char *) data;
}
int
base64Valid(const char *str)
{
- const char *p;
+ const char *p = str;
int valid = 1;
- for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+ while (*p && *p && (*p == '=' || strchr(base64_chars, *p))) {
unsigned int val = token_decode(p);
if (val == DECODE_ERROR) {
valid = 0;
break;
}
+ p += 4;
+ if (*p == '\n')
+ p++;
}
return valid;
}
GSS_C_INTEG_FLAG | /* integrity */
GSS_C_CONF_FLAG | /* confidentiality */
GSS_C_SEQUENCE_FLAG | /* sequencing */
- GSS_C_REPLAY_FLAG; /* replay detection */
+ GSS_C_REPLAY_FLAG| /* replay detection */
+ GSS_C_MUTUAL_FLAG; /*xxx big hack */
*pCtx = ctx;
switch (vendor) {
case VENDORPEC_UKERNA:
- bInternalAttribute = true;
+ switch (attrid) {
+ case PW_GSS_ACCEPTOR_SERVICE_NAME:
+ case PW_GSS_ACCEPTOR_HOST_NAME:
+ case PW_GSS_ACCEPTOR_SERVICE_SPECIFIC:
+ case PW_GSS_ACCEPTOR_REALM_NAME:
+ case PW_SAML_AAA_ASSERTION:
+ bInternalAttribute = true;
+ break;
+ default:
+ break;
+ }
break;
default:
break;
return isInternalAttributeP(ATTRID(attribute), VENDOR(attribute));
}
+static bool
+isFragmentedAttributeP(uint16_t attrid, uint16_t vendor)
+{
+ /* A bit of a hack for the PAC for now. Should be configurable. */
+ return (vendor == VENDORPEC_UKERNA) &&
+ !isInternalAttributeP(attrid, vendor);
+}
+
+static bool
+isFragmentedAttributeP(uint32_t attribute)
+{
+ return isFragmentedAttributeP(ATTRID(attribute), VENDOR(attribute));
+}
+
/*
* Copy AVP list, same as paircopy except it filters out attributes
* containing keys.
if (i == -1)
i = 0;
+ if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid)) {
+ return false;
+ } else if (isFragmentedAttributeP(attrid)) {
+ return getFragmentedAttribute(attrid,
+ authenticated,
+ complete,
+ value);
+ }
+
for (vp = pairfind(m_vps, attrid);
vp != NULL;
vp = pairfind(vp->next, attrid)) {
duplicateBuffer(valueBuf, value);
}
- if (display_value != GSS_C_NO_BUFFER) {
+ if (display_value != GSS_C_NO_BUFFER &&
+ vp->type != PW_TYPE_OCTETS) {
char displayString[MAX_STRING_LEN];
gss_buffer_desc displayBuf;
}
bool
+gss_eap_radius_attr_provider::getFragmentedAttribute(uint32_t attrid,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value) const
+{
+ return getFragmentedAttribute(ATTRID(attrid), VENDOR(attrid),
+ authenticated, complete, value);
+}
+
+bool
gss_eap_radius_attr_provider::getAttribute(uint16_t attribute,
uint16_t vendor,
int *authenticated,
unsigned char *p;
uint32_t attr = VENDORATTR(vendor, attribute);
- buffer->length = 0;
- buffer->value = NULL;
+ if (buffer != GSS_C_NO_BUFFER) {
+ buffer->length = 0;
+ buffer->value = NULL;
+ }
vp = pairfind(vps, attr);
if (vp == NULL) {
return GSS_S_UNAVAILABLE;
}
- do {
- buffer->length += vp->length;
- } while (concat && (vp = pairfind(vp->next, attr)) != NULL);
+ if (buffer != GSS_C_NO_BUFFER) {
+ do {
+ buffer->length += vp->length;
+ } while (concat && (vp = pairfind(vp->next, attr)) != NULL);
- buffer->value = GSSEAP_MALLOC(buffer->length);
- if (buffer->value == NULL) {
- *minor = ENOMEM;
- return GSS_S_FAILURE;
- }
+ buffer->value = GSSEAP_MALLOC(buffer->length);
+ if (buffer->value == NULL) {
+ *minor = ENOMEM;
+ return GSS_S_FAILURE;
+ }
- p = (unsigned char *)buffer->value;
+ p = (unsigned char *)buffer->value;
- for (vp = pairfind(vps, attr);
- concat && vp != NULL;
- vp = pairfind(vp->next, attr)) {
- memcpy(p, vp->vp_octets, vp->length);
- p += vp->length;
+ for (vp = pairfind(vps, attr);
+ concat && vp != NULL;
+ vp = pairfind(vp->next, attr)) {
+ memcpy(p, vp->vp_octets, vp->length);
+ p += vp->length;
+ }
}
*minor = 0;
int *authenticated,
int *complete,
gss_buffer_t value) const;
+ bool getFragmentedAttribute(uint32_t attrid,
+ int *authenticated,
+ int *complete,
+ gss_buffer_t value) const;
bool authenticated(void) const { return m_authenticated; }
#define PW_GSS_ACCEPTOR_SERVICE_SPECIFIC 130
#define PW_GSS_ACCEPTOR_REALM_NAME 131
#define PW_SAML_AAA_ASSERTION 132
+#define PW_MS_WINDOWS_AUTH_DATA 133
#define IS_RADIUS_ERROR(code) ((code) >= ERROR_TABLE_BASE_rse && \
(code) <= ERROR_TABLE_BASE_rse + RSE_TIMEOUT_IO)
buf.value = (void *)shibAttr->getSerializedValues()[*more].c_str();
buf.length = strlen((char *)buf.value);
- if (buf.length != 0) {
+ /* XXX hack until we have proper binary attribute support */
+ if (attr->length == sizeof("urn:mspac:") - 1 &&
+ memcmp(attr->value, "urn:mspac:", attr->length) == 0) {
+ ssize_t octetLen;
+
+ value->value = GSSEAP_MALLOC(buf.length);
+ if (value->value == NULL)
+ throw std::bad_alloc();
+
+ octetLen = base64Decode((char *)buf.value, value->value);
+ if (octetLen < 0) {
+ GSSEAP_FREE(value->value);
+ value->value = NULL;
+ return false;
+ }
+
+ value->length = octetLen;
+ } else if (buf.length != 0) {
if (value != NULL)
duplicateBuffer(buf, value);
if (authenticated != NULL)
*authenticated = m_authenticated;
if (complete != NULL)
- *complete = false;
+ *complete = true;
if (nvalues > ++i)
*more = i;
bool
gss_eap_shib_attr_provider::init(void)
{
- if (SPConfig::getConfig().getFeatures() == 0 &&
- ShibbolethResolver::init() == false)
- return false;
+ bool ret = false;
+
+ try {
+ if (SPConfig::getConfig().getFeatures() == 0)
+ ret = ShibbolethResolver::init();
+ } catch (exception &e) {
+ }
- gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext);
+ if (ret)
+ gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext);
- return true;
+ return ret;
}
void
-Subproject commit ac0ba1f390586dd0300f0a036ce30952b1dd5def
+Subproject commit 1a7258779c5454494ac8e257cca2fc99a7e36dfe
-Subproject commit 28fcbaa4e8c5090550a3e0ceaf0ea6a1355b890b
+Subproject commit bdbac801c636a747fdb3c0a39a564f3f77452cf3