+/*
+ * 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;
+}
+