Blame src/gp_rpc_init_sec_context.c

Packit Service 9f2c4a
/* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */
Packit Service 9f2c4a
Packit Service 9f2c4a
#include "gp_rpc_process.h"
Packit Service 9f2c4a
#include <gssapi/gssapi_krb5.h>
Packit Service 9f2c4a
Packit Service 9f2c4a
int gp_init_sec_context(struct gp_call_ctx *gpcall,
Packit Service 9f2c4a
                        union gp_rpc_arg *arg,
Packit Service 9f2c4a
                        union gp_rpc_res *res)
Packit Service 9f2c4a
{
Packit Service 9f2c4a
    struct gssx_arg_init_sec_context *isca;
Packit Service 9f2c4a
    struct gssx_res_init_sec_context *iscr;
Packit Service 9f2c4a
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
Packit Service 9f2c4a
    gss_cred_id_t ich = GSS_C_NO_CREDENTIAL;
Packit Service 9f2c4a
    gss_name_t target_name = GSS_C_NO_NAME;
Packit Service 9f2c4a
    gss_OID mech_type = GSS_C_NO_OID;
Packit Service 9f2c4a
    uint32_t req_flags;
Packit Service 9f2c4a
    uint32_t time_req;
Packit Service 9f2c4a
    struct gss_channel_bindings_struct cbs;
Packit Service 9f2c4a
    gss_channel_bindings_t pcbs;
Packit Service 9f2c4a
    gss_buffer_desc ibuf = { 0, NULL };
Packit Service 9f2c4a
    gss_buffer_t pibuf = &ibuf;
Packit Service 9f2c4a
    gss_OID actual_mech_type = GSS_C_NO_OID;
Packit Service 9f2c4a
    gss_buffer_desc obuf = GSS_C_EMPTY_BUFFER;
Packit Service 9f2c4a
    uint32_t ret_maj;
Packit Service 9f2c4a
    uint32_t ret_min;
Packit Service 9f2c4a
    uint32_t init_maj;
Packit Service 9f2c4a
    uint32_t init_min;
Packit Service 9f2c4a
    int exp_ctx_type;
Packit Service 9f2c4a
    struct gp_cred_check_handle gcch = {
Packit Service 9f2c4a
        .ctx = gpcall,
Packit Service 9f2c4a
        .options.options_len = arg->init_sec_context.options.options_len,
Packit Service 9f2c4a
        .options.options_val = arg->init_sec_context.options.options_val,
Packit Service 9f2c4a
    };
Packit Service 9f2c4a
    uint32_t gccn_before = 0;
Packit Service 9f2c4a
    uint32_t gccn_after = 0;
Packit Service 9f2c4a
    int ret;
Packit Service 9f2c4a
Packit Service 9f2c4a
    isca = &arg->init_sec_context;
Packit Service 9f2c4a
    iscr = &res->init_sec_context;
Packit Service 9f2c4a
Packit Service 9f2c4a
    GPRPCDEBUG(gssx_arg_init_sec_context, isca);
Packit Service 9f2c4a
Packit Service 9f2c4a
    exp_ctx_type = gp_get_exported_context_type(&isca->call_ctx);
Packit Service 9f2c4a
    if (exp_ctx_type == -1) {
Packit Service 9f2c4a
        ret_maj = GSS_S_FAILURE;
Packit Service 9f2c4a
        ret_min = EINVAL;
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (isca->context_handle) {
Packit Service 9f2c4a
        ret_maj = gp_import_gssx_to_ctx_id(&ret_min, 0,
Packit Service 9f2c4a
                                           isca->context_handle, &ctx;;
Packit Service 9f2c4a
        if (ret_maj) {
Packit Service 9f2c4a
            goto done;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (isca->cred_handle) {
Packit Service 9f2c4a
        ret_maj = gp_import_gssx_cred(&ret_min, gpcall,
Packit Service 9f2c4a
                                      isca->cred_handle, &ich;;
Packit Service 9f2c4a
        if (ret_maj) {
Packit Service 9f2c4a
            goto done;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
Packit Service 9f2c4a
        gccn_before = gp_check_sync_creds(&gcch, ich);
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret_maj = gp_conv_gssx_to_name(&ret_min, isca->target_name, &target_name);
Packit Service 9f2c4a
    if (ret_maj) {
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret = gp_conv_gssx_to_oid_alloc(&isca->mech_type, &mech_type);
Packit Service 9f2c4a
    if (ret) {
Packit Service 9f2c4a
        ret_maj = GSS_S_FAILURE;
Packit Service 9f2c4a
        ret_min = ret;
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    req_flags = isca->req_flags;
Packit Service 9f2c4a
    time_req = isca->time_req;
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (isca->input_cb) {
Packit Service 9f2c4a
        pcbs = &cb;;
Packit Service 9f2c4a
        gp_conv_gssx_to_cb(isca->input_cb, pcbs);
Packit Service 9f2c4a
    } else {
Packit Service 9f2c4a
        pcbs = GSS_C_NO_CHANNEL_BINDINGS;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (isca->input_token) {
Packit Service 9f2c4a
        gp_conv_gssx_to_buffer(isca->input_token, &ibuf);
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (!ich) {
Packit Service 9f2c4a
        if (gss_oid_equal(mech_type, gss_mech_krb5)) {
Packit Service 9f2c4a
            ret_maj = gp_add_krb5_creds(&ret_min, gpcall,
Packit Service 9f2c4a
                                        ACQ_NORMAL, NULL, NULL,
Packit Service 9f2c4a
                                        GSS_C_INITIATE,
Packit Service 9f2c4a
                                        time_req, 0, &ich,
Packit Service 9f2c4a
                                        NULL, NULL, NULL);
Packit Service 9f2c4a
        } else {
Packit Service 9f2c4a
            ret_maj = GSS_S_NO_CRED;
Packit Service 9f2c4a
            ret_min = 0;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
Packit Service 9f2c4a
        if (ret_maj) {
Packit Service 9f2c4a
            goto done;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret_maj = gp_cred_allowed(&ret_min, gpcall, ich, target_name);
Packit Service 9f2c4a
    if (ret_maj) {
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    gp_filter_flags(gpcall, &req_flags);
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret_maj = gss_init_sec_context(&ret_min,
Packit Service 9f2c4a
                                   ich,
Packit Service 9f2c4a
                                   &ctx,
Packit Service 9f2c4a
                                   target_name,
Packit Service 9f2c4a
                                   mech_type,
Packit Service 9f2c4a
                                   req_flags,
Packit Service 9f2c4a
                                   time_req,
Packit Service 9f2c4a
                                   pcbs,
Packit Service 9f2c4a
                                   pibuf,
Packit Service 9f2c4a
                                   &actual_mech_type,
Packit Service 9f2c4a
                                   &obuf,
Packit Service 9f2c4a
                                   NULL,
Packit Service 9f2c4a
                                   NULL);
Packit Service 9f2c4a
    if (ret_maj != GSS_S_COMPLETE &&
Packit Service 9f2c4a
        ret_maj != GSS_S_CONTINUE_NEEDED) {
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    } else {
Packit Service 9f2c4a
        init_maj = ret_maj;
Packit Service 9f2c4a
        init_min = ret_min;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    if (init_maj == GSS_S_CONTINUE_NEEDED) {
Packit Service 9f2c4a
        exp_ctx_type = gp_get_continue_needed_type();
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    iscr->context_handle = calloc(1, sizeof(gssx_ctx));
Packit Service 9f2c4a
    if (!iscr->context_handle) {
Packit Service 9f2c4a
        ret_maj = GSS_S_FAILURE;
Packit Service 9f2c4a
        ret_min = ENOMEM;
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, mech_type,
Packit Service 9f2c4a
                                       &ctx, iscr->context_handle);
Packit Service 9f2c4a
    if (ret_maj) {
Packit Service 9f2c4a
        goto done;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (obuf.length != 0) {
Packit Service 9f2c4a
        iscr->output_token = calloc(1, sizeof(gssx_buffer));
Packit Service 9f2c4a
        if (!iscr->output_token) {
Packit Service 9f2c4a
            ret_maj = GSS_S_FAILURE;
Packit Service 9f2c4a
            ret_min = ENOMEM;
Packit Service 9f2c4a
            goto done;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
        ret = gp_conv_buffer_to_gssx(&obuf, iscr->output_token);
Packit Service 9f2c4a
        if (ret) {
Packit Service 9f2c4a
            ret_maj = GSS_S_FAILURE;
Packit Service 9f2c4a
            ret_min = ret;
Packit Service 9f2c4a
            goto done;
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    gccn_after = gp_check_sync_creds(&gcch, ich);
Packit Service 9f2c4a
Packit Service 9f2c4a
    if (gccn_before != gccn_after) {
Packit Service 9f2c4a
        /* export creds back to client for sync up */
Packit Service 9f2c4a
        ret_maj = gp_export_sync_creds(&ret_min, gpcall, &ich,
Packit Service 9f2c4a
                                       &iscr->options.options_val,
Packit Service 9f2c4a
                                       &iscr->options.options_len);
Packit Service 9f2c4a
        if (ret_maj) {
Packit Service 9f2c4a
            /* not fatal, log and continue */
Packit Service 9f2c4a
            GPDEBUG("Failed to export sync creds (%d: %d)",
Packit Service 9f2c4a
                    (int)ret_maj, (int)ret_min);
Packit Service 9f2c4a
        }
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
Packit Service 9f2c4a
    ret_maj = GSS_S_COMPLETE;
Packit Service 9f2c4a
Packit Service 9f2c4a
done:
Packit Service 9f2c4a
    if (ret_maj == GSS_S_COMPLETE) {
Packit Service 9f2c4a
        ret_maj = init_maj;
Packit Service 9f2c4a
        ret_min = init_min;
Packit Service 9f2c4a
    }
Packit Service 9f2c4a
    ret = gp_conv_status_to_gssx(ret_maj, ret_min, mech_type,
Packit Service 9f2c4a
                                 &iscr->status);
Packit Service 9f2c4a
Packit Service 9f2c4a
    GPRPCDEBUG(gssx_res_init_sec_context, iscr);
Packit Service 9f2c4a
Packit Service 9f2c4a
    gss_release_name(&ret_min, &target_name);
Packit Service 9f2c4a
    gss_release_oid(&ret_min, &mech_type);
Packit Service 9f2c4a
    gss_release_cred(&ret_min, &ich;;
Packit Service 9f2c4a
    gss_release_buffer(&ret_min, &obuf);
Packit Service 9f2c4a
    return ret;
Packit Service 9f2c4a
}