1 /* Copyright 2008,2009 Bernhard R. Fischer.
2  *
3  * This file is part of OnionCat.
4  *
5  * OnionCat is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * OnionCat is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with OnionCat. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*! @file
19  *  ocatv6conv.c
20  *  These functions convert IPv6 addresses to onion URLs
21  *  and vice versa.
22  *
23  *  @author Bernhard R. Fischer <rahra _at_ cypherpunkt at>
24  *  @version 2008/02/03-01
25  */
26 
27 
28 #include "ocat.h"
29 #include "ocat_netdesc.h"
30 
31 static const char BASE32[] = "abcdefghijklmnopqrstuvwxyz234567";
32 //! array contains inverse mapping of base32 starting with '2'.
33 static const char deBASE32_[] = {
34    /*          2   3   4   5   6   7   8   9
35               32  33  34  35  36  37  38  39  3a  3b  3c  3d  3e  3f */
36               26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1,
37    /*      A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
38       40  41  42  43  44  45  46  47  48  49  4a  4b  4c  4d  4e  4f */
39       -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
40    /*  P   Q   R   S   T   U   V   W   X   Y   Z
41       50  51  52  53  54  55  56  57  58  59  5a */
42       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
43 
44 
has_tor_prefix(const struct in6_addr * addr)45 int has_tor_prefix(const struct in6_addr *addr)
46 {
47    return memcmp(addr, &NDESC(prefix), 6) == 0;
48 }
49 
50 
set_tor_prefix(struct in6_addr * addr)51 void set_tor_prefix(struct in6_addr *addr)
52 {
53    memcpy(addr, &NDESC(prefix), 6);
54 }
55 
56 
57 /*! Shift byte buffer of size ONION_URL_LEN (=17) 5 bits to the left.
58  *  @param bin Pointer to byte buffer, must be at least ONION_URL_LEN
59  *             bytes long.
60  */
shl5(char * bin)61 void shl5(char *bin)
62 {
63    int i;
64 
65    for (i = 0; i < ONION_URL_LEN - 1; i++)
66    {
67       bin[i] <<= 5;
68       bin[i] |= (bin[i + 1] >> 3) & 0x1f;
69    }
70    bin[i] <<= 5;
71 }
72 
73 
oniontipv6(const char * onion,struct in6_addr * ip6)74 int oniontipv6(const char *onion, struct in6_addr *ip6)
75 {
76    int i, j;
77 
78    memset(ip6, 0, sizeof(struct in6_addr));
79 
80    for (i = 0; i < 16; i++)
81    {
82       shl5((char*) ip6);
83       j = toupper((int) onion[i]);
84       if ((j < '2') || (j > 'Z'))
85          return -1;
86       if ((j = deBASE32_[j - '2']) == -1)
87          return -1;
88       *(((char*) ip6) + 15) |= j;
89    }
90    set_tor_prefix(ip6);
91    return 0;
92 }
93 
94 
oniontipv4(const char * onion,struct in_addr * ip,int prefix_mask)95 int oniontipv4(const char *onion, struct in_addr *ip, int prefix_mask)
96 {
97    struct in6_addr ip6;
98    //uint32_t netmask = 0xffffffff << (32 - prefix_len);
99    uint32_t netmask = prefix_mask;
100    uint32_t ip4;
101 
102    if (oniontipv6(onion, &ip6))
103       return -1;
104    memcpy(&ip4, &ip6.s6_addr[12], sizeof(ip4));
105    ip4 &= htonl(~netmask);
106    ip->s_addr |= ip4;
107    return 0;
108 }
109 
110 
111 /*! Convert IPv6 address to onion-URL (without ".onion").
112  *  @param ip6 Pointer to IPv6 address of type struct in6_addr.
113  *  @param onion Pointer to buffer to should receive onion-URL.
114  *         The buffer *must* be at least ONION_URL_LEN + 1 (=17) bytes long.
115  *  @return Returns always again pointer to buffer.
116  */
ipv6tonion(const struct in6_addr * ip6,char * onion)117 char *ipv6tonion(const struct in6_addr *ip6, char *onion)
118 {
119    int i;
120    char bin[ONION_URL_LEN], *r = onion;
121 
122    memcpy(bin, (char*) ip6 + 6, 10);
123 
124    for (i = 0; i < ONION_URL_LEN; i++, onion++)
125    {
126       *onion = BASE32[bin[0] >> 3 & 0x1f];
127       shl5(bin);
128    }
129    *onion = '\0';
130    return r;
131 }
132 
133 
134 /*! Generate a random onion-URL.
135  *  @paran onion must be of at least ONION_URL_LEN + 1 (=17).
136  */
rand_onion(char * onion)137 void rand_onion(char *onion)
138 {
139    int i;
140 
141    if (RAND_MAX < 32)
142       log_msg(LOG_WARNING, "weak randomness: RAND_MAX = %d < 32", RAND_MAX);
143 
144    for (i = 0; i < ONION_URL_LEN; i++, onion++)
145       *onion = BASE32[rand() & 0x1f];
146    *onion = '\0';
147 }
148 
149 
150 /*! Convert struct sockaddr to stuct sockaddr_str which holds the address
151  *  in string representation.
152  *  @param saddr Const pointer to source of type struct sockaddr-
153  *  @param sas Pointer to destination of type struct sockaddr_str.
154  *  @return Pointer to string (sas->sstr_addr) or NULL on error. In the
155  *          latter case errno will be set correctly.
156  */
inet_ntops(const struct sockaddr * saddr,struct sockaddr_str * sas)157 const char *inet_ntops(const struct sockaddr *saddr, struct sockaddr_str *sas)
158 {
159    char *src;
160 
161    log_debug("convert sockaddr %p to sockaddr_str %p", saddr, sas);
162    switch (saddr->sa_family)
163    {
164       case AF_INET:
165          src = (char*) &((struct sockaddr_in*) saddr)->sin_addr;
166          sas->sstr_port = ((struct sockaddr_in*) saddr)->sin_port;
167          break;
168 
169       case AF_INET6:
170          src = (char*) &((struct sockaddr_in6*) saddr)->sin6_addr;
171          sas->sstr_port = ((struct sockaddr_in6*) saddr)->sin6_port;
172          break;
173 
174       default:
175          errno = EAFNOSUPPORT;
176          return NULL;
177    }
178 
179    sas->sstr_family = saddr->sa_family;
180    return inet_ntop(saddr->sa_family, src, sas->sstr_addr, sizeof(sas->sstr_addr));
181 }
182 
183