示例#1
0
/*
 * Build a tree given a set of profile values retrieved by
 * walk_rtree_capath_vals().
 */
static krb5_error_code
rtree_capath_tree(krb5_context context,
                  const krb5_data *client,
                  const krb5_data *server,
                  char **vals,
                  krb5_principal **rettree)
{
    krb5_error_code retval = 0;
    unsigned int nvals, nlinks, nprincs, i;
    krb5_data srcrealm, dstrealm;
    krb5_principal *tree, *pprinc;

    *rettree = NULL;
    tree = pprinc = NULL;
    for (nvals = 0; vals[nvals] != NULL; nvals++)
        ;
    if (vals[0] != NULL && *vals[0] == '.') {
        nlinks = 0;
    } else {
        nlinks = nvals;
    }
    nprincs = nlinks + 2;
    tree = calloc(nprincs + 1, sizeof(krb5_principal));
    if (tree == NULL) {
        retval = ENOMEM;
        goto error;
    }
    for (i = 0; i < nprincs + 1; i++)
        tree[i] = NULL;
    /* Invariant: PPRINC points one past end of list. */
    pprinc = &tree[0];
    /* Local TGS name */
    retval = krb5int_tgtname(context, client, client, pprinc++);
    if (retval) goto error;
    srcrealm = *client;
    for (i = 0; i < nlinks; i++) {
        dstrealm.data = vals[i];
        dstrealm.length = strcspn(vals[i], "\t ");
        retval = krb5int_tgtname(context, &dstrealm, &srcrealm, pprinc++);
        if (retval) goto error;
        srcrealm = dstrealm;
    }
    retval = krb5int_tgtname(context, server, &srcrealm, pprinc++);
    if (retval) goto error;
    *rettree = tree;

error:
    profile_free_list(vals);
    if (retval) {
        while (pprinc != NULL && pprinc > &tree[0]) {
            /* krb5_free_principal() correctly handles null input */
            krb5_free_principal(context, *--pprinc);
            *pprinc = NULL;
        }
        free(tree);
    }
    return retval;
}
示例#2
0
文件: fast.c 项目: DirectXMan12/krb5
krb5_error_code
krb5int_fast_tgs_armor(krb5_context context,
                       struct krb5int_fast_request_state *state,
                       krb5_keyblock *subkey, krb5_keyblock *session_key,
                       krb5_ccache ccache, krb5_data *target_realm)
{
    krb5_principal target_principal = NULL;
    krb5_keyblock *existing_armor = NULL;
    krb5_error_code retval = 0;

    if (ccache) {
        retval = krb5int_tgtname(context, target_realm, target_realm,
                                 &target_principal);
        if (retval == 0)
            retval = fast_armor_ap_request(context, state, ccache,
                                           target_principal);
        if (retval == 0) {
            existing_armor = state->armor_key;
            state->armor_key = NULL;
            retval = krb5_c_fx_cf2_simple(context, existing_armor,
                                          "explicitarmor", subkey,
                                          "tgsarmor", &state->armor_key);
        }
    } else {
        retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor",
                                      session_key, "ticketarmor",
                                      &state->armor_key);
    }
    if (target_principal)
        krb5_free_principal(context, target_principal);
    krb5_free_keyblock(context, existing_armor);
    return retval;
}
示例#3
0
/* Set up a request for a TGT for realm, using ctx->cur_tgt. */
static krb5_error_code
make_request_for_tgt(krb5_context context, krb5_tkt_creds_context ctx,
                     const krb5_data *realm)
{
    krb5_error_code code;

    /* Construct the principal krbtgt/<realm>@<cur-tgt-realm>. */
    krb5_free_principal(context, ctx->tgt_princ);
    ctx->tgt_princ = NULL;
    code = krb5int_tgtname(context, realm, &ctx->cur_tgt->server->realm,
                           &ctx->tgt_princ);
    if (code != 0)
        return code;

    TRACE_TKT_CREDS_TGT_REQ(context, ctx->tgt_princ, ctx->cur_tgt->server);

    /* Construct input creds using ctx->tgt_in_creds as a container. */
    memset(&ctx->tgt_in_creds, 0, sizeof(ctx->tgt_in_creds));
    ctx->tgt_in_creds.client = ctx->client;
    ctx->tgt_in_creds.server = ctx->tgt_princ;

    /* Make a request for the above creds with no extra options. */
    ctx->tgs_in_creds = &ctx->tgt_in_creds;
    code = make_request(context, ctx, 0);
    return code;
}
示例#4
0
krb5_error_code
krb5int_fast_as_armor(krb5_context context,
                      struct krb5int_fast_request_state *state,
                      krb5_gic_opt_ext *opte,
                      krb5_kdc_req *request)
{
    krb5_error_code retval = 0;
    krb5_ccache ccache = NULL;
    krb5_principal target_principal = NULL;
    krb5_data *target_realm;

    krb5_clear_error_message(context);
    target_realm = krb5_princ_realm(context, request->server);
    if (opte->opt_private->fast_ccache_name) {
        TRACE_FAST_ARMOR_CCACHE(context, opte->opt_private->fast_ccache_name);
        state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
        retval = krb5_cc_resolve(context, opte->opt_private->fast_ccache_name,
                                 &ccache);
        if (retval == 0) {
            retval = krb5int_tgtname(context, target_realm, target_realm,
                                     &target_principal);
        }
        if (retval == 0) {
            krb5_data config_data;
            config_data.data = NULL;
            retval = krb5_cc_get_config(context, ccache, target_principal,
                                        KRB5_CONF_FAST_AVAIL, &config_data);
            if ((retval == 0) && config_data.data) {
                TRACE_FAST_CCACHE_CONFIG(context);
                state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
            }
            krb5_free_data_contents(context, &config_data);
            retval = 0;
        }
        if (opte->opt_private->fast_flags & KRB5_FAST_REQUIRED) {
            TRACE_FAST_REQUIRED(context);
            state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
        }
        if (retval == 0 && (state->fast_state_flags & KRB5INT_FAST_DO_FAST)) {
            retval = fast_armor_ap_request(context, state, ccache,
                                           target_principal);
        }
        if (retval != 0) {
            const char * errmsg;
            errmsg = krb5_get_error_message(context, retval);
            if (errmsg) {
                krb5_set_error_message(context, retval,
                                       "%s constructing AP-REQ armor", errmsg);
                krb5_free_error_message(context, errmsg);
            }
        }
    }
    if (ccache)
        krb5_cc_close(context, ccache);
    if (target_principal)
        krb5_free_principal(context, target_principal);
    return retval;
}
示例#5
0
文件: fast.c 项目: DirectXMan12/krb5
krb5_error_code
krb5int_fast_as_armor(krb5_context context,
                      struct krb5int_fast_request_state *state,
                      krb5_get_init_creds_opt *opt, krb5_kdc_req *request)
{
    krb5_error_code retval = 0;
    krb5_ccache ccache = NULL;
    krb5_principal target_principal = NULL;
    krb5_data *target_realm;
    const char *ccname = k5_gic_opt_get_fast_ccache_name(opt);
    krb5_flags fast_flags;

    krb5_clear_error_message(context);
    target_realm = &request->server->realm;
    if (ccname != NULL) {
        TRACE_FAST_ARMOR_CCACHE(context, ccname);
        state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
        retval = krb5_cc_resolve(context, ccname, &ccache);
        if (retval == 0) {
            retval = krb5int_tgtname(context, target_realm, target_realm,
                                     &target_principal);
        }
        if (retval == 0) {
            krb5_data config_data;
            config_data.data = NULL;
            retval = krb5_cc_get_config(context, ccache, target_principal,
                                        KRB5_CC_CONF_FAST_AVAIL, &config_data);
            if ((retval == 0) && config_data.data) {
                TRACE_FAST_CCACHE_CONFIG(context);
                state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
            }
            krb5_free_data_contents(context, &config_data);
            retval = 0;
        }
        fast_flags = k5_gic_opt_get_fast_flags(opt);
        if (fast_flags & KRB5_FAST_REQUIRED) {
            TRACE_FAST_REQUIRED(context);
            state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
        }
        if (retval == 0 && (state->fast_state_flags & KRB5INT_FAST_DO_FAST)) {
            retval = fast_armor_ap_request(context, state, ccache,
                                           target_principal);
        }
        if (retval != 0) {
            k5_prependmsg(context, retval,
                          _("Error constructing AP-REQ armor"));
        }
    }
    if (ccache)
        krb5_cc_close(context, ccache);
    if (target_principal)
        krb5_free_principal(context, target_principal);
    return retval;
}
示例#6
0
/*
 * Point *TGT at an allocated credentials structure containing a TGT for realm
 * retrieved from ctx->ccache.  If we are retrieving a foreign TGT, accept any
 * issuing realm (i.e. match only the service principal name).  If the TGT is
 * not found in the cache, return successfully but set *tgt to NULL.
 */
static krb5_error_code
get_cached_tgt(krb5_context context, krb5_tkt_creds_context ctx,
               const krb5_data *realm, krb5_creds **tgt)
{
    krb5_creds mcreds;
    krb5_error_code code;
    krb5_principal tgtname = NULL;
    krb5_flags flags;
    krb5_boolean local_realm = data_eq(*realm, ctx->client->realm);

    *tgt = NULL;

    /* Construct the principal krbtgt/<realm>@<client realm>.  The realm
     * won't matter if we're getting a foreign TGT. */
    code = krb5int_tgtname(context, realm, &ctx->client->realm, &tgtname);
    if (code != 0)
        goto cleanup;

    /* Don't match the TGT realm if we're getting a foreign TGT. */
    flags = KRB5_TC_SUPPORTED_KTYPES;
    if (!local_realm)
        flags |= KRB5_TC_MATCH_SRV_NAMEONLY;

    /* Construct a matching cred for the ccache query. */
    memset(&mcreds, 0, sizeof(mcreds));
    mcreds.client = ctx->client;
    mcreds.server = tgtname;

    /* Fetch the TGT credential. */
    context->use_conf_ktypes = TRUE;
    code = cache_get(context, ctx->ccache, flags, &mcreds, tgt);
    context->use_conf_ktypes = FALSE;

    /* Handle not-found errors.  Make a note if we couldn't find a local TGT
     * because of enctypes. */
    if (local_realm && code == KRB5_CC_NOT_KTYPE)
        ctx->cache_code = KRB5_CC_NOT_KTYPE;
    if (code != 0 && code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE)
        goto cleanup;
    code = 0;

cleanup:
    krb5_free_principal(context, tgtname);
    return code;
}
示例#7
0
/*
 * Build tree by hierarchical traversal.
 */
static krb5_error_code
rtree_hier_tree(krb5_context context,
                const krb5_data *client,
                const krb5_data *server,
                krb5_principal **rettree,
                int sep)
{
    krb5_error_code retval;
    krb5_data *realms;
    const krb5_data *dstrealm, *srcrealm;
    krb5_principal *tree, *pprinc;
    size_t nrealms, nprincs, i;

    *rettree = NULL;
    retval = rtree_hier_realms(context, client, server,
                               &realms, &nrealms, sep);
    if (retval)
        return retval;
    nprincs = nrealms;
    pprinc = tree = calloc(nprincs + 1, sizeof(krb5_principal));
    if (tree == NULL) {
        retval = ENOMEM;
        goto error;
    }
    for (i = 0; i < nrealms; i++)
        tree[i] = NULL;
    srcrealm = client;
    for (i = 0; i < nrealms; i++) {
        dstrealm = &realms[i];
        retval = krb5int_tgtname(context, dstrealm, srcrealm, pprinc++);
        if (retval) goto error;
        srcrealm = dstrealm;
    }
    *rettree = tree;
    free_realmlist(context, realms, nrealms);
    return 0;
error:
    while (pprinc != NULL && pprinc > tree) {
        krb5_free_principal(context, *--pprinc);
        *pprinc = NULL;
    }
    free_realmlist(context, realms, nrealms);
    free(tree);
    return retval;
}
示例#8
0
文件: fwd_tgt.c 项目: Baalmart/krb5
/* Get a TGT for use at the remote host */
krb5_error_code KRB5_CALLCONV
krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
                   char *rhost, krb5_principal client, krb5_principal server,
                   krb5_ccache cc, int forwardable, krb5_data *outbuf)
/* Should forwarded TGT also be forwardable? */
{
    krb5_replay_data replaydata;
    krb5_data * scratch = 0;
    krb5_address **addrs = NULL;
    krb5_error_code retval;
    krb5_creds creds, tgt;
    krb5_creds *pcreds;
    krb5_flags kdcoptions;
    int close_cc = 0;
    int free_rhost = 0;
    krb5_enctype enctype = 0;
    krb5_keyblock *session_key;
    krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;

    memset(&creds, 0, sizeof(creds));
    memset(&tgt, 0, sizeof(creds));

    if (cc == 0) {
        if ((retval = krb5int_cc_default(context, &cc)))
            goto errout;
        close_cc = 1;
    }
    retval = krb5_auth_con_getkey (context, auth_context, &session_key);
    if (retval)
        goto errout;
    if (session_key) {
        enctype = session_key->enctype;
        krb5_free_keyblock (context, session_key);
        session_key = NULL;
    } else if (server) { /* must server be non-NULL when rhost is given? */
        /* Try getting credentials to see what the remote side supports.
           Not bulletproof, just a heuristic.  */
        krb5_creds in, *out = 0;
        memset (&in, 0, sizeof(in));

        retval = krb5_copy_principal (context, server, &in.server);
        if (retval)
            goto punt;
        retval = krb5_copy_principal (context, client, &in.client);
        if (retval)
            goto punt;
        retval = krb5_get_credentials (context, 0, cc, &in, &out);
        if (retval)
            goto punt;
        /* Got the credentials.  Okay, now record the enctype and
           throw them away.  */
        enctype = out->keyblock.enctype;
        krb5_free_creds (context, out);
    punt:
        krb5_free_cred_contents (context, &in);
    }

    if ((retval = krb5_copy_principal(context, client, &creds.client)))
        goto errout;

    retval = krb5int_tgtname(context, &client->realm, &client->realm,
                             &creds.server);
    if (retval)
        goto errout;

    /* fetch tgt directly from cache */
    context->use_conf_ktypes = 1;
    retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
                                    &creds, &tgt);
    context->use_conf_ktypes = old_use_conf_ktypes;
    if (retval)
        goto errout;

    /* tgt->client must be equal to creds.client */
    if (!krb5_principal_compare(context, tgt.client, creds.client)) {
        retval = KRB5_PRINC_NOMATCH;
        goto errout;
    }

    if (!tgt.ticket.length) {
        retval = KRB5_NO_TKT_SUPPLIED;
        goto errout;
    }

    if (tgt.addresses && *tgt.addresses) {
        if (rhost == NULL) {
            if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
                retval = KRB5_FWD_BAD_PRINCIPAL;
                goto errout;
            }

            if (krb5_princ_size(context, server) < 2){
                retval = KRB5_CC_BADNAME;
                goto errout;
            }

            rhost = malloc(server->data[1].length+1);
            if (!rhost) {
                retval = ENOMEM;
                goto errout;
            }
            free_rhost = 1;
            memcpy(rhost, server->data[1].data, server->data[1].length);
            rhost[server->data[1].length] = '\0';
        }

        retval = krb5_os_hostaddr(context, rhost, &addrs);
        if (retval)
            goto errout;
    }

    creds.keyblock.enctype = enctype;
    creds.times = tgt.times;
    creds.times.starttime = 0;
    kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;

    if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
        kdcoptions &= ~(KDC_OPT_FORWARDABLE);

    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
                                        addrs, &creds, &pcreds))) {
        if (enctype) {
            creds.keyblock.enctype = 0;
            if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
                                                addrs, &creds, &pcreds)))
                goto errout;
        }
        else goto errout;
    }
    retval = krb5_mk_1cred(context, auth_context, pcreds,
                           &scratch, &replaydata);
    krb5_free_creds(context, pcreds);

    if (retval) {
        if (scratch)
            krb5_free_data(context, scratch);
    } else {
        *outbuf = *scratch;
        free(scratch);
    }

errout:
    if (addrs)
        krb5_free_addresses(context, addrs);
    if (close_cc)
        krb5_cc_close(context, cc);
    if (free_rhost)
        free(rhost);
    krb5_free_cred_contents(context, &creds);
    krb5_free_cred_contents(context, &tgt);
    return retval;
}