zerotier / toss

Dead simple LAN file transfers from the command line
Other
399 stars 23 forks source link

Token incorrectly parsed #1

Open Mrokkk opened 7 years ago

Mrokkk commented 7 years ago

Hi! I think I've found some bug, which makes toss unusable. I've applied following patch:

diff --git a/catch.c b/catch.c
index 6cdd654..e95e5e3 100644
--- a/catch.c
+++ b/catch.c
@@ -111,6 +111,7 @@ int main(int argc,char **argv)
                        const char *fromaddr = (char *)0;
                        memset(&sa,0,sizeof(struct sockaddr_storage));
                        enum toss_ip_scope ipsc = IP_SCOPE_NONE;
+                       printf("iplen: %d\n", iplen);
                        switch(iplen) {
                                case 4:
                                        sa.ss_family = AF_INET;

If I generate hash by ./toss ${some_file} and run ./catch ${hash}, I get:

./catch: catching LICENSE.txt (1110 bytes)
iplen: 0
iplen: 0
iplen: 0
./catch: no addresses worked! bad token or no network path?

It's occurs both on localhost and LAN.

lalip commented 3 years ago

I dug around the code for a while - it looks to me like your diagnosis is correct in that there's something wrong with the token, but according to what I've found, the problem occurs when it's created rather than parsed.

the loop you're looking at starts reading token from byte 18. for a short token like test/wv7aaaaaaaaaaaaqxzmvtnjvm3sowaaa, this is what that looks like: 00 00. in other words, just one byte shy from the end of the token, where there are obviously no addresses to be found at all.

this prompted me to check toss.c. after a bunch of digging, it turns out it doesn't accept any IPv6 interfaces in any of my devices! the code under this condition is never executed.

further down the file, I found a while loop whose condition incorrectly assumes there will be an equal amount of IPv4 interfaces as IPv6 interfaces. thus, I wrote the following hack:

diff --git a/toss.c b/toss.c
index c660a13..85d7065 100644
--- a/toss.c
+++ b/toss.c
@@ -177,7 +177,7 @@ int main(int argc,char **argv)
        token[tokenlen++] = filedigest[i];
    unsigned int ip4ptr2 = 0,ip6ptr2 = 0;
    n = 0;
-       while ((ip4ptr2 < ip4ptr)&&(ip6ptr2 < ip6ptr)&&((tokenlen + 17 + 5) <= TOSS_MAX_TOKEN_BYTES)) {
+       while ((ip4ptr2 < ip4ptr)&&((tokenlen + 17 + 5) <= TOSS_MAX_TOKEN_BYTES)) {
        if (n) {
            token[tokenlen++] = 16;
            for(int i=0;i<16;++i)
@@ -187,7 +187,7 @@ int main(int argc,char **argv)
            for(int i=0;i<4;++i)
                token[tokenlen++] = ip4s[ip4ptr2++];
        }
-           n ^= 1;
    }
    while ((tokenlen % 5) != 0)
        ++tokenlen;

works fine for me now! tokens are a fair bit longer, as intended: test/wc4qaaaaaaaaaaaqxzmvtnjvm3sowbgavbtiibfmciaacbfmcqaacbfmceaacaaa

still, I'm not convinced that's the sole issue, so instead of coming up with a revised condition and submitting a pull request that only fixes the symptom, I figured I'd post my findings here and leave it to somebody else who understands networking better to confirm the root cause.

(I've edited some distracting details out: you may read them by clicking on edited at the top)