mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-23 16:49:19 +02:00
Release 0.5.1
This commit is contained in:
parent
f41c4bb9f3
commit
6536fc7c5d
15
CHANGELOG
15
CHANGELOG
|
@ -5,6 +5,21 @@ iodine - http://code.kryo.se/iodine
|
||||||
|
|
||||||
CHANGES:
|
CHANGES:
|
||||||
|
|
||||||
|
2009-03-21: 0.5.1 "Boringo"
|
||||||
|
- Added initial Windows support, fixes #43.
|
||||||
|
- Added length check of autoprobe responses
|
||||||
|
- Refactored and added unit tests
|
||||||
|
- Added syslog logging for iodined on version and login packets
|
||||||
|
- Fixed segfault when encoding just one block, fixes #51.
|
||||||
|
The normal code was never affected by this.
|
||||||
|
- Added win32 code to read DNS server from system, fixes #45.
|
||||||
|
- Disabled password echo on win32, fixes #44.
|
||||||
|
- Fix encoding error making all autoprobing > 1024 bytes fail, #52.
|
||||||
|
- Increase default interface MTU to 1200.
|
||||||
|
- Fix autoprobing error making every third probe fail, set IP flag
|
||||||
|
Dont-Fragment where supported. Fixes #54.
|
||||||
|
- Added TAP32 version 0901 as accepted (#53).
|
||||||
|
|
||||||
2009-01-23: 0.5.0 "iPassed"
|
2009-01-23: 0.5.0 "iPassed"
|
||||||
- Fixed segfault in server when sending version reject.
|
- Fixed segfault in server when sending version reject.
|
||||||
- Applied patch to make iodine build on BeOS R5-BONE and Haiku,
|
- Applied patch to make iodine build on BeOS R5-BONE and Haiku,
|
||||||
|
|
23
Makefile
23
Makefile
|
@ -14,8 +14,25 @@ MKDIR_FLAGS=-p
|
||||||
RM=rm
|
RM=rm
|
||||||
RM_FLAGS=-f
|
RM_FLAGS=-f
|
||||||
|
|
||||||
|
TARGETOS = `uname`
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@(cd src; $(MAKE) all)
|
@(cd src; $(MAKE) TARGETOS=$(TARGETOS) all)
|
||||||
|
|
||||||
|
cross-mingw:
|
||||||
|
@(cd src; $(MAKE) TARGETOS=windows32 CC=i686-mingw32-gcc all)
|
||||||
|
|
||||||
|
cross-mingw-dist: cross-mingw
|
||||||
|
@rm -rf iodine-latest-win32*
|
||||||
|
@mkdir -p iodine-latest-win32/bin
|
||||||
|
@for i in `ls bin`; do cp bin/$$i iodine-latest-win32/bin/$$i.exe; done
|
||||||
|
@cp /usr/i686-mingw32/usr/bin/zlib1.dll iodine-latest-win32/bin
|
||||||
|
@cp README* CH* TO* iodine-latest-win32
|
||||||
|
@echo "Create date: " > iodine-latest-win32/VERSION
|
||||||
|
@date >> iodine-latest-win32/VERSION
|
||||||
|
@echo "SVN version: " >> iodine-latest-win32/VERSION
|
||||||
|
@svnversion >> iodine-latest-win32/VERSION
|
||||||
|
@zip -r iodine-latest-win32.zip iodine-latest-win32
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(sbindir)
|
$(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(sbindir)
|
||||||
|
@ -35,11 +52,11 @@ 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) TARGETOS=$(TARGETOS) all)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning..."
|
@echo "Cleaning..."
|
||||||
@(cd src; $(MAKE) clean)
|
@(cd src; $(MAKE) clean)
|
||||||
@(cd tests; $(MAKE) clean)
|
@(cd tests; $(MAKE) clean)
|
||||||
@rm -rf bin
|
@rm -rf bin iodine-latest-win32*
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
|
||||||
|
iodine - http://code.kryo.se/iodine
|
||||||
|
|
||||||
|
***********************************
|
||||||
|
|
||||||
|
Extra README file for Win32 related stuff
|
||||||
|
|
||||||
|
|
||||||
|
== Running iodine on Windows:
|
||||||
|
1. Install the TAP32 driver
|
||||||
|
http://openvpn.net/index.php/downloads.html
|
||||||
|
choose OpenVPN 2.0.9 Windows Installer, when installing you can
|
||||||
|
select to install only the TAP driver.
|
||||||
|
|
||||||
|
2. Have one TAP32 interface installed
|
||||||
|
|
||||||
|
3. Name the interface "dns"
|
||||||
|
|
||||||
|
4. Make sure the interface does not have a default gateway set
|
||||||
|
|
||||||
|
5. Run iodine/iodined as normal.
|
||||||
|
|
||||||
|
6. Enjoy!
|
||||||
|
|
||||||
|
|
||||||
|
== Building on Windows:
|
||||||
|
You need:
|
||||||
|
MinGW, MSYS, GCC, zlib
|
||||||
|
|
||||||
|
Then just run make
|
||||||
|
|
||||||
|
|
||||||
|
== Cross-compiling for MinGW:
|
||||||
|
You need:
|
||||||
|
MinGW crosscompiler, crosscompiled zlib
|
||||||
|
|
||||||
|
Then run "make cross-mingw"
|
||||||
|
Note that the binaries will not get a .exe suffix
|
||||||
|
|
||||||
|
|
||||||
|
== Zlib download
|
||||||
|
You can get zlib for MinGW here (both for native and crosscompile):
|
||||||
|
http://code.kryo.se/iodine/deps/zlib.zip
|
||||||
|
Unzip it in your MinGW directory on Windows or in $ROOT/usr for
|
||||||
|
cross-compile.
|
||||||
|
|
||||||
|
|
||||||
|
== Results of crappy Win32 API:
|
||||||
|
The following fixable limitations apply:
|
||||||
|
- Exactly one TAP32 interface must be installed
|
||||||
|
- The TAP32 interface must be named "dns" and be version 0801 or 0901
|
||||||
|
- Server cannot read packet destination address
|
||||||
|
|
||||||
|
The following (probably) un-fixable limitations apply:
|
||||||
|
- A password entered as -P argument can be shown in process list
|
||||||
|
- Priviligies cannot be dropped
|
||||||
|
- chroot() cannot be used
|
||||||
|
- Detaching from terminal not possible
|
||||||
|
- Server on windows must be run with /30 netmask
|
||||||
|
- Client can only talk to server, not other clients
|
||||||
|
|
|
@ -5,11 +5,12 @@ CLIENT = ../bin/iodine
|
||||||
SERVEROBJS = iodined.o user.o fw_query.o
|
SERVEROBJS = iodined.o user.o fw_query.o
|
||||||
SERVER = ../bin/iodined
|
SERVER = ../bin/iodined
|
||||||
|
|
||||||
OS = `uname | tr "a-z" "A-Z"`
|
OS = `echo $(TARGETOS) | tr "a-z" "A-Z"`
|
||||||
ARCH = `uname -m`
|
ARCH = `uname -m`
|
||||||
|
|
||||||
LDFLAGS = -lz `sh osflags link`
|
LIBPATH = -L.
|
||||||
CFLAGS = -c -g -Wall -D$(OS) -pedantic `sh osflags cflags`
|
LDFLAGS = -lz `sh osflags $(TARGETOS) link` $(LIBPATH)
|
||||||
|
CFLAGS = -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags`
|
||||||
|
|
||||||
all: stateos $(CLIENT) $(SERVER)
|
all: stateos $(CLIENT) $(SERVER)
|
||||||
|
|
||||||
|
@ -32,5 +33,5 @@ $(SERVER): $(COMMONOBJS) $(SERVEROBJS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning src/"
|
@echo "Cleaning src/"
|
||||||
@rm -f $(CLIENT) $(SERVER) *~ *.o *.core
|
@rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core
|
||||||
|
|
||||||
|
|
46
src/base32.c
46
src/base32.c
|
@ -27,7 +27,6 @@
|
||||||
static const char cb32[] =
|
static const char cb32[] =
|
||||||
"abcdefghijklmnopqrstuvwxyz012345";
|
"abcdefghijklmnopqrstuvwxyz012345";
|
||||||
static unsigned char rev32[128];
|
static unsigned char rev32[128];
|
||||||
static int reverse_init = 0;
|
|
||||||
|
|
||||||
static int base32_decode(void *, size_t *, const char *, size_t);
|
static int base32_decode(void *, size_t *, const char *, size_t);
|
||||||
static int base32_encode(char *, size_t *, const void *, size_t);
|
static int base32_encode(char *, size_t *, const void *, size_t);
|
||||||
|
@ -70,6 +69,22 @@ base32_blksize_enc()
|
||||||
return BLKSIZE_ENC;
|
return BLKSIZE_ENC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
base32_reverse_init()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char c;
|
||||||
|
static int reverse_init = 0;
|
||||||
|
|
||||||
|
if (!reverse_init) {
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
c = cb32[i];
|
||||||
|
rev32[(int) c] = i;
|
||||||
|
}
|
||||||
|
reverse_init = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
b32_5to8(int in)
|
b32_5to8(int in)
|
||||||
{
|
{
|
||||||
|
@ -79,15 +94,7 @@ b32_5to8(int in)
|
||||||
int
|
int
|
||||||
b32_8to5(int in)
|
b32_8to5(int in)
|
||||||
{
|
{
|
||||||
int i;
|
base32_reverse_init();
|
||||||
int c;
|
|
||||||
if (!reverse_init) {
|
|
||||||
for (i = 0; i < 32; i++) {
|
|
||||||
c = cb32[i];
|
|
||||||
rev32[(int) c] = i;
|
|
||||||
}
|
|
||||||
reverse_init = 1;
|
|
||||||
}
|
|
||||||
return rev32[in];
|
return rev32[in];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,9 +110,12 @@ base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
memset(buf, 0, *buflen);
|
memset(buf, 0, *buflen);
|
||||||
|
|
||||||
/* how many chars can we encode within the buf */
|
/* how many chars can we encode within the buf */
|
||||||
maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC - 1) - 1;
|
maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC);
|
||||||
/* how big will the encoded data be */
|
/* how big will the encoded data be */
|
||||||
newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW + 1) + 1;
|
newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW);
|
||||||
|
if (size % BLKSIZE_RAW) {
|
||||||
|
newsize += BLKSIZE_ENC;
|
||||||
|
}
|
||||||
/* if the buffer is too small, eat some of the data */
|
/* if the buffer is too small, eat some of the data */
|
||||||
if (*buflen < newsize) {
|
if (*buflen < newsize) {
|
||||||
size = maxsize;
|
size = maxsize;
|
||||||
|
@ -132,7 +142,7 @@ base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
/* store number of bytes from data that was used */
|
/* store number of bytes from data that was used */
|
||||||
*buflen = size;
|
*buflen = size;
|
||||||
|
|
||||||
return strlen(buf) - 1;
|
return strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECODE_ERROR 0xffffffff
|
#define DECODE_ERROR 0xffffffff
|
||||||
|
@ -183,17 +193,9 @@ base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||||
size_t newsize;
|
size_t newsize;
|
||||||
size_t maxsize;
|
size_t maxsize;
|
||||||
const char *p;
|
const char *p;
|
||||||
unsigned char c;
|
|
||||||
int len;
|
int len;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!reverse_init) {
|
base32_reverse_init();
|
||||||
for (i = 0; i < 32; i++) {
|
|
||||||
c = cb32[i];
|
|
||||||
rev32[(int) c] = i;
|
|
||||||
}
|
|
||||||
reverse_init = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* chars needed to decode slen */
|
/* chars needed to decode slen */
|
||||||
newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1;
|
newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1;
|
||||||
|
|
19
src/base64.c
19
src/base64.c
|
@ -78,7 +78,6 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
size_t newsize;
|
size_t newsize;
|
||||||
size_t maxsize;
|
size_t maxsize;
|
||||||
unsigned char c;
|
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
unsigned char *q;
|
unsigned char *q;
|
||||||
|
@ -86,18 +85,14 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
|
|
||||||
memset(buf, 0, *buflen);
|
memset(buf, 0, *buflen);
|
||||||
|
|
||||||
if (!reverse_init) {
|
/* how many chars can we encode within the buf */
|
||||||
for (i = 0; i < 64; i++) {
|
maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC);
|
||||||
c = cb64[i];
|
/* how big will the encoded data be */
|
||||||
rev64[(int) c] = i;
|
newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW);
|
||||||
}
|
if (size % BLKSIZE_RAW) {
|
||||||
reverse_init = 1;
|
newsize += BLKSIZE_ENC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* how many chars can we encode within the buf */
|
|
||||||
maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC - 1) - 1;
|
|
||||||
/* how big will the encoded data be */
|
|
||||||
newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW + 1) + 1;
|
|
||||||
/* if the buffer is too small, eat some of the data */
|
/* if the buffer is too small, eat some of the data */
|
||||||
if (*buflen < newsize) {
|
if (*buflen < newsize) {
|
||||||
size = maxsize;
|
size = maxsize;
|
||||||
|
@ -120,7 +115,7 @@ base64_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||||
/* store number of bytes from data that was used */
|
/* store number of bytes from data that was used */
|
||||||
*buflen = size;
|
*buflen = size;
|
||||||
|
|
||||||
return strlen(buf) - 1;
|
return strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECODE_ERROR 0xffffffff
|
#define DECODE_ERROR 0xffffffff
|
||||||
|
|
150
src/common.c
150
src/common.c
|
@ -14,14 +14,7 @@
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <arpa/nameser.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#ifdef DARWIN
|
|
||||||
#include <arpa/nameser8_compat.h>
|
|
||||||
#endif
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <err.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -33,12 +26,25 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <conio.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef DARWIN
|
||||||
|
#include <arpa/nameser8_compat.h>
|
||||||
|
#endif
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
|
/* daemon(3) exists only in 4.4BSD or later, and in GNU libc */
|
||||||
#if !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
|
#if !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__)
|
||||||
static int daemon(int nochdir, int noclose)
|
static int daemon(int nochdir, int noclose)
|
||||||
{
|
{
|
||||||
int fd, i;
|
int fd, i;
|
||||||
|
@ -82,11 +88,24 @@ int setgroups(int count, int *groups)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
check_superuser(void (*usage_fn)(void))
|
||||||
|
{
|
||||||
|
#ifndef WINDOWS32
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
warnx("Run as root and you'll be happy.\n");
|
||||||
|
usage_fn();
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
open_dns(int localport, in_addr_t listen_ip)
|
open_dns(int localport, in_addr_t listen_ip)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int flag;
|
int flag = 1;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
@ -95,22 +114,32 @@ open_dns(int localport, in_addr_t listen_ip)
|
||||||
/* listen_ip already in network byte order from inet_addr, or 0 */
|
/* listen_ip already in network byte order from inet_addr, or 0 */
|
||||||
addr.sin_addr.s_addr = listen_ip;
|
addr.sin_addr.s_addr = listen_ip;
|
||||||
|
|
||||||
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||||
|
fprintf(stderr, "got fd %d\n", fd);
|
||||||
err(1, "socket");
|
err(1, "socket");
|
||||||
|
}
|
||||||
|
|
||||||
flag = 1;
|
flag = 1;
|
||||||
#ifdef SO_REUSEPORT
|
#ifdef SO_REUSEPORT
|
||||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag));
|
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag));
|
||||||
#endif
|
#endif
|
||||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
|
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag));
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
|
/* To get destination address from each UDP datagram, see iodined.c:read_dns() */
|
||||||
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, &flag, sizeof(flag));
|
setsockopt(fd, IPPROTO_IP, DSTADDR_SOCKOPT, (const void*) &flag, sizeof(flag));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IP_OPT_DONT_FRAG
|
||||||
|
/* Set dont-fragment ip header flag */
|
||||||
|
flag = DONT_FRAG_VALUE;
|
||||||
|
setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag));
|
||||||
|
#endif
|
||||||
|
|
||||||
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||||
err(1, "bind");
|
err(1, "bind");
|
||||||
|
|
||||||
printf("Opened UDP socket\n");
|
fprintf(stderr, "Opened UDP socket\n");
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +153,7 @@ close_dns(int fd)
|
||||||
void
|
void
|
||||||
do_chroot(char *newroot)
|
do_chroot(char *newroot)
|
||||||
{
|
{
|
||||||
#if !defined(__BEOS__) || defined(__HAIKU__)
|
#if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__))
|
||||||
if (chroot(newroot) != 0 || chdir("/") != 0)
|
if (chroot(newroot) != 0 || chdir("/") != 0)
|
||||||
err(1, "%s", newroot);
|
err(1, "%s", newroot);
|
||||||
|
|
||||||
|
@ -138,31 +167,54 @@ do_chroot(char *newroot)
|
||||||
void
|
void
|
||||||
do_detach()
|
do_detach()
|
||||||
{
|
{
|
||||||
printf("Detaching from terminal...\n");
|
#ifndef WINDOWS32
|
||||||
|
fprintf(stderr, "Detaching from terminal...\n");
|
||||||
daemon(0, 0);
|
daemon(0, 0);
|
||||||
umask(0);
|
umask(0);
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "Windows version does not support detaching\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
read_password(char *buf, size_t len)
|
read_password(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
char pwd[80];
|
||||||
|
#ifndef WINDOWS32
|
||||||
struct termios old;
|
struct termios old;
|
||||||
struct termios tp;
|
struct termios tp;
|
||||||
char pwd[80];
|
|
||||||
|
|
||||||
tcgetattr(0, &tp);
|
tcgetattr(0, &tp);
|
||||||
old = tp;
|
old = tp;
|
||||||
|
|
||||||
tp.c_lflag &= (~ECHO);
|
tp.c_lflag &= (~ECHO);
|
||||||
tcsetattr(0, TCSANOW, &tp);
|
tcsetattr(0, TCSANOW, &tp);
|
||||||
|
#else
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("Enter password: ");
|
fprintf(stderr, "Enter password: ");
|
||||||
fflush(stdout);
|
fflush(stderr);
|
||||||
|
#ifndef WINDOWS32
|
||||||
scanf("%79s", pwd);
|
scanf("%79s", pwd);
|
||||||
printf("\n");
|
#else
|
||||||
|
for (i = 0; i < sizeof(pwd); i++) {
|
||||||
|
pwd[i] = getch();
|
||||||
|
if (pwd[i] == '\r' || pwd[i] == '\n') {
|
||||||
|
pwd[i] = 0;
|
||||||
|
break;
|
||||||
|
} else if (pwd[i] == '\b') {
|
||||||
|
i--; /* Remove the \b char */
|
||||||
|
if (i >=0) i--; /* If not first char, remove one more */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
tcsetattr(0, TCSANOW, &old);
|
tcsetattr(0, TCSANOW, &old);
|
||||||
|
#endif
|
||||||
|
|
||||||
strncpy(buf, pwd, len);
|
strncpy(buf, pwd, len);
|
||||||
buf[len-1] = '\0';
|
buf[len-1] = '\0';
|
||||||
|
@ -184,3 +236,61 @@ check_topdomain(char *str)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
int
|
||||||
|
inet_aton(const char *cp, struct in_addr *inp)
|
||||||
|
{
|
||||||
|
inp->s_addr = inet_addr(cp);
|
||||||
|
return inp->s_addr != INADDR_ANY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
warn(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list list;
|
||||||
|
|
||||||
|
va_start(list, fmt);
|
||||||
|
if (fmt) fprintf(stderr, fmt, list);
|
||||||
|
if (errno == 0) {
|
||||||
|
fprintf(stderr, ": WSA error %d\n", WSAGetLastError());
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, ": %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
va_end(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
warnx(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list list;
|
||||||
|
|
||||||
|
va_start(list, fmt);
|
||||||
|
if (fmt) fprintf(stderr, fmt, list);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
err(int eval, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list list;
|
||||||
|
|
||||||
|
va_start(list, fmt);
|
||||||
|
warn(fmt, list);
|
||||||
|
va_end(list);
|
||||||
|
exit(eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
errx(int eval, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list list;
|
||||||
|
|
||||||
|
va_start(list, fmt);
|
||||||
|
warnx(fmt, list);
|
||||||
|
va_end(list);
|
||||||
|
exit(eval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
33
src/common.h
33
src/common.h
|
@ -17,10 +17,15 @@
|
||||||
#ifndef __COMMON_H__
|
#ifndef __COMMON_H__
|
||||||
#define __COMMON_H__
|
#define __COMMON_H__
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#ifdef WINDOWS32
|
||||||
#include <sys/types.h>
|
#include "windows.h"
|
||||||
|
#else
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||||
|
@ -39,6 +44,20 @@
|
||||||
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
|
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined IP_MTU_DISCOVER
|
||||||
|
/* Linux */
|
||||||
|
# define IP_OPT_DONT_FRAG IP_MTU_DISCOVER
|
||||||
|
# define DONT_FRAG_VALUE IP_PMTUDISC_DO
|
||||||
|
#elif defined IP_DONTFRAG
|
||||||
|
/* FreeBSD */
|
||||||
|
# define IP_OPT_DONT_FRAG IP_DONTFRAG
|
||||||
|
# define DONT_FRAG_VALUE 1
|
||||||
|
#elif defined IP_DONTFRAGMENT
|
||||||
|
/* Winsock2 */
|
||||||
|
# define IP_OPT_DONT_FRAG IP_DONTFRAGMENT
|
||||||
|
# define DONT_FRAG_VALUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
struct packet
|
struct packet
|
||||||
{
|
{
|
||||||
int len; /* Total packet length */
|
int len; /* Total packet length */
|
||||||
|
@ -58,6 +77,7 @@ struct query {
|
||||||
int fromlen;
|
int fromlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void check_superuser(void (*usage_fn)(void));
|
||||||
int open_dns(int, in_addr_t);
|
int open_dns(int, in_addr_t);
|
||||||
void close_dns(int);
|
void close_dns(int);
|
||||||
|
|
||||||
|
@ -68,4 +88,13 @@ void read_password(char*, size_t);
|
||||||
|
|
||||||
int check_topdomain(char *);
|
int check_topdomain(char *);
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
int inet_aton(const char *cp, struct in_addr *inp);
|
||||||
|
|
||||||
|
void err(int eval, const char *fmt, ...);
|
||||||
|
void warn(const char *fmt, ...);
|
||||||
|
void errx(int eval, const char *fmt, ...);
|
||||||
|
void warnx(const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
20
src/dns.c
20
src/dns.c
|
@ -14,13 +14,7 @@
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <arpa/nameser.h>
|
|
||||||
#ifdef DARWIN
|
|
||||||
#include <arpa/nameser8_compat.h>
|
|
||||||
#endif
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <err.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -28,6 +22,18 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#else
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef DARWIN
|
||||||
|
#include <arpa/nameser8_compat.h>
|
||||||
|
#endif
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <err.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "read.h"
|
#include "read.h"
|
||||||
|
@ -177,7 +183,7 @@ dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomai
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
short
|
unsigned short
|
||||||
dns_get_id(char *packet, size_t packetlen)
|
dns_get_id(char *packet, size_t packetlen)
|
||||||
{
|
{
|
||||||
HEADER *header;
|
HEADER *header;
|
||||||
|
|
|
@ -26,7 +26,7 @@ typedef enum {
|
||||||
|
|
||||||
int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t);
|
int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t);
|
||||||
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain);
|
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain);
|
||||||
short dns_get_id(char *packet, size_t packetlen);
|
unsigned short dns_get_id(char *packet, size_t packetlen);
|
||||||
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
|
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
|
||||||
|
|
||||||
#endif /* _DNS_H_ */
|
#endif /* _DNS_H_ */
|
||||||
|
|
|
@ -35,7 +35,7 @@ void fw_query_put(struct fw_query *fw_query)
|
||||||
fwq_ix = 0;
|
fwq_ix = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fw_query_get(short query_id, struct fw_query **fw_query)
|
void fw_query_get(unsigned short query_id, struct fw_query **fw_query)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,24 @@
|
||||||
#define __FW_QUERY_H__
|
#define __FW_QUERY_H__
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FW_QUERY_CACHE_SIZE 16
|
#define FW_QUERY_CACHE_SIZE 16
|
||||||
|
|
||||||
struct fw_query {
|
struct fw_query {
|
||||||
struct sockaddr addr;
|
struct sockaddr addr;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
short id;
|
unsigned short id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void fw_query_init();
|
void fw_query_init();
|
||||||
void fw_query_put(struct fw_query *fw_query);
|
void fw_query_put(struct fw_query *fw_query);
|
||||||
void fw_query_get(short query_id, struct fw_query **fw_query);
|
void fw_query_get(unsigned short query_id, struct fw_query **fw_query);
|
||||||
|
|
||||||
#endif /*__FW_QUERY_H__*/
|
#endif /*__FW_QUERY_H__*/
|
||||||
|
|
||||||
|
|
346
src/iodine.c
346
src/iodine.c
|
@ -20,22 +20,28 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <err.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
#ifdef DARWIN
|
#ifdef DARWIN
|
||||||
#include <arpa/nameser8_compat.h>
|
#include <arpa/nameser8_compat.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
|
@ -46,6 +52,11 @@
|
||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
WORD req_version = MAKEWORD(2, 2);
|
||||||
|
WSADATA wsa_data;
|
||||||
|
#endif
|
||||||
|
|
||||||
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,
|
static int build_hostname(char *buf, size_t buflen,
|
||||||
|
@ -64,9 +75,6 @@ static int downstream_fragment;
|
||||||
static int down_ack_seqno;
|
static int down_ack_seqno;
|
||||||
static int down_ack_fragment;
|
static int down_ack_fragment;
|
||||||
|
|
||||||
static int max_downstream_frag_size;
|
|
||||||
static int autodetect_frag_size;
|
|
||||||
|
|
||||||
/* Current up/downstream IP packet */
|
/* Current up/downstream IP packet */
|
||||||
static struct packet outpkt;
|
static struct packet outpkt;
|
||||||
static struct packet inpkt;
|
static struct packet inpkt;
|
||||||
|
@ -132,7 +140,7 @@ build_hostname(char *buf, size_t buflen,
|
||||||
size_t space;
|
size_t space;
|
||||||
char *b;
|
char *b;
|
||||||
|
|
||||||
space = MIN(0xFF, buflen) - strlen(topdomain) - 5;
|
space = MIN(0xFF, buflen) - strlen(topdomain) - 7;
|
||||||
if (!encoder->places_dots())
|
if (!encoder->places_dots())
|
||||||
space -= (space / 57); /* space for dots */
|
space -= (space / 57); /* space for dots */
|
||||||
|
|
||||||
|
@ -424,7 +432,7 @@ send_fragsize_probe(int fd, int fragsize)
|
||||||
fragsize &= 2047;
|
fragsize &= 2047;
|
||||||
|
|
||||||
buf[0] = 'r'; /* Probe downstream fragsize packet */
|
buf[0] = 'r'; /* Probe downstream fragsize packet */
|
||||||
buf[1] = b32_5to8((userid << 1) | (fragsize & 1024));
|
buf[1] = b32_5to8((userid << 1) | ((fragsize >> 10) & 1));
|
||||||
buf[2] = b32_5to8((fragsize >> 5) & 31);
|
buf[2] = b32_5to8((fragsize >> 5) & 31);
|
||||||
buf[3] = b32_5to8(fragsize & 31);
|
buf[3] = b32_5to8(fragsize & 31);
|
||||||
|
|
||||||
|
@ -489,20 +497,15 @@ send_codec_switch(int fd, int userid, int bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handshake(int dns_fd)
|
handshake_version(int dns_fd, int *seed)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
uint32_t payload;
|
|
||||||
char server[65];
|
|
||||||
char client[65];
|
|
||||||
char login[16];
|
|
||||||
char in[4096];
|
char in[4096];
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
int read;
|
uint32_t payload;
|
||||||
int mtu;
|
|
||||||
int seed;
|
|
||||||
int i;
|
int i;
|
||||||
int r;
|
int r;
|
||||||
|
int read;
|
||||||
|
|
||||||
for (i = 0; running && i < 5; i++) {
|
for (i = 0; running && i < 5; i++) {
|
||||||
tv.tv_sec = i + 1;
|
tv.tv_sec = i + 1;
|
||||||
|
@ -533,11 +536,11 @@ handshake(int dns_fd)
|
||||||
((in[7] & 0xff)));
|
((in[7] & 0xff)));
|
||||||
|
|
||||||
if (strncmp("VACK", in, 4) == 0) {
|
if (strncmp("VACK", in, 4) == 0) {
|
||||||
seed = payload;
|
*seed = payload;
|
||||||
userid = in[8];
|
userid = in[8];
|
||||||
|
|
||||||
printf("Version ok, both using protocol v 0x%08x. You are user #%d\n", VERSION, userid);
|
fprintf(stderr, "Version ok, both using protocol v 0x%08x. You are user #%d\n", VERSION, userid);
|
||||||
goto perform_login;
|
return 0;
|
||||||
} else if (strncmp("VNAK", in, 4) == 0) {
|
} else if (strncmp("VNAK", in, 4) == 0) {
|
||||||
warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up",
|
warnx("You use protocol v 0x%08x, server uses v 0x%08x. Giving up",
|
||||||
VERSION, payload);
|
VERSION, payload);
|
||||||
|
@ -550,12 +553,26 @@ handshake(int dns_fd)
|
||||||
warnx("did not receive proper login challenge");
|
warnx("did not receive proper login challenge");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Retrying version check...\n");
|
fprintf(stderr, "Retrying version check...\n");
|
||||||
}
|
}
|
||||||
errx(1, "couldn't connect to server");
|
warnx("couldn't connect to server");
|
||||||
/* NOTREACHED */
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handshake_login(int dns_fd, int seed)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
char in[4096];
|
||||||
|
char login[16];
|
||||||
|
char server[65];
|
||||||
|
char client[65];
|
||||||
|
int mtu;
|
||||||
|
fd_set fds;
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
int read;
|
||||||
|
|
||||||
perform_login:
|
|
||||||
login_calculate(login, 16, password, seed);
|
login_calculate(login, 16, password, seed);
|
||||||
|
|
||||||
for (i=0; running && i<5 ;i++) {
|
for (i=0; running && i<5 ;i++) {
|
||||||
|
@ -580,7 +597,7 @@ perform_login:
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
int netmask;
|
int netmask;
|
||||||
if (strncmp("LNAK", in, 4) == 0) {
|
if (strncmp("LNAK", in, 4) == 0) {
|
||||||
printf("Bad password\n");
|
fprintf(stderr, "Bad password\n");
|
||||||
return 1;
|
return 1;
|
||||||
} else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d",
|
} else if (sscanf(in, "%64[^-]-%64[^-]-%d-%d",
|
||||||
server, client, &mtu, &netmask) == 4) {
|
server, client, &mtu, &netmask) == 4) {
|
||||||
|
@ -589,22 +606,32 @@ perform_login:
|
||||||
client[64] = 0;
|
client[64] = 0;
|
||||||
if (tun_setip(client, netmask) == 0 &&
|
if (tun_setip(client, netmask) == 0 &&
|
||||||
tun_setmtu(mtu) == 0) {
|
tun_setmtu(mtu) == 0) {
|
||||||
goto perform_case_check;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
warnx("Received handshake with bad data");
|
warnx("Received handshake with bad data");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Received bad handshake\n");
|
fprintf(stderr, "Received bad handshake\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Retrying login...\n");
|
fprintf(stderr, "Retrying login...\n");
|
||||||
}
|
}
|
||||||
warnx("couldn't login to server");
|
warnx("couldn't login to server");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handshake_case_check(int dns_fd)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
char in[4096];
|
||||||
|
fd_set fds;
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
int read;
|
||||||
|
|
||||||
perform_case_check:
|
|
||||||
case_preserved = 0;
|
case_preserved = 0;
|
||||||
for (i=0; running && i<5 ;i++) {
|
for (i=0; running && i<5 ;i++) {
|
||||||
tv.tv_sec = i + 1;
|
tv.tv_sec = i + 1;
|
||||||
|
@ -623,8 +650,8 @@ perform_case_check:
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
if (in[0] == 'z' || in[0] == 'Z') {
|
if (in[0] == 'z' || in[0] == 'Z') {
|
||||||
if (read < (27 * 2)) {
|
if (read < (27 * 2)) {
|
||||||
printf("Received short case check reply. Will use base32 encoder\n");
|
fprintf(stderr, "Received short case check reply. Will use base32 encoder\n");
|
||||||
goto switch_codec;
|
return;
|
||||||
} else {
|
} else {
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
|
@ -636,27 +663,35 @@ perform_case_check:
|
||||||
case_preserved = 0;
|
case_preserved = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto switch_codec;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Received bad case check reply\n");
|
fprintf(stderr, "Received bad case check reply\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Got error on case check, will use base32\n");
|
fprintf(stderr, "Got error on case check, will use base32\n");
|
||||||
goto switch_codec;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Retrying case check...\n");
|
fprintf(stderr, "Retrying case check...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("No reply on case check, continuing\n");
|
fprintf(stderr, "No reply on case check, continuing\n");
|
||||||
switch_codec:
|
}
|
||||||
if (!case_preserved)
|
|
||||||
goto autodetect_max_fragsize;
|
static void
|
||||||
|
handshake_switch_codec(int dns_fd)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
char in[4096];
|
||||||
|
fd_set fds;
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
int read;
|
||||||
|
|
||||||
dataenc = get_base64_encoder();
|
dataenc = get_base64_encoder();
|
||||||
printf("Switching to %s codec\n", dataenc->name);
|
fprintf(stderr, "Switching to %s codec\n", dataenc->name);
|
||||||
/* Send to server that this user will use base64 from now on */
|
/* Send to server that this user will use base64 from now on */
|
||||||
for (i=0; running && i<5 ;i++) {
|
for (i=0; running && i<5 ;i++) {
|
||||||
int bits;
|
int bits;
|
||||||
|
@ -677,33 +712,45 @@ switch_codec:
|
||||||
|
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
if (strncmp("BADLEN", in, 6) == 0) {
|
if (strncmp("BADLEN", in, 6) == 0) {
|
||||||
printf("Server got bad message length. ");
|
fprintf(stderr, "Server got bad message length. ");
|
||||||
goto codec_revert;
|
goto codec_revert;
|
||||||
} else if (strncmp("BADIP", in, 5) == 0) {
|
} else if (strncmp("BADIP", in, 5) == 0) {
|
||||||
printf("Server rejected sender IP address. ");
|
fprintf(stderr, "Server rejected sender IP address. ");
|
||||||
goto codec_revert;
|
goto codec_revert;
|
||||||
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
||||||
printf("Server rejected the selected codec. ");
|
fprintf(stderr, "Server rejected the selected codec. ");
|
||||||
goto codec_revert;
|
goto codec_revert;
|
||||||
}
|
}
|
||||||
in[read] = 0; /* zero terminate */
|
in[read] = 0; /* zero terminate */
|
||||||
printf("Server switched to codec %s\n", in);
|
fprintf(stderr, "Server switched to codec %s\n", in);
|
||||||
goto autodetect_max_fragsize;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Retrying codec switch...\n");
|
fprintf(stderr, "Retrying codec switch...\n");
|
||||||
}
|
}
|
||||||
printf("No reply from server on codec switch. ");
|
fprintf(stderr, "No reply from server on codec switch. ");
|
||||||
|
|
||||||
codec_revert:
|
codec_revert:
|
||||||
printf("Falling back to base32\n");
|
fprintf(stderr, "Falling back to base32\n");
|
||||||
dataenc = get_base32_encoder();
|
dataenc = get_base32_encoder();
|
||||||
autodetect_max_fragsize:
|
}
|
||||||
if (autodetect_frag_size) {
|
|
||||||
|
static int
|
||||||
|
handshake_autoprobe_fragsize(int dns_fd)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
char in[4096];
|
||||||
|
fd_set fds;
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
int read;
|
||||||
int proposed_fragsize = 768;
|
int proposed_fragsize = 768;
|
||||||
int range = 768;
|
int range = 768;
|
||||||
max_downstream_frag_size = 0;
|
int max_fragsize = 0;
|
||||||
printf("Autoprobing max downstream fragment size... (skip with -m fragsize)\n");
|
|
||||||
while (running && range > 0 && (range >= 8 || !max_downstream_frag_size)) {
|
max_fragsize = 0;
|
||||||
|
fprintf(stderr, "Autoprobing max downstream fragment size... (skip with -m fragsize)\n");
|
||||||
|
while (running && range > 0 && (range >= 8 || !max_fragsize)) {
|
||||||
for (i=0; running && i<3 ;i++) {
|
for (i=0; running && i<3 ;i++) {
|
||||||
tv.tv_sec = 1;
|
tv.tv_sec = 1;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
@ -721,40 +768,64 @@ autodetect_max_fragsize:
|
||||||
/* We got a reply */
|
/* We got a reply */
|
||||||
int acked_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
|
int acked_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
|
||||||
if (acked_fragsize == proposed_fragsize) {
|
if (acked_fragsize == proposed_fragsize) {
|
||||||
printf("%d ok.. ", acked_fragsize);
|
if (read == proposed_fragsize) {
|
||||||
fflush(stdout);
|
fprintf(stderr, "%d ok.. ", acked_fragsize);
|
||||||
max_downstream_frag_size = acked_fragsize;
|
fflush(stderr);
|
||||||
|
max_fragsize = acked_fragsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strncmp("BADIP", in, 5) == 0) {
|
||||||
|
fprintf(stderr, "got BADIP.. ");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, ".");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
range >>= 1;
|
range >>= 1;
|
||||||
|
if (max_fragsize == proposed_fragsize) {
|
||||||
|
/* Try bigger */
|
||||||
proposed_fragsize += range;
|
proposed_fragsize += range;
|
||||||
continue;
|
} else {
|
||||||
}
|
/* Try smaller */
|
||||||
}
|
fprintf(stderr, "%d not ok.. ", proposed_fragsize);
|
||||||
}
|
fflush(stderr);
|
||||||
}
|
|
||||||
printf("%d not ok.. ", proposed_fragsize);
|
|
||||||
fflush(stdout);
|
|
||||||
range >>= 1;
|
|
||||||
proposed_fragsize -= range;
|
proposed_fragsize -= range;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!running) {
|
if (!running) {
|
||||||
printf("\n");
|
fprintf(stderr, "\n");
|
||||||
warnx("stopped while autodetecting fragment size (Try probing manually with -m)");
|
warnx("stopped while autodetecting fragment size (Try probing manually with -m)");
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
if (range == 0) {
|
if (range == 0) {
|
||||||
/* Tried all the way down to 2 and found no good size */
|
/* Tried all the way down to 2 and found no good size */
|
||||||
printf("\n");
|
fprintf(stderr, "\n");
|
||||||
warnx("found no accepted fragment size. (Try probing manually with -m)");
|
warnx("found no accepted fragment size. (Try probing manually with -m)");
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
printf("will use %d\n", max_downstream_frag_size);
|
fprintf(stderr, "will use %d\n", max_fragsize);
|
||||||
}
|
return max_fragsize;
|
||||||
printf("Setting downstream fragment size to max %d...\n", max_downstream_frag_size);
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handshake_set_fragsize(int dns_fd, int fragsize)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
char in[4096];
|
||||||
|
fd_set fds;
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
int read;
|
||||||
|
|
||||||
|
fprintf(stderr, "Setting downstream fragment size to max %d...\n", fragsize);
|
||||||
for (i=0; running && i<5 ;i++) {
|
for (i=0; running && i<5 ;i++) {
|
||||||
tv.tv_sec = i + 1;
|
tv.tv_sec = i + 1;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
send_set_downstream_fragsize(dns_fd, max_downstream_frag_size);
|
send_set_downstream_fragsize(dns_fd, fragsize);
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(dns_fd, &fds);
|
FD_SET(dns_fd, &fds);
|
||||||
|
@ -768,21 +839,53 @@ autodetect_max_fragsize:
|
||||||
int accepted_fragsize;
|
int accepted_fragsize;
|
||||||
|
|
||||||
if (strncmp("BADFRAG", in, 7) == 0) {
|
if (strncmp("BADFRAG", in, 7) == 0) {
|
||||||
printf("Server rejected fragsize. Keeping default.");
|
fprintf(stderr, "Server rejected fragsize. Keeping default.");
|
||||||
goto done;
|
return;
|
||||||
} else if (strncmp("BADIP", in, 5) == 0) {
|
} else if (strncmp("BADIP", in, 5) == 0) {
|
||||||
printf("Server rejected sender IP address.\n");
|
fprintf(stderr, "Server rejected sender IP address.\n");
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
|
accepted_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff);
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Retrying set fragsize...\n");
|
fprintf(stderr, "Retrying set fragsize...\n");
|
||||||
}
|
}
|
||||||
printf("No reply from server when setting fragsize. Keeping default.\n");
|
fprintf(stderr, "No reply from server when setting fragsize. Keeping default.\n");
|
||||||
done:
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handshake(int dns_fd, int autodetect_frag_size, int fragsize)
|
||||||
|
{
|
||||||
|
int seed;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = handshake_version(dns_fd, &seed);
|
||||||
|
if (r) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = handshake_login(dns_fd, seed);
|
||||||
|
if (r) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
handshake_case_check(dns_fd);
|
||||||
|
|
||||||
|
if (case_preserved) {
|
||||||
|
handshake_switch_codec(dns_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autodetect_frag_size) {
|
||||||
|
fragsize = handshake_autoprobe_fragsize(dns_fd);
|
||||||
|
if (!fragsize) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handshake_set_fragsize(dns_fd, fragsize);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,8 +893,9 @@ static char *
|
||||||
get_resolvconf_addr()
|
get_resolvconf_addr()
|
||||||
{
|
{
|
||||||
static char addr[16];
|
static char addr[16];
|
||||||
char buf[80];
|
|
||||||
char *rv;
|
char *rv;
|
||||||
|
#ifndef WINDOWS32
|
||||||
|
char buf[80];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
rv = NULL;
|
rv = NULL;
|
||||||
|
@ -809,7 +913,29 @@ get_resolvconf_addr()
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
#else /* !WINDOWS32 */
|
||||||
|
FIXED_INFO *fixed_info;
|
||||||
|
ULONG buflen;
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
|
rv = NULL;
|
||||||
|
fixed_info = malloc(sizeof(FIXED_INFO));
|
||||||
|
buflen = sizeof(FIXED_INFO);
|
||||||
|
|
||||||
|
if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
||||||
|
/* official ugly api workaround */
|
||||||
|
free(fixed_info);
|
||||||
|
fixed_info = malloc(buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GetNetworkParams(fixed_info, &buflen);
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr));
|
||||||
|
addr[15] = 0;
|
||||||
|
rv = addr;
|
||||||
|
}
|
||||||
|
free(fixed_info);
|
||||||
|
#endif
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,7 +957,7 @@ static void
|
||||||
usage() {
|
usage() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
|
||||||
"[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname);
|
"[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -840,19 +966,19 @@ static void
|
||||||
help() {
|
help() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
printf("iodine IP over DNS tunneling client\n");
|
fprintf(stderr, "iodine IP over DNS tunneling client\n");
|
||||||
printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
|
||||||
"[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname);
|
"[-P password] [-m maxfragsize] [nameserver] topdomain\n", __progname);
|
||||||
printf(" -v to print version info and exit\n");
|
fprintf(stderr, " -v to print version info and exit\n");
|
||||||
printf(" -h to print this help and exit\n");
|
fprintf(stderr, " -h to print this help and exit\n");
|
||||||
printf(" -f to keep running in foreground\n");
|
fprintf(stderr, " -f to keep running in foreground\n");
|
||||||
printf(" -u name to drop privileges and run as user 'name'\n");
|
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
|
||||||
printf(" -t dir to chroot to directory dir\n");
|
fprintf(stderr, " -t dir to chroot to directory dir\n");
|
||||||
printf(" -d device to set tunnel device name\n");
|
fprintf(stderr, " -d device to set tunnel device name\n");
|
||||||
printf(" -P password used for authentication (max 32 chars will be used)\n");
|
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
||||||
printf(" -m maxfragsize, to limit size of downstream packets\n");
|
fprintf(stderr, " -m maxfragsize, to limit size of downstream packets\n");
|
||||||
printf("nameserver is the IP number of the relaying nameserver, if absent /etc/resolv.conf is used\n");
|
fprintf(stderr, "nameserver is the IP number of the relaying nameserver, if absent /etc/resolv.conf is used\n");
|
||||||
printf("topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -860,7 +986,7 @@ help() {
|
||||||
static void
|
static void
|
||||||
version() {
|
version() {
|
||||||
printf("iodine IP over DNS tunneling client\n");
|
printf("iodine IP over DNS tunneling client\n");
|
||||||
printf("version: 0.5.0 from 2009-01-23\n");
|
printf("version: 0.5.1 from 2009-03-21\n");
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -869,7 +995,9 @@ int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *nameserv_addr;
|
char *nameserv_addr;
|
||||||
|
#ifndef WINDOWS32
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
#endif
|
||||||
char *username;
|
char *username;
|
||||||
int foreground;
|
int foreground;
|
||||||
char *newroot;
|
char *newroot;
|
||||||
|
@ -877,6 +1005,8 @@ main(int argc, char **argv)
|
||||||
int choice;
|
int choice;
|
||||||
int tun_fd;
|
int tun_fd;
|
||||||
int dns_fd;
|
int dns_fd;
|
||||||
|
int max_downstream_frag_size;
|
||||||
|
int autodetect_frag_size;
|
||||||
|
|
||||||
memset(password, 0, 33);
|
memset(password, 0, 33);
|
||||||
username = NULL;
|
username = NULL;
|
||||||
|
@ -894,6 +1024,10 @@ main(int argc, char **argv)
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
dataenc = get_base32_encoder();
|
dataenc = get_base32_encoder();
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
WSAStartup(req_version, &wsa_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
__progname = strrchr(argv[0], '/');
|
__progname = strrchr(argv[0], '/');
|
||||||
if (__progname == NULL)
|
if (__progname == NULL)
|
||||||
|
@ -941,11 +1075,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (geteuid() != 0) {
|
check_superuser(usage);
|
||||||
warnx("Run as root and you'll be happy.\n");
|
|
||||||
usage();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
@ -985,11 +1115,13 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
|
#ifndef WINDOWS32
|
||||||
if ((pw = getpwnam(username)) == NULL) {
|
if ((pw = getpwnam(username)) == NULL) {
|
||||||
warnx("User %s does not exist!\n", username);
|
warnx("User %s does not exist!\n", username);
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(password) == 0)
|
if (strlen(password) == 0)
|
||||||
|
@ -1003,10 +1135,10 @@ main(int argc, char **argv)
|
||||||
signal(SIGINT, sighandler);
|
signal(SIGINT, sighandler);
|
||||||
signal(SIGTERM, sighandler);
|
signal(SIGTERM, sighandler);
|
||||||
|
|
||||||
if(handshake(dns_fd))
|
if(handshake(dns_fd, autodetect_frag_size, max_downstream_frag_size))
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
|
|
||||||
printf("Sending queries for %s to %s\n", topdomain, nameserv_addr);
|
fprintf(stderr, "Sending queries for %s to %s\n", topdomain, nameserv_addr);
|
||||||
|
|
||||||
if (foreground == 0)
|
if (foreground == 0)
|
||||||
do_detach();
|
do_detach();
|
||||||
|
@ -1015,6 +1147,7 @@ main(int argc, char **argv)
|
||||||
do_chroot(newroot);
|
do_chroot(newroot);
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
|
#ifndef WINDOWS32
|
||||||
gid_t gids[1];
|
gid_t gids[1];
|
||||||
gids[0] = pw->pw_gid;
|
gids[0] = pw->pw_gid;
|
||||||
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
||||||
|
@ -1022,6 +1155,7 @@ main(int argc, char **argv)
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream_seqno = 0;
|
downstream_seqno = 0;
|
||||||
|
|
176
src/iodined.c
176
src/iodined.c
|
@ -23,22 +23,30 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef DARWIN
|
||||||
|
#include <arpa/nameser8_compat.h>
|
||||||
|
#endif
|
||||||
#define _XPG4_2
|
#define _XPG4_2
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <grp.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <zlib.h>
|
#include <grp.h>
|
||||||
#include <arpa/nameser.h>
|
#include <sys/uio.h>
|
||||||
#ifdef DARWIN
|
#include <pwd.h>
|
||||||
#include <arpa/nameser8_compat.h>
|
#include <netdb.h>
|
||||||
|
#include <syslog.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -52,6 +60,11 @@
|
||||||
#include "fw_query.h"
|
#include "fw_query.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
WORD req_version = MAKEWORD(2, 2);
|
||||||
|
WSADATA wsa_data;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int running = 1;
|
static int running = 1;
|
||||||
static char *topdomain;
|
static char *topdomain;
|
||||||
static char password[33];
|
static char password[33];
|
||||||
|
@ -81,6 +94,23 @@ sigint(int sig)
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#define LOG_EMERG 0
|
||||||
|
#define LOG_ALERT 1
|
||||||
|
#define LOG_CRIT 2
|
||||||
|
#define LOG_ERR 3
|
||||||
|
#define LOG_WARNING 4
|
||||||
|
#define LOG_NOTICE 5
|
||||||
|
#define LOG_INFO 6
|
||||||
|
#define LOG_DEBUG 7
|
||||||
|
static void
|
||||||
|
syslog(int a, const char *str, ...)
|
||||||
|
{
|
||||||
|
/* TODO: implement (add to event log), move to common.c */
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
check_user_and_ip(int userid, struct query *q)
|
check_user_and_ip(int userid, struct query *q)
|
||||||
{
|
{
|
||||||
|
@ -208,7 +238,7 @@ send_chunk(int dns_fd, int userid) {
|
||||||
((users[userid].outpacket.fragment & 15) << 1) | (last & 1);
|
((users[userid].outpacket.fragment & 15) << 1) | (last & 1);
|
||||||
|
|
||||||
if (debug >= 1) {
|
if (debug >= 1) {
|
||||||
printf("OUT pkt seq# %d, frag %d (last=%d), offset %d, fragsize %d, total %d, to user %d\n",
|
fprintf(stderr, "OUT pkt seq# %d, frag %d (last=%d), offset %d, fragsize %d, total %d, to user %d\n",
|
||||||
users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15,
|
users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15,
|
||||||
last, users[userid].outpacket.offset, datalen, users[userid].outpacket.len, userid);
|
last, users[userid].outpacket.offset, datalen, users[userid].outpacket.len, userid);
|
||||||
}
|
}
|
||||||
|
@ -306,13 +336,19 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
memcpy(&(users[userid].q), q, sizeof(struct query));
|
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, userid, q);
|
send_version_response(dns_fd, VERSION_ACK, users[userid].seed, userid, q);
|
||||||
|
syslog(LOG_INFO, "accepted version for user #%d from %s",
|
||||||
|
userid, inet_ntoa(tempin->sin_addr));
|
||||||
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, created_users, 0, q);
|
send_version_response(dns_fd, VERSION_FULL, created_users, 0, q);
|
||||||
|
syslog(LOG_INFO, "dropped user from %s, server full",
|
||||||
|
inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
send_version_response(dns_fd, VERSION_NACK, VERSION, 0, q);
|
send_version_response(dns_fd, VERSION_NACK, VERSION, 0, q);
|
||||||
|
syslog(LOG_INFO, "dropped user from %s, sent bad version %08X",
|
||||||
|
inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr), version);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if(in[0] == 'L' || in[0] == 'l') {
|
} else if(in[0] == 'L' || in[0] == 'l') {
|
||||||
|
@ -322,6 +358,8 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
|
|
||||||
if (check_user_and_ip(userid, q) != 0) {
|
if (check_user_and_ip(userid, q) != 0) {
|
||||||
write_dns(dns_fd, q, "BADIP", 5);
|
write_dns(dns_fd, q, "BADIP", 5);
|
||||||
|
syslog(LOG_WARNING, "dropped login request from user #%d from unexpected source %s",
|
||||||
|
userid, inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
users[userid].last_pkt = time(NULL);
|
users[userid].last_pkt = time(NULL);
|
||||||
|
@ -340,11 +378,14 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
|
|
||||||
write_dns(dns_fd, q, out, read);
|
write_dns(dns_fd, q, out, read);
|
||||||
q->id = 0;
|
q->id = 0;
|
||||||
|
syslog(LOG_NOTICE, "accepted password from user #%d, given IP %s", userid, tmp[1]);
|
||||||
|
|
||||||
free(tmp[1]);
|
free(tmp[1]);
|
||||||
free(tmp[0]);
|
free(tmp[0]);
|
||||||
} else {
|
} else {
|
||||||
write_dns(dns_fd, q, "LNAK", 4);
|
write_dns(dns_fd, q, "LNAK", 4);
|
||||||
|
syslog(LOG_WARNING, "rejected login request from user #%d from %s, bad password",
|
||||||
|
userid, inet_ntoa(((struct sockaddr_in *) &q->from)->sin_addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -441,7 +482,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug >= 1) {
|
if (debug >= 1) {
|
||||||
printf("PING pkt from user %d\n", userid);
|
fprintf(stderr, "PING pkt from user %d\n", userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (users[userid].q.id != 0) {
|
if (users[userid].q.id != 0) {
|
||||||
|
@ -491,7 +532,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
up_frag <= users[userid].inpacket.fragment) {
|
up_frag <= users[userid].inpacket.fragment) {
|
||||||
/* Got repeated old packet, skip it */
|
/* Got repeated old packet, skip it */
|
||||||
if (debug >= 1) {
|
if (debug >= 1) {
|
||||||
printf("IN pkt seq# %d, frag %d, dropped duplicate\n",
|
fprintf(stderr, "IN pkt seq# %d, frag %d, dropped duplicate\n",
|
||||||
up_seq, up_frag);
|
up_seq, up_frag);
|
||||||
}
|
}
|
||||||
/* Update seqno and maybe send immediate response packet */
|
/* Update seqno and maybe send immediate response packet */
|
||||||
|
@ -516,7 +557,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
users[userid].inpacket.offset += read;
|
users[userid].inpacket.offset += read;
|
||||||
|
|
||||||
if (debug >= 1) {
|
if (debug >= 1) {
|
||||||
printf("IN pkt seq# %d, frag %d (last=%d), fragsize %d, total %d, from user %d\n",
|
fprintf(stderr, "IN pkt seq# %d, frag %d (last=%d), fragsize %d, total %d, from user %d\n",
|
||||||
up_seq, up_frag, lastfrag, read, users[userid].inpacket.len, userid);
|
up_seq, up_frag, lastfrag, read, users[userid].inpacket.len, userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,7 +583,7 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Discarded data, uncompress() result: %d\n", ret);
|
fprintf(stderr, "Discarded data, uncompress() result: %d\n", ret);
|
||||||
}
|
}
|
||||||
users[userid].inpacket.len = users[userid].inpacket.offset = 0;
|
users[userid].inpacket.len = users[userid].inpacket.offset = 0;
|
||||||
}
|
}
|
||||||
|
@ -567,7 +608,7 @@ handle_ns_request(int dns_fd, struct query *q)
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
struct sockaddr_in *tempin;
|
struct sockaddr_in *tempin;
|
||||||
tempin = (struct sockaddr_in *) &(q->from);
|
tempin = (struct sockaddr_in *) &(q->from);
|
||||||
printf("TX: client %s, type %d, name %s, %d bytes NS reply\n",
|
fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes NS reply\n",
|
||||||
inet_ntoa(tempin->sin_addr), q->type, q->name, len);
|
inet_ntoa(tempin->sin_addr), q->type, q->name, len);
|
||||||
}
|
}
|
||||||
if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
|
if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
|
||||||
|
@ -598,7 +639,7 @@ forward_query(int bind_fd, struct query *q)
|
||||||
myaddr->sin_port = htons(bind_port);
|
myaddr->sin_port = htons(bind_port);
|
||||||
|
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
printf("TX: NS reply \n");
|
fprintf(stderr, "TX: NS reply \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sendto(bind_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
|
if (sendto(bind_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
|
||||||
|
@ -613,7 +654,7 @@ tunnel_bind(int bind_fd, int dns_fd)
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
socklen_t fromlen;
|
socklen_t fromlen;
|
||||||
struct fw_query *query;
|
struct fw_query *query;
|
||||||
short id;
|
unsigned short id;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
fromlen = sizeof(struct sockaddr);
|
fromlen = sizeof(struct sockaddr);
|
||||||
|
@ -626,20 +667,20 @@ tunnel_bind(int bind_fd, int dns_fd)
|
||||||
id = dns_get_id(packet, r);
|
id = dns_get_id(packet, r);
|
||||||
|
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
printf("RX: Got response on query %u from DNS\n", (id & 0xFFFF));
|
fprintf(stderr, "RX: Got response on query %u from DNS\n", (id & 0xFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get sockaddr from id */
|
/* Get sockaddr from id */
|
||||||
fw_query_get(id, &query);
|
fw_query_get(id, &query);
|
||||||
if (!query && debug >= 2) {
|
if (!query && debug >= 2) {
|
||||||
printf("Lost sender of id %u, dropping reply\n", (id & 0xFFFF));
|
fprintf(stderr, "Lost sender of id %u, dropping reply\n", (id & 0xFFFF));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
struct sockaddr_in *in;
|
struct sockaddr_in *in;
|
||||||
in = (struct sockaddr_in *) &(query->addr);
|
in = (struct sockaddr_in *) &(query->addr);
|
||||||
printf("TX: client %s id %u, %d bytes\n",
|
fprintf(stderr, "TX: client %s id %u, %d bytes\n",
|
||||||
inet_ntoa(in->sin_addr), (id & 0xffff), r);
|
inet_ntoa(in->sin_addr), (id & 0xffff), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +707,7 @@ tunnel_dns(int tun_fd, int dns_fd, int bind_fd)
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
struct sockaddr_in *tempin;
|
struct sockaddr_in *tempin;
|
||||||
tempin = (struct sockaddr_in *) &(q.from);
|
tempin = (struct sockaddr_in *) &(q.from);
|
||||||
printf("RX: client %s, type %d, name %s\n",
|
fprintf(stderr, "RX: client %s, type %d, name %s\n",
|
||||||
inet_ntoa(tempin->sin_addr), q.type, q.name);
|
inet_ntoa(tempin->sin_addr), q.type, q.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,11 +815,12 @@ read_dns(int fd, struct query *q)
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
char packet[64*1024];
|
char packet[64*1024];
|
||||||
|
int r;
|
||||||
|
#ifndef WINDOWS32
|
||||||
char address[96];
|
char address[96];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
int r;
|
|
||||||
|
|
||||||
addrlen = sizeof(struct sockaddr);
|
addrlen = sizeof(struct sockaddr);
|
||||||
iov.iov_base = packet;
|
iov.iov_base = packet;
|
||||||
|
@ -793,12 +835,17 @@ read_dns(int fd, struct query *q)
|
||||||
msg.msg_flags = 0;
|
msg.msg_flags = 0;
|
||||||
|
|
||||||
r = recvmsg(fd, &msg, 0);
|
r = recvmsg(fd, &msg, 0);
|
||||||
|
#else
|
||||||
|
addrlen = sizeof(struct sockaddr);
|
||||||
|
r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
|
||||||
|
#endif /* !WINDOWS32 */
|
||||||
|
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
dns_decode(NULL, 0, q, QR_QUERY, packet, r);
|
dns_decode(NULL, 0, q, QR_QUERY, packet, r);
|
||||||
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
|
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
|
||||||
q->fromlen = addrlen;
|
q->fromlen = addrlen;
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||||
|
|
||||||
|
@ -809,6 +856,7 @@ read_dns(int fd, struct query *q)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return strlen(q->name);
|
return strlen(q->name);
|
||||||
} else if (r < 0) {
|
} else if (r < 0) {
|
||||||
|
@ -830,7 +878,7 @@ write_dns(int fd, struct query *q, char *data, int datalen)
|
||||||
if (debug >= 2) {
|
if (debug >= 2) {
|
||||||
struct sockaddr_in *tempin;
|
struct sockaddr_in *tempin;
|
||||||
tempin = (struct sockaddr_in *) &(q->from);
|
tempin = (struct sockaddr_in *) &(q->from);
|
||||||
printf("TX: client %s, type %d, name %s, %d bytes data\n",
|
fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes data\n",
|
||||||
inet_ntoa(tempin->sin_addr), q->type, q->name, datalen);
|
inet_ntoa(tempin->sin_addr), q->type, q->name, datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,7 +889,7 @@ static void
|
||||||
usage() {
|
usage() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
|
||||||
"[-t chrootdir] [-d device] [-m mtu] "
|
"[-t chrootdir] [-d device] [-m mtu] "
|
||||||
"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
|
"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
|
||||||
" tunnel_ip[/netmask] topdomain\n", __progname);
|
" tunnel_ip[/netmask] topdomain\n", __progname);
|
||||||
|
@ -852,46 +900,49 @@ static void
|
||||||
help() {
|
help() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
printf("iodine IP over DNS tunneling server\n");
|
fprintf(stderr, "iodine IP over DNS tunneling server\n");
|
||||||
printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
|
||||||
"[-t chrootdir] [-d device] [-m mtu] "
|
"[-t chrootdir] [-d device] [-m mtu] "
|
||||||
"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
|
"[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
|
||||||
" tunnel_ip[/netmask] topdomain\n", __progname);
|
" tunnel_ip[/netmask] topdomain\n", __progname);
|
||||||
printf(" -v to print version info and exit\n");
|
fprintf(stderr, " -v to print version info and exit\n");
|
||||||
printf(" -h to print this help and exit\n");
|
fprintf(stderr, " -h to print this help and exit\n");
|
||||||
printf(" -c to disable check of client IP/port on each request\n");
|
fprintf(stderr, " -c to disable check of client IP/port on each request\n");
|
||||||
printf(" -s to skip creating and configuring the tun device, "
|
fprintf(stderr, " -s to skip creating and configuring the tun device, "
|
||||||
"which then has to be created manually\n");
|
"which then has to be created manually\n");
|
||||||
printf(" -f to keep running in foreground\n");
|
fprintf(stderr, " -f to keep running in foreground\n");
|
||||||
printf(" -D to increase debug level\n");
|
fprintf(stderr, " -D to increase debug level\n");
|
||||||
printf(" -u name to drop privileges and run as user 'name'\n");
|
fprintf(stderr, " -u name to drop privileges and run as user 'name'\n");
|
||||||
printf(" -t dir to chroot to directory dir\n");
|
fprintf(stderr, " -t dir to chroot to directory dir\n");
|
||||||
printf(" -d device to set tunnel device name\n");
|
fprintf(stderr, " -d device to set tunnel device name\n");
|
||||||
printf(" -m mtu to set tunnel device mtu\n");
|
fprintf(stderr, " -m mtu to set tunnel device mtu\n");
|
||||||
printf(" -l ip address to listen on for incoming dns traffic "
|
fprintf(stderr, " -l ip address to listen on for incoming dns traffic "
|
||||||
"(default 0.0.0.0)\n");
|
"(default 0.0.0.0)\n");
|
||||||
printf(" -p port to listen on for incoming dns traffic (default 53)\n");
|
fprintf(stderr, " -p port to listen on for incoming dns traffic (default 53)\n");
|
||||||
printf(" -n ip to respond with to NS queries\n");
|
fprintf(stderr, " -n ip to respond with to NS queries\n");
|
||||||
printf(" -b port to forward normal DNS queries to (on localhost)\n");
|
fprintf(stderr, " -b port to forward normal DNS queries to (on localhost)\n");
|
||||||
printf(" -P password used for authentication (max 32 chars will be used)\n");
|
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
||||||
printf("tunnel_ip is the IP number of the local tunnel interface.\n");
|
fprintf(stderr, "tunnel_ip is the IP number of the local tunnel interface.\n");
|
||||||
printf(" /netmask sets the size of the tunnel network.\n");
|
fprintf(stderr, " /netmask sets the size of the tunnel network.\n");
|
||||||
printf("topdomain is the FQDN that is delegated to this server.\n");
|
fprintf(stderr, "topdomain is the FQDN that is delegated to this server.\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.5.0 from 2009-01-23\n");
|
printf("version: 0.5.1 from 2009-03-21\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
extern char *__progname;
|
||||||
in_addr_t listen_ip;
|
in_addr_t listen_ip;
|
||||||
|
#ifndef WINDOWS32
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
#endif
|
||||||
int foreground;
|
int foreground;
|
||||||
char *username;
|
char *username;
|
||||||
char *newroot;
|
char *newroot;
|
||||||
|
@ -916,7 +967,7 @@ main(int argc, char **argv)
|
||||||
foreground = 0;
|
foreground = 0;
|
||||||
bind_enable = 0;
|
bind_enable = 0;
|
||||||
bind_fd = 0;
|
bind_fd = 0;
|
||||||
mtu = 1024;
|
mtu = 1200;
|
||||||
listen_ip = INADDR_ANY;
|
listen_ip = INADDR_ANY;
|
||||||
port = 53;
|
port = 53;
|
||||||
ns_ip = INADDR_ANY;
|
ns_ip = INADDR_ANY;
|
||||||
|
@ -927,6 +978,10 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
WSAStartup(req_version, &wsa_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(BSD) && !defined(__GLIBC__)
|
#if !defined(BSD) && !defined(__GLIBC__)
|
||||||
__progname = strrchr(argv[0], '/');
|
__progname = strrchr(argv[0], '/');
|
||||||
if (__progname == NULL)
|
if (__progname == NULL)
|
||||||
|
@ -1000,10 +1055,7 @@ main(int argc, char **argv)
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (geteuid() != 0) {
|
check_superuser(usage);
|
||||||
warnx("Run as root and you'll be happy.\n");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
usage();
|
usage();
|
||||||
|
@ -1034,10 +1086,12 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
|
#ifndef WINDOWS32
|
||||||
if ((pw = getpwnam(username)) == NULL) {
|
if ((pw = getpwnam(username)) == NULL) {
|
||||||
warnx("User %s does not exist!\n", username);
|
warnx("User %s does not exist!\n", username);
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mtu <= 0) {
|
if (mtu <= 0) {
|
||||||
|
@ -1056,18 +1110,18 @@ main(int argc, char **argv)
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
printf("Requests for domains outside of %s will be forwarded to port %d\n",
|
fprintf(stderr, "Requests for domains outside of %s will be forwarded to port %d\n",
|
||||||
topdomain, bind_port);
|
topdomain, bind_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port != 53) {
|
if (port != 53) {
|
||||||
printf("ALERT! Other dns servers expect you to run on port 53.\n");
|
fprintf(stderr, "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);
|
fprintf(stderr, "You must manually forward port 53 to port %d for things to work.\n", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
printf("Debug level %d enabled, will stay in foreground.\n", debug);
|
fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", debug);
|
||||||
printf("Add more -D switches to set higher debug level.\n");
|
fprintf(stderr, "Add more -D switches to set higher debug level.\n");
|
||||||
foreground = 1;
|
foreground = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,10 +1158,10 @@ main(int argc, char **argv)
|
||||||
created_users = init_users(my_ip, netmask);
|
created_users = init_users(my_ip, netmask);
|
||||||
|
|
||||||
if (created_users < USERS) {
|
if (created_users < USERS) {
|
||||||
printf("Limiting to %d simultaneous users because of netmask /%d\n",
|
fprintf(stderr, "Limiting to %d simultaneous users because of netmask /%d\n",
|
||||||
created_users, netmask);
|
created_users, netmask);
|
||||||
}
|
}
|
||||||
printf("Listening to dns for domain %s\n", topdomain);
|
fprintf(stderr, "Listening to dns for domain %s\n", topdomain);
|
||||||
|
|
||||||
if (foreground == 0)
|
if (foreground == 0)
|
||||||
do_detach();
|
do_detach();
|
||||||
|
@ -1117,16 +1171,24 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
signal(SIGINT, sigint);
|
signal(SIGINT, sigint);
|
||||||
if (username != NULL) {
|
if (username != NULL) {
|
||||||
|
#ifndef WINDOWS32
|
||||||
gid_t gids[1];
|
gid_t gids[1];
|
||||||
gids[0] = pw->pw_gid;
|
gids[0] = pw->pw_gid;
|
||||||
if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
|
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();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
|
openlog(__progname, LOG_NOWAIT, LOG_DAEMON);
|
||||||
|
#endif
|
||||||
|
syslog(LOG_INFO, "started, listening on port %d", port);
|
||||||
|
|
||||||
tunnel(tun_fd, dnsd_fd, bind_fd);
|
tunnel(tun_fd, dnsd_fd, bind_fd);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "stopping");
|
||||||
cleanup3:
|
cleanup3:
|
||||||
close_dns(bind_fd);
|
close_dns(bind_fd);
|
||||||
cleanup2:
|
cleanup2:
|
||||||
|
|
|
@ -15,9 +15,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include "windows.h"
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
case $1 in
|
case $2 in
|
||||||
link)
|
link)
|
||||||
|
|
||||||
case `uname` in
|
case $1 in
|
||||||
SunOS | solaris)
|
SunOS | solaris)
|
||||||
echo '-lsocket -lnsl';
|
echo '-lsocket -lnsl';
|
||||||
;;
|
;;
|
||||||
|
@ -13,10 +13,13 @@ link)
|
||||||
Haiku)
|
Haiku)
|
||||||
echo '-lnetwork';
|
echo '-lnetwork';
|
||||||
;;
|
;;
|
||||||
|
windows32)
|
||||||
|
echo '-lws2_32 -liphlpapi';
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
cflags)
|
cflags)
|
||||||
case `uname` in
|
case $1 in
|
||||||
BeOS)
|
BeOS)
|
||||||
echo '-Dsocklen_t=int';
|
echo '-Dsocklen_t=int';
|
||||||
;;
|
;;
|
||||||
|
|
271
src/tun.c
271
src/tun.c
|
@ -23,16 +23,39 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
HANDLE dev_handle;
|
||||||
|
struct tun_data data;
|
||||||
|
|
||||||
|
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
|
||||||
|
#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE(10, METHOD_BUFFERED)
|
||||||
|
#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE(6, METHOD_BUFFERED)
|
||||||
|
|
||||||
|
#define TAP_ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
||||||
|
#define TAP_DEVICE_SPACE "\\\\.\\Global\\"
|
||||||
|
#define TAP_VERSION_ID_0801 "tap0801"
|
||||||
|
#define TAP_VERSION_ID_0901 "tap0901"
|
||||||
|
#define KEY_COMPONENT_ID "ComponentId"
|
||||||
|
#define NET_CFG_INST_ID "NetCfgInstanceId"
|
||||||
|
#else
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "tun.h"
|
|
||||||
|
|
||||||
#define TUN_MAX_TRY 50
|
#define TUN_MAX_TRY 50
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "tun.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
char if_name[50];
|
char if_name[50];
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
@ -63,7 +86,7 @@ open_tun(const char *tun_device)
|
||||||
if_name[sizeof(if_name)-1] = '\0';
|
if_name[sizeof(if_name)-1] = '\0';
|
||||||
|
|
||||||
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
||||||
printf("Opened %s\n", ifreq.ifr_name);
|
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +99,7 @@ open_tun(const char *tun_device)
|
||||||
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
|
snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
|
||||||
|
|
||||||
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
|
||||||
printf("Opened %s\n", ifreq.ifr_name);
|
fprintf(stderr, "Opened %s\n", ifreq.ifr_name);
|
||||||
snprintf(if_name, sizeof(if_name), "dns%d", i);
|
snprintf(if_name, sizeof(if_name), "dns%d", i);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
@ -111,14 +134,14 @@ open_tun(const char *tun_device)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Opened %s\n", tun_name);
|
fprintf(stderr, "Opened %s\n", tun_name);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < TUN_MAX_TRY; i++) {
|
for (i = 0; i < TUN_MAX_TRY; i++) {
|
||||||
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
|
||||||
|
|
||||||
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
|
||||||
printf("Opened %s\n", tun_name);
|
fprintf(stderr, "Opened %s\n", tun_name);
|
||||||
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
snprintf(if_name, sizeof(if_name), "tun%d", i);
|
||||||
return tun_fd;
|
return tun_fd;
|
||||||
}
|
}
|
||||||
|
@ -134,6 +157,148 @@ open_tun(const char *tun_device)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !LINUX */
|
#endif /* !LINUX */
|
||||||
|
#else /* WINDOWS32 */
|
||||||
|
static void
|
||||||
|
get_device(char *device, int device_len)
|
||||||
|
{
|
||||||
|
LONG status;
|
||||||
|
HKEY adapter_key;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
|
||||||
|
|
||||||
|
if (status != ERROR_SUCCESS) {
|
||||||
|
warnx("Error opening registry key " TAP_ADAPTER_KEY );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
char name[256];
|
||||||
|
char unit[256];
|
||||||
|
char component[256];
|
||||||
|
|
||||||
|
char cid_string[256] = KEY_COMPONENT_ID;
|
||||||
|
HKEY device_key;
|
||||||
|
DWORD datatype;
|
||||||
|
DWORD len;
|
||||||
|
|
||||||
|
/* Iterate through all adapter of this kind */
|
||||||
|
len = sizeof(name);
|
||||||
|
status = RegEnumKeyEx(adapter_key, index, name, &len, NULL, NULL, NULL, NULL);
|
||||||
|
if (status == ERROR_NO_MORE_ITEMS) {
|
||||||
|
break;
|
||||||
|
} else if (status != ERROR_SUCCESS) {
|
||||||
|
warnx("Error enumerating subkeys of registry key " TAP_ADAPTER_KEY );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(unit, sizeof(unit), TAP_ADAPTER_KEY "\\%s", name);
|
||||||
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit, 0, KEY_READ, &device_key);
|
||||||
|
if (status != ERROR_SUCCESS) {
|
||||||
|
warnx("Error opening registry key %s", unit);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check component id */
|
||||||
|
len = sizeof(component);
|
||||||
|
status = RegQueryValueEx(device_key, cid_string, NULL, &datatype, (LPBYTE)component, &len);
|
||||||
|
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (strncmp(TAP_VERSION_ID_0801, component, strlen(TAP_VERSION_ID_0801)) == 0 ||
|
||||||
|
strncmp(TAP_VERSION_ID_0901, component, strlen(TAP_VERSION_ID_0901)) == 0) {
|
||||||
|
/* We found a TAP32 device, get its NetCfgInstanceId */
|
||||||
|
char iid_string[256] = NET_CFG_INST_ID;
|
||||||
|
|
||||||
|
status = RegQueryValueEx(device_key, iid_string, NULL, &datatype, (LPBYTE) device, (DWORD *) &device_len);
|
||||||
|
if (status != ERROR_SUCCESS || datatype != REG_SZ) {
|
||||||
|
warnx("Error reading registry key %s\\%s on TAP device", unit, iid_string);
|
||||||
|
} else {
|
||||||
|
/* Done getting name of TAP device */
|
||||||
|
RegCloseKey(device_key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
RegCloseKey(device_key);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
RegCloseKey(adapter_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WINAPI tun_reader(LPVOID arg)
|
||||||
|
{
|
||||||
|
struct tun_data *tun = arg;
|
||||||
|
char buf[64*1024];
|
||||||
|
int len;
|
||||||
|
int res;
|
||||||
|
OVERLAPPED olpd;
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
sock = open_dns(0, INADDR_ANY);
|
||||||
|
|
||||||
|
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
|
while(TRUE) {
|
||||||
|
olpd.Offset = 0;
|
||||||
|
olpd.OffsetHigh = 0;
|
||||||
|
res = ReadFile(tun->tun, buf, sizeof(buf), (LPDWORD) &len, &olpd);
|
||||||
|
if (!res) {
|
||||||
|
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||||
|
res = GetOverlappedResult(dev_handle, &olpd, (LPDWORD) &len, FALSE);
|
||||||
|
res = sendto(sock, buf, len, 0, (struct sockaddr*) &(tun->addr),
|
||||||
|
sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
open_tun(const char *tun_device)
|
||||||
|
{
|
||||||
|
char adapter[256];
|
||||||
|
char tapfile[512];
|
||||||
|
int tunfd;
|
||||||
|
in_addr_t local;
|
||||||
|
|
||||||
|
memset(adapter, 0, sizeof(adapter));
|
||||||
|
get_device(adapter, sizeof(adapter));
|
||||||
|
|
||||||
|
if (strlen(adapter) == 0) {
|
||||||
|
warnx("No TAP adapters found. See README-win32.txt for help.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tapfile, sizeof(tapfile), "%s%s.tap", TAP_DEVICE_SPACE, adapter);
|
||||||
|
fprintf(stderr, "Opening device %s\n", tapfile);
|
||||||
|
dev_handle = CreateFile(tapfile, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
|
||||||
|
if (dev_handle == INVALID_HANDLE_VALUE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO get name of interface */
|
||||||
|
strncpy(if_name, "dns", MIN(4, sizeof(if_name)));
|
||||||
|
|
||||||
|
/* Use a UDP connection to forward packets from tun,
|
||||||
|
* so we can still use select() in main code.
|
||||||
|
* A thread does blocking reads on tun device and
|
||||||
|
* sends data as udp to this socket */
|
||||||
|
|
||||||
|
local = htonl(0x7f000001); /* 127.0.0.1 */
|
||||||
|
tunfd = open_dns(55353, local);
|
||||||
|
|
||||||
|
data.tun = dev_handle;
|
||||||
|
memset(&(data.addr), 0, sizeof(data.addr));
|
||||||
|
data.addr.sin_family = AF_INET;
|
||||||
|
data.addr.sin_port = htons(55353);
|
||||||
|
data.addr.sin_addr.s_addr = local;
|
||||||
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, &data, 0, NULL);
|
||||||
|
|
||||||
|
return tunfd;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
close_tun(int tun_fd)
|
close_tun(int tun_fd)
|
||||||
|
@ -145,7 +310,7 @@ close_tun(int tun_fd)
|
||||||
int
|
int
|
||||||
write_tun(int tun_fd, char *data, size_t len)
|
write_tun(int tun_fd, char *data, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
|
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
|
||||||
data += 4;
|
data += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
#else /* !FREEBSD/DARWIN */
|
#else /* !FREEBSD/DARWIN */
|
||||||
|
@ -162,19 +327,45 @@ write_tun(int tun_fd, char *data, size_t len)
|
||||||
#endif /* !LINUX */
|
#endif /* !LINUX */
|
||||||
#endif /* FREEBSD */
|
#endif /* FREEBSD */
|
||||||
|
|
||||||
|
#ifndef WINDOWS32
|
||||||
if (write(tun_fd, data, len) != len) {
|
if (write(tun_fd, data, len) != len) {
|
||||||
warn("write_tun");
|
warn("write_tun");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#else /* WINDOWS32 */
|
||||||
|
{
|
||||||
|
DWORD written;
|
||||||
|
DWORD res;
|
||||||
|
OVERLAPPED olpd;
|
||||||
|
|
||||||
|
olpd.Offset = 0;
|
||||||
|
olpd.OffsetHigh = 0;
|
||||||
|
olpd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
res = WriteFile(dev_handle, data, len, &written, &olpd);
|
||||||
|
if (!res && GetLastError() == ERROR_IO_PENDING) {
|
||||||
|
WaitForSingleObject(olpd.hEvent, INFINITE);
|
||||||
|
res = GetOverlappedResult(dev_handle, &olpd, &written, FALSE);
|
||||||
|
if (written != len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
read_tun(int tun_fd, char *buf, size_t len)
|
read_tun(int tun_fd, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
|
#if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD) || defined(WINDOWS32)
|
||||||
/* FreeBSD/Darwin/NetBSD has no header */
|
/* FreeBSD/Darwin/NetBSD has no header */
|
||||||
return read(tun_fd, buf + 4, len - 4) + 4;
|
int bytes;
|
||||||
|
bytes = recv(tun_fd, buf + 4, len, 0);
|
||||||
|
if (bytes < 0) {
|
||||||
|
return bytes;
|
||||||
|
} else {
|
||||||
|
return bytes + 4;
|
||||||
|
}
|
||||||
#else /* !FREEBSD */
|
#else /* !FREEBSD */
|
||||||
return read(tun_fd, buf, len);
|
return read(tun_fd, buf, len);
|
||||||
#endif /* !FREEBSD */
|
#endif /* !FREEBSD */
|
||||||
|
@ -187,10 +378,16 @@ tun_setip(const char *ip, int netbits)
|
||||||
int netmask;
|
int netmask;
|
||||||
struct in_addr net;
|
struct in_addr net;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
int r;
|
int r;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
DWORD status;
|
||||||
|
DWORD ipdata[3];
|
||||||
|
struct in_addr addr;
|
||||||
|
DWORD len;
|
||||||
|
#endif
|
||||||
|
|
||||||
netmask = 0;
|
netmask = 0;
|
||||||
for (i = 0; i < netbits; i++) {
|
for (i = 0; i < netbits; i++) {
|
||||||
netmask = (netmask << 1) | 1;
|
netmask = (netmask << 1) | 1;
|
||||||
|
@ -198,7 +395,11 @@ tun_setip(const char *ip, int netbits)
|
||||||
netmask <<= (32 - netbits);
|
netmask <<= (32 - netbits);
|
||||||
net.s_addr = htonl(netmask);
|
net.s_addr = htonl(netmask);
|
||||||
|
|
||||||
if (inet_addr(ip) != INADDR_NONE) {
|
if (inet_addr(ip) == INADDR_NONE) {
|
||||||
|
fprintf(stderr, "Invalid IP: %s!\n", ip);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#ifndef WINDOWS32
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
"/sbin/ifconfig %s %s %s netmask %s",
|
"/sbin/ifconfig %s %s %s netmask %s",
|
||||||
if_name,
|
if_name,
|
||||||
|
@ -206,7 +407,7 @@ tun_setip(const char *ip, int netbits)
|
||||||
ip,
|
ip,
|
||||||
inet_ntoa(net));
|
inet_ntoa(net));
|
||||||
|
|
||||||
printf("Setting IP of %s to %s\n", if_name, ip);
|
fprintf(stderr, "Setting IP of %s to %s\n", if_name, ip);
|
||||||
#ifndef LINUX
|
#ifndef LINUX
|
||||||
r = system(cmdline);
|
r = system(cmdline);
|
||||||
if(r != 0) {
|
if(r != 0) {
|
||||||
|
@ -216,33 +417,67 @@ tun_setip(const char *ip, int netbits)
|
||||||
"/sbin/route add %s/%d %s",
|
"/sbin/route add %s/%d %s",
|
||||||
ip, netbits, ip);
|
ip, netbits, ip);
|
||||||
}
|
}
|
||||||
printf("Adding route %s/%d to %s\n", ip, netbits, ip);
|
fprintf(stderr, "Adding route %s/%d to %s\n", ip, netbits, ip);
|
||||||
#endif
|
#endif
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
} else {
|
#else /* WINDOWS32 */
|
||||||
printf("Invalid IP: %s!\n", ip);
|
|
||||||
|
/* Set device as connected */
|
||||||
|
fprintf(stderr, "Enabling interface '%s'\n", if_name);
|
||||||
|
status = 1;
|
||||||
|
r = DeviceIoControl(dev_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status,
|
||||||
|
sizeof(status), &status, sizeof(status), &len, NULL);
|
||||||
|
if (!r) {
|
||||||
|
fprintf(stderr, "Failed to enable interface\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
if (inet_aton(ip, &addr)) {
|
||||||
|
ipdata[0] = (DWORD) addr.s_addr; /* local ip addr */
|
||||||
|
ipdata[1] = net.s_addr & ipdata[0]; /* network addr */
|
||||||
|
ipdata[2] = (DWORD) net.s_addr; /* netmask */
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell ip/networkaddr/netmask to device for arp use */
|
||||||
|
r = DeviceIoControl(dev_handle, TAP_IOCTL_CONFIG_TUN, &ipdata,
|
||||||
|
sizeof(ipdata), &ipdata, sizeof(ipdata), &len, NULL);
|
||||||
|
if (!r) {
|
||||||
|
fprintf(stderr, "Failed to set interface in TUN mode\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use netsh to set ip address */
|
||||||
|
fprintf(stderr, "Setting IP of interface '%s' to %s (can take a few seconds)...\n", if_name, ip);
|
||||||
|
snprintf(cmdline, sizeof(cmdline), "netsh interface ip set address \"%s\" static %s %s",
|
||||||
|
if_name, ip, inet_ntoa(net));
|
||||||
|
return system(cmdline);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tun_setmtu(const unsigned mtu)
|
tun_setmtu(const unsigned mtu)
|
||||||
{
|
{
|
||||||
|
#ifndef WINDOWS32
|
||||||
char cmdline[512];
|
char cmdline[512];
|
||||||
|
|
||||||
if (mtu > 200 && mtu < 1500) {
|
if (mtu > 200 && mtu <= 1500) {
|
||||||
snprintf(cmdline, sizeof(cmdline),
|
snprintf(cmdline, sizeof(cmdline),
|
||||||
"/sbin/ifconfig %s mtu %u",
|
"/sbin/ifconfig %s mtu %u",
|
||||||
if_name,
|
if_name,
|
||||||
mtu);
|
mtu);
|
||||||
|
|
||||||
printf("Setting MTU of %s to %u\n", if_name, mtu);
|
fprintf(stderr, "Setting MTU of %s to %u\n", if_name, mtu);
|
||||||
return system(cmdline);
|
return system(cmdline);
|
||||||
} else {
|
} else {
|
||||||
warn("MTU out of range: %u\n", mtu);
|
warn("MTU out of range: %u\n", mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
#else /* WINDOWS32 */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/user.c
11
src/user.c
|
@ -21,13 +21,18 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FIX_WINDOWS_H__
|
||||||
|
#define __FIX_WINDOWS_H__
|
||||||
|
|
||||||
|
typedef unsigned int in_addr_t;
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windns.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
|
#define T_A DNS_TYPE_A
|
||||||
|
#define T_NS DNS_TYPE_NS
|
||||||
|
#define T_NULL DNS_TYPE_NULL
|
||||||
|
|
||||||
|
#define C_IN 1
|
||||||
|
|
||||||
|
#define SERVFAIL 2
|
||||||
|
#define NXDOMAIN 3
|
||||||
|
#define NOTIMP 4
|
||||||
|
#define REFUSED 5
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned id :16; /* query identification number */
|
||||||
|
/* fields in third byte */
|
||||||
|
unsigned rd :1; /* recursion desired */
|
||||||
|
unsigned tc :1; /* truncated message */
|
||||||
|
unsigned aa :1; /* authoritive answer */
|
||||||
|
unsigned opcode :4; /* purpose of message */
|
||||||
|
unsigned qr :1; /* response flag */
|
||||||
|
/* fields in fourth byte */
|
||||||
|
unsigned rcode :4; /* response code */
|
||||||
|
unsigned cd: 1; /* checking disabled by resolver */
|
||||||
|
unsigned ad: 1; /* authentic data from named */
|
||||||
|
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
|
||||||
|
unsigned ra :1; /* recursion available */
|
||||||
|
/* remaining bytes */
|
||||||
|
unsigned qdcount :16; /* number of question entries */
|
||||||
|
unsigned ancount :16; /* number of answer entries */
|
||||||
|
unsigned nscount :16; /* number of authority entries */
|
||||||
|
unsigned arcount :16; /* number of resource entries */
|
||||||
|
} HEADER;
|
||||||
|
|
||||||
|
struct ip
|
||||||
|
{
|
||||||
|
unsigned int ip_hl:4; /* header length */
|
||||||
|
unsigned int ip_v:4; /* version */
|
||||||
|
u_char ip_tos; /* type of service */
|
||||||
|
u_short ip_len; /* total length */
|
||||||
|
u_short ip_id; /* identification */
|
||||||
|
u_short ip_off; /* fragment offset field */
|
||||||
|
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||||
|
#define IP_DF 0x4000 /* dont fragment flag */
|
||||||
|
#define IP_MF 0x2000 /* more fragments flag */
|
||||||
|
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||||
|
u_char ip_ttl; /* time to live */
|
||||||
|
u_char ip_p; /* protocol */
|
||||||
|
u_short ip_sum; /* checksum */
|
||||||
|
struct in_addr ip_src, ip_dst; /* source and dest address */
|
||||||
|
};
|
||||||
|
|
||||||
|
DWORD WINAPI tun_reader(LPVOID arg);
|
||||||
|
struct tun_data {
|
||||||
|
HANDLE tun;
|
||||||
|
int sock;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -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 fw_query.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
|
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/fw_query.o
|
||||||
|
|
||||||
OS = `uname | tr "a-z" "A-Z"`
|
OS = `uname | tr "a-z" "A-Z"`
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,18 @@
|
||||||
#include "base32.h"
|
#include "base32.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
#define TUPLES 5
|
||||||
|
|
||||||
static struct tuple
|
static struct tuple
|
||||||
{
|
{
|
||||||
char *a;
|
char *a;
|
||||||
char *b;
|
char *b;
|
||||||
} testpairs[] = {
|
} testpairs[TUPLES] = {
|
||||||
{ "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" },
|
{ "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" },
|
||||||
{ "abc123", "mfrggmjsgm" },
|
{ "abc123", "mfrggmjsgm" },
|
||||||
{ NULL, NULL }
|
{ "test", "orsxg3a" },
|
||||||
|
{ "tst", "orzxi" },
|
||||||
|
{ "", "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_base32_encode)
|
START_TEST(test_base32_encode)
|
||||||
|
@ -40,18 +44,14 @@ START_TEST(test_base32_encode)
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b32;
|
struct encoder *b32;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b32->encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a));
|
val = b32->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
||||||
|
|
||||||
fail_unless(val > 0, strerror(errno));
|
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
||||||
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
"'%s' != '%s'", buf, testpairs[_i].b);
|
||||||
"'%s' != '%s'", buf, testpairs[i].b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -61,19 +61,15 @@ START_TEST(test_base32_decode)
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b32;
|
struct encoder *b32;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
|
||||||
|
|
||||||
b32 = get_base32_encoder();
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b32->decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b));
|
val = b32->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
||||||
|
|
||||||
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,
|
||||||
"'%s' != '%s'", buf, testpairs[i].a);
|
"'%s' != '%s'", buf, testpairs[_i].a);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -89,15 +85,58 @@ START_TEST(test_base32_5to8_8to5)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_base32_blksize)
|
||||||
|
{
|
||||||
|
size_t rawlen;
|
||||||
|
size_t enclen;
|
||||||
|
char *rawbuf;
|
||||||
|
char *encbuf;
|
||||||
|
struct encoder *b32;
|
||||||
|
int i;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
b32 = get_base32_encoder();
|
||||||
|
|
||||||
|
rawlen = b32->blocksize_raw();
|
||||||
|
enclen = b32->blocksize_encoded();
|
||||||
|
|
||||||
|
rawbuf = malloc(rawlen + 16);
|
||||||
|
encbuf = malloc(enclen + 16);
|
||||||
|
|
||||||
|
for (i = 0; i < rawlen; i++) {
|
||||||
|
rawbuf[i] = 'A';
|
||||||
|
}
|
||||||
|
rawbuf[i] = 0;
|
||||||
|
|
||||||
|
val = b32->encode(encbuf, &enclen, rawbuf, rawlen);
|
||||||
|
|
||||||
|
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
||||||
|
fail_unless(enclen == 5, "encoded %d bytes, not 5", enclen);
|
||||||
|
fail_unless(val == 8, "encoded string %s was length %d", encbuf, val);
|
||||||
|
|
||||||
|
memset(rawbuf, 0, rawlen + 16);
|
||||||
|
|
||||||
|
enclen = val;
|
||||||
|
val = b32->decode(rawbuf, &rawlen, encbuf, enclen);
|
||||||
|
|
||||||
|
fail_unless(rawlen == 5, "raw length was %d not 5", rawlen);
|
||||||
|
fail_unless(val == 5, "val was not 5 but %d", val);
|
||||||
|
for (i = 0; i < rawlen; i++) {
|
||||||
|
fail_unless(rawbuf[i] == 'A');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_base32_create_tests()
|
test_base32_create_tests()
|
||||||
{
|
{
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Base32");
|
tc = tcase_create("Base32");
|
||||||
tcase_add_test(tc, test_base32_encode);
|
tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES);
|
||||||
tcase_add_test(tc, test_base32_decode);
|
tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES);
|
||||||
tcase_add_test(tc, test_base32_5to8_8to5);
|
tcase_add_test(tc, test_base32_5to8_8to5);
|
||||||
|
tcase_add_test(tc, test_base32_blksize);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,13 @@
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
#define TUPLES 5
|
||||||
|
|
||||||
static struct tuple
|
static struct tuple
|
||||||
{
|
{
|
||||||
char *a;
|
char *a;
|
||||||
char *b;
|
char *b;
|
||||||
} testpairs[] = {
|
} testpairs[TUPLES] = {
|
||||||
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
|
{ "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" },
|
||||||
{ "abc1231", "ywjJmtiZmq" },
|
{ "abc1231", "ywjJmtiZmq" },
|
||||||
{
|
{
|
||||||
|
@ -59,7 +61,7 @@ static struct tuple
|
||||||
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
|
"776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321"
|
||||||
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
|
"0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba"
|
||||||
},
|
},
|
||||||
{ NULL, NULL }
|
{ "", "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(test_base64_encode)
|
START_TEST(test_base64_encode)
|
||||||
|
@ -68,18 +70,14 @@ START_TEST(test_base64_encode)
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b64;
|
struct encoder *b64;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
|
||||||
|
|
||||||
b64 = get_base64_encoder();
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b64->encode(buf, &len, testpairs[i].a, strlen(testpairs[i].a));
|
val = b64->encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a));
|
||||||
|
|
||||||
fail_unless(val > 0, strerror(errno));
|
fail_unless(strcmp(buf, testpairs[_i].b) == 0,
|
||||||
fail_unless(strcmp(buf, testpairs[i].b) == 0,
|
"'%s' != '%s'", buf, testpairs[_i].b);
|
||||||
"'%s' != '%s'", buf, testpairs[i].b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -89,18 +87,56 @@ START_TEST(test_base64_decode)
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
struct encoder *b64;
|
struct encoder *b64;
|
||||||
int val;
|
int val;
|
||||||
int i;
|
|
||||||
|
|
||||||
b64 = get_base64_encoder();
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
for (i = 0; testpairs[i].a != NULL; i++) {
|
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
val = b64->decode(buf, &len, testpairs[i].b, strlen(testpairs[i].b));
|
val = b64->decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b));
|
||||||
|
|
||||||
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,
|
||||||
"'%s' != '%s'", buf, testpairs[i].a);
|
"'%s' != '%s'", buf, testpairs[_i].a);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_base64_blksize)
|
||||||
|
{
|
||||||
|
size_t rawlen;
|
||||||
|
size_t enclen;
|
||||||
|
char *rawbuf;
|
||||||
|
char *encbuf;
|
||||||
|
struct encoder *b64;
|
||||||
|
int i;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
b64 = get_base64_encoder();
|
||||||
|
|
||||||
|
rawlen = b64->blocksize_raw();
|
||||||
|
enclen = b64->blocksize_encoded();
|
||||||
|
|
||||||
|
rawbuf = malloc(rawlen + 16);
|
||||||
|
encbuf = malloc(enclen + 16);
|
||||||
|
|
||||||
|
for (i = 0; i < rawlen; i++) {
|
||||||
|
rawbuf[i] = 'A';
|
||||||
|
}
|
||||||
|
rawbuf[i] = 0;
|
||||||
|
|
||||||
|
val = b64->encode(encbuf, &enclen, rawbuf, rawlen);
|
||||||
|
|
||||||
|
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
||||||
|
fail_unless(enclen == 3, "encoded %d bytes, not 3", enclen);
|
||||||
|
fail_unless(val == 4, "encoded string %s was length %d", encbuf, val);
|
||||||
|
|
||||||
|
memset(rawbuf, 0, rawlen + 16);
|
||||||
|
|
||||||
|
enclen = val;
|
||||||
|
val = b64->decode(rawbuf, &rawlen, encbuf, enclen);
|
||||||
|
|
||||||
|
fail_unless(rawlen == 3, "raw length was %d not 3", rawlen);
|
||||||
|
fail_unless(val == 3);
|
||||||
|
for (i = 0; i < rawlen; i++) {
|
||||||
|
fail_unless(rawbuf[i] == 'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -111,8 +147,9 @@ test_base64_create_tests()
|
||||||
TCase *tc;
|
TCase *tc;
|
||||||
|
|
||||||
tc = tcase_create("Base64");
|
tc = tcase_create("Base64");
|
||||||
tcase_add_test(tc, test_base64_encode);
|
tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES);
|
||||||
tcase_add_test(tc, test_base64_decode);
|
tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES);
|
||||||
|
tcase_add_test(tc, test_base64_blksize);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
62
tests/dns.c
62
tests/dns.c
|
@ -33,14 +33,14 @@
|
||||||
|
|
||||||
static void dump_packet(char *, size_t);
|
static void dump_packet(char *, size_t);
|
||||||
|
|
||||||
static char queryPacket[] =
|
static char query_packet[] =
|
||||||
"\x05\x39\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x2D\x41\x6A\x62\x63"
|
"\x05\x39\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x2D\x41\x6A\x62\x63"
|
||||||
"\x75\x79\x74\x63\x70\x65\x62\x30\x67\x71\x30\x6C\x74\x65\x62\x75\x78"
|
"\x75\x79\x74\x63\x70\x65\x62\x30\x67\x71\x30\x6C\x74\x65\x62\x75\x78"
|
||||||
"\x67\x69\x64\x75\x6E\x62\x73\x73\x61\x33\x64\x66\x6F\x6E\x30\x63\x61"
|
"\x67\x69\x64\x75\x6E\x62\x73\x73\x61\x33\x64\x66\x6F\x6E\x30\x63\x61"
|
||||||
"\x7A\x64\x62\x6F\x72\x71\x71\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00"
|
"\x7A\x64\x62\x6F\x72\x71\x71\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00"
|
||||||
"\x0A\x00\x01\x00\x00\x29\x10\x00\x00\x00\x80\x00\x00\x00";
|
"\x0A\x00\x01\x00\x00\x29\x10\x00\x00\x00\x80\x00\x00\x00";
|
||||||
|
|
||||||
static char answerPacket[] =
|
static char answer_packet[] =
|
||||||
"\x05\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
|
"\x05\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
|
||||||
"\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
|
"\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
|
||||||
"\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
|
"\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
|
||||||
|
@ -48,7 +48,7 @@ static char answerPacket[] =
|
||||||
"\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F"
|
"\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F"
|
||||||
"\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64";
|
"\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64";
|
||||||
|
|
||||||
static char answerPacketHighTransId[] =
|
static char answer_packet_high_trans_id[] =
|
||||||
"\x85\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
|
"\x85\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
|
||||||
"\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
|
"\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
|
||||||
"\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
|
"\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
|
||||||
|
@ -87,14 +87,14 @@ START_TEST(test_encode_query)
|
||||||
}
|
}
|
||||||
strcpy(d, topdomain);
|
strcpy(d, topdomain);
|
||||||
ret = dns_encode(buf, len, &q, QR_QUERY, resolv, strlen(resolv));
|
ret = dns_encode(buf, len, &q, QR_QUERY, resolv, strlen(resolv));
|
||||||
len = sizeof(queryPacket) - 1; /* Skip extra null character */
|
len = sizeof(query_packet) - 1; /* Skip extra null character */
|
||||||
|
|
||||||
if (strncmp(queryPacket, buf, sizeof(queryPacket)) || ret != len) {
|
if (strncmp(query_packet, buf, sizeof(query_packet)) || ret != len) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
dump_packet(queryPacket, len);
|
dump_packet(query_packet, len);
|
||||||
dump_packet(buf, ret);
|
dump_packet(buf, ret);
|
||||||
}
|
}
|
||||||
fail_unless(strncmp(queryPacket, buf, sizeof(queryPacket)) == 0, "Did not compile expected packet");
|
fail_unless(strncmp(query_packet, buf, sizeof(query_packet)) == 0, "Did not compile expected packet");
|
||||||
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -110,10 +110,10 @@ START_TEST(test_decode_query)
|
||||||
memset(&q, 0, sizeof(struct query));
|
memset(&q, 0, sizeof(struct query));
|
||||||
memset(&buf, 0, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
q.id = 0;
|
q.id = 0;
|
||||||
len = sizeof(queryPacket) - 1;
|
len = sizeof(query_packet) - 1;
|
||||||
enc = get_base32_encoder();
|
enc = get_base32_encoder();
|
||||||
|
|
||||||
dns_decode(buf, sizeof(buf), &q, QR_QUERY, queryPacket, len);
|
dns_decode(buf, sizeof(buf), &q, QR_QUERY, query_packet, len);
|
||||||
domain = strstr(q.name, topdomain);
|
domain = strstr(q.name, topdomain);
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
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);
|
||||||
|
@ -139,9 +139,9 @@ START_TEST(test_encode_response)
|
||||||
q.id = 1337;
|
q.id = 1337;
|
||||||
|
|
||||||
ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData));
|
ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData));
|
||||||
len = sizeof(answerPacket) - 1; /* Skip extra null character */
|
len = sizeof(answer_packet) - 1; /* Skip extra null character */
|
||||||
|
|
||||||
fail_unless(strncmp(answerPacket, buf, sizeof(answerPacket)) == 0, "Did not compile expected packet");
|
fail_unless(strncmp(answer_packet, buf, sizeof(answer_packet)) == 0, "Did not compile expected packet");
|
||||||
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -156,7 +156,7 @@ START_TEST(test_decode_response)
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
memset(&buf, 0, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
|
||||||
ret = dns_decode(buf, len, &q, QR_ANSWER, answerPacket, sizeof(answerPacket)-1);
|
ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet, sizeof(answer_packet)-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), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
||||||
fail_unless(q.id == 0x0539);
|
fail_unless(q.id == 0x0539);
|
||||||
|
@ -173,12 +173,45 @@ START_TEST(test_decode_response_with_high_trans_id)
|
||||||
len = sizeof(buf);
|
len = sizeof(buf);
|
||||||
memset(&buf, 0, sizeof(buf));
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
|
||||||
ret = dns_decode(buf, len, &q, QR_ANSWER, answerPacketHighTransId, sizeof(answerPacketHighTransId)-1);
|
ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id)-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), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
|
||||||
fail_unless(q.id == 0x8539, "q.id was %08X instead of %08X!", q.id, 0x8539);
|
fail_unless(q.id == 0x8539, "q.id was %08X instead of %08X!", q.id, 0x8539);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_get_id_short_packet)
|
||||||
|
{
|
||||||
|
char buf[5];
|
||||||
|
int len;
|
||||||
|
unsigned short id;
|
||||||
|
|
||||||
|
len = sizeof(buf);
|
||||||
|
memset(&buf, 5, sizeof(buf));
|
||||||
|
|
||||||
|
id = dns_get_id(buf, len);
|
||||||
|
fail_unless(id == 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_get_id_low)
|
||||||
|
{
|
||||||
|
unsigned short id;
|
||||||
|
|
||||||
|
id = dns_get_id(answer_packet, sizeof(answer_packet));
|
||||||
|
fail_unless(id == 1337);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_get_id_high)
|
||||||
|
{
|
||||||
|
unsigned short id;
|
||||||
|
|
||||||
|
id = dns_get_id(answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id));
|
||||||
|
fail_unless(id == 0x8539);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dump_packet(char *buf, size_t len)
|
dump_packet(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -209,6 +242,9 @@ test_dns_create_tests()
|
||||||
tcase_add_test(tc, test_encode_response);
|
tcase_add_test(tc, test_encode_response);
|
||||||
tcase_add_test(tc, test_decode_response);
|
tcase_add_test(tc, test_decode_response);
|
||||||
tcase_add_test(tc, test_decode_response_with_high_trans_id);
|
tcase_add_test(tc, test_decode_response_with_high_trans_id);
|
||||||
|
tcase_add_test(tc, test_get_id_short_packet);
|
||||||
|
tcase_add_test(tc, test_get_id_low);
|
||||||
|
tcase_add_test(tc, test_get_id_high);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2009 Erik Ekman <yarrick@kryo.se>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <check.h>
|
||||||
|
|
||||||
|
#include "fw_query.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
START_TEST(test_fw_query_simple)
|
||||||
|
{
|
||||||
|
struct fw_query q;
|
||||||
|
struct fw_query *qp;
|
||||||
|
|
||||||
|
q.addrlen = 33;
|
||||||
|
q.id = 0x848A;
|
||||||
|
|
||||||
|
fw_query_init();
|
||||||
|
|
||||||
|
/* Test empty cache */
|
||||||
|
fw_query_get(0x848A, &qp);
|
||||||
|
fail_unless(qp == NULL);
|
||||||
|
|
||||||
|
fw_query_put(&q);
|
||||||
|
|
||||||
|
/* Test cache with one entry */
|
||||||
|
fw_query_get(0x848A, &qp);
|
||||||
|
fail_unless(qp->addrlen == q.addrlen);
|
||||||
|
fail_unless(qp->id == q.id);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_fw_query_edge)
|
||||||
|
{
|
||||||
|
struct fw_query q;
|
||||||
|
struct fw_query *qp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fw_query_init();
|
||||||
|
|
||||||
|
q.addrlen = 33;
|
||||||
|
q.id = 0x848A;
|
||||||
|
fw_query_put(&q);
|
||||||
|
|
||||||
|
for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) {
|
||||||
|
q.addrlen++;
|
||||||
|
q.id++;
|
||||||
|
fw_query_put(&q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The query should still be cached */
|
||||||
|
fw_query_get(0x848A, &qp);
|
||||||
|
fail_unless(qp->addrlen == 33);
|
||||||
|
fail_unless(qp->id == 0x848A);
|
||||||
|
|
||||||
|
q.addrlen++;
|
||||||
|
q.id++;
|
||||||
|
fw_query_put(&q);
|
||||||
|
|
||||||
|
/* but now it is overwritten */
|
||||||
|
fw_query_get(0x848A, &qp);
|
||||||
|
fail_unless(qp == NULL);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
TCase *
|
||||||
|
test_fw_query_create_tests()
|
||||||
|
{
|
||||||
|
TCase *tc;
|
||||||
|
|
||||||
|
tc = tcase_create("Forwarded query");
|
||||||
|
tcase_add_test(tc, test_fw_query_simple);
|
||||||
|
tcase_add_test(tc, test_fw_query_edge);
|
||||||
|
|
||||||
|
return tc;
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ START_TEST(test_login_hash)
|
||||||
int len;
|
int len;
|
||||||
int seed;
|
int seed;
|
||||||
|
|
||||||
len = 16;
|
len = sizeof(ans);
|
||||||
seed = 15;
|
seed = 15;
|
||||||
|
|
||||||
memset(ans, 0, sizeof(ans));
|
memset(ans, 0, sizeof(ans));
|
||||||
|
@ -37,6 +37,26 @@ START_TEST(test_login_hash)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_login_hash_short)
|
||||||
|
{
|
||||||
|
char ans[8];
|
||||||
|
char check[sizeof(ans)];
|
||||||
|
char pass[32] = "iodine is the shit";
|
||||||
|
int len;
|
||||||
|
int seed;
|
||||||
|
|
||||||
|
len = sizeof(ans);
|
||||||
|
seed = 15;
|
||||||
|
|
||||||
|
memset(ans, 0, sizeof(ans));
|
||||||
|
memset(check, 0, sizeof(check));
|
||||||
|
|
||||||
|
/* If len < 16, it should do nothing */
|
||||||
|
login_calculate(ans, len, pass, seed);
|
||||||
|
fail_if(memcmp(ans, check, sizeof(ans)));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
TCase *
|
TCase *
|
||||||
test_login_create_tests()
|
test_login_create_tests()
|
||||||
{
|
{
|
||||||
|
@ -44,6 +64,7 @@ test_login_create_tests()
|
||||||
|
|
||||||
tc = tcase_create("Login");
|
tc = tcase_create("Login");
|
||||||
tcase_add_test(tc, test_login_hash);
|
tcase_add_test(tc, test_login_hash);
|
||||||
|
tcase_add_test(tc, test_login_hash_short);
|
||||||
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
135
tests/read.c
135
tests/read.c
|
@ -83,14 +83,42 @@ START_TEST(test_read_putlong)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_read_name)
|
START_TEST(test_read_name_empty_loop)
|
||||||
{
|
{
|
||||||
unsigned char emptyloop[] = {
|
unsigned char emptyloop[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
||||||
|
char buf[1024];
|
||||||
|
char *data;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
data = (char*) emptyloop + sizeof(HEADER);
|
||||||
|
buf[1023] = 'A';
|
||||||
|
rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023);
|
||||||
|
fail_unless(buf[1023] == 'A');
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_read_name_inf_loop)
|
||||||
|
{
|
||||||
unsigned char infloop[] = {
|
unsigned char infloop[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 };
|
||||||
|
char buf[1024];
|
||||||
|
char *data;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
data = (char*) infloop + sizeof(HEADER);
|
||||||
|
buf[4] = '\a';
|
||||||
|
rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4);
|
||||||
|
fail_unless(buf[4] == '\a');
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_read_name_longname)
|
||||||
|
{
|
||||||
unsigned char longname[] =
|
unsigned char longname[] =
|
||||||
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
|
@ -100,12 +128,61 @@ START_TEST(test_read_name)
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
"\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA"
|
||||||
"\x00\x00\x01\x00\x01";
|
"\x00\x00\x01\x00\x01";
|
||||||
|
char buf[1024];
|
||||||
|
char *data;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
data = (char*) longname + sizeof(HEADER);
|
||||||
|
buf[256] = '\a';
|
||||||
|
rv = readname((char*) longname, sizeof(longname), &data, buf, 256);
|
||||||
|
fail_unless(buf[256] == '\a');
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_read_name_onejump)
|
||||||
|
{
|
||||||
unsigned char onejump[] =
|
unsigned char onejump[] =
|
||||||
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
"AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00"
|
||||||
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
|
"\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00";
|
||||||
|
char buf[1024];
|
||||||
|
char *data;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
data = (char*) onejump + sizeof(HEADER);
|
||||||
|
rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256);
|
||||||
|
fail_unless(rv == 9);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_read_name_badjump_start)
|
||||||
|
{
|
||||||
unsigned char badjump[] = {
|
unsigned char badjump[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
||||||
|
unsigned char *jumper;
|
||||||
|
char buf[1024];
|
||||||
|
char *data;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/* This test uses malloc to cause segfault if jump is executed */
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
jumper = malloc(sizeof(badjump));
|
||||||
|
if (jumper) {
|
||||||
|
memcpy(jumper, badjump, sizeof(badjump));
|
||||||
|
data = (char*) jumper + sizeof(HEADER);
|
||||||
|
rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256);
|
||||||
|
|
||||||
|
fail_unless(rv == 0);
|
||||||
|
fail_unless(buf[0] == 0);
|
||||||
|
}
|
||||||
|
free(jumper);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_read_name_badjump_second)
|
||||||
|
{
|
||||||
unsigned char badjump2[] = {
|
unsigned char badjump2[] = {
|
||||||
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 };
|
||||||
|
@ -114,42 +191,7 @@ START_TEST(test_read_name)
|
||||||
char *data;
|
char *data;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
/* This test uses malloc to cause segfault if jump is executed */
|
||||||
data = (char*) emptyloop + sizeof(HEADER);
|
|
||||||
buf[1023] = 'A';
|
|
||||||
rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023);
|
|
||||||
fail_unless(buf[1023] == 'A', NULL);
|
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
data = (char*) infloop + sizeof(HEADER);
|
|
||||||
buf[4] = '\a';
|
|
||||||
rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4);
|
|
||||||
fail_unless(buf[4] == '\a', NULL);
|
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
data = (char*) longname + sizeof(HEADER);
|
|
||||||
buf[256] = '\a';
|
|
||||||
rv = readname((char*) longname, sizeof(longname), &data, buf, 256);
|
|
||||||
fail_unless(buf[256] == '\a', NULL);
|
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
data = (char*) onejump + sizeof(HEADER);
|
|
||||||
rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256);
|
|
||||||
fail_unless(rv == 9, NULL);
|
|
||||||
|
|
||||||
/* These two tests use malloc to cause segfault if jump is executed */
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
jumper = malloc(sizeof(badjump));
|
|
||||||
if (jumper) {
|
|
||||||
memcpy(jumper, badjump, sizeof(badjump));
|
|
||||||
data = (char*) jumper + sizeof(HEADER);
|
|
||||||
rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256);
|
|
||||||
|
|
||||||
fail_unless(rv == 0, NULL);
|
|
||||||
fail_unless(buf[0] == 0, NULL);
|
|
||||||
}
|
|
||||||
free(jumper);
|
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
jumper = malloc(sizeof(badjump2));
|
jumper = malloc(sizeof(badjump2));
|
||||||
if (jumper) {
|
if (jumper) {
|
||||||
|
@ -157,7 +199,7 @@ START_TEST(test_read_name)
|
||||||
data = (char*) jumper + sizeof(HEADER);
|
data = (char*) jumper + sizeof(HEADER);
|
||||||
rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256);
|
rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256);
|
||||||
|
|
||||||
fail_unless(rv == 4, NULL);
|
fail_unless(rv == 4);
|
||||||
fail_unless(strcmp("BA.", buf) == 0,
|
fail_unless(strcmp("BA.", buf) == 0,
|
||||||
"buf is not BA: %s", buf);
|
"buf is not BA: %s", buf);
|
||||||
}
|
}
|
||||||
|
@ -180,7 +222,7 @@ START_TEST(test_putname)
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, domain);
|
ret = putname(&b, 256, domain);
|
||||||
|
|
||||||
fail_unless(ret == strlen(domain) + 1, NULL);
|
fail_unless(ret == strlen(domain) + 1);
|
||||||
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
|
fail_unless(strncmp(buf, out, ret) == 0, "Happy flow failed");
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
@ -201,8 +243,8 @@ START_TEST(test_putname_nodot)
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, nodot);
|
ret = putname(&b, 256, nodot);
|
||||||
|
|
||||||
fail_unless(ret == -1, NULL);
|
fail_unless(ret == -1);
|
||||||
fail_unless(b == buf, NULL);
|
fail_unless(b == buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -226,8 +268,8 @@ START_TEST(test_putname_toolong)
|
||||||
b = buf;
|
b = buf;
|
||||||
ret = putname(&b, 256, toolong);
|
ret = putname(&b, 256, toolong);
|
||||||
|
|
||||||
fail_unless(ret == -1, NULL);
|
fail_unless(ret == -1);
|
||||||
fail_unless(b == buf, NULL);
|
fail_unless(b == buf);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -241,7 +283,12 @@ test_read_create_tests()
|
||||||
tcase_set_timeout(tc, 60);
|
tcase_set_timeout(tc, 60);
|
||||||
tcase_add_test(tc, test_read_putshort);
|
tcase_add_test(tc, test_read_putshort);
|
||||||
tcase_add_test(tc, test_read_putlong);
|
tcase_add_test(tc, test_read_putlong);
|
||||||
tcase_add_test(tc, test_read_name);
|
tcase_add_test(tc, test_read_name_empty_loop);
|
||||||
|
tcase_add_test(tc, test_read_name_inf_loop);
|
||||||
|
tcase_add_test(tc, test_read_name_longname);
|
||||||
|
tcase_add_test(tc, test_read_name_onejump);
|
||||||
|
tcase_add_test(tc, test_read_name_badjump_start);
|
||||||
|
tcase_add_test(tc, test_read_name_badjump_second);
|
||||||
tcase_add_test(tc, test_putname);
|
tcase_add_test(tc, test_putname);
|
||||||
tcase_add_test(tc, test_putname_nodot);
|
tcase_add_test(tc, test_putname_nodot);
|
||||||
tcase_add_test(tc, test_putname_toolong);
|
tcase_add_test(tc, test_putname_toolong);
|
||||||
|
|
|
@ -53,6 +53,9 @@ main()
|
||||||
test = test_user_create_tests();
|
test = test_user_create_tests();
|
||||||
suite_add_tcase(iodine, test);
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
|
test = test_fw_query_create_tests();
|
||||||
|
suite_add_tcase(iodine, test);
|
||||||
|
|
||||||
runner = srunner_create(iodine);
|
runner = srunner_create(iodine);
|
||||||
srunner_run_all(runner, CK_NORMAL);
|
srunner_run_all(runner, CK_NORMAL);
|
||||||
failed = srunner_ntests_failed(runner);
|
failed = srunner_ntests_failed(runner);
|
||||||
|
|
|
@ -24,6 +24,7 @@ TCase *test_encoding_create_tests();
|
||||||
TCase *test_read_create_tests();
|
TCase *test_read_create_tests();
|
||||||
TCase *test_login_create_tests();
|
TCase *test_login_create_tests();
|
||||||
TCase *test_user_create_tests();
|
TCase *test_user_create_tests();
|
||||||
|
TCase *test_fw_query_create_tests();
|
||||||
|
|
||||||
char *va_str(const char *, ...);
|
char *va_str(const char *, ...);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue