X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=mech_eap%2Futil_cred.c;h=707e02934fba98c9b0cf61155aac9603d0c76657;hp=d0ca5af855957b0aaa43ed0a11e151faf64c68c2;hb=HEAD;hpb=85893cd14827015aa8f7fc9eea041ff420223d4d diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c index d0ca5af..707e029 100644 --- a/mech_eap/util_cred.c +++ b/mech_eap/util_cred.c @@ -36,8 +36,12 @@ #include "gssapiP_eap.h" -#include -#include /* for BUFSIZ */ +#ifdef WIN32 +# include /* may need to use ShFolder.h instead */ +# include +#else +# include +#endif OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred) @@ -54,7 +58,7 @@ 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; } @@ -65,6 +69,20 @@ gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred) 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) { @@ -79,16 +97,18 @@ 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) { @@ -111,32 +131,54 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred) } 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; } @@ -162,16 +204,20 @@ readDefaultIdentityAndCreds(OM_uint32 *minor, 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) { @@ -189,16 +235,30 @@ cleanup: 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, + gss_const_name_t desiredName, OM_uint32 timeReq GSSEAP_UNUSED, const gss_OID_set desiredMechs, int credUsage, @@ -208,10 +268,6 @@ gssEapAcquireCred(OM_uint32 *minor, { 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; @@ -245,104 +301,29 @@ gssEapAcquireCred(OM_uint32 *minor, 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_LOCK(&((gss_name_t)desiredName)->mutex); major = gssEapDuplicateName(minor, desiredName, &cred->name); if (GSS_ERROR(major)) { - GSSEAP_MUTEX_UNLOCK(&desiredName->mutex); + GSSEAP_MUTEX_UNLOCK(&((gss_name_t)desiredName)->mutex); goto cleanup; } - 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; + GSSEAP_MUTEX_UNLOCK(&((gss_name_t)desiredName)->mutex); } - 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); @@ -361,12 +342,8 @@ gssEapAcquireCred(OM_uint32 *minor, 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; } @@ -376,12 +353,12 @@ cleanup: * lock because mechanisms list is immutable. */ int -gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech) +gssEapCredAvailable(gss_const_cred_id_t cred, gss_OID mech) { 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; @@ -391,6 +368,72 @@ gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech) 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, @@ -403,9 +446,16 @@ gssEapInquireCred(OM_uint32 *minor, 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) { @@ -430,7 +480,7 @@ gssEapInquireCred(OM_uint32 *minor, else major = gssEapIndicateMechs(minor, mechanisms); if (GSS_ERROR(major)) - return major; + goto cleanup; } if (cred->expiryTime == 0) { @@ -447,12 +497,338 @@ gssEapInquireCred(OM_uint32 *minor, } 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; +} + +/* + * 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, + gss_const_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, + gss_const_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; }