2 * krb5-agent - Renews Kerberos tickets periodically.
3 * Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 volatile int died = 0;
30 int execmode = 0, failsafe = 0;
31 int verbose = 0, quiet = 0;
34 krb5_context context = NULL;
35 krb5_ccache ccache = NULL;
37 void cleanup_krb5(void)
40 krb5_cc_close(context, ccache);
43 krb5_free_context(context);
47 void sighandler(int sig)
71 if((ret = krb5_cc_default(context, &ccache)) != 0) {
73 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
79 memset(&creds, 0, sizeof(creds));
80 if((ret = krb5_cc_get_principal(context, ccache, &me)) != 0) {
82 fprintf(stderr, "could not get principal from cache: %s\n", error_message(ret));
85 if((ret = krb5_get_renewed_creds(context, &creds, me, ccache, NULL)) != 0) {
87 fprintf(stderr, "could not get renewed credentials: %s\n", error_message(ret));
90 if((ret = krb5_cc_initialize(context, ccache, me)) != 0) {
92 fprintf(stderr, "could not reinitialize cache: %s\n", error_message(ret));
93 krb5_free_cred_contents(context, &creds);
96 if((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) {
98 fprintf(stderr, "could not store renewed credentials: %s\n", error_message(ret));
99 krb5_free_cred_contents(context, &creds);
102 krb5_free_cred_contents(context, &creds);
104 printf("successfully renewed credentials\n");
108 krb5_free_principal(context, me);
111 time_t goodrenewtime(void)
122 if((ret = krb5_cc_default(context, &ccache)) != 0) {
124 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
132 if((ret = krb5_cc_get_principal(context, ccache, &me)) != 0) {
134 fprintf(stderr, "could not get principal from cache: %s\n", error_message(ret));
137 if((ret = krb5_cc_start_seq_get(context, ccache, &cur)) != 0) {
139 fprintf(stderr, "could not open credentials cache: %s\n", error_message(ret));
143 while(!krb5_cc_next_cred(context, ccache, &cur, &creds)) {
144 if(!strcmp(krb5_princ_component(context, creds.server, 0)->data, KRB5_TGS_NAME) &&
145 !strcmp(krb5_princ_component(context, creds.server, 1)->data, me->realm.data)) {
146 if(!creds.times.starttime)
147 creds.times.starttime = creds.times.authtime;
148 good = (creds.times.starttime + (((creds.times.endtime - creds.times.starttime) * 9) / 10));
151 krb5_free_cred_contents(context, &creds);
156 krb5_cc_end_seq_get(context, ccache, &cur);
158 krb5_free_principal(context, me);
162 int main(int argc, char **argv)
166 time_t interval, now;
171 while((c = getopt(argc, argv, "+hi:vqf")) != -1) {
183 p = optarg + strlen(optarg) - 1;
184 if((*p >= 'a') && (*p <= 'z')) {
197 interval *= atoi(optarg);
203 fprintf(stderr, "usage: krb5-agent [-hvqf] [-i interval] [program args...]\n");
204 exit((c == 'h')?0:1);
208 atexit(cleanup_krb5);
209 if((ret = krb5_init_context(&context)) != 0) {
211 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
215 if(context != NULL) {
216 if((ret = krb5_cc_default(context, &ccache)) != 0) {
218 fprintf(stderr, "could not initialize Kerberos context: %s\n", error_message(ret));
226 signal(SIGCHLD, sighandler);
227 if((child = fork()) < 0) {
233 snprintf(buf, 80, "KRB5_AGENT_PID=%i", getppid());
235 execvp(argv[optind], argv + optind);
236 perror(argv[optind]);
239 signal(SIGHUP, sighandler);
240 signal(SIGINT, sighandler);
241 signal(SIGTERM, sighandler);
245 renewat = now + interval;
248 wpid = waitpid(-1, &status, WNOHANG);
251 } else if(execmode && (wpid == child)) {
252 /* Try to preserve exit status as best as we can... */
253 if(WIFEXITED(status)) {
254 exit(WEXITSTATUS(status));
257 signal(WTERMSIG(status), SIG_DFL);
258 kill(getpid(), WTERMSIG(status));
265 if((renewat = goodrenewtime()) < 0) {
267 } else if(verbose >= 2) {
268 printf("will renew tickets at %s", ctime(&renewat));
274 sleep(renewat - now);
276 if((renewat >= 0) && (now >= renewat)) {
280 renewat = now + interval;
287 * compile-command: "gcc -Wall -g -o krb5-agent krb5-agent.c -lkrb5"