10 volatile int died = 0;
12 int execmode = 0, failsafe = 0;
13 int verbose = 0, quiet = 0;
16 krb5_context context = NULL;
17 krb5_ccache ccache = NULL;
19 void cleanup_krb5(void)
22 krb5_cc_close(context, ccache);
25 krb5_free_context(context);
29 void sighandler(int sig)
53 if((ret = krb5_cc_default(context, &ccache)) != 0) {
55 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
61 memset(&creds, 0, sizeof(creds));
62 if((ret = krb5_cc_get_principal(context, ccache, &me)) != 0) {
64 fprintf(stderr, "could not get principal from cache: %s\n", error_message(ret));
67 if((ret = krb5_get_renewed_creds(context, &creds, me, ccache, NULL)) != 0) {
69 fprintf(stderr, "could not get renewed credentials: %s\n", error_message(ret));
72 if((ret = krb5_cc_initialize(context, ccache, me)) != 0) {
74 fprintf(stderr, "could not reinitialize cache: %s\n", error_message(ret));
75 krb5_free_cred_contents(context, &creds);
78 if((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) {
80 fprintf(stderr, "could not store renewed credentials: %s\n", error_message(ret));
81 krb5_free_cred_contents(context, &creds);
84 krb5_free_cred_contents(context, &creds);
86 printf("successfully renewed credentials\n");
90 krb5_free_principal(context, me);
93 time_t goodrenewtime(void)
104 if((ret = krb5_cc_default(context, &ccache)) != 0) {
106 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
114 if((ret = krb5_cc_get_principal(context, ccache, &me)) != 0) {
116 fprintf(stderr, "could not get principal from cache: %s\n", error_message(ret));
119 if((ret = krb5_cc_start_seq_get(context, ccache, &cur)) != 0) {
121 fprintf(stderr, "could not open credentials cache: %s\n", error_message(ret));
125 while(!krb5_cc_next_cred(context, ccache, &cur, &creds)) {
126 if(!strcmp(krb5_princ_component(context, creds.server, 0)->data, KRB5_TGS_NAME) &&
127 !strcmp(krb5_princ_component(context, creds.server, 1)->data, me->realm.data)) {
128 if(!creds.times.starttime)
129 creds.times.starttime = creds.times.authtime;
130 good = (creds.times.starttime + (((creds.times.endtime - creds.times.starttime) * 9) / 10));
133 krb5_free_cred_contents(context, &creds);
138 krb5_cc_end_seq_get(context, ccache, &cur);
140 krb5_free_principal(context, me);
144 int main(int argc, char **argv)
148 time_t interval, now;
153 while((c = getopt(argc, argv, "+hi:vqf")) != -1) {
165 p = optarg + strlen(optarg) - 1;
166 if((*p >= 'a') && (*p <= 'z')) {
179 interval *= atoi(optarg);
185 fprintf(stderr, "usage: krb5-agent [-hvqf] [-i interval] [program args...]\n");
186 exit((c == 'h')?0:1);
190 atexit(cleanup_krb5);
191 if((ret = krb5_init_context(&context)) != 0) {
193 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
197 if(context != NULL) {
198 if((ret = krb5_cc_default(context, &ccache)) != 0) {
200 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
208 signal(SIGCHLD, sighandler);
209 if((child = fork()) < 0) {
215 snprintf(buf, 80, "KRB5_AGENT_PID=%i", getpid());
217 execvp(argv[optind], argv + optind);
218 perror(argv[optind]);
221 signal(SIGHUP, sighandler);
222 signal(SIGINT, sighandler);
223 signal(SIGTERM, sighandler);
227 renewat = now + interval;
230 wpid = waitpid(-1, &status, WNOHANG);
233 } else if(execmode && (wpid == child)) {
234 /* Try to preserve exit status as best as we can... */
235 if(WIFEXITED(status)) {
236 exit(WEXITSTATUS(status));
239 signal(WTERMSIG(status), SIG_DFL);
240 kill(getpid(), WTERMSIG(status));
247 if((renewat = goodrenewtime()) < 0) {
249 } else if(verbose >= 2) {
250 printf("will renew tickets at %s", ctime(&renewat));
256 sleep(renewat - now);
258 if((renewat >= 0) && (now >= renewat)) {
262 renewat = now + interval;
269 * compile-command: "gcc -Wall -g -o krb5-agent krb5-agent.c -lkrb5"