X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/53a941d3f97a50964587c6e9533b1e43e74a57a8..9f90c1f6d21867ca0e1a2b42a9514299221cbe1d:/proxy/tripe-mitm.c
diff --git a/proxy/tripe-mitm.c b/proxy/tripe-mitm.c
index 7394aaaa..ab05a882 100644
--- a/proxy/tripe-mitm.c
+++ b/proxy/tripe-mitm.c
@@ -9,19 +9,18 @@
*
* This file is part of Trivial IP Encryption (TrIPE).
*
- * TrIPE is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * TrIPE is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your
+ * option) any later version.
*
- * TrIPE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * TrIPE is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
* You should have received a copy of the GNU General Public License
- * along with TrIPE; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with TrIPE. If not, see .
*/
/*----- Header files ------------------------------------------------------*/
@@ -63,15 +62,16 @@
#include
#include
+#include
#include
#include
-#include
+
+#include "util.h"
/*----- Data structures ---------------------------------------------------*/
typedef struct peer {
sel_file sf;
- dh_pub kpub;
const char *name;
struct filter *f;
} peer;
@@ -116,26 +116,17 @@ static void dopacket(int fd, unsigned mode, void *vv)
static void addpeer(unsigned ac, char **av)
{
- key_packstruct kps[DH_PUBFETCHSZ];
- key_packdef *kp;
struct hostent *h;
struct sockaddr_in sin;
int len = PKBUFSZ;
peer *p;
int fd;
- int e;
- if (ac != 4)
- die(1, "syntax: peer:NAME:PORT:ADDR:PORT");
- if (npeer >= 2)
- die(1, "enough peers already");
+ if (ac != 4) die(1, "syntax: peer:NAME:PORT:ADDR:PORT");
+ if (npeer >= 2) die(1, "enough peers already");
+ if (!key_bytag(&keys, av[0])) die(1, "no key named `%s'", av[0]);
p = &peers[npeer++];
p->name = xstrdup(av[0]);
- kp = key_fetchinit(dh_pubfetch, kps, &p->kpub);
- e = key_fetchbyname(kp, &keys, av[0]);
- key_fetchdone(kp);
- if (e)
- die(1, "key_fetch `%s': %s", av[0], key_strerror(e));
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
die(1, "socket: %s", strerror(errno));
fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
@@ -190,8 +181,7 @@ static void dofork(filter *f, const octet *buf, size_t sz)
static void addfork(filter *f, unsigned ac, char **av)
{
forkfilt *ff;
- if (ac != 1)
- die(1, "syntax: filt:fork:NAME");
+ if (ac != 1) die(1, "syntax: filt:fork:NAME");
ff = CREATE(forkfilt);
ff->name = xstrdup(av[0]);
ff->fn = 0;
@@ -207,23 +197,18 @@ static void nextfork(unsigned ac, char **av)
forknode *fn, **ffn;
peer *p;
- if (ac < 1)
- die(1, "syntax: next:NAME:...");
+ if (ac < 1) die(1, "syntax: next:NAME:...");
for (i = 0; i < 2; i++) {
p = &peers[i];
for (f = p->f; f; f = f->next) {
- if (f->func != dofork)
- continue;
+ if (f->func != dofork) continue;
ff = f->state;
- for (j = 0; j < ac; j++) {
- if (strcmp(av[j], ff->name) == 0)
- goto match;
- }
+ for (j = 0; j < ac; j++)
+ if (strcmp(av[j], ff->name) == 0) goto match;
continue;
match:
fn = CREATE(forknode);
- for (ffn = &ff->fn; *ffn; ffn = &(*ffn)->next)
- ;
+ for (ffn = &ff->fn; *ffn; ffn = &(*ffn)->next);
fn->f = f->next;
f->next = 0;
fn->next = 0;
@@ -254,17 +239,39 @@ static void docorrupt(filter *f, const octet *buf, size_t sz)
static void addcorrupt(filter *f, unsigned ac, char **av)
{
corrupt *c;
- if (ac > 1)
- die(1, "syntax: filt:corrupt[:PCORRUPT]");
+ if (ac > 1) die(1, "syntax: filt:corrupt[:P-CORRUPT]");
c = CREATE(corrupt);
- if (ac > 0)
- c->p_corrupt = atoi(av[0]);
- else
- c->p_corrupt = 5;
+ if (ac > 0) c->p_corrupt = atoi(av[0]);
+ else c->p_corrupt = 5;
f->state = c;
f->func = docorrupt;
}
+/*----- Drop filter -------------------------------------------------------*/
+
+typedef struct drop {
+ unsigned p_drop;
+} drop;
+
+static void dodrop(filter *f, const octet *buf, size_t sz)
+{
+ drop *d = f->state;
+
+ if (!RND(d->p_drop)) puts("drop packet");
+ else PASS(f->next, buf, sz);
+}
+
+static void adddrop(filter *f, unsigned ac, char **av)
+{
+ drop *d;
+ if (ac > 1) die(1, "syntax: filt:drop[:P-DROP]");
+ d = CREATE(drop);
+ if (ac > 0) d->p_drop = atoi(av[0]);
+ else d->p_drop = 5;
+ f->state = d;
+ f->func = dodrop;
+}
+
/*----- Delay filter ------------------------------------------------------*/
typedef struct delaynode {
@@ -309,6 +316,8 @@ static void dsend(delaynode *dn, unsigned force)
{
delay *d = dn->d;
delaynode *ddn;
+ unsigned i;
+
fputs(" send...\n", stdout);
assert(dn->buf);
PASS(d->f->next, dn->buf, dn->sz);
@@ -331,7 +340,7 @@ static void dsend(delaynode *dn, unsigned force)
ddn->flag = 0;
printf(" move id %u from slot %u to slot %u", ddn->seq, ddn->i, dn->i);
}
- { unsigned i; for (i = 0; i < d->n; i++) assert(d->q[i].buf); }
+ for (i = 0; i < d->n; i++) assert(d->q[i].buf);
fputs(" remove", stdout);
}
}
@@ -376,19 +385,14 @@ static void adddelay(filter *f, unsigned ac, char **av)
delay *d;
unsigned i;
- if (ac < 1 || ac > 3)
- die(1, "syntax: filt:delay:QLEN[:MILLIS:PREPLAY]");
+ if (ac < 1 || ac > 3) die(1, "syntax: filt:delay:QLEN[:MILLIS:P-REPLAY]");
d = CREATE(delay);
d->max = atoi(av[0]);
- if (ac > 1)
- d->t = strtoul(av[1], 0, 10);
- else
- d->t = 100;
+ if (ac > 1) d->t = strtoul(av[1], 0, 10);
+ else d->t = 100;
d->t *= 1000;
- if (ac > 2)
- d->p_replay = atoi(av[2]);
- else
- d->p_replay = 20;
+ if (ac > 2) d->p_replay = atoi(av[2]);
+ else d->p_replay = 20;
d->n = 0;
d->q = xmalloc(d->max * sizeof(delaynode));
d->f = f;
@@ -407,13 +411,12 @@ static void adddelay(filter *f, unsigned ac, char **av)
static void dosend(filter *f, const octet *buf, size_t sz)
{
printf("send to `%s'\n", f->p_to->name);
- write(f->p_to->sf.fd, buf, sz);
+ DISCARD(write(f->p_to->sf.fd, buf, sz));
}
static void addsend(filter *f, unsigned ac, char **av)
{
- if (ac)
- die(1, "syntax: filt:send");
+ if (ac) die(1, "syntax: filt:send");
f->func = dosend;
}
@@ -424,6 +427,7 @@ const struct filtab {
{ "send", addsend },
{ "fork", addfork },
{ "delay", adddelay },
+ { "drop", adddrop },
{ "corrupt", addcorrupt },
{ 0, 0 }
};
@@ -432,21 +436,16 @@ static void dofilter(peer *from, peer *to, unsigned ac, char **av)
{
filter **ff, *f = CREATE(filter);
const struct filtab *ft;
- if (ac < 1)
- die(1, "syntax: {l,r,}filt:NAME:...");
+ if (ac < 1) die(1, "syntax: {l,r,}filt:NAME:...");
f->next = 0;
f->p_from = from;
f->p_to = to;
f->state = 0;
- for (ff = &from->f; *ff; ff = &(*ff)->next)
- ;
+ for (ff = &from->f; *ff; ff = &(*ff)->next);
*ff = f;
- for (ft = filtab; ft->name; ft++) {
- if (strcmp(av[0], ft->name) == 0) {
- ft->func(f, ac - 1, av + 1);
- return;
- }
- }
+ for (ft = filtab; ft->name; ft++)
+ if (strcmp(av[0], ft->name) == 0)
+ { ft->func(f, ac - 1, av + 1); return; }
die(1, "unknown filter `%s'", av[0]);
}
@@ -475,8 +474,7 @@ static void floodtimer(struct timeval *tv, void *vv)
sz /= 2;
rng->ops->fill(rng, buf, sz);
- if (f->type < 0x100)
- buf[0] = f->type;
+ if (f->type < 0x100) buf[0] = f->type;
puts("flood packet");
PASS(f->p->f, buf, sz);
setflood(f);
@@ -493,22 +491,15 @@ static void setflood(flood *f)
static void doflood(peer *p, unsigned ac, char **av)
{
flood *f;
- if (ac > 3)
- die(1, "syntax: flood[:TYPE:MILLIS:SIZE]");
+ if (ac > 3) die(1, "syntax: flood[:TYPE:MILLIS:SIZE]");
f = CREATE(flood);
f->p = p;
- if (ac > 0)
- f->type = strtoul(av[0], 0, 16);
- else
- f->type = 0x100;
- if (ac > 1)
- f->t = atoi(av[1]);
- else
- f->t = 10;
- if (ac > 2)
- f->sz = atoi(av[2]);
- else
- f->sz = 128;
+ if (ac > 0) f->type = strtoul(av[0], 0, 16);
+ else f->type = 0x100;
+ if (ac > 1) f->t = atoi(av[1]);
+ else f->t = 10;
+ if (ac > 2) f->sz = atoi(av[2]);
+ else f->sz = 128;
f->t *= 1000;
setflood(f);
}
@@ -543,15 +534,11 @@ static void include(unsigned ac, char **av)
{
FILE *fp;
dstr d = DSTR_INIT;
- if (!ac)
- die(1, "syntax: include:FILE:...");
+ if (!ac) die(1, "syntax: include:FILE:...");
while (*av) {
if ((fp = fopen(*av, "r")) == 0)
die(1, "fopen `%s': %s", *av, strerror(errno));
- while (dstr_putline(&d, fp) != EOF) {
- parse(d.buf);
- DRESET(&d);
- }
+ while (dstr_putline(&d, fp) != EOF) { parse(d.buf); DRESET(&d); }
fclose(fp);
av++;
}
@@ -582,8 +569,7 @@ static void parse(char *p)
const struct cmdtab *ct;
p = strtok(p, ":");
- if (!p || *p == '#')
- return;
+ if (!p || *p == '#') return;
do {
v[c++] = p;
p = strtok(0, ":");
@@ -631,6 +617,7 @@ Filters:\n\
send\n\
fork:TAG\n\
delay:QLEN[:MILLIS:P-REPLAY]\n\
+ drop[:P-DROP]\n\
corrupt[:P-CORRUPT]\n",
fp);
}
@@ -640,7 +627,8 @@ int main(int argc, char *argv[])
const char *kfname = "keyring.pub";
int i;
unsigned f = 0;
- char buf[16];
+ char buf[32];
+ static octet zero[CHACHA_NONCESZ];
#define f_bogus 1u
@@ -653,43 +641,30 @@ int main(int argc, char *argv[])
{ "keyring", OPTF_ARGREQ, 0, 'k' },
{ 0, 0, 0, 0 }
};
- if ((i = mdwopt(argc, argv, "hvuk:", opt, 0, 0, 0)) < 0)
- break;
+ if ((i = mdwopt(argc, argv, "hvuk:", opt, 0, 0, 0)) < 0) break;
switch (i) {
- case 'h':
- help(stdout);
- exit(0);
- case 'v':
- version(stdout);
- exit(0);
- case 'u':
- usage(stdout);
- exit(0);
- case 'k':
- kfname = optarg;
- break;
- default:
- f |= f_bogus;
- break;
+ case 'h': help(stdout); exit(0);
+ case 'v': version(stdout); exit(0);
+ case 'u': usage(stdout); exit(0);
+ case 'k': kfname = optarg; break;
+ default: f |= f_bogus; break;
}
}
- if (f & f_bogus) {
- usage(stderr);
- exit(1);
- }
+ if (f & f_bogus) { usage(stderr); exit(1); }
+
rand_noisesrc(RAND_GLOBAL, &noise_source);
- rand_seed(RAND_GLOBAL, 160);
+ rand_seed(RAND_GLOBAL, 256);
rand_get(RAND_GLOBAL, buf, sizeof(buf));
- rng = rc4_rand(buf, sizeof(buf));
+ rng = chacha20_rand(buf, sizeof(buf), zero);
sel_init(&sel);
if (key_open(&keys, kfname, KOPEN_READ, key_moan, 0))
die(1, "couldn't open `%s': %s", kfname, strerror(errno));
- for (i = optind; i < argc; i++)
- parse(argv[i]);
- if (npeer != 2)
- die(1, "need two peers");
- for (;;)
- sel_select(&sel);
+ for (i = optind; i < argc; i++) parse(argv[i]);
+ if (npeer != 2) die(1, "need two peers");
+ for (;;) {
+ if (sel_select(&sel) && errno != EINTR)
+ die(1, "select failed: %s", strerror(errno));
+ }
#undef f_bogus
}