X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_socket.c;h=e83baf4e709279dee9a452c990fa276eadb073a7;hp=45c293905280284c1376580fcd2f9f8fb77f4e9a;hb=6b5c1d940b5a653a24b91d3c52bca935399b713c;hpb=d58d092bc9f0a541ce5f0b265ee819f7ab086560 diff --git a/apps/s_socket.c b/apps/s_socket.c index 45c2939052..e83baf4e70 100644 --- a/apps/s_socket.c +++ b/apps/s_socket.c @@ -1,4 +1,4 @@ -/* apps/s_socket.c */ +/* apps/s_socket.c - socket-related functions used by s_client and s_server */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,20 +56,21 @@ * [including the GNU Public Licence.] */ +#include +#include +#include +#include +#include + /* With IPv6, it looks like Digital has mixed up the proper order of recursive header file inclusion, resulting in the compiler complaining that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is needed to have fileno() declared correctly... So let's define u_int */ -#if defined(VMS) && defined(__DECC) && !defined(__U_INT) +#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) #define __U_INT typedef unsigned int u_int; #endif -#include -#include -#include -#include -#include #define USE_SOCKETS #define NON_MAIN #include "apps.h" @@ -78,27 +79,49 @@ typedef unsigned int u_int; #include "s_apps.h" #include -#ifdef VMS -#if (__VMS_VER < 70000000) /* FIONBIO used as a switch to enable ioctl, - and that isn't in VMS < 7.0 */ -#undef FIONBIO +#ifdef FLAT_INC +#include "e_os.h" +#else +#include "../e_os.h" +#endif + +#ifndef OPENSSL_NO_SOCK + +#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) +#include "netdb.h" #endif -#include /* for vfork() */ + +static struct hostent *GetHostByName(const char *name); +#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) +static void ssl_sock_cleanup(void); +#endif +static int ssl_sock_init(void); +static int init_client_ip(int *sock, const unsigned char ip[4], int port, + int type); +static int init_server(int *sock, int port, int type); +static int init_server_long(int *sock, int port,char *ip, int type); +static int do_accept(int acc_sock, int *sock, char **host); +static int host_ip(const char *str, unsigned char ip[4]); +#ifndef NO_SYS_UN_H +static int init_server_unix(int *sock, const char *path); +static int do_accept_unix(int acc_sock, int *sock); #endif -static struct hostent *GetHostByName(char *name); -int sock_init(void ); -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ #else #define SOCKET_PROTOCOL IPPROTO_TCP #endif -#ifdef WINDOWS +#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) +static int wsa_init_done=0; +#endif + +#ifdef OPENSSL_SYS_WINDOWS static struct WSAData wsa_state; static int wsa_init_done=0; -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 static HWND topWnd=0; static FARPROC lpTopWndProc=NULL; static FARPROC lpTopHookProc=NULL; @@ -114,7 +137,7 @@ static LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam, case WM_DESTROY: case WM_CLOSE: SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc); - sock_cleanup(); + ssl_sock_cleanup(); break; } } @@ -127,30 +150,46 @@ static BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam) return(FALSE); } -#endif /* WIN32 */ -#endif /* WINDOWS */ +#endif /* OPENSSL_SYS_WIN32 */ +#endif /* OPENSSL_SYS_WINDOWS */ -void sock_cleanup(void) +#ifdef OPENSSL_SYS_WINDOWS +static void ssl_sock_cleanup(void) { -#ifdef WINDOWS if (wsa_init_done) { wsa_init_done=0; +#ifndef OPENSSL_SYS_WINCE WSACancelBlockingCall(); +#endif + WSACleanup(); + } + } +#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) +static void sock_cleanup(void) + { + if (wsa_init_done) + { + wsa_init_done=0; WSACleanup(); } -#endif } +#endif -int sock_init(void) +static int ssl_sock_init(void) { -#ifdef WINDOWS +#ifdef WATT32 + extern int _watt_do_exit; + _watt_do_exit = 0; + if (sock_init()) + return (0); +#elif defined(OPENSSL_SYS_WINDOWS) if (!wsa_init_done) { int err; #ifdef SIGINT - signal(SIGINT,(void (*)(int))sock_cleanup); + signal(SIGINT,(void (*)(int))ssl_sock_cleanup); #endif wsa_init_done=1; memset(&wsa_state,0,sizeof(wsa_state)); @@ -161,38 +200,57 @@ int sock_init(void) return(0); } -#ifdef WIN16 +#ifdef OPENSSL_SYS_WIN16 EnumTaskWindows(GetCurrentTask(),enumproc,0L); lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC); lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance); SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc); -#endif /* WIN16 */ +#endif /* OPENSSL_SYS_WIN16 */ } -#endif /* WINDOWS */ +#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) + WORD wVerReq; + WSADATA wsaData; + int err; + + if (!wsa_init_done) + { + +# ifdef SIGINT + signal(SIGINT,(void (*)(int))sock_cleanup); +# endif + + wsa_init_done=1; + wVerReq = MAKEWORD( 2, 0 ); + err = WSAStartup(wVerReq,&wsaData); + if (err != 0) + { + BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err); + return(0); + } + } +#endif /* OPENSSL_SYS_WINDOWS */ return(1); } -int init_client(int *sock, char *host, int port) +int init_client(int *sock, const char *host, int port, int type) { unsigned char ip[4]; - short p=0; + ip[0] = ip[1] = ip[2] = ip[3] = 0; if (!host_ip(host,&(ip[0]))) - { - return(0); - } - if (p != 0) port=p; - return(init_client_ip(sock,ip,port)); + return 0; + return init_client_ip(sock,ip,port,type); } -int init_client_ip(int *sock, unsigned char ip[4], int port) +static int init_client_ip(int *sock, const unsigned char ip[4], int port, + int type) { unsigned long addr; struct sockaddr_in them; int s,i; - if (!sock_init()) return(0); + if (!ssl_sock_init()) return(0); memset((char *)&them,0,sizeof(them)); them.sin_family=AF_INET; @@ -204,127 +262,141 @@ int init_client_ip(int *sock, unsigned char ip[4], int port) ((unsigned long)ip[3]); them.sin_addr.s_addr=htonl(addr); - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + if (type == SOCK_STREAM) + s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + else /* ( type == SOCK_DGRAM) */ + s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + if (s == INVALID_SOCKET) { perror("socket"); return(0); } - i=0; - i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); - if (i < 0) { perror("keepalive"); return(0); } +#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) + if (type == SOCK_STREAM) + { + i=0; + i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); + if (i < 0) { closesocket(s); perror("keepalive"); return(0); } + } +#endif if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1) - { close(s); perror("connect"); return(0); } + { closesocket(s); perror("connect"); return(0); } *sock=s; return(1); } -int nbio_sock_error(int sock) +#ifndef NO_SYS_UN_H +int init_client_unix(int *sock, const char *server) { - int j,i; - int size; + struct sockaddr_un them; + int s; - size=sizeof(int); - /* Note: under VMS with SOCKETSHR the third parameter is currently - * of type (int *) whereas under other systems it is (void *) if - * you don't have a cast it will choke the compiler: if you do - * have a cast then you can either go for (int *) or (void *). - */ - i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,(void *)&size); - if (i < 0) - return(1); - else - return(j); - } - -int nbio_init_client_ip(int *sock, unsigned char ip[4], int port) - { - unsigned long addr; - struct sockaddr_in them; - int s,i; + if (strlen(server) > (UNIX_PATH_MAX + 1)) return(0); + if (!ssl_sock_init()) return(0); - if (!sock_init()) return(0); + s=socket(AF_UNIX, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { perror("socket"); return(0); } memset((char *)&them,0,sizeof(them)); - them.sin_family=AF_INET; - them.sin_port=htons((unsigned short)port); - addr= (unsigned long) - ((unsigned long)ip[0]<<24L)| - ((unsigned long)ip[1]<<16L)| - ((unsigned long)ip[2]<< 8L)| - ((unsigned long)ip[3]); - them.sin_addr.s_addr=htonl(addr); + them.sun_family=AF_UNIX; + strcpy(them.sun_path, server); - if (*sock <= 0) - { -#ifdef FIONBIO - unsigned long l=1; + if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) + { closesocket(s); perror("connect"); return(0); } + *sock=s; + return(1); + } #endif - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); - if (s == INVALID_SOCKET) { perror("socket"); return(0); } - - i=0; - i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); - if (i < 0) { perror("keepalive"); return(0); } - *sock=s; +int do_server(int port, int type, int *ret, + int (*cb)(char *hostname, int s, int stype, unsigned char *context), + unsigned char *context, int naccept) + { + int sock; + char *name = NULL; + int accept_socket = 0; + int i; -#ifdef FIONBIO - BIO_socket_ioctl(s,FIONBIO,&l); -#endif - } - else - s= *sock; + if (!init_server(&accept_socket,port,type)) return(0); - i=connect(s,(struct sockaddr *)&them,sizeof(them)); - if (i == INVALID_SOCKET) + if (ret != NULL) { - if (BIO_sock_should_retry(i)) - return(-1); + *ret=accept_socket; + /* return(1);*/ + } + for (;;) + { + if (type==SOCK_STREAM) + { +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (do_accept(accept_socket,&sock,NULL) == 0) +#else + if (do_accept(accept_socket,&sock,&name) == 0) +#endif + { + SHUTDOWN(accept_socket); + return(0); + } + } else - return(0); + sock = accept_socket; + i=(*cb)(name,sock, type, context); + if (name != NULL) OPENSSL_free(name); + if (type==SOCK_STREAM) + SHUTDOWN2(sock); + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) + { + SHUTDOWN2(accept_socket); + return(i); + } } - else - return(1); } -int do_server(int port, int *ret, int (*cb)(), char *context) +#ifndef NO_SYS_UN_H +int do_server_unix(const char *path, int *ret, + int (*cb)(char *hostname, int s, int stype, unsigned char *context), + unsigned char *context, int naccept) { int sock; - char *name; - int accept_socket; + int accept_socket = 0; int i; - if (!init_server(&accept_socket,port)) return(0); + if (!init_server_unix(&accept_socket, path)) return(0); if (ret != NULL) - { *ret=accept_socket; - /* return(1);*/ - } for (;;) { - if (do_accept(accept_socket,&sock,&name) == 0) + if (do_accept_unix(accept_socket, &sock) == 0) { SHUTDOWN(accept_socket); - return(0); + i = 0; + goto out; } - i=(*cb)(name,sock, context); - if (name != NULL) Free(name); + i=(*cb)(NULL, sock, 0, context); SHUTDOWN2(sock); - if (i < 0) + if (naccept != -1) + naccept--; + if (i < 0 || naccept == 0) { SHUTDOWN2(accept_socket); - return(i); + goto out; } } +out: + unlink(path); + return(i); } +#endif -int init_server_long(int *sock, int port, char *ip) +static int init_server_long(int *sock, int port, char *ip, int type) { int ret=0; struct sockaddr_in server; - int s= -1,i; + int s= -1; - if (!sock_init()) return(0); + if (!ssl_sock_init()) return(0); memset((char *)&server,0,sizeof(server)); server.sin_family=AF_INET; @@ -338,7 +410,11 @@ int init_server_long(int *sock, int port, char *ip) #else memcpy(&server.sin_addr,ip,4); #endif - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + + if (type == SOCK_STREAM) + s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + else /* type == SOCK_DGRAM */ + s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP); if (s == INVALID_SOCKET) goto err; #if defined SOL_SOCKET && defined SO_REUSEADDR @@ -350,14 +426,13 @@ int init_server_long(int *sock, int port, char *ip) #endif if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) { -#ifndef WINDOWS +#ifndef OPENSSL_SYS_WINDOWS perror("bind"); #endif goto err; } /* Make it 128 for linux */ - if (listen(s,128) == -1) goto err; - i=0; + if (type==SOCK_STREAM && listen(s,128) == -1) goto err; *sock=s; ret=1; err: @@ -368,22 +443,66 @@ err: return(ret); } -int init_server(int *sock, int port) +static int init_server(int *sock, int port, int type) { - return(init_server_long(sock, port, NULL)); + return(init_server_long(sock, port, NULL, type)); } -int do_accept(int acc_sock, int *sock, char **host) +#ifndef NO_SYS_UN_H +static int init_server_unix(int *sock, const char *path) { - int ret,i; + int ret = 0; + struct sockaddr_un server; + int s = -1; + + if (strlen(path) > (UNIX_PATH_MAX + 1)) return(0); + if (!ssl_sock_init()) return(0); + + s=socket(AF_UNIX, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) goto err; + + memset((char *)&server,0,sizeof(server)); + server.sun_family=AF_UNIX; + strcpy(server.sun_path, path); + + if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) + { +#ifndef OPENSSL_SYS_WINDOWS + perror("bind"); +#endif + goto err; + } + /* Make it 128 for linux */ + if (listen(s,128) == -1) + { +#ifndef OPENSSL_SYS_WINDOWS + perror("listen"); +#endif + unlink(path); + goto err; + } + *sock=s; + ret=1; +err: + if ((ret == 0) && (s != -1)) + { + SHUTDOWN(s); + } + return(ret); + } +#endif + +static int do_accept(int acc_sock, int *sock, char **host) + { + int ret; struct hostent *h1,*h2; static struct sockaddr_in from; int len; /* struct linger ling; */ - if (!sock_init()) return(0); + if (!ssl_sock_init()) return(0); -#ifndef WINDOWS +#ifndef OPENSSL_SYS_WINDOWS redoit: #endif @@ -397,7 +516,8 @@ redoit: ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len); if (ret == INVALID_SOCKET) { -#ifdef WINDOWS +#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) + int i; i=WSAGetLastError(); BIO_printf(bio_err,"accept error %d\n",i); #else @@ -439,23 +559,25 @@ redoit: } else { - if ((*host=(char *)Malloc(strlen(h1->h_name)+1)) == NULL) + if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL) { - perror("Malloc"); + perror("OPENSSL_malloc"); + closesocket(ret); return(0); } - strcpy(*host,h1->h_name); + BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1); h2=GetHostByName(*host); if (h2 == NULL) { BIO_printf(bio_err,"gethostbyname failure\n"); + closesocket(ret); return(0); } - i=0; if (h2->h_addrtype != AF_INET) { BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n"); + closesocket(ret); return(0); } } @@ -464,6 +586,32 @@ end: return(1); } +#ifndef NO_SYS_UN_H +static int do_accept_unix(int acc_sock, int *sock) + { + int ret; + + if (!ssl_sock_init()) return(0); + +redoit: + ret=accept(acc_sock, NULL, NULL); + if (ret == INVALID_SOCKET) + { + if (errno == EINTR) + { + /*check_timeout(); */ + goto redoit; + } + fprintf(stderr,"errno=%d ",errno); + perror("accept"); + return(0); + } + + *sock=ret; + return(1); + } +#endif + int extract_host_port(char *str, char **host_ptr, unsigned char *ip, short *port_ptr) { @@ -489,7 +637,7 @@ err: return(0); } -int host_ip(char *str, unsigned char ip[4]) +static int host_ip(const char *str, unsigned char ip[4]) { unsigned int in[4]; int i; @@ -511,7 +659,7 @@ int host_ip(char *str, unsigned char ip[4]) { /* do a gethostbyname */ struct hostent *he; - if (!sock_init()) return(0); + if (!ssl_sock_init()) return(0); he=GetHostByName(str); if (he == NULL) @@ -535,7 +683,7 @@ err: return(0); } -int extract_port(char *str, short *port_ptr) +int extract_port(const char *str, short *port_ptr) { int i; struct servent *s; @@ -567,7 +715,7 @@ static struct ghbn_cache_st static unsigned long ghbn_hits=0L; static unsigned long ghbn_miss=0L; -static struct hostent *GetHostByName(char *name) +static struct hostent *GetHostByName(const char *name) { struct hostent *ret; int i,lowi=0; @@ -592,9 +740,12 @@ static struct hostent *GetHostByName(char *name) ret=gethostbyname(name); if (ret == NULL) return(NULL); /* else add to cache */ - strncpy(ghbn_cache[lowi].name,name,128); - memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent)); - ghbn_cache[lowi].order=ghbn_miss+ghbn_hits; + if(strlen(name) < sizeof ghbn_cache[0].name) + { + strcpy(ghbn_cache[lowi].name,name); + memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent)); + ghbn_cache[lowi].order=ghbn_miss+ghbn_hits; + } return(ret); } else @@ -606,68 +757,4 @@ static struct hostent *GetHostByName(char *name) } } -#ifndef MSDOS -int spawn(int argc, char **argv, int *in, int *out) - { - int pid; -#define CHILD_READ p1[0] -#define CHILD_WRITE p2[1] -#define PARENT_READ p2[0] -#define PARENT_WRITE p1[1] - int p1[2],p2[2]; - - if ((pipe(p1) < 0) || (pipe(p2) < 0)) return(-1); - -#ifdef VMS - if ((pid=vfork()) == 0) -#else - if ((pid=fork()) == 0) -#endif - { /* child */ - if (dup2(CHILD_WRITE,fileno(stdout)) < 0) - perror("dup2"); - if (dup2(CHILD_WRITE,fileno(stderr)) < 0) - perror("dup2"); - if (dup2(CHILD_READ,fileno(stdin)) < 0) - perror("dup2"); - close(CHILD_READ); - close(CHILD_WRITE); - - close(PARENT_READ); - close(PARENT_WRITE); - execvp(argv[0],argv); - perror("child"); - exit(1); - } - - /* parent */ - *in= PARENT_READ; - *out=PARENT_WRITE; - close(CHILD_READ); - close(CHILD_WRITE); - return(pid); - } -#endif /* MSDOS */ - - -#ifdef undef - /* Turn on synchronous sockets so that we can do a WaitForMultipleObjects - * on sockets */ - { - SOCKET s; - int optionValue = SO_SYNCHRONOUS_NONALERT; - int err; - - err = setsockopt( - INVALID_SOCKET, - SOL_SOCKET, - SO_OPENTYPE, - (char *)&optionValue, - sizeof(optionValue)); - if (err != NO_ERROR) { - /* failed for some reason... */ - BIO_printf(bio_err, "failed to setsockopt(SO_OPENTYPE, SO_SYNCHRONOUS_ALERT) - %d\n", - WSAGetLastError()); - } - } #endif