Fix warnings when compiling for Windows.
[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 "cipher.h"
25 #include "connection.h"
26 #include "logger.h"
27 #include "meta.h"
28 #include "net.h"
29 #include "protocol.h"
30 #include "utils.h"
31 #include "xalloc.h"
32
33 #ifndef MIN
34 static ssize_t MIN(ssize_t x, ssize_t y) {
35         return x < y ? x : y;
36 }
37 #endif
38
39 bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) {
40         (void)type;
41         connection_t *c = handle;
42
43         if(!c) {
44                 logger(DEBUG_ALWAYS, LOG_ERR, "send_meta_sptps() called with NULL pointer!");
45                 abort();
46         }
47
48         buffer_add(&c->outbuf, buffer, length);
49         io_set(&c->io, IO_READ | IO_WRITE);
50
51         return true;
52 }
53
54 bool send_meta(connection_t *c, const char *buffer, size_t length) {
55         if(!c) {
56                 logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
57                 abort();
58         }
59
60         logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of metadata to %s (%s)", (unsigned long)length,
61                c->name, c->hostname);
62
63         if(c->protocol_minor >= 2) {
64                 return sptps_send_record(&c->sptps, 0, buffer, length);
65         }
66
67         /* Add our data to buffer */
68         if(c->status.encryptout) {
69 #ifdef DISABLE_LEGACY
70                 return false;
71 #else
72
73                 if(length > c->outbudget) {
74                         logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
75                         return false;
76                 } else {
77                         c->outbudget -= length;
78                 }
79
80                 size_t outlen = length;
81
82                 if(!cipher_encrypt(c->outcipher, 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 char *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)", (unsigned long)length,
105                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 -= 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
253                         if((size_t)inlen > c->inbudget) {
254                                 logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
255                                 return false;
256                         } else {
257                                 c->inbudget -= inlen;
258                         }
259
260                         size_t outlen = inlen;
261
262                         if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || (size_t)inlen != outlen) {
263                                 logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting metadata from %s (%s)",
264                                        c->name, c->hostname);
265                                 return false;
266                         }
267
268                         inlen = 0;
269 #endif
270                 }
271
272                 while(c->inbuf.len) {
273                         /* Are we receiving a TCPpacket? */
274
275                         if(c->tcplen) {
276                                 char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen);
277
278                                 if(!tcpbuffer) {
279                                         break;
280                                 }
281
282                                 if(!c->node) {
283                                         if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) {
284                                                 if(tcpbuffer[0] == 0 && tcpbuffer[1] == 0x5a) {
285                                                         logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted");
286                                                 } else {
287                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected");
288                                                         return false;
289                                                 }
290                                         } else if(c->outgoing && proxytype == PROXY_SOCKS5 && c->allow_request == ID) {
291                                                 if(tcpbuffer[0] != 5) {
292                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server");
293                                                         return false;
294                                                 }
295
296                                                 if(tcpbuffer[1] == (char)0xff) {
297                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected: unsuitable authentication method");
298                                                         return false;
299                                                 }
300
301                                                 if(tcpbuffer[2] != 5) {
302                                                         logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server");
303                                                         return false;
304                                                 }
305
306                                                 if(tcpbuffer[3] == 0) {
307                                                         logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted");
308                                                 } else {
309                                                         logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request rejected");
310                                                         return false;
311                                                 }
312                                         } else {
313                                                 logger(DEBUG_CONNECTIONS, LOG_ERR, "c->tcplen set but c->node is NULL!");
314                                                 abort();
315                                         }
316                                 } else {
317                                         if(c->allow_request == ALL) {
318                                                 receive_tcppacket(c, tcpbuffer, c->tcplen);
319                                         } else {
320                                                 logger(DEBUG_CONNECTIONS, LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname);
321                                                 return false;
322                                         }
323                                 }
324
325                                 c->tcplen = 0;
326                         }
327
328                         /* Otherwise we are waiting for a request */
329
330                         char *request = buffer_readline(&c->inbuf);
331
332                         if(request) {
333                                 bool result = receive_request(c, request);
334
335                                 if(!result) {
336                                         return false;
337                                 }
338
339                                 continue;
340                         } else {
341                                 break;
342                         }
343                 }
344         } while(inlen);
345
346         return true;
347 }