Exemple #1
0
static time_t
renew_func(void *ptr)
{
    struct renew_ctx *ctx = ptr;
    krb5_error_code ret;
    time_t expire;
    int new_tickets = 0;

    if (renewable_flag) {
	ret = renew_validate(ctx->context, renewable_flag, validate_flag,
			     ctx->ccache, server_str, ctx->ticket_life);
	if (ret)
	    new_tickets = 1;
    } else
	new_tickets = 1;

    if (new_tickets)
	get_new_tickets(ctx->context, ctx->principal,
			ctx->ccache, ctx->ticket_life, 0);

#ifndef NO_AFS
    if(do_afslog && k_hasafs())
	krb5_afslog(ctx->context, ctx->ccache, NULL, NULL);
#endif

    expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
			     server_str) / 2;
    return expire + 1;
}
Exemple #2
0
static time_t
renew_func(void *ptr)
{
    struct renew_ctx *ctx = ptr;
    time_t expire;
    time_t renew_expire;
    static time_t exp_delay = 1;

    expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
			     server_str, &renew_expire);

    if (renew_expire > expire) {
	renew_validate(ctx->context, 1, validate_flag, ctx->ccache,
		       server_str, ctx->ticket_life);
        expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
				 server_str, &renew_expire);
    }

    if (expire < ctx->ticket_life / 2) {
	get_new_tickets(ctx->context, ctx->principal,
			ctx->ccache, ctx->ticket_life, 0);
        expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
				 server_str, &renew_expire);
    }

#ifndef NO_AFS
    if(do_afslog && k_hasafs())
	krb5_afslog(ctx->context, ctx->ccache, NULL, NULL);
#endif

    /*
     * If our tickets have expired and we been able to either renew them
     * or obtain new tickets, then we still call this function but we use
     * an exponential backoff.  This should take care of the case where
     * we are using stored credentials but the KDC has been unavailable
     * for some reason...
     */

    if (expire < 1) {
        if (exp_delay < 7200)
	    exp_delay *= 2;
	return exp_delay;
    }
    exp_delay = 1;

    return expire / 2 + 1;
}
Exemple #3
0
static time_t
renew_func(void *ptr)
{
    krb5_error_code ret;
    struct renew_ctx *ctx = ptr;
    time_t renew_expire;
    static time_t exp_delay = 1;

    /*
     * NOTE: We count on the ccache implementation to notice changes to the
     * actual ccache filesystem/whatever objects.  There should be no ccache
     * types for which this is not the case, but it might not hurt to
     * re-krb5_cc_resolve() after each successful renew_validate()/
     * get_new_tickets() call.
     */

    expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
			     server_str, &renew_expire);

    /*
     * When a keytab is available to obtain new tickets, if we are within
     * half of the original ticket lifetime of the renew limit, get a new
     * TGT instead of renewing the existing TGT.  Note, ctx->ticket_life
     * is zero by default (without a '-l' option) and cannot be used to
     * set the time scale on which we decide whether we're "close to the
     * renew limit".
     */
    if (use_keytab || keytab_str)
	expire += ctx->timeout;
    if (renew_expire > expire) {
	ret = renew_validate(ctx->context, 1, validate_flag, ctx->ccache,
		       server_str, ctx->ticket_life);
    } else {
	ret = get_new_tickets(ctx->context, ctx->principal, ctx->ccache,
			      ctx->ticket_life, 0);
    }
    expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
			     server_str, &renew_expire);

#ifndef NO_AFS
    if (ret == 0 && server_str == NULL && do_afslog && k_hasafs())
	krb5_afslog(ctx->context, ctx->ccache, NULL, NULL);
#endif

    update_siginfo_msg(expire, server_str);

    /*
     * If our tickets have expired and we been able to either renew them
     * or obtain new tickets, then we still call this function but we use
     * an exponential backoff.  This should take care of the case where
     * we are using stored credentials but the KDC has been unavailable
     * for some reason...
     */

    if (expire < 1) {
	/*
	 * We can't ask to keep spamming stderr but not syslog, so we warn
	 * only once.
	 */
	if (exp_delay == 1) {
	    krb5_warnx(ctx->context, N_("NOTICE: Could not renew/refresh "
					"tickets", ""));
	}
        if (exp_delay < 7200)
	    exp_delay += exp_delay / 2 + 1;
	return exp_delay;
    }
    exp_delay = 1;

    return expire / 2 + 1;
}
Exemple #4
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache  ccache;
    krb5_principal principal = NULL;
    int optidx = 0;
    krb5_deltat ticket_life = 0;
#ifdef HAVE_SIGACTION
    struct sigaction sa;
#endif

    setprogname(argv[0]);

    setlocale(LC_ALL, "");
    bindtextdomain("heimdal_kuser", HEIMDAL_LOCALEDIR);
    textdomain("heimdal_kuser");

    ret = krb5_init_context(&context);
    if (ret == KRB5_CONFIG_BADFORMAT)
	errx(1, "krb5_init_context failed to parse configuration file");
    else 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;

    /*
     * Open the keytab now, we use the keytab to determine the principal's
     * realm when the requested principal has no realm.
     */
    if (use_keytab || keytab_str) {
	if (keytab_str)
	    ret = krb5_kt_resolve(context, keytab_str, &kt);
	else
	    ret = krb5_kt_default(context, &kt);
	if (ret)
	    krb5_err(context, 1, ret, "resolving keytab");
    }

    if (pk_enterprise_flag) {
	ret = krb5_pk_enterprise_cert(context, pk_user_id,
				      argv[0], &principal,
				      &ent_user_id);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");

	pk_user_id = NULL;

    } else if (anonymous_flag) {

	ret = krb5_make_principal(context, &principal, argv[0],
				  KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
				  NULL);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_make_principal");
	krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);

    } else if (use_keytab || keytab_str) {
	get_princ_kt(context, &principal, argv[0]);
    } else {
	get_princ(context, &principal, argv[0]);
    }

    if (fcache_version)
	krb5_set_fcache_version(context, fcache_version);

    if (renewable_flag == -1)
	/* this seems somewhat pointless, but whatever */
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"renewable", FALSE, &renewable_flag);
    if (do_afslog == -1)
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"afslog", TRUE, &do_afslog);

    if (cred_cache)
	ret = krb5_cc_resolve(context, cred_cache, &ccache);
    else {
	if (argc > 1) {
	    char s[1024];
	    ret = krb5_cc_new_unique(context, NULL, NULL, &ccache);
	    if (ret)
		krb5_err(context, 1, ret, "creating cred cache");
	    snprintf(s, sizeof(s), "%s:%s",
		     krb5_cc_get_type(context, ccache),
		     krb5_cc_get_name(context, ccache));
	    setenv("KRB5CCNAME", s, 1);
	} else {
	    ret = krb5_cc_cache_match(context, principal, &ccache);
	    if (ret) {
		const char *type;
		ret = krb5_cc_default(context, &ccache);
		if (ret)
		    krb5_err(context, 1, ret,
			     N_("resolving credentials cache", ""));

		/*
		 * Check if the type support switching, and we do,
		 * then do that instead over overwriting the current
		 * default credential
		 */
		type = krb5_cc_get_type(context, ccache);
		if (krb5_cc_support_switch(context, type)) {
		    krb5_cc_close(context, ccache);
		    ret = get_switched_ccache(context, type, principal,
					      &ccache);
		}
	    }
	}
    }
    if (ret)
	krb5_err(context, 1, ret, N_("resolving credentials cache", ""));

#ifndef NO_AFS
    if (argc > 1 && k_hasafs())
	k_setpag();
#endif

    if (lifetime) {
	int tmp = parse_time(lifetime, "s");
	if (tmp < 0)
	    errx(1, N_("unparsable time: %s", ""), lifetime);

	ticket_life = tmp;
    }

    if (addrs_flag == 0 && extra_addresses.num_strings > 0)
	krb5_errx(context, 1,
		  N_("specifying both extra addresses and "
		     "no addresses makes no sense", ""));
    {
	int i;
	krb5_addresses addresses;
	memset(&addresses, 0, sizeof(addresses));
	for(i = 0; i < extra_addresses.num_strings; i++) {
	    ret = krb5_parse_address(context, extra_addresses.strings[i],
				     &addresses);
	    if (ret == 0) {
		krb5_add_extra_addresses(context, &addresses);
		krb5_free_addresses(context, &addresses);
	    }
	}
	free_getarg_strings(&extra_addresses);
    }

    if (renew_flag || validate_flag) {
	ret = renew_validate(context, renew_flag, validate_flag,
			     ccache, server_str, ticket_life);

#ifndef NO_AFS
	if (ret == 0 && server_str == NULL && do_afslog && k_hasafs())
	    krb5_afslog(context, ccache, NULL, NULL);
#endif

	exit(ret != 0);
    }

    ret = get_new_tickets(context, principal, ccache, ticket_life, 1);
    if (ret)
	exit(1);

#ifndef NO_AFS
    if (ret == 0 && server_str == NULL && do_afslog && k_hasafs())
	krb5_afslog(context, ccache, NULL, NULL);
#endif

    if (argc > 1) {
	struct renew_ctx ctx;
	time_t timeout;

	timeout = ticket_lifetime(context, ccache, principal,
				  server_str, NULL) / 2;

	ctx.context = context;
	ctx.ccache = ccache;
	ctx.principal = principal;
	ctx.ticket_life = ticket_life;
	ctx.timeout = timeout;

#ifdef HAVE_SIGACTION
	memset(&sa, 0, sizeof(sa));
	sigemptyset(&sa.sa_mask);
	sa.sa_handler = handle_siginfo;

	sigaction(SIGINFO, &sa, NULL);
#endif

	ret = simple_execvp_timed(argv[1], argv+1,
				  renew_func, &ctx, timeout);
#define EX_NOEXEC	126
#define EX_NOTFOUND	127
	if (ret == EX_NOEXEC)
	    krb5_warnx(context, N_("permission denied: %s", ""), argv[1]);
	else if (ret == EX_NOTFOUND)
	    krb5_warnx(context, N_("command not found: %s", ""), argv[1]);

	krb5_cc_destroy(context, ccache);
#ifndef NO_AFS
	if (k_hasafs())
	    k_unlog();
#endif
    } else {
	krb5_cc_close(context, ccache);
	ret = 0;
    }
    krb5_free_principal(context, principal);
    if (kt)
	krb5_kt_close(context, kt);
    krb5_free_context(context);
    return ret;
}
Exemple #5
0
int
main (int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache  ccache;
    krb5_principal principal;
    int optidx = 0;
    krb5_deltat ticket_life = 0;
    int parseflags = 0;

    setprogname (argv[0]);

    setlocale (LC_ALL, "");
#if defined(HEIMDAL_LOCALEDIR)
    bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR);
    textdomain("heimdal_kuser");
#endif

    ret = krb5_init_context (&context);
    if (ret == KRB5_CONFIG_BADFORMAT)
	errx (1, "krb5_init_context failed to parse configuration file");
    else 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 (canonicalize_flag)
	parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;

    if (argv[0]) {
	ret = krb5_parse_name_flags (context, argv[0], parseflags, &principal);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_parse_name");
    } else {
	ret = krb5_get_default_principal (context, &principal);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_get_default_principal");
    }

    if(fcache_version)
	krb5_set_fcache_version(context, fcache_version);

    if(renewable_flag == -1)
	/* this seems somewhat pointless, but whatever */
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"renewable", FALSE, &renewable_flag);
#ifndef HEIMDAL_SMALLER
    if(get_v4_tgt == -1)
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"krb4_get_tickets", FALSE, &get_v4_tgt);
#endif
    if(do_afslog == -1)
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"afslog", TRUE, &do_afslog);

    if(cred_cache)
	ret = krb5_cc_resolve(context, cred_cache, &ccache);
    else {
	if(argc > 1) {
	    char s[1024];
	    ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache);
	    if(ret)
		krb5_err(context, 1, ret, "creating cred cache");
	    snprintf(s, sizeof(s), "%s:%s",
		     krb5_cc_get_type(context, ccache),
		     krb5_cc_get_name(context, ccache));
	    setenv("KRB5CCNAME", s, 1);
#ifndef HEIMDAL_SMALLER
	    if (get_v4_tgt) {
		int fd;
		if (asprintf(&krb4_cc_name, "%s_XXXXXX", TKT_ROOT) < 0)
		    krb5_errx(context, 1, "out of memory");
		if((fd = mkstemp(krb4_cc_name)) >= 0) {
		    close(fd);
		    setenv("KRBTKFILE", krb4_cc_name, 1);
		} else {
		    free(krb4_cc_name);
		    krb4_cc_name = NULL;
		}
	    }
#endif
	} else {
	    ret = krb5_cc_cache_match(context, principal, &ccache);
	    if (ret)
		ret = krb5_cc_default (context, &ccache);
	}
    }
    if (ret)
	krb5_err (context, 1, ret, N_("resolving credentials cache", ""));

    if(argc > 1 && k_hasafs ())
	k_setpag();

    if (lifetime) {
	int tmp = parse_time (lifetime, "s");
	if (tmp < 0)
	    errx (1, N_("unparsable time: %s", ""), lifetime);

	ticket_life = tmp;
    }

    if(addrs_flag == 0 && extra_addresses.num_strings > 0)
	krb5_errx(context, 1,
		  N_("specifying both extra addresses and "
		     "no addresses makes no sense", ""));
    {
	int i;
	krb5_addresses addresses;
	memset(&addresses, 0, sizeof(addresses));
	for(i = 0; i < extra_addresses.num_strings; i++) {
	    ret = krb5_parse_address(context, extra_addresses.strings[i],
				     &addresses);
	    if (ret == 0) {
		krb5_add_extra_addresses(context, &addresses);
		krb5_free_addresses(context, &addresses);
	    }
	}
	free_getarg_strings(&extra_addresses);
    }

    if(renew_flag || validate_flag) {
	ret = renew_validate(context, renew_flag, validate_flag,
			     ccache, server_str, ticket_life);
	exit(ret != 0);
    }

#ifndef HEIMDAL_SMALLER
    if(!convert_524)
#endif
	get_new_tickets(context, principal, ccache, ticket_life, 1);

#ifndef HEIMDAL_SMALLER
    if(get_v4_tgt || convert_524)
	do_524init(context, ccache, NULL, server_str);
#endif
    if(do_afslog && k_hasafs())
	krb5_afslog(context, ccache, NULL, NULL);
    if(argc > 1) {
	struct renew_ctx ctx;
	time_t timeout;

	timeout = ticket_lifetime(context, ccache, principal, server_str) / 2;

	ctx.context = context;
	ctx.ccache = ccache;
	ctx.principal = principal;
	ctx.ticket_life = ticket_life;

	ret = simple_execvp_timed(argv[1], argv+1,
				  renew_func, &ctx, timeout);
#define EX_NOEXEC	126
#define EX_NOTFOUND	127
	if(ret == EX_NOEXEC)
	    krb5_warnx(context, N_("permission denied: %s", ""), argv[1]);
	else if(ret == EX_NOTFOUND)
	    krb5_warnx(context, N_("command not found: %s", ""), argv[1]);
	
	krb5_cc_destroy(context, ccache);
#ifndef HEIMDAL_SMALLER
	_krb5_krb_dest_tkt(context, krb4_cc_name);
#endif
	if(k_hasafs())
	    k_unlog();
    } else {
	krb5_cc_close (context, ccache);
	ret = 0;
    }
    krb5_free_principal(context, principal);
    krb5_free_context (context);
    return ret;
}