Ejemplo n.º 1
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_creds(krb5_context context,
	       krb5_get_creds_opt opt,
	       krb5_ccache ccache,
	       krb5_const_principal inprinc,
	       krb5_creds **out_creds)
{
    krb5_kdc_flags flags;
    krb5_flags options;
    krb5_creds in_creds;
    krb5_error_code ret;
    krb5_creds **tgts;
    krb5_creds *res_creds;
    int i;

    if (opt && opt->enctype) {
	ret = krb5_enctype_valid(context, opt->enctype);
	if (ret)
	    return ret;
    }

    memset(&in_creds, 0, sizeof(in_creds));
    in_creds.server = rk_UNCONST(inprinc);

    ret = krb5_cc_get_principal(context, ccache, &in_creds.client);
    if (ret)
	return ret;

    if (opt)
	options = opt->options;
    else
	options = 0;
    flags.i = 0;

    *out_creds = NULL;
    res_creds = calloc(1, sizeof(*res_creds));
    if (res_creds == NULL) {
	krb5_free_principal(context, in_creds.client);
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    if (opt && opt->enctype) {
	in_creds.session.keytype = opt->enctype;
	options |= KRB5_TC_MATCH_KEYTYPE;
    }

    /*
     * If we got a credential, check if credential is expired before
     * returning it.
     */
    ret = krb5_cc_retrieve_cred(context,
                                ccache,
				options & KRB5_TC_MATCH_KEYTYPE,
                                &in_creds, res_creds);
    /*
     * If we got a credential, check if credential is expired before
     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
     */
    if (ret == 0) {
	krb5_timestamp timeret;

	/* If expired ok, don't bother checking */
        if(options & KRB5_GC_EXPIRED_OK) {
            *out_creds = res_creds;
	    krb5_free_principal(context, in_creds.client);
            goto out;
        }

	krb5_timeofday(context, &timeret);
	if(res_creds->times.endtime > timeret) {
	    *out_creds = res_creds;
	    krb5_free_principal(context, in_creds.client);
            goto out;
	}
	if(options & KRB5_GC_CACHED)
	    krb5_cc_remove_cred(context, ccache, 0, res_creds);

    } else if(ret != KRB5_CC_END) {
        free(res_creds);
	krb5_free_principal(context, in_creds.client);
	goto out;
    }
    free(res_creds);
    if(options & KRB5_GC_CACHED) {
	krb5_free_principal(context, in_creds.client);
	ret = not_found(context, in_creds.server, KRB5_CC_NOTFOUND);
	goto out;
    }
    if(options & KRB5_GC_USER_USER) {
	flags.b.enc_tkt_in_skey = 1;
	options |= KRB5_GC_NO_STORE;
    }
    if (options & KRB5_GC_FORWARDABLE)
	flags.b.forwardable = 1;
    if (options & KRB5_GC_NO_TRANSIT_CHECK)
	flags.b.disable_transited_check = 1;
    if (options & KRB5_GC_CONSTRAINED_DELEGATION) {
	flags.b.request_anonymous = 1; /* XXX ARGH confusion */
	flags.b.constrained_delegation = 1;
    }
    if (options & KRB5_GC_CANONICALIZE)
	flags.b.canonicalize = 1;

    tgts = NULL;
    ret = _krb5_get_cred_kdc_any(context, flags, ccache,
				 &in_creds, opt->self, opt->ticket,
				 out_creds, &tgts);
    krb5_free_principal(context, in_creds.client);
    for(i = 0; tgts && tgts[i]; i++) {
	krb5_cc_store_cred(context, ccache, tgts[i]);
	krb5_free_creds(context, tgts[i]);
    }
    free(tgts);
    if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0)
	krb5_cc_store_cred(context, ccache, *out_creds);

 out:
    _krb5_debug(context, 5, "krb5_get_creds: ret = %d", ret);

    return ret;
}
Ejemplo n.º 2
0
static krb5_error_code
get_cred_kdc_referral(krb5_context context,
		      krb5_kdc_flags flags,
		      krb5_ccache ccache,
		      krb5_creds *in_creds,
		      krb5_principal impersonate_principal,
		      Ticket *second_ticket,
		      krb5_creds **out_creds,
		      krb5_creds ***ret_tgts)
{
    krb5_const_realm client_realm;
    krb5_error_code ret;
    krb5_creds tgt, referral, ticket;
    int loop = 0;
    int ok_as_delegate = 1;

    if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
	krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
			       N_("Name too short to do referals, skipping", ""));
	return KRB5KDC_ERR_PATH_NOT_ACCEPTED;
    }

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

    flags.b.canonicalize = 1;

    *out_creds = NULL;

    client_realm = krb5_principal_get_realm(context, in_creds->client);

    /* find tgt for the clients base realm */
    {
	krb5_principal tgtname;

	ret = krb5_make_principal(context, &tgtname,
				  client_realm,
				  KRB5_TGS_NAME,
				  client_realm,
				  NULL);
	if(ret)
	    return ret;

	ret = find_cred(context, ccache, tgtname, *ret_tgts, &tgt);
	krb5_free_principal(context, tgtname);
	if (ret)
	    return ret;
    }

    referral = *in_creds;
    ret = krb5_copy_principal(context, in_creds->server, &referral.server);
    if (ret) {
	krb5_free_cred_contents(context, &tgt);
	return ret;
    }
    ret = krb5_principal_set_realm(context, referral.server, client_realm);
    if (ret) {
	krb5_free_cred_contents(context, &tgt);
	krb5_free_principal(context, referral.server);
	return ret;
    }

    while (loop++ < 17) {
	krb5_creds **tickets;
	krb5_creds mcreds;
	char *referral_realm;

	/* Use cache if we are not doing impersonation or contrainte deleg */
	if (impersonate_principal == NULL || flags.b.constrained_delegation) {
	    krb5_cc_clear_mcred(&mcreds);
	    mcreds.server = referral.server;
	    ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &ticket);
	} else
	    ret = EINVAL;

	if (ret) {
	    ret = get_cred_kdc_address(context, ccache, flags, NULL,
				       &referral, &tgt, impersonate_principal,
				       second_ticket, &ticket);
	    if (ret)
		goto out;
	}

	/* Did we get the right ticket ? */
	if (krb5_principal_compare_any_realm(context,
					     referral.server,
					     ticket.server))
	    break;

	if (!krb5_principal_is_krbtgt(context, ticket.server)) {
	    krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US,
				   N_("Got back an non krbtgt "
				      "ticket referrals", ""));
	    ret = KRB5KRB_AP_ERR_NOT_US;
	    goto out;
	}

	referral_realm = ticket.server->name.name_string.val[1];

	/* check that there are no referrals loops */
	tickets = *ret_tgts;

	krb5_cc_clear_mcred(&mcreds);
	mcreds.server = ticket.server;

	while(tickets && *tickets){
	    if(krb5_compare_creds(context,
				  KRB5_TC_DONT_MATCH_REALM,
				  &mcreds,
				  *tickets))
	    {
		krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
				       N_("Referral from %s "
					  "loops back to realm %s", ""),
				       tgt.server->realm,
				       referral_realm);
		ret = KRB5_GET_IN_TKT_LOOP;
                goto out;
	    }
	    tickets++;
	}

	/*
	 * if either of the chain or the ok_as_delegate was stripped
	 * by the kdc, make sure we strip it too.
	 */

	if (ok_as_delegate == 0 || ticket.flags.b.ok_as_delegate == 0) {
	    ok_as_delegate = 0;
	    ticket.flags.b.ok_as_delegate = 0;
	}

	ret = add_cred(context, &ticket, ret_tgts);
	if (ret)
	    goto out;

	/* try realm in the referral */
	ret = krb5_principal_set_realm(context,
				       referral.server,
				       referral_realm);
	krb5_free_cred_contents(context, &tgt);
	tgt = ticket;
	memset(&ticket, 0, sizeof(ticket));
	if (ret)
	    goto out;
    }

    ret = krb5_copy_creds(context, &ticket, out_creds);

out:
    krb5_free_principal(context, referral.server);
    krb5_free_cred_contents(context, &tgt);
    krb5_free_cred_contents(context, &ticket);
    return ret;
}
Ejemplo n.º 3
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_credentials_with_flags(krb5_context context,
				krb5_flags options,
				krb5_kdc_flags flags,
				krb5_ccache ccache,
				krb5_creds *in_creds,
				krb5_creds **out_creds)
{
    krb5_error_code ret;
    krb5_creds **tgts;
    krb5_creds *res_creds;
    int i;

    if (in_creds->session.keytype) {
	ret = krb5_enctype_valid(context, in_creds->session.keytype);
	if (ret)
	    return ret;
    }

    *out_creds = NULL;
    res_creds = calloc(1, sizeof(*res_creds));
    if (res_creds == NULL) {
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    if (in_creds->session.keytype)
	options |= KRB5_TC_MATCH_KEYTYPE;

    /*
     * If we got a credential, check if credential is expired before
     * returning it.
     */
    ret = krb5_cc_retrieve_cred(context,
                                ccache,
                                in_creds->session.keytype ?
                                KRB5_TC_MATCH_KEYTYPE : 0,
                                in_creds, res_creds);
    /*
     * If we got a credential, check if credential is expired before
     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
     */
    if (ret == 0) {
	krb5_timestamp timeret;

	/* If expired ok, don't bother checking */
        if(options & KRB5_GC_EXPIRED_OK) {
            *out_creds = res_creds;
            return 0;
        }

	krb5_timeofday(context, &timeret);
	if(res_creds->times.endtime > timeret) {
	    *out_creds = res_creds;
	    return 0;
	}
	if(options & KRB5_GC_CACHED)
	    krb5_cc_remove_cred(context, ccache, 0, res_creds);

    } else if(ret != KRB5_CC_END) {
        free(res_creds);
        return ret;
    }
    free(res_creds);
    if(options & KRB5_GC_CACHED)
	return not_found(context, in_creds->server, KRB5_CC_NOTFOUND);

    if(options & KRB5_GC_USER_USER)
	flags.b.enc_tkt_in_skey = 1;
    if (flags.b.enc_tkt_in_skey)
	options |= KRB5_GC_NO_STORE;

    tgts = NULL;
    ret = _krb5_get_cred_kdc_any(context, flags, ccache,
				 in_creds, NULL, NULL, out_creds, &tgts);
    for(i = 0; tgts && tgts[i]; i++) {
	krb5_cc_store_cred(context, ccache, tgts[i]);
	krb5_free_creds(context, tgts[i]);
    }
    free(tgts);
    if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0)
	krb5_cc_store_cred(context, ccache, *out_creds);
    return ret;
}
Ejemplo n.º 4
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    krb5_get_creds_opt opt;
    krb5_principal server;
    krb5_principal impersonate = NULL;

    setprogname (argv[0]);

    ret = krb5_init_context (&context);
    if (ret)
	errx(1, "krb5_init_context failed: %d", ret);

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc != 1)
	usage (1);

    if(cache_str) {
	ret = krb5_cc_resolve(context, cache_str, &cache);
	if (ret)
	    krb5_err (context, 1, ret, "%s", cache_str);
    } else {
	ret = krb5_cc_default (context, &cache);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");
    }

    ret = krb5_get_creds_opt_alloc(context, &opt);
    if (ret)
	krb5_err (context, 1, ret, "krb5_get_creds_opt_alloc");

    if (etype_str) {
	krb5_enctype enctype;

	ret = krb5_string_to_enctype(context, etype_str, &enctype);
	if (ret)
	    krb5_errx (context, 1, N_("unrecognized enctype: %s", ""), 
		       etype_str);
	krb5_get_creds_opt_set_enctype(context, opt, enctype);
    }

    if (impersonate_str) {
	ret = krb5_parse_name(context, impersonate_str, &impersonate);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_parse_name %s", impersonate_str);
	krb5_get_creds_opt_set_impersonate(context, opt, impersonate);
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
    }

    if (out_cache_str)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);

    if (forwardable_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE);
    if (!transit_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK);
    if (canonicalize_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE);

    if (delegation_cred_str) {
	krb5_ccache id;
	krb5_creds c, mc;
	Ticket ticket;

	krb5_cc_clear_mcred(&mc);
	ret = krb5_cc_get_principal(context, cache, &mc.server);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_get_principal");

	ret = krb5_cc_resolve(context, delegation_cred_str, &id);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");

	ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL);
	if (ret) {
	    krb5_clear_error_message(context);
	    krb5_err (context, 1, ret, "decode_Ticket");
	}
	krb5_free_cred_contents(context, &c);

	ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_get_creds_opt_set_ticket");
	free_Ticket(&ticket);

	krb5_cc_close (context, id);
	krb5_free_principal(context, mc.server);

	krb5_get_creds_opt_add_options(context, opt,
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

    ret = krb5_parse_name(context, argv[0], &server);
    if (ret)
	krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]);

    if (nametype_str) {
	ret = krb5_parse_nametype(context, nametype_str,
				  &server->name.name_type);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_nametype");
    }

    ret = krb5_get_creds(context, opt, cache, server, &out);
    if (ret)
	krb5_err (context, 1, ret, "krb5_get_creds");

    if (out_cache_str) {
	krb5_ccache id;

	ret = krb5_cc_resolve(context, out_cache_str, &id);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_initialize(context, id, out->client);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, out);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_store_cred");
	krb5_cc_close (context, id);
    }

    krb5_free_creds(context, out);
    krb5_free_principal(context, server);
    krb5_get_creds_opt_free(context, opt);
    krb5_cc_close (context, cache);
    krb5_free_context (context);

    return 0;
}
Ejemplo n.º 5
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    int32_t nametype = KRB5_NT_UNKNOWN;
    krb5_get_creds_opt opt;
    krb5_principal server = NULL;
    krb5_principal impersonate;

    setprogname(argv[0]);

    ret = krb5_init_context(&context);
    if (ret)
	errx(1, "krb5_init_context failed: %d", ret);

    if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if (version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (debug_flag) {
        ret = krb5_set_debug_dest(context, getprogname(), "STDERR");
        if (ret)
            krb5_warn(context, ret, "krb5_set_debug_dest");
    }

    if (cache_str) {
	ret = krb5_cc_resolve(context, cache_str, &cache);
	if (ret)
	    krb5_err(context, 1, ret, "%s", cache_str);
    } else {
	ret = krb5_cc_default (context, &cache);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve");
    }

    ret = krb5_get_creds_opt_alloc(context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_creds_opt_alloc");

    if (etype_str) {
	krb5_enctype enctype;

	ret = krb5_string_to_enctype(context, etype_str, &enctype);
	if (ret)
	    krb5_errx(context, 1, N_("unrecognized enctype: %s", ""),
		      etype_str);
	krb5_get_creds_opt_set_enctype(context, opt, enctype);
    }

    if (impersonate_str) {
	ret = krb5_parse_name(context, impersonate_str, &impersonate);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name %s", impersonate_str);
	krb5_get_creds_opt_set_impersonate(context, opt, impersonate);
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
        krb5_free_principal(context, impersonate);
    }

    if (out_cache_str)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);

    if (forwardable_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE);
    if (!transit_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK);
    if (canonicalize_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE);
    if (!store_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
    if (cached_only_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CACHED);

    if (delegation_cred_str) {
	krb5_ccache id;
	krb5_creds c, mc;
	Ticket ticket;

	krb5_cc_clear_mcred(&mc);
	ret = krb5_cc_get_principal(context, cache, &mc.server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_get_principal");

	ret = krb5_cc_resolve(context, delegation_cred_str, &id);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_retrieve_cred");

	ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL);
	if (ret) {
	    krb5_clear_error_message(context);
	    krb5_err(context, 1, ret, "decode_Ticket");
	}
	krb5_free_cred_contents(context, &c);

	ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_get_creds_opt_set_ticket");
	free_Ticket(&ticket);

	krb5_cc_close(context, id);
	krb5_free_principal(context, mc.server);

	krb5_get_creds_opt_add_options(context, opt,
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

    if (nametype_str != NULL) {
        ret = krb5_parse_nametype(context, nametype_str, &nametype);
        if (ret)
            krb5_err(context, 1, ret, "krb5_parse_nametype");
    }

    if (nametype == KRB5_NT_SRV_HST ||
        nametype == KRB5_NT_SRV_HST_NEEDS_CANON)
        is_hostbased_flag = 1;

    if (is_hostbased_flag) {
	const char *sname = NULL;
	const char *hname = NULL;

        if (nametype_str != NULL &&
            nametype != KRB5_NT_SRV_HST &&
            nametype != KRB5_NT_SRV_HST_NEEDS_CANON)
            krb5_errx(context, 1, "--hostbased not compatible with "
                      "non-hostbased --name-type");

        if (is_canonical_flag)
            nametype = KRB5_NT_SRV_HST;
        else
            nametype = KRB5_NT_SRV_HST_NEEDS_CANON;

        /*
         * Host-based service names can have more than one component.
         *
         * RFC5179 did not, but should have, assign a Kerberos name-type
         * corresponding to GSS_C_NT_DOMAINBASED.  But it's basically a
         * host-based service name type with one additional component.
         *
         * So that's how we're treating host-based service names here:
         * two or more components.
         */

        if (argc == 0) {
            usage(1);
        } else if (argc == 1) {
            krb5_principal server2;

            /*
             * In this case the one argument is a principal name, not the
             * service name.
             *
             * We parse the argument as a principal name, extract the service
             * and hostname components, use krb5_sname_to_principal(), then
             * extract the service and hostname components from that.
             */

            ret = krb5_parse_name(context, argv[0], &server);
            if (ret)
                krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]);
            sname = krb5_principal_get_comp_string(context, server, 0);

            /*
             * If a single-component principal name is given, then we'll
             * default the hostname, as krb5_principal_get_comp_string()
             * returns NULL in this case.
             */
            hname = krb5_principal_get_comp_string(context, server, 1);

	    ret = krb5_sname_to_principal(context, hname, sname,
					   KRB5_NT_SRV_HST, &server2);
            sname = krb5_principal_get_comp_string(context, server2, 0);
            hname = krb5_principal_get_comp_string(context, server2, 1);

            /*
             * Modify the original with the new sname/hname.  This way we
             * retain any additional principal name components from the given
             * principal name.
             *
             * The name-type is set further below.
             */
            ret = krb5_principal_set_comp_string(context, server, 0, sname);
            if (ret)
                krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]);
            ret = krb5_principal_set_comp_string(context, server, 1, hname);
            if (ret)
                krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]);
            krb5_free_principal(context, server2);
        } else {
            size_t i;

            /*
             * In this case the arguments are principal name components.
             *
             * The service and hostname components can be defaulted by passing
             * empty strings.
             */
	    sname = argv[0];
            if (*sname == '\0')
                sname = NULL;
	    hname = argv[1];
            if (hname == NULL || *hname == '\0')
                hname = NULL;
	    ret = krb5_sname_to_principal(context, hname, sname,
                                          KRB5_NT_SRV_HST, &server);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_sname_to_principal");

            for (i = 2; i < argc; i++) {
                ret = krb5_principal_set_comp_string(context, server, i, argv[i]);
                if (ret)
                    krb5_err(context, 1, ret, "krb5_principal_set_comp_string");
            }
	}
    } else if (argc == 1) {
	ret = krb5_parse_name(context, argv[0], &server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]);
    } else {
	usage(1);
    }

    if (nametype != KRB5_NT_UNKNOWN)
        server->name.name_type = (NAME_TYPE)nametype;

    ret = krb5_get_creds(context, opt, cache, server, &out);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_creds");

    if (out_cache_str) {
	krb5_ccache id;

	ret = krb5_cc_resolve(context, out_cache_str, &id);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_initialize(context, id, out->client);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, out);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_store_cred");
	krb5_cc_close(context, id);
    }

    krb5_free_creds(context, out);
    krb5_free_principal(context, server);
    krb5_get_creds_opt_free(context, opt);
    krb5_cc_close (context, cache);
    krb5_free_context (context);

    return 0;
}
Ejemplo n.º 6
0
krb5_error_code
krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache,
			   krb5_creds *in_cred, krb5_creds **out_cred,
			   krb5_creds ***tgts, int kdcopt)
{
    krb5_error_code retval, subretval;
    krb5_principal client, server, supplied_server, out_supplied_server;
    krb5_creds tgtq, cc_tgt, *tgtptr, *referral_tgts[KRB5_REFERRAL_MAXHOPS];
    krb5_creds *otgtptr = NULL;
    int tgtptr_isoffpath = 0;
    krb5_boolean old_use_conf_ktypes;
    char **hrealms;
    unsigned int referral_count, i;
    krb5_authdata **supplied_authdata, **out_supplied_authdata = NULL;

    /* 
     * Set up client and server pointers.  Make a fresh and modifyable
     * copy of the in_cred server and save the supplied version.
     */
    client = in_cred->client;
    if ((retval=krb5_copy_principal(context, in_cred->server, &server)))
        return retval;
    /* We need a second copy for the output creds. */
    if ((retval = krb5_copy_principal(context, server,
				      &out_supplied_server)) != 0 ) {
	krb5_free_principal(context, server);
	return retval;
    }
    if (in_cred->authdata != NULL) {
	if ((retval = krb5_copy_authdata(context, in_cred->authdata,
					 &out_supplied_authdata)) != 0) {
	    krb5_free_principal(context, out_supplied_server);
	    krb5_free_principal(context, server);
	    return retval;
	}
    }

    supplied_server = in_cred->server;
    in_cred->server=server;
    supplied_authdata = in_cred->authdata;

    DUMP_PRINC("gc_from_kdc initial client", client);
    DUMP_PRINC("gc_from_kdc initial server", server);
    memset(&cc_tgt, 0, sizeof(cc_tgt));
    memset(&tgtq, 0, sizeof(tgtq));
    memset(&referral_tgts, 0, sizeof(referral_tgts));

    tgtptr = NULL;
    *tgts = NULL;
    *out_cred=NULL;
    old_use_conf_ktypes = context->use_conf_ktypes;

    /* Copy client realm to server if no hint. */
    if (krb5_is_referral_realm(&server->realm)) {
        /* Use the client realm. */
        DPRINTF(("gc_from_kdc: no server realm supplied, "
		 "using client realm.\n"));
	krb5_free_data_contents(context, &server->realm);
	if (!( server->realm.data = (char *)malloc(client->realm.length+1)))
	    return ENOMEM;
	memcpy(server->realm.data, client->realm.data, client->realm.length);
	server->realm.length = client->realm.length;
	server->realm.data[server->realm.length] = 0;
    }
    /*
     * Retreive initial TGT to match the specified server, either for the
     * local realm in the default (referral) case or for the remote
     * realm if we're starting someplace non-local.
     */
    retval = tgt_mcred(context, client, server, client, &tgtq);
    if (retval)
	goto cleanup;

    /* Fast path: Is it in the ccache? */
    context->use_conf_ktypes = 1;
    retval = krb5_cc_retrieve_cred(context, ccache, RETR_FLAGS,
				   &tgtq, &cc_tgt);
    if (!retval) {
	tgtptr = &cc_tgt;
    } else if (!HARD_CC_ERR(retval)) {
        DPRINTF(("gc_from_kdc: starting do_traversal to find "
		 "initial TGT for referral\n"));
	tgtptr_isoffpath = 0;
	otgtptr = NULL;
	retval = do_traversal(context, ccache, client, server,
			      &cc_tgt, &tgtptr, tgts, &tgtptr_isoffpath);
    }
    if (retval) {
        DPRINTF(("gc_from_kdc: failed to find initial TGT for referral\n"));
        goto cleanup;
    }

    DUMP_PRINC("gc_from_kdc: server as requested", supplied_server);

    if (in_cred->second_ticket.length != 0 &&
	(kdcopt & KDC_OPT_CNAME_IN_ADDL_TKT) == 0) {
	kdcopt |= KDC_OPT_ENC_TKT_IN_SKEY;
    }

    /*
     * Try requesting a service ticket from our local KDC with referrals
     * turned on.  If the first referral succeeds, follow a referral-only
     * path, otherwise fall back to old-style assumptions.
     */

    /*
     * Save TGTPTR because we rewrite it in the referral loop, and
     * we might need to explicitly free it later.
     */
    otgtptr = tgtptr;
    for (referral_count = 0;
	 referral_count < KRB5_REFERRAL_MAXHOPS;
	 referral_count++) {
#if 0
        DUMP_PRINC("gc_from_kdc: referral loop: tgt in use", tgtptr->server);
        DUMP_PRINC("gc_from_kdc: referral loop: request is for", server);
#endif
        retval = krb5_get_cred_via_tkt(context, tgtptr,
				       KDC_OPT_CANONICALIZE | 
				       FLAGS2OPTS(tgtptr->ticket_flags) |  
				       kdcopt,
				       tgtptr->addresses, in_cred, out_cred);
	if (retval) {
	    DPRINTF(("gc_from_kdc: referral TGS-REQ request failed: <%s>\n",
		     error_message(retval)));
	    /* If we haven't gone anywhere yet, fail through to the
	       non-referral case. */
	    if (referral_count==0) {
	        DPRINTF(("gc_from_kdc: initial referral failed; "
			 "punting to fallback.\n"));
	        break;
	    }
	    /* Otherwise, try the same query without canonicalization
	       set, and fail hard if that doesn't work. */
	    DPRINTF(("gc_from_kdc: referral #%d failed; "
		     "retrying without option.\n", referral_count + 1));
	    retval = krb5_get_cred_via_tkt(context, tgtptr,
					   FLAGS2OPTS(tgtptr->ticket_flags) |  
					   kdcopt,
					   tgtptr->addresses,
					   in_cred, out_cred);
	    /* Whether or not that succeeded, we're done. */
	    goto cleanup;
	}
	/* Referral request succeeded; let's see what it is. */
	if (krb5_principal_compare(context, in_cred->server,
				   (*out_cred)->server)) {
	    DPRINTF(("gc_from_kdc: request generated ticket "
		     "for requested server principal\n"));
	    DUMP_PRINC("gc_from_kdc final referred reply",
		       in_cred->server);

	    /*
	     * Check if the return enctype is one that we requested if
	     * needed.
	     */
	    if (old_use_conf_ktypes || context->tgs_ktype_count == 0)
		goto cleanup;
	    for (i = 0; i < context->tgs_ktype_count; i++) {
		if ((*out_cred)->keyblock.enctype == context->tgs_ktypes[i]) {
		    /* Found an allowable etype, so we're done */
		    goto cleanup;
		}
	    }
	    /*
	     *  We need to try again, but this time use the
	     *  tgs_ktypes in the context. At this point we should
	     *  have all the tgts to succeed.
	     */

	    /* Free "wrong" credential */
	    krb5_free_creds(context, *out_cred);
	    *out_cred = NULL;
	    /* Re-establish tgs etypes */
	    context->use_conf_ktypes = old_use_conf_ktypes;
	    retval = krb5_get_cred_via_tkt(context, tgtptr,
					   KDC_OPT_CANONICALIZE | 
					   FLAGS2OPTS(tgtptr->ticket_flags) |  
					   kdcopt,
					   tgtptr->addresses,
					   in_cred, out_cred);
	    goto cleanup;
	}
	else if (IS_TGS_PRINC(context, (*out_cred)->server)) {
	    krb5_data *r1, *r2;

	    DPRINTF(("gc_from_kdc: request generated referral tgt\n"));
	    DUMP_PRINC("gc_from_kdc credential received",
		       (*out_cred)->server);

	    if (referral_count == 0)
		r1 = &tgtptr->server->data[1];
	    else
		r1 = &referral_tgts[referral_count-1]->server->data[1];

	    r2 = &(*out_cred)->server->data[1];
	    if (data_eq(*r1, *r2)) {
		DPRINTF(("gc_from_kdc: referred back to "
			 "previous realm; fall back\n"));
		krb5_free_creds(context, *out_cred);
		*out_cred = NULL;
		break;
	    }
	    /* Check for referral routing loop. */
	    for (i=0;i<referral_count;i++) {
#if 0
		DUMP_PRINC("gc_from_kdc: loop compare #1",
			   (*out_cred)->server);
		DUMP_PRINC("gc_from_kdc: loop compare #2",
			   referral_tgts[i]->server);
#endif
		if (krb5_principal_compare(context,
					   (*out_cred)->server,
					   referral_tgts[i]->server)) {
		    DFPRINTF((stderr,
			      "krb5_get_cred_from_kdc_opt: "
			      "referral routing loop - "
			      "got referral back to hop #%d\n", i));
		    retval=KRB5_KDC_UNREACH;
		    goto cleanup;
		}
	    }
	    /* Point current tgt pointer at newly-received TGT. */
	    if (tgtptr == &cc_tgt)
		krb5_free_cred_contents(context, tgtptr);
	    tgtptr=*out_cred;
	    /* Save requested auth data with TGT in case it ends up stored */
	    if (supplied_authdata != NULL) {
		/* Ensure we note TGT contains authorization data */
		retval = krb5_copy_authdata(context,
					    supplied_authdata,
					    &(*out_cred)->authdata);
		if (retval)
		    goto cleanup;
	    }
	    /* Save pointer to tgt in referral_tgts. */
	    referral_tgts[referral_count]=*out_cred;
	    *out_cred = NULL;
	    /* Copy krbtgt realm to server principal. */
	    krb5_free_data_contents(context, &server->realm);
	    retval = krb5int_copy_data_contents(context,
						&tgtptr->server->data[1],
						&server->realm);
	    if (retval)
		return retval;
	    /* Don't ask for KDC to add auth data multiple times */
	    in_cred->authdata = NULL;
	    /*
	     * Future work: rewrite server principal per any
	     * supplied padata.
	     */
	} else {
	    /* Not a TGT; punt to fallback. */
	    krb5_free_creds(context, *out_cred);
	    *out_cred = NULL;
	    break;
	}
    }

    DUMP_PRINC("gc_from_kdc client at fallback", client);
    DUMP_PRINC("gc_from_kdc server at fallback", server);

    /*
     * At this point referrals have been tried and have failed.  Go
     * back to the server principal as originally issued and try the
     * conventional path.
     */

    /*
     * Referrals have failed.  Look up fallback realm if not
     * originally provided.
     */
    if (krb5_is_referral_realm(&supplied_server->realm)) {
        if (server->length >= 2) {
	    retval=krb5_get_fallback_host_realm(context, &server->data[1],
						&hrealms);
	    if (retval) goto cleanup;
#if 0
	    DPRINTF(("gc_from_kdc: using fallback realm of %s\n",
		     hrealms[0]));
#endif
	    krb5_free_data_contents(context,&in_cred->server->realm);
	    server->realm.data=hrealms[0];
	    server->realm.length=strlen(hrealms[0]);
	    free(hrealms);
	}
	else {
	    /*
	     * Problem case: Realm tagged for referral but apparently not
	     * in a <type>/<host> format that
	     * krb5_get_fallback_host_realm can deal with.
	     */
	    DPRINTF(("gc_from_kdc: referral specified "
		     "but no fallback realm avaiable!\n"));
	    return KRB5_ERR_HOST_REALM_UNKNOWN;
	}
    }

    DUMP_PRINC("gc_from_kdc server at fallback after fallback rewrite",
	       server);

    /*
     * Get a TGT for the target realm.
     */

    krb5_free_cred_contents(context, &tgtq);
    retval = tgt_mcred(context, client, server, client, &tgtq);
    if (retval)
	goto cleanup;

    /* Fast path: Is it in the ccache? */
    /* Free tgtptr data if reused from above. */
    if (tgtptr == &cc_tgt)
	krb5_free_cred_contents(context, tgtptr);
    tgtptr = NULL;
    /* Free saved TGT in OTGTPTR if it was off-path. */
    if (tgtptr_isoffpath)
	krb5_free_creds(context, otgtptr);
    otgtptr = NULL;
    /* Free TGTS if previously filled by do_traversal() */
    if (*tgts != NULL) {
	for (i = 0; (*tgts)[i] != NULL; i++) {
	    krb5_free_creds(context, (*tgts)[i]);
	}
	free(*tgts);
	*tgts = NULL;
    }
    context->use_conf_ktypes = 1;
    retval = krb5_cc_retrieve_cred(context, ccache, RETR_FLAGS,
				   &tgtq, &cc_tgt);
    if (!retval) {
	tgtptr = &cc_tgt;
    } else if (!HARD_CC_ERR(retval)) {
	tgtptr_isoffpath = 0;
	retval = do_traversal(context, ccache, client, server,
			      &cc_tgt, &tgtptr, tgts, &tgtptr_isoffpath);
    }
    if (retval)
	goto cleanup;
    otgtptr = tgtptr;

    /*
     * Finally have TGT for target realm!  Try using it to get creds.
     */

    if (!krb5_c_valid_enctype(tgtptr->keyblock.enctype)) {
	retval = KRB5_PROG_ETYPE_NOSUPP;
	goto cleanup;
    }
    context->use_conf_ktypes = old_use_conf_ktypes;
    retval = krb5_get_cred_via_tkt(context, tgtptr,
				   FLAGS2OPTS(tgtptr->ticket_flags) |
				   kdcopt,
				   tgtptr->addresses, in_cred, out_cred);

cleanup:
    krb5_free_cred_contents(context, &tgtq);
    if (tgtptr == &cc_tgt)
	krb5_free_cred_contents(context, tgtptr);
    if (tgtptr_isoffpath)
	krb5_free_creds(context, otgtptr);
    context->use_conf_ktypes = old_use_conf_ktypes;
    /* Drop the original principal back into in_cred so that it's cached
       in the expected format. */
    DUMP_PRINC("gc_from_kdc: final hacked server principal at cleanup",
	       server);
    krb5_free_principal(context, server);
    in_cred->server = supplied_server;
    in_cred->authdata = supplied_authdata;
    if (*out_cred && !retval) {
        /* Success: free server, swap supplied server back in. */
        krb5_free_principal (context, (*out_cred)->server);
	(*out_cred)->server = out_supplied_server;
	assert((*out_cred)->authdata == NULL);
	(*out_cred)->authdata = out_supplied_authdata;
    }
    else {
        /* 
	 * Failure: free out_supplied_server.  Don't free out_cred here
	 * since it's either null or a referral TGT that we free below,
	 * and we may need it to return.
	 */
        krb5_free_principal(context, out_supplied_server);
	krb5_free_authdata(context, out_supplied_authdata);
    }
    DUMP_PRINC("gc_from_kdc: final server after reversion", in_cred->server);
    /*
     * Deal with ccache TGT management: If tgts has been set from
     * initial non-referral TGT discovery, leave it alone.  Otherwise, if
     * referral_tgts[0] exists return it as the only entry in tgts.
     * (Further referrals are never cached, only the referral from the
     * local KDC.)  This is part of cleanup because useful received TGTs
     * should be cached even if the main request resulted in failure.
     */

    if (*tgts == NULL) {
        if (referral_tgts[0]) {
#if 0
  	    /*
	     * This should possibly be a check on the candidate return
	     * credential against the cache, in the circumstance where we
	     * don't want to clutter the cache with near-duplicate
	     * credentials on subsequent iterations.  For now, it is
	     * disabled.
	     */
	    subretval=...?;
	    if (subretval) {
#endif
	        /* Allocate returnable TGT list. */
	        if (!(*tgts=calloc(sizeof (krb5_creds *), 2)))
		    return ENOMEM;
		subretval=krb5_copy_creds(context, referral_tgts[0], &((*tgts)[0]));
		if(subretval)
		    return subretval;
		(*tgts)[1]=NULL;
		DUMP_PRINC("gc_from_kdc: returning referral TGT for ccache",
			   (*tgts)[0]->server);
#if 0
	    }
#endif
	}
    }

    /* Free referral TGTs list. */
    for (i=0;i<KRB5_REFERRAL_MAXHOPS;i++) {
        if(referral_tgts[i]) {
	    krb5_free_creds(context, referral_tgts[i]);
	}
    }
    DPRINTF(("gc_from_kdc finishing with %s\n",
	     retval ? error_message(retval) : "no error"));
    return retval;
}
Ejemplo n.º 7
0
int main(int argc, char **argv)
{
	int log_level = 0;
	char *ap_req_str = NULL;
	char *plain_text_str;
	unsigned char *plain_text;
	size_t plain_text_len;

	/* krb5 */
	krb5_error_code ret;
	krb5_context context;
	krb5_auth_context auth_context;
	char *princ_str_tn = "kink/tn.example.com";
	krb5_principal princ_tn;
	char *princ_str_nut = "kink/nut.example.com";
	krb5_principal princ_nut;
	char *princ_str_krbtgt = "krbtgt/EXAMPLE.COM";
	krb5_principal princ_krbtgt;
	krb5_ccache ccache;
	krb5_keytab keytab;
	krb5_creds creds_tgt;
	krb5_data ap_req;
	krb5_data cipher_text;

	prog = (const char *) basename(argv[0]);
	if (prog == NULL) {
		fprintf(stderr,
			"basename: %s -- %s\n", strerror(errno), argv[0]);

		return(0);
		/* NOTREACHED */
	}

	{
		int ch = 0;

		while ((ch = getopt(argc, argv, "dq:")) != -1) {
			switch (ch) {
			case 'd':
				log_level++;
				break;
			case 'q':
				ap_req_str = optarg;
				break;
			default:
				usage();
				/* NOTREACHED */

				break;
			}
		}

		argc -= optind;
		argv += optind;
	}

	if (!argc) {
		usage();
		/* NOTREACHED */
	}
	plain_text_str = argv[0];

	{
		printf("DBG: %s starts arg(%s)\n", prog, plain_text_str);
	}

	/* prepare encrypted data */
	{
		{ /* stdout */
			printf("std:plain_text:%s\n", plain_text_str);
		}
		plain_text_len = strlen(plain_text_str);
		plain_text_len = plain_text_len/2 + plain_text_len%2;
		plain_text = (unsigned char *)malloc(plain_text_len);
		memset(plain_text, 0, plain_text_len);
		plain_text = hex2data(plain_text_str, plain_text);
	}

	if (ap_req_str != NULL) {
		hex2krb5data(ap_req_str, &ap_req);
		if (log_level) {
			dump_krb5_data(&ap_req);
		}
		{ /* stdout */
			int i = 0;
			unsigned char *p;
			p = (unsigned char *)ap_req.data;
			printf("std:ap_req:");
			for (i = 0; i < ap_req.length; i++) {
				printf("%02x", *p++);
			}
			printf("\n");
		}
	}

	/* prepare krb5 */
	{
		/** init context */
		ret = krb5_init_context(&context);
		if (ret != 0) {
			printf("ERR:krb5_init_context:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		/** setup principals */
		ret = krb5_parse_name(context, princ_str_tn, &princ_tn);
		if (ret != 0) {
			printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
		ret = krb5_parse_name(context, princ_str_nut, &princ_nut);
		if (ret != 0) {
			printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
		ret = krb5_parse_name(context, princ_str_krbtgt, &princ_krbtgt);
		if (ret != 0) {
			printf("ERR:krb5_parse_name:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		/** prepare credential cache */
		ret = krb5_cc_default(context, &ccache);
		if (ret != 0) {
			printf("ERR:krb5_cc_default:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		/** prepare keytab */
		/*ret = krb5_kt_resolve(context, "/usr/local/var/krb5kdc/kadm5.keytab", &keytab);*/
		ret = krb5_kt_default(context, &keytab);
		if (ret != 0) {
			/* printf("ERR:krb5_kt_default:%s", krb5_get_err_text(context, ret)); */
			printf("ERR:krb5_kt_resolve:%s", krb5_get_err_text(context, ret));
			return(ret);
		}

	}

	/* get TGT */
	/* just only retrieve TGT from credential cache */
	{
		krb5_creds mcreds;
		memset(&mcreds, 0, sizeof(mcreds));
		mcreds.client = princ_tn;
		mcreds.server = princ_krbtgt;

		ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &creds_tgt);
		if (ret != 0) {
			printf("ERR:krb5_cc_retrieve_cred:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
	}

	/* prepare authentiation context */
	{
		ret = krb5_auth_con_init(context, &auth_context);
		if (ret != 0) {
			printf("ERR:krb5_auth_con_init:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		ret = krb5_auth_con_setflags(context, auth_context,
					     KRB5_AUTH_CONTEXT_DO_SEQUENCE);
		if (ret != 0) {
			printf("ERR:krb5_auth_con_setflags:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		/* if USE_SKEY */
		/*
		ret = krb5_auth_con_setuserkey(context, auth_context, &creds_tgt.session);
		if (ret != 0) {
			printf("ERR:krb5_auth_con_setuseruserkey:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
		*/
	}

	/* set keyblock in auth_context */
	if (ap_req_str != NULL) {
		krb5_ticket *ticket;
		krb5_flags ap_req_options;
		
		ap_req_options = AP_OPTS_MUTUAL_REQUIRED;
		ticket = NULL;
		ret = krb5_rd_req(context,
				  &auth_context,
				  &ap_req,
				  NULL,
				  keytab,
				  &ap_req_options,
				  &ticket);
		if (log_level) {
			printf("info: ticket.ticket.key is SKEYID_d\n");
			/*dump_krb5_ticket(context, *ticket);*/
		}
		if (log_level) {
			printf("ap_req_opt (%d)\n", ap_req_options);
		}
		if (ret != 0) {
			printf("ERR:krb5_rd_req:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
		if (log_level) {
			dump_krb5_keyblock(auth_context->keyblock);
		}

		krb5_free_ticket(context, ticket);
	}
	else {
		krb5_creds mcreds;
		krb5_creds *cred;
		krb5_creds cred_copy;

		memset(&mcreds, 0, sizeof(mcreds));
		mcreds.client = princ_tn;
		mcreds.server = princ_nut;

		ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &mcreds, &cred);
		if (ret != 0) {
			printf("ERR:krb5_get_credentials:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		/* mk_req_extends reallocate cred, so use a copy */
		ret = krb5_copy_creds_contents(context,
					       (const krb5_creds *)cred,
					       &cred_copy);
		if (ret != 0) {
			printf("ERR:krb5_copy_creds_contents:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		/*
		 * If auth_con == NULL, one is allocated.
		 * This is used later. (keyblock is used to decrypt AP_REP)
		 */
		ret = krb5_mk_req_extended(context,
					   &auth_context,
					   AP_OPTS_MUTUAL_REQUIRED,
					   NULL /* in_data */,
					   &cred_copy,
					   &ap_req);
		if (ret != 0) {
			printf("ERR:krb5_mk_req_extended:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
	}

	/* encrypt */
	{
		krb5_crypto crypto;

		ret = krb5_crypto_init(context,
				       auth_context->keyblock,
				       auth_context->keyblock->keytype,
				       &crypto);
		if (ret != 0) {
			printf("ERR:krb5_crypto_init:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		ret = krb5_encrypt(context,
				   crypto,
				   39, /* usage */
				   plain_text,
				   plain_text_len,
				   &cipher_text);
		if (ret != 0) {
			printf("ERR:krb5_encrypt:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}
		{ /* stdout */
			int i = 0;
			unsigned char *p;
			p = (unsigned char *)cipher_text.data;
			printf("std:cipher_text:");
			for (i = 0; i < cipher_text.length; i++) {
				printf("%02x", *p++);
			}
			printf("\n");
		}

		krb5_crypto_destroy(context, crypto);
	}

	/* clenaup */
	{
		/*free(plain_text);*/
		/*krb5_data_free(&ap_req);*/
		krb5_free_cred_contents(context, &creds_tgt);

		ret = krb5_kt_close(context, keytab);
		if (ret != 0) {
			printf("ERR:krb5_kt_close:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		ret = krb5_cc_close(context, ccache);
		if (ret != 0) {
			printf("ERR:krb5_cc_close:%s\n", krb5_get_err_text(context, ret));
			return(ret);
		}

		krb5_free_principal(context, princ_krbtgt);
		krb5_free_principal(context, princ_nut);
		krb5_free_principal(context, princ_tn);
		krb5_free_context(context);
	}

	return(0);
}