This commit is contained in:
rsc 2006-04-09 00:24:28 +00:00
parent 0e6fee11c8
commit 20bd3ca2e2
3 changed files with 175 additions and 11 deletions

View file

@ -1,8 +1,8 @@
<$PLAN9/src/mkhdr
TARG=vf
TARG=vf unvf
OFILES=vf.$O\
OFILES=
LIB=../common/libcommon.a\
@ -16,5 +16,5 @@ UPDATE=\
$HFILES\
${OFILES:%.$O=%.c}\
<$PLAN9/src/mkone
<$PLAN9/src/mkmany
CFLAGS=$CFLAGS -I../common

156
src/cmd/upas/vf/unvf.c Normal file
View file

@ -0,0 +1,156 @@
/*
* For decoding the files that get passed to validateattachment.
* NOT a general mime decoder.
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
enum { None, Base64, Quoted };
static int decquoted(char *out, char *in, char *e);
void
main(void)
{
Biobuf b, b1;
char *p, *encoding;
int e, len;
Binit(&b, 0, OREAD);
Binit(&b1, 1, OWRITE);
/* header */
encoding = nil;
while((p = Brdstr(&b, '\n', 1)) != nil){
if(p[0] == 0)
break;
if(strncmp(p, "Content-Transfer-Encoding: ", 27) == 0)
encoding = strdup(p+27);
free(p);
}
e = None;
if(encoding == nil)
e = None;
else if(strcmp(encoding, "base64") == 0)
e = Base64;
else if(strcmp(encoding, "quoted-printable") == 0)
e = Quoted;
while((p = Brdstr(&b, '\n', 0)) != nil){
if(strncmp(p, "--", 2) == 0 && e != None)
break;
len = strlen(p);
switch(e){
case None:
break;
case Base64:
len = dec64((uchar*)p, len, p, len);
break;
case Quoted:
len = decquoted(p, p, p+len);
break;
}
Bwrite(&b1, p, len);
free(p);
}
exits(0);
}
/*
* decode quoted
*/
enum
{
Self= 1,
Hex= 2
};
uchar tableqp[256];
static void
initquoted(void)
{
int c;
memset(tableqp, 0, 256);
for(c = ' '; c <= '<'; c++)
tableqp[c] = Self;
for(c = '>'; c <= '~'; c++)
tableqp[c] = Self;
tableqp['\t'] = Self;
tableqp['='] = Hex;
}
static int
hex2int(int x)
{
if(x >= '0' && x <= '9')
return x - '0';
if(x >= 'A' && x <= 'F')
return (x - 'A') + 10;
if(x >= 'a' && x <= 'f')
return (x - 'a') + 10;
return 0;
}
static char*
decquotedline(char *out, char *in, char *e)
{
int c, soft;
/* dump trailing white space */
while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n'))
e--;
/* trailing '=' means no newline */
if(*e == '='){
soft = 1;
e--;
} else
soft = 0;
while(in <= e){
c = (*in++) & 0xff;
switch(tableqp[c]){
case Self:
*out++ = c;
break;
case Hex:
c = hex2int(*in++)<<4;
c |= hex2int(*in++);
*out++ = c;
break;
}
}
if(!soft)
*out++ = '\n';
*out = 0;
return out;
}
static int
decquoted(char *out, char *in, char *e)
{
char *p, *nl;
if(tableqp[' '] == 0)
initquoted();
p = out;
while((nl = strchr(in, '\n')) != nil && nl < e){
p = decquotedline(p, in, nl);
in = nl + 1;
}
if(in < e)
p = decquotedline(p, in, e-1);
/* make sure we end with a new line */
if(*(p-1) != '\n'){
*p++ = '\n';
*p = 0;
}
return p - out;
}

View file

@ -5,6 +5,11 @@
#include "common.h"
#include <ctype.h>
enum {
Accept = 0xA,
Discard = 0xD,
};
Biobuf in;
Biobuf out;
@ -400,12 +405,12 @@ savetmp(Part *p)
char buf[40], *name;
int fd;
strcpy(buf, "/tmp/vf.XXXXXXXXXXX");
name = mktemp(buf);
if((fd = create(name, OWRITE|OEXCL, 0666)) < 0){
strcpy(buf, "/var/tmp/vf.XXXXXXXXXXX");
if((fd = mkstemp(buf)) < 0){
fprint(2, "error creating temporary file: %r\n");
refuse();
}
name = buf;
close(fd);
if(save(p, name) < 0){
fprint(2, "error saving temporary file: %r\n");
@ -433,10 +438,13 @@ runchecker(Part *p)
int pid;
char *name;
Waitmsg *w;
static char *val;
if(access("/mail/lib/validateattachment", AEXEC) < 0)
if(val == nil)
val = unsharp("#9/mail/lib/validateattachment");
if(val == nil || access(val, AEXEC) < 0)
return 0;
name = savetmp(p);
fprint(2, "run checker %s\n", name);
switch(pid = fork()){
@ -444,7 +452,7 @@ runchecker(Part *p)
sysfatal("fork: %r");
case 0:
dup(2, 1);
execl("/mail/lib/validateattachment", "validateattachment", name, nil);
execl(val, "validateattachment", name, nil);
_exits("exec failed");
}
@ -462,11 +470,11 @@ runchecker(Part *p)
}
if(p->filename)
name = s_to_c(p->filename);
if(strstr(w->msg, "discard")){
if(atoi(w->msg) == Discard){
syslog(0, "mail", "vf validateattachment rejected %s", name);
refuse();
}
if(strstr(w->msg, "accept")){
if(atoi(w->msg) == Accept){
syslog(0, "mail", "vf validateattachment accepted %s", name);
return 1;
}