mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-23 16:49:19 +02:00
Tagged iodine 0.4.2
This commit is contained in:
parent
d27bd67997
commit
e45bdece8e
17
CHANGELOG
17
CHANGELOG
|
@ -5,6 +5,23 @@ iodine - http://code.kryo.se/iodine
|
||||||
|
|
||||||
CHANGES:
|
CHANGES:
|
||||||
|
|
||||||
|
2008-08-06: 0.4.2 "Opened Zone"
|
||||||
|
- Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann
|
||||||
|
- Applied a patch for not creating and configuring the tun interface,
|
||||||
|
Debian bug #477692 by Vincent Bernat, controlled by -s switch
|
||||||
|
- Applied a security patch from Andrew Griffiths, use setgroups() to
|
||||||
|
limit the groups of the user
|
||||||
|
- Applied a patch to make iodine build on (Open)Solaris, from Albert Lee
|
||||||
|
Needs TUN/TAP driver: http://www.whiteboard.ne.jp/~admin2/tuntap/
|
||||||
|
Still needs some more code in tun.c for opening/closing the device
|
||||||
|
- Added option in server (-c) to disable IP/port checking on each packet,
|
||||||
|
will hopefully help when server is behind NAT
|
||||||
|
- Fixed bug #21, now only IP address part of each packet is checked.
|
||||||
|
Should remove the need for the -c option and also work with
|
||||||
|
bugfixed DNS servers worldwide.
|
||||||
|
- Added -D option on server to enable debugging. Debug level 1 now prints
|
||||||
|
info about each RX/TX datagram.
|
||||||
|
|
||||||
2007-11-30: 0.4.1 "Tea Online"
|
2007-11-30: 0.4.1 "Tea Online"
|
||||||
- Introduced encoding API
|
- Introduced encoding API
|
||||||
- Switched to new Base32 implementation
|
- Switched to new Base32 implementation
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -35,7 +35,7 @@ uninstall:
|
||||||
test: all
|
test: all
|
||||||
@echo "!! The check library is required for compiling and running the tests"
|
@echo "!! The check library is required for compiling and running the tests"
|
||||||
@echo "!! Get it at http://check.sf.net"
|
@echo "!! Get it at http://check.sf.net"
|
||||||
@(cd tests; make all)
|
@(cd tests; $(MAKE) all)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning..."
|
@echo "Cleaning..."
|
||||||
|
|
22
man/iodine.8
22
man/iodine.8
|
@ -1,5 +1,5 @@
|
||||||
.\" groff -man -Tascii iodine.8
|
.\" groff -man -Tascii iodine.8
|
||||||
.TH IODINE 8 "JUN 2007" "User Manuals"
|
.TH IODINE 8 "JUL 2008" "User Manuals"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
iodine, iodined \- tunnel IPv4 over DNS
|
iodine, iodined \- tunnel IPv4 over DNS
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -25,7 +25,7 @@ iodine, iodined \- tunnel IPv4 over DNS
|
||||||
|
|
||||||
.B iodined [-h]
|
.B iodined [-h]
|
||||||
|
|
||||||
.B iodined [-f] [-u
|
.B iodined [-c] [-s] [-f] [-D] [-u
|
||||||
.I user
|
.I user
|
||||||
.B ] [-P
|
.B ] [-P
|
||||||
.I password
|
.I password
|
||||||
|
@ -78,6 +78,16 @@ Use the TUN device 'device' instead of the normal one, which is dnsX on Linux
|
||||||
and otherwise tunX.
|
and otherwise tunX.
|
||||||
.SS Server Options:
|
.SS Server Options:
|
||||||
.TP
|
.TP
|
||||||
|
.B -c
|
||||||
|
Disable checks on client IP on all incoming requests.
|
||||||
|
.TP
|
||||||
|
.B -s
|
||||||
|
Don't try to configure IP address or MTU. This should only be used if
|
||||||
|
you have already configured the device that will be used.
|
||||||
|
.TP
|
||||||
|
.B -D
|
||||||
|
Increase debug level. Level 1 prints info about each RX/TX packet.
|
||||||
|
.TP
|
||||||
.B -m mtu
|
.B -m mtu
|
||||||
Set 'mtu' as mtu size for the tunnel device. This will be sent to the client
|
Set 'mtu' as mtu size for the tunnel device. This will be sent to the client
|
||||||
on connect, and the client will use the same mtu.
|
on connect, and the client will use the same mtu.
|
||||||
|
@ -124,13 +134,13 @@ the same on both the client and the server.
|
||||||
.TP
|
.TP
|
||||||
Try it out within your own LAN! Follow these simple steps:
|
Try it out within your own LAN! Follow these simple steps:
|
||||||
.TP
|
.TP
|
||||||
- On your server, run: ./iodined -f 10.0.0.1 test.asdf
|
- On your server, run: ./iodined \-f 10.0.0.1 test.asdf
|
||||||
(If you already use the 10.0.0.0 network, use another internal net like
|
(If you already use the 10.0.0.0 network, use another internal net like
|
||||||
172.16.0.0)
|
172.16.0.0)
|
||||||
.TP
|
.TP
|
||||||
- Enter a password
|
- Enter a password
|
||||||
.TP
|
.TP
|
||||||
- On the client, run: ./iodine -f 192.168.0.1 test.asdf
|
- On the client, run: ./iodine \-f 192.168.0.1 test.asdf
|
||||||
(Replace 192.168.0.1 with the server's ip address)
|
(Replace 192.168.0.1 with the server's ip address)
|
||||||
.TP
|
.TP
|
||||||
- Enter the same password
|
- Enter the same password
|
||||||
|
@ -160,10 +170,10 @@ tunnel1 IN NS tunnel1host.mytunnel.com.
|
||||||
Now any DNS querys for domains ending with tunnel1.mytunnnel.com will be sent
|
Now any DNS querys for domains ending with tunnel1.mytunnnel.com will be sent
|
||||||
to your server. Start iodined on the server. The first argument is the tunnel
|
to your server. Start iodined on the server. The first argument is the tunnel
|
||||||
IP address (like 192.168.99.1) and the second is the assigned domain (in this
|
IP address (like 192.168.99.1) and the second is the assigned domain (in this
|
||||||
case tunnel1.mytunnel.com). The -f argument will keep iodined running in the
|
case tunnel1.mytunnel.com). The \-f argument will keep iodined running in the
|
||||||
foreground, which helps when testing. iodined will start a virtual interface,
|
foreground, which helps when testing. iodined will start a virtual interface,
|
||||||
and also start listening for DNS queries on UDP port 53. Either enter a
|
and also start listening for DNS queries on UDP port 53. Either enter a
|
||||||
password on the commandline (-P pass) or after the server has started. Now
|
password on the commandline (\-P pass) or after the server has started. Now
|
||||||
everything is ready for the client.
|
everything is ready for the client.
|
||||||
.TP
|
.TP
|
||||||
.B Client side:
|
.B Client side:
|
||||||
|
|
|
@ -8,10 +8,10 @@ SERVER = ../bin/iodined
|
||||||
OS = `uname | tr "a-z" "A-Z"`
|
OS = `uname | tr "a-z" "A-Z"`
|
||||||
ARCH = `uname -m`
|
ARCH = `uname -m`
|
||||||
|
|
||||||
LDFLAGS = -lz
|
LDFLAGS = -lz `sh osflags link`
|
||||||
CFLAGS = -c -g -Wall -D$(OS) -pedantic
|
CFLAGS = -c -g -Wall -D$(OS) -pedantic
|
||||||
|
|
||||||
all: stateos $(CLIENT) $(SERVER) $(TESTSUITE)
|
all: stateos $(CLIENT) $(SERVER)
|
||||||
|
|
||||||
stateos:
|
stateos:
|
||||||
@echo OS is $(OS), arch is $(ARCH)
|
@echo OS is $(OS), arch is $(ARCH)
|
||||||
|
|
58
src/common.c
58
src/common.c
|
@ -1,4 +1,5 @@
|
||||||
/* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
/* Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
||||||
|
* Copyright (c) 2007 Albert Lee <trisk@acm.jhu.edu>.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -21,6 +22,8 @@
|
||||||
#endif
|
#endif
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -29,10 +32,48 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
|
||||||
|
#if !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
|
||||||
|
static int daemon(int nochdir, int noclose)
|
||||||
|
{
|
||||||
|
int fd, i;
|
||||||
|
|
||||||
|
switch (fork()) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nochdir) {
|
||||||
|
chdir("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsid() < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noclose) {
|
||||||
|
if ((fd = open("/dev/null", O_RDWR)) >= 0) {
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
dup2(fd, i);
|
||||||
|
}
|
||||||
|
if (fd > 2) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
open_dns(int localport, in_addr_t listen_ip)
|
open_dns(int localport, in_addr_t listen_ip)
|
||||||
{
|
{
|
||||||
|
@ -111,3 +152,20 @@ 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;
|
||||||
|
}
|
||||||
|
|
|
@ -54,4 +54,6 @@ void do_detach();
|
||||||
|
|
||||||
void read_password(char*, size_t);
|
void read_password(char*, size_t);
|
||||||
|
|
||||||
|
int check_topdomain(char *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
src/dns.c
10
src/dns.c
|
@ -150,14 +150,13 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
warnx("Got NXDOMAIN as reply");
|
warnx("Got NXDOMAIN as reply");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case SERVFAIL:
|
case SERVFAIL:
|
||||||
warnx("Got SERVFAIL as reply");
|
warnx("Got SERVFAIL as reply");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NOERROR:
|
case NOERROR:
|
||||||
default:
|
default:
|
||||||
warnx("no query or answer in answer");
|
warnx("no query or answer in reply packet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -178,7 +177,7 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
rv = MIN(rlen, sizeof(rdata));
|
rv = MIN(rlen, sizeof(rdata));
|
||||||
rv = readdata(packet, &data, rdata, rv);
|
rv = readdata(packet, &data, rdata, rv);
|
||||||
|
|
||||||
if(type == T_NULL && rv > 2) {
|
if(type == T_NULL && rv > 2 && buf) {
|
||||||
rv = MIN(rv, buflen);
|
rv = MIN(rv, buflen);
|
||||||
memcpy(buf, rdata, rv);
|
memcpy(buf, rdata, rv);
|
||||||
}
|
}
|
||||||
|
@ -194,11 +193,6 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
|
||||||
readshort(packet, &data, &type);
|
readshort(packet, &data, &type);
|
||||||
readshort(packet, &data, &class);
|
readshort(packet, &data, &class);
|
||||||
|
|
||||||
if(type != T_NULL) {
|
|
||||||
rv = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(q->name, name, sizeof(q->name));
|
strncpy(q->name, name, sizeof(q->name));
|
||||||
q->name[sizeof(q->name) - 1] = '\0';
|
q->name[sizeof(q->name) - 1] = '\0';
|
||||||
q->type = type;
|
q->type = type;
|
||||||
|
|
34
src/iodine.c
34
src/iodine.c
|
@ -23,10 +23,12 @@
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
@ -76,6 +78,10 @@ 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;
|
||||||
|
|
||||||
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
|
static char *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sighandler(int sig)
|
sighandler(int sig)
|
||||||
{
|
{
|
||||||
|
@ -396,8 +402,11 @@ handshake(int dns_fd)
|
||||||
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) {
|
||||||
|
if (read == 0) {
|
||||||
warn("handshake read");
|
warn("handshake read");
|
||||||
|
}
|
||||||
|
/* if read < 0 then warning has been printed already */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +611,7 @@ static void
|
||||||
version() {
|
version() {
|
||||||
|
|
||||||
printf("iodine IP over DNS tunneling client\n");
|
printf("iodine IP over DNS tunneling client\n");
|
||||||
printf("version: 0.4.1 from 2007-11-30\n");
|
printf("version: 0.4.2 from 2008-08-06\n");
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -630,6 +639,14 @@ main(int argc, char **argv)
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
dataenc = get_base32_encoder();
|
dataenc = get_base32_encoder();
|
||||||
|
|
||||||
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
|
__progname = strrchr(argv[0], '/');
|
||||||
|
if (__progname == NULL)
|
||||||
|
__progname = argv[0];
|
||||||
|
else
|
||||||
|
__progname++;
|
||||||
|
#endif
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "vfhu:t:d:P:")) != -1) {
|
while ((choice = getopt(argc, argv, "vfhu:t:d:P:")) != -1) {
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
case 'v':
|
case 'v':
|
||||||
|
@ -687,8 +704,13 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
set_nameserver(nameserv_addr);
|
set_nameserver(nameserv_addr);
|
||||||
|
|
||||||
if (strlen(topdomain) > 128 || topdomain[0] == '.') {
|
if(strlen(topdomain) <= 128) {
|
||||||
warnx("Use a topdomain max 128 chars long. Do not start it with a dot.\n");
|
if(check_topdomain(topdomain)) {
|
||||||
|
warnx("Topdomain contains invalid characters.\n");
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warnx("Use a topdomain max 128 chars long.\n");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +744,9 @@ main(int argc, char **argv)
|
||||||
do_chroot(newroot);
|
do_chroot(newroot);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
gid_t gids[1];
|
||||||
|
gids[0] = pw->pw_gid;
|
||||||
|
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
||||||
warnx("Could not switch to user %s!\n", username);
|
warnx("Could not switch to user %s!\n", username);
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
227
src/iodined.c
227
src/iodined.c
|
@ -21,10 +21,12 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -32,6 +34,10 @@
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef DARWIN
|
||||||
|
#include <arpa/nameser8_compat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
|
@ -47,10 +53,17 @@ static char *topdomain;
|
||||||
static char password[33];
|
static char password[33];
|
||||||
static struct encoder *b32;
|
static struct encoder *b32;
|
||||||
|
|
||||||
|
static int check_ip;
|
||||||
static int my_mtu;
|
static int my_mtu;
|
||||||
static in_addr_t my_ip;
|
static in_addr_t my_ip;
|
||||||
|
|
||||||
static int read_dns(int, struct query *, char *, int);
|
static int debug;
|
||||||
|
|
||||||
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
|
static char *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int read_dns(int, struct query *);
|
||||||
static void write_dns(int, struct query *, char *, int);
|
static void write_dns(int, struct query *, char *, int);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -59,6 +72,15 @@ sigint(int sig)
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ip_cmp(int userid, struct query *q)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *tempin;
|
||||||
|
|
||||||
|
tempin = (struct sockaddr_in *) &(q->from);
|
||||||
|
return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tunnel_tun(int tun_fd, int dns_fd)
|
tunnel_tun(int tun_fd, int dns_fd)
|
||||||
{
|
{
|
||||||
|
@ -118,33 +140,43 @@ send_version_response(int fd, version_ack_t ack, uint32_t payload, struct user *
|
||||||
out[5] = ((payload >> 16) & 0xff);
|
out[5] = ((payload >> 16) & 0xff);
|
||||||
out[6] = ((payload >> 8) & 0xff);
|
out[6] = ((payload >> 8) & 0xff);
|
||||||
out[7] = ((payload) & 0xff);
|
out[7] = ((payload) & 0xff);
|
||||||
|
if (u) {
|
||||||
out[8] = u->id;
|
out[8] = u->id;
|
||||||
|
} else {
|
||||||
|
out[8] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
write_dns(fd, &u->q, out, sizeof(out));
|
write_dns(fd, &u->q, out, sizeof(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
tunnel_dns(int tun_fd, int dns_fd)
|
handle_null_request(int tun_fd, int dns_fd, struct query *q)
|
||||||
{
|
{
|
||||||
struct in_addr tempip;
|
struct in_addr tempip;
|
||||||
struct user dummy;
|
|
||||||
struct ip *hdr;
|
struct ip *hdr;
|
||||||
unsigned long outlen;
|
unsigned long outlen;
|
||||||
|
char in[64*1024];
|
||||||
char logindata[16];
|
char logindata[16];
|
||||||
char out[64*1024];
|
char out[64*1024];
|
||||||
char in[64*1024];
|
|
||||||
char unpacked[64*1024];
|
char unpacked[64*1024];
|
||||||
char *tmp[2];
|
char *tmp[2];
|
||||||
|
char *domain;
|
||||||
int userid;
|
int userid;
|
||||||
int touser;
|
int touser;
|
||||||
int version;
|
int version;
|
||||||
int read;
|
|
||||||
int code;
|
int code;
|
||||||
|
int read;
|
||||||
|
|
||||||
userid = -1;
|
userid = -1;
|
||||||
if ((read = read_dns(dns_fd, &(dummy.q), in, sizeof(in))) <= 0)
|
domain = strstr(q->name, topdomain);
|
||||||
return 0;
|
if (!domain) {
|
||||||
|
/* Not for us, discard */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
read = (int) (domain - q->name);
|
||||||
|
memcpy(in, q->name, MIN(read, sizeof(in)));
|
||||||
|
|
||||||
if(in[0] == 'V' || in[0] == 'v') {
|
if(in[0] == 'V' || in[0] == 'v') {
|
||||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
||||||
|
@ -160,34 +192,37 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||||
if (version == VERSION) {
|
if (version == VERSION) {
|
||||||
userid = find_available_user();
|
userid = find_available_user();
|
||||||
if (userid >= 0) {
|
if (userid >= 0) {
|
||||||
|
struct sockaddr_in *tempin;
|
||||||
|
|
||||||
users[userid].seed = rand();
|
users[userid].seed = rand();
|
||||||
memcpy(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen);
|
/* Store remote IP number */
|
||||||
memcpy(&(users[userid].q), &(dummy.q), sizeof(struct query));
|
tempin = (struct sockaddr_in *) &(q->from);
|
||||||
users[userid].addrlen = dummy.q.fromlen;
|
memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
|
||||||
|
|
||||||
|
memcpy(&(users[userid].q), q, sizeof(struct query));
|
||||||
users[userid].encoder = get_base32_encoder();
|
users[userid].encoder = get_base32_encoder();
|
||||||
send_version_response(dns_fd, VERSION_ACK, users[userid].seed, &users[userid]);
|
send_version_response(dns_fd, VERSION_ACK, users[userid].seed, &users[userid]);
|
||||||
users[userid].q.id = 0;
|
users[userid].q.id = 0;
|
||||||
} else {
|
} else {
|
||||||
/* No space for another user */
|
/* No space for another user */
|
||||||
send_version_response(dns_fd, VERSION_FULL, USERS, &dummy);
|
send_version_response(dns_fd, VERSION_FULL, USERS, NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
send_version_response(dns_fd, VERSION_NACK, VERSION, &dummy);
|
send_version_response(dns_fd, VERSION_NACK, VERSION, NULL);
|
||||||
}
|
}
|
||||||
} else if(in[0] == 'L' || in[0] == 'l') {
|
} else if(in[0] == 'L' || in[0] == 'l') {
|
||||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
||||||
/* Login phase, handle auth */
|
/* Login phase, handle auth */
|
||||||
userid = unpacked[0];
|
userid = unpacked[0];
|
||||||
if (userid < 0 || userid >= USERS) {
|
if (userid < 0 || userid >= USERS) {
|
||||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
write_dns(dns_fd, q, "BADIP", 5);
|
||||||
return 0; /* illegal id */
|
return; /* illegal id */
|
||||||
}
|
}
|
||||||
users[userid].last_pkt = time(NULL);
|
users[userid].last_pkt = time(NULL);
|
||||||
login_calculate(logindata, 16, password, users[userid].seed);
|
login_calculate(logindata, 16, password, users[userid].seed);
|
||||||
|
|
||||||
if (dummy.q.fromlen != users[userid].addrlen ||
|
if (check_ip && ip_cmp(userid, q) != 0) {
|
||||||
memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) != 0) {
|
write_dns(dns_fd, q, "BADIP", 5);
|
||||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
|
||||||
} else {
|
} else {
|
||||||
if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
|
if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
|
||||||
/* Login ok, send ip/mtu info */
|
/* Login ok, send ip/mtu info */
|
||||||
|
@ -200,31 +235,31 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||||
read = snprintf(out, sizeof(out), "%s-%s-%d",
|
read = snprintf(out, sizeof(out), "%s-%s-%d",
|
||||||
tmp[0], tmp[1], my_mtu);
|
tmp[0], tmp[1], my_mtu);
|
||||||
|
|
||||||
write_dns(dns_fd, &(dummy.q), out, read);
|
write_dns(dns_fd, q, out, read);
|
||||||
dummy.q.id = 0;
|
q->id = 0;
|
||||||
|
|
||||||
free(tmp[1]);
|
free(tmp[1]);
|
||||||
free(tmp[0]);
|
free(tmp[0]);
|
||||||
} else {
|
} else {
|
||||||
write_dns(dns_fd, &(dummy.q), "LNAK", 4);
|
write_dns(dns_fd, q, "LNAK", 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(in[0] == 'P' || in[0] == 'p') {
|
} else if(in[0] == 'P' || in[0] == 'p') {
|
||||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
||||||
/* Ping packet, store userid */
|
/* Ping packet, store userid */
|
||||||
userid = unpacked[0];
|
userid = unpacked[0];
|
||||||
if (userid < 0 || userid >= USERS) {
|
if (userid < 0 || userid >= USERS || ip_cmp(userid, q) != 0) {
|
||||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
write_dns(dns_fd, q, "BADIP", 5);
|
||||||
return 0; /* illegal id */
|
return; /* illegal id */
|
||||||
}
|
}
|
||||||
memcpy(&(users[userid].q), &(dummy.q), sizeof(struct query));
|
memcpy(&(users[userid].q), q, sizeof(struct query));
|
||||||
users[userid].last_pkt = time(NULL);
|
users[userid].last_pkt = time(NULL);
|
||||||
} else if(in[0] == 'Z' || in[0] == 'z') {
|
} else if(in[0] == 'Z' || in[0] == 'z') {
|
||||||
/* Case conservation check */
|
/* Case conservation check */
|
||||||
|
|
||||||
/* Reply with received hostname as data */
|
/* Reply with received hostname as data */
|
||||||
write_dns(dns_fd, &(dummy.q), in, read);
|
write_dns(dns_fd, q, in, read);
|
||||||
return 0;
|
return;
|
||||||
} else if((in[0] >= '0' && in[0] <= '9')
|
} else if((in[0] >= '0' && in[0] <= '9')
|
||||||
|| (in[0] >= 'a' && in[0] <= 'f')
|
|| (in[0] >= 'a' && in[0] <= 'f')
|
||||||
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
||||||
|
@ -237,22 +272,20 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||||
|
|
||||||
userid = code >> 1;
|
userid = code >> 1;
|
||||||
if (userid < 0 || userid >= USERS) {
|
if (userid < 0 || userid >= USERS) {
|
||||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
write_dns(dns_fd, q, "BADIP", 5);
|
||||||
return 0; /* illegal id */
|
return; /* illegal id */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check sending ip number */
|
/* Check sending ip number */
|
||||||
if (dummy.q.fromlen != users[userid].addrlen ||
|
if (check_ip && ip_cmp(userid, q) != 0) {
|
||||||
memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) != 0) {
|
write_dns(dns_fd, 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[1]), read - 1,
|
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);
|
||||||
memcpy(&(users[userid].q), &(dummy.q), sizeof(struct query));
|
memcpy(&(users[userid].q), q, sizeof(struct query));
|
||||||
users[userid].addrlen = dummy.q.fromlen;
|
|
||||||
memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read);
|
memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read);
|
||||||
users[userid].inpacket.len += read;
|
users[userid].inpacket.len += read;
|
||||||
users[userid].inpacket.offset += read;
|
users[userid].inpacket.offset += read;
|
||||||
|
@ -281,14 +314,35 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 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 && ip_cmp(userid, q) == 0 && users[userid].outpacket.len > 0) {
|
||||||
memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) == 0 &&
|
write_dns(dns_fd, q, users[userid].outpacket.data, users[userid].outpacket.len);
|
||||||
users[userid].outpacket.len > 0) {
|
|
||||||
|
|
||||||
write_dns(dns_fd, &(dummy.q), users[userid].outpacket.data, users[userid].outpacket.len);
|
|
||||||
users[userid].outpacket.len = 0;
|
users[userid].outpacket.len = 0;
|
||||||
users[userid].q.id = 0;
|
users[userid].q.id = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tunnel_dns(int tun_fd, int dns_fd)
|
||||||
|
{
|
||||||
|
struct query q;
|
||||||
|
int read;
|
||||||
|
|
||||||
|
if ((read = read_dns(dns_fd, &q)) <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (debug >= 1) {
|
||||||
|
struct sockaddr_in *tempin;
|
||||||
|
tempin = (struct sockaddr_in *) &(q.from);
|
||||||
|
printf("RX: client %s, type %d, name %s\n", inet_ntoa(tempin->sin_addr), q.type, q.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (q.type) {
|
||||||
|
case T_NULL:
|
||||||
|
handle_null_request(tun_fd, dns_fd, &q);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -349,36 +403,28 @@ tunnel(int tun_fd, int dns_fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
read_dns(int fd, struct query *q, char *buf, int buflen)
|
read_dns(int fd, struct query *q)
|
||||||
{
|
{
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
char packet[64*1024];
|
char packet[64*1024];
|
||||||
char *domain;
|
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
int rv;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
addrlen = sizeof(struct sockaddr);
|
addrlen = sizeof(struct sockaddr);
|
||||||
r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
|
r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
|
||||||
|
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
dns_decode(buf, buflen, q, QR_QUERY, packet, r);
|
dns_decode(NULL, 0, q, QR_QUERY, packet, r);
|
||||||
domain = strstr(q->name, topdomain);
|
|
||||||
if (domain) {
|
|
||||||
rv = (int) (domain - q->name);
|
|
||||||
memcpy(buf, q->name, MIN(rv, buflen));
|
|
||||||
q->fromlen = addrlen;
|
|
||||||
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
|
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
|
||||||
} else {
|
q->fromlen = addrlen;
|
||||||
rv = 0;
|
|
||||||
}
|
return strlen(q->name);
|
||||||
} else if (r < 0) {
|
} else if (r < 0) {
|
||||||
/* Error */
|
/* Error */
|
||||||
warn("read dns");
|
warn("read dns");
|
||||||
rv = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -389,6 +435,13 @@ write_dns(int fd, struct query *q, char *data, int datalen)
|
||||||
|
|
||||||
len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, data, datalen);
|
len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, data, datalen);
|
||||||
|
|
||||||
|
if (debug >= 1) {
|
||||||
|
struct sockaddr_in *tempin;
|
||||||
|
tempin = (struct sockaddr_in *) &(q->from);
|
||||||
|
printf("TX: client %s, type %d, name %s, %d bytes data\n",
|
||||||
|
inet_ntoa(tempin->sin_addr), q->type, q->name, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen);
|
sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +449,7 @@ static void
|
||||||
usage() {
|
usage() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] [-m mtu] "
|
printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] [-t chrootdir] [-d device] [-m mtu] "
|
||||||
"[-l ip address to listen on] [-p port] [-P password]"
|
"[-l ip address to listen on] [-p port] [-P password]"
|
||||||
" tunnel_ip topdomain\n", __progname);
|
" tunnel_ip topdomain\n", __progname);
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -407,12 +460,15 @@ help() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
printf("iodine IP over DNS tunneling server\n");
|
printf("iodine IP over DNS tunneling server\n");
|
||||||
printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] [-m mtu] "
|
printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] [-t chrootdir] [-d device] [-m mtu] "
|
||||||
"[-l ip address to listen on] [-p port] [-P password]"
|
"[-l ip address to listen on] [-p port] [-P password]"
|
||||||
" tunnel_ip topdomain\n", __progname);
|
" tunnel_ip topdomain\n", __progname);
|
||||||
printf(" -v to print version info and exit\n");
|
printf(" -v to print version info and exit\n");
|
||||||
printf(" -h to print this help and exit\n");
|
printf(" -h to print this help and exit\n");
|
||||||
|
printf(" -c to disable check of client IP/port on each request\n");
|
||||||
|
printf(" -s to skip creating and configuring the tun device which then has to be created manually\n");
|
||||||
printf(" -f to keep running in foreground\n");
|
printf(" -f to keep running in foreground\n");
|
||||||
|
printf(" -D to increase debug level\n");
|
||||||
printf(" -u name to drop privileges and run as user 'name'\n");
|
printf(" -u name to drop privileges and run as user 'name'\n");
|
||||||
printf(" -t dir to chroot to directory dir\n");
|
printf(" -t dir to chroot to directory dir\n");
|
||||||
printf(" -d device to set tunnel device name\n");
|
printf(" -d device to set tunnel device name\n");
|
||||||
|
@ -428,7 +484,7 @@ help() {
|
||||||
static void
|
static void
|
||||||
version() {
|
version() {
|
||||||
printf("iodine IP over DNS tunneling server\n");
|
printf("iodine IP over DNS tunneling server\n");
|
||||||
printf("version: 0.4.1 from 2007-11-30\n");
|
printf("version: 0.4.2 from 2008-08-06\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,6 +502,7 @@ main(int argc, char **argv)
|
||||||
int choice;
|
int choice;
|
||||||
int port;
|
int port;
|
||||||
int mtu;
|
int mtu;
|
||||||
|
int skipipconfig;
|
||||||
|
|
||||||
username = NULL;
|
username = NULL;
|
||||||
newroot = NULL;
|
newroot = NULL;
|
||||||
|
@ -454,23 +511,43 @@ main(int argc, char **argv)
|
||||||
mtu = 1024;
|
mtu = 1024;
|
||||||
listen_ip = INADDR_ANY;
|
listen_ip = INADDR_ANY;
|
||||||
port = 53;
|
port = 53;
|
||||||
|
check_ip = 1;
|
||||||
|
skipipconfig = 0;
|
||||||
|
debug = 0;
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
|
__progname = strrchr(argv[0], '/');
|
||||||
|
if (__progname == NULL)
|
||||||
|
__progname = argv[0];
|
||||||
|
else
|
||||||
|
__progname++;
|
||||||
|
#endif
|
||||||
|
|
||||||
memset(password, 0, sizeof(password));
|
memset(password, 0, sizeof(password));
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
while ((choice = getopt(argc, argv, "vfhu:t:d:m:l:p:P:")) != -1) {
|
while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:P:")) != -1) {
|
||||||
switch(choice) {
|
switch(choice) {
|
||||||
case 'v':
|
case 'v':
|
||||||
version();
|
version();
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
check_ip = 0;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
skipipconfig = 1;
|
||||||
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
foreground = 1;
|
foreground = 1;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help();
|
||||||
break;
|
break;
|
||||||
|
case 'D':
|
||||||
|
debug++;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
username = optarg;
|
username = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -488,10 +565,6 @@ 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));
|
||||||
|
@ -518,8 +591,13 @@ main(int argc, char **argv)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
topdomain = strdup(argv[1]);
|
topdomain = strdup(argv[1]);
|
||||||
if (strlen(topdomain) > 128 || topdomain[0] == '.') {
|
if(strlen(topdomain) <= 128) {
|
||||||
warnx("Use a topdomain max 128 chars long. Do not start it with a dot.\n");
|
if(check_topdomain(topdomain)) {
|
||||||
|
warnx("Topdomain contains invalid characters.\n");
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warnx("Use a topdomain max 128 chars long.\n");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,11 +608,27 @@ 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 (debug) {
|
||||||
|
printf("Debug level %d enabled, will stay in foreground.\n", debug);
|
||||||
|
printf("Add more -D switches to set higher debug level.\n");
|
||||||
|
foreground = 1;
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
@ -545,6 +639,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
if ((tun_fd = open_tun(device)) == -1)
|
if ((tun_fd = open_tun(device)) == -1)
|
||||||
goto cleanup0;
|
goto cleanup0;
|
||||||
|
if (!skipipconfig)
|
||||||
if (tun_setip(argv[0]) != 0 || tun_setmtu(mtu) != 0)
|
if (tun_setip(argv[0]) != 0 || tun_setmtu(mtu) != 0)
|
||||||
goto cleanup1;
|
goto cleanup1;
|
||||||
if ((dnsd_fd = open_dns(port, listen_ip)) == -1)
|
if ((dnsd_fd = open_dns(port, listen_ip)) == -1)
|
||||||
|
@ -564,7 +659,9 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
signal(SIGINT, sigint);
|
signal(SIGINT, sigint);
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
gid_t gids[1];
|
||||||
|
gids[0] = pw->pw_gid;
|
||||||
|
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
||||||
warnx("Could not switch to user %s!\n", username);
|
warnx("Could not switch to user %s!\n", username);
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
link)
|
||||||
|
|
||||||
|
case `uname` in
|
||||||
|
SunOS | solaris)
|
||||||
|
echo '-lsocket -lnsl';
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
|
@ -25,8 +25,7 @@ struct user {
|
||||||
time_t last_pkt;
|
time_t last_pkt;
|
||||||
int seed;
|
int seed;
|
||||||
in_addr_t tun_ip;
|
in_addr_t tun_ip;
|
||||||
struct sockaddr host;
|
struct in_addr host;
|
||||||
int addrlen;
|
|
||||||
struct query q;
|
struct query q;
|
||||||
struct packet inpacket;
|
struct packet inpacket;
|
||||||
struct packet outpacket;
|
struct packet outpacket;
|
||||||
|
|
|
@ -21,6 +21,6 @@ $(TEST): $(OBJS) $(SRCOBJS)
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning..."
|
@echo "Cleaning tests/"
|
||||||
@rm -f *~ *.core $(TEST) $(OBJS)
|
@rm -f *~ *.core $(TEST) $(OBJS)
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ START_TEST(test_base32_encode)
|
||||||
|
|
||||||
fail_unless(val > 0, strerror(errno));
|
fail_unless(val > 0, strerror(errno));
|
||||||
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
||||||
va_str("'%s' != '%s'", buf, testpairs[i].b));
|
"'%s' != '%s'", buf, testpairs[i].b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -66,7 +66,7 @@ START_TEST(test_base32_decode)
|
||||||
fail_unless(val > 0, strerror(errno));
|
fail_unless(val > 0, strerror(errno));
|
||||||
fail_unless(buf != NULL, "buf == NULL");
|
fail_unless(buf != NULL, "buf == NULL");
|
||||||
fail_unless(strcmp(buf, testpairs[i].a) == 0,
|
fail_unless(strcmp(buf, testpairs[i].a) == 0,
|
||||||
va_str("'%s' != '%s'", buf, testpairs[i].a));
|
"'%s' != '%s'", buf, testpairs[i].a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
|
@ -75,7 +75,7 @@ START_TEST(test_base64_encode)
|
||||||
|
|
||||||
fail_unless(val > 0, strerror(errno));
|
fail_unless(val > 0, strerror(errno));
|
||||||
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
||||||
va_str("'%s' != '%s'", buf, testpairs[i].b));
|
"'%s' != '%s'", buf, testpairs[i].b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -94,7 +94,7 @@ START_TEST(test_base64_decode)
|
||||||
fail_unless(val > 0, strerror(errno));
|
fail_unless(val > 0, strerror(errno));
|
||||||
fail_unless(buf != NULL, "buf == NULL");
|
fail_unless(buf != NULL, "buf == NULL");
|
||||||
fail_unless(strcmp(buf, testpairs[i].a) == 0,
|
fail_unless(strcmp(buf, testpairs[i].a) == 0,
|
||||||
va_str("'%s' != '%s'", buf, testpairs[i].a));
|
"'%s' != '%s'", buf, testpairs[i].a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
|
@ -88,7 +88,7 @@ START_TEST(test_encode_query)
|
||||||
dump_packet(buf, ret);
|
dump_packet(buf, ret);
|
||||||
}
|
}
|
||||||
fail_unless(strncmp(queryPacket, buf, sizeof(queryPacket)) == 0, "Did not compile expected packet");
|
fail_unless(strncmp(queryPacket, buf, sizeof(queryPacket)) == 0, "Did not compile expected packet");
|
||||||
fail_unless(ret == len, va_str("Bad packet length: %d, expected %d", ret, len));
|
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ START_TEST(test_decode_query)
|
||||||
unpack_data(buf, len, &(q.name[1]), (int) (domain - q.name) - 1, enc);
|
unpack_data(buf, len, &(q.name[1]), (int) (domain - q.name) - 1, enc);
|
||||||
|
|
||||||
fail_unless(strncmp(buf, innerData, strlen(innerData)) == 0, "Did not extract expected host: '%s'", buf);
|
fail_unless(strncmp(buf, innerData, strlen(innerData)) == 0, "Did not extract expected host: '%s'", buf);
|
||||||
fail_unless(strlen(buf) == strlen(innerData), va_str("Bad host length: %d, expected %d: '%s'", strlen(buf), strlen(innerData), buf));
|
fail_unless(strlen(buf) == strlen(innerData), "Bad host length: %d, expected %d: '%s'", strlen(buf), strlen(innerData), buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ START_TEST(test_encode_response)
|
||||||
len = sizeof(answerPacket) - 1; /* Skip extra null character */
|
len = sizeof(answerPacket) - 1; /* Skip extra null character */
|
||||||
|
|
||||||
fail_unless(strncmp(answerPacket, buf, sizeof(answerPacket)) == 0, "Did not compile expected packet");
|
fail_unless(strncmp(answerPacket, buf, sizeof(answerPacket)) == 0, "Did not compile expected packet");
|
||||||
fail_unless(ret == len, va_str("Bad packet length: %d, expected %d", ret, len));
|
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ START_TEST(test_decode_response)
|
||||||
|
|
||||||
ret = dns_decode(buf, len, NULL, QR_ANSWER, answerPacket, sizeof(answerPacket)-1);
|
ret = dns_decode(buf, len, NULL, QR_ANSWER, answerPacket, sizeof(answerPacket)-1);
|
||||||
fail_unless(strncmp(msgData, buf, sizeof(msgData)) == 0, "Did not extract expected data");
|
fail_unless(strncmp(msgData, buf, sizeof(msgData)) == 0, "Did not extract expected data");
|
||||||
fail_unless(ret == strlen(msgData), va_str("Bad data length: %d, expected %d", ret, strlen(msgData)));
|
fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ START_TEST(test_inline_dotify)
|
||||||
inline_dotify(b, sizeof(temp));
|
inline_dotify(b, sizeof(temp));
|
||||||
|
|
||||||
fail_unless(strcmp(dottests[i].b, temp) == 0,
|
fail_unless(strcmp(dottests[i].b, temp) == 0,
|
||||||
va_str("'%s' != '%s'", temp, dottests[i].b));
|
"'%s' != '%s'", temp, dottests[i].b);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ START_TEST(test_inline_undotify)
|
||||||
inline_undotify(b, sizeof(temp));
|
inline_undotify(b, sizeof(temp));
|
||||||
|
|
||||||
fail_unless(strcmp(dottests[i].a, temp) == 0,
|
fail_unless(strcmp(dottests[i].a, temp) == 0,
|
||||||
va_str("'%s' != '%s'", temp, dottests[i].a));
|
"'%s' != '%s'", temp, dottests[i].a);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
tests/read.c
14
tests/read.c
|
@ -45,14 +45,14 @@ START_TEST(test_read_putshort)
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
putshort(&p, i);
|
putshort(&p, i);
|
||||||
fail_unless(ntohs(k) == i,
|
fail_unless(ntohs(k) == i,
|
||||||
va_str("Bad value on putshort for %d: %d != %d",
|
"Bad value on putshort for %d: %d != %d",
|
||||||
i, ntohs(k), i));
|
i, ntohs(k), i);
|
||||||
|
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
readshort(NULL, &p, (short *) &l);
|
readshort(NULL, &p, (short *) &l);
|
||||||
fail_unless(l == i,
|
fail_unless(l == i,
|
||||||
va_str("Bad value on readshort for %d: %d != %d",
|
"Bad value on readshort for %d: %d != %d",
|
||||||
i, l, i));
|
i, l, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -72,13 +72,13 @@ START_TEST(test_read_putlong)
|
||||||
putlong(&p, j);
|
putlong(&p, j);
|
||||||
|
|
||||||
fail_unless(ntohl(k) == j,
|
fail_unless(ntohl(k) == j,
|
||||||
va_str("Bad value on putlong for %d: %d != %d", i, ntohl(j), j));
|
"Bad value on putlong for %d: %d != %d", i, ntohl(j), j);
|
||||||
|
|
||||||
p = (char*)&k;
|
p = (char*)&k;
|
||||||
readlong(NULL, &p, &l);
|
readlong(NULL, &p, &l);
|
||||||
|
|
||||||
fail_unless(l == j,
|
fail_unless(l == j,
|
||||||
va_str("Bad value on readlong for %d: %d != %d", i, l, j));
|
"Bad value on readlong for %d: %d != %d", i, l, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -159,7 +159,7 @@ START_TEST(test_read_name)
|
||||||
|
|
||||||
fail_unless(rv == 4, NULL);
|
fail_unless(rv == 4, NULL);
|
||||||
fail_unless(strcmp("BA.", buf) == 0,
|
fail_unless(strcmp("BA.", buf) == 0,
|
||||||
va_str("buf is not BA: %s", buf));
|
"buf is not BA: %s", buf);
|
||||||
}
|
}
|
||||||
free(jumper);
|
free(jumper);
|
||||||
}
|
}
|
||||||
|
|
16
tests/test.c
16
tests/test.c
|
@ -22,20 +22,6 @@
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
char *
|
|
||||||
va_str(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
static char buf[512];
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
@ -68,7 +54,7 @@ main()
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
runner = srunner_create(iodine);
|
runner = srunner_create(iodine);
|
||||||
srunner_run_all(runner, CK_VERBOSE);
|
srunner_run_all(runner, CK_MINIMAL);
|
||||||
failed = srunner_ntests_failed(runner);
|
failed = srunner_ntests_failed(runner);
|
||||||
|
|
||||||
srunner_free(runner);
|
srunner_free(runner);
|
||||||
|
|
Loading…
Reference in New Issue