Esempio n. 1
0
static krb5_error_code
mspac_get_attribute_types(krb5_context kcontext,
                          krb5_authdata_context context,
                          void *plugin_context,
                          void *request_context,
                          krb5_data **out_attrs)
{
    struct mspac_context *pacctx = (struct mspac_context *)request_context;
    unsigned int i, j;
    krb5_data *attrs;
    krb5_error_code code;

    if (pacctx->pac == NULL)
        return ENOENT;

    attrs = calloc(1 + pacctx->pac->pac->cBuffers + 1, sizeof(krb5_data));
    if (attrs == NULL)
        return ENOMEM;

    j = 0;

    /* The entire PAC */
    code = krb5int_copy_data_contents(kcontext,
                                      &mspac_attribute_types[0].attribute,
                                      &attrs[j++]);
    if (code != 0) {
        free(attrs);
        return code;
    }

    /* PAC buffers */
    for (i = 0; i < pacctx->pac->pac->cBuffers; i++) {
        krb5_data attr;

        code = mspac_type2attr(pacctx->pac->pac->Buffers[i].ulType, &attr);
        if (code == 0) {
            code = krb5int_copy_data_contents(kcontext, &attr, &attrs[j++]);
            if (code != 0) {
                krb5int_free_data_list(kcontext, attrs);
                return code;
            }
        } else {
            int length;

            length = asprintf(&attrs[j].data, "urn:mspac:%d",
                              pacctx->pac->pac->Buffers[i].ulType);
            if (length < 0) {
                krb5int_free_data_list(kcontext, attrs);
                return ENOMEM;
            }
            attrs[j++].length = length;
        }
    }
    attrs[j].data = NULL;
    attrs[j].length = 0;

    *out_attrs = attrs;

    return 0;
}
Esempio n. 2
0
OM_uint32 KRB5_CALLCONV
krb5_gss_inquire_name(OM_uint32 *minor_status,
                      gss_name_t name,
                      int *name_is_MN,
                      gss_OID *MN_mech,
                      gss_buffer_set_t *attrs)
{
    krb5_context context;
    krb5_error_code code;
    krb5_gss_name_t kname;
    krb5_data *kattrs = NULL;

    if (minor_status != NULL)
        *minor_status = 0;

    if (attrs != NULL)
        *attrs = GSS_C_NO_BUFFER_SET;

    code = krb5_gss_init_context(&context);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    kname = (krb5_gss_name_t)name;

    code = k5_mutex_lock(&kname->lock);
    if (code != 0) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }

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

    code = krb5_authdata_get_attribute_types(context,
                                             kname->ad_context,
                                             &kattrs);
    if (code != 0)
        goto cleanup;

    code = data_list_to_buffer_set(context, kattrs, attrs);
    kattrs = NULL;
    if (code != 0)
        goto cleanup;

cleanup:
    k5_mutex_unlock(&kname->lock);
    krb5int_free_data_list(context, kattrs);

    krb5_free_context(context);

    return kg_map_name_error(minor_status, code);
}
Esempio n. 3
0
void KRB5_CALLCONV
krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx)
{
    if (ctx == NULL)
        return;
    krb5_free_creds(context, ctx->in_creds);
    krb5_cc_close(context, ctx->ccache);
    krb5_free_principal(context, ctx->req_server);
    krb5_free_authdata(context, ctx->authdata);
    krb5_free_creds(context, ctx->cur_tgt);
    krb5int_free_data_list(context, ctx->realms_seen);
    krb5_free_principal(context, ctx->tgt_princ);
    krb5_free_keyblock(context, ctx->subkey);
    krb5_free_data_contents(context, &ctx->previous_request);
    krb5int_free_data_list(context, ctx->realm_path);
    krb5_free_creds(context, ctx->reply_creds);
    free(ctx);
}
Esempio n. 4
0
krb5_error_code KRB5_CALLCONV
krb5_authdata_get_attribute_types(krb5_context kcontext,
                                  krb5_authdata_context context,
                                  krb5_data **out_attrs)
{
    int i;
    krb5_error_code code = 0;
    krb5_data *attrs = NULL;
    unsigned int attrs_len = 0;

    for (i = 0; i < context->n_modules; i++) {
        struct _krb5_authdata_context_module *module = &context->modules[i];
        krb5_data *attrs2 = NULL;

        if (module->ftable->get_attribute_types == NULL)
            continue;

        if ((*module->ftable->get_attribute_types)(kcontext,
                                                   context,
                                                   module->plugin_context,
                                                   *(module->request_context_pp),
                                                   &attrs2))
            continue;

        code = k5_merge_data_list(&attrs, attrs2, &attrs_len);
        if (code != 0) {
            krb5int_free_data_list(kcontext, attrs2);
            break;
        }
        if (attrs2 != NULL)
            free(attrs2);
    }

    if (code != 0) {
        krb5int_free_data_list(kcontext, attrs);
        attrs = NULL;
    }

    *out_attrs = attrs;

    return code;
}
Esempio n. 5
0
/* Owns data on success */
static krb5_error_code
data_list_to_buffer_set(krb5_context context,
                        krb5_data *data,
                        gss_buffer_set_t *buffer_set)
{
    gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
    OM_uint32 minor_status;
    int i;
    krb5_error_code code = 0;

    if (data == NULL)
        goto cleanup;

    if (buffer_set == NULL)
        goto cleanup;

    if (GSS_ERROR(gss_create_empty_buffer_set(&minor_status,
                                              &set))) {
        assert(minor_status != 0);
        code = minor_status;
        goto cleanup;
    }

    for (i = 0; data[i].data != NULL; i++)
        ;

    set->count = i;
    set->elements = gssalloc_calloc(i, sizeof(gss_buffer_desc));
    if (set->elements == NULL) {
        gss_release_buffer_set(&minor_status, &set);
        code = ENOMEM;
        goto cleanup;
    }

    /*
     * Copy last element first so data remains properly
     * NULL-terminated in case of allocation failure
     * in data_to_gss() on windows.
     */
    for (i = set->count-1; i >= 0; i--) {
        if (data_to_gss(&data[i], &set->elements[i])) {
            gss_release_buffer_set(&minor_status, &set);
            code = ENOMEM;
            goto cleanup;
        }
    }
cleanup:
    krb5int_free_data_list(context, data);

    if (buffer_set != NULL)
        *buffer_set = set;

    return code;
}
Esempio n. 6
0
/*
 * Begin the referrals request loop.  Expects ctx->cur_tgt to be a TGT for
 * ctx->realm->server.
 */
static krb5_error_code
begin_referrals(krb5_context context, krb5_tkt_creds_context ctx)
{
    ctx->state = STATE_REFERRALS;
    ctx->referral_count = 1;

    /* Empty out the realms-seen list for loop checking. */
    krb5int_free_data_list(context, ctx->realms_seen);
    ctx->realms_seen = NULL;

    /* Generate the first referral request. */
    return make_request_for_service(context, ctx, TRUE);
}
Esempio n. 7
0
/* Initialize the realm path fields for getting a TGT for
 * ctx->server->realm. */
static krb5_error_code
init_realm_path(krb5_context context, krb5_tkt_creds_context ctx)
{
    krb5_error_code code;
    krb5_principal *tgt_princ_list = NULL;
    krb5_data *realm_path;
    size_t nrealms, i;

    /* Construct a list of TGT principals from client to server.  We will throw
     * this away after grabbing the remote realms from each principal. */
    code = krb5_walk_realm_tree(context, &ctx->client->realm,
                                &ctx->server->realm,
                                &tgt_princ_list, KRB5_REALM_BRANCH_CHAR);
    if (code != 0)
        return code;

    /* Count the number of principals and allocate the realm path. */
    for (nrealms = 0; tgt_princ_list[nrealms]; nrealms++);
    assert(nrealms > 1);
    realm_path = k5alloc((nrealms + 1) * sizeof(*realm_path), &code);
    if (realm_path == NULL)
        goto cleanup;

    /* Steal the remote realm field from each TGT principal. */
    for (i = 0; i < nrealms; i++) {
        assert(tgt_princ_list[i]->length == 2);
        realm_path[i] = tgt_princ_list[i]->data[1];
        tgt_princ_list[i]->data[1].data = NULL;
    }
    realm_path[nrealms] = empty_data();

    /* Initialize the realm path fields in ctx. */
    krb5int_free_data_list(context, ctx->realm_path);
    ctx->realm_path = realm_path;
    ctx->last_realm = realm_path + nrealms - 1;
    ctx->cur_realm = realm_path;
    ctx->next_realm = ctx->last_realm;
    realm_path = NULL;

cleanup:
    krb5_free_realm_tree(context, tgt_princ_list);
    return 0;
}
Esempio n. 8
0
krb5_error_code
k5_client_realm_path(krb5_context context, const krb5_data *client,
                     const krb5_data *server, krb5_data **rpath_out)
{
    krb5_error_code retval;
    char **capvals;
    size_t i;
    krb5_data *rpath = NULL, d;

    retval = rtree_capath_vals(context, client, server, &capvals);
    if (retval)
        return retval;

    /* Count capaths (if any) and allocate space.  Leave room for the client
     * realm, server realm, and terminator. */
    for (i = 0; capvals != NULL && capvals[i] != NULL; i++);
    rpath = calloc(i + 3, sizeof(*rpath));
    if (rpath == NULL)
        return ENOMEM;

    /* Populate rpath with the client realm, capaths, and server realm. */
    retval = krb5int_copy_data_contents(context, client, &rpath[0]);
    if (retval)
        goto cleanup;
    for (i = 0; capvals != NULL && capvals[i] != NULL; i++) {
        d = make_data(capvals[i], strcspn(capvals[i], "\t "));
        retval = krb5int_copy_data_contents(context, &d, &rpath[i + 1]);
        if (retval)
            goto cleanup;
    }
    retval = krb5int_copy_data_contents(context, server, &rpath[i + 1]);
    if (retval)
        goto cleanup;

    /* Terminate rpath and return it. */
    rpath[i + 2] = empty_data();
    *rpath_out = rpath;
    rpath = NULL;

cleanup:
    krb5int_free_data_list(context, rpath);
    return retval;
}
Esempio n. 9
0
/*
 * Begin the process of getting a foreign TGT, either for the explicitly
 * specified server realm or for the fallback realm.  Expects that
 * ctx->server->realm is the realm of the desired TGT, and that
 * ctx->getting_tgt_for is the state we should advance to after we have the
 * desired TGT.
 */
static krb5_error_code
begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
{
    krb5_error_code code;
    krb5_creds *cached_tgt;

    ctx->state = STATE_GET_TGT;

    /* See if we have a cached TGT for the server realm. */
    code = get_cached_tgt(context, ctx, &ctx->server->realm, &cached_tgt);
    if (code != 0)
        return code;
    if (cached_tgt != NULL) {
        TRACE_TKT_CREDS_CACHED_SERVICE_TGT(context, cached_tgt);
        krb5_free_creds(context, ctx->cur_tgt);
        ctx->cur_tgt = cached_tgt;
        return end_get_tgt(context, ctx);
    }

    /* Start with the local tgt. */
    krb5_free_creds(context, ctx->cur_tgt);
    ctx->cur_tgt = NULL;
    code = get_cached_tgt(context, ctx, &ctx->client->realm, &ctx->cur_tgt);
    if (code != 0)
        return code;
    if (ctx->cur_tgt == NULL)
        return ctx->cache_code;
    TRACE_TKT_CREDS_LOCAL_TGT(context, ctx->cur_tgt);

    /* Initialize the realm path. */
    code = init_realm_path(context, ctx);
    if (code != 0)
        return code;

    /* Empty out the realms-seen list for loop checking. */
    krb5int_free_data_list(context, ctx->realms_seen);
    ctx->realms_seen = NULL;

    /* Generate the first request. */
    return get_tgt_request(context, ctx);
}
Esempio n. 10
0
/* Initialize the realm path fields for getting a TGT for
 * ctx->server->realm. */
static krb5_error_code
init_realm_path(krb5_context context, krb5_tkt_creds_context ctx)
{
    krb5_error_code code;
    krb5_data *realm_path;
    size_t nrealms;

    /* Get the client realm path and count its length. */
    code = k5_client_realm_path(context, &ctx->client->realm,
                                &ctx->server->realm, &realm_path);
    if (code != 0)
        return code;
    for (nrealms = 0; realm_path[nrealms].data != NULL; nrealms++);
    assert(nrealms > 1);

    /* Initialize the realm path fields in ctx. */
    krb5int_free_data_list(context, ctx->realm_path);
    ctx->realm_path = realm_path;
    ctx->last_realm = realm_path + nrealms - 1;
    ctx->cur_realm = realm_path;
    ctx->next_realm = ctx->last_realm;
    return 0;
}