check radsec config when acquiring acceptor cred
[moonshot.git] / moonshot / mech_eap / accept_sec_context.c
index afbd554..e503477 100644 (file)
@@ -328,7 +328,7 @@ setAcceptorIdentity(OM_uint32 *minor,
     krb5_principal krbPrinc;
     struct rs_context *rc = ctx->acceptorCtx.radContext;
 
-    assert(rc != NULL);
+    GSSEAP_ASSERT(rc != NULL);
 
     if (ctx->acceptorName == GSS_C_NO_NAME) {
         *minor = 0;
@@ -343,8 +343,8 @@ setAcceptorIdentity(OM_uint32 *minor,
     GSSEAP_KRB_INIT(&krbContext);
 
     krbPrinc = ctx->acceptorName->krbPrincipal;
-    assert(krbPrinc != NULL);
-    assert(KRB_PRINC_LENGTH(krbPrinc) >= 2);
+    GSSEAP_ASSERT(krbPrinc != NULL);
+    GSSEAP_ASSERT(KRB_PRINC_LENGTH(krbPrinc) >= 2);
 
     /* Acceptor-Service-Name */
     krbPrincComponentToGssBuffer(krbPrinc, 0, &nameBuf);
@@ -418,58 +418,35 @@ createRadiusHandle(OM_uint32 *minor,
                    gss_ctx_id_t ctx)
 {
     struct gss_eap_acceptor_ctx *actx = &ctx->acceptorCtx;
-    const char *configFile = RS_CONFIG_FILE;
-    const char *configStanza = "gss-eap";
-    struct rs_alloc_scheme ralloc;
     struct rs_error *err;
+    const char *configStanza = "gss-eap";
+    OM_uint32 major;
 
-    assert(actx->radContext == NULL);
-    assert(actx->radConn == NULL);
+    GSSEAP_ASSERT(actx->radContext == NULL);
+    GSSEAP_ASSERT(actx->radConn == NULL);
+    GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
 
-    if (rs_context_create(&actx->radContext) != 0) {
-        *minor = GSSEAP_RADSEC_CONTEXT_FAILURE;
-        return GSS_S_FAILURE;
-    }
+    major = gssEapCreateRadiusContext(minor, cred, &actx->radContext);
+    if (GSS_ERROR(major))
+        return major;
 
-    if (cred->radiusConfigFile.value != NULL)
-        configFile = (const char *)cred->radiusConfigFile.value;
     if (cred->radiusConfigStanza.value != NULL)
         configStanza = (const char *)cred->radiusConfigStanza.value;
 
-    ralloc.calloc  = GSSEAP_CALLOC;
-    ralloc.malloc  = GSSEAP_MALLOC;
-    ralloc.free    = GSSEAP_FREE;
-    ralloc.realloc = GSSEAP_REALLOC;
-
-    rs_context_set_alloc_scheme(actx->radContext, &ralloc);
-
-    if (rs_context_read_config(actx->radContext, configFile) != 0) {
-        err = rs_err_ctx_pop(actx->radContext);
-        goto fail;
-    }
-
-    if (rs_context_init_freeradius_dict(actx->radContext, NULL) != 0) {
-        err = rs_err_ctx_pop(actx->radContext);
-        goto fail;
-    }
-
     if (rs_conn_create(actx->radContext, &actx->radConn, configStanza) != 0) {
         err = rs_err_conn_pop(actx->radConn);
-        goto fail;
+        return gssEapRadiusMapError(minor, err);
     }
 
     if (actx->radServer != NULL) {
         if (rs_conn_select_peer(actx->radConn, actx->radServer) != 0) {
             err = rs_err_conn_pop(actx->radConn);
-            goto fail;
+            return gssEapRadiusMapError(minor, err);
         }
     }
 
     *minor = 0;
     return GSS_S_COMPLETE;
-
-fail:
-    return gssEapRadiusMapError(minor, err);
 }
 
 /*
@@ -550,7 +527,7 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor,
         goto cleanup;
     }
 
-    assert(resp != NULL);
+    GSSEAP_ASSERT(resp != NULL);
 
     frresp = rs_packet_frpkt(resp);
     switch (frresp->code) {
@@ -606,7 +583,7 @@ cleanup:
     if (resp != NULL)
         rs_packet_destroy(resp);
     if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIATOR_EXTS) {
-        assert(major == GSS_S_CONTINUE_NEEDED);
+        GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED);
 
         rs_conn_destroy(ctx->acceptorCtx.radConn);
         ctx->acceptorCtx.radConn = NULL;
@@ -616,6 +593,40 @@ cleanup:
 }
 
 static OM_uint32
+eapGssSmAcceptGssFlags(OM_uint32 *minor,
+                       gss_cred_id_t cred GSSEAP_UNUSED,
+                       gss_ctx_id_t ctx,
+                       gss_name_t target GSSEAP_UNUSED,
+                       gss_OID mech GSSEAP_UNUSED,
+                       OM_uint32 reqFlags GSSEAP_UNUSED,
+                       OM_uint32 timeReq GSSEAP_UNUSED,
+                       gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+                       gss_buffer_t inputToken,
+                       gss_buffer_t outputToken GSSEAP_UNUSED,
+                       OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+    unsigned char *p;
+    OM_uint32 initiatorGssFlags;
+
+    GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
+
+    if (inputToken->length < 4) {
+        *minor = GSSEAP_TOK_TRUNC;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /* allow flags to grow for future expansion */
+    p = (unsigned char *)inputToken->value + inputToken->length - 4;
+
+    initiatorGssFlags = load_uint32_be(p);
+    initiatorGssFlags &= GSSEAP_WIRE_FLAGS_MASK;
+
+    ctx->gssFlags |= initiatorGssFlags;
+
+    return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
 eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
                                  gss_cred_id_t cred GSSEAP_UNUSED,
                                  gss_ctx_id_t ctx,
@@ -628,20 +639,26 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
                                  gss_buffer_t outputToken GSSEAP_UNUSED,
                                  OM_uint32 *smFlags GSSEAP_UNUSED)
 {
-    OM_uint32 major, tmpMinor;
+    OM_uint32 major;
     gss_iov_buffer_desc iov[2];
 
     iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
     iov[0].buffer.length = 0;
     iov[0].buffer.value = NULL;
 
-    iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM;
-    iov[1].buffer = *inputToken;
+    iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM | GSS_IOV_BUFFER_FLAG_ALLOCATED;
+
+    /* XXX necessary because decrypted in place and we verify it later */
+    major = duplicateBuffer(minor, inputToken, &iov[1].buffer);
+    if (GSS_ERROR(major))
+        return major;
 
     major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
                                     iov, 2, TOK_TYPE_WRAP);
-    if (GSS_ERROR(major))
+    if (GSS_ERROR(major)) {
+        gssEapReleaseIov(iov, 2);
         return major;
+    }
 
     if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS &&
         !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
@@ -652,11 +669,36 @@ eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
         *minor = 0;
     }
 
-    gss_release_buffer(&tmpMinor, &iov[0].buffer);
+    gssEapReleaseIov(iov, 2);
 
     return major;
 }
 
+static OM_uint32
+eapGssSmAcceptInitiatorMIC(OM_uint32 *minor,
+                           gss_cred_id_t cred GSSEAP_UNUSED,
+                           gss_ctx_id_t ctx,
+                           gss_name_t target GSSEAP_UNUSED,
+                           gss_OID mech GSSEAP_UNUSED,
+                           OM_uint32 reqFlags GSSEAP_UNUSED,
+                           OM_uint32 timeReq GSSEAP_UNUSED,
+                           gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+                           gss_buffer_t inputToken,
+                           gss_buffer_t outputToken GSSEAP_UNUSED,
+                           OM_uint32 *smFlags GSSEAP_UNUSED)
+{
+    OM_uint32 major;
+
+    major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
+    if (GSS_ERROR(major))
+        return major;
+
+    GSSEAP_SM_TRANSITION_NEXT(ctx);
+
+    *minor = 0;
+    return GSS_S_CONTINUE_NEEDED;
+}
+
 #ifdef GSSEAP_ENABLE_REAUTH
 static OM_uint32
 eapGssSmAcceptReauthCreds(OM_uint32 *minor,
@@ -688,42 +730,28 @@ eapGssSmAcceptReauthCreds(OM_uint32 *minor,
 #endif
 
 static OM_uint32
-eapGssSmAcceptCompleteInitiatorExts(OM_uint32 *minor,
-                                    gss_cred_id_t cred GSSEAP_UNUSED,
-                                    gss_ctx_id_t ctx,
-                                    gss_name_t target GSSEAP_UNUSED,
-                                    gss_OID mech GSSEAP_UNUSED,
-                                    OM_uint32 reqFlags GSSEAP_UNUSED,
-                                    OM_uint32 timeReq GSSEAP_UNUSED,
-                                    gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
-                                    gss_buffer_t inputToken GSSEAP_UNUSED,
-                                    gss_buffer_t outputToken GSSEAP_UNUSED,
-                                    OM_uint32 *smFlags GSSEAP_UNUSED)
+eapGssSmAcceptAcceptorMIC(OM_uint32 *minor,
+                          gss_cred_id_t cred GSSEAP_UNUSED,
+                          gss_ctx_id_t ctx,
+                          gss_name_t target GSSEAP_UNUSED,
+                          gss_OID mech GSSEAP_UNUSED,
+                          OM_uint32 reqFlags GSSEAP_UNUSED,
+                          OM_uint32 timeReq GSSEAP_UNUSED,
+                          gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
+                          gss_buffer_t inputToken GSSEAP_UNUSED,
+                          gss_buffer_t outputToken,
+                          OM_uint32 *smFlags)
 {
-    GSSEAP_SM_TRANSITION_NEXT(ctx);
-
-    *minor = 0;
+    OM_uint32 major;
 
-    return GSS_S_CONTINUE_NEEDED;
-}
+    major = gssEapMakeTokenMIC(minor, ctx, outputToken);
+    if (GSS_ERROR(major))
+        return major;
 
-static OM_uint32
-eapGssSmAcceptCompleteAcceptorExts(OM_uint32 *minor,
-                                   gss_cred_id_t cred GSSEAP_UNUSED,
-                                   gss_ctx_id_t ctx,
-                                   gss_name_t target GSSEAP_UNUSED,
-                                   gss_OID mech GSSEAP_UNUSED,
-                                   OM_uint32 reqFlags GSSEAP_UNUSED,
-                                   OM_uint32 timeReq GSSEAP_UNUSED,
-                                   gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
-                                   gss_buffer_t inputToken GSSEAP_UNUSED,
-                                   gss_buffer_t outputToken GSSEAP_UNUSED,
-                                   OM_uint32 *smFlags)
-{
     GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
 
     *minor = 0;
-    *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
+    *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
 
     return GSS_S_COMPLETE;
 }
@@ -769,6 +797,13 @@ static struct gss_eap_sm eapGssAcceptorSm[] = {
         eapGssSmAcceptAuthenticate
     },
     {
+        ITOK_TYPE_GSS_FLAGS,
+        ITOK_TYPE_NONE,
+        GSSEAP_STATE_INITIATOR_EXTS,
+        0,
+        eapGssSmAcceptGssFlags
+    },
+    {
         ITOK_TYPE_GSS_CHANNEL_BINDINGS,
         ITOK_TYPE_NONE,
         GSSEAP_STATE_INITIATOR_EXTS,
@@ -776,11 +811,11 @@ static struct gss_eap_sm eapGssAcceptorSm[] = {
         eapGssSmAcceptGssChannelBindings,
     },
     {
-        ITOK_TYPE_NONE,
+        ITOK_TYPE_INITIATOR_MIC,
         ITOK_TYPE_NONE,
         GSSEAP_STATE_INITIATOR_EXTS,
-        0,
-        eapGssSmAcceptCompleteInitiatorExts,
+        SM_ITOK_FLAG_REQUIRED,
+        eapGssSmAcceptInitiatorMIC,
     },
 #ifdef GSSEAP_ENABLE_REAUTH
     {
@@ -793,16 +828,16 @@ static struct gss_eap_sm eapGssAcceptorSm[] = {
 #endif
     {
         ITOK_TYPE_NONE,
-        ITOK_TYPE_NONE,
+        ITOK_TYPE_ACCEPTOR_MIC,
         GSSEAP_STATE_ACCEPTOR_EXTS,
         0,
-        eapGssSmAcceptCompleteAcceptorExts
+        eapGssSmAcceptAcceptorMIC
     },
 };
 
 OM_uint32
-gss_accept_sec_context(OM_uint32 *minor,
-                       gss_ctx_id_t *context_handle,
+gssEapAcceptSecContext(OM_uint32 *minor,
+                       gss_ctx_id_t ctx,
                        gss_cred_id_t cred,
                        gss_buffer_t input_token,
                        gss_channel_bindings_t input_chan_bindings,
@@ -814,30 +849,6 @@ gss_accept_sec_context(OM_uint32 *minor,
                        gss_cred_id_t *delegated_cred_handle)
 {
     OM_uint32 major, tmpMinor;
-    gss_ctx_id_t ctx = *context_handle;
-
-    *minor = 0;
-
-    output_token->length = 0;
-    output_token->value = NULL;
-
-    if (src_name != NULL)
-        *src_name = GSS_C_NO_NAME;
-
-    if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
-        *minor = GSSEAP_TOK_TRUNC;
-        return GSS_S_DEFECTIVE_TOKEN;
-    }
-
-    if (ctx == GSS_C_NO_CONTEXT) {
-        major = gssEapAllocContext(minor, &ctx);
-        if (GSS_ERROR(major))
-            return major;
-
-        *context_handle = ctx;
-    }
-
-    GSSEAP_MUTEX_LOCK(&ctx->mutex);
 
     if (cred == GSS_C_NO_CREDENTIAL) {
         if (ctx->cred == GSS_C_NO_CREDENTIAL) {
@@ -909,15 +920,11 @@ gss_accept_sec_context(OM_uint32 *minor,
         }
     }
 
-    assert(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
+    GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
 
 cleanup:
     if (cred != GSS_C_NO_CREDENTIAL)
         GSSEAP_MUTEX_UNLOCK(&cred->mutex);
-    GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
-
-    if (GSS_ERROR(major))
-        gssEapReleaseContext(&tmpMinor, context_handle);
 
     return major;
 }
@@ -1003,3 +1010,62 @@ eapGssSmAcceptGssReauth(OM_uint32 *minor,
     return major;
 }
 #endif /* GSSEAP_ENABLE_REAUTH */
+
+OM_uint32 GSSAPI_CALLCONV
+gss_accept_sec_context(OM_uint32 *minor,
+                       gss_ctx_id_t *context_handle,
+                       gss_cred_id_t cred,
+                       gss_buffer_t input_token,
+                       gss_channel_bindings_t input_chan_bindings,
+                       gss_name_t *src_name,
+                       gss_OID *mech_type,
+                       gss_buffer_t output_token,
+                       OM_uint32 *ret_flags,
+                       OM_uint32 *time_rec,
+                       gss_cred_id_t *delegated_cred_handle)
+{
+    OM_uint32 major, tmpMinor;
+    gss_ctx_id_t ctx = *context_handle;
+
+    *minor = 0;
+
+    output_token->length = 0;
+    output_token->value = NULL;
+
+    if (src_name != NULL)
+        *src_name = GSS_C_NO_NAME;
+
+    if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
+        *minor = GSSEAP_TOK_TRUNC;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (ctx == GSS_C_NO_CONTEXT) {
+        major = gssEapAllocContext(minor, &ctx);
+        if (GSS_ERROR(major))
+            return major;
+
+        *context_handle = ctx;
+    }
+
+    GSSEAP_MUTEX_LOCK(&ctx->mutex);
+
+    major = gssEapAcceptSecContext(minor,
+                                   ctx,
+                                   cred,
+                                   input_token,
+                                   input_chan_bindings,
+                                   src_name,
+                                   mech_type,
+                                   output_token,
+                                   ret_flags,
+                                   time_rec,
+                                   delegated_cred_handle);
+
+    GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
+
+    if (GSS_ERROR(major))
+        gssEapReleaseContext(&tmpMinor, context_handle);
+
+    return major;
+}