-Subproject commit b6cbbcfa4b40bbbf29cfe62f35e9f672684d37d0
+Subproject commit ade6c4fa17f837504a3902296d4b4f636e28b51e
AC_SUBST(JANSSON_LIBS)
fi
])dnl
+
+AC_DEFUN([AX_CHECK_LIBMOONSHOT],
+[AC_MSG_CHECKING(for Moonshot identity selector implementation)
+LIBMOONSHOT_DIR=
+found_libmoonshot="no"
+AC_ARG_WITH(libmoonshot,
+ AC_HELP_STRING([--with-libmoonshot],
+ [Use libmoonshot (in specified installation directory)]),
+ [check_libmoonshot_dir="$withval"],
+ [check_libmoonshot_dir=])
+for dir in $check_libmoonshot_dir $prefix /usr /usr/local ../../moonshot-ui/libmoonshot ; do
+ libmoonshotdir="$dir"
+ if test -f "$dir/include/libmoonshot.h"; then
+ found_libmoonshot="yes";
+ LIBMOONSHOT_DIR="${libmoonshotdir}"
+ LIBMOONSHOT_CFLAGS="-I$libmoonshotdir/include";
+ break;
+ fi
+done
+AC_MSG_RESULT($found_libmoonshot)
+if test x_$found_libmoonshot != x_yes; then
+ AC_MSG_ERROR([
+----------------------------------------------------------------------
+ Cannot find Moonshot identity selector libraries.
+
+ Please install wpa_supplicant or specify installation directory with
+ --with-libmoonshot=(dir).
+----------------------------------------------------------------------
+])
+else
+ printf "libmoonshot found in $libmoonshotdir\n";
+ LIBMOONSHOT_LIBS="-lmoonshot";
+ LIBMOONSHOT_LDFLAGS="-L$libmoonshot/lib";
+ AC_SUBST(LIBMOONSHOT_CFLAGS)
+ AC_SUBST(LIBMOONSHOT_LDFLAGS)
+ AC_SUBST(LIBMOONSHOT_LIBS)
+ AC_CHECK_LIB(moonshot, moonshot_get_identity, [AC_DEFINE_UNQUOTED([HAVE_MOONSHOT_GET_IDENTITY], 1, [Define if Moonshot identity selector is available])], [], "$LIBMOONSHOT_LIBS")
+fi
+])dnl
+
AX_CHECK_SHIBRESOLVER
AX_CHECK_RADSEC
AX_CHECK_JANSSON
+AX_CHECK_LIBMOONSHOT
AC_CONFIG_FILES([Makefile libeap/Makefile mech_eap/Makefile])
AC_OUTPUT
util_krb.c \
util_lucid.c \
util_mech.c \
+ util_moonshot.c \
util_name.c \
util_oid.c \
util_ordering.c \
return GSS_S_FAILURE;
}
- if (cred->radiusConfigFile != NULL)
- configFile = cred->radiusConfigFile;
- if (cred->radiusConfigStanza != NULL)
- configStanza = cred->radiusConfigStanza;
+ if (cred->radiusConfigFile.value != NULL)
+ configFile = (const char *)cred->radiusConfigFile.value;
+ if (cred->radiusConfigStanza.value != NULL)
+ configStanza = (const char *)cred->radiusConfigStanza.value;
ralloc.calloc = GSSEAP_CALLOC;
ralloc.malloc = GSSEAP_MALLOC;
GSSEAP_MUTEX_LOCK(&ctx->mutex);
if (cred == GSS_C_NO_CREDENTIAL) {
- if (ctx->defaultCred == GSS_C_NO_CREDENTIAL) {
+ if (ctx->cred == GSS_C_NO_CREDENTIAL) {
major = gssEapAcquireCred(minor,
GSS_C_NO_NAME,
- GSS_C_NO_BUFFER,
GSS_C_INDEFINITE,
GSS_C_NO_OID_SET,
GSS_C_ACCEPT,
- &ctx->defaultCred,
+ &ctx->cred,
NULL,
NULL);
if (GSS_ERROR(major))
goto cleanup;
}
- cred = ctx->defaultCred;
+ cred = ctx->cred;
}
GSSEAP_MUTEX_LOCK(&cred->mutex);
- if (cred->name != GSS_C_NO_NAME) {
- major = gssEapDuplicateName(minor, cred->name, &ctx->acceptorName);
- if (GSS_ERROR(major))
- goto cleanup;
- }
+ /*
+ * Calling gssEapInquireCred() forces the default acceptor credential name
+ * to be resolved.
+ */
+ major = gssEapInquireCred(minor, cred, &ctx->acceptorName, NULL, NULL, NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
major = gssEapSmStep(minor,
cred,
gss_OID_set *actual_mechs,
OM_uint32 *time_rec)
{
- return gssEapAcquireCred(minor, desired_name, GSS_C_NO_BUFFER,
+ return gssEapAcquireCred(minor, desired_name,
time_req, desired_mechs, cred_usage,
output_cred_handle, actual_mechs, time_rec);
}
gss_OID_set *actual_mechs,
OM_uint32 *time_rec)
{
- return gssEapAcquireCred(minor, desired_name, password,
- time_req, desired_mechs, cred_usage,
- output_cred_handle, actual_mechs, time_rec);
+ OM_uint32 major, tmpMinor;
+
+ major = gssEapAcquireCred(minor, desired_name,
+ time_req, desired_mechs, cred_usage,
+ output_cred_handle, actual_mechs, time_rec);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapSetCredPassword(minor, *output_cred_handle, password);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+cleanup:
+ if (GSS_ERROR(major))
+ gssEapReleaseCred(&tmpMinor, output_cred_handle);
+
+ return major;
}
major = gssEapAcquireCred(minor,
desired_name,
- GSS_C_NO_BUFFER,
time_req,
&mechs,
cred_usage,
OM_uint32 *initiator_time_rec,
OM_uint32 *acceptor_time_rec)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
OM_uint32 time_req, time_rec = 0;
gss_OID_set_desc mechs;
major = gssEapAcquireCred(minor,
desired_name,
- password,
time_req,
&mechs,
cred_usage,
output_cred_handle,
actual_mechs,
&time_rec);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapSetCredPassword(minor, *output_cred_handle, password);
+ if (GSS_ERROR(major))
+ goto cleanup;
if (initiator_time_rec != NULL)
*initiator_time_rec = time_rec;
if (acceptor_time_rec != NULL)
*acceptor_time_rec = time_rec;
+cleanup:
+ if (GSS_ERROR(major))
+ gssEapReleaseCred(&tmpMinor, output_cred_handle);
+
return major;
}
#define CRED_FLAG_INITIATE 0x00010000
#define CRED_FLAG_ACCEPT 0x00020000
-#define CRED_FLAG_DEFAULT_IDENTITY 0x00040000
-#define CRED_FLAG_PASSWORD 0x00080000
-#define CRED_FLAG_DEFAULT_CCACHE 0x00100000
+#define CRED_FLAG_PASSWORD 0x00040000
+#define CRED_FLAG_DEFAULT_CCACHE 0x00080000
+#define CRED_FLAG_RESOLVED 0x00100000
#define CRED_FLAG_PUBLIC_MASK 0x0000FFFF
#ifdef HAVE_HEIMDAL_VERSION
GSSEAP_MUTEX mutex;
OM_uint32 flags;
gss_name_t name;
+ gss_name_t target; /* for initiator */
gss_buffer_desc password;
gss_OID_set mechanisms;
time_t expiryTime;
- char *radiusConfigFile;
- char *radiusConfigStanza;
+ gss_buffer_desc radiusConfigFile;
+ gss_buffer_desc radiusConfigStanza;
+ gss_buffer_desc caCertificate;
+ gss_buffer_desc subjectNameConstraint;
+ gss_buffer_desc subjectAltNameConstraint;
#ifdef GSSEAP_ENABLE_REAUTH
krb5_ccache krbCredCache;
gss_cred_id_t reauthCred;
time_t expiryTime;
uint64_t sendSeq, recvSeq;
void *seqState;
- gss_cred_id_t defaultCred;
+ gss_cred_id_t cred;
union {
struct gss_eap_initiator_ctx initiator;
#define initiatorCtx ctxU.initiator
error_code GSSEAP_BAD_CRED_OPTION, "Bad credential option"
error_code GSSEAP_NO_DEFAULT_IDENTITY, "Default credentials identity unavailable"
error_code GSSEAP_NO_DEFAULT_CRED, "Missing default password or other credentials"
+error_code GSSEAP_CRED_RESOLVED, "Credential is already fully resolved"
+
+#
+# Local identity service errors
+#
+error_code GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE, "Unable to start identity service"
+error_code GSSEAP_NO_IDENTITY_SELECTED, "No identity selected"
+error_code GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR, "Identity service installation error"
+error_code GSSEAP_IDENTITY_SERVICE_OS_ERROR, "Identity service OS error"
+error_code GSSEAP_IDENTITY_SERVICE_IPC_ERROR, "Identity service IPC error"
+error_code GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR, "Unknown identity service error"
+
#
# Wrap/unwrap/PRF errors
#
#endif
static OM_uint32
-peerConfigInit(OM_uint32 *minor,
- gss_cred_id_t cred,
- gss_ctx_id_t ctx)
+peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
{
OM_uint32 major;
krb5_context krbContext;
struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
+ gss_cred_id_t cred = ctx->cred;
eapPeerConfig->identity = NULL;
eapPeerConfig->identity_len = 0;
eapPeerConfig->password = (unsigned char *)cred->password.value;
eapPeerConfig->password_len = cred->password.length;
+ /* certs */
+ eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
+ eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
+ eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
+
*minor = 0;
return GSS_S_COMPLETE;
}
static OM_uint32
initBegin(OM_uint32 *minor,
- gss_cred_id_t cred,
gss_ctx_id_t ctx,
gss_name_t target,
gss_OID mech,
gss_channel_bindings_t chanBindings GSSEAP_UNUSED)
{
OM_uint32 major;
+ gss_cred_id_t cred = ctx->cred;
assert(cred != GSS_C_NO_CREDENTIAL);
static OM_uint32
eapGssSmInitAuthenticate(OM_uint32 *minor,
- gss_cred_id_t cred,
+ gss_cred_id_t cred GSSEAP_UNUSED,
gss_ctx_id_t ctx,
gss_name_t target GSSEAP_UNUSED,
gss_OID mech GSSEAP_UNUSED,
assert(inputToken != GSS_C_NO_BUFFER);
- major = peerConfigInit(minor, cred, ctx);
+ major = peerConfigInit(minor, ctx);
if (GSS_ERROR(major))
goto cleanup;
GSSEAP_MUTEX_LOCK(&ctx->mutex);
- if (cred == GSS_C_NO_CREDENTIAL) {
- if (ctx->defaultCred == GSS_C_NO_CREDENTIAL) {
- major = gssEapAcquireCred(minor,
- GSS_C_NO_NAME,
- GSS_C_NO_BUFFER,
- time_req,
- GSS_C_NO_OID_SET,
- GSS_C_INITIATE,
- &ctx->defaultCred,
- NULL,
- NULL);
- if (GSS_ERROR(major))
- goto cleanup;
- }
+ if (cred != GSS_C_NO_CREDENTIAL)
+ GSSEAP_MUTEX_LOCK(&cred->mutex);
- cred = ctx->defaultCred;
+ if (ctx->cred == GSS_C_NO_CREDENTIAL) {
+ major = gssEapResolveInitiatorCred(minor, cred, target_name, &ctx->cred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ assert(ctx->cred != GSS_C_NO_CREDENTIAL);
}
- GSSEAP_MUTEX_LOCK(&cred->mutex);
+ GSSEAP_MUTEX_LOCK(&ctx->cred->mutex);
- if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
- major = GSS_S_NO_CRED;
- *minor = GSSEAP_CRED_USAGE_MISMATCH;
- goto cleanup;
- }
+ assert(ctx->cred->flags & CRED_FLAG_RESOLVED);
+ assert(ctx->cred->flags & CRED_FLAG_INITIATE);
if (initialContextToken) {
- major = initBegin(minor, cred, ctx, target_name, mech_type,
+ major = initBegin(minor, ctx, target_name, mech_type,
req_flags, time_req, input_chan_bindings);
if (GSS_ERROR(major))
goto cleanup;
cleanup:
if (cred != GSS_C_NO_CREDENTIAL)
GSSEAP_MUTEX_UNLOCK(&cred->mutex);
+ if (ctx->cred != GSS_C_NO_CREDENTIAL)
+ GSSEAP_MUTEX_UNLOCK(&ctx->cred->mutex);
GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
if (GSS_ERROR(major))
const gss_OID oid GSSEAP_UNUSED,
const gss_buffer_t buffer)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
gss_buffer_desc configFileBuffer = GSS_C_EMPTY_BUFFER;
if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
return major;
}
- if (cred->radiusConfigFile != NULL)
- GSSEAP_FREE(cred->radiusConfigFile);
-
- cred->radiusConfigFile = (char *)configFileBuffer.value;
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
+ cred->radiusConfigFile = configFileBuffer;
*minor = 0;
return GSS_S_COMPLETE;
const gss_OID oid GSSEAP_UNUSED,
const gss_buffer_t buffer)
{
- OM_uint32 major;
+ OM_uint32 major, tmpMinor;
gss_buffer_desc configStanzaBuffer = GSS_C_EMPTY_BUFFER;
if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
return major;
}
- if (cred->radiusConfigStanza != NULL)
- GSSEAP_FREE(cred->radiusConfigStanza);
-
- cred->radiusConfigStanza = (char *)configStanzaBuffer.value;
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
+ cred->radiusConfigStanza = configStanzaBuffer;
*minor = 0;
return GSS_S_COMPLETE;
#endif
#if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#define GSSEAP_UNUSED __attribute__ ((__unused__))
+#define GSSEAP_UNUSED __attribute__ ((__unused__))
#else
#define GSSEAP_UNUSED
#endif
const char *string,
gss_buffer_t buffer);
+#define makeStringBufferOrCleanup(src, dst) \
+ do { \
+ major = makeStringBuffer((minor), (src), (dst));\
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
OM_uint32
bufferToString(OM_uint32 *minor,
const gss_buffer_t buffer,
const gss_buffer_t src,
gss_buffer_t dst);
+#define duplicateBufferOrCleanup(src, dst) \
+ do { \
+ major = duplicateBuffer((minor), (src), (dst)); \
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
static inline int
bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2)
{
OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
+gss_OID
+gssEapPrimaryMechForCred(gss_cred_id_t cred);
+
OM_uint32
gssEapAcquireCred(OM_uint32 *minor,
const gss_name_t desiredName,
- const gss_buffer_t password,
OM_uint32 timeReq,
const gss_OID_set desiredMechs,
int cred_usage,
gss_OID_set *pActualMechs,
OM_uint32 *timeRec);
+OM_uint32
+gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password);
+
+OM_uint32
+gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target);
+
+OM_uint32
+gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t target,
+ gss_cred_id_t *resolvedCred);
+
int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech);
OM_uint32
gss_OID
gssEapSaslNameToOid(const gss_buffer_t name);
+/* util_moonshot.c */
+OM_uint32
+libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName);
+
+OM_uint32
+libMoonshotResolveInitiatorCred(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t targetName);
+
/* util_name.c */
#define EXPORT_NAME_FLAG_OID 0x1
#define EXPORT_NAME_FLAG_COMPOSITE 0x2
gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
sequenceFree(&tmpMinor, &ctx->seqState);
- gssEapReleaseCred(&tmpMinor, &ctx->defaultCred);
+ gssEapReleaseCred(&tmpMinor, &ctx->cred);
GSSEAP_MUTEX_DESTROY(&ctx->mutex);
return GSS_S_COMPLETE;
}
+static void
+zeroAndReleasePassword(gss_buffer_t password)
+{
+ if (password->value != NULL) {
+ memset(password->value, 0, password->length);
+ GSSEAP_FREE(password->value);
+ }
+
+ password->value = NULL;
+ password->length = 0;
+}
+
OM_uint32
gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
{
GSSEAP_KRB_INIT(&krbContext);
gssEapReleaseName(&tmpMinor, &cred->name);
+ gssEapReleaseName(&tmpMinor, &cred->target);
- if (cred->password.value != NULL) {
- memset(cred->password.value, 0, cred->password.length);
- GSSEAP_FREE(cred->password.value);
- }
+ zeroAndReleasePassword(&cred->password);
- if (cred->radiusConfigFile != NULL)
- GSSEAP_FREE(cred->radiusConfigFile);
- if (cred->radiusConfigStanza != NULL)
- GSSEAP_FREE(cred->radiusConfigStanza);
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
+ gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
+ gss_release_buffer(&tmpMinor, &cred->caCertificate);
+ gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
#ifdef GSSEAP_ENABLE_REAUTH
if (cred->krbCredCache != NULL) {
}
static OM_uint32
-readDefaultIdentityAndCreds(OM_uint32 *minor,
- gss_buffer_t defaultIdentity,
- gss_buffer_t defaultCreds)
+readStaticIdentityFile(OM_uint32 *minor,
+ gss_buffer_t defaultIdentity,
+ gss_buffer_t defaultPassword)
{
OM_uint32 major, tmpMinor;
FILE *fp = NULL;
char pwbuf[BUFSIZ], buf[BUFSIZ];
char *ccacheName;
struct passwd *pw = NULL, pwd;
+ int i = 0;
defaultIdentity->length = 0;
defaultIdentity->value = NULL;
- defaultCreds->length = 0;
- defaultCreds->value = NULL;
+ if (defaultPassword != GSS_C_NO_BUFFER) {
+ defaultPassword->length = 0;
+ defaultPassword->value = NULL;
+ }
ccacheName = getenv("GSSEAP_IDENTITY");
if (ccacheName == NULL) {
break;
}
- if (defaultIdentity->value == NULL)
+ if (i == 0)
dst = defaultIdentity;
- else if (defaultCreds->value == NULL)
- dst = defaultCreds;
+ else if (i == 1)
+ dst = defaultPassword;
else
break;
- major = duplicateBuffer(minor, &src, dst);
- if (GSS_ERROR(major))
- goto cleanup;
+ if (dst != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, &src, dst);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ i++;
}
if (defaultIdentity->length == 0) {
if (GSS_ERROR(major)) {
gss_release_buffer(&tmpMinor, defaultIdentity);
- gss_release_buffer(&tmpMinor, defaultCreds);
+ zeroAndReleasePassword(defaultPassword);
}
+ memset(buf, 0, sizeof(buf));
+
return major;
}
+gss_OID
+gssEapPrimaryMechForCred(gss_cred_id_t cred)
+{
+ gss_OID nameMech = GSS_C_NO_OID;
+
+ if (cred->mechanisms != GSS_C_NO_OID_SET &&
+ cred->mechanisms->count == 1)
+ nameMech = &cred->mechanisms->elements[0];
+
+ return nameMech;
+}
+
OM_uint32
gssEapAcquireCred(OM_uint32 *minor,
const gss_name_t desiredName,
- const gss_buffer_t password,
OM_uint32 timeReq GSSEAP_UNUSED,
const gss_OID_set desiredMechs,
int credUsage,
{
OM_uint32 major, tmpMinor;
gss_cred_id_t cred;
- gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
- gss_name_t defaultIdentityName = GSS_C_NO_NAME;
- gss_buffer_desc defaultCreds = GSS_C_EMPTY_BUFFER;
- gss_OID nameMech = GSS_C_NO_OID;
/* XXX TODO validate with changed set_cred_option API */
*pCred = GSS_C_NO_CREDENTIAL;
if (GSS_ERROR(major))
goto cleanup;
- if (cred->mechanisms != GSS_C_NO_OID_SET &&
- cred->mechanisms->count == 1)
- nameMech = &cred->mechanisms->elements[0];
-
- if (cred->flags & CRED_FLAG_INITIATE) {
- major = readDefaultIdentityAndCreds(minor, &defaultIdentity, &defaultCreds);
- if (major == GSS_S_COMPLETE) {
- major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
- nameMech, &defaultIdentityName);
- if (GSS_ERROR(major))
- goto cleanup;
- } else if (major != GSS_S_CRED_UNAVAIL)
- goto cleanup;
- }
-
if (desiredName != GSS_C_NO_NAME) {
GSSEAP_MUTEX_LOCK(&desiredName->mutex);
}
GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
-
- if (defaultIdentityName != GSS_C_NO_NAME) {
- int nameEqual;
-
- major = gssEapCompareName(minor, desiredName,
- defaultIdentityName, &nameEqual);
- if (GSS_ERROR(major))
- goto cleanup;
- else if (nameEqual)
- cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
- }
- } else {
- if (cred->flags & CRED_FLAG_ACCEPT) {
- gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
- char serviceName[5 + MAXHOSTNAMELEN];
-
- /* default host-based service is host@localhost */
- memcpy(serviceName, "host@", 5);
- if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
- major = GSS_S_FAILURE;
- *minor = GSSEAP_NO_HOSTNAME;
- goto cleanup;
- }
-
- nameBuf.value = serviceName;
- nameBuf.length = strlen((char *)nameBuf.value);
-
- major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
- nameMech, &cred->name);
- if (GSS_ERROR(major))
- goto cleanup;
- } else if (cred->flags & CRED_FLAG_INITIATE) {
- if (defaultIdentityName == GSS_C_NO_NAME) {
- major = GSS_S_CRED_UNAVAIL;
- *minor = GSSEAP_NO_DEFAULT_IDENTITY;
- goto cleanup;
- }
-
- cred->name = defaultIdentityName;
- defaultIdentityName = GSS_C_NO_NAME;
- }
- cred->flags |= CRED_FLAG_DEFAULT_IDENTITY;
- }
-
- assert(cred->name != GSS_C_NO_NAME);
-
- if (password != GSS_C_NO_BUFFER) {
- major = duplicateBuffer(minor, password, &cred->password);
- if (GSS_ERROR(major))
- goto cleanup;
-
- cred->flags |= CRED_FLAG_PASSWORD;
- } else if (defaultCreds.value != NULL &&
- (cred->flags & CRED_FLAG_DEFAULT_IDENTITY)) {
- cred->password = defaultCreds;
-
- defaultCreds.length = 0;
- defaultCreds.value = NULL;
-
- cred->flags |= CRED_FLAG_PASSWORD;
- } else if (cred->flags & CRED_FLAG_INITIATE) {
- /*
- * OK, here we need to ask the supplicant if we have creds or it
- * will acquire them, so GS2 can know whether to prompt for a
- * password or not.
- */
-#if 0
- && !gssEapCanReauthP(cred, GSS_C_NO_NAME, timeReq)
-#endif
- major = GSS_S_CRED_UNAVAIL;
- *minor = GSSEAP_NO_DEFAULT_CRED;
- goto cleanup;
}
if (pActualMechs != NULL) {
cleanup:
if (GSS_ERROR(major))
gssEapReleaseCred(&tmpMinor, &cred);
- gssEapReleaseName(&tmpMinor, &defaultIdentityName);
- gss_release_buffer(&tmpMinor, &defaultIdentity);
- if (defaultCreds.value != NULL) {
- memset(defaultCreds.value, 0, defaultCreds.length);
- gss_release_buffer(&tmpMinor, &defaultCreds);
- }
return major;
}
return present;
}
+static OM_uint32
+staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+
+ *pName = GSS_C_NO_NAME;
+
+ major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER);
+ if (major == GSS_S_COMPLETE) {
+ major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+ nameMech, pName);
+ }
+
+ gss_release_buffer(&tmpMinor, &defaultIdentity);
+
+ return major;
+}
+
+static OM_uint32
+gssEapResolveCredIdentity(OM_uint32 *minor,
+ gss_cred_id_t cred)
+{
+ OM_uint32 major;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+
+ if (cred->name != GSS_C_NO_NAME) {
+ *minor = 0;
+ return GSS_S_COMPLETE;
+ }
+
+ if (cred->flags & CRED_FLAG_ACCEPT) {
+ gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
+ char serviceName[5 + MAXHOSTNAMELEN];
+
+ /* default host-based service is host@localhost */
+ memcpy(serviceName, "host@", 5);
+ if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
+ *minor = GSSEAP_NO_HOSTNAME;
+ return GSS_S_FAILURE;
+ }
+
+ nameBuf.value = serviceName;
+ nameBuf.length = strlen((char *)nameBuf.value);
+
+ major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
+ nameMech, &cred->name);
+ if (GSS_ERROR(major))
+ return major;
+ } else if (cred->flags & CRED_FLAG_INITIATE) {
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+ major = libMoonshotResolveDefaultIdentity(minor, cred, &cred->name);
+ if (major == GSS_S_CRED_UNAVAIL)
+#endif
+ major = staticIdentityFileResolveDefaultIdentity(minor, cred, &cred->name);
+ if (major != GSS_S_CRED_UNAVAIL)
+ return major;
+ }
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+
OM_uint32
gssEapInquireCred(OM_uint32 *minor,
gss_cred_id_t cred,
time_t now, lifetime;
if (name != NULL) {
- major = gssEapDuplicateName(minor, cred->name, name);
+ major = gssEapResolveCredIdentity(minor, cred);
if (GSS_ERROR(major))
- return major;
+ goto cleanup;
+
+ if (cred->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, cred->name, name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ } else
+ *name = GSS_C_NO_NAME;
}
if (cred_usage != NULL) {
else
major = gssEapIndicateMechs(minor, mechanisms);
if (GSS_ERROR(major))
- return major;
+ goto cleanup;
}
if (cred->expiryTime == 0) {
}
if (lifetime == 0) {
+ major = GSS_S_CREDENTIALS_EXPIRED;
*minor = GSSEAP_CRED_EXPIRED;
- return GSS_S_CREDENTIALS_EXPIRED;
+ goto cleanup;
}
major = GSS_S_COMPLETE;
*minor = 0;
+cleanup:
+ return major;
+}
+
+OM_uint32
+gssEapSetCredPassword(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t password)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (password != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, password, &newPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ cred->flags |= CRED_FLAG_PASSWORD;
+ } else {
+ cred->flags &= ~(CRED_FLAG_PASSWORD);
+ }
+
+ gss_release_buffer(&tmpMinor, &cred->password);
+ cred->password = newPassword;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ return major;
+}
+
+static OM_uint32
+gssEapDuplicateCred(OM_uint32 *minor,
+ const gss_cred_id_t src,
+ gss_cred_id_t *pDst)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t dst = GSS_C_NO_CREDENTIAL;
+
+ *pDst = GSS_C_NO_CREDENTIAL;
+
+ major = gssEapAllocCred(minor, &dst);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ dst->flags = src->flags;
+
+ if (src->name != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, src->name, &dst->name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (src->target != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, src->target, &dst->target);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (src->password.value != NULL) {
+ major = duplicateBuffer(minor, &src->password, &dst->password);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ dst->expiryTime = src->expiryTime;
+
+ if (src->radiusConfigFile.value != NULL)
+ duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile);
+ if (src->radiusConfigStanza.value != NULL)
+ duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza);
+ if (src->caCertificate.value != NULL)
+ duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate);
+ if (src->subjectNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
+ if (src->subjectAltNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
+
+#ifdef GSSEAP_ENABLE_REAUTH
+ /* XXX krbCredCache, reauthCred */
+#endif
+
+ *pDst = dst;
+ dst = GSS_C_NO_CREDENTIAL;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ gssEapReleaseCred(&tmpMinor, &dst);
+
+ return major;
+}
+
+static OM_uint32
+staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
+ gss_name_t defaultIdentityName = GSS_C_NO_NAME;
+ gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER;
+ int isDefaultIdentity = FALSE;
+
+ major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
+ gssEapPrimaryMechForCred(cred), &defaultIdentityName);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if (defaultIdentityName == GSS_C_NO_NAME) {
+ if (cred->name == GSS_C_NO_NAME) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_IDENTITY;
+ goto cleanup;
+ }
+ } else {
+ if (cred->name == GSS_C_NO_NAME) {
+ cred->name = defaultIdentityName;
+ defaultIdentityName = GSS_C_NO_NAME;
+ isDefaultIdentity = TRUE;
+ } else {
+ major = gssEapCompareName(minor, cred->name,
+ defaultIdentityName, &isDefaultIdentity);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+ }
+
+ if (isDefaultIdentity &&
+ (cred->flags & CRED_FLAG_PASSWORD) == 0) {
+ major = gssEapSetCredPassword(minor, cred, &defaultPassword);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+cleanup:
+ gssEapReleaseName(&tmpMinor, &defaultIdentityName);
+ zeroAndReleasePassword(&defaultPassword);
+ gss_release_buffer(&tmpMinor, &defaultIdentity);
+
+ return major;
+}
+
+OM_uint32
+gssEapResolveInitiatorCred(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ const gss_name_t targetName
+#ifndef HAVE_MOONSHOT_GET_IDENTITY
+ GSSEAP_UNUSED
+#endif
+ ,
+ gss_cred_id_t *pResolvedCred)
+{
+ OM_uint32 major, tmpMinor;
+ gss_cred_id_t resolvedCred = GSS_C_NO_CREDENTIAL;
+
+ if (cred == GSS_C_NO_CREDENTIAL) {
+ major = gssEapAcquireCred(minor,
+ GSS_C_NO_NAME,
+ GSS_C_INDEFINITE,
+ GSS_C_NO_OID_SET,
+ GSS_C_INITIATE,
+ &resolvedCred,
+ NULL,
+ NULL);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ } else {
+ if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
+ major = GSS_S_NO_CRED;
+ *minor = GSSEAP_CRED_USAGE_MISMATCH;
+ goto cleanup;
+ }
+
+ major = gssEapDuplicateCred(minor, cred, &resolvedCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if ((resolvedCred->flags & CRED_FLAG_RESOLVED) == 0) {
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+ major = libMoonshotResolveInitiatorCred(minor, resolvedCred, targetName);
+ if (major == GSS_S_CRED_UNAVAIL)
+#endif
+ major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ if ((resolvedCred->flags & CRED_FLAG_PASSWORD) == 0) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_CRED;
+ goto cleanup;
+ }
+
+ resolvedCred->flags |= CRED_FLAG_RESOLVED;
+ }
+
+ *pResolvedCred = resolvedCred;
+ resolvedCred = GSS_C_NO_CREDENTIAL;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ gssEapReleaseCred(&tmpMinor, &resolvedCred);
+
return major;
}
--- /dev/null
+/*
+ * Copyright (c) 2011, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gssapiP_eap.h"
+
+#ifdef HAVE_MOONSHOT_GET_IDENTITY
+#include <libmoonshot.h>
+
+static OM_uint32
+libMoonshotMapError(OM_uint32 *minor,
+ MoonshotError **pError)
+{
+ MoonshotError *error = *pError;
+
+ assert(error != NULL);
+
+ switch (error->code) {
+ case MOONSHOT_ERROR_UNABLE_TO_START_SERVICE:
+ *minor = GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE;
+ break;
+ case MOONSHOT_ERROR_NO_IDENTITY_SELECTED:
+ *minor = GSSEAP_NO_IDENTITY_SELECTED;
+ break;
+ case MOONSHOT_ERROR_INSTALLATION_ERROR:
+ *minor = GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR;
+ break;
+ case MOONSHOT_ERROR_OS_ERROR:
+ *minor = GSSEAP_IDENTITY_SERVICE_OS_ERROR;
+ break;
+ case MOONSHOT_ERROR_IPC_ERROR:
+ *minor = GSSEAP_IDENTITY_SERVICE_IPC_ERROR;
+ break;
+ default:
+ *minor = GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR;
+ break;
+ }
+
+ gssEapSaveStatusInfo(*minor, error->message);
+ moonshot_error_free(error);
+ *pError = NULL;
+
+ return GSS_S_CRED_UNAVAIL;
+}
+
+OM_uint32
+libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
+ const gss_cred_id_t cred,
+ gss_name_t *pName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_name_t name = GSS_C_NO_NAME;
+ gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
+ char *nai = NULL;
+ char *password = NULL;
+ char *serverCertificateHash = NULL;
+ char *caCertificate = NULL;
+ char *subjectNameConstraint = NULL;
+ char *subjectAltNameConstraint = NULL;
+ MoonshotError *error = NULL;
+
+ *pName = GSS_C_NO_NAME;
+
+ if (!moonshot_get_default_identity(&nai,
+ &password,
+ &serverCertificateHash,
+ &caCertificate,
+ &subjectNameConstraint,
+ &subjectAltNameConstraint,
+ &error)) {
+ if (error->code == MOONSHOT_ERROR_NO_IDENTITY_SELECTED) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_NO_DEFAULT_IDENTITY;
+ moonshot_error_free(error);
+ } else
+ major = libMoonshotMapError(minor, &error);
+ goto cleanup;
+ }
+
+ tmpBuffer.value = nai;
+ tmpBuffer.length = strlen(nai);
+
+ major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME, nameMech, &name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ *pName = name;
+ name = GSS_C_NO_NAME;
+
+cleanup:
+ moonshot_free(nai);
+ moonshot_free(password);
+ moonshot_free(serverCertificateHash);
+ moonshot_free(caCertificate);
+ moonshot_free(subjectNameConstraint);
+ moonshot_free(subjectAltNameConstraint);
+
+ gssEapReleaseName(&tmpMinor, &name);
+
+ return major;
+}
+
+OM_uint32
+libMoonshotResolveInitiatorCred(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t targetName)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID nameMech = gssEapPrimaryMechForCred(cred);
+ gss_buffer_desc initiator = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc target = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
+ char *nai = NULL;
+ char *password = NULL;
+ char *serverCertificateHash = NULL;
+ char *caCertificate = NULL;
+ char *subjectNameConstraint = NULL;
+ char *subjectAltNameConstraint = NULL;
+ MoonshotError *error = NULL;
+
+ if (cred->name != GSS_C_NO_NAME) {
+ major = gssEapExportName(minor, cred->name, &initiator);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (targetName != GSS_C_NO_NAME) {
+ major = gssEapExportName(minor, targetName, &target);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (!moonshot_get_identity((const char *)initiator.value,
+ (const char *)cred->password.value,
+ (const char *)target.value,
+ &nai,
+ &password,
+ &serverCertificateHash,
+ &caCertificate,
+ &subjectNameConstraint,
+ &subjectAltNameConstraint,
+ &error)) {
+ major = libMoonshotMapError(minor, &error);
+ goto cleanup;
+ }
+
+ gssEapReleaseName(&tmpMinor, &cred->name);
+
+ tmpBuffer.value = nai;
+ tmpBuffer.length = strlen(nai);
+
+ major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME,
+ nameMech, &cred->name);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ tmpBuffer.value = password;
+ tmpBuffer.length = strlen(password);
+
+ major = gssEapSetCredPassword(minor, cred, &tmpBuffer);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ gss_release_buffer(&tmpMinor, &cred->caCertificate);
+ gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
+
+ if (serverCertificateHash != NULL) {
+ size_t len = strlen(serverCertificateHash);
+
+ #define HASH_PREFIX "hash://server/sha256/"
+ #define HASH_PREFIX_LEN (sizeof(HASH_PREFIX) - 1)
+
+ cred->caCertificate.value = GSSEAP_MALLOC(HASH_PREFIX_LEN + len + 1);
+ if (cred->caCertificate.value == NULL) {
+ major = GSS_S_FAILURE;
+ *minor = ENOMEM;
+ goto cleanup;
+ }
+
+ memcpy(cred->caCertificate.value, HASH_PREFIX, HASH_PREFIX_LEN);
+ memcpy((char *)cred->caCertificate.value + HASH_PREFIX_LEN, serverCertificateHash, len);
+
+ ((char *)cred->caCertificate.value)[HASH_PREFIX_LEN + len] = '\0';
+
+ cred->caCertificate.length = HASH_PREFIX_LEN + len;
+ } else if (caCertificate != NULL) {
+ makeStringBufferOrCleanup(caCertificate, &cred->caCertificate);
+ }
+
+ if (subjectNameConstraint != NULL)
+ makeStringBufferOrCleanup(subjectNameConstraint, &cred->subjectNameConstraint);
+ if (subjectAltNameConstraint != NULL)
+ makeStringBufferOrCleanup(subjectAltNameConstraint, &cred->subjectAltNameConstraint);
+
+cleanup:
+ moonshot_free(nai);
+ moonshot_free(password);
+ moonshot_free(serverCertificateHash);
+ moonshot_free(caCertificate);
+ moonshot_free(subjectNameConstraint);
+ moonshot_free(subjectAltNameConstraint);
+
+ gss_release_buffer(&tmpMinor, &initiator);
+ gss_release_buffer(&tmpMinor, &target);
+
+ return major;
+}
+#endif /* HAVE_MOONSHOT_GET_IDENTITY */