| t@@ -0,0 +1,156 @@
+/*
+ * For decoding the files that get passed to validateattachment.
+ * NOT a general mime decoder.
+ */
+#include
+#include
+#include
+
+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;
+}
+ |
| t@@ -5,6 +5,11 @@
#include "common.h"
#include
+enum {
+ Accept = 0xA,
+ Discard = 0xD,
+};
+
Biobuf in;
Biobuf out;
t@@ -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");
t@@ -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()){
t@@ -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");
}
t@@ -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;
} |