xref: /reactos/dll/3rdparty/mbedtls/net_sockets.c (revision 8a978a17)
1 /*
2  *  TCP/IP or UDP/IP networking functions
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  *
46  *  This file is part of mbed TLS (https://tls.mbed.org)
47  */
48 
49 #if !defined(MBEDTLS_CONFIG_FILE)
50 #include "mbedtls/config.h"
51 #else
52 #include MBEDTLS_CONFIG_FILE
53 #endif
54 
55 #if defined(MBEDTLS_NET_C)
56 
57 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
58     !defined(__APPLE__) && !defined(_WIN32)
59 #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
60 #endif
61 
62 #if defined(MBEDTLS_PLATFORM_C)
63 #include "mbedtls/platform.h"
64 #else
65 #include <stdlib.h>
66 #endif
67 
68 #include "mbedtls/net_sockets.h"
69 
70 #include <string.h>
71 
72 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
73     !defined(EFI32)
74 
75 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
76 #undef _WIN32_WINNT
77 /* Enables getaddrinfo() & Co */
78 #define _WIN32_WINNT 0x0501
79 #endif
80 
81 #include <ws2tcpip.h>
82 
83 #include <winsock2.h>
84 #include <windows.h>
85 
86 #if defined(_MSC_VER)
87 #if defined(_WIN32_WCE)
88 #pragma comment( lib, "ws2.lib" )
89 #else
90 #pragma comment( lib, "ws2_32.lib" )
91 #endif
92 #endif /* _MSC_VER */
93 
94 #define read(fd,buf,len)        recv( fd, (char*)( buf ), (int)( len ), 0 )
95 #define write(fd,buf,len)       send( fd, (char*)( buf ), (int)( len ), 0 )
96 #define close(fd)               closesocket(fd)
97 
98 static int wsa_init_done = 0;
99 
100 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
101 
102 #include <sys/types.h>
103 #include <sys/socket.h>
104 #include <netinet/in.h>
105 #include <arpa/inet.h>
106 #include <sys/time.h>
107 #include <unistd.h>
108 #include <signal.h>
109 #include <fcntl.h>
110 #include <netdb.h>
111 #include <errno.h>
112 
113 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
114 
115 /* Some MS functions want int and MSVC warns if we pass size_t,
116  * but the standard functions use socklen_t, so cast only for MSVC */
117 #if defined(_MSC_VER)
118 #define MSVC_INT_CAST   (int)
119 #else
120 #define MSVC_INT_CAST
121 #endif
122 
123 #include <stdio.h>
124 
125 #include <time.h>
126 
127 #include <stdint.h>
128 
129 /*
130  * Prepare for using the sockets interface
131  */
132 static int net_prepare( void )
133 {
134 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
135     !defined(EFI32)
136     WSADATA wsaData;
137 
138     if( wsa_init_done == 0 )
139     {
140         if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
141             return( MBEDTLS_ERR_NET_SOCKET_FAILED );
142 
143         wsa_init_done = 1;
144     }
145 #else
146 #if !defined(EFIX64) && !defined(EFI32)
147     signal( SIGPIPE, SIG_IGN );
148 #endif
149 #endif
150     return( 0 );
151 }
152 
153 /*
154  * Initialize a context
155  */
156 void mbedtls_net_init( mbedtls_net_context *ctx )
157 {
158     ctx->fd = -1;
159 }
160 
161 /*
162  * Initiate a TCP connection with host:port and the given protocol
163  */
164 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
165                          const char *port, int proto )
166 {
167     int ret;
168     struct addrinfo hints, *addr_list, *cur;
169 
170     if( ( ret = net_prepare() ) != 0 )
171         return( ret );
172 
173     /* Do name resolution with both IPv6 and IPv4 */
174     memset( &hints, 0, sizeof( hints ) );
175     hints.ai_family = AF_UNSPEC;
176     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
177     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
178 
179     if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
180         return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
181 
182     /* Try the sockaddrs until a connection succeeds */
183     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
184     for( cur = addr_list; cur != NULL; cur = cur->ai_next )
185     {
186         ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
187                             cur->ai_protocol );
188         if( ctx->fd < 0 )
189         {
190             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
191             continue;
192         }
193 
194         if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
195         {
196             ret = 0;
197             break;
198         }
199 
200         close( ctx->fd );
201         ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
202     }
203 
204     freeaddrinfo( addr_list );
205 
206     return( ret );
207 }
208 
209 /*
210  * Create a listening socket on bind_ip:port
211  */
212 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
213 {
214     int n, ret;
215     struct addrinfo hints, *addr_list, *cur;
216 
217     if( ( ret = net_prepare() ) != 0 )
218         return( ret );
219 
220     /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
221     memset( &hints, 0, sizeof( hints ) );
222     hints.ai_family = AF_UNSPEC;
223     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
224     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
225     if( bind_ip == NULL )
226         hints.ai_flags = AI_PASSIVE;
227 
228     if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
229         return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
230 
231     /* Try the sockaddrs until a binding succeeds */
232     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
233     for( cur = addr_list; cur != NULL; cur = cur->ai_next )
234     {
235         ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
236                             cur->ai_protocol );
237         if( ctx->fd < 0 )
238         {
239             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
240             continue;
241         }
242 
243         n = 1;
244         if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
245                         (const char *) &n, sizeof( n ) ) != 0 )
246         {
247             close( ctx->fd );
248             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
249             continue;
250         }
251 
252         if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
253         {
254             close( ctx->fd );
255             ret = MBEDTLS_ERR_NET_BIND_FAILED;
256             continue;
257         }
258 
259         /* Listen only makes sense for TCP */
260         if( proto == MBEDTLS_NET_PROTO_TCP )
261         {
262             if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
263             {
264                 close( ctx->fd );
265                 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
266                 continue;
267             }
268         }
269 
270         /* Bind was successful */
271         ret = 0;
272         break;
273     }
274 
275     freeaddrinfo( addr_list );
276 
277     return( ret );
278 
279 }
280 
281 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
282     !defined(EFI32)
283 /*
284  * Check if the requested operation would be blocking on a non-blocking socket
285  * and thus 'failed' with a negative return value.
286  */
287 static int net_would_block( const mbedtls_net_context *ctx )
288 {
289     ((void) ctx);
290     return( WSAGetLastError() == WSAEWOULDBLOCK );
291 }
292 #else
293 /*
294  * Check if the requested operation would be blocking on a non-blocking socket
295  * and thus 'failed' with a negative return value.
296  *
297  * Note: on a blocking socket this function always returns 0!
298  */
299 static int net_would_block( const mbedtls_net_context *ctx )
300 {
301     int err = errno;
302 
303     /*
304      * Never return 'WOULD BLOCK' on a blocking socket
305      */
306     if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
307     {
308         errno = err;
309         return( 0 );
310     }
311 
312     switch( errno = err )
313     {
314 #if defined EAGAIN
315         case EAGAIN:
316 #endif
317 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
318         case EWOULDBLOCK:
319 #endif
320             return( 1 );
321     }
322     return( 0 );
323 }
324 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
325 
326 /*
327  * Accept a connection from a remote client
328  */
329 int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
330                         mbedtls_net_context *client_ctx,
331                         void *client_ip, size_t buf_size, size_t *ip_len )
332 {
333     int ret;
334     int type;
335 
336     struct sockaddr_storage client_addr;
337 
338 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
339     defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
340     socklen_t n = (socklen_t) sizeof( client_addr );
341     socklen_t type_len = (socklen_t) sizeof( type );
342 #else
343     int n = (int) sizeof( client_addr );
344     int type_len = (int) sizeof( type );
345 #endif
346 
347     /* Is this a TCP or UDP socket? */
348     if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
349                     (void *) &type, &type_len ) != 0 ||
350         ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
351     {
352         return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
353     }
354 
355     if( type == SOCK_STREAM )
356     {
357         /* TCP: actual accept() */
358         ret = client_ctx->fd = (int) accept( bind_ctx->fd,
359                                              (struct sockaddr *) &client_addr, &n );
360     }
361     else
362     {
363         /* UDP: wait for a message, but keep it in the queue */
364         char buf[1] = { 0 };
365 
366         ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
367                         (struct sockaddr *) &client_addr, &n );
368 
369 #if defined(_WIN32)
370         if( ret == SOCKET_ERROR &&
371             WSAGetLastError() == WSAEMSGSIZE )
372         {
373             /* We know buf is too small, thanks, just peeking here */
374             ret = 0;
375         }
376 #endif
377     }
378 
379     if( ret < 0 )
380     {
381         if( net_would_block( bind_ctx ) != 0 )
382             return( MBEDTLS_ERR_SSL_WANT_READ );
383 
384         return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
385     }
386 
387     /* UDP: hijack the listening socket to communicate with the client,
388      * then bind a new socket to accept new connections */
389     if( type != SOCK_STREAM )
390     {
391         struct sockaddr_storage local_addr;
392         int one = 1;
393 
394         if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
395             return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
396 
397         client_ctx->fd = bind_ctx->fd;
398         bind_ctx->fd   = -1; /* In case we exit early */
399 
400         n = sizeof( struct sockaddr_storage );
401         if( getsockname( client_ctx->fd,
402                          (struct sockaddr *) &local_addr, &n ) != 0 ||
403             ( bind_ctx->fd = (int) socket( local_addr.ss_family,
404                                            SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
405             setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
406                         (const char *) &one, sizeof( one ) ) != 0 )
407         {
408             return( MBEDTLS_ERR_NET_SOCKET_FAILED );
409         }
410 
411         if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
412         {
413             return( MBEDTLS_ERR_NET_BIND_FAILED );
414         }
415     }
416 
417     if( client_ip != NULL )
418     {
419         if( client_addr.ss_family == AF_INET )
420         {
421             struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
422             *ip_len = sizeof( addr4->sin_addr.s_addr );
423 
424             if( buf_size < *ip_len )
425                 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
426 
427             memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
428         }
429         else
430         {
431             struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
432             *ip_len = sizeof( addr6->sin6_addr.s6_addr );
433 
434             if( buf_size < *ip_len )
435                 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
436 
437             memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
438         }
439     }
440 
441     return( 0 );
442 }
443 
444 /*
445  * Set the socket blocking or non-blocking
446  */
447 int mbedtls_net_set_block( mbedtls_net_context *ctx )
448 {
449 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
450     !defined(EFI32)
451     u_long n = 0;
452     return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
453 #else
454     return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
455 #endif
456 }
457 
458 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
459 {
460 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
461     !defined(EFI32)
462     u_long n = 1;
463     return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
464 #else
465     return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
466 #endif
467 }
468 
469 /*
470  * Portable usleep helper
471  */
472 void mbedtls_net_usleep( unsigned long usec )
473 {
474 #if defined(_WIN32)
475     Sleep( ( usec + 999 ) / 1000 );
476 #else
477     struct timeval tv;
478     tv.tv_sec  = usec / 1000000;
479 #if defined(__unix__) || defined(__unix) || \
480     ( defined(__APPLE__) && defined(__MACH__) )
481     tv.tv_usec = (suseconds_t) usec % 1000000;
482 #else
483     tv.tv_usec = usec % 1000000;
484 #endif
485     select( 0, NULL, NULL, NULL, &tv );
486 #endif
487 }
488 
489 /*
490  * Read at most 'len' characters
491  */
492 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
493 {
494     int ret;
495     int fd = ((mbedtls_net_context *) ctx)->fd;
496 
497     if( fd < 0 )
498         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
499 
500     ret = (int) read( fd, buf, len );
501 
502     if( ret < 0 )
503     {
504         if( net_would_block( ctx ) != 0 )
505             return( MBEDTLS_ERR_SSL_WANT_READ );
506 
507 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
508     !defined(EFI32)
509         if( WSAGetLastError() == WSAECONNRESET )
510             return( MBEDTLS_ERR_NET_CONN_RESET );
511 #else
512         if( errno == EPIPE || errno == ECONNRESET )
513             return( MBEDTLS_ERR_NET_CONN_RESET );
514 
515         if( errno == EINTR )
516             return( MBEDTLS_ERR_SSL_WANT_READ );
517 #endif
518 
519         return( MBEDTLS_ERR_NET_RECV_FAILED );
520     }
521 
522     return( ret );
523 }
524 
525 /*
526  * Read at most 'len' characters, blocking for at most 'timeout' ms
527  */
528 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
529                       uint32_t timeout )
530 {
531     int ret;
532     struct timeval tv;
533     fd_set read_fds;
534     int fd = ((mbedtls_net_context *) ctx)->fd;
535 
536     if( fd < 0 )
537         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
538 
539     FD_ZERO( &read_fds );
540     FD_SET( fd, &read_fds );
541 
542     tv.tv_sec  = timeout / 1000;
543     tv.tv_usec = ( timeout % 1000 ) * 1000;
544 
545     ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
546 
547     /* Zero fds ready means we timed out */
548     if( ret == 0 )
549         return( MBEDTLS_ERR_SSL_TIMEOUT );
550 
551     if( ret < 0 )
552     {
553 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
554     !defined(EFI32)
555         if( WSAGetLastError() == WSAEINTR )
556             return( MBEDTLS_ERR_SSL_WANT_READ );
557 #else
558         if( errno == EINTR )
559             return( MBEDTLS_ERR_SSL_WANT_READ );
560 #endif
561 
562         return( MBEDTLS_ERR_NET_RECV_FAILED );
563     }
564 
565     /* This call will not block */
566     return( mbedtls_net_recv( ctx, buf, len ) );
567 }
568 
569 /*
570  * Write at most 'len' characters
571  */
572 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
573 {
574     int ret;
575     int fd = ((mbedtls_net_context *) ctx)->fd;
576 
577     if( fd < 0 )
578         return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
579 
580     ret = (int) write( fd, buf, len );
581 
582     if( ret < 0 )
583     {
584         if( net_would_block( ctx ) != 0 )
585             return( MBEDTLS_ERR_SSL_WANT_WRITE );
586 
587 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
588     !defined(EFI32)
589         if( WSAGetLastError() == WSAECONNRESET )
590             return( MBEDTLS_ERR_NET_CONN_RESET );
591 #else
592         if( errno == EPIPE || errno == ECONNRESET )
593             return( MBEDTLS_ERR_NET_CONN_RESET );
594 
595         if( errno == EINTR )
596             return( MBEDTLS_ERR_SSL_WANT_WRITE );
597 #endif
598 
599         return( MBEDTLS_ERR_NET_SEND_FAILED );
600     }
601 
602     return( ret );
603 }
604 
605 /*
606  * Gracefully close the connection
607  */
608 void mbedtls_net_free( mbedtls_net_context *ctx )
609 {
610     if( ctx->fd == -1 )
611         return;
612 
613     shutdown( ctx->fd, 2 );
614     close( ctx->fd );
615 
616     ctx->fd = -1;
617 }
618 
619 #endif /* MBEDTLS_NET_C */
620