Stop spurious "unable to load config info" errors in req
[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 #include <openssl/e_os2.h>
66
67 /* With IPv6, it looks like Digital has mixed up the proper order of
68    recursive header file inclusion, resulting in the compiler complaining
69    that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which
70    is needed to have fileno() declared correctly...  So let's define u_int */
71 #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
72 #define __U_INT
73 typedef unsigned int u_int;
74 #endif
75
76 #define USE_SOCKETS
77 #define NON_MAIN
78 #include "apps.h"
79 #undef USE_SOCKETS
80 #undef NON_MAIN
81 #include "s_apps.h"
82 #include <openssl/ssl.h>
83
84 static struct hostent *GetHostByName(char *name);
85 #ifdef OPENSSL_SYS_WINDOWS
86 static void sock_cleanup(void);
87 #endif
88 static int sock_init(void);
89 static int init_client_ip(int *sock,unsigned char ip[4], int port);
90 static int init_server(int *sock, int port);
91 static int init_server_long(int *sock, int port,char *ip);
92 static int do_accept(int acc_sock, int *sock, char **host);
93 static int host_ip(char *str, unsigned char ip[4]);
94
95 #ifdef OPENSSL_SYS_WIN16
96 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
97 #else
98 #define SOCKET_PROTOCOL IPPROTO_TCP
99 #endif
100
101 #ifdef OPENSSL_SYS_WINDOWS
102 static struct WSAData wsa_state;
103 static int wsa_init_done=0;
104
105 #ifdef OPENSSL_SYS_WIN16
106 static HWND topWnd=0;
107 static FARPROC lpTopWndProc=NULL;
108 static FARPROC lpTopHookProc=NULL;
109 extern HINSTANCE _hInstance;  /* nice global CRT provides */
110
111 static LONG FAR PASCAL topHookProc(HWND hwnd, UINT message, WPARAM wParam,
112              LPARAM lParam)
113         {
114         if (hwnd == topWnd)
115                 {
116                 switch(message)
117                         {
118                 case WM_DESTROY:
119                 case WM_CLOSE:
120                         SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopWndProc);
121                         sock_cleanup();
122                         break;
123                         }
124                 }
125         return CallWindowProc(lpTopWndProc,hwnd,message,wParam,lParam);
126         }
127
128 static BOOL CALLBACK enumproc(HWND hwnd,LPARAM lParam)
129         {
130         topWnd=hwnd;
131         return(FALSE);
132         }
133
134 #endif /* OPENSSL_SYS_WIN32 */
135 #endif /* OPENSSL_SYS_WINDOWS */
136
137 #ifdef OPENSSL_SYS_WINDOWS
138 static void sock_cleanup(void)
139         {
140         if (wsa_init_done)
141                 {
142                 wsa_init_done=0;
143                 WSACancelBlockingCall();
144                 WSACleanup();
145                 }
146         }
147 #endif
148
149 static int sock_init(void)
150         {
151 #ifdef OPENSSL_SYS_WINDOWS
152         if (!wsa_init_done)
153                 {
154                 int err;
155           
156 #ifdef SIGINT
157                 signal(SIGINT,(void (*)(int))sock_cleanup);
158 #endif
159                 wsa_init_done=1;
160                 memset(&wsa_state,0,sizeof(wsa_state));
161                 if (WSAStartup(0x0101,&wsa_state)!=0)
162                         {
163                         err=WSAGetLastError();
164                         BIO_printf(bio_err,"unable to start WINSOCK, error code=%d\n",err);
165                         return(0);
166                         }
167
168 #ifdef OPENSSL_SYS_WIN16
169                 EnumTaskWindows(GetCurrentTask(),enumproc,0L);
170                 lpTopWndProc=(FARPROC)GetWindowLong(topWnd,GWL_WNDPROC);
171                 lpTopHookProc=MakeProcInstance((FARPROC)topHookProc,_hInstance);
172
173                 SetWindowLong(topWnd,GWL_WNDPROC,(LONG)lpTopHookProc);
174 #endif /* OPENSSL_SYS_WIN16 */
175                 }
176 #endif /* OPENSSL_SYS_WINDOWS */
177         return(1);
178         }
179
180 int init_client(int *sock, char *host, int port)
181         {
182         unsigned char ip[4];
183         short p=0;
184
185         if (!host_ip(host,&(ip[0])))
186                 {
187                 return(0);
188                 }
189         if (p != 0) port=p;
190         return(init_client_ip(sock,ip,port));
191         }
192
193 static int init_client_ip(int *sock, unsigned char ip[4], int port)
194         {
195         unsigned long addr;
196         struct sockaddr_in them;
197         int s,i;
198
199         if (!sock_init()) return(0);
200
201         memset((char *)&them,0,sizeof(them));
202         them.sin_family=AF_INET;
203         them.sin_port=htons((unsigned short)port);
204         addr=(unsigned long)
205                 ((unsigned long)ip[0]<<24L)|
206                 ((unsigned long)ip[1]<<16L)|
207                 ((unsigned long)ip[2]<< 8L)|
208                 ((unsigned long)ip[3]);
209         them.sin_addr.s_addr=htonl(addr);
210
211         s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
212         if (s == INVALID_SOCKET) { perror("socket"); return(0); }
213
214 #ifndef OPENSSL_SYS_MPE
215         i=0;
216         i=setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
217         if (i < 0) { perror("keepalive"); return(0); }
218 #endif
219
220         if (connect(s,(struct sockaddr *)&them,sizeof(them)) == -1)
221                 { close(s); perror("connect"); return(0); }
222         *sock=s;
223         return(1);
224         }
225
226 int do_server(int port, int *ret, int (*cb)(), char *context)
227         {
228         int sock;
229         char *name;
230         int accept_socket;
231         int i;
232
233         if (!init_server(&accept_socket,port)) return(0);
234
235         if (ret != NULL)
236                 {
237                 *ret=accept_socket;
238                 /* return(1);*/
239                 }
240         for (;;)
241                 {
242                 if (do_accept(accept_socket,&sock,&name) == 0)
243                         {
244                         SHUTDOWN(accept_socket);
245                         return(0);
246                         }
247                 i=(*cb)(name,sock, context);
248                 if (name != NULL) OPENSSL_free(name);
249                 SHUTDOWN2(sock);
250                 if (i < 0)
251                         {
252                         SHUTDOWN2(accept_socket);
253                         return(i);
254                         }
255                 }
256         }
257
258 static int init_server_long(int *sock, int port, char *ip)
259         {
260         int ret=0;
261         struct sockaddr_in server;
262         int s= -1,i;
263
264         if (!sock_init()) return(0);
265
266         memset((char *)&server,0,sizeof(server));
267         server.sin_family=AF_INET;
268         server.sin_port=htons((unsigned short)port);
269         if (ip == NULL)
270                 server.sin_addr.s_addr=INADDR_ANY;
271         else
272 /* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
273 #ifndef BIT_FIELD_LIMITS
274                 memcpy(&server.sin_addr.s_addr,ip,4);
275 #else
276                 memcpy(&server.sin_addr,ip,4);
277 #endif
278         s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
279
280         if (s == INVALID_SOCKET) goto err;
281 #if defined SOL_SOCKET && defined SO_REUSEADDR
282                 {
283                 int j = 1;
284                 setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
285                            (void *) &j, sizeof j);
286                 }
287 #endif
288         if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
289                 {
290 #ifndef OPENSSL_SYS_WINDOWS
291                 perror("bind");
292 #endif
293                 goto err;
294                 }
295         /* Make it 128 for linux */
296         if (listen(s,128) == -1) goto err;
297         i=0;
298         *sock=s;
299         ret=1;
300 err:
301         if ((ret == 0) && (s != -1))
302                 {
303                 SHUTDOWN(s);
304                 }
305         return(ret);
306         }
307
308 static int init_server(int *sock, int port)
309         {
310         return(init_server_long(sock, port, NULL));
311         }
312
313 static int do_accept(int acc_sock, int *sock, char **host)
314         {
315         int ret,i;
316         struct hostent *h1,*h2;
317         static struct sockaddr_in from;
318         int len;
319 /*      struct linger ling; */
320
321         if (!sock_init()) return(0);
322
323 #ifndef OPENSSL_SYS_WINDOWS
324 redoit:
325 #endif
326
327         memset((char *)&from,0,sizeof(from));
328         len=sizeof(from);
329         /* Note: under VMS with SOCKETSHR the fourth parameter is currently
330          * of type (int *) whereas under other systems it is (void *) if
331          * you don't have a cast it will choke the compiler: if you do
332          * have a cast then you can either go for (int *) or (void *).
333          */
334         ret=accept(acc_sock,(struct sockaddr *)&from,(void *)&len);
335         if (ret == INVALID_SOCKET)
336                 {
337 #ifdef OPENSSL_SYS_WINDOWS
338                 i=WSAGetLastError();
339                 BIO_printf(bio_err,"accept error %d\n",i);
340 #else
341                 if (errno == EINTR)
342                         {
343                         /*check_timeout(); */
344                         goto redoit;
345                         }
346                 fprintf(stderr,"errno=%d ",errno);
347                 perror("accept");
348 #endif
349                 return(0);
350                 }
351
352 /*
353         ling.l_onoff=1;
354         ling.l_linger=0;
355         i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
356         if (i < 0) { perror("linger"); return(0); }
357         i=0;
358         i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
359         if (i < 0) { perror("keepalive"); return(0); }
360 */
361
362         if (host == NULL) goto end;
363 #ifndef BIT_FIELD_LIMITS
364         /* I should use WSAAsyncGetHostByName() under windows */
365         h1=gethostbyaddr((char *)&from.sin_addr.s_addr,
366                 sizeof(from.sin_addr.s_addr),AF_INET);
367 #else
368         h1=gethostbyaddr((char *)&from.sin_addr,
369                 sizeof(struct in_addr),AF_INET);
370 #endif
371         if (h1 == NULL)
372                 {
373                 BIO_printf(bio_err,"bad gethostbyaddr\n");
374                 *host=NULL;
375                 /* return(0); */
376                 }
377         else
378                 {
379                 if ((*host=(char *)OPENSSL_malloc(strlen(h1->h_name)+1)) == NULL)
380                         {
381                         perror("OPENSSL_malloc");
382                         return(0);
383                         }
384                 strcpy(*host,h1->h_name);
385
386                 h2=GetHostByName(*host);
387                 if (h2 == NULL)
388                         {
389                         BIO_printf(bio_err,"gethostbyname failure\n");
390                         return(0);
391                         }
392                 i=0;
393                 if (h2->h_addrtype != AF_INET)
394                         {
395                         BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
396                         return(0);
397                         }
398                 }
399 end:
400         *sock=ret;
401         return(1);
402         }
403
404 int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
405              short *port_ptr)
406         {
407         char *h,*p;
408
409         h=str;
410         p=strchr(str,':');
411         if (p == NULL)
412                 {
413                 BIO_printf(bio_err,"no port defined\n");
414                 return(0);
415                 }
416         *(p++)='\0';
417
418         if ((ip != NULL) && !host_ip(str,ip))
419                 goto err;
420         if (host_ptr != NULL) *host_ptr=h;
421
422         if (!extract_port(p,port_ptr))
423                 goto err;
424         return(1);
425 err:
426         return(0);
427         }
428
429 static int host_ip(char *str, unsigned char ip[4])
430         {
431         unsigned int in[4]; 
432         int i;
433
434         if (sscanf(str,"%u.%u.%u.%u",&(in[0]),&(in[1]),&(in[2]),&(in[3])) == 4)
435                 {
436                 for (i=0; i<4; i++)
437                         if (in[i] > 255)
438                                 {
439                                 BIO_printf(bio_err,"invalid IP address\n");
440                                 goto err;
441                                 }
442                 ip[0]=in[0];
443                 ip[1]=in[1];
444                 ip[2]=in[2];
445                 ip[3]=in[3];
446                 }
447         else
448                 { /* do a gethostbyname */
449                 struct hostent *he;
450
451                 if (!sock_init()) return(0);
452
453                 he=GetHostByName(str);
454                 if (he == NULL)
455                         {
456                         BIO_printf(bio_err,"gethostbyname failure\n");
457                         goto err;
458                         }
459                 /* cast to short because of win16 winsock definition */
460                 if ((short)he->h_addrtype != AF_INET)
461                         {
462                         BIO_printf(bio_err,"gethostbyname addr is not AF_INET\n");
463                         return(0);
464                         }
465                 ip[0]=he->h_addr_list[0][0];
466                 ip[1]=he->h_addr_list[0][1];
467                 ip[2]=he->h_addr_list[0][2];
468                 ip[3]=he->h_addr_list[0][3];
469                 }
470         return(1);
471 err:
472         return(0);
473         }
474
475 int extract_port(char *str, short *port_ptr)
476         {
477         int i;
478         struct servent *s;
479
480         i=atoi(str);
481         if (i != 0)
482                 *port_ptr=(unsigned short)i;
483         else
484                 {
485                 s=getservbyname(str,"tcp");
486                 if (s == NULL)
487                         {
488                         BIO_printf(bio_err,"getservbyname failure for %s\n",str);
489                         return(0);
490                         }
491                 *port_ptr=ntohs((unsigned short)s->s_port);
492                 }
493         return(1);
494         }
495
496 #define GHBN_NUM        4
497 static struct ghbn_cache_st
498         {
499         char name[128];
500         struct hostent ent;
501         unsigned long order;
502         } ghbn_cache[GHBN_NUM];
503
504 static unsigned long ghbn_hits=0L;
505 static unsigned long ghbn_miss=0L;
506
507 static struct hostent *GetHostByName(char *name)
508         {
509         struct hostent *ret;
510         int i,lowi=0;
511         unsigned long low= (unsigned long)-1;
512
513         for (i=0; i<GHBN_NUM; i++)
514                 {
515                 if (low > ghbn_cache[i].order)
516                         {
517                         low=ghbn_cache[i].order;
518                         lowi=i;
519                         }
520                 if (ghbn_cache[i].order > 0)
521                         {
522                         if (strncmp(name,ghbn_cache[i].name,128) == 0)
523                                 break;
524                         }
525                 }
526         if (i == GHBN_NUM) /* no hit*/
527                 {
528                 ghbn_miss++;
529                 ret=gethostbyname(name);
530                 if (ret == NULL) return(NULL);
531                 /* else add to cache */
532                 strncpy(ghbn_cache[lowi].name,name,128);
533                 memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent));
534                 ghbn_cache[lowi].order=ghbn_miss+ghbn_hits;
535                 return(ret);
536                 }
537         else
538                 {
539                 ghbn_hits++;
540                 ret= &(ghbn_cache[i].ent);
541                 ghbn_cache[i].order=ghbn_miss+ghbn_hits;
542                 return(ret);
543                 }
544         }