mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-22 06:41:26 +00:00
Use base64 is case is preserved and plus sign is allowed
This commit is contained in:
parent
612d142819
commit
d7f2d60d56
|
@ -21,6 +21,8 @@ CHANGES:
|
||||||
- iodine client now shuts down if it detects a server restart.
|
- iodine client now shuts down if it detects a server restart.
|
||||||
- iodined now replies to NS request on its own domain, fixes issue #33.
|
- iodined now replies to NS request on its own domain, fixes issue #33.
|
||||||
The destination IP address is sent as reply.
|
The destination IP address is sent as reply.
|
||||||
|
- Upstream data is now Base64 encoded if relay server preserves case and
|
||||||
|
supports the plus (+) character in domain names, fixes #16.
|
||||||
|
|
||||||
2008-08-06: 0.4.2 "Opened Zone"
|
2008-08-06: 0.4.2 "Opened Zone"
|
||||||
- Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann
|
- Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann
|
||||||
|
|
97
src/iodine.c
97
src/iodine.c
|
@ -40,6 +40,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base32.h"
|
#include "base32.h"
|
||||||
|
#include "base64.h"
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "login.h"
|
#include "login.h"
|
||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
|
@ -146,13 +147,13 @@ build_hostname(char *buf, size_t buflen,
|
||||||
return space;
|
return space;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
is_sending()
|
is_sending()
|
||||||
{
|
{
|
||||||
return (packet.len != 0);
|
return (packet.len != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
read_dns(int fd, char *buf, int buflen)
|
read_dns(int fd, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
|
@ -324,7 +325,7 @@ send_chunk(int fd)
|
||||||
send_query(fd, buf);
|
send_query(fd, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
send_login(int fd, char *login, int len)
|
send_login(int fd, char *login, int len)
|
||||||
{
|
{
|
||||||
char data[19];
|
char data[19];
|
||||||
|
@ -361,7 +362,7 @@ send_ping(int fd)
|
||||||
send_packet(fd, 'P', data, sizeof(data));
|
send_packet(fd, 'P', data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
send_version(int fd, uint32_t version)
|
send_version(int fd, uint32_t version)
|
||||||
{
|
{
|
||||||
char data[6];
|
char data[6];
|
||||||
|
@ -379,15 +380,33 @@ send_version(int fd, uint32_t version)
|
||||||
send_packet(fd, 'V', data, sizeof(data));
|
send_packet(fd, 'V', data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
send_case_check(int fd)
|
send_case_check(int fd)
|
||||||
{
|
{
|
||||||
char buf[512] = "zZaAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY123-4560789.";
|
/* The '+' plus character is not allowed according to RFC.
|
||||||
|
* Expect to get SERVFAIL or similar if it is rejected.
|
||||||
|
*/
|
||||||
|
char buf[512] = "zZ+-aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY1234.";
|
||||||
|
|
||||||
strncat(buf, topdomain, 512 - strlen(buf));
|
strncat(buf, topdomain, 512 - strlen(buf));
|
||||||
send_query(fd, buf);
|
send_query(fd, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_codec_switch(int fd, int userid, int bits)
|
||||||
|
{
|
||||||
|
char buf[512] = "S00.";
|
||||||
|
if (userid >= 0 && userid < 9) {
|
||||||
|
buf[1] += userid;
|
||||||
|
}
|
||||||
|
if (bits >= 0 && bits < 9) {
|
||||||
|
buf[2] += bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncat(buf, topdomain, 512 - strlen(buf));
|
||||||
|
send_query(fd, buf);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handshake(int dns_fd)
|
handshake(int dns_fd)
|
||||||
{
|
{
|
||||||
|
@ -519,30 +538,30 @@ perform_case_check:
|
||||||
if(r > 0) {
|
if(r > 0) {
|
||||||
read = read_dns(dns_fd, in, sizeof(in));
|
read = read_dns(dns_fd, in, sizeof(in));
|
||||||
|
|
||||||
if(read <= 0) {
|
|
||||||
warn("read");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
if (in[0] == 'z' || in[0] == 'Z') {
|
if (in[0] == 'z' || in[0] == 'Z') {
|
||||||
if (read < (26 * 2)) {
|
if (read < (27 * 2)) {
|
||||||
printf("Received short case reply...\n");
|
printf("Received short case check reply. Will use base32 encoder\n");
|
||||||
|
goto switch_codec;
|
||||||
} else {
|
} else {
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
|
/* TODO enhance this, base128 is probably also possible */
|
||||||
case_preserved = 1;
|
case_preserved = 1;
|
||||||
for (k = 0; k < 26 && case_preserved; k += 2) {
|
for (k = 0; k < 27 && case_preserved; k += 2) {
|
||||||
if (in[k] == in[k+1]) {
|
if (in[k] == in[k+1]) {
|
||||||
/* test string: zZaAbBcCdD... */
|
/* test string: zZ+-aAbBcCdDeE... */
|
||||||
case_preserved = 0;
|
case_preserved = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
goto switch_codec;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Received bad case check reply\n");
|
printf("Received bad case check reply\n");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
printf("Got error on case check, will use base32\n");
|
||||||
|
goto switch_codec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,6 +569,52 @@ perform_case_check:
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("No reply on case check, continuing\n");
|
printf("No reply on case check, continuing\n");
|
||||||
|
switch_codec:
|
||||||
|
if (!case_preserved)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dataenc = get_base64_encoder();
|
||||||
|
printf("Switching to %s codec\n", dataenc->name);
|
||||||
|
/* Send to server that this user will use base64 from now on */
|
||||||
|
for (i=0; running && i<5 ;i++) {
|
||||||
|
int bits;
|
||||||
|
tv.tv_sec = i + 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
bits = 6; /* base64 = 6 bits per byte */
|
||||||
|
|
||||||
|
send_codec_switch(dns_fd, userid, bits);
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(dns_fd, &fds);
|
||||||
|
|
||||||
|
r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
|
||||||
|
if(r > 0) {
|
||||||
|
read = read_dns(dns_fd, in, sizeof(in));
|
||||||
|
|
||||||
|
if (read > 0) {
|
||||||
|
if (strncmp("BADLEN", in, 6) == 0) {
|
||||||
|
printf("Server got bad message length. ");
|
||||||
|
goto codec_revert;
|
||||||
|
} else if (strncmp("BADIP", in, 5) == 0) {
|
||||||
|
printf("Server rejected sender IP address. ");
|
||||||
|
goto codec_revert;
|
||||||
|
} else if (strncmp("BADCODEC", in, 8) == 0) {
|
||||||
|
printf("Server rejected the selected codec. ");
|
||||||
|
goto codec_revert;
|
||||||
|
}
|
||||||
|
in[read] = 0; /* zero terminate */
|
||||||
|
printf("Server switched to codec %s\n", in);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Retrying codec switch...\n");
|
||||||
|
}
|
||||||
|
printf("No reply from server on codec switch. ");
|
||||||
|
codec_revert:
|
||||||
|
printf("Falling back to base32\n");
|
||||||
|
dataenc = get_base32_encoder();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "base32.h"
|
#include "base32.h"
|
||||||
|
#include "base64.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
#include "login.h"
|
#include "login.h"
|
||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
|
@ -261,11 +262,43 @@ 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].last_pkt = time(NULL);
|
users[userid].last_pkt = time(NULL);
|
||||||
} else if(in[0] == 'Z' || in[0] == 'z') {
|
} else if(in[0] == 'Z' || in[0] == 'z') {
|
||||||
/* Case conservation check */
|
/* Check for case conservation and chars not allowed according to RFC */
|
||||||
|
|
||||||
/* Reply with received hostname as data */
|
/* Reply with received hostname as data */
|
||||||
write_dns(dns_fd, q, in, domain_len);
|
write_dns(dns_fd, q, in, domain_len);
|
||||||
return;
|
return;
|
||||||
|
} else if(in[0] == 'S' || in[0] == 's') {
|
||||||
|
int codec;
|
||||||
|
struct encoder *enc;
|
||||||
|
if (domain_len != 4) { /* len = 4, example: "S15." */
|
||||||
|
write_dns(dns_fd, q, "BADLEN", 6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
userid = in[1] & 0x7;
|
||||||
|
|
||||||
|
if (ip_cmp(userid, q) != 0) {
|
||||||
|
write_dns(dns_fd, q, "BADIP", 5);
|
||||||
|
return; /* illegal id */
|
||||||
|
}
|
||||||
|
|
||||||
|
codec = in[2] & 0xF;
|
||||||
|
switch (codec) {
|
||||||
|
case 5: /* 5 bits per byte = base32 */
|
||||||
|
enc = get_base32_encoder();
|
||||||
|
user_switch_codec(userid, enc);
|
||||||
|
write_dns(dns_fd, q, enc->name, strlen(enc->name));
|
||||||
|
break;
|
||||||
|
case 6: /* 6 bits per byte = base64 */
|
||||||
|
enc = get_base64_encoder();
|
||||||
|
user_switch_codec(userid, enc);
|
||||||
|
write_dns(dns_fd, q, enc->name, strlen(enc->name));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
write_dns(dns_fd, q, "BADCODEC", 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
} else if((in[0] >= '0' && in[0] <= '9')
|
} else if((in[0] >= '0' && in[0] <= '9')
|
||||||
|| (in[0] >= 'a' && in[0] <= 'f')
|
|| (in[0] >= 'a' && in[0] <= 'f')
|
||||||
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
||||||
|
|
|
@ -106,3 +106,11 @@ find_available_user()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
user_switch_codec(int userid, struct encoder *enc)
|
||||||
|
{
|
||||||
|
if (userid < 0 || userid >= USERS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
users[userid].encoder = enc;
|
||||||
|
}
|
||||||
|
|
|
@ -38,5 +38,6 @@ void init_users(in_addr_t);
|
||||||
int find_user_by_ip(uint32_t);
|
int find_user_by_ip(uint32_t);
|
||||||
int all_users_waiting_to_send();
|
int all_users_waiting_to_send();
|
||||||
int find_available_user();
|
int find_available_user();
|
||||||
|
void user_switch_codec(int userid, struct encoder *enc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue