#include "gssapiP_eap.h"
-#include <pwd.h>
+#ifdef WIN32
+# include <shlobj.h> /* may need to use ShFolder.h instead */
+# include <stdio.h>
+#else
+# include <pwd.h>
+#endif
OM_uint32
gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
}
if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
gssEapReleaseCred(&tmpMinor, &cred);
return GSS_S_FAILURE;
}
return GSS_S_COMPLETE;
}
+static void
+zeroAndReleasePassword(gss_buffer_t password)
+{
+ GSSEAP_ASSERT(password != GSS_C_NO_BUFFER);
+
+ 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->caCertificateBlob);
+ gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
+ gss_release_buffer(&tmpMinor, &cred->clientCertificate);
+ gss_release_buffer(&tmpMinor, &cred->privateKey);
#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 buf[BUFSIZ];
char *ccacheName;
+ int i = 0;
+#ifndef WIN32
struct passwd *pw = NULL, pwd;
+ char pwbuf[BUFSIZ];
+#endif
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) {
+#ifdef WIN32
+ TCHAR szPath[MAX_PATH];
+
+ if (!SUCCEEDED(SHGetFolderPath(NULL,
+ CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
+ NULL, /* User access token */
+ 0, /* SHGFP_TYPE_CURRENT */
+ szPath))) {
+ major = GSS_S_CRED_UNAVAIL;
+ *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */
+ goto cleanup;
+ }
+
+ snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
+#else
if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
pw == NULL || pw->pw_dir == NULL) {
major = GSS_S_CRED_UNAVAIL;
- *minor = errno;
+ *minor = GSSEAP_GET_LAST_ERROR();
goto cleanup;
}
snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
+#endif /* WIN32 */
ccacheName = buf;
}
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 credMech = GSS_C_NO_OID;
+
+ if (cred != GSS_C_NO_CREDENTIAL &&
+ cred->mechanisms != GSS_C_NO_OID_SET &&
+ cred->mechanisms->count == 1)
+ credMech = &cred->mechanisms->elements[0];
+
+ return credMech;
+}
+
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);
+#ifdef GSSEAP_ENABLE_ACCEPTOR
+ if (cred->flags & CRED_FLAG_ACCEPT) {
+ struct rs_context *radContext;
- if (password != GSS_C_NO_BUFFER) {
- major = duplicateBuffer(minor, password, &cred->password);
+ major = gssEapCreateRadiusContext(minor, cred, &radContext);
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;
+ rs_context_destroy(radContext);
}
+#endif
if (pActualMechs != NULL) {
major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
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);
- }
+ gssEapTraceStatus("gss_acquire_cred", major, *minor);
return major;
}
OM_uint32 minor;
int present = 0;
- assert(mech != GSS_C_NO_OID);
+ GSSEAP_ASSERT(mech != GSS_C_NO_OID);
if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET)
return TRUE;
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,
+ gss_name_t *name,
+ OM_uint32 *pLifetime,
+ gss_cred_usage_t *cred_usage,
+ gss_OID_set *mechanisms)
+{
+ OM_uint32 major;
+ time_t now, lifetime;
+
+ if (name != NULL) {
+ major = gssEapResolveCredIdentity(minor, cred);
+ if (GSS_ERROR(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) {
+ OM_uint32 flags = (cred->flags & (CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT));
+
+ switch (flags) {
+ case CRED_FLAG_INITIATE:
+ *cred_usage = GSS_C_INITIATE;
+ break;
+ case CRED_FLAG_ACCEPT:
+ *cred_usage = GSS_C_ACCEPT;
+ break;
+ default:
+ *cred_usage = GSS_C_BOTH;
+ break;
+ }
+ }
+
+ if (mechanisms != NULL) {
+ if (cred->mechanisms != GSS_C_NO_OID_SET)
+ major = duplicateOidSet(minor, cred->mechanisms, mechanisms);
+ else
+ major = gssEapIndicateMechs(minor, mechanisms);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (cred->expiryTime == 0) {
+ lifetime = GSS_C_INDEFINITE;
+ } else {
+ now = time(NULL);
+ lifetime = now - cred->expiryTime;
+ if (lifetime < 0)
+ lifetime = 0;
+ }
+
+ if (pLifetime != NULL) {
+ *pLifetime = lifetime;
+ }
+
+ if (lifetime == 0) {
+ major = GSS_S_CREDENTIALS_EXPIRED;
+ *minor = GSSEAP_CRED_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;
+}
+
+/*
+ * Currently only the privateKey path is exposed to the application
+ * (via gss_set_cred_option() or the third line in ~/.gss_eap_id).
+ * At some point in the future we may add support for setting the
+ * client certificate separately.
+ */
+OM_uint32
+gssEapSetCredClientCertificate(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_buffer_t clientCert,
+ const gss_buffer_t privateKey)
+{
+ OM_uint32 major, tmpMinor;
+ gss_buffer_desc newClientCert = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc newPrivateKey = GSS_C_EMPTY_BUFFER;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (clientCert == GSS_C_NO_BUFFER &&
+ privateKey == GSS_C_NO_BUFFER) {
+ cred->flags &= ~(CRED_FLAG_CERTIFICATE);
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+ goto cleanup;
+ }
+
+ if (clientCert != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, clientCert, &newClientCert);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ if (privateKey != GSS_C_NO_BUFFER) {
+ major = duplicateBuffer(minor, privateKey, &newPrivateKey);
+ if (GSS_ERROR(major))
+ goto cleanup;
+ }
+
+ cred->flags |= CRED_FLAG_CERTIFICATE;
+
+ gss_release_buffer(&tmpMinor, &cred->clientCertificate);
+ cred->clientCertificate = newClientCert;
+
+ gss_release_buffer(&tmpMinor, &cred->privateKey);
+ cred->privateKey = newPrivateKey;
+
+ major = GSS_S_COMPLETE;
+ *minor = 0;
+
+cleanup:
+ if (GSS_ERROR(major)) {
+ gss_release_buffer(&tmpMinor, &newClientCert);
+ gss_release_buffer(&tmpMinor, &newPrivateKey);
+ }
+
+ return major;
+}
+
+OM_uint32
+gssEapSetCredService(OM_uint32 *minor,
+ gss_cred_id_t cred,
+ const gss_name_t target)
+{
+ OM_uint32 major, tmpMinor;
+ gss_name_t newTarget = GSS_C_NO_NAME;
+
+ if (cred->flags & CRED_FLAG_RESOLVED) {
+ major = GSS_S_FAILURE;
+ *minor = GSSEAP_CRED_RESOLVED;
+ goto cleanup;
+ }
+
+ if (target != GSS_C_NO_NAME) {
+ major = gssEapDuplicateName(minor, target, &newTarget);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+ cred->flags |= CRED_FLAG_TARGET;
+ } else {
+ cred->flags &= ~(CRED_FLAG_TARGET);
+ }
+
+ gssEapReleaseName(&tmpMinor, &cred->target);
+ cred->target = newTarget;
+
+ 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->caCertificateBlob.value != NULL)
+ duplicateBufferOrCleanup(&src->caCertificateBlob, &dst->caCertificateBlob);
+ if (src->subjectNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
+ if (src->subjectAltNameConstraint.value != NULL)
+ duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
+ if (src->clientCertificate.value != NULL)
+ duplicateBufferOrCleanup(&src->clientCertificate, &dst->clientCertificate);
+ if (src->privateKey.value != NULL)
+ duplicateBufferOrCleanup(&src->privateKey, &dst->privateKey);
+
+#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, 0,
+ &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) && major != GSS_S_CRED_UNAVAIL)
+ goto cleanup;
+
+ /* If we have a caller-supplied password, the credential is resolved. */
+ if ((resolvedCred->flags &
+ (CRED_FLAG_PASSWORD | CRED_FLAG_CERTIFICATE)) == 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;
+}