Support for libradius
[mech_eap.orig] / accept_sec_context.c
index 9de9821..d54fb2a 100644 (file)
 
 #include "gssapiP_eap.h"
 
-#define EAP_MAX_METHODS 8
-
-#define EAP_TTLS_AUTH_PAP 1
-#define EAP_TTLS_AUTH_CHAP 2
-#define EAP_TTLS_AUTH_MSCHAP 4
-#define EAP_TTLS_AUTH_MSCHAPV2 8
-
-#if 1
-struct eap_user {
-        struct {
-                int vendor;
-                u32 method;
-        } methods[EAP_MAX_METHODS];
-        u8 *password;
-        size_t password_len;
-        int password_hash; /* whether password is hashed with
-                            * nt_password_hash() */
-        int phase2;
-        int force_version;
-        int ttls_auth; /* bitfield of
-                        * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
-};
-
-struct eap_eapol_interface {
-        /* Lower layer to full authenticator variables */
-        Boolean eapResp; /* shared with EAPOL Backend Authentication */
-        struct wpabuf *eapRespData;
-        Boolean portEnabled;
-        int retransWhile;
-        Boolean eapRestart; /* shared with EAPOL Authenticator PAE */
-        int eapSRTT;
-        int eapRTTVAR;
-
-        /* Full authenticator to lower layer variables */
-        Boolean eapReq; /* shared with EAPOL Backend Authentication */
-        Boolean eapNoReq; /* shared with EAPOL Backend Authentication */
-        Boolean eapSuccess;
-        Boolean eapFail;
-        Boolean eapTimeout;
-        struct wpabuf *eapReqData;
-        u8 *eapKeyData;
-        size_t eapKeyDataLen;
-        Boolean eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */
-
-        /* AAA interface to full authenticator variables */
-        Boolean aaaEapReq;
-        Boolean aaaEapNoReq;
-        Boolean aaaSuccess;
-        Boolean aaaFail;
-        struct wpabuf *aaaEapReqData;
-        u8 *aaaEapKeyData;
-        size_t aaaEapKeyDataLen;
-        Boolean aaaEapKeyAvailable;
-        int aaaMethodTimeout;
-
-        /* Full authenticator to AAA interface variables */
-        Boolean aaaEapResp;
-        struct wpabuf *aaaEapRespData;
-        /* aaaIdentity -> eap_get_identity() */
-        Boolean aaaTimeout;
-};
-
-#define eapol_callbacks     SERVER_eapol_callbacks
-
-struct eapol_callbacks {
-        int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
-                            int phase2, struct eap_user *user);
-        const char * (*get_eap_req_id_text)(void *ctx, size_t *len);
-};
-
-#define eap_config          SERVER_eap_config
-
-struct eap_config {
-        void *ssl_ctx;
-        void *msg_ctx;
-        void *eap_sim_db_priv;
-        Boolean backend_auth;
-        int eap_server;
-        u8 *pac_opaque_encr_key;
-        u8 *eap_fast_a_id;
-        size_t eap_fast_a_id_len;
-        char *eap_fast_a_id_info;
-        int eap_fast_prov;
-        int pac_key_lifetime;
-        int pac_key_refresh_time;
-        int eap_sim_aka_result_ind;
-        int tnc;
-        struct wps_context *wps;
-        const struct wpabuf *assoc_wps_ie;
-        const u8 *peer_addr;
-        int fragment_size;
-};
-
-struct eap_sm * eap_server_sm_init(void *eapol_ctx,
-                                   struct eapol_callbacks *eapol_cb,
-                                   struct eap_config *eap_conf);
-void eap_server_sm_deinit(struct eap_sm *sm);
-int eap_server_sm_step(struct eap_sm *sm);
-void eap_sm_notify_cached(struct eap_sm *sm);
-void eap_sm_pending_cb(struct eap_sm *sm);
-int eap_sm_method_pending(struct eap_sm *sm);
-const u8 * eap_get_identity(struct eap_sm *sm, size_t *len);
-struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm);
-
-#include <eap_server/eap_i.h>
-
-static OM_uint32
-initTls(OM_uint32 *minor,
-        gss_ctx_id_t ctx)
-{
-    struct tls_config tconf;
-    struct tls_connection_params tparams;
-
-    memset(&tconf, 0, sizeof(tconf));
-    ctx->acceptorCtx.tlsContext = tls_init(&tconf);
-    if (ctx->acceptorCtx.tlsContext == NULL)
-        return GSS_S_FAILURE;
-
-    memset(&tparams, 0, sizeof(tparams));
-    tparams.ca_cert = "ca.pem";
-    tparams.client_cert = "server.pem";
-    tparams.private_key = "server-key.pem";
-
-    if (tls_global_set_params(ctx->acceptorCtx.tlsContext, &tparams)) {
-        return GSS_S_FAILURE;
-    }
-
-    if (tls_global_set_verify(ctx->acceptorCtx.tlsContext, 0)) {
-        return GSS_S_FAILURE;
-    }
-
-    return GSS_S_COMPLETE;
-}
-
-static int
-serverGetEapUser(void *ctx,
-                 const unsigned char *identity,
-                 size_t identityLength,
-                 int phase2,
-                 struct eap_user *user)
-{
-    gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
-    OM_uint32 major, minor;
-    gss_buffer_desc buf;
-
-    memset(user, 0, sizeof(*user));
-
-    buf.length = identityLength;
-    buf.value = (void *)identity;
-
-    if (phase2 == 0) {
-        user->methods[0].vendor = EAP_VENDOR_IETF;
-        user->methods[0].method = EAP_TYPE_PEAP;
-        return 0;
-    }
-
-    major = gssEapImportName(&minor, &buf, GSS_C_NT_USER_NAME,
-                             &gssCtx->initiatorName);
-    if (GSS_ERROR(major))
-        return -1;
-
-    /*
-     * OK, obviously there is no real security here, this is simply
-     * for testing the token exchange; this code will be completely
-     * replaced with libradsec once that library is available.
-     */
-    user->methods[0].vendor = EAP_VENDOR_IETF;
-    user->methods[0].method = EAP_TYPE_MSCHAPV2;
-    user->password = (unsigned char *)strdup(" ");
-    user->password_len = 1;
-
-    return 0;
-}
-
-static const char *
-serverGetEapReqIdText(void *ctx,
-                      size_t *len)
-{
-    *len = 0;
-    return NULL;
-}
-#endif
+#define RC_CONFIG_FILE      SYSCONFDIR "/radiusclient/radiusclient.conf"
 
+/*
+ * Mark a context as ready for cryptographic operations
+ */
 static OM_uint32
 acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx)
 {
     OM_uint32 major;
+    VALUE_PAIR *vp;
+    gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
 
     /* Cache encryption type derived from selected mechanism OID */
-    major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &ctx->encryptionType);
+    major = gssEapOidToEnctype(minor, ctx->mechanismUsed,
+                               &ctx->encryptionType);
     if (GSS_ERROR(major))
         return major;
 
-    if (ctx->encryptionType != ENCTYPE_NULL &&
-        ctx->acceptorCtx.eapPolInterface->eapKeyAvailable) {
-        major = rfc3961EncTypeToChecksumType(minor, ctx->encryptionType,
-                                             &ctx->checksumType);
-        if (GSS_ERROR(major))
-            return major;
+    vp = rc_avpair_get(ctx->acceptorCtx.avps, PW_USER_NAME, 0);
+    if (vp != NULL) {
+        nameBuf.length = vp->lvalue;
+        nameBuf.value = vp->strvalue;
+    } else {
+        ctx->gssFlags |= GSS_C_ANON_FLAG;
+    }
 
+    major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
+                             &ctx->initiatorName);
+    if (GSS_ERROR(major))
+        return major;
+
+    vp = rc_avpair_get(ctx->acceptorCtx.avps, PW_MSCHAP2_SUCCESS, 0);
+    if (ctx->encryptionType != ENCTYPE_NULL && vp != NULL) {
         major = gssEapDeriveRfc3961Key(minor,
-                                       ctx->acceptorCtx.eapPolInterface->eapKeyData,
-                                       ctx->acceptorCtx.eapPolInterface->eapKeyDataLen,
+                                       (unsigned char *)vp->strvalue,
+                                       vp->lvalue,
                                        ctx->encryptionType,
                                        &ctx->rfc3961Key);
         if (GSS_ERROR(major))
             return major;
+
+        major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
+                                           &ctx->checksumType);
+        if (GSS_ERROR(major))
+            return major;
     } else {
         /*
          * draft-howlett-eap-gss says that integrity/confidentialty should
@@ -248,10 +86,13 @@ acceptReady(OM_uint32 *minor, gss_ctx_id_t ctx)
         ctx->gssFlags &= ~(GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
     }
 
-    sequenceInit(&ctx->seqState, ctx->recvSeq,
-                 ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
-                 ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
-                 TRUE);
+    major = sequenceInit(minor,
+                         &ctx->seqState, ctx->recvSeq,
+                         ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
+                         ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
+                         TRUE);
+    if (GSS_ERROR(major))
+        return major;
 
     return GSS_S_COMPLETE;
 }
@@ -265,30 +106,26 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
                            gss_buffer_t outputToken)
 {
     OM_uint32 major;
-    OM_uint32 tmpMinor, tmpMajor;
+    OM_uint32 service = PW_AUTHENTICATE_ONLY;
     int code;
-    struct wpabuf respData;
-    static struct eapol_callbacks cb = { serverGetEapUser, serverGetEapReqIdText };
-    if (ctx->acceptorCtx.eap == NULL) {
-        struct eap_config eapConfig;
-
-        major = initTls(minor, ctx);
-        if (GSS_ERROR(major))
+    VALUE_PAIR *send = NULL;
+    VALUE_PAIR *received = NULL;
+    rc_handle *rh = ctx->acceptorCtx.radHandle;
+    char msgBuffer[4096];
+
+    if (rh == NULL) {
+        rh = ctx->acceptorCtx.radHandle = rc_read_config(RC_CONFIG_FILE);
+        if (rh == NULL) {
+            *minor = errno;
+            major = GSS_S_FAILURE;
             goto cleanup;
+        }
 
-        memset(&eapConfig, 0, sizeof(eapConfig));
-        eapConfig.eap_server = 1;
-        eapConfig.ssl_ctx = ctx->acceptorCtx.tlsContext;
-
-        ctx->acceptorCtx.eap = eap_server_sm_init(ctx, &cb, &eapConfig);
-        if (ctx->acceptorCtx.eap == NULL) {
+        if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) {
+            *minor = errno;
             major = GSS_S_FAILURE;
             goto cleanup;
         }
-
-        ctx->acceptorCtx.eapPolInterface = eap_get_interface(ctx->acceptorCtx.eap);
-        ctx->acceptorCtx.eapPolInterface->portEnabled = TRUE;
-        ctx->acceptorCtx.eapPolInterface->eapRestart = TRUE;
     }
 
     if (ctx->acceptorName == GSS_C_NO_NAME &&
@@ -299,48 +136,61 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
             goto cleanup;
     }
 
-    wpabuf_set(&respData, inputToken->value, inputToken->length);
-    ctx->acceptorCtx.eapPolInterface->eapRespData = &respData;
-    ctx->acceptorCtx.eapPolInterface->eapResp = TRUE;
+    if (rc_avpair_add(rh, &send, PW_EAP_MESSAGE,
+                      inputToken->value, inputToken->length, 0) == NULL) {
+        *minor = ENOMEM;
+        major = GSS_S_FAILURE;
+        goto cleanup;
+    }
 
-    code = eap_server_sm_step(ctx->acceptorCtx.eap);
+    if (rc_avpair_add(rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
+        *minor = ENOMEM;
+        major = GSS_S_FAILURE;
+        goto cleanup;
+    }
 
-    if (ctx->acceptorCtx.eapPolInterface->eapReq) {
-        ctx->acceptorCtx.eapPolInterface->eapReq = 0;
-        major = GSS_S_CONTINUE_NEEDED;
+    code = rc_auth(rh, 0, send, &received, msgBuffer);
+    if (code != 0) {
+        *minor = errno;
+        major = GSS_S_UNAVAILABLE;
+        goto cleanup;
     }
 
-    if (ctx->acceptorCtx.eapPolInterface->eapSuccess) {
-        ctx->acceptorCtx.eapPolInterface->eapSuccess = 0;
-        major = acceptReady(minor, ctx);
+    if (code == OK_RC || code == PW_ACCESS_CHALLENGE) {
+        VALUE_PAIR *eapResponse;
+        gss_buffer_desc eapBuf = GSS_C_EMPTY_BUFFER;
+
+        eapResponse = rc_avpair_get(received, PW_EAP_MESSAGE, 0);
+        if (eapResponse != NULL) {
+            eapBuf.length = eapResponse->lvalue;
+            eapBuf.value = eapResponse->strvalue;
+        }
+
+        major = duplicateBuffer(minor, &eapBuf, outputToken);
         if (GSS_ERROR(major))
             goto cleanup;
 
-        ctx->state = EAP_STATE_GSS_CHANNEL_BINDINGS;
         major = GSS_S_CONTINUE_NEEDED;
-    } else if (ctx->acceptorCtx.eapPolInterface->eapFail) {
-        ctx->acceptorCtx.eapPolInterface->eapFail = 0;
-        major = GSS_S_FAILURE;
-    } else if (code == 0) {
+    } else {
         major = GSS_S_FAILURE;
+        goto cleanup;
     }
 
-    if (ctx->acceptorCtx.eapPolInterface->eapReqData != NULL) {
-        gss_buffer_desc buf;
+    if (code == OK_RC) {
+        ctx->acceptorCtx.avps = received;
+        received = NULL;
 
-        buf.length = wpabuf_len(ctx->acceptorCtx.eapPolInterface->eapReqData);
-        buf.value = (void *)wpabuf_head(ctx->acceptorCtx.eapPolInterface->eapReqData);
-
-        tmpMajor = duplicateBuffer(&tmpMinor, &buf, outputToken);
-        if (GSS_ERROR(tmpMajor)) {
-            major = tmpMajor;
-            *minor = tmpMinor;
+        major = acceptReady(minor, ctx);
+        if (GSS_ERROR(major))
             goto cleanup;
-        }
+
+        ctx->state = EAP_STATE_GSS_CHANNEL_BINDINGS;
+        major = GSS_S_CONTINUE_NEEDED;
     }
 
 cleanup:
-    ctx->acceptorCtx.eapPolInterface->eapRespData = NULL;
+    if (received != NULL)
+        rc_avpair_free(received);
 
     return major;
 }
@@ -411,7 +261,7 @@ eapGssSmAcceptEstablished(OM_uint32 *minor,
     return GSS_S_BAD_STATUS;
 }
 
-static struct eap_gss_acceptor_sm {
+static struct gss_eap_acceptor_sm {
     enum gss_eap_token_type inputTokenType;
     enum gss_eap_token_type outputTokenType;
     OM_uint32 (*processToken)(OM_uint32 *,
@@ -446,14 +296,12 @@ gss_accept_sec_context(OM_uint32 *minor,
     OM_uint32 major;
     OM_uint32 tmpMajor, tmpMinor;
     gss_ctx_id_t ctx = *context_handle;
-    struct eap_gss_acceptor_sm *sm = NULL;
-    gss_buffer_desc innerInputToken, innerOutputToken;
+    struct gss_eap_acceptor_sm *sm = NULL;
+    gss_buffer_desc innerInputToken = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER;
 
     *minor = 0;
 
-    innerOutputToken.length = 0;
-    innerOutputToken.value = NULL;
-
     output_token->length = 0;
     output_token->value = NULL;
 
@@ -541,3 +389,4 @@ cleanup:
 
     return major;
 }
+