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) |
