summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--makefile2
-rw-r--r--src/bencoding.c7
-rw-r--r--src/dht.c18
-rw-r--r--src/main.c26
5 files changed, 37 insertions, 19 deletions
diff --git a/README.md b/README.md
index 6f4cf70..df6045a 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
# external libraries
* https://github.com/kokke/tiny-AES-c
+
+# todo
+* implement BEP-0042 DHT security extension
diff --git a/makefile b/makefile
index aba35cd..c513bbc 100644
--- a/makefile
+++ b/makefile
@@ -1,7 +1,7 @@
DESTDIR=/
CC=cc
MYCFLAGS=-Wall -Wextra -Wformat -pedantic -g -Isrc -Itmp -Itiny-AES-c
-MYLDFLAGS=-lresolv
+MYLDFLAGS=-lresolv -lmd
default:
mkdir -p tmp
diff --git a/src/bencoding.c b/src/bencoding.c
index b32e2ea..e456486 100644
--- a/src/bencoding.c
+++ b/src/bencoding.c
@@ -197,12 +197,16 @@ int b2json_charsize (unsigned char a) {
return 2;
if (a < ' ')
return 6;
+ if (a > 127)
+ return 1;
return 1;
}
/**
* write a string representation of a character in a JSON string
*
+ * non-ASCII characters are replaced with a '.'
+ *
* @param dest [out] destination
* @param a [in] the character in question
* @return the destination pointer, incremented for the number of bytes written
@@ -239,6 +243,9 @@ char * b2json_charrepr (char * dest, unsigned char a) {
sprintf(buf, "\\u00%02x", a);
strncpy(dest, buf, 6);
return dest+6;
+ } else if (a > 127) {
+ *dest++ = '.';
+ return dest;
} else {
*dest++ = a;
return dest;
diff --git a/src/dht.c b/src/dht.c
index 8cfe1ca..bd310ee 100644
--- a/src/dht.c
+++ b/src/dht.c
@@ -12,6 +12,7 @@
#include <resolv.h>
#include <limits.h>
#include <assert.h>
+#include <sha1.h> // http://github.com/clibs/sha1 and in major distributions
#define ECB 1
#define AES128 1
#include <aes.c>
@@ -166,6 +167,7 @@ void bucket_free (struct bucket * b) {
*/
struct peer {
+ int socket; /**< tcp socket for bep-0009 */
struct sockaddr_in6 addr; /**< peer ip address and port */
struct peer * next;
};
@@ -209,8 +211,7 @@ void peer_print (FILE * s, const struct peer * p) {
enum interested {
announce = 1 << 0, /**< will announce myself on every work() call with no packet */
peers = 1 << 1, /**< will get peers on every work() call with no packet */
- info = 1 << 2, /**< download metadata into `dht->dl`/$hash.info */
- dl = 1 << 3 /**< download torrent content into `dht->dl`/$hash.blob TODO */
+ info = 1 << 2 /**< download metadata into `dht->dl`/$hash.info */
};
/**
@@ -221,7 +222,7 @@ struct torrent {
enum interested type; /**< is truthy only for manually added torrents */
unsigned char hash[20]; /**< infohash */
struct peer * peers;
- struct node * nodes; /**< closest K DHT nodes to this hash, used only for announce, peers, info and dl torrents */
+ struct node * nodes; /**< closest K DHT nodes to this hash, used only for announce, peers and info torrents */
struct torrent * next;
struct torrent * prev; /**< prev is here so that we can easily pop the oldest torrent. dht->last_torrent is useful here */
};
@@ -295,7 +296,7 @@ struct dht {
struct bucket * buckets;
struct bucket * buckets6; /**< IPv6 routing table */
struct torrent * torrents; /**< linked list of torrents for which we want to know peers */
- int dl; /**< dirfd storage directory for download and info torrents */
+ int dl; /**< dirfd storage directory for info torrents */
void (* possible_torrent)(struct dht *, const unsigned char *); /**< a user callback function that is called whenever we come across a torrent hash from a network */
void * userdata; /**< unused, but left for the library user to set so he can refer back to his structures from callback code, such as dht->possible_torrent(d, h) */
unsigned torrents_num; /**< number of torrents. this number can rise indefinitely, so it can, and should be capped by the caller, depending on available memory */
@@ -395,6 +396,12 @@ void sendb (struct dht * d, struct bencoding * b, const struct sockaddr_in6 * a)
struct bencoding * v = bstr(strdup("TK00"));
v->key = bstr(strdup("v"));
binsert(b, v);
+ struct bencoding * ip = calloc(1, sizeof *ip);
+ ip->type = string;
+ ip->key = bstr(strdup("key"));
+ memcpy((b->value = malloc(18)), a->sin6_addr.s6_addr + (family(a->sin6_addr.s6_addr) == AF_INET ? 12 : 0), (b->valuelen = family(a->sin6_addr.s6_addr) == AF_INET ? 6 : 18));
+ memcpy(b->value + (family(a->sin6_addr.s6_addr) == AF_INET ? 4 : 16), &a->sin6_port, 2);
+ binsert(b, ip);
int len = b2json_length(b);
char json[len+1];
b2json(json, b);
@@ -1495,8 +1502,9 @@ void handle (struct dht * d, char * pkt, int len, struct sockaddr_in6 addr) {
char * qtype = "";
if (q && q->type & string)
qtype = q->value;
+ struct bencoding * ro = bpath(b, "ro");
struct bencoding * rid = bpath(b, "a/id");
- if (rid && rid->type & string && rid->valuelen == 20) {
+ if (rid && rid->type & string && rid->valuelen == 20 && (!ro || !(ro->type & num) || ro->intvalue != 1 /* BEP-0043 */)) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-sign"
potential_node(d, &addr, rid->value);
diff --git a/src/main.c b/src/main.c
index f613e4e..e659e6b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -48,24 +48,24 @@ int main (int argc, char ** argv) {
error_at_line(3, errno, __FILE__, __LINE__, "sigaction(SIGTERM)");
if (sigaction(SIGUSR1, &sigact, NULL) == -1)
error_at_line(4, errno, __FILE__, __LINE__, "sigaction(SIGUSR1)");
- struct itimerval itimerval = {
- .it_interval = {
- .tv_sec = 13*60
- }
- };
- if (setitimer(ITIMER_REAL, &itimerval, NULL))
- error_at_line(5, errno, __FILE__, __LINE__, "setitimer");
sigset_t sigset;
if (sigemptyset(&sigset) == -1)
- error_at_line(6, errno, __FILE__, __LINE__, "sigemptyset");
+ error_at_line(5, errno, __FILE__, __LINE__, "sigemptyset");
if (sigaddset(&sigset, SIGUSR1) == -1)
- error_at_line(7, errno, __FILE__, __LINE__, "sigaddset(SIGUSR1)");
+ error_at_line(6, errno, __FILE__, __LINE__, "sigaddset(SIGUSR1)");
if (sigaddset(&sigset, SIGALRM) == -1)
- error_at_line(8, errno, __FILE__, __LINE__, "sigaddset(SIGALRM)");
+ error_at_line(7, errno, __FILE__, __LINE__, "sigaddset(SIGALRM)");
if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1)
- error_at_line(9, errno, __FILE__, __LINE__, "sigprocmask");
+ error_at_line(8, errno, __FILE__, __LINE__, "sigprocmask");
+ /* struct itimerval itimerval = {
+ .it_interval = {
+ .tv_sec = 60
+ }
+ };
+ if (setitimer(ITIMER_REAL, &itimerval, NULL) == -1)
+ error_at_line(9, errno, __FILE__, __LINE__, "setitimer"); */
if (argc != 1+1)
- error_at_line(10, 0, __FILE__, __LINE__, "%s configfile.ben > possible_torrents.L", S0(argv[0]));
+ error_at_line(10, 0, __FILE__, __LINE__, "%s configfile.ben >> possible_torrents.L", S0(argv[0]));
int cf = open(argv[1], O_RDWR | O_CLOEXEC | O_CREAT, 00664);
if (cf == -1)
error_at_line(11, errno, __FILE__, __LINE__, "open(%s)", argv[1]);
@@ -89,12 +89,12 @@ int main (int argc, char ** argv) {
memcpy(torrent->hash, "\xdd\x82\x55\xec\xdc\x7c\xa5\x5f\xb0\xbb\xf8\x13\x23\xd8\x70\x62\xdb\x1f\x6d\x1c", 20);
torrent->type = announce | peers;
add_torrent(dht, torrent);
- work(dht);
struct pollfd pollfd = {
.fd = dht->socket,
.events = POLLIN
};
w:
+ alarm(13*60);
while (poll(&pollfd, 1, -1) == 1)
work(dht);
if (errno == EINTR) {