#include "gssapiP_eap.h"
#ifdef WIN32
-#include <shlobj.h>
+# include <shlobj.h> /* may need to use ShFolder.h instead */
+# include <stdio.h>
#else
-#include <pwd.h>
+# include <pwd.h>
#endif
OM_uint32
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);
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) {
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;
}
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
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))
if (GSS_ERROR(major))
gssEapReleaseCred(&tmpMinor, &cred);
+ 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 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,
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 */
isDefaultIdentity = TRUE;
} else {
major = gssEapCompareName(minor, cred->name,
- defaultIdentityName, &isDefaultIdentity);
+ defaultIdentityName, 0,
+ &isDefaultIdentity);
if (GSS_ERROR(major))
goto cleanup;
}
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;