Пример #1
0
void *server_thread(void *pvt)
{
    const char **argv;
    struct athread *data;
    char buffer[MAX_RPC_SIZE];
    uint32_t buflen;
    gss_buffer_desc in_token = GSS_C_EMPTY_BUFFER;
    uint32_t ret_maj;
    uint32_t ret_min;
    struct gssx_ctx *context_handle = NULL;
    struct gssx_cred *cred_handle = NULL;
    struct gssx_name *src_name = NULL;
    gss_buffer_desc out_token = GSS_C_EMPTY_BUFFER;
    struct gssx_cred *deleg_cred = NULL;
    gss_OID_set mech_set = GSS_C_NO_OID_SET;
    gss_OID_set mech_names = GSS_C_NO_OID_SET;
    gss_OID_set mech_types = GSS_C_NO_OID_SET;
    gss_OID_set mech_attrs = GSS_C_NO_OID_SET;
    gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET;
    gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc short_desc = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc long_desc = GSS_C_EMPTY_BUFFER;
    gss_OID_set mechs = GSS_C_NO_OID_SET;
    gss_buffer_desc target_buf;
    struct gssx_name *target_name = NULL;
    struct gssx_name *canon_name = NULL;
    gss_buffer_desc out_name_buf = GSS_C_EMPTY_BUFFER;
    gss_OID out_name_type = GSS_C_NO_OID;
    gss_buffer_desc msg_token = GSS_C_EMPTY_BUFFER;
    int ret;
    gss_buffer_desc input_message_buffer = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output_message_buffer = GSS_C_EMPTY_BUFFER;
    gss_qop_t qop_state;
    int conf_state;

    data = (struct athread *)pvt;
    argv = data->argv;

    target_buf.value = (void *)data->target;
    target_buf.length = strlen(data->target) + 1;

    /* import name family functions tests */
    ret_maj = gpm_import_name(&ret_min, &target_buf,
                              GSS_C_NT_HOSTBASED_SERVICE, &target_name);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_canonicalize_name(&ret_min, target_name,
                                    discard_const(gss_mech_krb5),
                                    &canon_name);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_display_name(&ret_min, canon_name,
                               &out_name_buf, &out_name_type);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }
    DEBUG("Acquiring for: %s\n", (char *)out_name_buf.value);

    /* indicate mechs family functions tests */
    ret_maj = gpm_indicate_mechs(&ret_min, &mech_set);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    ret_maj = gpm_inquire_names_for_mech(&ret_min,
                                         &mech_set->elements[0],
                                         &mech_names);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(&mech_set->elements[0], ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_inquire_attrs_for_mech(&ret_min,
                                         &mech_set->elements[0],
                                         &mech_attrs,
                                         &known_mech_attrs);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(&mech_set->elements[0], ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_inquire_saslname_for_mech(&ret_min,
                                            &mech_set->elements[0],
                                            &sasl_mech_name,
                                            &mech_name,
                                            &mech_description);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(&mech_set->elements[0], ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_display_mech_attr(&ret_min,
                                    &mech_attrs->elements[0],
                                    &name, &short_desc, &long_desc);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_indicate_mechs_by_attrs(&ret_min,
                                          GSS_C_NO_OID_SET,
                                          GSS_C_NO_OID_SET,
                                          GSS_C_NO_OID_SET,
                                          &mechs);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }
    ret_maj = gpm_inquire_mechs_for_name(&ret_min, target_name, &mech_types);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    ret_maj = gpm_acquire_cred(&ret_min,
                               NULL, NULL,
                               GSS_C_INDEFINITE,
                               mech_set,
                               GSS_C_ACCEPT,
                               false,
                               &cred_handle,
                               NULL,
                               NULL);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    ret = t_recv_buffer(data->srv_pipe[0], buffer, &buflen);
    if (ret) {
        DEBUG("Failed to get data from client!\n");
        goto done;
    }

    in_token.value = buffer;
    in_token.length = buflen;

    ret_maj = gpm_accept_sec_context(&ret_min,
                                     &context_handle,
                                     cred_handle,
                                     &in_token,
                                     GSS_C_NO_CHANNEL_BINDINGS,
                                     &src_name,
                                     NULL,
                                     &out_token,
                                     NULL,
                                     NULL,
                                     &deleg_cred);
    if (ret_maj) {
        DEBUG("gssproxy returned an error: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    if (out_token.length) {
        ret = t_send_buffer(data->cli_pipe[1],
                             out_token.value, out_token.length);
        if (ret) {
            DEBUG("Failed to send data to client!\n");
            goto done;
        }
    }

    /* receive message from client */
    ret = t_recv_buffer(data->srv_pipe[0], buffer, &buflen);
    if (ret) {
        DEBUG("Failed to get data from client!\n");
        goto done;
    }
    in_token.value = buffer;
    in_token.length = buflen;

    /* receive signature from client */
    ret = t_recv_buffer(data->srv_pipe[0],
                         &buffer[in_token.length], &buflen);
    if (ret) {
        DEBUG("Failed to get data from client!\n");
        goto done;
    }
    msg_token.value = &buffer[in_token.length];
    msg_token.length = buflen;

    ret_maj = gpm_verify_mic(&ret_min, context_handle,
                             &in_token, &msg_token, NULL);
    if (ret_maj) {
        DEBUG("gpm_verify_mic failed: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    DEBUG("Received valid msg from client: [%s]\n", buffer);

    ret = t_recv_buffer(data->srv_pipe[0], buffer, &buflen);
    if (ret) {
        DEBUG("Failed to get data from client!\n");
        goto done;
    }

    input_message_buffer.value = buffer;
    input_message_buffer.length = buflen;

    ret_maj = gpm_unwrap(&ret_min,
                         context_handle,
                         &input_message_buffer,
                         &output_message_buffer,
                         &conf_state,
                         &qop_state);
    if (ret_maj) {
        DEBUG("gpm_unwrap failed: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    DEBUG("Received valid msg from client: [%s]\n",
        (char *)output_message_buffer.value);

done:
    gpm_release_name(&ret_min, &src_name);
    gpm_release_buffer(&ret_min, &out_token);
    gpm_release_buffer(&ret_min, &output_message_buffer);
    gpm_release_cred(&ret_min, &deleg_cred);
    gpm_delete_sec_context(&ret_min, &context_handle, GSS_C_NO_BUFFER);
    gss_release_oid_set(&ret_min, &mech_set);
    gss_release_oid_set(&ret_min, &mech_names);
    gss_release_oid_set(&ret_min, &mech_types);
    gss_release_oid_set(&ret_min, &mech_attrs);
    gss_release_oid_set(&ret_min, &known_mech_attrs);
    gss_release_buffer(&ret_min, &sasl_mech_name);
    gss_release_buffer(&ret_min, &mech_name);
    gss_release_buffer(&ret_min, &mech_description);
    gss_release_buffer(&ret_min, &name);
    gss_release_buffer(&ret_min, &short_desc);
    gss_release_buffer(&ret_min, &long_desc);
    gss_release_oid_set(&ret_min, &mechs);
    gpm_release_name(&ret_min, &target_name);
    gpm_release_name(&ret_min, &canon_name);
    gss_release_buffer(&ret_min, &out_name_buf);
    gss_release_oid(&ret_min, &out_name_type);
    close(data->srv_pipe[0]);
    close(data->cli_pipe[1]);
    pthread_exit(NULL);
}
Пример #2
0
uint32_t gp_export_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall,
                             gss_cred_id_t *in, gssx_cred *out)
{
    uint32_t ret_maj;
    uint32_t ret_min;
    gss_name_t name = NULL;
    uint32_t lifetime;
    gss_cred_usage_t cred_usage;
    gss_OID_set mechanisms = NULL;
    uint32_t initiator_lifetime;
    uint32_t acceptor_lifetime;
    struct gssx_cred_element *el;
    int ret;
    int i, j;
    struct gp_creds_handle *handle = NULL;
    gss_buffer_desc token = GSS_C_EMPTY_BUFFER;

    ret_maj = gss_inquire_cred(&ret_min, *in,
                               &name, &lifetime, &cred_usage, &mechanisms);
    if (ret_maj) {
        goto done;
    }

    ret_maj = gp_conv_name_to_gssx(&ret_min, name, &out->desired_name);
    if (ret_maj) {
        goto done;
    }
    gss_release_name(&ret_min, &name);
    name = NULL;

    out->elements.elements_len = mechanisms->count;
    out->elements.elements_val = calloc(out->elements.elements_len,
                                        sizeof(gssx_cred_element));
    if (!out->elements.elements_val) {
        ret_maj = GSS_S_FAILURE;
        ret_min = ENOMEM;
        goto done;
    }

    for (i = 0, j = 0; i < mechanisms->count; i++, j++) {

        el = &out->elements.elements_val[j];

        ret_maj = gss_inquire_cred_by_mech(&ret_min, *in,
                                           &mechanisms->elements[i],
                                           &name,
                                           &initiator_lifetime,
                                           &acceptor_lifetime,
                                           &cred_usage);
        if (ret_maj) {
            gp_log_failure(&mechanisms->elements[i], ret_maj, ret_min);

            /* temporarily skip any offender */
            out->elements.elements_len--;
            j--;
            continue;
#if 0
            ret = EINVAL;
            goto done;
#endif
        }

        ret_maj = gp_conv_name_to_gssx(&ret_min, name, &el->MN);
        if (ret_maj) {
            goto done;
        }
        gss_release_name(&ret_min, &name);
        name = NULL;

        ret = gp_conv_oid_to_gssx(&mechanisms->elements[i], &el->mech);
        if (ret) {
            ret_maj = GSS_S_FAILURE;
            ret_min = ret;
            goto done;
        }
        el->cred_usage = gp_conv_gssx_to_cred_usage(cred_usage);

        el->initiator_time_rec = initiator_lifetime;
        el->acceptor_time_rec = acceptor_lifetime;
    }

    handle = gp_service_get_creds_handle(gpcall->service);
    if (!handle) {
        ret_maj = GSS_S_FAILURE;
        ret_min = EINVAL;
        goto done;
    }

    ret_maj = gss_export_cred(&ret_min, *in, &token);
    if (ret_maj) {
        goto done;
    }

    ret = gp_encrypt_buffer(handle->context, &handle->key,
                            token.length, token.value,
                            &out->cred_handle_reference);
    if (ret) {
        ret_maj = GSS_S_FAILURE;
        ret_min = ret;
        goto done;
    }
    out->needs_release = false;
    /* now we have serialized creds in the hands of the client.
     * we can safey free them here so that we can remain sateless and
     * not leak memory */
    gss_release_cred(&ret_min, in);

    ret_maj = GSS_S_COMPLETE;
    ret_min = 0;

done:
    *min = ret_min;
    gss_release_name(&ret_min, &name);
    gss_release_oid_set(&ret_min, &mechanisms);
    return ret_maj;
}
Пример #3
0
void *client_thread(void *pvt)
{
    const char **argv;
    struct athread *data;
    uint32_t ret_maj;
    uint32_t ret_min;
    char buffer[MAX_RPC_SIZE];
    uint32_t buflen;
    gss_buffer_desc target_buf;
    gss_buffer_desc in_token = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc out_token = GSS_C_EMPTY_BUFFER;
    struct gssx_name *name = NULL;
    struct gssx_ctx *ctx = NULL;
    struct gssx_cred *cred_handle = NULL;
    int ret = 0;
    gss_buffer_desc msg_buf = GSS_C_EMPTY_BUFFER;
    int conf_state;
    uint32_t max_size;

    data = (struct athread *)pvt;
    argv = data->argv;

    target_buf.value = (void *)data->target;
    target_buf.length = strlen(data->target) + 1;

    ret_maj = gpm_import_name(&ret_min, &target_buf,
                              GSS_C_NT_HOSTBASED_SERVICE, &name);
    if (ret_maj) {
        goto done;
    }

    do {
        ret_maj = gpm_init_sec_context(&ret_min,
                                       cred_handle,
                                       &ctx,
                                       name,
                                       GSS_C_NO_OID,
                                       GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
                                       0,
                                       GSS_C_NO_CHANNEL_BINDINGS,
                                       &in_token,
                                       NULL,
                                       &out_token,
                                       NULL,
                                       NULL);
        if (ret_maj != GSS_S_COMPLETE &&
            ret_maj != GSS_S_CONTINUE_NEEDED) {
            DEBUG("gss_init_sec_context() failed with: %d\n", ret_maj);
            goto done;
        }
        if (out_token.length != 0) {
            /* send to server */
            ret = t_send_buffer(data->srv_pipe[1],
                                 out_token.value, out_token.length);
            if (ret) {
                goto done;
            }

            gss_release_buffer(&ret_min, &out_token);
        }

        if (!ctx) {
            goto done;
        }

        if (ret_maj == GSS_S_CONTINUE_NEEDED) {
            /* and wait for reply */
            ret = t_recv_buffer(data->cli_pipe[0], buffer, &buflen);
            if (ret) {
                goto done;
            }

            in_token.value = buffer;
            in_token.length = buflen;
        }

    } while (ret_maj == GSS_S_CONTINUE_NEEDED);

    memcpy(buffer, CLI_MSG, sizeof(CLI_MSG));
    msg_buf.value = (void *)buffer;
    msg_buf.length = sizeof(CLI_MSG);

    ret_maj = gpm_get_mic(&ret_min, ctx,
                          GSS_C_QOP_DEFAULT,
                          &msg_buf, &out_token);
    if (ret_maj) {
        DEBUG("gpm_get_mic failed: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    /* send msg to server */
    ret = t_send_buffer(data->srv_pipe[1],
                         msg_buf.value, msg_buf.length);
    if (ret) {
        goto done;
    }

    /* send signature to server */
    ret = t_send_buffer(data->srv_pipe[1],
                         out_token.value, out_token.length);
    if (ret) {
        goto done;
    }

    gss_release_buffer(&ret_min, &out_token);

    in_token.value = discard_const(CLI_MSG);
    in_token.length = strlen(in_token.value) + 1;

    ret_maj = gpm_wrap(&ret_min,
                       ctx,
                       1, /* conf_req_flag */
                       GSS_C_QOP_DEFAULT, /* qop_req */
                       &in_token,
                       &conf_state,
                       &out_token);
    if (ret_maj) {
        DEBUG("gpm_wrap failed: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    /* send to server */
    ret = t_send_buffer(data->srv_pipe[1],
                         out_token.value,
                         out_token.length);
    if (ret) {
        goto done;
    }

    ret_maj = gpm_wrap_size_limit(&ret_min,
                                  ctx,
                                  1, /* conf_req */
                                  GSS_C_QOP_DEFAULT, /* qop_req */
                                  4096, /* size_req */
                                  &max_size);
    if (ret_maj) {
        DEBUG("gpm_wrap_size_limit failed: %d\n", ret_maj);
        gp_log_failure(GSS_C_NO_OID, ret_maj, ret_min);
        goto done;
    }

    DEBUG("client: Success!\n");

done:
    gpm_release_name(&ret_min, &name);
    gss_release_buffer(&ret_min, &out_token);
    close(data->cli_pipe[0]);
    close(data->srv_pipe[1]);
    pthread_exit(NULL);
}