X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=mech_eap%2Futil_cred.c;h=53a19a74fe831938427cee906a546ab89526b99b;hb=49c65b803b43e159e38f6a16505bad54de153916;hp=11dcfeb71a384979d73ae55a04d3f1eeba7b0805;hpb=39ff48ca32975124dbada37f56dd470d375435e3;p=mech_eap.git diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c index 11dcfeb..53a19a7 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 @@ -103,6 +104,8 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred) gss_release_buffer(&tmpMinor, &cred->caCertificate); gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint); gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint); + gss_release_buffer(&tmpMinor, &cred->privateKey); + gss_release_buffer(&tmpMinor, &cred->clientCertificate); #ifdef GSSEAP_ENABLE_REAUTH if (cred->krbCredCache != NULL) { @@ -127,7 +130,8 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred) static OM_uint32 readStaticIdentityFile(OM_uint32 *minor, gss_buffer_t defaultIdentity, - gss_buffer_t defaultPassword) + gss_buffer_t defaultPassword, + gss_buffer_t defaultPrivateKey) { OM_uint32 major, tmpMinor; FILE *fp = NULL; @@ -147,6 +151,11 @@ readStaticIdentityFile(OM_uint32 *minor, defaultPassword->value = NULL; } + if (defaultPrivateKey != GSS_C_NO_BUFFER) { + defaultPrivateKey->length = 0; + defaultPrivateKey->value = NULL; + } + ccacheName = getenv("GSSEAP_IDENTITY"); if (ccacheName == NULL) { #ifdef WIN32 @@ -155,10 +164,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; } @@ -202,6 +211,8 @@ readStaticIdentityFile(OM_uint32 *minor, dst = defaultIdentity; else if (i == 1) dst = defaultPassword; + else if (i == 2) + dst = defaultPrivateKey; else break; @@ -230,6 +241,7 @@ cleanup: if (GSS_ERROR(major)) { gss_release_buffer(&tmpMinor, defaultIdentity); zeroAndReleasePassword(defaultPassword); + gss_release_buffer(&tmpMinor, defaultPrivateKey); } memset(buf, 0, sizeof(buf)); @@ -306,6 +318,18 @@ gssEapAcquireCred(OM_uint32 *minor, GSSEAP_MUTEX_UNLOCK(&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)) @@ -337,7 +361,7 @@ gssEapCredAvailable(gss_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; @@ -358,7 +382,8 @@ staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor, *pName = GSS_C_NO_NAME; - major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER); + major = readStaticIdentityFile(minor, &defaultIdentity, + GSS_C_NO_BUFFER, GSS_C_NO_BUFFER); if (major == GSS_S_COMPLETE) { major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME, nameMech, pName); @@ -522,6 +547,102 @@ 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, @@ -572,6 +693,8 @@ gssEapDuplicateCred(OM_uint32 *minor, duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint); if (src->subjectAltNameConstraint.value != NULL) duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint); + if (src->privateKey.value != NULL) + duplicateBufferOrCleanup(&src->privateKey, &dst->privateKey); #ifdef GSSEAP_ENABLE_REAUTH /* XXX krbCredCache, reauthCred */ @@ -596,9 +719,11 @@ staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred) gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER; gss_name_t defaultIdentityName = GSS_C_NO_NAME; gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER; + gss_buffer_desc defaultPrivateKey = GSS_C_EMPTY_BUFFER; int isDefaultIdentity = FALSE; - major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword); + major = readStaticIdentityFile(minor, &defaultIdentity, + &defaultPassword, &defaultPrivateKey); if (GSS_ERROR(major)) goto cleanup; @@ -626,17 +751,26 @@ staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred) } } - if (isDefaultIdentity && - (cred->flags & CRED_FLAG_PASSWORD) == 0) { - major = gssEapSetCredPassword(minor, cred, &defaultPassword); - if (GSS_ERROR(major)) - goto cleanup; + if (isDefaultIdentity) { + if (defaultPrivateKey.length != 0) { + major = gssEapSetCredClientCertificate(minor, cred, GSS_C_NO_BUFFER, + &defaultPrivateKey); + if (GSS_ERROR(major)) + goto cleanup; + } + + if ((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); + gss_release_buffer(&tmpMinor, &defaultPrivateKey); return major; } @@ -683,10 +817,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;