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