#include <signal.h>
#include <sys/wait.h>
-#define STD_INTERVAL (3600 * 8)
-
volatile int died = 0;
pid_t child;
int execmode = 0, failsafe = 0;
int verbose = 0, quiet = 0;
+time_t renewat;
+
krb5_context context = NULL;
krb5_ccache ccache = NULL;
{
if(ccache != NULL)
krb5_cc_close(context, ccache);
+ ccache = NULL;
if(context != NULL)
krb5_free_context(context);
+ context = NULL;
}
void sighandler(int sig)
case SIGCHLD:
died = 1;
break;
+ case SIGHUP:
+ case SIGINT:
+ case SIGTERM:
+ if(execmode)
+ kill(child, sig);
+ break;
}
}
void renew(void)
{
int ret;
+ krb5_principal me;
+ krb5_creds creds;
- if(ccache == NULL)
+ if(context == NULL)
return;
+ if(ccache == NULL) {
+ if((ret = krb5_cc_default(context, &ccache)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
+ return;
+ }
+ }
+
+ me = NULL;
+ memset(&creds, 0, sizeof(creds));
+ if((ret = krb5_cc_get_principal(context, ccache, &me)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not get principal from cache: %s\n", error_message(ret));
+ goto out;
+ }
+ if((ret = krb5_get_renewed_creds(context, &creds, me, ccache, NULL)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not get renewed credentials: %s\n", error_message(ret));
+ goto out;
+ }
+ if((ret = krb5_cc_initialize(context, ccache, me)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not reinitialize cache: %s\n", error_message(ret));
+ krb5_free_cred_contents(context, &creds);
+ goto out;
+ }
+ if((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not store renewed credentials: %s\n", error_message(ret));
+ krb5_free_cred_contents(context, &creds);
+ goto out;
+ }
+ krb5_free_cred_contents(context, &creds);
+ if(verbose >= 1)
+ printf("successfully renewed credentials\n");
+
+ out:
+ if(me != NULL)
+ krb5_free_principal(context, me);
+}
+
+time_t goodrenewtime(void)
+{
+ int ret;
+ krb5_principal me;
+ krb5_cc_cursor cur;
+ krb5_creds creds;
+ time_t now, good;
+
+ if(context == NULL)
+ return(-1);
+ if(ccache == NULL) {
+ if((ret = krb5_cc_default(context, &ccache)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
+ return(-1);
+ }
+ }
+
+ me = NULL;
+ cur = NULL;
+ good = -1;
+ if((ret = krb5_cc_get_principal(context, ccache, &me)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not get principal from cache: %s\n", error_message(ret));
+ goto out;
+ }
+ if((ret = krb5_cc_start_seq_get(context, ccache, &cur)) != 0) {
+ if(!quiet)
+ fprintf(stderr, "could not open credentials cache: %s\n", error_message(ret));
+ goto out;
+ }
+ now = time(NULL);
+ while(!krb5_cc_next_cred(context, ccache, &cur, &creds)) {
+ if(!strcmp(krb5_princ_component(context, creds.server, 0)->data, KRB5_TGS_NAME) &&
+ !strcmp(krb5_princ_component(context, creds.server, 1)->data, me->realm.data)) {
+ if(!creds.times.starttime)
+ creds.times.starttime = creds.times.authtime;
+ good = (creds.times.starttime + (((creds.times.endtime - creds.times.starttime) * 9) / 10));
+ break;
+ }
+ krb5_free_cred_contents(context, &creds);
+ }
+
+ out:
+ if(cur != NULL)
+ krb5_cc_end_seq_get(context, ccache, &cur);
+ if(me != NULL)
+ krb5_free_principal(context, me);
+ return(good);
}
int main(int argc, char **argv)
{
char *p;
int c;
- time_t interval, last, now;
+ time_t interval, now;
pid_t wpid;
int ret, status;
- interval = STD_INTERVAL;
+ interval = -1;
while((c = getopt(argc, argv, "+hi:vqf")) != -1) {
switch(c) {
case 'v':
break;
case 'i':
p = optarg + strlen(optarg) - 1;
- if((*p >= 'a') || (*p <= 'z')) {
+ if((*p >= 'a') && (*p <= 'z')) {
if(*p == 'm')
interval = 60;
else if(*p == 'h')
perror(argv[optind]);
exit(255);
}
+ signal(SIGHUP, sighandler);
+ signal(SIGINT, sighandler);
+ signal(SIGTERM, sighandler);
}
- now = last = time(NULL);
+ now = time(NULL);
+ if(interval >= 0)
+ renewat = now + interval;
while(1) {
if(died) {
wpid = waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status)) {
exit(WEXITSTATUS(status));
} else {
+ cleanup_krb5();
signal(WTERMSIG(status), SIG_DFL);
kill(getpid(), WTERMSIG(status));
exit(255);
}
died = 0;
}
- sleep((last + interval) - now);
+ if(interval < 0) {
+ if((renewat = goodrenewtime()) < 0) {
+ renewat = -1;
+ } else if(verbose >= 2) {
+ printf("will renew tickets at %s", ctime(&renewat));
+ }
+ }
+ if(renewat < 0)
+ sleep(60);
+ else
+ sleep(renewat - now);
now = time(NULL);
- if(now >= last + interval)
+ if((renewat >= 0) && (now >= renewat)) {
renew();
+ now = time(NULL);
+ if(interval >= 0)
+ renewat = now + interval;
+ }
}
}