[BACK]Return to s_socket.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/s_socket.c, Revision 1.2

1.2     ! jsing       1: /* $OpenBSD: s_socket.c,v 1.1 2014/08/26 17:47:25 jsing Exp $ */
1.1       jsing       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 <sys/socket.h>
                     60:
                     61: #include <netinet/in.h>
                     62:
                     63: #include <errno.h>
                     64: #include <netdb.h>
                     65: #include <stdio.h>
                     66: #include <stdlib.h>
                     67: #include <string.h>
                     68: #include <unistd.h>
                     69:
                     70: #include "apps.h"
                     71:
                     72: #include <openssl/ssl.h>
                     73:
                     74: #include "s_apps.h"
                     75:
                     76: static int init_server(int *sock, int port, int type);
                     77: static int init_server_long(int *sock, int port, char *ip, int type);
                     78: static int do_accept(int acc_sock, int *sock, char **host);
                     79:
                     80: #define SOCKET_PROTOCOL        IPPROTO_TCP
                     81:
                     82: int
                     83: init_client(int *sock, char *host, char *port, int type, int af)
                     84: {
                     85:        struct addrinfo hints, *ai_top, *ai;
                     86:        int i, s;
                     87:
                     88:        memset(&hints, '\0', sizeof(hints));
                     89:        hints.ai_family = af;
                     90:        hints.ai_socktype = type;
                     91:
                     92:        if ((i = getaddrinfo(host, port, &hints, &ai_top)) != 0) {
                     93:                BIO_printf(bio_err, "getaddrinfo: %s\n", gai_strerror(i));
                     94:                return (0);
                     95:        }
                     96:        if (ai_top == NULL || ai_top->ai_addr == NULL) {
                     97:                BIO_printf(bio_err, "getaddrinfo returned no addresses\n");
                     98:                if (ai_top != NULL) {
                     99:                        freeaddrinfo(ai_top);
                    100:                }
                    101:                return (0);
                    102:        }
                    103:        for (ai = ai_top; ai != NULL; ai = ai->ai_next) {
                    104:                s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
                    105:                if (s == -1) {
                    106:                        continue;
                    107:                }
                    108:                if (type == SOCK_STREAM) {
                    109:                        i = 0;
                    110:                        i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
                    111:                            (char *) &i, sizeof(i));
                    112:                        if (i < 0) {
                    113:                                perror("keepalive");
                    114:                                close(s);
                    115:                                return (0);
                    116:                        }
                    117:                }
                    118:                if ((i = connect(s, ai->ai_addr, ai->ai_addrlen)) == 0) {
                    119:                        *sock = s;
                    120:                        freeaddrinfo(ai_top);
                    121:                        return (1);
                    122:                }
                    123:                close(s);
                    124:        }
                    125:
                    126:        perror("connect");
                    127:        close(s);
                    128:        freeaddrinfo(ai_top);
                    129:        return (0);
                    130: }
                    131:
                    132: int
                    133: do_server(int port, int type, int *ret,
                    134:     int (*cb) (char *hostname, int s, unsigned char *context),
                    135:     unsigned char *context)
                    136: {
                    137:        int sock;
                    138:        char *name = NULL;
                    139:        int accept_socket = 0;
                    140:        int i;
                    141:
                    142:        if (!init_server(&accept_socket, port, type))
                    143:                return (0);
                    144:
                    145:        if (ret != NULL) {
                    146:                *ret = accept_socket;
                    147:                /* return(1); */
                    148:        }
                    149:        for (;;) {
                    150:                if (type == SOCK_STREAM) {
                    151:                        if (do_accept(accept_socket, &sock, &name) == 0) {
                    152:                                shutdown(accept_socket, SHUT_RD);
                    153:                                close(accept_socket);
                    154:                                return (0);
                    155:                        }
                    156:                } else
                    157:                        sock = accept_socket;
                    158:                i = (*cb) (name, sock, context);
                    159:                free(name);
                    160:                if (type == SOCK_STREAM) {
                    161:                        shutdown(sock, SHUT_RDWR);
                    162:                        close(sock);
                    163:                }
                    164:                if (i < 0) {
                    165:                        shutdown(accept_socket, SHUT_RDWR);
                    166:                        close(accept_socket);
                    167:                        return (i);
                    168:                }
                    169:        }
                    170: }
                    171:
                    172: static int
                    173: init_server_long(int *sock, int port, char *ip, int type)
                    174: {
                    175:        int ret = 0;
                    176:        struct sockaddr_in server;
                    177:        int s = -1;
                    178:
                    179:        memset((char *) &server, 0, sizeof(server));
                    180:        server.sin_family = AF_INET;
                    181:        server.sin_port = htons((unsigned short) port);
                    182:        if (ip == NULL)
                    183:                server.sin_addr.s_addr = INADDR_ANY;
                    184:        else
                    185:                memcpy(&server.sin_addr.s_addr, ip, 4);
                    186:
                    187:        if (type == SOCK_STREAM)
                    188:                s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
                    189:        else                    /* type == SOCK_DGRAM */
                    190:                s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                    191:
                    192:        if (s == -1)
                    193:                goto err;
                    194: #if defined SOL_SOCKET && defined SO_REUSEADDR
                    195:        {
                    196:                int j = 1;
                    197:                setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                    198:                    (void *) &j, sizeof j);
                    199:        }
                    200: #endif
                    201:        if (bind(s, (struct sockaddr *) & server, sizeof(server)) == -1) {
                    202:                perror("bind");
                    203:                goto err;
                    204:        }
                    205:        /* Make it 128 for linux */
                    206:        if (type == SOCK_STREAM && listen(s, 128) == -1)
                    207:                goto err;
                    208:        *sock = s;
                    209:        ret = 1;
                    210: err:
                    211:        if ((ret == 0) && (s != -1)) {
                    212:                shutdown(s, SHUT_RD);
                    213:                close(s);
                    214:        }
                    215:        return (ret);
                    216: }
                    217:
                    218: static int
                    219: init_server(int *sock, int port, int type)
                    220: {
                    221:        return (init_server_long(sock, port, NULL, type));
                    222: }
                    223:
                    224: static int
                    225: do_accept(int acc_sock, int *sock, char **host)
                    226: {
                    227:        int ret;
                    228:        struct hostent *h1, *h2;
                    229:        static struct sockaddr_in from;
                    230:        socklen_t len;
                    231: /*     struct linger ling; */
                    232:
                    233: redoit:
                    234:
                    235:        memset((char *) &from, 0, sizeof(from));
                    236:        len = sizeof(from);
                    237:        ret = accept(acc_sock, (struct sockaddr *) & from, &len);
                    238:        if (ret == -1) {
                    239:                if (errno == EINTR) {
                    240:                        /* check_timeout(); */
                    241:                        goto redoit;
                    242:                }
                    243:                fprintf(stderr, "errno=%d ", errno);
                    244:                perror("accept");
                    245:                return (0);
                    246:        }
                    247: /*
                    248:        ling.l_onoff=1;
                    249:        ling.l_linger=0;
                    250:        i=setsockopt(ret,SOL_SOCKET,SO_LINGER,(char *)&ling,sizeof(ling));
                    251:        if (i < 0) { perror("linger"); return(0); }
                    252:        i=0;
                    253:        i=setsockopt(ret,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
                    254:        if (i < 0) { perror("keepalive"); return(0); }
                    255: */
                    256:
                    257:        if (host == NULL)
                    258:                goto end;
                    259:        h1 = gethostbyaddr((char *) &from.sin_addr.s_addr,
                    260:            sizeof(from.sin_addr.s_addr), AF_INET);
                    261:        if (h1 == NULL) {
                    262:                BIO_printf(bio_err, "bad gethostbyaddr\n");
                    263:                *host = NULL;
                    264:                /* return(0); */
                    265:        } else {
                    266:                if ((*host = strdup(h1->h_name)) == NULL) {
                    267:                        perror("strdup");
                    268:                        close(ret);
                    269:                        return (0);
                    270:                }
                    271:
                    272:                h2 = gethostbyname(*host);
                    273:                if (h2 == NULL) {
                    274:                        BIO_printf(bio_err, "gethostbyname failure\n");
                    275:                        close(ret);
                    276:                        return (0);
                    277:                }
                    278:                if (h2->h_addrtype != AF_INET) {
                    279:                        BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
                    280:                        close(ret);
                    281:                        return (0);
                    282:                }
                    283:        }
                    284:
                    285: end:
                    286:        *sock = ret;
                    287:        return (1);
                    288: }
                    289:
                    290: int
                    291: extract_host_port(char *str, char **host_ptr, unsigned char *ip,
                    292:     char **port_ptr)
                    293: {
                    294:        char *h, *p;
                    295:
                    296:        h = str;
                    297:        p = strrchr(str, '/');  /* IPv6 host/port */
                    298:        if (p == NULL) {
                    299:                p = strrchr(str, ':');
                    300:        }
                    301:        if (p == NULL) {
                    302:                BIO_printf(bio_err, "no port defined\n");
                    303:                return (0);
                    304:        }
                    305:        *(p++) = '\0';
                    306:
                    307:        if (host_ptr != NULL)
                    308:                *host_ptr = h;
                    309:
                    310:        if (port_ptr != NULL && p != NULL && *p != '\0')
                    311:                *port_ptr = p;
                    312:
                    313:        return (1);
                    314: }
                    315:
                    316: int
                    317: extract_port(char *str, short *port_ptr)
                    318: {
                    319:        int i;
                    320:        const char *errstr;
                    321:        struct servent *s;
                    322:
                    323:        i = strtonum(str, 1, 65535, &errstr);
                    324:        if (!errstr) {
                    325:                *port_ptr = (unsigned short) i;
                    326:        } else {
                    327:                s = getservbyname(str, "tcp");
                    328:                if (s == NULL) {
                    329:                        BIO_printf(bio_err, "getservbyname failure for %s\n", str);
                    330:                        return (0);
                    331:                }
                    332:                *port_ptr = ntohs((unsigned short) s->s_port);
                    333:        }
                    334:        return (1);
                    335: }