mirror of
https://github.com/yarrick/iodine.git
synced 2024-12-28 10:37:52 +00:00
#6 reworked encoding
This commit is contained in:
parent
faea33eaae
commit
dbfecb5be6
150
src/base32.c
150
src/base32.c
@ -18,140 +18,160 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "encoding.h"
|
||||
#include "base32.h"
|
||||
|
||||
static const char cb32[] =
|
||||
"abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static unsigned char rev32[128];
|
||||
static int reverse_init = 0;
|
||||
|
||||
static struct encoder base32_encoder =
|
||||
{
|
||||
"BASE32",
|
||||
base32_encode,
|
||||
base32_decode,
|
||||
base32_handles_dots,
|
||||
base32_handles_dots
|
||||
};
|
||||
|
||||
struct encoder
|
||||
*get_base32_encoder()
|
||||
{
|
||||
return &base32_encoder;
|
||||
}
|
||||
|
||||
int
|
||||
base32_encode(char **buf, size_t *buflen, const void *data, size_t size)
|
||||
base32_handles_dots()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
|
||||
{
|
||||
size_t newsize;
|
||||
char *newbuf;
|
||||
char *s;
|
||||
char *p;
|
||||
char *q;
|
||||
size_t maxsize;
|
||||
unsigned char *s;
|
||||
unsigned char *p;
|
||||
unsigned char *q;
|
||||
int i;
|
||||
|
||||
newsize = 8 * (size / 5 + 1) + 1;
|
||||
if (newsize > *buflen) {
|
||||
if ((newbuf = realloc(*buf, newsize)) == NULL) {
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
*buflen = 0;
|
||||
return 0;
|
||||
}
|
||||
memset(buf, 0, *buflen);
|
||||
|
||||
*buf = newbuf;
|
||||
*buflen = newsize;
|
||||
/* how many chars can we encode within the buf */
|
||||
maxsize = 5 * (*buflen / 8 - 1) - 1;
|
||||
/* how big will the encoded data be */
|
||||
newsize = 8 * (size / 5 + 1) + 1;
|
||||
/* if the buffer is too small, eat some of the data */
|
||||
if (*buflen < newsize) {
|
||||
size = maxsize;
|
||||
}
|
||||
|
||||
p = s = *buf;
|
||||
q = (char*)data;
|
||||
p = s = (unsigned char *) buf;
|
||||
q = (unsigned char *)data;
|
||||
|
||||
for(i=0;i<size;i+=5) {
|
||||
p[0] = cb32[(q[0] >> 3)];
|
||||
p[1] = cb32[((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6)];
|
||||
p[0] = cb32[((q[0] & 0xf8) >> 3)];
|
||||
p[1] = cb32[(((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6))];
|
||||
p[2] = (i+1 < size) ? cb32[((q[1] & 0x3e) >> 1)] : '\0';
|
||||
p[3] = (i+1 < size) ? cb32[((q[1] & 0x01) << 4) | ((q[2] & 0xf0) >> 4)] : '\0';
|
||||
p[4] = (i+2 < size) ? cb32[((q[2] & 0x0f) << 1) | ((q[3] & 0x80) >> 7)] : '\0';
|
||||
p[5] = (i+3 < size) ? cb32[((q[3] & 0x3e) >> 2)] : '\0';
|
||||
p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) > 5)] : '\0';
|
||||
p[5] = (i+3 < size) ? cb32[((q[3] & 0x7c) >> 2)] : '\0';
|
||||
p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) >> 5)] : '\0';
|
||||
p[7] = (i+4 < size) ? cb32[((q[4] & 0x1f))] : '\0';
|
||||
|
||||
q += 5;
|
||||
p += 8;
|
||||
}
|
||||
*p = 0;
|
||||
return strlen(s);
|
||||
|
||||
/* store number of bytes from data that was used */
|
||||
*buflen = size;
|
||||
|
||||
return strlen(buf) - 1;
|
||||
}
|
||||
|
||||
#define DECODE_ERROR 0xffffffff
|
||||
#define REV32(x) rev32[(int) (x)]
|
||||
|
||||
static int
|
||||
pos(char c)
|
||||
decode_token(const unsigned char *t, unsigned char *data, size_t len)
|
||||
{
|
||||
const char *p;
|
||||
for (p = cb32; *p; p++)
|
||||
if (*p == c)
|
||||
return p - cb32;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_token(const char *t, char *data)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(t);
|
||||
|
||||
if (len < 2)
|
||||
return 0;
|
||||
|
||||
data[0] = ((pos(t[0]) & 0x1f) << 3) |
|
||||
((pos(t[1]) & 0x1c) >> 2);
|
||||
data[0] = ((REV32(t[0]) & 0x1f) << 3) |
|
||||
((REV32(t[1]) & 0x1c) >> 2);
|
||||
|
||||
if (len < 4)
|
||||
return 1;
|
||||
|
||||
data[1] = ((pos(t[1]) & 0x03) << 6) |
|
||||
((pos(t[2]) & 0x1f) << 1) |
|
||||
((pos(t[3]) & 0x10) >> 4);
|
||||
data[1] = ((REV32(t[1]) & 0x03) << 6) |
|
||||
((REV32(t[2]) & 0x1f) << 1) |
|
||||
((REV32(t[3]) & 0x10) >> 4);
|
||||
|
||||
if (len < 5)
|
||||
return 2;
|
||||
|
||||
data[2] = ((pos(t[3]) & 0x0f) << 4) |
|
||||
((pos(t[4]) & 0x1e) >> 1);
|
||||
data[2] = ((REV32(t[3]) & 0x0f) << 4) |
|
||||
((REV32(t[4]) & 0x1e) >> 1);
|
||||
|
||||
if (len < 7)
|
||||
return 3;
|
||||
|
||||
data[3] = ((pos(t[4]) & 0x01) << 7) |
|
||||
((pos(t[5]) & 0x1f) << 2) |
|
||||
((pos(t[6]) & 0x18) >> 3);
|
||||
data[3] = ((REV32(t[4]) & 0x01) << 7) |
|
||||
((REV32(t[5]) & 0x1f) << 2) |
|
||||
((REV32(t[6]) & 0x18) >> 3);
|
||||
|
||||
if (len < 8)
|
||||
return 4;
|
||||
|
||||
data[4] = ((pos(t[6]) & 0x07) << 5) |
|
||||
((pos(t[7]) & 0x1f));
|
||||
data[4] = ((REV32(t[6]) & 0x07) << 5) |
|
||||
((REV32(t[7]) & 0x1f));
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
int
|
||||
base32_decode(void **buf, size_t *buflen, const char *str)
|
||||
base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
|
||||
{
|
||||
unsigned char *q;
|
||||
size_t newsize;
|
||||
size_t maxsize;
|
||||
const char *p;
|
||||
char *newbuf;
|
||||
unsigned char c;
|
||||
int len;
|
||||
|
||||
newsize = 5 * (strlen(str) / 8 + 1) + 1;
|
||||
if (newsize > *buflen) {
|
||||
if ((newbuf = realloc(*buf, newsize)) == NULL) {
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
*buflen = 0;
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
|
||||
*buf = newbuf;
|
||||
*buflen = newsize;
|
||||
if (!reverse_init) {
|
||||
for (i = 0; i < 32; i++) {
|
||||
c = cb32[i];
|
||||
rev32[(int) c] = i;
|
||||
}
|
||||
reverse_init = 1;
|
||||
}
|
||||
|
||||
/* chars needed to decode slen */
|
||||
newsize = 5 * (slen / 8 + 1) + 1;
|
||||
/* encoded chars that fit in buf */
|
||||
maxsize = 8 * (*buflen / 5 + 1) + 1;
|
||||
/* if the buffer is too small, eat some of the data */
|
||||
if (*buflen < newsize) {
|
||||
slen = maxsize;
|
||||
}
|
||||
|
||||
q = *buf;
|
||||
q = buf;
|
||||
for (p = str; *p && strchr(cb32, *p); p += 8) {
|
||||
len = decode_token(p, (char *) q);
|
||||
len = decode_token((unsigned char *) p, (unsigned char *) q, slen);
|
||||
q += len;
|
||||
slen -= 8;
|
||||
|
||||
if (len < 5)
|
||||
break;
|
||||
}
|
||||
*q = '\0';
|
||||
|
||||
return q - (unsigned char *) *buf;
|
||||
return q - (unsigned char *) buf;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,9 @@
|
||||
#ifndef __BASE32_H__
|
||||
#define __BASE32_H__
|
||||
|
||||
int base32_encode(char **, size_t *, const void *, size_t);
|
||||
int base32_decode(void **, size_t *, const char *);
|
||||
struct encoder *get_base32_encoder(void);
|
||||
int base32_handles_dots();
|
||||
int base32_encode(char *, size_t *, const void *, size_t);
|
||||
int base32_decode(void *, size_t *, const char *, size_t);
|
||||
|
||||
#endif
|
||||
|
230
src/encoding.c
230
src/encoding.c
@ -14,207 +14,71 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include "encoding.h"
|
||||
|
||||
/* For FreeBSD */
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#define SPACING 63
|
||||
#define ENC_CHUNK 8
|
||||
#define RAW_CHUNK 5
|
||||
|
||||
static const char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ98765-";
|
||||
static const char padder[] = " 1234";
|
||||
static char reverse32[128];
|
||||
static int reverse_init = 0;
|
||||
|
||||
/* Eat 5 bytes from src, write 8 bytes to dest */
|
||||
static void
|
||||
encode_chunk(char *dest, const char *src)
|
||||
int
|
||||
inline_dotify(char *buf, size_t buflen)
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned dots;
|
||||
unsigned pos;
|
||||
unsigned total;
|
||||
char *reader, *writer;
|
||||
|
||||
*dest++ = base32[(*src & 0xF8) >> 3]; /* 1111 1000 first byte */
|
||||
total = strlen(buf);
|
||||
dots = total / 62;
|
||||
|
||||
c = (*src++ & 0x07) << 2; /* 0000 0111 first byte */
|
||||
c |= ((*src & 0xC0) >> 6); /* 1100 0000 second byte */
|
||||
*dest++ = base32[(int) c];
|
||||
writer = buf;
|
||||
writer += total;
|
||||
writer += dots;
|
||||
|
||||
*dest++ = base32[(*src & 0x3E) >> 1]; /* 0011 1110 second byte */
|
||||
total += dots;
|
||||
if (strlen(buf) + dots > buflen) {
|
||||
writer = buf;
|
||||
writer += buflen;
|
||||
total = buflen;
|
||||
}
|
||||
|
||||
c = (*src++ & 0x01) << 4; /* 0000 0001 second byte */
|
||||
c |= ((*src & 0xF0) >> 4); /* 1111 0000 third byte */
|
||||
*dest++ = base32[(int) c];
|
||||
|
||||
c = (*src++ & 0x0F) << 1; /* 0000 1111 third byte */
|
||||
c |= ((*src & 0x80) >> 7); /* 1000 0000 fourth byte */
|
||||
*dest++ = base32[(int) c];
|
||||
|
||||
*dest++ = base32[(*src & 0x7C) >> 2]; /* 0111 1100 fourth byte */
|
||||
reader = writer - dots;
|
||||
pos = (unsigned) (reader - buf) + 1;
|
||||
|
||||
c = (*src++ & 0x03) << 3; /* 0000 0011 fourth byte */
|
||||
c |= ((*src & 0xE0) >> 5); /* 1110 0000 fifth byte */
|
||||
*dest++ = base32[(int) c];
|
||||
|
||||
*dest++ = base32[*src++ & 0x1F]; /* 0001 1111 fifth byte */
|
||||
}
|
||||
|
||||
/* Eat 8 bytes from src, write 5 bytes to dest */
|
||||
static void
|
||||
decode_chunk(char *dest, char *src)
|
||||
{
|
||||
unsigned char c;
|
||||
int i;
|
||||
|
||||
if (!reverse_init) {
|
||||
for (i = 0; i < 32; i++) {
|
||||
c = base32[i];
|
||||
reverse32[(int) c] = i;
|
||||
while (dots) {
|
||||
if (pos % 62 == 0) {
|
||||
*writer-- = '.';
|
||||
dots--;
|
||||
}
|
||||
reverse_init = 1;
|
||||
*writer-- = *reader--;
|
||||
pos--;
|
||||
}
|
||||
|
||||
c = reverse32[(int) *src++] << 3; /* Take bits 11111 from byte 1 */
|
||||
c |= (reverse32[(int) *src] & 0x1C) >> 2; /* Take bits 11100 from byte 2 */
|
||||
*dest++ = c;
|
||||
|
||||
c = (reverse32[(int) *src++] & 0x3) << 6; /* Take bits 00011 from byte 2 */
|
||||
c |= reverse32[(int) *src++] << 1; /* Take bits 11111 from byte 3 */
|
||||
c |= (reverse32[(int) *src] & 0x10) >> 4; /* Take bits 10000 from byte 4 */
|
||||
*dest++ = c;
|
||||
|
||||
c = (reverse32[(int) *src++] & 0xF) << 4; /* Take bits 01111 from byte 4 */
|
||||
c |= (reverse32[(int) *src] & 0x1E) >> 1; /* Take bits 11110 from byte 5 */
|
||||
*dest++ = c;
|
||||
|
||||
c = reverse32[(int) *src++] << 7; /* Take bits 00001 from byte 5 */
|
||||
c |= reverse32[(int) *src++] << 2; /* Take bits 11111 from byte 6 */
|
||||
c |= (reverse32[(int) *src] & 0x18) >> 3; /* Take bits 11000 from byte 7 */
|
||||
*dest++ = c;
|
||||
|
||||
c = (reverse32[(int) *src++] & 0x7) << 5; /* Take bits 00111 from byte 7 */
|
||||
c |= reverse32[(int) *src++]; /* Take bits 11111 from byte 8 */
|
||||
*dest++ = c;
|
||||
/* return new length of string */
|
||||
return total;
|
||||
}
|
||||
|
||||
int
|
||||
encode_data(const char *buf, const size_t len, int space, char *dest)
|
||||
int
|
||||
inline_undotify(char *buf, size_t len)
|
||||
{
|
||||
int final;
|
||||
int write;
|
||||
int realwrite;
|
||||
int chunks;
|
||||
int leftovers;
|
||||
int i;
|
||||
char encoded[255];
|
||||
char padding[5];
|
||||
const char *dp;
|
||||
char *pp;
|
||||
char *ep;
|
||||
unsigned pos;
|
||||
unsigned dots;
|
||||
char *reader, *writer;
|
||||
|
||||
space -= space / SPACING;
|
||||
chunks = (space - 1) / ENC_CHUNK;
|
||||
while ((chunks + 1) * ENC_CHUNK + 1 > space) {
|
||||
chunks--;
|
||||
}
|
||||
write = RAW_CHUNK * chunks;
|
||||
write = MIN(write, len); /* do not use more bytes than is available; */
|
||||
final = (write == len); /* is this the last block? */
|
||||
chunks = write / RAW_CHUNK;
|
||||
leftovers = write % RAW_CHUNK;
|
||||
writer = buf;
|
||||
reader = writer;
|
||||
|
||||
memset(encoded, 0, sizeof(encoded));
|
||||
ep = encoded;
|
||||
dp = buf;
|
||||
for (i = 0; i < chunks; i++) {
|
||||
encode_chunk(ep, dp);
|
||||
ep += ENC_CHUNK;
|
||||
dp += RAW_CHUNK;
|
||||
}
|
||||
realwrite = ENC_CHUNK * chunks;
|
||||
memset(padding, 0, sizeof(padding));
|
||||
pp = padding;
|
||||
if (leftovers) {
|
||||
pp += RAW_CHUNK - leftovers;
|
||||
memcpy(pp, dp, leftovers);
|
||||
pos = 0;
|
||||
dots = 0;
|
||||
|
||||
pp = padding;
|
||||
*ep++ = padder[leftovers];
|
||||
encode_chunk(ep, pp);
|
||||
|
||||
realwrite += ENC_CHUNK + 1; /* plus padding character */
|
||||
}
|
||||
ep = encoded;
|
||||
if (len > 0) {
|
||||
for (i = 1; i <= realwrite; i++) {
|
||||
if (i % SPACING == 0) {
|
||||
*dest++ = '.';
|
||||
}
|
||||
*dest++ = *ep++;
|
||||
}
|
||||
}
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
int
|
||||
decode_data(char *dest, int size, const char *src, char *srcend)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
int chunks;
|
||||
int padded;
|
||||
char encoded[255];
|
||||
char padding[5];
|
||||
int enclen;
|
||||
char *pp;
|
||||
char *ep;
|
||||
|
||||
memset(encoded, 0, sizeof(encoded));
|
||||
memset(dest, 0, size);
|
||||
|
||||
/* First byte is not encoded */
|
||||
*dest++ = *src++;
|
||||
len = 1;
|
||||
|
||||
ep = encoded;
|
||||
enclen = 0;
|
||||
while(enclen < sizeof(encoded) && src < srcend) {
|
||||
if(*src == '.') {
|
||||
src++;
|
||||
while (pos < len) {
|
||||
if (*reader == '.') {
|
||||
reader++;
|
||||
pos++;
|
||||
dots++;
|
||||
continue;
|
||||
}
|
||||
|
||||
*ep++ = *src++;
|
||||
enclen++;
|
||||
*writer++ = *reader++;
|
||||
pos++;
|
||||
}
|
||||
chunks = enclen / 8;
|
||||
padded = enclen % 8;
|
||||
|
||||
ep = encoded;
|
||||
for (i = 0; i < chunks-1; i++) {
|
||||
decode_chunk(dest, ep);
|
||||
dest += RAW_CHUNK;
|
||||
ep += ENC_CHUNK;
|
||||
len += RAW_CHUNK;
|
||||
}
|
||||
/* Read last chunk */
|
||||
if (padded) {
|
||||
pp = padding;
|
||||
padded = *ep++ - '0';
|
||||
decode_chunk(pp, ep);
|
||||
pp += RAW_CHUNK - padded;
|
||||
memcpy(dest, pp, padded);
|
||||
len += padded;
|
||||
} else {
|
||||
decode_chunk(dest, ep);
|
||||
len += RAW_CHUNK;
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
/* return new length of string */
|
||||
return len - dots;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,16 @@
|
||||
#ifndef _ENCODING_H_
|
||||
#define _ENCODING_H_
|
||||
|
||||
int encode_data(const char *, const size_t, int, char *);
|
||||
int decode_data(char *, int, const char *, char *);
|
||||
int inline_dotify(char *, size_t);
|
||||
int inline_undotify(char *, size_t);
|
||||
|
||||
struct encoder {
|
||||
char name[8];
|
||||
int (*encode) (char *, size_t *, const void *, size_t);
|
||||
int (*decode) (void *, size_t *, const char *, size_t);
|
||||
int (*places_dots) (void);
|
||||
int (*eats_dots) (void);
|
||||
};
|
||||
|
||||
#endif /* _ENCODING_H_ */
|
||||
|
||||
|
32
src/iodine.c
32
src/iodine.c
@ -35,6 +35,8 @@
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
#include "base32.h"
|
||||
#include "dns.h"
|
||||
#include "login.h"
|
||||
#include "tun.h"
|
||||
@ -62,6 +64,8 @@ static int packetpos;
|
||||
static int packetlen;
|
||||
static uint16_t chunkid;
|
||||
|
||||
static struct encoder *enc;
|
||||
|
||||
static void
|
||||
sighandler(int sig)
|
||||
{
|
||||
@ -92,23 +96,31 @@ build_hostname(char *buf, size_t buflen,
|
||||
const char *data, const size_t datalen,
|
||||
const char *topdomain)
|
||||
{
|
||||
int consumed;
|
||||
int avail;
|
||||
int encsize;
|
||||
unsigned space;
|
||||
char *b;
|
||||
|
||||
avail = MIN(0xFF, buflen) - strlen(topdomain) - 2;
|
||||
memset(buf, 0, buflen);
|
||||
b = buf;
|
||||
|
||||
consumed = encode_data(data, datalen, avail, b);
|
||||
|
||||
space = MIN(0xFF, buflen) - strlen(topdomain) - 2;
|
||||
if (!enc->places_dots())
|
||||
space -= (space / 62); /* space for dots */
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
encsize = enc->encode(buf, &space, data, datalen);
|
||||
|
||||
if (!enc->places_dots())
|
||||
inline_dotify(buf, buflen);
|
||||
|
||||
b = buf;
|
||||
b += strlen(buf);
|
||||
|
||||
if (*b != '.')
|
||||
*b++ = '.';
|
||||
|
||||
strncpy(b, topdomain, strlen(topdomain)+1);
|
||||
|
||||
return consumed;
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
int
|
||||
@ -522,6 +534,8 @@ main(int argc, char **argv)
|
||||
newroot = NULL;
|
||||
device = NULL;
|
||||
chunkid = 0;
|
||||
|
||||
enc = get_base32_encoder();
|
||||
|
||||
while ((choice = getopt(argc, argv, "vfhu:t:d:P:")) != -1) {
|
||||
switch(choice) {
|
||||
|
@ -34,10 +34,11 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "dns.h"
|
||||
#include "encoding.h"
|
||||
#include "base32.h"
|
||||
#include "user.h"
|
||||
#include "login.h"
|
||||
#include "tun.h"
|
||||
#include "encoding.h"
|
||||
#include "version.h"
|
||||
|
||||
int running = 1;
|
||||
@ -46,6 +47,8 @@ char *topdomain;
|
||||
|
||||
char password[33];
|
||||
|
||||
struct encoder *b32;
|
||||
|
||||
int my_mtu;
|
||||
in_addr_t my_ip;
|
||||
|
||||
@ -123,6 +126,14 @@ send_version_response(int fd, version_ack_t ack, uint32_t payload, struct user *
|
||||
write_dns(fd, &u->q, out, sizeof(out));
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc)
|
||||
{
|
||||
if (!enc->eats_dots())
|
||||
datalen = inline_undotify(data, datalen);
|
||||
return enc->decode(buf, &buflen, data, datalen);
|
||||
}
|
||||
|
||||
static int
|
||||
tunnel_dns(int tun_fd, int dns_fd)
|
||||
{
|
||||
@ -133,6 +144,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
char logindata[16];
|
||||
char out[64*1024];
|
||||
char in[64*1024];
|
||||
char unpacked[64*1024];
|
||||
char *tmp[2];
|
||||
int userid;
|
||||
int touser;
|
||||
@ -145,14 +157,15 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
return 0;
|
||||
|
||||
if(in[0] == 'V' || in[0] == 'v') {
|
||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
||||
/* Version greeting, compare and send ack/nak */
|
||||
if (read > 4) {
|
||||
/* Received V + 32bits version */
|
||||
|
||||
version = (((in[1] & 0xff) << 24) |
|
||||
((in[2] & 0xff) << 16) |
|
||||
((in[3] & 0xff) << 8) |
|
||||
((in[4] & 0xff)));
|
||||
version = (((unpacked[0] & 0xff) << 24) |
|
||||
((unpacked[1] & 0xff) << 16) |
|
||||
((unpacked[2] & 0xff) << 8) |
|
||||
((unpacked[3] & 0xff)));
|
||||
|
||||
if (version == VERSION) {
|
||||
userid = find_available_user();
|
||||
@ -161,6 +174,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
memcpy(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen);
|
||||
memcpy(&(users[userid].q), &(dummy.q), sizeof(struct query));
|
||||
users[userid].addrlen = dummy.q.fromlen;
|
||||
users[userid].encoder = get_base32_encoder();
|
||||
send_version_response(dns_fd, VERSION_ACK, users[userid].seed, &users[userid]);
|
||||
users[userid].q.id = 0;
|
||||
} else {
|
||||
@ -174,8 +188,9 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
send_version_response(dns_fd, VERSION_NACK, VERSION, &dummy);
|
||||
}
|
||||
} else if(in[0] == 'L' || in[0] == 'l') {
|
||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
||||
/* Login phase, handle auth */
|
||||
userid = in[1];
|
||||
userid = unpacked[0];
|
||||
if (userid < 0 || userid >= USERS) {
|
||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
||||
return 0; /* illegal id */
|
||||
@ -187,7 +202,7 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) != 0) {
|
||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
||||
} else {
|
||||
if (read >= 18 && (memcmp(logindata, in+2, 16) == 0)) {
|
||||
if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
|
||||
/* Login ok, send ip/mtu info */
|
||||
|
||||
tempip.s_addr = my_ip;
|
||||
@ -208,8 +223,9 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
}
|
||||
}
|
||||
} else if(in[0] == 'P' || in[0] == 'p') {
|
||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
|
||||
/* Ping packet, store userid */
|
||||
userid = in[1];
|
||||
userid = unpacked[0];
|
||||
if (userid < 0 || userid >= USERS) {
|
||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
||||
return 0; /* illegal id */
|
||||
@ -237,12 +253,16 @@ tunnel_dns(int tun_fd, int dns_fd)
|
||||
memcmp(&(users[userid].host), &(dummy.q.from), dummy.q.fromlen) != 0) {
|
||||
write_dns(dns_fd, &(dummy.q), "BADIP", 5);
|
||||
} else {
|
||||
/* decode with this users encoding */
|
||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1,
|
||||
users[userid].encoder);
|
||||
|
||||
users[userid].last_pkt = time(NULL);
|
||||
memcpy(&(users[userid].q), &(dummy.q), sizeof(struct query));
|
||||
users[userid].addrlen = dummy.q.fromlen;
|
||||
memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, in + 1, read - 1);
|
||||
users[userid].inpacket.len += read - 1;
|
||||
users[userid].inpacket.offset += read - 1;
|
||||
memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read);
|
||||
users[userid].inpacket.len += read;
|
||||
users[userid].inpacket.offset += read;
|
||||
|
||||
if (code & 1) {
|
||||
outlen = sizeof(out);
|
||||
@ -351,10 +371,11 @@ read_dns(int fd, struct query *q, char *buf, int buflen)
|
||||
if (r > 0) {
|
||||
dns_decode(buf, buflen, q, QR_QUERY, packet, r);
|
||||
domain = strstr(q->name, topdomain);
|
||||
rv = decode_data(buf, buflen, q->name, domain);
|
||||
rv = (int) (domain - q->name);
|
||||
memcpy(buf, q->name, MIN(rv, buflen));
|
||||
q->fromlen = addrlen;
|
||||
memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
|
||||
} else if (r < 0) {
|
||||
} else if (r < 0) {
|
||||
/* Error */
|
||||
perror("recvfrom");
|
||||
rv = 0;
|
||||
@ -438,6 +459,8 @@ main(int argc, char **argv)
|
||||
listen_ip = INADDR_ANY;
|
||||
port = 53;
|
||||
|
||||
b32 = get_base32_encoder();
|
||||
|
||||
memset(password, 0, 33);
|
||||
srand(time(NULL));
|
||||
|
||||
|
@ -47,5 +47,6 @@ login_calculate(char *buf, int buflen, char *pass, int seed)
|
||||
md5_init(&ctx);
|
||||
md5_append(&ctx, temp, 32);
|
||||
md5_finish(&ctx, (unsigned char *) buf);
|
||||
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
#include "user.h"
|
||||
|
||||
struct user users[USERS];
|
||||
|
@ -30,6 +30,7 @@ struct user {
|
||||
struct query q;
|
||||
struct packet inpacket;
|
||||
struct packet outpacket;
|
||||
struct encoder *encoder;
|
||||
};
|
||||
|
||||
extern struct user users[USERS];
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
/* This is the version of the network protocol
|
||||
It is usually equal to the latest iodine version number */
|
||||
#define VERSION 0x00000400
|
||||
#define VERSION 0x00000401
|
||||
|
||||
#endif /* _VERSION_H_ */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user