xref: /freebsd/crypto/openssl/crypto/bio/bio_addr.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1 /*
2  * Copyright 2016-2025 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 #ifndef _GNU_SOURCE
11 # define _GNU_SOURCE
12 #endif
13 
14 /*
15  * VC configurations may define UNICODE, to indicate to the C RTL that
16  * WCHAR functions are preferred.
17  * This affects functions like gai_strerror(), which is implemented as
18  * an alias macro for gai_strerrorA() (which returns a const char *) or
19  * gai_strerrorW() (which returns a const WCHAR *).  This source file
20  * assumes POSIX declarations, so prefer the non-UNICODE definitions.
21  */
22 #undef UNICODE
23 
24 #include <assert.h>
25 #include <string.h>
26 
27 #include "bio_local.h"
28 #include <openssl/crypto.h>
29 
30 #ifndef OPENSSL_NO_SOCK
31 #include <openssl/err.h>
32 #include <openssl/buffer.h>
33 #include "internal/thread_once.h"
34 
35 CRYPTO_RWLOCK *bio_lookup_lock;
36 static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
37 
38 /*
39  * Throughout this file and bio_local.h, the existence of the macro
40  * AI_PASSIVE is used to detect the availability of struct addrinfo,
41  * getnameinfo() and getaddrinfo().  If that macro doesn't exist,
42  * we use our own implementation instead, using gethostbyname,
43  * getservbyname and a few other.
44  */
45 
46 /**********************************************************************
47  *
48  * Address structure
49  *
50  */
51 
BIO_ADDR_new(void)52 BIO_ADDR *BIO_ADDR_new(void)
53 {
54     BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
55 
56     if (ret == NULL)
57         return NULL;
58 
59     ret->sa.sa_family = AF_UNSPEC;
60     return ret;
61 }
62 
BIO_ADDR_free(BIO_ADDR * ap)63 void BIO_ADDR_free(BIO_ADDR *ap)
64 {
65     OPENSSL_free(ap);
66 }
67 
BIO_ADDR_copy(BIO_ADDR * dst,const BIO_ADDR * src)68 int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src)
69 {
70     if (dst == NULL || src == NULL)
71         return 0;
72 
73     if (src->sa.sa_family == AF_UNSPEC) {
74         BIO_ADDR_clear(dst);
75         return 1;
76     }
77 
78     return BIO_ADDR_make(dst, &src->sa);
79 }
80 
BIO_ADDR_dup(const BIO_ADDR * ap)81 BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap)
82 {
83     BIO_ADDR *ret = NULL;
84 
85     if (ap != NULL) {
86         ret = BIO_ADDR_new();
87         if (ret != NULL && !BIO_ADDR_copy(ret, ap)) {
88             BIO_ADDR_free(ret);
89             ret = NULL;
90         }
91     }
92     return ret;
93 }
94 
BIO_ADDR_clear(BIO_ADDR * ap)95 void BIO_ADDR_clear(BIO_ADDR *ap)
96 {
97     memset(ap, 0, sizeof(*ap));
98     ap->sa.sa_family = AF_UNSPEC;
99 }
100 
101 /*
102  * BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
103  * of a struct sockaddr.
104  */
BIO_ADDR_make(BIO_ADDR * ap,const struct sockaddr * sa)105 int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
106 {
107     memset(ap, 0, sizeof(BIO_ADDR));
108     if (sa->sa_family == AF_INET) {
109         memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
110         return 1;
111     }
112 #if OPENSSL_USE_IPV6
113     if (sa->sa_family == AF_INET6) {
114         memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6));
115         return 1;
116     }
117 #endif
118 #ifndef OPENSSL_NO_UNIX_SOCK
119     if (sa->sa_family == AF_UNIX) {
120         memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un));
121         return 1;
122     }
123 #endif
124 
125     return 0;
126 }
127 
BIO_ADDR_rawmake(BIO_ADDR * ap,int family,const void * where,size_t wherelen,unsigned short port)128 int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
129                      const void *where, size_t wherelen,
130                      unsigned short port)
131 {
132 #ifndef OPENSSL_NO_UNIX_SOCK
133     if (family == AF_UNIX) {
134         if (wherelen + 1 > sizeof(ap->s_un.sun_path))
135             return 0;
136         memset(&ap->s_un, 0, sizeof(ap->s_un));
137         ap->s_un.sun_family = family;
138         strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1);
139         return 1;
140     }
141 #endif
142     if (family == AF_INET) {
143         if (wherelen != sizeof(struct in_addr))
144             return 0;
145         memset(&ap->s_in, 0, sizeof(ap->s_in));
146         ap->s_in.sin_family = family;
147         ap->s_in.sin_port = port;
148         ap->s_in.sin_addr = *(struct in_addr *)where;
149         return 1;
150     }
151 #if OPENSSL_USE_IPV6
152     if (family == AF_INET6) {
153         if (wherelen != sizeof(struct in6_addr))
154             return 0;
155         memset(&ap->s_in6, 0, sizeof(ap->s_in6));
156         ap->s_in6.sin6_family = family;
157         ap->s_in6.sin6_port = port;
158         ap->s_in6.sin6_addr = *(struct in6_addr *)where;
159         return 1;
160     }
161 #endif
162 
163     return 0;
164 }
165 
BIO_ADDR_family(const BIO_ADDR * ap)166 int BIO_ADDR_family(const BIO_ADDR *ap)
167 {
168     return ap->sa.sa_family;
169 }
170 
BIO_ADDR_rawaddress(const BIO_ADDR * ap,void * p,size_t * l)171 int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
172 {
173     size_t len = 0;
174     const void *addrptr = NULL;
175 
176     if (ap->sa.sa_family == AF_INET) {
177         len = sizeof(ap->s_in.sin_addr);
178         addrptr = &ap->s_in.sin_addr;
179     }
180 #if OPENSSL_USE_IPV6
181     else if (ap->sa.sa_family == AF_INET6) {
182         len = sizeof(ap->s_in6.sin6_addr);
183         addrptr = &ap->s_in6.sin6_addr;
184     }
185 #endif
186 #ifndef OPENSSL_NO_UNIX_SOCK
187     else if (ap->sa.sa_family == AF_UNIX) {
188         len = strlen(ap->s_un.sun_path);
189         addrptr = &ap->s_un.sun_path;
190     }
191 #endif
192 
193     if (addrptr == NULL)
194         return 0;
195 
196     if (p != NULL) {
197         memcpy(p, addrptr, len);
198     }
199     if (l != NULL)
200         *l = len;
201 
202     return 1;
203 }
204 
BIO_ADDR_rawport(const BIO_ADDR * ap)205 unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
206 {
207     if (ap->sa.sa_family == AF_INET)
208         return ap->s_in.sin_port;
209 #if OPENSSL_USE_IPV6
210     if (ap->sa.sa_family == AF_INET6)
211         return ap->s_in6.sin6_port;
212 #endif
213     return 0;
214 }
215 
216 /*-
217  * addr_strings - helper function to get host and service names
218  * @ap: the BIO_ADDR that has the input info
219  * @numeric: 0 if actual names should be returned, 1 if the numeric
220  * representation should be returned.
221  * @hostname: a pointer to a pointer to a memory area to store the
222  * hostname or numeric representation.  Unused if NULL.
223  * @service: a pointer to a pointer to a memory area to store the
224  * service name or numeric representation.  Unused if NULL.
225  *
226  * The return value is 0 on failure, with the error code in the error
227  * stack, and 1 on success.
228  */
addr_strings(const BIO_ADDR * ap,int numeric,char ** hostname,char ** service)229 static int addr_strings(const BIO_ADDR *ap, int numeric,
230                         char **hostname, char **service)
231 {
232     if (BIO_sock_init() != 1)
233         return 0;
234 
235     if (1) {
236 #ifdef AI_PASSIVE
237         int ret = 0;
238         char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
239         int flags = 0;
240 
241         if (numeric)
242             flags |= NI_NUMERICHOST | NI_NUMERICSERV;
243 
244         if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
245                                BIO_ADDR_sockaddr_size(ap),
246                                host, sizeof(host), serv, sizeof(serv),
247                                flags)) != 0) {
248 # ifdef EAI_SYSTEM
249             if (ret == EAI_SYSTEM) {
250                 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
251                                "calling getnameinfo()");
252             } else
253 # endif
254             {
255                 ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, gai_strerror(ret));
256             }
257             return 0;
258         }
259 
260         /* VMS getnameinfo() has a bug, it doesn't fill in serv, which
261          * leaves it with whatever garbage that happens to be there.
262          * However, we initialise serv with the empty string (serv[0]
263          * is therefore NUL), so it gets real easy to detect when things
264          * didn't go the way one might expect.
265          */
266         if (serv[0] == '\0') {
267             BIO_snprintf(serv, sizeof(serv), "%d",
268                          ntohs(BIO_ADDR_rawport(ap)));
269         }
270 
271         if (hostname != NULL)
272             *hostname = OPENSSL_strdup(host);
273         if (service != NULL)
274             *service = OPENSSL_strdup(serv);
275     } else {
276 #endif
277         if (hostname != NULL)
278             *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
279         if (service != NULL) {
280             char serv[6];        /* port is 16 bits => max 5 decimal digits */
281             BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
282             *service = OPENSSL_strdup(serv);
283         }
284     }
285 
286     if ((hostname != NULL && *hostname == NULL)
287             || (service != NULL && *service == NULL)) {
288         if (hostname != NULL) {
289             OPENSSL_free(*hostname);
290             *hostname = NULL;
291         }
292         if (service != NULL) {
293             OPENSSL_free(*service);
294             *service = NULL;
295         }
296         return 0;
297     }
298 
299     return 1;
300 }
301 
BIO_ADDR_hostname_string(const BIO_ADDR * ap,int numeric)302 char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
303 {
304     char *hostname = NULL;
305 
306     if (addr_strings(ap, numeric, &hostname, NULL))
307         return hostname;
308 
309     return NULL;
310 }
311 
BIO_ADDR_service_string(const BIO_ADDR * ap,int numeric)312 char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
313 {
314     char *service = NULL;
315 
316     if (addr_strings(ap, numeric, NULL, &service))
317         return service;
318 
319     return NULL;
320 }
321 
BIO_ADDR_path_string(const BIO_ADDR * ap)322 char *BIO_ADDR_path_string(const BIO_ADDR *ap)
323 {
324 #ifndef OPENSSL_NO_UNIX_SOCK
325     if (ap->sa.sa_family == AF_UNIX)
326         return OPENSSL_strdup(ap->s_un.sun_path);
327 #endif
328     return NULL;
329 }
330 
331 /*
332  * BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
333  * for a given BIO_ADDR.  In reality, this is simply a type safe cast.
334  * The returned struct sockaddr is const, so it can't be tampered with.
335  */
BIO_ADDR_sockaddr(const BIO_ADDR * ap)336 const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
337 {
338     return &(ap->sa);
339 }
340 
341 /*
342  * BIO_ADDR_sockaddr_noconst - non-public function that does the same
343  * as BIO_ADDR_sockaddr, but returns a non-const.  USE WITH CARE, as
344  * it allows you to tamper with the data (and thereby the contents
345  * of the input BIO_ADDR).
346  */
BIO_ADDR_sockaddr_noconst(BIO_ADDR * ap)347 struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
348 {
349     return &(ap->sa);
350 }
351 
352 /*
353  * BIO_ADDR_sockaddr_size - non-public function that returns the size
354  * of the struct sockaddr the BIO_ADDR is using.  If the protocol family
355  * isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
356  * the size of the BIO_ADDR type is returned.
357  */
BIO_ADDR_sockaddr_size(const BIO_ADDR * ap)358 socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
359 {
360     if (ap->sa.sa_family == AF_INET)
361         return sizeof(ap->s_in);
362 #if OPENSSL_USE_IPV6
363     if (ap->sa.sa_family == AF_INET6)
364         return sizeof(ap->s_in6);
365 #endif
366 #ifndef OPENSSL_NO_UNIX_SOCK
367     if (ap->sa.sa_family == AF_UNIX)
368         return sizeof(ap->s_un);
369 #endif
370     return sizeof(*ap);
371 }
372 
373 /**********************************************************************
374  *
375  * Address info database
376  *
377  */
378 
BIO_ADDRINFO_next(const BIO_ADDRINFO * bai)379 const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
380 {
381     if (bai != NULL)
382         return bai->bai_next;
383     return NULL;
384 }
385 
BIO_ADDRINFO_family(const BIO_ADDRINFO * bai)386 int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
387 {
388     if (bai != NULL)
389         return bai->bai_family;
390     return 0;
391 }
392 
BIO_ADDRINFO_socktype(const BIO_ADDRINFO * bai)393 int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
394 {
395     if (bai != NULL)
396         return bai->bai_socktype;
397     return 0;
398 }
399 
BIO_ADDRINFO_protocol(const BIO_ADDRINFO * bai)400 int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
401 {
402     if (bai != NULL) {
403         if (bai->bai_protocol != 0)
404             return bai->bai_protocol;
405 
406 #ifndef OPENSSL_NO_UNIX_SOCK
407         if (bai->bai_family == AF_UNIX)
408             return 0;
409 #endif
410 
411         switch (bai->bai_socktype) {
412         case SOCK_STREAM:
413             return IPPROTO_TCP;
414         case SOCK_DGRAM:
415             return IPPROTO_UDP;
416         default:
417             break;
418         }
419     }
420     return 0;
421 }
422 
423 /*
424  * BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
425  * of the struct sockaddr inside the BIO_ADDRINFO.
426  */
BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO * bai)427 socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
428 {
429     if (bai != NULL)
430         return bai->bai_addrlen;
431     return 0;
432 }
433 
434 /*
435  * BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
436  * as the struct sockaddr it is.
437  */
BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO * bai)438 const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
439 {
440     if (bai != NULL)
441         return bai->bai_addr;
442     return NULL;
443 }
444 
BIO_ADDRINFO_address(const BIO_ADDRINFO * bai)445 const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
446 {
447     if (bai != NULL)
448         return (BIO_ADDR *)bai->bai_addr;
449     return NULL;
450 }
451 
BIO_ADDRINFO_free(BIO_ADDRINFO * bai)452 void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
453 {
454     if (bai == NULL)
455         return;
456 
457 #ifdef AI_PASSIVE
458 # ifndef OPENSSL_NO_UNIX_SOCK
459 #  define _cond bai->bai_family != AF_UNIX
460 # else
461 #  define _cond 1
462 # endif
463     if (_cond) {
464         freeaddrinfo(bai);
465         return;
466     }
467 #endif
468 
469     /* Free manually when we know that addrinfo_wrap() was used.
470      * See further comment above addrinfo_wrap()
471      */
472     while (bai != NULL) {
473         BIO_ADDRINFO *next = bai->bai_next;
474         OPENSSL_free(bai->bai_addr);
475         OPENSSL_free(bai);
476         bai = next;
477     }
478 }
479 
480 /**********************************************************************
481  *
482  * Service functions
483  *
484  */
485 
486 /*-
487  * The specs in hostserv can take these forms:
488  *
489  * host:service         => *host = "host", *service = "service"
490  * host:*               => *host = "host", *service = NULL
491  * host:                => *host = "host", *service = NULL
492  * :service             => *host = NULL, *service = "service"
493  * *:service            => *host = NULL, *service = "service"
494  *
495  * in case no : is present in the string, the result depends on
496  * hostserv_prio, as follows:
497  *
498  * when hostserv_prio == BIO_PARSE_PRIO_HOST
499  * host                 => *host = "host", *service untouched
500  *
501  * when hostserv_prio == BIO_PARSE_PRIO_SERV
502  * service              => *host untouched, *service = "service"
503  *
504  */
BIO_parse_hostserv(const char * hostserv,char ** host,char ** service,enum BIO_hostserv_priorities hostserv_prio)505 int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
506                        enum BIO_hostserv_priorities hostserv_prio)
507 {
508     const char *h = NULL; size_t hl = 0;
509     const char *p = NULL; size_t pl = 0;
510 
511     if (*hostserv == '[') {
512         if ((p = strchr(hostserv, ']')) == NULL)
513             goto spec_err;
514         h = hostserv + 1;
515         hl = p - h;
516         p++;
517         if (*p == '\0')
518             p = NULL;
519         else if (*p != ':')
520             goto spec_err;
521         else {
522             p++;
523             pl = strlen(p);
524         }
525     } else {
526         const char *p2 = strrchr(hostserv, ':');
527         p = strchr(hostserv, ':');
528 
529         /*-
530          * Check for more than one colon.  There are three possible
531          * interpretations:
532          * 1. IPv6 address with port number, last colon being separator.
533          * 2. IPv6 address only.
534          * 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
535          *    IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
536          * Because of this ambiguity, we currently choose to make it an
537          * error.
538          */
539         if (p != p2)
540             goto amb_err;
541 
542         if (p != NULL) {
543             h = hostserv;
544             hl = p - h;
545             p++;
546             pl = strlen(p);
547         } else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
548             h = hostserv;
549             hl = strlen(h);
550         } else {
551             p = hostserv;
552             pl = strlen(p);
553         }
554     }
555 
556     if (p != NULL && strchr(p, ':'))
557         goto spec_err;
558 
559     if (h != NULL && host != NULL) {
560         if (hl == 0
561             || (hl == 1 && h[0] == '*')) {
562             *host = NULL;
563         } else {
564             *host = OPENSSL_strndup(h, hl);
565             if (*host == NULL)
566                 return 0;
567         }
568     }
569     if (p != NULL && service != NULL) {
570         if (pl == 0
571             || (pl == 1 && p[0] == '*')) {
572             *service = NULL;
573         } else {
574             *service = OPENSSL_strndup(p, pl);
575             if (*service == NULL) {
576                 if (h != NULL && host != NULL) {
577                     OPENSSL_free(*host);
578                     *host = NULL;
579                 }
580                 return 0;
581             }
582         }
583     }
584 
585     return 1;
586  amb_err:
587     ERR_raise(ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
588     return 0;
589  spec_err:
590     ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
591     return 0;
592 }
593 
594 /* addrinfo_wrap is used to build our own addrinfo "chain".
595  * (it has only one entry, so calling it a chain may be a stretch)
596  * It should ONLY be called when getaddrinfo() and friends
597  * aren't available, OR when dealing with a non IP protocol
598  * family, such as AF_UNIX
599  *
600  * the return value is 1 on success, or 0 on failure, which
601  * only happens if a memory allocation error occurred.
602  */
addrinfo_wrap(int family,int socktype,const void * where,size_t wherelen,unsigned short port,BIO_ADDRINFO ** bai)603 static int addrinfo_wrap(int family, int socktype,
604                          const void *where, size_t wherelen,
605                          unsigned short port,
606                          BIO_ADDRINFO **bai)
607 {
608     if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL)
609         return 0;
610 
611     (*bai)->bai_family = family;
612     (*bai)->bai_socktype = socktype;
613     if (socktype == SOCK_STREAM)
614         (*bai)->bai_protocol = IPPROTO_TCP;
615     if (socktype == SOCK_DGRAM)
616         (*bai)->bai_protocol = IPPROTO_UDP;
617 #ifndef OPENSSL_NO_UNIX_SOCK
618     if (family == AF_UNIX)
619         (*bai)->bai_protocol = 0;
620 #endif
621     {
622         /* Magic: We know that BIO_ADDR_sockaddr_noconst is really
623            just an advanced cast of BIO_ADDR* to struct sockaddr *
624            by the power of union, so while it may seem that we're
625            creating a memory leak here, we are not.  It will be
626            all right. */
627         BIO_ADDR *addr = BIO_ADDR_new();
628         if (addr != NULL) {
629             BIO_ADDR_rawmake(addr, family, where, wherelen, port);
630             (*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
631         }
632     }
633     (*bai)->bai_next = NULL;
634     if ((*bai)->bai_addr == NULL) {
635         BIO_ADDRINFO_free(*bai);
636         *bai = NULL;
637         return 0;
638     }
639     return 1;
640 }
641 
DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)642 DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
643 {
644     bio_lookup_lock = CRYPTO_THREAD_lock_new();
645     return bio_lookup_lock != NULL;
646 }
647 
BIO_lookup(const char * host,const char * service,enum BIO_lookup_type lookup_type,int family,int socktype,BIO_ADDRINFO ** res)648 int BIO_lookup(const char *host, const char *service,
649                enum BIO_lookup_type lookup_type,
650                int family, int socktype, BIO_ADDRINFO **res)
651 {
652     return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res);
653 }
654 
655 /*-
656  * BIO_lookup_ex - look up the host and service you want to connect to.
657  * @host: the host (or node, in case family == AF_UNIX) you want to connect to.
658  * @service: the service you want to connect to.
659  * @lookup_type: declare intent with the result, client or server.
660  * @family: the address family you want to use.  Use AF_UNSPEC for any, or
661  *  AF_INET, AF_INET6 or AF_UNIX.
662  * @socktype: The socket type you want to use.  Can be SOCK_STREAM, SOCK_DGRAM
663  *  or 0 for all.
664  * @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all.
665  *            Note that some platforms may not return IPPROTO_SCTP without
666  *            explicitly requesting it (i.e. IPPROTO_SCTP may not be returned
667  *            with 0 for the protocol)
668  * @res: Storage place for the resulting list of returned addresses
669  *
670  * This will do a lookup of the host and service that you want to connect to.
671  * It returns a linked list of different addresses you can try to connect to.
672  *
673  * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
674  *
675  * The return value is 1 on success or 0 in case of error.
676  */
BIO_lookup_ex(const char * host,const char * service,int lookup_type,int family,int socktype,int protocol,BIO_ADDRINFO ** res)677 int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
678                   int family, int socktype, int protocol, BIO_ADDRINFO **res)
679 {
680     int ret = 0;                 /* Assume failure */
681 
682     switch (family) {
683     case AF_INET:
684 #if OPENSSL_USE_IPV6
685     case AF_INET6:
686 #endif
687 #ifndef OPENSSL_NO_UNIX_SOCK
688     case AF_UNIX:
689 #endif
690 #ifdef AF_UNSPEC
691     case AF_UNSPEC:
692 #endif
693         break;
694     default:
695         ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
696         return 0;
697     }
698 
699 #ifndef OPENSSL_NO_UNIX_SOCK
700     if (family == AF_UNIX) {
701         if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
702             return 1;
703         else
704             ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
705         return 0;
706     }
707 #endif
708 
709     if (BIO_sock_init() != 1)
710         return 0;
711 
712     if (1) {
713 #ifdef AI_PASSIVE
714         int gai_ret = 0, old_ret = 0;
715         struct addrinfo hints;
716 
717         memset(&hints, 0, sizeof(hints));
718 
719         hints.ai_family = family;
720         hints.ai_socktype = socktype;
721         hints.ai_protocol = protocol;
722 # ifdef AI_ADDRCONFIG
723 #  ifdef AF_UNSPEC
724         if (host != NULL && family == AF_UNSPEC)
725 #  endif
726             hints.ai_flags |= AI_ADDRCONFIG;
727 # endif
728 
729         if (lookup_type == BIO_LOOKUP_SERVER)
730             hints.ai_flags |= AI_PASSIVE;
731 
732         /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
733          * macro magic in bio_local.h
734          */
735 # if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
736       retry:
737 # endif
738         switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
739 # ifdef EAI_SYSTEM
740         case EAI_SYSTEM:
741             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
742                            "calling getaddrinfo()");
743             ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB);
744             break;
745 # endif
746 # ifdef EAI_MEMORY
747         case EAI_MEMORY:
748             ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
749                            gai_strerror(old_ret ? old_ret : gai_ret));
750             break;
751 # endif
752         case 0:
753             ret = 1;             /* Success */
754             break;
755         default:
756 # if defined(AI_ADDRCONFIG) && defined(AI_NUMERICHOST)
757             if (hints.ai_flags & AI_ADDRCONFIG) {
758                 hints.ai_flags &= ~AI_ADDRCONFIG;
759                 hints.ai_flags |= AI_NUMERICHOST;
760                 old_ret = gai_ret;
761                 goto retry;
762             }
763 # endif
764             ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB,
765                            gai_strerror(old_ret ? old_ret : gai_ret));
766             break;
767         }
768     } else {
769 #endif
770         const struct hostent *he;
771 /*
772  * Because struct hostent is defined for 32-bit pointers only with
773  * VMS C, we need to make sure that '&he_fallback_address' and
774  * '&he_fallback_addresses' are 32-bit pointers
775  */
776 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
777 # pragma pointer_size save
778 # pragma pointer_size 32
779 #endif
780         /* Windows doesn't seem to have in_addr_t */
781 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
782         static uint32_t he_fallback_address;
783         static const char *he_fallback_addresses[] = {
784             (char *)&he_fallback_address, NULL
785         };
786 #else
787         static in_addr_t he_fallback_address;
788         static const char *he_fallback_addresses[] = {
789             (char *)&he_fallback_address, NULL
790         };
791 #endif
792         static const struct hostent he_fallback = {
793             NULL, NULL, AF_INET, sizeof(he_fallback_address),
794             (char **)&he_fallback_addresses
795         };
796 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
797 # pragma pointer_size restore
798 #endif
799 
800         struct servent *se;
801         /* Apparently, on WIN64, s_proto and s_port have traded places... */
802 #ifdef _WIN64
803         struct servent se_fallback = { NULL, NULL, NULL, 0 };
804 #else
805         struct servent se_fallback = { NULL, NULL, 0, NULL };
806 #endif
807 
808         if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
809             /* Should this be raised inside do_bio_lookup_init()? */
810             ERR_raise(ERR_LIB_BIO, ERR_R_CRYPTO_LIB);
811             return 0;
812         }
813 
814         if (!CRYPTO_THREAD_write_lock(bio_lookup_lock))
815             return 0;
816 
817         he_fallback_address = INADDR_ANY;
818         if (host == NULL) {
819             he = &he_fallback;
820             switch (lookup_type) {
821             case BIO_LOOKUP_CLIENT:
822                 he_fallback_address = INADDR_LOOPBACK;
823                 break;
824             case BIO_LOOKUP_SERVER:
825                 he_fallback_address = INADDR_ANY;
826                 break;
827             default:
828                 /* We forgot to handle a lookup type! */
829                 assert("We forgot to handle a lookup type!" == NULL);
830                 ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR);
831                 ret = 0;
832                 goto err;
833             }
834         } else {
835             he = gethostbyname(host);
836 
837             if (he == NULL) {
838 #ifndef OPENSSL_SYS_WINDOWS
839                 /*
840                  * This might be misleading, because h_errno is used as if
841                  * it was errno. To minimize mixup add 1000. Underlying
842                  * reason for this is that hstrerror is declared obsolete,
843                  * not to mention that a) h_errno is not always guaranteed
844                  * to be meaningless; b) hstrerror can reside in yet another
845                  * library, linking for sake of hstrerror is an overkill;
846                  * c) this path is not executed on contemporary systems
847                  * anyway [above getaddrinfo/gai_strerror is]. We just let
848                  * system administrator figure this out...
849                  */
850 # if defined(OPENSSL_SYS_VXWORKS)
851                 /* h_errno doesn't exist on VxWorks */
852                 ERR_raise_data(ERR_LIB_SYS, 1000,
853                                "calling gethostbyname()");
854 # else
855                 ERR_raise_data(ERR_LIB_SYS, 1000 + h_errno,
856                                "calling gethostbyname()");
857 # endif
858 #else
859                 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
860                                "calling gethostbyname()");
861 #endif
862                 ret = 0;
863                 goto err;
864             }
865         }
866 
867         if (service == NULL) {
868             se_fallback.s_port = 0;
869             se_fallback.s_proto = NULL;
870             se = &se_fallback;
871         } else {
872             char *endp = NULL;
873             long portnum = strtol(service, &endp, 10);
874 
875 /*
876  * Because struct servent is defined for 32-bit pointers only with
877  * VMS C, we need to make sure that 'proto' is a 32-bit pointer.
878  */
879 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
880 # pragma pointer_size save
881 # pragma pointer_size 32
882 #endif
883             char *proto = NULL;
884 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
885 # pragma pointer_size restore
886 #endif
887 
888             switch (socktype) {
889             case SOCK_STREAM:
890                 proto = "tcp";
891                 break;
892             case SOCK_DGRAM:
893                 proto = "udp";
894                 break;
895             }
896 
897             if (endp != service && *endp == '\0'
898                     && portnum > 0 && portnum < 65536) {
899                 se_fallback.s_port = htons((unsigned short)portnum);
900                 se_fallback.s_proto = proto;
901                 se = &se_fallback;
902             } else if (endp == service) {
903                 se = getservbyname(service, proto);
904 
905                 if (se == NULL) {
906                     ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
907                                    "calling getservbyname()");
908                     goto err;
909                 }
910             } else {
911                 ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE);
912                 goto err;
913             }
914         }
915 
916         *res = NULL;
917 
918         {
919 /*
920  * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
921  * we must make sure our iterator designates the same element type, hence
922  * the pointer size dance.
923  */
924 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
925 # pragma pointer_size save
926 # pragma pointer_size 32
927 #endif
928             char **addrlistp;
929 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
930 # pragma pointer_size restore
931 #endif
932             size_t addresses;
933             BIO_ADDRINFO *tmp_bai = NULL;
934 
935             /* The easiest way to create a linked list from an
936                array is to start from the back */
937             for (addrlistp = he->h_addr_list; *addrlistp != NULL;
938                  addrlistp++)
939                 ;
940 
941             for (addresses = addrlistp - he->h_addr_list;
942                  addrlistp--, addresses-- > 0; ) {
943                 if (!addrinfo_wrap(he->h_addrtype, socktype,
944                                    *addrlistp, he->h_length,
945                                    se->s_port, &tmp_bai))
946                     goto addrinfo_wrap_err;
947                 tmp_bai->bai_next = *res;
948                 *res = tmp_bai;
949                 continue;
950              addrinfo_wrap_err:
951                 BIO_ADDRINFO_free(*res);
952                 *res = NULL;
953                 ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
954                 ret = 0;
955                 goto err;
956             }
957 
958             ret = 1;
959         }
960      err:
961         CRYPTO_THREAD_unlock(bio_lookup_lock);
962     }
963 
964     return ret;
965 }
966 
967 #endif /* OPENSSL_NO_SOCK */
968