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