Applied Bill Sommerfeld's patches
authorTheodore Tso <tytso@mit.edu>
Tue, 9 Jun 1992 15:26:25 +0000 (15:26 +0000)
committerTheodore Tso <tytso@mit.edu>
Tue, 9 Jun 1992 15:26:25 +0000 (15:26 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2286 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/rcache/rc_dfl.c
src/lib/krb5/rcache/rc_io.c

index 6ddcfabd1f30b68ce39e2736aba2d4449392bc28..23b2dd677e1291ed05681f105d759e8e8f900d35 100644 (file)
@@ -193,7 +193,8 @@ krb5_deltat lifespan;
 #ifndef NOIOSTUFF
  if (retval = krb5_rc_io_creat(&t->d,&t->name))
    return retval;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) &t->lifespan,sizeof(t->lifespan)))
+ if (krb5_rc_io_write(&t->d,(krb5_pointer) &t->lifespan,sizeof(t->lifespan))
+     || krb5_rc_io_sync(&t->d))
    return KRB5_RC_IO;
 #endif
  return 0;
@@ -256,6 +257,73 @@ char *name;
  return 0;
 }
 
+void krb5_rc_free_entry (rep)
+    krb5_donot_replay **rep;
+{
+    krb5_donot_replay *rp = *rep;
+    
+    *rep = NULL;
+    if (rp) 
+    {
+       if (rp->client)
+           free(rp->client);
+
+       if (rp->server)
+           free(rp->server);
+       rp->client = NULL;
+       rp->server = NULL;
+       free(rp);
+    }
+}
+
+krb5_error_code krb5_rc_io_fetch(t, rep, maxlen) 
+    struct dfl_data *t;
+    krb5_donot_replay *rep;
+    int maxlen;
+{
+    int len;
+    krb5_error_code retval;
+    
+    retval = krb5_rc_io_read (&t->d, (krb5_pointer) &len, sizeof(len));
+    if (retval) 
+       return retval;
+    
+    if ((len <= 0) || (len >= maxlen))
+       return KRB5_RC_IO_EOF;
+
+    rep->client = malloc (len);
+    if (!rep->client)
+       return KRB5_RC_MALLOC;
+    
+    retval = krb5_rc_io_read (&t->d, (krb5_pointer) rep->client, len);
+    if (retval) 
+       return retval;
+    
+    retval = krb5_rc_io_read (&t->d, (krb5_pointer) &len, sizeof(len));
+    if (retval) 
+       return retval;
+    
+    if ((len <= 0) || (len >= maxlen))
+       return KRB5_RC_IO_EOF;
+
+    rep->server = malloc (len);
+    if (!rep->server)
+       return KRB5_RC_MALLOC;
+    
+    retval = krb5_rc_io_read (&t->d, (krb5_pointer) rep->server, len);
+    if (retval) 
+       return retval;
+    
+    retval = krb5_rc_io_read (&t->d, (krb5_pointer) &rep->cusec, sizeof(rep->cusec));
+    if (retval)
+       return retval;
+    
+    retval = krb5_rc_io_read (&t->d, (krb5_pointer) &rep->ctime, sizeof(rep->ctime));
+    return retval;
+}
+    
+
+
 krb5_error_code krb5_rc_dfl_recover(id)
 krb5_rcache id;
 {
@@ -267,86 +335,105 @@ krb5_rcache id;
  int i;
  krb5_donot_replay *rep;
  krb5_error_code retval;
+    int max_size;
 
  if (retval = krb5_rc_io_open(&t->d,t->name))
    return retval;
+    max_size = krb5_rc_io_size(t);
+    rep = NULL;
  if (krb5_rc_io_read(&t->d,(krb5_pointer) &t->lifespan,sizeof(t->lifespan))) {
-     krb5_rc_io_close(&t->d);
-     return KRB5_RC_IO;
+       retval = KRB5_RC_IO;
+       goto io_fail;
  }
 
  /* now read in each auth_replay and insert into table */
  for (;;)
   {
-#define FREE1 FREE(rep);
-#define FREE2 {FREE(rep->client); FREE(rep);}
-#define FREE3 {FREE(rep->server); FREE(rep->client); FREE(rep);}
-#define CLOSE krb5_rc_io_close(&t->d);
-
+       rep = NULL;
    if (krb5_rc_io_mark(&t->d)) {
-     krb5_rc_io_close(&t->d);
-     return KRB5_RC_IO;
+           retval = KRB5_RC_IO;
+           goto io_fail;
    }
+       
    if (!(rep = (krb5_donot_replay *) malloc(sizeof(krb5_donot_replay)))) {
-     CLOSE;
-     return KRB5_RC_MALLOC;
-   }
-   switch(krb5_rc_io_read(&t->d,(krb5_pointer) &i,sizeof(i)))
-    {
-     case KRB5_RC_IO_EOF: FREE1; goto end_loop;
-     case 0: break; default: FREE1; CLOSE; return KRB5_RC_IO; break;
-    }
-   if (!(rep->client = malloc(i)))
-    { FREE1; CLOSE; return KRB5_RC_MALLOC; }
-   switch(krb5_rc_io_read(&t->d,(krb5_pointer) rep->client,i))
-    {
-     case KRB5_RC_IO_EOF: FREE2; goto end_loop;
-     case 0: break; default: FREE2; CLOSE; return KRB5_RC_IO; break;
-    }
-   switch(krb5_rc_io_read(&t->d,(krb5_pointer) &i,sizeof(i)))
-    {
-     case KRB5_RC_IO_EOF: FREE2; goto end_loop;
-     case 0: break; default: FREE2; CLOSE; return KRB5_RC_IO; break;
-    }
-   if (!(rep->server = malloc(i)))
-    { FREE2; CLOSE; return KRB5_RC_MALLOC; }
-   switch(krb5_rc_io_read(&t->d,(krb5_pointer) rep->server,i))
-    {
-     case KRB5_RC_IO_EOF: FREE3; goto end_loop;
-     case 0: break; default: FREE3; CLOSE; return KRB5_RC_IO; break;
-    }
-   switch(krb5_rc_io_read(&t->d,(krb5_pointer) &rep->cusec,sizeof(rep->cusec))) 
-    {
-     case KRB5_RC_IO_EOF: FREE3; goto end_loop;
-     case 0: break; default: FREE3; CLOSE; return KRB5_RC_IO; break;
+           retval = KRB5_RC_MALLOC;
+           goto io_fail;
     }
-   switch(krb5_rc_io_read(&t->d,(krb5_pointer) &rep->ctime,sizeof(rep->ctime)))
+       rep->client = NULL;
+       rep->server = NULL;
+       
+       retval = krb5_rc_io_fetch (t, rep, max_size);
+
+       if (retval == KRB5_RC_IO_EOF)
+           break;
+       else if (retval != 0)
+           goto io_fail;
+
+       
+       if (alive(rep,t->lifespan) == CMP_EXPIRED) 
     {
-     case KRB5_RC_IO_EOF: FREE3; goto end_loop;
-     case 0: break; default: FREE3; CLOSE; return KRB5_RC_IO; break;
+           krb5_rc_free_entry(&rep);
+           continue;
     }
-   if (alive(rep,t->lifespan) != CMP_EXPIRED) {
+
      if (store(id,rep) == CMP_MALLOC) {/* can't be a replay */
-       CLOSE; 
-       return KRB5_RC_MALLOC; 
+           retval = KRB5_RC_MALLOC; goto io_fail;
      } 
      /* store() copies the server & client fields to make sure they don't get
-       stomped on by other callers, so we need to free them */
+        * stomped on by other callers, so we need to free them */
      FREE(rep->server);
      FREE(rep->client);
-   } else FREE3;                       /* don't need it anymore, punt! */
+       rep = NULL;
  }
- end_loop: krb5_rc_io_unmark(&t->d);
+ end_loop:
+    retval = 0;
+    krb5_rc_io_unmark(&t->d);
 /* An automatic expunge here could remove the need for mark/unmark but
-would be inefficient. */
- return 0;
+     * would be inefficient. */
+ io_fail:
+    krb5_rc_free_entry(&rep);
+    if (retval)
+       krb5_rc_io_close(&t->d);
+    return retval;
 #endif
 }
 
+krb5_error_code krb5_rc_io_store (t, rep)
+    struct dfl_data *t;
+    krb5_donot_replay *rep;
+{
+    int clientlen, serverlen, len;
+    char *buf, *ptr;
+    unsigned long ret;
+
+    clientlen = strlen (rep->client) + 1;
+    serverlen = strlen (rep->server) + 1;
+    len = sizeof(clientlen) + clientlen + sizeof(serverlen) + serverlen +
+       sizeof(rep->cusec) + sizeof(rep->ctime);
+    buf = malloc (len);
+    if (buf == 0)
+       return KRB5_RC_MALLOC;
+    ptr = buf;
+    memcpy(ptr, &clientlen, sizeof(clientlen)); ptr += sizeof(clientlen);
+    memcpy(ptr, rep->client, clientlen); ptr += clientlen;
+    memcpy(ptr, &serverlen, sizeof(serverlen)); ptr += sizeof(serverlen);
+    memcpy(ptr, rep->server, serverlen); ptr += serverlen;
+    memcpy(ptr, &rep->cusec, sizeof(rep->cusec)); ptr += sizeof(rep->cusec);
+    memcpy(ptr, &rep->ctime, sizeof(rep->ctime)); ptr += sizeof(rep->ctime);
+
+    ret = krb5_rc_io_write(&t->d, buf, len);
+    free(buf);
+    return ret;
+}
+
 krb5_error_code krb5_rc_dfl_store(id, rep)
 krb5_rcache id;
 krb5_donot_replay *rep;
 {
+    unsigned long ret;
  struct dfl_data *t = (struct dfl_data *)id->data;
  int i;
 
@@ -360,24 +447,22 @@ krb5_donot_replay *rep;
    default: /* wtf? */ ;
   }
 #ifndef NOIOSTUFF
- i = strlen(rep->client) + 1;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) &i,sizeof(i)))
-   return KRB5_RC_IO;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) rep->client,i))
-   return KRB5_RC_IO;
- i = strlen(rep->server) + 1;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) &i,sizeof(i)))
-   return KRB5_RC_IO;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) rep->server,i))
-   return KRB5_RC_IO;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) &rep->cusec,sizeof(rep->cusec)))
-   return KRB5_RC_IO;
- if (krb5_rc_io_write(&t->d,(krb5_pointer) &rep->ctime,sizeof(rep->ctime)))
-   return KRB5_RC_IO;
+    ret = krb5_rc_io_store (t, rep);
+    if (ret)
+       return ret;
 #endif
  /* Shall we automatically expunge? */
  if (t->nummisses > t->numhits + EXCESSREPS)
+    {
    return krb5_rc_dfl_expunge(id);
+    }
+#ifndef NOIOSTUFF
+    else
+    {
+       if (krb5_rc_io_sync(&t->d))
+           return KRB5_RC_IO;
+    }
+#endif
  return 0;
 }
 
@@ -437,21 +522,11 @@ krb5_rcache id;
    return KRB5_RC_IO;
  for (q = t->a;q;q = q->na)
   {
-   i = strlen(q->rep.client) + 1;
-   if (krb5_rc_io_write(&tmp,(krb5_pointer) &i,sizeof(i)))
-     return KRB5_RC_IO;
-   if (krb5_rc_io_write(&tmp,(krb5_pointer) q->rep.client,i))
-     return KRB5_RC_IO;
-   i = strlen(q->rep.server) + 1;
-   if (krb5_rc_io_write(&tmp,(krb5_pointer) &i,sizeof(i)))
-     return KRB5_RC_IO;
-   if (krb5_rc_io_write(&tmp,(krb5_pointer) q->rep.server,i))
-     return KRB5_RC_IO;
-   if (krb5_rc_io_write(&tmp,(krb5_pointer) &q->rep.cusec,sizeof(q->rep.cusec)))
-     return KRB5_RC_IO;
-   if (krb5_rc_io_write(&tmp,(krb5_pointer) &q->rep.ctime,sizeof(q->rep.ctime)))
+       if (krb5_rc_io_store (&tmp, &q->rep))
      return KRB5_RC_IO;
   }
+    if (krb5_rc_io_sync(&t->d))
+       return KRB5_RC_IO;
  if (krb5_rc_io_move(&t->d,&tmp))
    return KRB5_RC_IO;
 #endif
index 680fa4e10b1527eae3407a8f681889bddda48616..a32b914fdc7a782811ec5f2ed172894702e328f1 100644 (file)
@@ -26,6 +26,7 @@ static char rcsid_rc_io_c[] =
 #include "rc_io.h"
 #include <krb5/sysincl.h>
 #include <krb5/osconf.h>
+#include <sys/stat.h>
 
 #ifdef KRB5_USE_INET
 #include <netinet/in.h>
@@ -83,7 +84,7 @@ char **fn;
  else
   {
       /* %d is max 11 digits (-, 10 digits of 32-bit number)
-        11 + /krb5_RC + aaa = 24, +6 for slop */
+        11 + /krb5_RC + aaa = 24, +6 for slop */
    if (!(d->fn = malloc(30 + dirlen)))
      return KRB5_RC_IO_MALLOC;
    if (fn)
@@ -109,24 +110,36 @@ char **fn;
      (void) strcpy(*fn,d->fn + dirlen);
   }
  if (d->fd == -1)
+    {
    switch(errno)
     {
-     case EBADF: FREE(d->fn); return KRB5_RC_IO_UNKNOWN; break;
-     case EFBIG: FREE(d->fn); return KRB5_RC_IO_SPACE; break;
+       case EFBIG: 
 #ifdef EDQUOT
-     case EDQUOT: FREE(d->fn); return KRB5_RC_IO_SPACE; break;
+       case EDQUOT:
 #endif
-     case ENOSPC: FREE(d->fn); return KRB5_RC_IO_SPACE; break;
-     case EIO: FREE(d->fn); return KRB5_RC_IO_IO; break;
-     case EPERM: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     case EACCES: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     case EROFS: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     case EEXIST: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     default: FREE(d->fn); return KRB5_RC_IO_UNKNOWN; break;
+       case ENOSPC: 
+           retval = KRB5_RC_IO_SPACE; 
+           goto fail;
+       case EIO: 
+           retval = KRB5_RC_IO_IO; goto fail;
+
+       case EPERM: 
+       case EACCES: 
+       case EROFS: 
+       case EEXIST: 
+           retval = KRB5_RC_IO_PERM; goto fail;
+
+       default: 
+           retval = KRB5_RC_IO_UNKNOWN; goto fail;
+    }
     }
- if (retval = krb5_rc_io_write(d, (krb5_pointer)&rc_vno, sizeof(rc_vno))) {
+    if ((retval = krb5_rc_io_write(d, (krb5_pointer)&rc_vno, sizeof(rc_vno))) ||
+       (retval = krb5_rc_io_sync(d)))
+    {
+    fail:
      (void) unlink(d->fn);
      FREE(d->fn);
+       d->fn = NULL;
      (void) close(d->fd);
      return retval;
  }
@@ -152,7 +165,7 @@ char *fn;
 
      me = getuid();
      /* must be owned by this user, to prevent some security problems with
-       other users modifying replay cache stufff */
+        * other users modifying replay cache stufff */
      if ((statb.st_uid != me) || ((statb.st_mode & S_IFMT) != S_IFREG)) {
         FREE(d->fn);
         return KRB5_RC_IO_PERM;
@@ -162,30 +175,44 @@ char *fn;
  if (d->fd == -1) {
    switch(errno)
     {
-     case EBADF: FREE(d->fn); return KRB5_RC_IO_UNKNOWN; break;
-     case EFBIG: FREE(d->fn); return KRB5_RC_IO_SPACE; break;
+       case EFBIG: 
 #ifdef EDQUOT
-     case EDQUOT: FREE(d->fn); return KRB5_RC_IO_SPACE; break;
+       case EDQUOT:
 #endif
-     case ENOSPC: FREE(d->fn); return KRB5_RC_IO_SPACE; break;
-     case EIO: FREE(d->fn); return KRB5_RC_IO_IO; break;
-     case EPERM: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     case EACCES: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     case EROFS: FREE(d->fn); return KRB5_RC_IO_PERM; break;
-     default: FREE(d->fn); return KRB5_RC_IO_UNKNOWN; break;
+       case ENOSPC:
+           retval = KRB5_RC_IO_SPACE; 
+           goto fail;
+
+       case EIO: 
+           retval = KRB5_RC_IO_IO; 
+           goto fail;
+
+       case EPERM: 
+       case EACCES:
+       case EROFS: 
+           retval = KRB5_RC_IO_PERM; 
+           goto fail;
+
+           default: 
+           retval = KRB5_RC_IO_UNKNOWN; 
+           goto fail;
     }
  }
- if (retval = krb5_rc_io_read(d, (krb5_pointer) &rc_vno,  sizeof(rc_vno))) {
+    if (retval = krb5_rc_io_read(d, (krb5_pointer) &rc_vno,  sizeof(rc_vno)))  
+       goto unlk;
+
+
+    if (ntohs(rc_vno) != KRB5_RC_VNO) 
+    {
+       retval = KRB5_RCACHE_BADVNO;
+    unlk:
+       unlink(d->fn);
+    fail:
      (void) close(d->fd);
      FREE(d->fn); 
+       d->fn = NULL;
      return retval;
  }
- if (ntohs(rc_vno) != KRB5_RC_VNO) {
-     (void) close(d->fd);
-     FREE(d->fn); 
-     return KRB5_RCACHE_BADVNO;
- }
-
  return 0;
 }
 
@@ -218,16 +245,23 @@ int num;
      case EIO: return KRB5_RC_IO_IO; break;
      default: return KRB5_RC_IO_UNKNOWN; break;
     }
- if (fsync(d->fd) == -1)
-   switch(errno)
-    {
-     case EBADF: return KRB5_RC_IO_UNKNOWN; break;
-     case EIO: return KRB5_RC_IO_IO; break;
-     default: return KRB5_RC_IO_UNKNOWN; break;
-    }
  return 0;
 }
 
+krb5_error_code krb5_rc_io_sync (d)
+    krb5_rc_iostuff *d;
+{
+    if (fsync(d->fd) == -1) {
+      switch(errno)
+      {
+      case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+      case EIO: return KRB5_RC_IO_IO; break;
+      default: return KRB5_RC_IO_UNKNOWN; break;
+      }
+    }
+    return 0;
+}
+
 krb5_error_code krb5_rc_io_read (d, buf, num)
 krb5_rc_iostuff *d;
 krb5_pointer buf;
@@ -250,6 +284,7 @@ krb5_error_code krb5_rc_io_close (d)
 krb5_rc_iostuff *d;
 {
  FREE(d->fn);
+ d->fn = NULL;
  if (close(d->fd) == -1) /* can't happen */
    return KRB5_RC_IO_UNKNOWN;
  return 0;
@@ -284,3 +319,15 @@ krb5_rc_iostuff *d;
  (void) lseek(d->fd,d->mark,L_SET); /* if it fails, tough luck */
  return 0;
 }
+
+int krb5_rc_io_size (d)
+    krb5_rc_iostuff *d;
+{
+    struct stat statb;
+    
+    if (fstat (d->fd, &statb) == 0)
+       return statb.st_size;
+    else
+       return 0;
+}
+