#include "radius/radius.h"
#include "util_radius.h"
#include "utils/radius_utils.h"
+#include "openssl/err.h"
+#include "libmoonshot.h"
/* methods allowed for phase1 authentication*/
static const struct eap_method_type allowed_eap_method_types[] = {
case EAPOL_altReject:
flag = CTX_FLAG_EAP_ALT_REJECT;
break;
+ case EAPOL_eapTriggerStart:
+ flag = CTX_FLAG_EAP_TRIGGER_START;
+ break;
}
return flag;
{
}
+static void peerNotifyCert(void *ctx GSSEAP_UNUSED,
+ int depth ,
+ const char *subject GSSEAP_UNUSED,
+ const char *altsubject[] GSSEAP_UNUSED,
+ int num_altsubject GSSEAP_UNUSED,
+ const char *cert_hash GSSEAP_UNUSED,
+ const struct wpabuf *cert GSSEAP_UNUSED)
+{
+ printf("peerNotifyCert: depth=%d; hash=%s (%p)\n", depth, cert_hash, cert_hash);
+}
+
+
static struct eapol_callbacks gssEapPolicyCallbacks = {
peerGetConfig,
peerGetBool,
peerSetConfigBlob,
peerGetConfigBlob,
peerNotifyPending,
+ NULL, /* eap_param_needed */
+ peerNotifyCert
};
-#ifdef GSSEAP_DEBUG
-extern int wpa_debug_level;
-#endif
#define CHBIND_SERVICE_NAME_FLAG 0x01
#define CHBIND_HOST_NAME_FLAG 0x02
} /* else log failures? */
}
+static int cert_to_byte_array(X509 *cert, unsigned char **bytes)
+{
+ unsigned char *buf;
+ unsigned char *p;
+
+ int len = i2d_X509(cert, NULL);
+ if (len <= 0) {
+ return -1;
+ }
+
+ p = buf = GSSEAP_MALLOC(len);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ i2d_X509(cert, &buf);
+
+ *bytes = p;
+ return len;
+}
+
+static int sha256(unsigned char *bytes, int len, unsigned char *hash)
+{
+ EVP_MD_CTX ctx;
+ unsigned int hash_len;
+
+ EVP_MD_CTX_init(&ctx);
+ if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL)) {
+ printf("sha256(init_sec_context.c): EVP_DigestInit_ex failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+ if (!EVP_DigestUpdate(&ctx, bytes, len)) {
+ printf("sha256(init_sec_context.c): EVP_DigestUpdate failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+ if (!EVP_DigestFinal(&ctx, hash, &hash_len)) {
+ printf("sha256(init_sec_context.c): EVP_DigestFinal failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+
+ return hash_len;
+}
+
+
+static int peerValidateServer(int ok_so_far, X509* cert, void *ca_ctx)
+{
+ const char *realm = NULL;
+ unsigned char *cert_bytes = NULL;
+ int cert_len;
+ unsigned char hash[32];
+ int hash_len;
+ MoonshotError *error = NULL;
+ struct eap_peer_config *eap_config = (struct eap_peer_config *) ca_ctx;
+ char *identity = strdup((const char *) eap_config->identity);
+
+ // Truncate the identity to just the username
+ char* at = strchr(identity, '@');
+ if (at != NULL) {
+ *at = '\0';
+ }
+
+ cert_len = cert_to_byte_array(cert, &cert_bytes);
+ hash_len = sha256(cert_bytes, cert_len, hash);
+ GSSEAP_FREE(cert_bytes);
+
+ if (hash_len != 32) {
+ printf("peerValidateServer: Error: hash_len=%d, not 32!\n", hash_len);
+ return FALSE;
+ }
+
+ /* This is ugly, but it works -- anonymous_identity is '@' + realm
+ * (see peerConfigInit)
+ */
+ realm = ((char *) eap_config->anonymous_identity) + 1;
+
+ ok_so_far = moonshot_confirm_ca_certificate(identity, realm, hash, 32, &error);
+ free(identity);
+
+ printf("peerValidateServer: Returning %d\n", ok_so_far);
+ return ok_so_far;
+}
+
+
static OM_uint32
peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
{
GSSEAP_KRB_INIT(&krbContext);
eapPeerConfig->fragment_size = 1024;
-#ifdef GSSEAP_DEBUG
- wpa_debug_level = 0;
-#endif
-
+
GSSEAP_ASSERT(cred->name != GSS_C_NO_NAME);
if ((cred->name->flags & (NAME_FLAG_NAI | NAME_FLAG_SERVICE)) == 0) {
eapPeerConfig->client_cert = (unsigned char *)cred->clientCertificate.value;
eapPeerConfig->private_key = (unsigned char *)cred->privateKey.value;
}
- eapPeerConfig->private_key_passwd = (unsigned char *)cred->password.value;
+ eapPeerConfig->private_key_passwd = (char *)cred->password.value;
}
+ eapPeerConfig->server_cert_cb = peerValidateServer;
+ eapPeerConfig->server_cert_ctx = eapPeerConfig;
+
*minor = 0;
return GSS_S_COMPLETE;
}
p = (unsigned char *)inputToken->value;
major = load_uint32_be(&p[0]);
- *minor = ERROR_TABLE_BASE_eapg + load_uint32_be(&p[4]);
+ *minor = load_uint32_be(&p[4]);
+ if ((*minor >0) && (*minor < 128))
+ * minor += ERROR_TABLE_BASE_eapg;
+ else *minor = 0;
if (!GSS_ERROR(major) || !IS_WIRE_ERROR(*minor)) {
major = GSS_S_FAILURE;
OM_uint32 *smFlags)
{
struct eap_config eapConfig;
+ memset(&eapConfig, 0, sizeof(eapConfig));
+ eapConfig.cert_in_cb = 1;
#ifdef GSSEAP_ENABLE_REAUTH
if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) {
GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
GSSEAP_ASSERT(inputToken == GSS_C_NO_BUFFER);
- memset(&eapConfig, 0, sizeof(eapConfig));
-
ctx->initiatorCtx.eap = eap_peer_sm_init(ctx,
&gssEapPolicyCallbacks,
- ctx,
+ NULL, /* ctx?? */
&eapConfig);
if (ctx->initiatorCtx.eap == NULL) {
*minor = GSSEAP_PEER_SM_INIT_FAILURE;
if (GSS_ERROR(major))
gssEapReleaseContext(&tmpMinor, context_handle);
+ gssEapTraceStatus( "gss_init_sec_context", major, *minor);
return major;
}
+