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; }
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; }
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; }
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; }
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; }