From 08efbdac691d89e14bada1e90b3edd2758da1199 Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Sun, 14 Jun 2009 11:14:40 +0000 Subject: [PATCH] #36 send raw login packet directly to server --- src/common.c | 3 +++ src/common.h | 8 +++++++ src/iodine.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---- src/iodined.c | 4 +++- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/common.c b/src/common.c index 8511498..2a8380b 100644 --- a/src/common.c +++ b/src/common.c @@ -43,6 +43,9 @@ #include "common.h" +/* The raw header used when not using DNS protocol */ +const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 }; + /* daemon(3) exists only in 4.4BSD or later, and in GNU libc */ #if !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__) static int daemon(int nochdir, int noclose) diff --git a/src/common.h b/src/common.h index f39461a..eb1b39b 100644 --- a/src/common.h +++ b/src/common.h @@ -17,6 +17,14 @@ #ifndef __COMMON_H__ #define __COMMON_H__ +/* Last byte of raw header is the command */ +#define RAW_HDR_LEN 4 +#define RAW_HDR_IDENT_LEN 3 +#define RAW_HDR_CMD 3 +#define RAW_HDR_CMD_LOGIN 0x01 +#define RAW_HDR_CMD_DATA 0x02 +extern const unsigned char raw_header[RAW_HDR_LEN]; + #ifdef WINDOWS32 #include "windows.h" #else diff --git a/src/iodine.c b/src/iodine.c index c658021..024e080 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -67,6 +67,7 @@ static int running = 1; static char password[33]; static struct sockaddr_in nameserv; +static struct sockaddr_in raw_serv; static char *topdomain; static uint16_t rand_seed; @@ -120,6 +121,23 @@ send_query(int fd, char *hostname) sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv)); } +static void +send_raw(int fd, char *buf, int buflen, int cmd) +{ + unsigned char packet[4096]; + int len; + + len = MIN(sizeof(packet) - RAW_HDR_LEN, buflen); + + memcpy(packet, raw_header, RAW_HDR_LEN); + memcpy(&packet[RAW_HDR_LEN], buf, len); + + len += RAW_HDR_LEN; + packet[RAW_HDR_CMD] = cmd; + + sendto(fd, packet, len, 0, (struct sockaddr*)&raw_serv, sizeof(raw_serv)); +} + static void send_packet(int fd, char cmd, const char *data, const size_t datalen) { @@ -488,6 +506,16 @@ send_ip_request(int fd, int userid) send_query(fd, buf); } +static void +send_raw_udp_login(int dns_fd, int userid, int seed) +{ + char buf[17]; + login_calculate(buf, 16, password, seed + 1); + buf[16] = userid; + + send_raw(dns_fd, buf, sizeof(buf), RAW_HDR_CMD_LOGIN); +} + static void send_case_check(int fd) { @@ -643,7 +671,7 @@ handshake_login(int dns_fd, int seed) } static int -handshake_raw_udp(int dns_fd) +handshake_raw_udp(int dns_fd, int seed) { struct timeval tv; char in[4096]; @@ -694,9 +722,36 @@ handshake_raw_udp(int dns_fd) fprintf(stderr, " at %s", inet_ntoa(server)); fflush(stderr); - /* TODO do login against port 53 on remote server - * based on the old seed. If reply received, - * switch to raw udp mode */ + /* Store address to iodined server */ + memset(&raw_serv, 0, sizeof(raw_serv)); + raw_serv.sin_family = AF_INET; + raw_serv.sin_port = htons(53); + raw_serv.sin_addr = server; + + /* do login against port 53 on remote server + * based on the old seed. If reply received, + * switch to raw udp mode */ + for (i=0; running && i<4 ;i++) { + tv.tv_sec = i + 1; + tv.tv_usec = 0; + + send_raw_udp_login(dns_fd, userid, seed); + + 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)); + } else { + fprintf(stderr, "."); + fflush(stderr); + } + } + + + /* TODO */ fprintf(stderr, ": not implemented\n"); return 1; /* TODO and then return 0 on success */ @@ -951,7 +1006,7 @@ handshake(int dns_fd, int autodetect_frag_size, int fragsize) return r; } - handshake_raw_udp(dns_fd); + handshake_raw_udp(dns_fd, seed); handshake_case_check(dns_fd); diff --git a/src/iodined.c b/src/iodined.c index 3f06c29..a20066d 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -870,7 +870,9 @@ read_dns(int fd, struct query *q) #endif /* !WINDOWS32 */ if (r > 0) { - dns_decode(NULL, 0, q, QR_QUERY, packet, r); + if (dns_decode(NULL, 0, q, QR_QUERY, packet, r) < 0) { + return 0; + } memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen); q->fromlen = addrlen;