diff options
Diffstat (limited to 'src/lib/libssl/src/crypto/bio/b_sock.c')
-rw-r--r-- | src/lib/libssl/src/crypto/bio/b_sock.c | 242 |
1 files changed, 202 insertions, 40 deletions
diff --git a/src/lib/libssl/src/crypto/bio/b_sock.c b/src/lib/libssl/src/crypto/bio/b_sock.c index ead477d8a2..12b0a53a81 100644 --- a/src/lib/libssl/src/crypto/bio/b_sock.c +++ b/src/lib/libssl/src/crypto/bio/b_sock.c | |||
@@ -72,11 +72,9 @@ NETDB_DEFINE_CONTEXT | |||
72 | 72 | ||
73 | #ifndef OPENSSL_NO_SOCK | 73 | #ifndef OPENSSL_NO_SOCK |
74 | 74 | ||
75 | #ifdef OPENSSL_SYS_WIN16 | 75 | #include <openssl/dso.h> |
76 | #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ | 76 | |
77 | #else | ||
78 | #define SOCKET_PROTOCOL IPPROTO_TCP | 77 | #define SOCKET_PROTOCOL IPPROTO_TCP |
79 | #endif | ||
80 | 78 | ||
81 | #ifdef SO_MAXCONN | 79 | #ifdef SO_MAXCONN |
82 | #define MAX_LISTEN SO_MAXCONN | 80 | #define MAX_LISTEN SO_MAXCONN |
@@ -90,6 +88,17 @@ NETDB_DEFINE_CONTEXT | |||
90 | static int wsa_init_done=0; | 88 | static int wsa_init_done=0; |
91 | #endif | 89 | #endif |
92 | 90 | ||
91 | /* | ||
92 | * WSAAPI specifier is required to make indirect calls to run-time | ||
93 | * linked WinSock 2 functions used in this module, to be specific | ||
94 | * [get|free]addrinfo and getnameinfo. This is because WinSock uses | ||
95 | * uses non-C calling convention, __stdcall vs. __cdecl, on x86 | ||
96 | * Windows. On non-WinSock platforms WSAAPI needs to be void. | ||
97 | */ | ||
98 | #ifndef WSAAPI | ||
99 | #define WSAAPI | ||
100 | #endif | ||
101 | |||
93 | #if 0 | 102 | #if 0 |
94 | static unsigned long BIO_ghbn_hits=0L; | 103 | static unsigned long BIO_ghbn_hits=0L; |
95 | static unsigned long BIO_ghbn_miss=0L; | 104 | static unsigned long BIO_ghbn_miss=0L; |
@@ -226,6 +235,10 @@ int BIO_sock_error(int sock) | |||
226 | int j,i; | 235 | int j,i; |
227 | int size; | 236 | int size; |
228 | 237 | ||
238 | #if defined(OPENSSL_SYS_BEOS_R5) | ||
239 | return 0; | ||
240 | #endif | ||
241 | |||
229 | size=sizeof(int); | 242 | size=sizeof(int); |
230 | /* Note: under Windows the third parameter is of type (char *) | 243 | /* Note: under Windows the third parameter is of type (char *) |
231 | * whereas under other systems it is (void *) if you don't have | 244 | * whereas under other systems it is (void *) if you don't have |
@@ -466,7 +479,12 @@ int BIO_sock_init(void) | |||
466 | 479 | ||
467 | wsa_init_done=1; | 480 | wsa_init_done=1; |
468 | memset(&wsa_state,0,sizeof(wsa_state)); | 481 | memset(&wsa_state,0,sizeof(wsa_state)); |
469 | if (WSAStartup(0x0101,&wsa_state)!=0) | 482 | /* Not making wsa_state available to the rest of the |
483 | * code is formally wrong. But the structures we use | ||
484 | * are [beleived to be] invariable among Winsock DLLs, | ||
485 | * while API availability is [expected to be] probed | ||
486 | * at run-time with DSO_global_lookup. */ | ||
487 | if (WSAStartup(0x0202,&wsa_state)!=0) | ||
470 | { | 488 | { |
471 | err=WSAGetLastError(); | 489 | err=WSAGetLastError(); |
472 | SYSerr(SYS_F_WSASTARTUP,err); | 490 | SYSerr(SYS_F_WSASTARTUP,err); |
@@ -510,8 +528,8 @@ void BIO_sock_cleanup(void) | |||
510 | if (wsa_init_done) | 528 | if (wsa_init_done) |
511 | { | 529 | { |
512 | wsa_init_done=0; | 530 | wsa_init_done=0; |
513 | #ifndef OPENSSL_SYS_WINCE | 531 | #if 0 /* this call is claimed to be non-present in Winsock2 */ |
514 | WSACancelBlockingCall(); /* Winsock 1.1 specific */ | 532 | WSACancelBlockingCall(); |
515 | #endif | 533 | #endif |
516 | WSACleanup(); | 534 | WSACleanup(); |
517 | } | 535 | } |
@@ -581,12 +599,18 @@ static int get_ip(const char *str, unsigned char ip[4]) | |||
581 | int BIO_get_accept_socket(char *host, int bind_mode) | 599 | int BIO_get_accept_socket(char *host, int bind_mode) |
582 | { | 600 | { |
583 | int ret=0; | 601 | int ret=0; |
584 | struct sockaddr_in server,client; | 602 | union { |
585 | int s=INVALID_SOCKET,cs; | 603 | struct sockaddr sa; |
604 | struct sockaddr_in sa_in; | ||
605 | #if OPENSSL_USE_IPV6 | ||
606 | struct sockaddr_in6 sa_in6; | ||
607 | #endif | ||
608 | } server,client; | ||
609 | int s=INVALID_SOCKET,cs,addrlen; | ||
586 | unsigned char ip[4]; | 610 | unsigned char ip[4]; |
587 | unsigned short port; | 611 | unsigned short port; |
588 | char *str=NULL,*e; | 612 | char *str=NULL,*e; |
589 | const char *h,*p; | 613 | char *h,*p; |
590 | unsigned long l; | 614 | unsigned long l; |
591 | int err_num; | 615 | int err_num; |
592 | 616 | ||
@@ -600,8 +624,7 @@ int BIO_get_accept_socket(char *host, int bind_mode) | |||
600 | { | 624 | { |
601 | if (*e == ':') | 625 | if (*e == ':') |
602 | { | 626 | { |
603 | p= &(e[1]); | 627 | p=e; |
604 | *e='\0'; | ||
605 | } | 628 | } |
606 | else if (*e == '/') | 629 | else if (*e == '/') |
607 | { | 630 | { |
@@ -609,21 +632,70 @@ int BIO_get_accept_socket(char *host, int bind_mode) | |||
609 | break; | 632 | break; |
610 | } | 633 | } |
611 | } | 634 | } |
612 | 635 | if (p) *p++='\0'; /* points at last ':', '::port' is special [see below] */ | |
613 | if (p == NULL) | 636 | else p=h,h=NULL; |
637 | |||
638 | #ifdef EAI_FAMILY | ||
639 | do { | ||
640 | static union { void *p; | ||
641 | int (WSAAPI *f)(const char *,const char *, | ||
642 | const struct addrinfo *, | ||
643 | struct addrinfo **); | ||
644 | } p_getaddrinfo = {NULL}; | ||
645 | static union { void *p; | ||
646 | void (WSAAPI *f)(struct addrinfo *); | ||
647 | } p_freeaddrinfo = {NULL}; | ||
648 | struct addrinfo *res,hint; | ||
649 | |||
650 | if (p_getaddrinfo.p==NULL) | ||
651 | { | ||
652 | if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL || | ||
653 | (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL) | ||
654 | p_getaddrinfo.p=(void*)-1; | ||
655 | } | ||
656 | if (p_getaddrinfo.p==(void *)-1) break; | ||
657 | |||
658 | /* '::port' enforces IPv6 wildcard listener. Some OSes, | ||
659 | * e.g. Solaris, default to IPv6 without any hint. Also | ||
660 | * note that commonly IPv6 wildchard socket can service | ||
661 | * IPv4 connections just as well... */ | ||
662 | memset(&hint,0,sizeof(hint)); | ||
663 | if (h) | ||
614 | { | 664 | { |
615 | p=h; | 665 | if (strchr(h,':')) |
616 | h="*"; | 666 | { |
667 | if (h[1]=='\0') h=NULL; | ||
668 | #if OPENSSL_USE_IPV6 | ||
669 | hint.ai_family = AF_INET6; | ||
670 | #else | ||
671 | h=NULL; | ||
672 | #endif | ||
673 | } | ||
674 | else if (h[0]=='*' && h[1]=='\0') | ||
675 | h=NULL; | ||
617 | } | 676 | } |
618 | 677 | ||
678 | if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break; | ||
679 | |||
680 | addrlen = res->ai_addrlen<=sizeof(server) ? | ||
681 | res->ai_addrlen : | ||
682 | sizeof(server); | ||
683 | memcpy(&server, res->ai_addr, addrlen); | ||
684 | |||
685 | (*p_freeaddrinfo.f)(res); | ||
686 | goto again; | ||
687 | } while (0); | ||
688 | #endif | ||
689 | |||
619 | if (!BIO_get_port(p,&port)) goto err; | 690 | if (!BIO_get_port(p,&port)) goto err; |
620 | 691 | ||
621 | memset((char *)&server,0,sizeof(server)); | 692 | memset((char *)&server,0,sizeof(server)); |
622 | server.sin_family=AF_INET; | 693 | server.sa_in.sin_family=AF_INET; |
623 | server.sin_port=htons(port); | 694 | server.sa_in.sin_port=htons(port); |
695 | addrlen = sizeof(server.sa_in); | ||
624 | 696 | ||
625 | if (strcmp(h,"*") == 0) | 697 | if (h == NULL || strcmp(h,"*") == 0) |
626 | server.sin_addr.s_addr=INADDR_ANY; | 698 | server.sa_in.sin_addr.s_addr=INADDR_ANY; |
627 | else | 699 | else |
628 | { | 700 | { |
629 | if (!BIO_get_host_ip(h,&(ip[0]))) goto err; | 701 | if (!BIO_get_host_ip(h,&(ip[0]))) goto err; |
@@ -632,11 +704,11 @@ int BIO_get_accept_socket(char *host, int bind_mode) | |||
632 | ((unsigned long)ip[1]<<16L)| | 704 | ((unsigned long)ip[1]<<16L)| |
633 | ((unsigned long)ip[2]<< 8L)| | 705 | ((unsigned long)ip[2]<< 8L)| |
634 | ((unsigned long)ip[3]); | 706 | ((unsigned long)ip[3]); |
635 | server.sin_addr.s_addr=htonl(l); | 707 | server.sa_in.sin_addr.s_addr=htonl(l); |
636 | } | 708 | } |
637 | 709 | ||
638 | again: | 710 | again: |
639 | s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | 711 | s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL); |
640 | if (s == INVALID_SOCKET) | 712 | if (s == INVALID_SOCKET) |
641 | { | 713 | { |
642 | SYSerr(SYS_F_SOCKET,get_last_socket_error()); | 714 | SYSerr(SYS_F_SOCKET,get_last_socket_error()); |
@@ -654,22 +726,42 @@ again: | |||
654 | bind_mode=BIO_BIND_NORMAL; | 726 | bind_mode=BIO_BIND_NORMAL; |
655 | } | 727 | } |
656 | #endif | 728 | #endif |
657 | if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) | 729 | if (bind(s,&server.sa,addrlen) == -1) |
658 | { | 730 | { |
659 | #ifdef SO_REUSEADDR | 731 | #ifdef SO_REUSEADDR |
660 | err_num=get_last_socket_error(); | 732 | err_num=get_last_socket_error(); |
661 | if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && | 733 | if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && |
734 | #ifdef OPENSSL_SYS_WINDOWS | ||
735 | /* Some versions of Windows define EADDRINUSE to | ||
736 | * a dummy value. | ||
737 | */ | ||
738 | (err_num == WSAEADDRINUSE)) | ||
739 | #else | ||
662 | (err_num == EADDRINUSE)) | 740 | (err_num == EADDRINUSE)) |
741 | #endif | ||
663 | { | 742 | { |
664 | memcpy((char *)&client,(char *)&server,sizeof(server)); | 743 | client = server; |
665 | if (strcmp(h,"*") == 0) | 744 | if (h == NULL || strcmp(h,"*") == 0) |
666 | client.sin_addr.s_addr=htonl(0x7F000001); | 745 | { |
667 | cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); | 746 | #if OPENSSL_USE_IPV6 |
747 | if (client.sa.sa_family == AF_INET6) | ||
748 | { | ||
749 | memset(&client.sa_in6.sin6_addr,0,sizeof(client.sa_in6.sin6_addr)); | ||
750 | client.sa_in6.sin6_addr.s6_addr[15]=1; | ||
751 | } | ||
752 | else | ||
753 | #endif | ||
754 | if (client.sa.sa_family == AF_INET) | ||
755 | { | ||
756 | client.sa_in.sin_addr.s_addr=htonl(0x7F000001); | ||
757 | } | ||
758 | else goto err; | ||
759 | } | ||
760 | cs=socket(client.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL); | ||
668 | if (cs != INVALID_SOCKET) | 761 | if (cs != INVALID_SOCKET) |
669 | { | 762 | { |
670 | int ii; | 763 | int ii; |
671 | ii=connect(cs,(struct sockaddr *)&client, | 764 | ii=connect(cs,&client.sa,addrlen); |
672 | sizeof(client)); | ||
673 | closesocket(cs); | 765 | closesocket(cs); |
674 | if (ii == INVALID_SOCKET) | 766 | if (ii == INVALID_SOCKET) |
675 | { | 767 | { |
@@ -708,20 +800,52 @@ err: | |||
708 | int BIO_accept(int sock, char **addr) | 800 | int BIO_accept(int sock, char **addr) |
709 | { | 801 | { |
710 | int ret=INVALID_SOCKET; | 802 | int ret=INVALID_SOCKET; |
711 | static struct sockaddr_in from; | ||
712 | unsigned long l; | 803 | unsigned long l; |
713 | unsigned short port; | 804 | unsigned short port; |
714 | int len; | ||
715 | char *p; | 805 | char *p; |
716 | 806 | ||
717 | memset((char *)&from,0,sizeof(from)); | 807 | struct { |
718 | len=sizeof(from); | 808 | /* |
719 | /* Note: under VMS with SOCKETSHR the fourth parameter is currently | 809 | * As for following union. Trouble is that there are platforms |
720 | * of type (int *) whereas under other systems it is (void *) if | 810 | * that have socklen_t and there are platforms that don't, on |
721 | * you don't have a cast it will choke the compiler: if you do | 811 | * some platforms socklen_t is int and on some size_t. So what |
722 | * have a cast then you can either go for (int *) or (void *). | 812 | * one can do? One can cook #ifdef spaghetti, which is nothing |
813 | * but masochistic. Or one can do union between int and size_t. | ||
814 | * One naturally does it primarily for 64-bit platforms where | ||
815 | * sizeof(int) != sizeof(size_t). But would it work? Note that | ||
816 | * if size_t member is initialized to 0, then later int member | ||
817 | * assignment naturally does the job on little-endian platforms | ||
818 | * regardless accept's expectations! What about big-endians? | ||
819 | * If accept expects int*, then it works, and if size_t*, then | ||
820 | * length value would appear as unreasonably large. But this | ||
821 | * won't prevent it from filling in the address structure. The | ||
822 | * trouble of course would be if accept returns more data than | ||
823 | * actual buffer can accomodate and overwrite stack... That's | ||
824 | * where early OPENSSL_assert comes into picture. Besides, the | ||
825 | * only 64-bit big-endian platform found so far that expects | ||
826 | * size_t* is HP-UX, where stack grows towards higher address. | ||
827 | * <appro> | ||
723 | */ | 828 | */ |
724 | ret=accept(sock,(struct sockaddr *)&from,(void *)&len); | 829 | union { size_t s; int i; } len; |
830 | union { | ||
831 | struct sockaddr sa; | ||
832 | struct sockaddr_in sa_in; | ||
833 | #if OPENSSL_USE_IPV6 | ||
834 | struct sockaddr_in6 sa_in6; | ||
835 | #endif | ||
836 | } from; | ||
837 | } sa; | ||
838 | |||
839 | sa.len.s=0; | ||
840 | sa.len.i=sizeof(sa.from); | ||
841 | memset(&sa.from,0,sizeof(sa.from)); | ||
842 | ret=accept(sock,&sa.from.sa,(void *)&sa.len); | ||
843 | if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) | ||
844 | { | ||
845 | OPENSSL_assert(sa.len.s<=sizeof(sa.from)); | ||
846 | sa.len.i = (int)sa.len.s; | ||
847 | /* use sa.len.i from this point */ | ||
848 | } | ||
725 | if (ret == INVALID_SOCKET) | 849 | if (ret == INVALID_SOCKET) |
726 | { | 850 | { |
727 | if(BIO_sock_should_retry(ret)) return -2; | 851 | if(BIO_sock_should_retry(ret)) return -2; |
@@ -732,8 +856,46 @@ int BIO_accept(int sock, char **addr) | |||
732 | 856 | ||
733 | if (addr == NULL) goto end; | 857 | if (addr == NULL) goto end; |
734 | 858 | ||
735 | l=ntohl(from.sin_addr.s_addr); | 859 | #ifdef EAI_FAMILY |
736 | port=ntohs(from.sin_port); | 860 | do { |
861 | char h[NI_MAXHOST],s[NI_MAXSERV]; | ||
862 | size_t nl; | ||
863 | static union { void *p; | ||
864 | int (WSAAPI *f)(const struct sockaddr *,size_t/*socklen_t*/, | ||
865 | char *,size_t,char *,size_t,int); | ||
866 | } p_getnameinfo = {NULL}; | ||
867 | /* 2nd argument to getnameinfo is specified to | ||
868 | * be socklen_t. Unfortunately there is a number | ||
869 | * of environments where socklen_t is not defined. | ||
870 | * As it's passed by value, it's safe to pass it | ||
871 | * as size_t... <appro> */ | ||
872 | |||
873 | if (p_getnameinfo.p==NULL) | ||
874 | { | ||
875 | if ((p_getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL) | ||
876 | p_getnameinfo.p=(void*)-1; | ||
877 | } | ||
878 | if (p_getnameinfo.p==(void *)-1) break; | ||
879 | |||
880 | if ((*p_getnameinfo.f)(&sa.from.sa,sa.len.i,h,sizeof(h),s,sizeof(s), | ||
881 | NI_NUMERICHOST|NI_NUMERICSERV)) break; | ||
882 | nl = strlen(h)+strlen(s)+2; | ||
883 | p = *addr; | ||
884 | if (p) { *p = '\0'; p = OPENSSL_realloc(p,nl); } | ||
885 | else { p = OPENSSL_malloc(nl); } | ||
886 | if (p==NULL) | ||
887 | { | ||
888 | BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); | ||
889 | goto end; | ||
890 | } | ||
891 | *addr = p; | ||
892 | BIO_snprintf(*addr,nl,"%s:%s",h,s); | ||
893 | goto end; | ||
894 | } while(0); | ||
895 | #endif | ||
896 | if (sa.from.sa.sa_family != AF_INET) goto end; | ||
897 | l=ntohl(sa.from.sa_in.sin_addr.s_addr); | ||
898 | port=ntohs(sa.from.sa_in.sin_port); | ||
737 | if (*addr == NULL) | 899 | if (*addr == NULL) |
738 | { | 900 | { |
739 | if ((p=OPENSSL_malloc(24)) == NULL) | 901 | if ((p=OPENSSL_malloc(24)) == NULL) |