From 914402a6501febba84dd6aa076943d2f0eafc0ff Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Tue, 9 Jun 1992 15:26:25 +0000 Subject: [PATCH] Applied Bill Sommerfeld's patches git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2286 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/rcache/rc_dfl.c | 233 +++++++++++++++++++++++------------ src/lib/krb5/rcache/rc_io.c | 119 ++++++++++++------ 2 files changed, 237 insertions(+), 115 deletions(-) diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c index 6ddcfabd1..23b2dd677 100644 --- a/src/lib/krb5/rcache/rc_dfl.c +++ b/src/lib/krb5/rcache/rc_dfl.c @@ -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 diff --git a/src/lib/krb5/rcache/rc_io.c b/src/lib/krb5/rcache/rc_io.c index 680fa4e10..a32b914fd 100644 --- a/src/lib/krb5/rcache/rc_io.c +++ b/src/lib/krb5/rcache/rc_io.c @@ -26,6 +26,7 @@ static char rcsid_rc_io_c[] = #include "rc_io.h" #include #include +#include #ifdef KRB5_USE_INET #include @@ -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; +} + -- 2.26.2