reverting the code after 0.4.1, except for some patches

This commit is contained in:
Erik Ekman 2008-07-12 11:36:39 +00:00
parent cb3115865d
commit ddaebb0074
11 changed files with 94 additions and 135 deletions

View file

@ -1,5 +1,5 @@
CC = gcc CC = gcc
COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o md5.o common.o packet.o COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o md5.o common.o
CLIENTOBJS = iodine.o CLIENTOBJS = iodine.o
CLIENT = ../bin/iodine CLIENT = ../bin/iodine
SERVEROBJS = iodined.o user.o SERVEROBJS = iodined.o user.o

View file

@ -111,20 +111,3 @@ read_password(char *buf, size_t len)
strncpy(buf, pwd, len); strncpy(buf, pwd, len);
buf[len-1] = '\0'; buf[len-1] = '\0';
} }
int
check_topdomain(char *str)
{
int i;
if(str[0] == '.') /* special case */
return 1;
for( i = 0; i < strlen(str); i++) {
if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' )
continue;
else
return 1;
}
return 0;
}

View file

@ -30,6 +30,14 @@
#define QUERY_NAME_SIZE 256 #define QUERY_NAME_SIZE 256
struct packet
{
int len; /* Total packet length */
int sentlen; /* Length of chunk currently transmitted */
int offset; /* Current offset */
char data[64*1024]; /* The data */
};
struct query { struct query {
char name[QUERY_NAME_SIZE]; char name[QUERY_NAME_SIZE];
short type; short type;
@ -46,6 +54,4 @@ void do_detach();
void read_password(char*, size_t); void read_password(char*, size_t);
int check_topdomain(char *);
#endif #endif

View file

@ -49,7 +49,7 @@ inline_dotify(char *buf, size_t buflen)
} }
reader = writer - dots; reader = writer - dots;
pos = (unsigned) (reader - buf); pos = (unsigned) (reader - buf) + 1;
while (dots) { while (dots) {
if (pos % 62 == 0) { if (pos % 62 == 0) {

View file

@ -36,7 +36,6 @@
#endif #endif
#include "common.h" #include "common.h"
#include "packet.h"
#include "encoding.h" #include "encoding.h"
#include "base32.h" #include "base32.h"
#include "dns.h" #include "dns.h"
@ -46,7 +45,7 @@
static void send_ping(int fd); static void send_ping(int fd);
static void send_chunk(int fd); static void send_chunk(int fd);
static int build_hostname(char *buf, size_t buflen, size_t offset, static int build_hostname(char *buf, size_t buflen,
const char *data, const size_t datalen, const char *data, const size_t datalen,
const char *topdomain, struct encoder *encoder); const char *topdomain, struct encoder *encoder);
@ -67,9 +66,6 @@ static char userid;
/* DNS id for next packet */ /* DNS id for next packet */
static uint16_t chunkid; static uint16_t chunkid;
/* DNS id for last packet with payload from server */
static uint16_t server_id;
/* Base32 encoder used for non-data packets */ /* Base32 encoder used for non-data packets */
static struct encoder *b32; static struct encoder *b32;
@ -80,9 +76,6 @@ static struct encoder *dataenc;
/* result of case preservation check done after login */ /* result of case preservation check done after login */
static int case_preserved; static int case_preserved;
/* For easy conversion 0-F to ascii digit */
static char hex[] = "0123456789ABCDEF";
static void static void
sighandler(int sig) sighandler(int sig)
{ {
@ -92,16 +85,16 @@ sighandler(int sig)
static void static void
send_query(int fd, char *hostname) send_query(int fd, char *hostname)
{ {
char pkt[4096]; char packet[4096];
struct query q; struct query q;
size_t len; size_t len;
q.id = ++chunkid; q.id = ++chunkid;
q.type = T_NULL; q.type = T_NULL;
len = dns_encode(pkt, sizeof(pkt), &q, QR_QUERY, hostname, strlen(hostname)); len = dns_encode(packet, sizeof(packet), &q, QR_QUERY, hostname, strlen(hostname));
sendto(fd, pkt, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv)); sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv));
} }
static void static void
@ -109,15 +102,14 @@ send_packet(int fd, char cmd, const char *data, const size_t datalen)
{ {
char buf[4096]; char buf[4096];
build_hostname(buf, sizeof(buf), 1, data, datalen, topdomain, b32);
/* build_hostname clears buf, write command afterwards */
buf[0] = cmd; buf[0] = cmd;
build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, b32);
send_query(fd, buf); send_query(fd, buf);
} }
static int static int
build_hostname(char *buf, size_t buflen, size_t offset, build_hostname(char *buf, size_t buflen,
const char *data, const size_t datalen, const char *data, const size_t datalen,
const char *topdomain, struct encoder *encoder) const char *topdomain, struct encoder *encoder)
{ {
@ -125,15 +117,14 @@ build_hostname(char *buf, size_t buflen, size_t offset,
size_t space; size_t space;
char *b; char *b;
space = MIN(0xFF, buflen) - strlen(topdomain) - 2; space = MIN(0xFF, buflen) - strlen(topdomain) - 2;
if (!encoder->places_dots()) if (!encoder->places_dots())
space -= (space / 62); /* space for dots */ space -= (space / 62); /* space for dots */
memset(buf, 0, buflen); memset(buf, 0, buflen);
memset(buf, 'A', offset);
b = buf + offset; encsize = encoder->encode(buf, &space, data, datalen);
encsize = encoder->encode(b, &space, data, datalen);
if (!encoder->places_dots()) if (!encoder->places_dots())
inline_dotify(buf, buflen); inline_dotify(buf, buflen);
@ -149,6 +140,12 @@ build_hostname(char *buf, size_t buflen, size_t offset,
return space; return space;
} }
int
is_sending()
{
return (packet.len != 0);
}
int int
read_dns(int fd, char *buf, int buflen) read_dns(int fd, char *buf, int buflen)
{ {
@ -168,14 +165,15 @@ read_dns(int fd, char *buf, int buflen)
rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r); rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r);
if (rv > 0) { if (is_sending() && chunkid == q.id) {
server_id = q.id;
}
if (packet_empty(&packet) == 0 && chunkid == q.id) {
/* Got ACK on sent packet */ /* Got ACK on sent packet */
packet_advance(&packet); packet.offset += packet.sentlen;
if (!packet_empty(&packet)) { if (packet.offset == packet.len) {
/* Packet completed */
packet.offset = 0;
packet.len = 0;
packet.sentlen = 0;
} else {
/* More to send */ /* More to send */
send_chunk(fd); send_chunk(fd);
} }
@ -200,7 +198,10 @@ tunnel_tun(int tun_fd, int dns_fd)
inlen = read; inlen = read;
compress2((uint8_t*)out, &outlen, (uint8_t*)in, inlen, 9); compress2((uint8_t*)out, &outlen, (uint8_t*)in, inlen, 9);
packet_fill(&packet, out, outlen); memcpy(packet.data, out, MIN(outlen, sizeof(packet.data)));
packet.sentlen = 0;
packet.offset = 0;
packet.len = outlen;
send_chunk(dns_fd); send_chunk(dns_fd);
@ -225,7 +226,7 @@ tunnel_dns(int tun_fd, int dns_fd)
return -1; return -1;
write_tun(tun_fd, out, outlen); write_tun(tun_fd, out, outlen);
if (packet_empty(&packet)) if (!is_sending())
send_ping(dns_fd); send_ping(dns_fd);
return read; return read;
@ -246,7 +247,7 @@ tunnel(int tun_fd, int dns_fd)
tv.tv_usec = 0; tv.tv_usec = 0;
FD_ZERO(&fds); FD_ZERO(&fds);
if (packet_empty(&packet)) if (!is_sending())
FD_SET(tun_fd, &fds); FD_SET(tun_fd, &fds);
FD_SET(dns_fd, &fds); FD_SET(dns_fd, &fds);
@ -278,21 +279,19 @@ tunnel(int tun_fd, int dns_fd)
static void static void
send_chunk(int fd) send_chunk(int fd)
{ {
char hex[] = "0123456789ABCDEF";
char buf[4096]; char buf[4096];
int avail; int avail;
int code; int code;
int sentlen;
char *p; char *p;
p = packet.data; p = packet.data;
p += packet.offset; p += packet.offset;
avail = packet_len_to_send(&packet); avail = packet.len - packet.offset;
sentlen = build_hostname(buf, sizeof(buf), 3, p, avail, topdomain, dataenc); packet.sentlen = build_hostname(buf + 1, sizeof(buf) - 1, p, avail, topdomain, dataenc);
packet_send_len(&packet, sentlen); if (packet.sentlen == avail)
if (sentlen == avail)
code = 1; code = 1;
else else
code = 0; code = 0;
@ -300,9 +299,6 @@ send_chunk(int fd)
code |= (userid << 1); code |= (userid << 1);
buf[0] = hex[code]; buf[0] = hex[code];
/* tell server we received reply */
buf[1] = hex[(server_id >> 4) & 0xf];
buf[2] = hex[(server_id >> 0) & 0xf];
send_query(fd, buf); send_query(fd, buf);
} }
@ -326,17 +322,17 @@ send_login(int fd, char *login, int len)
static void static void
send_ping(int fd) send_ping(int fd)
{ {
char data[5]; char data[3];
/* clear any packet not sent */ if (is_sending()) {
packet_init(&packet); packet.sentlen = 0;
packet.offset = 0;
packet.len = 0;
}
data[0] = userid; data[0] = userid;
/* tell server we received reply */ data[1] = (rand_seed >> 8) & 0xff;
data[1] = hex[(server_id >> 4) & 0xf]; data[2] = (rand_seed >> 0) & 0xff;
data[2] = hex[(server_id >> 0) & 0xf];
data[3] = (rand_seed >> 8) & 0xff;
data[4] = (rand_seed >> 0) & 0xff;
rand_seed++; rand_seed++;
@ -451,7 +447,7 @@ perform_login:
if(r > 0) { if(r > 0) {
read = read_dns(dns_fd, in, sizeof(in)); read = read_dns(dns_fd, in, sizeof(in));
if(read < 0) { if(read <= 0) {
warn("read"); warn("read");
continue; continue;
} }
@ -633,7 +629,6 @@ main(int argc, char **argv)
newroot = NULL; newroot = NULL;
device = NULL; device = NULL;
chunkid = 0; chunkid = 0;
server_id = 0;
b32 = get_base32_encoder(); b32 = get_base32_encoder();
dataenc = get_base32_encoder(); dataenc = get_base32_encoder();
@ -642,14 +637,12 @@ main(int argc, char **argv)
switch(choice) { switch(choice) {
case 'v': case 'v':
version(); version();
/* NOTREACHED */
break; break;
case 'f': case 'f':
foreground = 1; foreground = 1;
break; break;
case 'h': case 'h':
help(); help();
/* NOTREACHED */
break; break;
case 'u': case 'u':
username = optarg; username = optarg;
@ -697,13 +690,8 @@ main(int argc, char **argv)
set_nameserver(nameserv_addr); set_nameserver(nameserv_addr);
if(strlen(topdomain) <= 128) { if (strlen(topdomain) > 128 || topdomain[0] == '.') {
if(check_topdomain(topdomain)) { warnx("Use a topdomain max 128 chars long. Do not start it with a dot.\n");
warnx("Topdomain contains invalid characters.\n");
usage();
}
} else {
warnx("Use a topdomain max 128 chars long.\n");
usage(); usage();
} }

View file

@ -82,8 +82,10 @@ tunnel_tun(int tun_fd, int dns_fd)
compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9); compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
/* if another packet is queued, throw away this one. TODO build queue */ /* if another packet is queued, throw away this one. TODO build queue */
if (packet_empty(&(users[userid].outpacket))) { if (users[userid].outpacket.len == 0) {
return packet_fill(&(users[userid].outpacket), out, outlen); memcpy(users[userid].outpacket.data, out, outlen);
users[userid].outpacket.len = outlen;
return outlen;
} else { } else {
return 0; return 0;
} }
@ -122,16 +124,6 @@ send_version_response(int fd, version_ack_t ack, uint32_t payload, struct user *
write_dns(fd, &u->q, out, sizeof(out)); write_dns(fd, &u->q, out, sizeof(out));
} }
static void
send_chunk(int dns_fd, struct query *q, int userid)
{
/* XXX: check MTU and only send part of packet if needed */
write_dns(dns_fd, q, users[userid].outpacket.data, users[userid].outpacket.len);
/* move this reset to after receiving ack */
users[userid].outpacket.len = 0;
users[userid].q.id = 0;
}
static int static int
tunnel_dns(int tun_fd, int dns_fd) tunnel_dns(int tun_fd, int dns_fd)
{ {
@ -255,7 +247,7 @@ tunnel_dns(int tun_fd, int dns_fd)
write_dns(dns_fd, &(dummy.q), "BADIP", 5); write_dns(dns_fd, &(dummy.q), "BADIP", 5);
} else { } else {
/* decode with this users encoding */ /* decode with this users encoding */
read = unpack_data(unpacked, sizeof(unpacked), &(in[3]), read - 3, read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1,
users[userid].encoder); users[userid].encoder);
users[userid].last_pkt = time(NULL); users[userid].last_pkt = time(NULL);
@ -267,8 +259,8 @@ tunnel_dns(int tun_fd, int dns_fd)
if (code & 1) { if (code & 1) {
outlen = sizeof(out); outlen = sizeof(out);
uncompress((uint8_t*)out, &outlen, (uint8_t*)users[userid].inpacket.data, uncompress((uint8_t*)out, &outlen,
users[userid].inpacket.len); (uint8_t*)users[userid].inpacket.data, users[userid].inpacket.len);
hdr = (struct ip*) (out + 4); hdr = (struct ip*) (out + 4);
touser = find_user_by_ip(hdr->ip_dst.s_addr); touser = find_user_by_ip(hdr->ip_dst.s_addr);
@ -279,21 +271,23 @@ tunnel_dns(int tun_fd, int dns_fd)
} else { } else {
/* send the compressed packet to other client /* send the compressed packet to other client
* if another packet is queued, throw away this one. TODO build queue */ * if another packet is queued, throw away this one. TODO build queue */
if (packet_empty(&(users[touser].outpacket))) { if (users[touser].outpacket.len == 0) {
packet_fill(&(users[touser].outpacket), users[userid].inpacket.data, memcpy(users[touser].outpacket.data, users[userid].inpacket.data, users[userid].inpacket.len);
users[userid].inpacket.len); users[touser].outpacket.len = users[userid].inpacket.len;
} }
} }
packet_init(&(users[userid].inpacket)); /* clear inpacket */ users[userid].inpacket.len = users[userid].inpacket.offset = 0;
} }
} }
} }
/* userid must be set for a reply to be sent */ /* userid must be set for a reply to be sent */
if (userid >= 0 && userid < USERS && dummy.q.fromlen == users[userid].addrlen && if (userid >= 0 && userid < USERS && dummy.q.fromlen == users[userid].addrlen &&
memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) == 0 && memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) == 0 &&
packet_empty(&(users[userid].outpacket)) == 0) { users[userid].outpacket.len > 0) {
send_chunk(dns_fd, &(dummy.q), userid); write_dns(dns_fd, &(dummy.q), users[userid].outpacket.data, users[userid].outpacket.len);
users[userid].outpacket.len = 0;
users[userid].q.id = 0;
} }
return 0; return 0;
@ -334,7 +328,9 @@ tunnel(int tun_fd, int dns_fd)
if (i==0) { if (i==0) {
for (j = 0; j < USERS; j++) { for (j = 0; j < USERS; j++) {
if (users[j].q.id != 0) { if (users[j].q.id != 0) {
send_chunk(dns_fd, &(users[j].q), j); write_dns(dns_fd, &(users[j].q), users[j].outpacket.data, users[j].outpacket.len);
users[j].outpacket.len = 0;
users[j].q.id = 0;
} }
} }
} else { } else {
@ -431,7 +427,8 @@ help() {
static void static void
version() { version() {
char *svnver = "$Rev$ from $Date$"; char *svnver;
svnver = "$Rev$ from $Date$";
printf("iodine IP over DNS tunneling server\n"); printf("iodine IP over DNS tunneling server\n");
printf("SVN version: %s\n", svnver); printf("SVN version: %s\n", svnver);
exit(0); exit(0);
@ -469,14 +466,12 @@ main(int argc, char **argv)
switch(choice) { switch(choice) {
case 'v': case 'v':
version(); version();
/* NOTREACHED */
break; break;
case 'f': case 'f':
foreground = 1; foreground = 1;
break; break;
case 'h': case 'h':
help(); help();
/* NOTREACHED */
break; break;
case 'u': case 'u':
username = optarg; username = optarg;
@ -495,6 +490,10 @@ main(int argc, char **argv)
break; break;
case 'p': case 'p':
port = atoi(optarg); port = atoi(optarg);
if (port) {
printf("ALERT! Other dns servers expect you to run on port 53.\n");
printf("You must manually forward port 53 to port %d for things to work.\n", port);
}
break; break;
case 'P': case 'P':
strncpy(password, optarg, sizeof(password)); strncpy(password, optarg, sizeof(password));
@ -505,7 +504,6 @@ main(int argc, char **argv)
break; break;
default: default:
usage(); usage();
/* NOTREACHED */
break; break;
} }
} }
@ -522,13 +520,8 @@ main(int argc, char **argv)
usage(); usage();
topdomain = strdup(argv[1]); topdomain = strdup(argv[1]);
if(strlen(topdomain) <= 128) { if (strlen(topdomain) > 128 || topdomain[0] == '.') {
if(check_topdomain(topdomain)) { warnx("Use a topdomain max 128 chars long. Do not start it with a dot.\n");
warnx("Topdomain contains invalid characters.\n");
usage();
}
} else {
warnx("Use a topdomain max 128 chars long.\n");
usage(); usage();
} }
@ -539,21 +532,11 @@ main(int argc, char **argv)
} }
} }
if (mtu <= 0) { if (mtu == 0) {
warnx("Bad MTU given.\n"); warnx("Bad MTU given.\n");
usage(); usage();
} }
if(port < 1 || port > 65535) {
warnx("Bad port number given.\n");
usage();
}
if (port != 53) {
printf("ALERT! Other dns servers expect you to run on port 53.\n");
printf("You must manually forward port 53 to port %d for things to work.\n", port);
}
if (listen_ip == INADDR_NONE) { if (listen_ip == INADDR_NONE) {
warnx("Bad IP address to listen on.\n"); warnx("Bad IP address to listen on.\n");
usage(); usage();

View file

@ -46,8 +46,9 @@ init_users(in_addr_t my_ip)
users[i].id = i; users[i].id = i;
snprintf(newip, sizeof(newip), "0.0.0.%d", i + 1); snprintf(newip, sizeof(newip), "0.0.0.%d", i + 1);
users[i].tun_ip = my_ip + inet_addr(newip);; users[i].tun_ip = my_ip + inet_addr(newip);;
packet_init(&(users[i].inpacket)); users[i].inpacket.len = 0;
packet_init(&(users[i].outpacket)); users[i].inpacket.offset = 0;
users[i].outpacket.len = 0;
users[i].q.id = 0; users[i].q.id = 0;
} }
} }

View file

@ -17,8 +17,6 @@
#ifndef __USER_H__ #ifndef __USER_H__
#define __USER_H__ #define __USER_H__
#include "packet.h"
#define USERS 8 #define USERS 8
struct user { struct user {

View file

@ -19,7 +19,7 @@
/* This is the version of the network protocol /* This is the version of the network protocol
It is usually equal to the latest iodine version number */ It is usually equal to the latest iodine version number */
#define VERSION 0x00000403 #define VERSION 0x00000402
#endif /* _VERSION_H_ */ #endif /* _VERSION_H_ */

View file

@ -1,7 +1,7 @@
CC = gcc CC = gcc
TEST = test TEST = test
OBJS = test.o base32.o base64.o read.o dns.o encoding.o login.o user.o OBJS = test.o base32.o base64.o read.o dns.o encoding.o login.o user.o
SRCOBJS = ../src/base32.o ../src/base64.o ../src/read.o ../src/dns.o ../src/encoding.o ../src/login.o ../src/md5.o ../src/user.o ../src/packet.o SRCOBJS = ../src/base32.o ../src/base64.o ../src/read.o ../src/dns.o ../src/encoding.o ../src/login.o ../src/md5.o ../src/user.o
OS = `uname | tr "a-z" "A-Z"` OS = `uname | tr "a-z" "A-Z"`
@ -21,6 +21,6 @@ $(TEST): $(OBJS) $(SRCOBJS)
clean: clean:
@echo "Cleaning..." @echo "Cleaning tests/"
@rm -f *~ *.core $(TEST) $(OBJS) @rm -f *~ *.core $(TEST) $(OBJS)

View file

@ -27,10 +27,10 @@ struct tuple
char *a; char *a;
char *b; char *b;
} dottests[] = { } dottests[] = {
{ "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaba", { "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab.a"}, "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a"},
{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."}, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."},
{ "abc123", "abc123" }, { "abc123", "abc123" },
{ NULL, NULL } { NULL, NULL }
}; };