openbsd-ports/security/cfs/patches/patch-cfs_fh_c
sturm a7d9ce80c3 several patches from Debian
- cmkdir now uses /dev/srandom (actually changed to arandom by me)
- support for filenames w/ 8bit chars
- sprintf() replaced with snprintf()
- some bugfixes

from Andreas Voegele <voegelas at gmx.net>
2005-04-07 20:23:44 +00:00

421 lines
11 KiB
Plaintext

--- cfs_fh.c.orig Thu May 3 20:24:59 2001
+++ cfs_fh.c Sat Mar 12 20:21:46 2005
@@ -177,6 +177,13 @@
perror("write");
return -1;
}
+ /* due to the way the file is padded we may actually have to
+ truncate it here. This happens when the write is at the end of
+ the file, is shorter than CFSBLOCK and brings the file to a length
+ which is evenly dividable by CFSBLOCK */
+ if (offset+len > dtov(sb.st_size) && vtod(offset+len) < sb.st_size) {
+ ftruncate(fd, vtod(offset+len));
+ }
/* iolen may contain CFSBLOCK extra chars */
return(dtov(iolen)-fronterr);
}
@@ -195,30 +202,39 @@
char *s;
{
static char cryptname[NFS_MAXNAMLEN+1];
+ static const u_char hexdigit[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
u_char cryptstring[MAXCLEARNAME+CFSBLOCK+1];
- u_char x[3];
u_long l;
- int i;
+ int i, j;
if ((s==NULL) || ((l=strlen(s)+1)>MAXCLEARNAME))
return NULL;
if (!strcmp(s,".") || !strcmp(s,".."))
return s;
l=(l+(CFSBLOCK-1)) & (~(CFSBLOCK-1));
+ if (l >= (sizeof(cryptname) >> 1))
+ return NULL;
bzero((char *)cryptstring,l);
strcpy(cryptstring,s);
chksum(cryptstring,l);
doencrypt(key,cryptstring,l,10241,zerovect);
- cryptname[0]='\0';
+ j = 0;
for (i=0; i<l; i++) {
- sprintf((char *)x,"%02x",cryptstring[i]);
- strcat(cryptname,x);
+ u_char b = cryptstring[i];
+ cryptname[j++] = hexdigit[(b >> 4) & 15];
+ cryptname[j++] = hexdigit[b & 15];
}
+ cryptname[j] = '\0';
return cryptname;
}
/*
- * set high order bits
+ * Carefully frob the high order bits of s in a way that is both easily
+ * reversible (see unchksum) and backwards-compatible (at least for 7-bit
+ * characters).
*/
chksum(s,l)
char *s;
@@ -229,17 +245,47 @@
u_char bits[8];
acc=0;
- for (i=0; s[i]!='\0'; i++)
- acc += s[i]*((i%6)+1);
+ /* Everything we do here must be reproducible without knowledge of
+ bit 7 because unchksum won't have that information. Therefore,
+ only accumulate the lower 7 bits of each char and stop at the
+ first occurrence of either 0x00 or 0x80. Note that, for inputs
+ with bit 7 constantly zero, this is equivalent to looking at the
+ whole string. */
+ for (i=0; (s[i]&0x7f) != '\0'; i++)
+ acc += (s[i]&0x7f)*((i%6)+1);
+ for (; s[i]!='\0'; i++) /* advance i if we stopped at a 0x80 */
+ ;
for (i++; i<l; i++) /* fill up the end */
s[i] = s[i%8];
for (i=0; i<8; i++)
bits[i] = (acc<<(i%8))&0x80;
for (i=0; i<l; i++)
- s[i] |= bits[i%8];
+ s[i] ^= bits[i%8];
}
+void
+unchksum(s,l)
+ char *s;
+ long l;
+{
+ u_long acc;
+ int i;
+ u_char bits[8];
+ acc=0;
+ for (i=0; (s[i]&0x7f) != '\0'; i++)
+ acc += (s[i]&0x7f)*((i%6)+1);
+ for (i=0; i<8; i++)
+ bits[i] = (acc<<(i%8))&0x80;
+ for (i=0; i<l; i++) {
+ s[i] ^= bits[i%8];
+ /* not sure whether this actually buys any performance */
+ if(s[i]=='\0')
+ break; /* found end of filename, can stop here */
+ }
+}
+
+
/*
* decrypt path component
* leaving "." and ".."
@@ -279,9 +325,7 @@
if (l%CFSBLOCK)
return NULL;
dodecrypt(key,clearstring,l,10241,zerovect);
- for (i=0; (clearstring[i]&0x7f) !='\0'; i++)
- clearstring[i] &= 0x7f;
- clearstring[i]='\0';
+ unchksum(clearstring,l);
return clearstring;
}
@@ -359,11 +403,11 @@
static fh_u roothandle;
-cfs_fileid rootnode={1,0,"\0\0\0\0\0\0\0\0","/NOWHERE/null",NULL,NULL,0,NULL,NULL};/* fileid=1; should be unique */
+cfs_fileid rootnode={1,0,{0,0,0,0,0,0,0,0},{'/','N','O','W','H','E','R','E','/','n','u','l','l'},NULL,NULL,0,NULL,NULL};/* fileid=1; should be unique */
nfstime roottime={0,0};
/* Had to change this - someone else was using the same magic number! */
-/* PLEASE change this value if you're going to re-use this code for
+/* PLEASE change this value if you're going to re-use this code for */
/* something else! Otherwise your FS and CFS can't both run... */
/* static u_char magictest[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; */
static u_char magictest[8]="M.Blaze";
@@ -514,10 +558,44 @@
cfsno(err)
int err;
{
-/* if (err==ENOENT)
+ switch (err) {
+ case 0:
+ return NFS_OK;
+ case EPERM:
+ return NFSERR_PERM;
+ case ENOENT:
+ return NFSERR_NOENT;
+ case EIO:
+ return NFSERR_IO;
+ case ENXIO:
+ return NFSERR_NXIO;
+ case EACCES:
+ return NFSERR_ACCES;
+ case EEXIST:
+ return NFSERR_EXIST;
+ case ENODEV:
+ return NFSERR_NODEV;
+ case ENOTDIR:
+ return NFSERR_NOTDIR;
+ case EISDIR:
+ return NFSERR_ISDIR;
+ case EFBIG:
+ return NFSERR_FBIG;
+ case ENOSPC:
+ return NFSERR_NOSPC;
+ case EROFS:
+ return NFSERR_ROFS;
+ case ENAMETOOLONG:
+ return NFSERR_NAMETOOLONG;
+ case ENOTEMPTY:
+ return NFSERR_NOTEMPTY;
+ case EDQUOT:
+ return NFSERR_DQUOT;
+ case ESTALE:
return NFSERR_STALE;
- else */
+ default:
return err;
+ }
}
@@ -732,12 +810,17 @@
{
char path[NFS_MAXPATHLEN+1];
struct stat sb;
+ int l;
if (p==NULL) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(path,"%s/%s",p->name,comp);
+ l = snprintf(path, sizeof(path), "%s/%s", p->name, comp);
+ if (l < 0 || l >= sizeof(path)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
if (mkdir(path,0)<0)
return -1;
if (stat(path,&sb)<0)
@@ -766,12 +849,22 @@
u_long i[2];
} buf;
char linkname[NFS_MAXPATHLEN+1];
+ int l;
if (p==NULL) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(path,"%s/%s",p->name,comp);
+ l = snprintf(path, sizeof(path), "%s/%s", p->name, comp);
+ if (l < 0 || l >= sizeof(path)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", p->name, comp);
+ if (l < 0 || l >= sizeof(linkname)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
if ((fd=open(path,O_CREAT|O_WRONLY|O_EXCL,0))<0) {
if (errno==EEXIST) {
@@ -785,7 +878,6 @@
if (fstat(fd,&sb)<0)
return -1;
close(fd);
- sprintf(linkname,"%s/.pvect_%s",p->name,comp);
if (!rs) {
if (p->ins->highsec) { /* create new pert file iff highsec */
/* note that there's a race condition here until the simlink */
@@ -800,8 +892,8 @@
/* hash. but this doesn't really matter since collisions */
/* are rare. we could save all 64 bits, but the encoding */
/* of the link would get messy and large */
- sprintf(vect,"%02x%02x%02x%02x",
- buf.ch[0],buf.ch[1],buf.ch[2],buf.ch[3]);
+ (void)snprintf(vect, sizeof(vect), "%02x%02x%02x%02x",
+ buf.ch[0], buf.ch[1], buf.ch[2], buf.ch[3]);
if (symlink(vect,linkname) != 0) {
strcpy(linkname,"/NOWHERE/null");
bcopy((char *)zerovect,(char *)vect,8);
@@ -839,6 +931,7 @@
char linkname[NFS_MAXPATHLEN+1];
char vect[NFS_MAXPATHLEN+1];
struct stat sb;
+ int l;
if (p==NULL) {
cfserrno=NFSERR_STALE;
@@ -852,12 +945,20 @@
}
if ((p->parent==0) && (!strcmp(comp,"..")))
return fhrootlook(p->ins->name,h);
- sprintf(path,"%s/%s",p->name,comp);
+ l = snprintf(path, sizeof(path), "%s/%s", p->name, comp);
+ if (l < 0 || l >= sizeof(path)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
if (lstat(path,&sb)<0) {
return -1; /* just need the inode */
}
/* check for a linkfile */
- sprintf(linkname,"%s/.pvect_%s",p->name,comp);
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", p->name, comp);
+ if (l < 0 || l >= sizeof(linkname)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
if (readlink(linkname,vect,9) != 8) {
bcopy((char *)zerovect,(char *)vect,8);
strcpy(linkname,"/NOWHERE/null");
@@ -980,13 +1081,22 @@
char path[NFS_MAXPATHLEN+1];
char linkname[NFS_MAXPATHLEN+1];
int ret;
+ int l;
if (f==NULL) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(linkname,"%s/.pvect_%s",f->name,s);
- sprintf(path,"%s/%s",f->name,s);
+ l = snprintf(path, sizeof(path), "%s/%s", f->name, s);
+ if (l < 0 || l >= sizeof(path)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", f->name, s);
+ if (l < 0 || l >= sizeof(linkname)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
/* note that we don't bother to check and see if there's a
handle allocated for this - just wait for the inode to be
reclaimed */
@@ -1001,13 +1111,21 @@
char *s;
{
char path[NFS_MAXPATHLEN+1];
+ int l;
+ int err;
if (f==NULL) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(path,"%s/%s",f->name,s);
- return (rmdir(path));
+ l = snprintf(path, sizeof(path), "%s/%s", f->name, s);
+ if (l < 0 || l >= sizeof(path)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ if ((err = rmdir(path)) < 0)
+ cfserrno = cfsno(errno);
+ return err;
}
DIR *
@@ -1055,15 +1173,24 @@
char linkname[NFS_MAXPATHLEN+1];
char vectval[9];
int ret;
+ int l;
if ((f==NULL)||(t==NULL)) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(buf,"%s/%s",t->name,n);
+ l = snprintf(buf, sizeof(buf), "%s/%s", t->name, n);
+ if (l < 0 || l >= sizeof(buf)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ l = snprintf(linkname, sizeof(linkname), "%s/.pvect_%s", t->name, n);
+ if (l < 0 || l >= sizeof(buf)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
if ((ret=link(f->name,buf))!=0)
return ret;
- sprintf(linkname,"%s/.pvect_%s",t->name,n);
unlink(linkname);
if (readlink(f->vectname,vectval,9) == 8) {
vectval[8]='\0';
@@ -1079,12 +1206,17 @@
char *t;
{
char buf[NFS_MAXPATHLEN+1];
+ int l;
if (f==NULL) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(buf,"%s/%s",f->name,n);
+ l = snprintf(buf, sizeof(buf), "%s/%s", f->name, n);
+ if (l < 0 || l >= sizeof(buf)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
return (symlink(t,buf));
}
@@ -1100,15 +1232,32 @@
char fblink[NFS_MAXPATHLEN+1];
char tblink[NFS_MAXPATHLEN+1];
char vectval[9];
+ int l;
if ((f==NULL)||(t==NULL)) {
cfserrno=NFSERR_STALE;
return -2;
}
- sprintf(fb,"%s/%s",f->name,fn);
- sprintf(tb,"%s/%s",t->name,tn);
- sprintf(fblink,"%s/.pvect_%s",f->name,fn);
- sprintf(tblink,"%s/.pvect_%s",t->name,tn);
+ l = snprintf(fb, sizeof(fb), "%s/%s", f->name, fn);
+ if (l < 0 || l >= sizeof(fb)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ l = snprintf(tb, sizeof(tb), "%s/%s", t->name, tn);
+ if (l < 0 || l >= sizeof(tb)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ l = snprintf(fblink, sizeof(fblink), "%s/.pvect_%s", f->name, fn);
+ if (l < 0 || l >= sizeof(fblink)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
+ l = snprintf(tblink, sizeof(tblink), "%s/.pvect_%s", t->name, tn);
+ if (l < 0 || l >= sizeof(tblink)) {
+ cfserrno = NFSERR_NAMETOOLONG;
+ return -2;
+ }
if (rename(fb,tb)==0) { /* now we have to do a lookup */
unlink(tblink); /* may be a quick race cndtn here */
if (readlink(fblink,vectval,9)==8) {
@@ -1160,7 +1309,8 @@
} else while (cookie<(NINSTANCES+2)) {
if (instances[cookie-2] != NULL) {
if (instances[cookie-2]->anon)
- sprintf(d.d_name,".ANON_%d",cookie-2);
+ (void)snprintf(d.d_name, sizeof(d.d_name),
+ ".ANON_%ld", cookie-2);
else
strcpy(d.d_name,
instances[cookie-2]->name);