First should-be-working version.
authorfredrik@DOLDA2000.COM <fredrik@DOLDA2000.COM@959494ce-11ee-0310-bf91-de5d638817bd>
Fri, 4 Mar 2005 03:24:43 +0000 (03:24 +0000)
committerfredrik@DOLDA2000.COM <fredrik@DOLDA2000.COM@959494ce-11ee-0310-bf91-de5d638817bd>
Fri, 4 Mar 2005 03:24:43 +0000 (03:24 +0000)
git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/utils@169 959494ce-11ee-0310-bf91-de5d638817bd

krb5-agent.c

index 7edd369..2f23567 100644 (file)
@@ -7,12 +7,12 @@
 #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;
 
@@ -20,8 +20,10 @@ void cleanup_krb5(void)
 {
     if(ccache != NULL)
        krb5_cc_close(context, ccache);
+    ccache = NULL;
     if(context != NULL)
        krb5_free_context(context);
+    context = NULL;
 }
 
 void sighandler(int sig)
@@ -30,26 +32,124 @@ 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':
@@ -63,7 +163,7 @@ int main(int argc, char **argv)
            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')
@@ -118,8 +218,13 @@ int main(int argc, char **argv)
            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);
@@ -130,6 +235,7 @@ int main(int argc, char **argv)
                if(WIFEXITED(status)) {
                    exit(WEXITSTATUS(status));
                } else {
+                   cleanup_krb5();
                    signal(WTERMSIG(status), SIG_DFL);
                    kill(getpid(), WTERMSIG(status));
                    exit(255);
@@ -137,10 +243,24 @@ int main(int argc, char **argv)
            }
            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;
+       }
     }
 }