0ff7bef0e868ac50d8871574931f57301bd49e9c
[tinc] / src / meta.c
1 /*
2     meta.c -- handle the meta communication
3     Copyright (C) 2000-2018 Guus Sliepen <guus@tinc-vpn.org>,
4                   2000-2005 Ivo Timmermans
5                   2006      Scott Lamb <slamb@slamb.org>
6
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License along
18     with this program; if not, write to the Free Software Foundation, Inc.,
19     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include "system.h"
23
24 #include <assert.h>
25
26 #include "cipher.h"
27 #include "connection.h"
28 #include "logger.h"
29 #include "meta.h"
30 #include "net.h"
31 #include "protocol.h"
32 #include "utils.h"
33
34 #ifndef MIN
35 static ssize_t MIN(ssize_t x, ssize_t y) {
36         return x < y ? x : y;
37 }
38 #endif
39
40 bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) {
41         (void)type;
42         connection_t *c = handle;
43
44         if(!c) {
45                 logger(DEBUG_ALWAYS, LOG_ERR, "send_meta_sptps() called with NULL pointer!");
46                 abort();
47         }
48
49         buffer_add(&c->outbuf, buffer, length);
50         io_set(&c->io, IO_READ | IO_WRITE);
51
52         return true;
53 }
54
55 bool send_meta(connection_t *c, const void *buffer, size_t length) {
56         if(!c) {
57                 logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
58                 abort();
59         }
60
61         logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of metadata to %s (%s)",
62                (unsigned long)length, c->name, c->hostname);
63
64         if(c->protocol_minor >= 2) {
65                 return sptps_send_record(&c->sptps, 0, buffer, length);
66         }
67
68         /* Add our data to buffer */
69         if(c->status.encryptout) {
70 #ifdef DISABLE_LEGACY
71                 return false;
72 #else
73                 assert(c->legacy);
74
75                 if(!decrease_budget(&c->legacy->out, length)) {
76                         logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
77                         return false;
78                 }
79
80                 size_t outlen = length;
81
82                 if(!cipher_encrypt(&c->legacy->out.cipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
83                         logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting metadata to %s (%s)",
84                                c->name, c->hostname);
85                         return false;
86                 }
87
88 #endif
89         } else {
90                 buffer_add(&c->outbuf, buffer, length);
91         }
92
93         io_set(&c->io, IO_READ | IO_WRITE);
94
95         return true;
96 }
97
98 void send_meta_raw(connection_t *c, const void *buffer, size_t length) {
99         if(!c) {
100                 logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
101                 abort();
102         }
103
104         logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of raw metadata to %s (%s)",
105                (unsigned long)length, c->name, c->hostname);
106
107         buffer_add(&c->outbuf, buffer, length);
108
109         io_set(&c->io, IO_READ | IO_WRITE);
110 }
111
112 void broadcast_meta(connection_t *from, const char *buffer, size_t length) {
113         for list_each(connection_t, c, &connection_list)
114                 if(c != from && c->edge) {
115                         send_meta(c, buffer, length);
116                 }
117 }
118
119 bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t length) {
120         const char *data = vdata;
121         connection_t *c = handle;
122
123         if(!c) {
124                 logger(DEBUG_ALWAYS, LOG_ERR, "receive_meta_sptps() called with NULL pointer!");
125                 abort();
126         }
127
128         if(type == SPTPS_HANDSHAKE) {
129                 if(c->allow_request == ACK) {
130                         return send_ack(c);
131                 } else {
132                         return true;
133                 }
134         }
135
136         if(!data) {
137                 return true;
138         }
139
140         /* Are we receiving a TCPpacket? */
141
142         if(c->tcplen) {
143                 if(length != c->tcplen) {
144                         return false;
145                 }
146
147                 receive_tcppacket(c, data, length);
148                 c->tcplen = 0;
149                 return true;
150         }
151
152         /* Change newline to null byte, just like non-SPTPS requests */
153
154         if(data[length - 1] == '\n') {
155                 ((char *)data)[length - 1] = 0;
156         }
157
158         /* Otherwise we are waiting for a request */
159
160         return receive_request(c, data);
161 }
162
163 bool receive_meta(connection_t *c) {
164         ssize_t inlen;
165         char inbuf[MAXBUFSIZE];
166         char *bufp = inbuf, *endp;
167
168         /* Strategy:
169            - Read as much as possible from the TCP socket in one go.
170            - Decrypt it.
171            - Check if a full request is in the input buffer.
172            - If yes, process request and remove it from the buffer,
173            then check again.
174            - If not, keep stuff in buffer and exit.
175          */
176
177         buffer_compact(&c->inbuf, MAXBUFSIZE);
178
179         if(sizeof(inbuf) <= c->inbuf.len) {
180                 logger(DEBUG_ALWAYS, LOG_ERR, "Input buffer full for %s (%s)", c->name, c->hostname);
181                 return false;
182         }
183
184         inlen = recv(c->socket, inbuf, sizeof(inbuf) - c->inbuf.len, 0);
185
186         if(inlen <= 0) {
187                 if(!inlen || !sockerrno) {
188                         logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)",
189                                c->name, c->hostname);
190                 } else if(sockwouldblock(sockerrno)) {
191                         return true;
192                 } else
193                         logger(DEBUG_ALWAYS, LOG_ERR, "Metadata socket read error for %s (%s): %s",
194                                c->name, c->hostname, sockstrerror(sockerrno));
195
196                 return false;
197         }
198
199         do {
200                 /* Are we receiving a SPTPS packet? */
201
202                 if(c->sptpslen) {
203                         ssize_t len = MIN(inlen, c->sptpslen - c->inbuf.len);
204                         buffer_add(&c->inbuf, bufp, len);
205
206                         char *sptpspacket = buffer_read(&c->inbuf, c->sptpslen);
207
208                         if(!sptpspacket) {
209                                 return true;
210                         }
211
212                         if(!receive_tcppacket_sptps(c, sptpspacket, c->sptpslen)) {
213                                 return false;
214                         }
215
216                         c->sptpslen = 0;
217
218                         bufp += len;
219                         inlen -= len;
220                         continue;
221                 }
222
223                 if(c->protocol_minor >= 2) {
224                         size_t len = sptps_receive_data(&c->sptps, bufp, inlen);
225
226                         if(!len) {
227                                 return false;
228                         }
229
230                         bufp += len;
231                         inlen -= (ssize_t)len;
232                         continue;
233                 }
234
235                 if(!c->status.decryptin) {
236                         endp = memchr(bufp, '\n', inlen);
237
238                         if(endp) {
239                                 endp++;
240                         } else {
241                                 endp = bufp + inlen;
242                         }
243
244                         buffer_add(&c->inbuf, bufp, endp - bufp);
245
246                         inlen -= endp - bufp;
247                         bufp = endp;
248                 } else {
249 #ifdef DISABLE_LEGACY
250                         return false;
251 #else
252                         assert(c->legacy);
253
254                         if(!decrease_budget(&c->legacy->in, (size_t) inlen)) {
255                                 logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
256                                 return false;
257                         }
258
259                         size_t outlen = inlen;
260
261                         if(!cipher_decrypt(&c->legacy->in.cipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || (size_t)inlen != outlen) {
262                                 logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting metadata from %s (%s)",
263                                        c->name, c->hostname);
264                                 return false;
265                         }
266
267                         inlen = 0;
268 #endif
269                 }
270
271                 while(c->inbuf.len) {
272                         /* Are we receiving a TCPpacket? */
273
274                         if(c->tcplen) {
275                                 char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen);
276
277                                 if(!tcpbuffer) {
278                                         break;
279                                 }
280
281                                 if(!c->node) {
282                                         if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) {
283                                                 if(tcpbuffer[0] == 0 && tcpbuffer[1] == 0x5a) {
284                                                         logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted");
285                                                 } else {
286                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected");
287                                                         return false;
288                                                 }
289                                         } else if(c->outgoing && proxytype == PROXY_SOCKS5 && c->allow_request == ID) {
290                                                 if(tcpbuffer[0] != 5) {
291                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server");
292                                                         return false;
293                                                 }
294
295                                                 if(tcpbuffer[1] == (char)0xff) {
296                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected: unsuitable authentication method");
297                                                         return false;
298                                                 }
299
300                                                 if(tcpbuffer[2] != 5) {
301                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server");
302                                                         return false;
303                                                 }
304
305                                                 if(tcpbuffer[3] == 0) {
306                                                         logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted");
307                                                 } else {
308                                                         logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request rejected");
309                                                         return false;
310                                                 }
311                                         } else {
312                                                 logger(DEBUG_CONNECTIONS, LOG_ERR, "c->tcplen set but c->node is NULL!");
313                                                 abort();
314                                         }
315                                 } else {
316                                         if(c->allow_request == ALL) {
317                                                 receive_tcppacket(c, tcpbuffer, c->tcplen);
318                                         } else {
319                                                 logger(DEBUG_CONNECTIONS, LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname);
320                                                 return false;
321                                         }
322                                 }
323
324                                 c->tcplen = 0;
325                         }
326
327                         /* Otherwise we are waiting for a request */
328
329                         char *request = buffer_readline(&c->inbuf);
330
331                         if(request) {
332                                 bool result = receive_request(c, request);
333
334                                 if(!result) {
335                                         return false;
336                                 }
337
338                                 continue;
339                         } else {
340                                 break;
341                         }
342                 }
343         } while(inlen);
344
345         return true;
346 }