Пример #1
0
krb5_error_code
kg_init_name(krb5_context context,
             krb5_principal principal,
             krb5_authdata_context ad_context,
             krb5_flags flags,
             krb5_gss_name_t *ret_name)
{
    krb5_error_code code;
    krb5_gss_name_t name;

    *ret_name = NULL;

    assert(principal != NULL);

    if (principal == NULL)
        return EINVAL;

    name = xmalloc(sizeof(krb5_gss_name_rec));
    if (name == NULL)
        return ENOMEM;

    memset(name, 0, sizeof(krb5_gss_name_rec));

    code = k5_mutex_init(&name->lock);
    if (code != 0)
        goto cleanup;

    if ((flags & KG_INIT_NAME_NO_COPY) == 0) {
        code = krb5_copy_principal(context, principal, &name->princ);
        if (code != 0)
            goto cleanup;

        if (ad_context != NULL) {
            code = krb5_authdata_context_copy(context,
                                              ad_context,
                                              &name->ad_context);
            if (code != 0)
                goto cleanup;
        }
    } else {
        name->princ = principal;
        name->ad_context = ad_context;
    }

    if ((flags & KG_INIT_NAME_INTERN) &&
        !kg_save_name((gss_name_t)name)) {
        code = G_VALIDATE_FAILED;
        goto cleanup;
    }

    *ret_name = name;

cleanup:
    if (code != 0)
        kg_release_name(context, 0, &name);

    return code;
}
Пример #2
0
/* Convert a JSON value to a krb5 GSS name or to NULL. */
static int
json_to_kgname(krb5_context context, k5_json_value v,
               krb5_gss_name_t *name_out)
{
    k5_json_array array;
    krb5_gss_name_t name = NULL;

    *name_out = NULL;
    if (k5_json_get_tid(v) == K5_JSON_TID_NULL)
        return 0;
    if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY)
        return -1;
    array = v;
    if (k5_json_array_length(array) != 3)
        return -1;
    name = calloc(1, sizeof(*name));
    if (name == NULL)
        return -1;
    if (k5_mutex_init(&name->lock)) {
        free(name);
        return -1;
    }

    if (json_to_principal(context, k5_json_array_get(array, 0), &name->princ))
        goto invalid;
    if (json_to_optional_string(k5_json_array_get(array, 1), &name->service))
        goto invalid;
    if (json_to_optional_string(k5_json_array_get(array, 2), &name->host))
        goto invalid;

    *name_out = name;
    return 0;

invalid:
    kg_release_name(context, &name);
    return -1;
}
Пример #3
0
OM_uint32
kg_compose_deleg_cred(OM_uint32 *minor_status,
                      krb5_gss_cred_id_t impersonator_cred,
                      krb5_creds *subject_creds,
                      OM_uint32 time_req,
                      krb5_gss_cred_id_t *output_cred,
                      OM_uint32 *time_rec,
                      krb5_context context)
{
    OM_uint32 major_status;
    krb5_error_code code;
    krb5_gss_cred_id_t cred = NULL;

    *output_cred = NULL;
    k5_mutex_assert_locked(&impersonator_cred->lock);

    if (!kg_is_initiator_cred(impersonator_cred) ||
        impersonator_cred->name == NULL ||
        impersonator_cred->impersonator != NULL) {
        code = G_BAD_USAGE;
        goto cleanup;
    }

    assert(impersonator_cred->name->princ != NULL);

    assert(subject_creds != NULL);
    assert(subject_creds->client != NULL);

    cred = xmalloc(sizeof(*cred));
    if (cred == NULL) {
        code = ENOMEM;
        goto cleanup;
    }
    memset(cred, 0, sizeof(*cred));

    code = k5_mutex_init(&cred->lock);
    if (code != 0)
        goto cleanup;

    cred->usage = GSS_C_INITIATE;

    cred->tgt_expire = subject_creds->times.endtime;

    code = kg_init_name(context, subject_creds->client, NULL, NULL, NULL, 0,
                        &cred->name);
    if (code != 0)
        goto cleanup;

    code = krb5_cc_new_unique(context, "MEMORY", NULL, &cred->ccache);
    if (code != 0)
        goto cleanup;
    cred->destroy_ccache = 1;

    code = krb5_cc_initialize(context, cred->ccache, subject_creds->client);
    if (code != 0)
        goto cleanup;

    /*
     * Only return a "proxy" credential for use with constrained
     * delegation if the subject credentials are forwardable.
     * Submitting non-forwardable credentials to the KDC for use
     * with constrained delegation will only return an error.
     */
    if (subject_creds->ticket_flags & TKT_FLG_FORWARDABLE) {
        code = make_proxy_cred(context, cred, impersonator_cred);
        if (code != 0)
            goto cleanup;
    }

    code = krb5_cc_store_cred(context, cred->ccache, subject_creds);
    if (code != 0)
        goto cleanup;

    if (time_rec != NULL) {
        krb5_timestamp now;

        code = krb5_timeofday(context, &now);
        if (code != 0)
            goto cleanup;

        *time_rec = cred->tgt_expire - now;
    }

    major_status = GSS_S_COMPLETE;
    *minor_status = 0;
    *output_cred = cred;

cleanup:
    if (code != 0) {
        *minor_status = code;
        major_status = GSS_S_FAILURE;
    }

    if (GSS_ERROR(major_status) && cred != NULL) {
        k5_mutex_destroy(&cred->lock);
        krb5_cc_destroy(context, cred->ccache);
        kg_release_name(context, &cred->name);
        xfree(cred);
    }

    return major_status;
}
Пример #4
0
krb5_error_code
kg_init_name(krb5_context context, krb5_principal principal,
             char *service, char *host, krb5_authdata_context ad_context,
             krb5_flags flags, krb5_gss_name_t *ret_name)
{
    krb5_error_code code;
    krb5_gss_name_t name;

    *ret_name = NULL;

    assert(principal != NULL);

    if (principal == NULL)
        return EINVAL;

    name = xmalloc(sizeof(krb5_gss_name_rec));
    if (name == NULL)
        return ENOMEM;

    memset(name, 0, sizeof(krb5_gss_name_rec));

    code = k5_mutex_init(&name->lock);
    if (code != 0)
        goto cleanup;

    if ((flags & KG_INIT_NAME_NO_COPY) == 0) {
        code = krb5_copy_principal(context, principal, &name->princ);
        if (code != 0)
            goto cleanup;

        if (ad_context != NULL) {
            code = krb5_authdata_context_copy(context,
                                              ad_context,
                                              &name->ad_context);
            if (code != 0)
                goto cleanup;
        }

        code = ENOMEM;
        if (service != NULL) {
            name->service = strdup(service);
            if (name->service == NULL)
                goto cleanup;
        }
        if (host != NULL) {
            name->host = strdup(host);
            if (name->host == NULL)
                goto cleanup;
        }
        code = 0;
    } else {
        name->princ = principal;
        name->service = service;
        name->host = host;
        name->ad_context = ad_context;
    }

    *ret_name = name;

cleanup:
    if (code != 0)
        kg_release_name(context, &name);

    return code;
}