1 /*
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include "bio_local.h"
13 #ifndef OPENSSL_NO_SOCK
14 # define SOCKET_PROTOCOL IPPROTO_TCP
15 # ifdef SO_MAXCONN
16 # define MAX_LISTEN SO_MAXCONN
17 # elif defined(SOMAXCONN)
18 # define MAX_LISTEN SOMAXCONN
19 # else
20 # define MAX_LISTEN 32
21 # endif
22 # if defined(OPENSSL_SYS_WINDOWS)
23 static int wsa_init_done = 0;
24 # endif
25
26 # if defined __TANDEM
27 # include <unistd.h>
28 # include <sys/time.h> /* select */
29 # elif defined _WIN32
30 # include <winsock.h> /* for type fd_set */
31 # else
32 # include <unistd.h>
33 # if defined __VMS
34 # include <sys/socket.h>
35 # elif defined _HPUX_SOURCE
36 # include <sys/time.h>
37 # else
38 # include <sys/select.h>
39 # endif
40 # endif
41
42 # ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_get_host_ip(const char * str,unsigned char * ip)43 int BIO_get_host_ip(const char *str, unsigned char *ip)
44 {
45 BIO_ADDRINFO *res = NULL;
46 int ret = 0;
47
48 if (BIO_sock_init() != 1)
49 return 0; /* don't generate another error code here */
50
51 if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
52 size_t l;
53
54 if (BIO_ADDRINFO_family(res) != AF_INET) {
55 ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
56 } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) {
57 /*
58 * Because only AF_INET addresses will reach this far, we can assert
59 * that l should be 4
60 */
61 if (ossl_assert(l == 4))
62 ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
63 }
64 BIO_ADDRINFO_free(res);
65 } else {
66 ERR_add_error_data(2, "host=", str);
67 }
68
69 return ret;
70 }
71
BIO_get_port(const char * str,unsigned short * port_ptr)72 int BIO_get_port(const char *str, unsigned short *port_ptr)
73 {
74 BIO_ADDRINFO *res = NULL;
75 int ret = 0;
76
77 if (str == NULL) {
78 ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED);
79 return 0;
80 }
81
82 if (BIO_sock_init() != 1)
83 return 0; /* don't generate another error code here */
84
85 if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
86 if (BIO_ADDRINFO_family(res) != AF_INET) {
87 ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
88 } else {
89 *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
90 ret = 1;
91 }
92 BIO_ADDRINFO_free(res);
93 } else {
94 ERR_add_error_data(2, "host=", str);
95 }
96
97 return ret;
98 }
99 # endif
100
BIO_sock_error(int sock)101 int BIO_sock_error(int sock)
102 {
103 int j = 0, i;
104 socklen_t size = sizeof(j);
105
106 /*
107 * Note: under Windows the third parameter is of type (char *) whereas
108 * under other systems it is (void *) if you don't have a cast it will
109 * choke the compiler: if you do have a cast then you can either go for
110 * (char *) or (void *).
111 */
112 i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
113 if (i < 0)
114 return get_last_socket_error();
115 else
116 return j;
117 }
118
119 # ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_gethostbyname(const char * name)120 struct hostent *BIO_gethostbyname(const char *name)
121 {
122 /*
123 * Caching gethostbyname() results forever is wrong, so we have to let
124 * the true gethostbyname() worry about this
125 */
126 return gethostbyname(name);
127 }
128 # endif
129
130 # ifdef BIO_HAVE_WSAMSG
131 LPFN_WSARECVMSG bio_WSARecvMsg;
132 LPFN_WSASENDMSG bio_WSASendMsg;
133 # endif
134
BIO_sock_init(void)135 int BIO_sock_init(void)
136 {
137 # ifdef OPENSSL_SYS_WINDOWS
138 static struct WSAData wsa_state;
139
140 if (!wsa_init_done) {
141 wsa_init_done = 1;
142 memset(&wsa_state, 0, sizeof(wsa_state));
143 /*
144 * Not making wsa_state available to the rest of the code is formally
145 * wrong. But the structures we use are [believed to be] invariable
146 * among Winsock DLLs, while API availability is [expected to be]
147 * probed at run-time with DSO_global_lookup.
148 */
149 if (WSAStartup(0x0202, &wsa_state) != 0) {
150 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
151 "calling wsastartup()");
152 ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP);
153 return -1;
154 }
155
156 /*
157 * On Windows, some socket functions are not exposed as a prototype.
158 * Instead, their function pointers must be loaded via this elaborate
159 * process...
160 */
161 # ifdef BIO_HAVE_WSAMSG
162 {
163 GUID id_WSARecvMsg = WSAID_WSARECVMSG;
164 GUID id_WSASendMsg = WSAID_WSASENDMSG;
165 DWORD len_out = 0;
166 SOCKET s;
167
168 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
169 if (s != INVALID_SOCKET) {
170 if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
171 &id_WSARecvMsg, sizeof(id_WSARecvMsg),
172 &bio_WSARecvMsg, sizeof(bio_WSARecvMsg),
173 &len_out, NULL, NULL) != 0
174 || len_out != sizeof(bio_WSARecvMsg))
175 bio_WSARecvMsg = NULL;
176
177 if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
178 &id_WSASendMsg, sizeof(id_WSASendMsg),
179 &bio_WSASendMsg, sizeof(bio_WSASendMsg),
180 &len_out, NULL, NULL) != 0
181 || len_out != sizeof(bio_WSASendMsg))
182 bio_WSASendMsg = NULL;
183
184 closesocket(s);
185 }
186 }
187 # endif
188 }
189 # endif /* OPENSSL_SYS_WINDOWS */
190 # ifdef WATT32
191 extern int _watt_do_exit;
192 _watt_do_exit = 0; /* don't make sock_init() call exit() */
193 if (sock_init())
194 return -1;
195 # endif
196
197 return 1;
198 }
199
bio_sock_cleanup_int(void)200 void bio_sock_cleanup_int(void)
201 {
202 # ifdef OPENSSL_SYS_WINDOWS
203 if (wsa_init_done) {
204 wsa_init_done = 0;
205 WSACleanup();
206 }
207 # endif
208 }
209
BIO_socket_ioctl(int fd,long type,void * arg)210 int BIO_socket_ioctl(int fd, long type, void *arg)
211 {
212 int i;
213
214 # ifdef __DJGPP__
215 i = ioctlsocket(fd, type, (char *)arg);
216 # else
217 # if defined(OPENSSL_SYS_VMS)
218 /*-
219 * 2011-02-18 SMS.
220 * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
221 * observe that all the consumers pass in an "unsigned long *",
222 * so we arrange a local copy with a short pointer, and use
223 * that, instead.
224 */
225 # if __INITIAL_POINTER_SIZE == 64
226 # define ARG arg_32p
227 # pragma pointer_size save
228 # pragma pointer_size 32
229 unsigned long arg_32;
230 unsigned long *arg_32p;
231 # pragma pointer_size restore
232 arg_32p = &arg_32;
233 arg_32 = *((unsigned long *)arg);
234 # else /* __INITIAL_POINTER_SIZE == 64 */
235 # define ARG arg
236 # endif /* __INITIAL_POINTER_SIZE == 64 [else] */
237 # else /* defined(OPENSSL_SYS_VMS) */
238 # define ARG arg
239 # endif /* defined(OPENSSL_SYS_VMS) [else] */
240
241 i = ioctlsocket(fd, type, ARG);
242 # endif /* __DJGPP__ */
243 if (i < 0)
244 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
245 "calling ioctlsocket()");
246 return i;
247 }
248
249 # ifndef OPENSSL_NO_DEPRECATED_1_1_0
BIO_get_accept_socket(char * host,int bind_mode)250 int BIO_get_accept_socket(char *host, int bind_mode)
251 {
252 int s = INVALID_SOCKET;
253 char *h = NULL, *p = NULL;
254 BIO_ADDRINFO *res = NULL;
255
256 if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
257 return INVALID_SOCKET;
258
259 if (BIO_sock_init() != 1)
260 return INVALID_SOCKET;
261
262 if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
263 goto err;
264
265 if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
266 BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
267 s = INVALID_SOCKET;
268 goto err;
269 }
270
271 if (!BIO_listen(s, BIO_ADDRINFO_address(res),
272 bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
273 BIO_closesocket(s);
274 s = INVALID_SOCKET;
275 }
276
277 err:
278 BIO_ADDRINFO_free(res);
279 OPENSSL_free(h);
280 OPENSSL_free(p);
281
282 return s;
283 }
284
BIO_accept(int sock,char ** ip_port)285 int BIO_accept(int sock, char **ip_port)
286 {
287 BIO_ADDR res;
288 int ret = -1;
289
290 ret = BIO_accept_ex(sock, &res, 0);
291 if (ret == (int)INVALID_SOCKET) {
292 if (BIO_sock_should_retry(ret)) {
293 ret = -2;
294 goto end;
295 }
296 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
297 "calling accept()");
298 ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
299 goto end;
300 }
301
302 if (ip_port != NULL) {
303 char *host = BIO_ADDR_hostname_string(&res, 1);
304 char *port = BIO_ADDR_service_string(&res, 1);
305 if (host != NULL && port != NULL) {
306 *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
307 } else {
308 *ip_port = NULL;
309 ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
310 }
311
312 if (*ip_port == NULL) {
313 BIO_closesocket(ret);
314 ret = (int)INVALID_SOCKET;
315 } else {
316 strcpy(*ip_port, host);
317 strcat(*ip_port, ":");
318 strcat(*ip_port, port);
319 }
320 OPENSSL_free(host);
321 OPENSSL_free(port);
322 }
323
324 end:
325 return ret;
326 }
327 # endif
328
BIO_set_tcp_ndelay(int s,int on)329 int BIO_set_tcp_ndelay(int s, int on)
330 {
331 int ret = 0;
332 # if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
333 int opt;
334
335 # ifdef SOL_TCP
336 opt = SOL_TCP;
337 # else
338 # ifdef IPPROTO_TCP
339 opt = IPPROTO_TCP;
340 # endif
341 # endif
342
343 ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
344 # endif
345 return (ret == 0);
346 }
347
BIO_socket_nbio(int s,int mode)348 int BIO_socket_nbio(int s, int mode)
349 {
350 int ret = -1;
351 int l;
352
353 l = mode;
354 # ifdef FIONBIO
355 l = mode;
356
357 ret = BIO_socket_ioctl(s, FIONBIO, &l);
358 # elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
359 /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
360
361 l = fcntl(s, F_GETFL, 0);
362 if (l == -1) {
363 ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
364 "calling fcntl()");
365 ret = -1;
366 } else {
367 # if defined(O_NONBLOCK)
368 l &= ~O_NONBLOCK;
369 # else
370 l &= ~FNDELAY; /* BSD4.x */
371 # endif
372 if (mode) {
373 # if defined(O_NONBLOCK)
374 l |= O_NONBLOCK;
375 # else
376 l |= FNDELAY; /* BSD4.x */
377 # endif
378 }
379 ret = fcntl(s, F_SETFL, l);
380
381 if (ret < 0) {
382 ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
383 "calling fcntl()");
384 }
385 }
386 # else
387 /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
388 ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT);
389 # endif
390
391 return (ret == 0);
392 }
393
BIO_sock_info(int sock,enum BIO_sock_info_type type,union BIO_sock_info_u * info)394 int BIO_sock_info(int sock,
395 enum BIO_sock_info_type type, union BIO_sock_info_u *info)
396 {
397 switch (type) {
398 case BIO_SOCK_INFO_ADDRESS:
399 {
400 socklen_t addr_len;
401 int ret = 0;
402 addr_len = sizeof(*info->addr);
403 ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
404 &addr_len);
405 if (ret == -1) {
406 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
407 "calling getsockname()");
408 ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR);
409 return 0;
410 }
411 if ((size_t)addr_len > sizeof(*info->addr)) {
412 ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
413 return 0;
414 }
415 }
416 break;
417 default:
418 ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE);
419 return 0;
420 }
421 return 1;
422 }
423
424 /*
425 * Wait on fd at most until max_time; succeed immediately if max_time == 0.
426 * If for_read == 0 then assume to wait for writing, else wait for reading.
427 * Returns -1 on error, 0 on timeout, and 1 on success.
428 */
BIO_socket_wait(int fd,int for_read,time_t max_time)429 int BIO_socket_wait(int fd, int for_read, time_t max_time)
430 {
431 fd_set confds;
432 struct timeval tv;
433 time_t now;
434
435 #ifdef _WIN32
436 if ((SOCKET)fd == INVALID_SOCKET)
437 #else
438 if (fd < 0 || fd >= FD_SETSIZE)
439 #endif
440 return -1;
441 if (max_time == 0)
442 return 1;
443
444 now = time(NULL);
445 if (max_time < now)
446 return 0;
447
448 FD_ZERO(&confds);
449 openssl_fdset(fd, &confds);
450 tv.tv_usec = 0;
451 tv.tv_sec = (long)(max_time - now); /* might overflow */
452 return select(fd + 1, for_read ? &confds : NULL,
453 for_read ? NULL : &confds, NULL, &tv);
454 }
455 #endif /* !defined(OPENSSL_NO_SOCK) */
456