RT3548: Remove unsupported platforms
[openssl.git] / apps / s_socket.c
1 /* apps/s_socket.c -  socket-related functions used by s_client and s_server */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <errno.h>
63 #include <signal.h>
64
65 /* With IPv6, it looks like Digital has mixed up the proper order of
66    recursive header file inclusion, resulting in the compiler complaining
67    that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which
68    is needed to have fileno() declared correctly...  So let's define u_int */
69 #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
70 #define __U_INT
71 typedef unsigned int u_int;
72 #endif
73
74 #define USE_SOCKETS
75 #define NON_MAIN
76 #include "apps.h"
77 #undef USE_SOCKETS
78 #undef NON_MAIN
79 #include "s_apps.h"
80 #include <openssl/ssl.h>
81
82 #ifdef FLAT_INC
83 #include "e_os.h"
84 #else
85 #include "../e_os.h"
86 #endif
87
88 #ifndef OPENSSL_NO_SOCK
89
90 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
91 #include "netdb.h"
92 #endif
93
94 static struct hostent *GetHostByName(const char *name);
95 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
96 static void ssl_sock_cleanup(void);
97 #endif
98 static int ssl_sock_init(void);
99 static int init_client_ip(int *sock, const unsigned char ip[4], int port,
100                           int type);
101 static int init_server(int *sock, int port, int type);
102 static int init_server_long(int *sock, int port,char *ip, int type);
103 static int do_accept(int acc_sock, int *sock, char **host);
104 static int host_ip(const char *str, unsigned char ip[4]);
105 #ifndef NO_SYS_UN_H
106 static int init_server_unix(int *sock, const char *path);
107 static int do_accept_unix(int acc_sock, int *sock);
108 #endif
109
110 #if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
111 static int wsa_init_done=0;
112 #endif
113
114 #ifdef OPENSSL_SYS_WINDOWS
115 static struct WSAData wsa_state;
116 static int wsa_init_done=0;
117
118 #endif /* OPENSSL_SYS_WINDOWS */
119
120 #ifdef OPENSSL_SYS_WINDOWS
121 static void ssl_sock_cleanup(void)
122         {
123         if (wsa_init_done)
124                 {
125                 wsa_init_done=0;
126 #ifndef OPENSSL_SYS_WINCE
127                 WSACancelBlockingCall();
128 #endif
129                 WSACleanup();
130                 }
131         }
132 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
133 static void sock_cleanup(void)
134     {
135     if (wsa_init_done)
136         {
137         wsa_init_done=0;
138                 WSACleanup();
139                 }
140         }
141 #endif
142
143 static int ssl_sock_init(void)
144         {
145 #ifdef WATT32
146         extern int _watt_do_exit;
147         _watt_do_exit = 0;
148         if (sock_init())
149                 return (0);
150 #elif defined(OPENSSL_SYS_WINDOWS)
151         if (!wsa_init_done)
152                 {
153                 int err;
154           
155 #ifdef SIGINT
156                 signal(SIGINT,(void (*)(int))ssl_sock_cleanup);
157 #endif
158                 wsa_init_done=1;
159                 memset(&wsa_state,0,sizeof(wsa_state));
160                 if (WSAStartup(0x0101,&wsa_state)!=0)
161                         {
162                         err=WSAGetLastError();
163                         BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err);
164                         return(0);
165                         }
166                 }
167 #elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
168    WORD wVerReq;
169    WSADATA wsaData;
170    int err;
171
172    if (!wsa_init_done)
173       {
174    
175 # ifdef SIGINT
176       signal(SIGINT,(void (*)(int))sock_cleanup);
177 # endif
178
179       wsa_init_done=1;
180       wVerReq = MAKEWORD( 2, 0 );
181       err = WSAStartup(wVerReq,&wsaData);
182       if (err != 0)
183          {
184          BIO_printf(bio_err,"unable to start WINSOCK2, error code=%d\n",err);
185          return(0);
186          }
187       }
188 #endif /* OPENSSL_SYS_WINDOWS */
189         return(1);
190         }
191
192 int init_client(int *sock, const char *host, int port, int type)
193         {
194         unsigned char ip[4];
195
196         ip[0] = ip[1] = ip[2] = ip[3] = 0;
197         if (!host_ip(host,&(ip[0])))
198                 return 0;
199         return init_client_ip(sock,ip,port,type);
200         }
201
202 static int init_client_ip(int *sock, const unsigned char ip[4], int port,
203                           int type)
204         {
205         unsigned long addr;
206         struct sockaddr_in them;
207         int s,i;
208
209         if (!ssl_sock_init()) return(0);
210
211         memset((char *)&them,0,sizeof(them));
212         them.sin_family=AF_INET;
213         them.sin_port=htons((unsigned short)port);
214         addr=(unsigned long)
215                 ((unsigned long)ip[0]<<24L)|
216                 ((unsigned long)ip[1]<<16L)|
217                 ((unsigned long)ip[2]<< 8L)|
218                 ((unsigned long)ip[3]);
219         them.sin_addr.s_addr=htonl(addr);
220
221         if (type == SOCK_STREAM)
222                 s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
223         else /* ( type == SOCK_DGRAM) */
224                 s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
225                         
226         if (s == INVALID_SOCKET) { perror("socket"); return(0); }
227
228 #if defined(SO_KEEPALIVE)
229         if (type == SOCK_STREAM)
230                 {
231                 i=0;
232                 i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
233                 if (i < 0) { closesocket(s); perror("keepalive"); return(0); }
234                 }
235 #endif
236
237         if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
238                 { closesocket(s); perror("connect"); return(0); }
239         *sock=s;
240         return(1);
241         }
242
243 #ifndef NO_SYS_UN_H
244 int init_client_unix(int *sock, const char *server)
245         {
246         struct sockaddr_un them;
247         int s;
248
249         if (strlen(server) > (UNIX_PATH_MAX + 1)) return(0);
250         if (!ssl_sock_init()) return(0);
251
252         s=socket(AF_UNIX, SOCK_STREAM, 0);
253         if (s == INVALID_SOCKET) { perror("socket"); return(0); }
254
255         memset((char *)&them,0,sizeof(them));
256         them.sun_family=AF_UNIX;
257         strcpy(them.sun_path, server);
258
259         if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1)
260                 { closesocket(s); perror("connect"); return(0); }
261         *sock=s;
262         return(1);
263         }
264 #endif
265
266 int do_server(int port, int type, int *ret,
267               int (*cb)(char *hostname, int s, int stype, unsigned char *context),
268               unsigned char *context, int naccept)
269         {
270         int sock;
271         char *name = NULL;
272         int accept_socket = 0;
273         int i;
274
275         if (!init_server(&accept_socket,port,type)) return(0);
276
277         if (ret != NULL)
278                 {
279                 *ret=accept_socket;
280                 /* return(1);*/
281                 }
282         for (;;)
283                 {
284                 if (type==SOCK_STREAM)
285                         {
286 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
287                         if (do_accept(accept_socket,&sock,NULL) == 0)
288 #else
289                         if (do_accept(accept_socket,&sock,&name) == 0)
290 #endif
291                                 {
292                                 SHUTDOWN(accept_socket);
293                                 return(0);
294                                 }
295                         }
296                 else
297                         sock = accept_socket;
298                 i=(*cb)(name,sock, type, context);
299                 if (name != NULL) OPENSSL_free(name);
300                 if (type==SOCK_STREAM)
301                         SHUTDOWN2(sock);
302                 if (naccept != -1)
303                         naccept--;
304                 if (i < 0 || naccept == 0)
305                         {
306                         SHUTDOWN2(accept_socket);
307                         return(i);
308                         }
309                 }
310         }
311
312 #ifndef NO_SYS_UN_H
313 int do_server_unix(const char *path, int *ret,
314                    int (*cb)(char *hostname, int s, int stype, unsigned char *context),
315                    unsigned char *context, int naccept)
316         {
317         int sock;
318         int accept_socket = 0;
319         int i;
320
321         if (!init_server_unix(&accept_socket, path)) return(0);
322
323         if (ret != NULL)
324                 *ret=accept_socket;
325         for (;;)
326                 {
327                 if (do_accept_unix(accept_socket, &sock) == 0)
328                         {
329                         SHUTDOWN(accept_socket);
330                         i = 0;
331                         goto out;
332                         }
333                 i=(*cb)(NULL, sock, 0, context);
334                 SHUTDOWN2(sock);
335                 if (naccept != -1)
336                         naccept--;
337                 if (i < 0 || naccept == 0)
338                         {
339                         SHUTDOWN2(accept_socket);
340                         goto out;
341                         }
342                 }
343 out:
344         unlink(path);
345         return(i);
346         }
347 #endif
348
349 static int init_server_long(int *sock, int port, char *ip, int type)
350         {
351         int ret=0;
352         struct sockaddr_in server;
353         int s= -1;
354
355         if (!ssl_sock_init()) return(0);
356
357         memset((char *)&server,0,sizeof(server));
358         server.sin_family=AF_INET;
359         server.sin_port=htons((unsigned short)port);
360         if (ip == NULL)
361                 server.sin_addr.s_addr=INADDR_ANY;
362         else
363 /* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
364 #ifndef BIT_FIELD_LIMITS
365                 memcpy(&server.sin_addr.s_addr,ip,4);
366 #else
367                 memcpy(&server.sin_addr,ip,4);
368 #endif
369         
370                 if (type == SOCK_STREAM)
371                         s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
372                 else /* type == SOCK_DGRAM */
373                         s=socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
374
375         if (s == INVALID_SOCKET) goto err;
376 #if defined SOL_SOCKET && defined SO_REUSEADDR
377                 {
378                 int j = 1;
379                 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
380                            (void *) &j, sizeof j);
381                 }
382 #endif
383         if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
384                 {
385 #ifndef OPENSSL_SYS_WINDOWS
386                 perror("bind");
387 #endif
388                 goto err;
389                 }
390         /* Make it 128 for linux */
391         if (type==SOCK_STREAM && listen(s,128) == -1) goto err;
392         *sock=s;
393         ret=1;
394 err:
395         if ((ret == 0) && (s != -1))
396                 {
397                 SHUTDOWN(s);
398                 }
399         return(ret);
400         }
401
402 static int init_server(int *sock, int port, int type)
403         {
404         return(init_server_long(sock, port, NULL, type));
405         }
406
407 #ifndef NO_SYS_UN_H
408 static int init_server_unix(int *sock, const char *path)
409         {
410         int ret = 0;
411         struct sockaddr_un server;
412         int s = -1;
413
414         if (strlen(path) > (UNIX_PATH_MAX + 1)) return(0);
415         if (!ssl_sock_init()) return(0);
416
417         s=socket(AF_UNIX, SOCK_STREAM, 0);
418         if (s == INVALID_SOCKET) goto err;
419
420         memset((char *)&server,0,sizeof(server));
421         server.sun_family=AF_UNIX;
422         strcpy(server.sun_path, path);
423
424         if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1)
425                 {
426 #ifndef OPENSSL_SYS_WINDOWS
427                 perror("bind");
428 #endif
429                 goto err;
430                 }
431         /* Make it 128 for linux */
432         if (listen(s,128) == -1)
433                 {
434 #ifndef OPENSSL_SYS_WINDOWS
435                 perror("listen");
436 #endif
437                 unlink(path);
438                 goto err;
439                 }
440         *sock=s;
441         ret=1;
442 err:
443         if ((ret == 0) && (s != -1))
444                 {
445                 SHUTDOWN(s);
446                 }
447         return(ret);
448         }
449 #endif
450
451 static int do_accept(int acc_sock, int *sock, char **host)
452         {
453         int ret;
454         struct hostent *h1,*h2;
455         static struct sockaddr_in from;
456         int len;
457 /*      struct linger ling; */
458
459         if (!ssl_sock_init()) return(0);
460
461 #ifndef OPENSSL_SYS_WINDOWS
462 redoit:
463 #endif
464
465         memset((char *)&from,0,sizeof(from));
466         len=sizeof(from);
467         /* Note: under VMS with SOCKETSHR the fourth parameter is currently
468          * of type (int *) whereas under other systems it is (void *) if
469          * you don't have a cast it will choke the compiler: if you do
470          * have a cast then you can either go for (int *) or (void *).
471          */
472         ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
473         if (ret == INVALID_SOCKET)
474                 {
475 #if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
476                 int i;
477                 i=WSAGetLastError();
478                 BIO_printf(bio_err,"accept error %d\n",i);
479 #else
480                 if (errno == EINTR)
481                         {
482                         /*check_timeout(); */
483                         goto redoit;
484                         }
485                 fprintf(stderr,"errno=%d ",errno);
486                 perror("accept");
487 #endif
488                 return(0);
489                 }
490
491 /*-
492         ling.l_onoff=1;
493         ling.l_linger=0;
494         i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
495         if (i < 0) { perror("linger"); return(0); }
496         i=0;
497         i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
498         if (i < 0) { perror("keepalive"); return(0); }
499 */
500
501         if (host == NULL) goto end;
502 #ifndef BIT_FIELD_LIMITS
503         /* I should use WSAAsyncGetHostByName() under windows */
504         h1=gethostbyaddr((char *)&from.sin_addr.s_addr,
505                 sizeof(from.sin_addr.s_addr),AF_INET);
506 #else
507         h1=gethostbyaddr((char *)&from.sin_addr,
508                 sizeof(struct in_addr),AF_INET);
509 #endif
510         if (h1 == NULL)
511                 {
512                 BIO_printf(bio_err,"bad gethostbyaddr\n");
513                 *host=NULL;
514                 /* return(0); */
515                 }
516         else
517                 {
518                 if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL)
519                         {
520                         perror("OPENSSL_malloc");
521                         closesocket(ret);
522                         return(0);
523                         }
524                 BUF_strlcpy(*host,h1->h_name,strlen(h1->h_name)+1);
525
526                 h2=GetHostByName(*host);
527                 if (h2 == NULL)
528                         {
529                         BIO_printf(bio_err,"gethostbyname failure\n");
530                         closesocket(ret);
531                         return(0);
532                         }
533                 if (h2->h_addrtype != AF_INET)
534                         {
535                         BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
536                         closesocket(ret);
537                         return(0);
538                         }
539                 }
540 end:
541         *sock=ret;
542         return(1);
543         }
544
545 #ifndef NO_SYS_UN_H
546 static int do_accept_unix(int acc_sock, int *sock)
547         {
548         int ret;
549
550         if (!ssl_sock_init()) return(0);
551
552 redoit:
553         ret=accept(acc_sock, NULL, NULL);
554         if (ret == INVALID_SOCKET)
555                 {
556                 if (errno == EINTR)
557                         {
558                         /*check_timeout(); */
559                         goto redoit;
560                         }
561                 fprintf(stderr,"errno=%d ",errno);
562                 perror("accept");
563                 return(0);
564                 }
565
566         *sock=ret;
567         return(1);
568         }
569 #endif
570
571 int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
572              short *port_ptr)
573         {
574         char *h,*p;
575
576         h=str;
577         p=strchr(str,':');
578         if (p == NULL)
579                 {
580                 BIO_printf(bio_err,"no port defined\n");
581                 return(0);
582                 }
583         *(p++)='\0';
584
585         if ((ip != NULL) && !host_ip(str,ip))
586                 goto err;
587         if (host_ptr != NULL) *host_ptr=h;
588
589         if (!extract_port(p,port_ptr))
590                 goto err;
591         return(1);
592 err:
593         return(0);
594         }
595
596 static int host_ip(const char *str, unsigned char ip[4])
597         {
598         unsigned int in[4]; 
599         int i;
600
601         if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
602                 {
603                 for (i=0; i<4; i++)
604                         if (in[i] > 255)
605                                 {
606                                 BIO_printf(bio_err,"invalid IP address\n");
607                                 goto err;
608                                 }
609                 ip[0]=in[0];
610                 ip[1]=in[1];
611                 ip[2]=in[2];
612                 ip[3]=in[3];
613                 }
614         else
615                 { /* do a gethostbyname */
616                 struct hostent *he;
617
618                 if (!ssl_sock_init()) return(0);
619
620                 he=GetHostByName(str);
621                 if (he == NULL)
622                         {
623                         BIO_printf(bio_err,"gethostbyname failure\n");
624                         goto err;
625                         }
626                 if (he->h_addrtype != AF_INET)
627                         {
628                         BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
629                         return(0);
630                         }
631                 ip[0]=he->h_addr_list[0][0];
632                 ip[1]=he->h_addr_list[0][1];
633                 ip[2]=he->h_addr_list[0][2];
634                 ip[3]=he->h_addr_list[0][3];
635                 }
636         return(1);
637 err:
638         return(0);
639         }
640
641 int extract_port(const char *str, short *port_ptr)
642         {
643         int i;
644         struct servent *s;
645
646         i=atoi(str);
647         if (i != 0)
648                 *port_ptr=(unsigned short)i;
649         else
650                 {
651                 s=getservbyname(str,"tcp");
652                 if (s == NULL)
653                         {
654                         BIO_printf(bio_err,"getservbyname failure for %s\n",str);
655                         return(0);
656                         }
657                 *port_ptr=ntohs((unsigned short)s->s_port);
658                 }
659         return(1);
660         }
661
662 #define GHBN_NUM        4
663 static struct ghbn_cache_st
664         {
665         char name[128];
666         struct hostent ent;
667         unsigned long order;
668         } ghbn_cache[GHBN_NUM];
669
670 static unsigned long ghbn_hits=0L;
671 static unsigned long ghbn_miss=0L;
672
673 static struct hostent *GetHostByName(const char *name)
674         {
675         struct hostent *ret;
676         int i,lowi=0;
677         unsigned long low= (unsigned long)-1;
678
679         for (i=0; i<GHBN_NUM; i++)
680                 {
681                 if (low > ghbn_cache[i].order)
682                         {
683                         low=ghbn_cache[i].order;
684                         lowi=i;
685                         }
686                 if (ghbn_cache[i].order > 0)
687                         {
688                         if (strncmp(name,ghbn_cache[i].name,128) == 0)
689                                 break;
690                         }
691                 }
692         if (i == GHBN_NUM) /* no hit*/
693                 {
694                 ghbn_miss++;
695                 ret=gethostbyname(name);
696                 if (ret == NULL) return(NULL);
697                 /* else add to cache */
698                 if(strlen(name) < sizeof ghbn_cache[0].name)
699                         {
700                         strcpy(ghbn_cache[lowi].name,name);
701                         memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent));
702                         ghbn_cache[lowi].order=ghbn_miss+ghbn_hits;
703                         }
704                 return(ret);
705                 }
706         else
707                 {
708                 ghbn_hits++;
709                 ret= &(ghbn_cache[i].ent);
710                 ghbn_cache[i].order=ghbn_miss+ghbn_hits;
711                 return(ret);
712                 }
713         }
714
715 #endif