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=856c0a5da5f47c2dc4a5bf2de504b0bb536adb76;hb=HEAD;hpb=77eab72ae59381941a8dc46182e9a833fde87938 diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c index 856c0a5..707e029 100644 --- a/mech_eap/util_cred.c +++ b/mech_eap/util_cred.c @@ -37,9 +37,10 @@ #include "gssapiP_eap.h" #ifdef WIN32 -#include +# include /* may need to use ShFolder.h instead */ +# include #else -#include +# include #endif OM_uint32 @@ -71,6 +72,8 @@ gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred) 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); @@ -101,8 +104,11 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred) 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) { @@ -155,10 +161,10 @@ readStaticIdentityFile(OM_uint32 *minor, if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */ NULL, /* User access token */ - 0, + 0, /* SHGFP_TYPE_CURRENT */ szPath))) { major = GSS_S_CRED_UNAVAIL; - *minor = GetLastError(); + *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */ goto cleanup; } @@ -240,18 +246,19 @@ cleanup: gss_OID gssEapPrimaryMechForCred(gss_cred_id_t cred) { - gss_OID nameMech = GSS_C_NO_OID; + gss_OID credMech = GSS_C_NO_OID; - if (cred->mechanisms != GSS_C_NO_OID_SET && + if (cred != GSS_C_NO_CREDENTIAL && + cred->mechanisms != GSS_C_NO_OID_SET && cred->mechanisms->count == 1) - nameMech = &cred->mechanisms->elements[0]; + credMech = &cred->mechanisms->elements[0]; - return nameMech; + return credMech; } OM_uint32 gssEapAcquireCred(OM_uint32 *minor, - const gss_name_t desiredName, + gss_const_name_t desiredName, OM_uint32 timeReq GSSEAP_UNUSED, const gss_OID_set desiredMechs, int credUsage, @@ -295,17 +302,29 @@ gssEapAcquireCred(OM_uint32 *minor, 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); + GSSEAP_MUTEX_UNLOCK(&((gss_name_t)desiredName)->mutex); } +#ifdef GSSEAP_ENABLE_ACCEPTOR + if (cred->flags & CRED_FLAG_ACCEPT) { + struct rs_context *radContext; + + major = gssEapCreateRadiusContext(minor, cred, &radContext); + if (GSS_ERROR(major)) + goto cleanup; + + rs_context_destroy(radContext); + } +#endif + if (pActualMechs != NULL) { major = duplicateOidSet(minor, cred->mechanisms, pActualMechs); if (GSS_ERROR(major)) @@ -324,6 +343,8 @@ cleanup: if (GSS_ERROR(major)) gssEapReleaseCred(&tmpMinor, &cred); + gssEapTraceStatus("gss_acquire_cred", major, *minor); + return major; } @@ -332,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; @@ -522,10 +543,72 @@ 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) + gss_const_name_t target) { OM_uint32 major, tmpMinor; gss_name_t newTarget = GSS_C_NO_NAME; @@ -540,6 +623,10 @@ gssEapSetCredService(OM_uint32 *minor, 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); @@ -598,10 +685,16 @@ gssEapDuplicateCred(OM_uint32 *minor, 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 */ @@ -650,7 +743,8 @@ staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred) isDefaultIdentity = TRUE; } else { major = gssEapCompareName(minor, cred->name, - defaultIdentityName, &isDefaultIdentity); + defaultIdentityName, 0, + &isDefaultIdentity); if (GSS_ERROR(major)) goto cleanup; } @@ -674,7 +768,7 @@ cleanup: OM_uint32 gssEapResolveInitiatorCred(OM_uint32 *minor, const gss_cred_id_t cred, - const gss_name_t targetName + gss_const_name_t targetName #ifndef HAVE_MOONSHOT_GET_IDENTITY GSSEAP_UNUSED #endif @@ -713,10 +807,12 @@ gssEapResolveInitiatorCred(OM_uint32 *minor, if (major == GSS_S_CRED_UNAVAIL) #endif major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred); - if (GSS_ERROR(major)) + if (GSS_ERROR(major) && major != GSS_S_CRED_UNAVAIL) goto cleanup; - if ((resolvedCred->flags & CRED_FLAG_PASSWORD) == 0) { + /* 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;