Example #1
0
int BIO_get_host_ip(const char *str, unsigned char *ip)
{
    BIO_ADDRINFO *res = NULL;
    int ret = 0;

    if (BIO_sock_init() != 1)
        return 0;               /* don't generate another error code here */

    if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
        size_t l;

        if (BIO_ADDRINFO_family(res) != AF_INET) {
            BIOerr(BIO_F_BIO_GET_HOST_IP,
                   BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
        } else {
            BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l);
            /* Because only AF_INET addresses will reach this far,
               we can assert that l should be 4 */
            OPENSSL_assert(l == 4);

            BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
            ret = 1;
        }
        BIO_ADDRINFO_free(res);
    } else {
        ERR_add_error_data(2, "host=", str);
    }

    return ret;
}
Example #2
0
static int tcp_connect(char *host, char *port) {
	int error, sd = -1;
	struct addrinfo hints, *res, *r;

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;

#ifdef _MSC_VER
	if (BIO_sock_init() != 1)
		exit(-1);
#endif

	error = getaddrinfo(host, port, &hints, &res);
	if (error != 0) {
		perror("getaddrinfo()");
		exit(-1);
	}

	for (r = res; r != NULL; r = r->ai_next) {
		sd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
		if (sd == -1)
			continue;

		if (connect(sd, r->ai_addr, r->ai_addrlen) == 0)
			break;

		close(sd);
	}

	freeaddrinfo(res);

	return sd;
}
Example #3
0
int BIO_get_port(const char *str, unsigned short *port_ptr)
{
    BIO_ADDRINFO *res = NULL;
    int ret = 0;

    if (str == NULL) {
        BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED);
        return (0);
    }

    if (BIO_sock_init() != 1)
        return 0;               /* don't generate another error code here */

    if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
        if (BIO_ADDRINFO_family(res) != AF_INET) {
            BIOerr(BIO_F_BIO_GET_PORT,
                   BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
        } else {
            *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
            ret = 1;
        }
        BIO_ADDRINFO_free(res);
    } else {
        ERR_add_error_data(2, "host=", str);
    }

    return ret;
}
Example #4
0
int BIO_get_accept_socket(char *host, int bind_mode)
{
    int s = INVALID_SOCKET;
    char *h = NULL, *p = NULL;
    BIO_ADDRINFO *res = NULL;

    if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
        return INVALID_SOCKET;

    if (BIO_sock_init() != 1)
        return INVALID_SOCKET;

    if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
        goto err;

    if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
                        BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
        s = INVALID_SOCKET;
        goto err;
    }

    if (!BIO_listen(s, BIO_ADDRINFO_address(res),
                    bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
        BIO_closesocket(s);
        s = INVALID_SOCKET;
    }

 err:
    BIO_ADDRINFO_free(res);
    OPENSSL_free(h);
    OPENSSL_free(p);

    return s;
}
Example #5
0
/*-
 * addr_strings - helper function to get host and service names
 * @ap: the BIO_ADDR that has the input info
 * @numeric: 0 if actual names should be returned, 1 if the numeric
 * representation should be returned.
 * @hostname: a pointer to a pointer to a memory area to store the
 * host name or numeric representation.  Unused if NULL.
 * @service: a pointer to a pointer to a memory area to store the
 * service name or numeric representation.  Unused if NULL.
 *
 * The return value is 0 on failure, with the error code in the error
 * stack, and 1 on success.
 */
static int addr_strings(const BIO_ADDR *ap, int numeric,
                        char **hostname, char **service)
{
    if (BIO_sock_init() != 1)
        return 0;

    if (1) {
#ifdef AI_PASSIVE
        int ret = 0;
        char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
        int flags = 0;

        if (numeric)
            flags |= NI_NUMERICHOST | NI_NUMERICSERV;

        if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
                               BIO_ADDR_sockaddr_size(ap),
                               host, sizeof(host), serv, sizeof(serv),
                               flags)) != 0) {
# ifdef EAI_SYSTEM
            if (ret == EAI_SYSTEM) {
                SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
                BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
            } else
# endif
            {
                BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
                ERR_add_error_data(1, gai_strerror(ret));
            }
            return 0;
        }

        /* VMS getnameinfo() has a bug, it doesn't fill in serv, which
         * leaves it with whatever garbage that happens to be there.
         * However, we initialise serv with the empty string (serv[0]
         * is therefore NUL), so it gets real easy to detect when things
         * didn't go the way one might expect.
         */
        if (serv[0] == '\0') {
            BIO_snprintf(serv, sizeof(serv), "%d",
                         ntohs(BIO_ADDR_rawport(ap)));
        }

        if (hostname)
            *hostname = OPENSSL_strdup(host);
        if (service)
            *service = OPENSSL_strdup(serv);
    } else {
#endif
        if (hostname)
            *hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
        if (service) {
            char serv[6];        /* port is 16 bits => max 5 decimal digits */
            BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
            *service = OPENSSL_strdup(serv);
        }
    }

    return 1;
}
Example #6
0
int BIO_get_host_ip(const char *str, unsigned char *ip)
	{
	int i;
	int err = 1;
	int locked = 0;
	struct hostent *he;

	i=get_ip(str,ip);
	if (i < 0)
		{
		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
		goto err;
		}

	/* At this point, we have something that is most probably correct
	   in some way, so let's init the socket. */
	if (BIO_sock_init() != 1)
		return 0; /* don't generate another error code here */

	/* If the string actually contained an IP address, we need not do
	   anything more */
	if (i > 0) return(1);

	/* do a gethostbyname */
	CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
	locked = 1;
	he=BIO_gethostbyname(str);
	if (he == NULL)
		{
		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
		goto err;
		}

	/* cast to short because of win16 winsock definition */
	if ((short)he->h_addrtype != AF_INET)
		{
		BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
		goto err;
		}
	for (i=0; i<4; i++)
		ip[i]=he->h_addr_list[0][i];
	err = 0;

 err:
	if (locked)
		CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
	if (err)
		{
		ERR_add_error_data(2,"host=",str);
		return 0;
		}
	else
		return 1;
	}
Example #7
0
/*-
 * addr_strings - helper function to get host and service names
 * @ap: the BIO_ADDR that has the input info
 * @numeric: 0 if actual names should be returned, 1 if the numeric
 * representation should be returned.
 * @hostname: a pointer to a pointer to a memory area to store the
 * host name or numeric representation.  Unused if NULL.
 * @service: a pointer to a pointer to a memory area to store the
 * service name or numeric representation.  Unused if NULL.
 *
 * The return value is 0 on failure, with the error code in the error
 * stack, and 1 on success.
 */
static int addr_strings(const BIO_ADDR *ap, int numeric,
                        char **hostname, char **service)
{
    if (BIO_sock_init() != 1)
        return 0;

    if (1) {
#ifdef AI_PASSIVE
        int ret = 0;
        char host[NI_MAXHOST], serv[NI_MAXSERV];
        int flags = 0;

        if (numeric)
            flags |= NI_NUMERICHOST | NI_NUMERICSERV;

        if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
                               BIO_ADDR_sockaddr_size(ap),
                               host, sizeof(host), serv, sizeof(serv),
                               flags)) != 0) {
# ifdef EAI_SYSTEM
            if (ret == EAI_SYSTEM) {
                SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
                BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
            } else
# endif
            {
                BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
                ERR_add_error_data(1, gai_strerror(ret));
            }
            return 0;
        }
        if (hostname)
            *hostname = OPENSSL_strdup(host);
        if (service)
            *service = OPENSSL_strdup(serv);
    } else {
#endif
        if (hostname)
            *hostname = OPENSSL_strdup(inet_ntoa(ap->sin.sin_addr));
        if (service) {
            char serv[6];        /* port is 16 bits => max 5 decimal digits */
            BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->sin.sin_port));
            *service = OPENSSL_strdup(serv);
        }
    }

    return 1;
}
Example #8
0
/*-
 * BIO_socket - create a socket
 * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
 * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
 * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
 * @options: BIO socket options (currently unused)
 *
 * Creates a socket.  This should be called before calling any
 * of BIO_connect and BIO_listen.
 *
 * Returns the file descriptor on success or INVALID_SOCKET on failure.  On
 * failure errno is set, and a status is added to the OpenSSL error stack.
 */
int BIO_socket(int domain, int socktype, int protocol, int options)
{
    int sock = -1;

    if (BIO_sock_init() != 1)
        return INVALID_SOCKET;

    sock = socket(domain, socktype, protocol);
    if (sock == -1) {
        SYSerr(SYS_F_SOCKET, get_last_socket_error());
        BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
        return INVALID_SOCKET;
    }

    return sock;
}
Example #9
0
int
tls_init(void)
{
	if (tls_initialised)
		return (0);

#ifdef USE_LIBSSL_INTERNALS
	SSL_load_error_strings();
	SSL_library_init();

	if (BIO_sock_init() != 1)
		return (-1);
#endif

	if ((tls_config_default = tls_config_new()) == NULL)
		return (-1);

	tls_initialised = 1;

	return (0);
}
Example #10
0
int
tls_init(void)
{
	static int tls_initialised = 0;

	if (tls_initialised)
		return (0);

	SSL_load_error_strings();
	SSL_library_init();

	if (BIO_sock_init() != 1)
		return (-1);

	if ((tls_config_default = tls_config_new()) == NULL)
		return (-1);

	tls_initialised = 1;

	return (0);
}
Example #11
0
int
BIO_get_accept_socket(char *host, int bind_mode)
{
	int ret = 0;
	union {
		struct sockaddr sa;
		struct sockaddr_in sa_in;
		struct sockaddr_in6 sa_in6;
	} server, client;
	int s = -1, cs, addrlen;
	unsigned char ip[4];
	unsigned short port;
	char *str = NULL, *e;
	char *h, *p;
	unsigned long l;
	int err_num;

	if (BIO_sock_init() != 1)
		return (-1);

	if ((str = BUF_strdup(host)) == NULL)
		return (-1);

	h = p = NULL;
	h = str;
	for (e = str; *e; e++) {
		if (*e == ':') {
			p = e;
		} else if (*e == '/') {
			*e = '\0';
			break;
		}
	}
	if (p)
		*p++='\0';	/* points at last ':', '::port' is special [see below] */
	else
		p = h, h = NULL;

#ifdef EAI_FAMILY
	do {
		struct addrinfo *res, hint;

		/* '::port' enforces IPv6 wildcard listener. Some OSes,
		 * e.g. Solaris, default to IPv6 without any hint. Also
		 * note that commonly IPv6 wildchard socket can service
		 * IPv4 connections just as well...  */
		memset(&hint, 0, sizeof(hint));
		hint.ai_flags = AI_PASSIVE;
		if (h) {
			if (strchr(h, ':')) {
				if (h[1] == '\0')
					h = NULL;
				hint.ai_family = AF_INET6;
			} else if (h[0] == '*' && h[1] == '\0') {
				hint.ai_family = AF_INET;
				h = NULL;
			}
		}

		if (getaddrinfo(h, p, &hint, &res))
			break;

		addrlen = res->ai_addrlen <= sizeof(server) ?
		    res->ai_addrlen : sizeof(server);
		memcpy(&server, res->ai_addr, addrlen);

		freeaddrinfo(res);
		goto again;
	} while (0);
#endif

	if (!BIO_get_port(p, &port))
		goto err;

	memset((char *)&server, 0, sizeof(server));
	server.sa_in.sin_family = AF_INET;
	server.sa_in.sin_port = htons(port);
	addrlen = sizeof(server.sa_in);

	if (h == NULL || strcmp(h, "*") == 0)
		server.sa_in.sin_addr.s_addr = INADDR_ANY;
	else {
		if (!BIO_get_host_ip(h, &(ip[0])))
			goto err;
		l = (unsigned long)((unsigned long)ip[0]<<24L)|
		    ((unsigned long)ip[1]<<16L)|
		    ((unsigned long)ip[2]<< 8L)|
		    ((unsigned long)ip[3]);
		server.sa_in.sin_addr.s_addr = htonl(l);
	}

again:
	s = socket(server.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL);
	if (s == -1) {
		SYSerr(SYS_F_SOCKET, errno);
		ERR_asprintf_error_data("port='%s'", host);
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
		goto err;
	}

#ifdef SO_REUSEADDR
	if (bind_mode == BIO_BIND_REUSEADDR) {
		int i = 1;

		ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i));
		bind_mode = BIO_BIND_NORMAL;
	}
#endif
	if (bind(s, &server.sa, addrlen) == -1) {
#ifdef SO_REUSEADDR
		err_num = errno;
		if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
		    (err_num == EADDRINUSE)) {
			client = server;
			if (h == NULL || strcmp(h, "*") == 0) {
				if (client.sa.sa_family == AF_INET6) {
					memset(&client.sa_in6.sin6_addr, 0, sizeof(client.sa_in6.sin6_addr));
					client.sa_in6.sin6_addr.s6_addr[15] = 1;
				} else if (client.sa.sa_family == AF_INET) {
					client.sa_in.sin_addr.s_addr = htonl(0x7F000001);
				} else
					goto err;
			}
			cs = socket(client.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL);
			if (cs != -1) {
				int ii;
				ii = connect(cs, &client.sa, addrlen);
				close(cs);
				if (ii == -1) {
					bind_mode = BIO_BIND_REUSEADDR;
					close(s);
					goto again;
				}
				/* else error */
			}
			/* else error */
		}
#endif
		SYSerr(SYS_F_BIND, err_num);
		ERR_asprintf_error_data("port='%s'", host);
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_BIND_SOCKET);
		goto err;
	}
	if (listen(s, MAX_LISTEN) == -1) {
		SYSerr(SYS_F_BIND, errno);
		ERR_asprintf_error_data("port='%s'", host);
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_LISTEN_SOCKET);
		goto err;
	}
	ret = 1;
err:
	free(str);
	if ((ret == 0) && (s != -1)) {
		close(s);
		s = -1;
	}
	return (s);
}
Example #12
0
int
main(int argc, char **argv)
{
	ARGS arg;
#define PROG_NAME_SIZE	39
	char pname[PROG_NAME_SIZE + 1];
	FUNCTION f, *fp;
	const char *prompt;
	char buf[1024];
	char *to_free = NULL;
	int n, i, ret = 0;
	char *p;
	LHASH_OF(FUNCTION) * prog = NULL;
	long errline;

	arg.data = NULL;
	arg.count = 0;

	if (pledge("stdio cpath wpath rpath inet dns proc flock tty", NULL) == -1) {
		fprintf(stderr, "openssl: pledge: %s\n", strerror(errno));
		exit(1);
	}

	bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
	if (bio_err == NULL) {
		fprintf(stderr, "openssl: failed to initialise bio_err\n");
		exit(1);
	}

	if (BIO_sock_init() != 1) {
		BIO_printf(bio_err, "BIO_sock_init failed\n");
		exit(1);
	}

	CRYPTO_set_locking_callback(lock_dbg_cb);

	openssl_startup();

	/* Lets load up our environment a little */
	p = getenv("OPENSSL_CONF");
	if (p == NULL) {
		p = to_free = make_config_name();
		if (p == NULL) {
			BIO_printf(bio_err, "error making config file name\n");
			goto end;
		}
	}

	default_config_file = p;

	config = NCONF_new(NULL);
	i = NCONF_load(config, p, &errline);
	if (i == 0) {
		if (ERR_GET_REASON(ERR_peek_last_error()) ==
		    CONF_R_NO_SUCH_FILE) {
			BIO_printf(bio_err,
			    "WARNING: can't open config file: %s\n", p);
			ERR_clear_error();
			NCONF_free(config);
			config = NULL;
		} else {
			ERR_print_errors(bio_err);
			NCONF_free(config);
			exit(1);
		}
	}

	if (!load_config(bio_err, NULL)) {
		BIO_printf(bio_err, "failed to load configuration\n");
		goto end;
	}

	prog = prog_init();

	/* first check the program name */
	program_name(argv[0], pname, sizeof pname);

	f.name = pname;
	fp = lh_FUNCTION_retrieve(prog, &f);
	if (fp != NULL) {
		argv[0] = pname;

		single_execution = 1;
		ret = fp->func(argc, argv);
		goto end;
	}
	/*
	 * ok, now check that there are not arguments, if there are, run with
	 * them, shifting the ssleay off the front
	 */
	if (argc != 1) {
		argc--;
		argv++;

		single_execution = 1;
		ret = do_cmd(prog, argc, argv);
		if (ret < 0)
			ret = 0;
		goto end;
	}
	/* ok, lets enter the old 'OpenSSL>' mode */

	for (;;) {
		ret = 0;
		p = buf;
		n = sizeof buf;
		i = 0;
		for (;;) {
			p[0] = '\0';
			if (i++)
				prompt = ">";
			else
				prompt = "OpenSSL> ";
			fputs(prompt, stdout);
			fflush(stdout);
			if (!fgets(p, n, stdin))
				goto end;
			if (p[0] == '\0')
				goto end;
			i = strlen(p);
			if (i <= 1)
				break;
			if (p[i - 2] != '\\')
				break;
			i -= 2;
			p += i;
			n -= i;
		}
		if (!chopup_args(&arg, buf, &argc, &argv))
			break;

		ret = do_cmd(prog, argc, argv);
		if (ret < 0) {
			ret = 0;
			goto end;
		}
		if (ret != 0)
			BIO_printf(bio_err, "error in %s\n", argv[0]);
		(void) BIO_flush(bio_err);
	}
	BIO_printf(bio_err, "bad exit\n");
	ret = 1;

end:
	free(to_free);

	if (config != NULL) {
		NCONF_free(config);
		config = NULL;
	}
	if (prog != NULL)
		lh_FUNCTION_free(prog);
	free(arg.data);

	openssl_shutdown();

	if (bio_err != NULL) {
		BIO_free(bio_err);
		bio_err = NULL;
	}
	return (ret);
}
Example #13
0
int BIO_get_accept_socket(char *host, int bind_mode)
	{
	int ret=0;
	struct sockaddr_in server,client;
	int s=INVALID_SOCKET,cs;
	unsigned char ip[4];
	unsigned short port;
	char *str=NULL,*e;
	const char *h,*p;
	unsigned long l;
	int err_num;

	if (BIO_sock_init() != 1) return(INVALID_SOCKET);

	if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);

	h=p=NULL;
	h=str;
	for (e=str; *e; e++)
		{
		if (*e == ':')
			{
			p= &(e[1]);
			*e='\0';
			}
		else if (*e == '/')
			{
			*e='\0';
			break;
			}
		}

	if (p == NULL)
		{
		p=h;
		h="*";
		}

	if (!BIO_get_port(p,&port)) goto err;

	memset((char *)&server,0,sizeof(server));
	server.sin_family=AF_INET;
	server.sin_port=htons(port);

	if (strcmp(h,"*") == 0)
		server.sin_addr.s_addr=INADDR_ANY;
	else
		{
                if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
		l=(unsigned long)
			((unsigned long)ip[0]<<24L)|
			((unsigned long)ip[1]<<16L)|
			((unsigned long)ip[2]<< 8L)|
			((unsigned long)ip[3]);
		server.sin_addr.s_addr=htonl(l);
		}

again:
	s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
	if (s == INVALID_SOCKET)
		{
		SYSerr(SYS_F_SOCKET,get_last_socket_error());
		ERR_add_error_data(3,"port='",host,"'");
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
		goto err;
		}

#ifdef SO_REUSEADDR
	if (bind_mode == BIO_BIND_REUSEADDR)
		{
		int i=1;

		ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
		bind_mode=BIO_BIND_NORMAL;
		}
#endif
	if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
		{
#ifdef SO_REUSEADDR
		err_num=get_last_socket_error();
		if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
			(err_num == EADDRINUSE))
			{
			memcpy((char *)&client,(char *)&server,sizeof(server));
			if (strcmp(h,"*") == 0)
				client.sin_addr.s_addr=htonl(0x7F000001);
			cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
			if (cs != INVALID_SOCKET)
				{
				int ii;
				ii=connect(cs,(struct sockaddr *)&client,
					sizeof(client));
				closesocket(cs);
				if (ii == INVALID_SOCKET)
					{
					bind_mode=BIO_BIND_REUSEADDR;
					closesocket(s);
					goto again;
					}
				/* else error */
				}
			/* else error */
			}
#endif
		SYSerr(SYS_F_BIND,err_num);
		ERR_add_error_data(3,"port='",host,"'");
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
		goto err;
		}
	if (listen(s,MAX_LISTEN) == -1)
		{
		SYSerr(SYS_F_BIND,get_last_socket_error());
		ERR_add_error_data(3,"port='",host,"'");
		BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
		goto err;
		}
	ret=1;
err:
	if (str != NULL) OPENSSL_free(str);
	if ((ret == 0) && (s != INVALID_SOCKET))
		{
		closesocket(s);
		s= INVALID_SOCKET;
		}
	return(s);
	}
Example #14
0
/*-
 * BIO_lookup - look up the node and service you want to connect to.
 * @node: the node you want to connect to.
 * @service: the service you want to connect to.
 * @lookup_type: declare intent with the result, client or server.
 * @family: the address family you want to use.  Use AF_UNSPEC for any, or
 *  AF_INET, AF_INET6 or AF_UNIX.
 * @socktype: The socket type you want to use.  Can be SOCK_STREAM, SOCK_DGRAM
 *  or 0 for all.
 * @res: Storage place for the resulting list of returned addresses
 *
 * This will do a lookup of the node and service that you want to connect to.
 * It returns a linked list of different addresses you can try to connect to.
 *
 * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
 *
 * The return value is 1 on success or 0 in case of error.
 */
int BIO_lookup(const char *host, const char *service,
               enum BIO_lookup_type lookup_type,
               int family, int socktype, BIO_ADDRINFO **res)
{
    int ret = 0;                 /* Assume failure */

    switch(family) {
    case AF_INET:
#ifdef AF_INET6
    case AF_INET6:
#endif
#ifdef AF_UNIX
    case AF_UNIX:
#endif
#ifdef AF_UNSPEC
    case AF_UNSPEC:
#endif
        break;
    default:
        BIOerr(BIO_F_BIO_LOOKUP, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
        return 0;
    }

#ifdef AF_UNIX
    if (family == AF_UNIX) {
        if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
            return 1;
        else
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
        return 0;
    }
#endif

    if (BIO_sock_init() != 1)
        return 0;

    if (1) {
        int gai_ret = 0;
#ifdef AI_PASSIVE
        struct addrinfo hints;
        memset(&hints, 0, sizeof hints);

        hints.ai_family = family;
        hints.ai_socktype = socktype;

        if (lookup_type == BIO_LOOKUP_SERVER)
            hints.ai_flags |= AI_PASSIVE;

        /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
         * macro magic in bio_lcl.h
         */
        switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
# ifdef EAI_SYSTEM
        case EAI_SYSTEM:
            SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
            break;
# endif
        case 0:
            ret = 1;             /* Success */
            break;
        default:
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
            ERR_add_error_data(1, gai_strerror(gai_ret));
            break;
        }
    } else {
#endif
        const struct hostent *he;
        /*
         * Because struct hostent is defined for 32-bit pointers only with
         * VMS C, we need to make sure that '&he_fallback_address' and
         * '&he_fallback_addresses' are 32-bit pointers
         */
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
        /* Windows doesn't seem to have in_addr_t */
#ifdef OPENSSL_SYS_WINDOWS
        static uint32_t he_fallback_address;
        static const char *he_fallback_addresses[] =
        { (char *)&he_fallback_address, NULL };
#else
        static in_addr_t he_fallback_address;
        static const char *he_fallback_addresses[] =
        { (char *)&he_fallback_address, NULL };
#endif
        static const struct hostent he_fallback =
        {   NULL, NULL, AF_INET, sizeof(he_fallback_address),
            (char **)&he_fallback_addresses
        };
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif

        struct servent *se;
        /* Apparently, on WIN64, s_proto and s_port have traded places... */
#ifdef _WIN64
        struct servent se_fallback = { NULL, NULL, NULL, 0 };
#else
        struct servent se_fallback = { NULL, NULL, 0, NULL };
#endif

        if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
            ret = 0;
            goto err;
        }

        CRYPTO_THREAD_write_lock(bio_lookup_lock);
        he_fallback_address = INADDR_ANY;
        if (host == NULL) {
            he = &he_fallback;
            switch(lookup_type) {
            case BIO_LOOKUP_CLIENT:
                he_fallback_address = INADDR_LOOPBACK;
                break;
            case BIO_LOOKUP_SERVER:
                he_fallback_address = INADDR_ANY;
                break;
            default:
                OPENSSL_assert(("We forgot to handle a lookup type!" == 0));
                break;
            }
        } else {
            he = gethostbyname(host);

            if (he == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
                BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
                ERR_add_error_data(1, hstrerror(h_errno));
#else
                SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
#endif
                ret = 0;
                goto err;
            }
        }

        if (service == NULL) {
            se_fallback.s_port = 0;
            se_fallback.s_proto = NULL;
            se = &se_fallback;
        } else {
            char *endp = NULL;
            long portnum = strtol(service, &endp, 10);

            /*
             * Because struct servent is defined for 32-bit pointers only with
             * VMS C, we need to make sure that 'proto' is a 32-bit pointer.
             */
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
            char *proto = NULL;
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif

            switch (socktype) {
            case SOCK_STREAM:
                proto = "tcp";
                break;
            case SOCK_DGRAM:
                proto = "udp";
                break;
            }

            if (endp != service && *endp == '\0'
                    && portnum > 0 && portnum < 65536) {
                se_fallback.s_port = htons(portnum);
                se_fallback.s_proto = proto;
                se = &se_fallback;
            } else if (endp == service) {
                se = getservbyname(service, proto);

                if (se == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
                    BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
                    ERR_add_error_data(1, hstrerror(h_errno));
#else
                    SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
#endif
                    goto err;
                }
            } else {
                BIOerr(BIO_F_BIO_LOOKUP, BIO_R_MALFORMED_HOST_OR_SERVICE);
                goto err;
            }
        }

        *res = NULL;

        {
            /*
             * Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
             * we must make sure our iterator designates the same element type, hence
             * the pointer size dance.
             */
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
            char **addrlistp;
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
            size_t addresses;
            BIO_ADDRINFO *tmp_bai = NULL;

            /* The easiest way to create a linked list from an
               array is to start from the back */
            for(addrlistp = he->h_addr_list; *addrlistp != NULL;
                    addrlistp++)
                ;

            for(addresses = addrlistp - he->h_addr_list;
                    addrlistp--, addresses-- > 0; ) {
                if (!addrinfo_wrap(he->h_addrtype, socktype,
                                   *addrlistp, he->h_length,
                                   se->s_port, &tmp_bai))
                    goto addrinfo_malloc_err;
                tmp_bai->bai_next = *res;
                *res = tmp_bai;
                continue;
addrinfo_malloc_err:
                BIO_ADDRINFO_free(*res);
                *res = NULL;
                BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
                ret = 0;
                goto err;
            }

            ret = 1;
        }
err:
        CRYPTO_THREAD_unlock(bio_lookup_lock);
    }

    return ret;
}