Ejemplo n.º 1
0
void set_nonblock(SOCKET fd, unsigned long nonblock) {
#if defined F_GETFL && defined F_SETFL && defined O_NONBLOCK && !defined __INNOTEK_LIBC__
    int err, flags;

    do {
        flags=fcntl(fd, F_GETFL, 0);
    } while(flags<0 && get_last_socket_error()==S_EINTR);
    if(flags<0) {
        sockerror("fcntl GETFL"); /* non-critical */
        return;
    }
    if(nonblock)
        flags|=O_NONBLOCK;
    else
        flags&=~O_NONBLOCK;
    do {
        err=fcntl(fd, F_SETFL, flags);
    } while(err<0 && get_last_socket_error()==S_EINTR);
    if(err<0)
        sockerror("fcntl SETFL"); /* non-critical */
#else /* WIN32 or similar */
    if(ioctlsocket(fd, (long)FIONBIO, &nonblock)<0)
        sockerror("ioctlsocket"); /* non-critical */
#if 0
    else
        s_log(LOG_DEBUG, "Socket %d set to %s mode",
            fd, nonblock ? "non-blocking" : "blocking");
#endif
#endif
}
Ejemplo n.º 2
0
static void init_local(CLI * c)
{
	SOCKADDR_UNION addr;
	socklen_t addr_len;
	char *accepted_address;

	
	addr_len = sizeof(SOCKADDR_UNION);
	c->local_rfd.is_socket =
	    !getpeername(c->local_rfd.fd, &addr.sa, &addr_len);
	if (c->local_rfd.is_socket) {
		memcpy(&c->peer_addr.sa, &addr.sa, addr_len);
		c->peer_addr_len = addr_len;
		if (set_socket_options(c->local_rfd.fd, 1))
			s_log(LOG_WARNING,
			      "Failed to set local socket options");
	} else {
		if (get_last_socket_error() != S_ENOTSOCK) {
			sockerror("getpeerbyname (local_rfd)");
			longjmp(c->err, 1);
		}
	}

	
	if (c->local_rfd.fd == c->local_wfd.fd) {
		c->local_wfd.is_socket = c->local_rfd.is_socket;
	} else {
		addr_len = sizeof(SOCKADDR_UNION);
		c->local_wfd.is_socket =
		    !getpeername(c->local_wfd.fd, &addr.sa, &addr_len);
		if (c->local_wfd.is_socket) {
			if (!c->local_rfd.is_socket) {	
				memcpy(&c->peer_addr.sa, &addr.sa, addr_len);
				c->peer_addr_len = addr_len;
			}
			if (set_socket_options(c->local_wfd.fd, 1))
				s_log(LOG_WARNING,
				      "Failed to set local socket options");
		} else {
			if (get_last_socket_error() != S_ENOTSOCK) {
				sockerror("getpeerbyname (local_wfd)");
				longjmp(c->err, 1);
			}
		}
	}

	
	if (!c->local_rfd.is_socket && !c->local_rfd.is_socket) {
		s_log(LOG_NOTICE, "Service [%s] accepted connection",
		      c->opt->servname);
		return;
	}

	
	accepted_address = s_ntop(&c->peer_addr, c->peer_addr_len);
	auth_user(c, accepted_address);
	s_log(LOG_NOTICE, "Service [%s] accepted connection from %s",
	      c->opt->servname, accepted_address);
	str_free(accepted_address);
}
Ejemplo n.º 3
0
int make_sockets(SOCKET fd[2]) { /* make a pair of connected ipv4 sockets */
#ifdef INET_SOCKET_PAIR
    struct sockaddr_in addr;
    socklen_t addrlen;
    SOCKET s; /* temporary socket awaiting for connection */

    /* create two *blocking* sockets first */
    s=s_socket(AF_INET, SOCK_STREAM, 0, 0, "make_sockets: s_socket#1");
    if(s==INVALID_SOCKET)
        return 1;
    fd[1]=s_socket(AF_INET, SOCK_STREAM, 0, 0, "make_sockets: s_socket#2");
    if(fd[1]==INVALID_SOCKET) {
        closesocket(s);
        return 1;
    }

    addrlen=sizeof addr;
    memset(&addr, 0, sizeof addr);
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
    addr.sin_port=htons(0); /* dynamic port allocation */
    if(bind(s, (struct sockaddr *)&addr, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "make_sockets: bind#1");
    if(bind(fd[1], (struct sockaddr *)&addr, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "make_sockets: bind#2");

    if(listen(s, 1)) {
        sockerror("make_sockets: listen");
        closesocket(s);
        closesocket(fd[1]);
        return 1;
    }
    if(getsockname(s, (struct sockaddr *)&addr, &addrlen)) {
        sockerror("make_sockets: getsockname");
        closesocket(s);
        closesocket(fd[1]);
        return 1;
    }
    if(connect(fd[1], (struct sockaddr *)&addr, addrlen)) {
        sockerror("make_sockets: connect");
        closesocket(s);
        closesocket(fd[1]);
        return 1;
    }
    fd[0]=s_accept(s, (struct sockaddr *)&addr, &addrlen, 1,
        "make_sockets: s_accept");
    if(fd[0]==INVALID_SOCKET) {
        closesocket(s);
        closesocket(fd[1]);
        return 1;
    }
    closesocket(s); /* don't care about the result */
    set_nonblock(fd[0], 1);
    set_nonblock(fd[1], 1);
#else
    if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "make_sockets: socketpair"))
        return 1;
#endif
    return 0;
}
Ejemplo n.º 4
0
int s_connect(CLI *c, SOCKADDR_UNION *addr, socklen_t addrlen) {
    int error;
    char *dst;

    dst=s_ntop(addr, addrlen);
    s_log(LOG_INFO, "s_connect: connecting %s", dst);

    if(!connect(c->fd, &addr->sa, addrlen)) {
        s_log(LOG_NOTICE, "s_connect: connected %s", dst);
        str_free(dst);
        return 0; /* no error -> success (on some OSes over the loopback) */
    }
    error=get_last_socket_error();
    if(error!=S_EINPROGRESS && error!=S_EWOULDBLOCK) {
        s_log(LOG_ERR, "s_connect: connect %s: %s (%d)",
            dst, s_strerror(error), error);
        str_free(dst);
        return -1;
    }

    s_log(LOG_DEBUG, "s_connect: s_poll_wait %s: waiting %d seconds",
        dst, c->opt->timeout_connect);
    s_poll_init(c->fds);
    s_poll_add(c->fds, c->fd, 1, 1);
    switch(s_poll_wait(c->fds, c->opt->timeout_connect, 0)) {
    case -1:
        error=get_last_socket_error();
        s_log(LOG_ERR, "s_connect: s_poll_wait %s: %s (%d)",
            dst, s_strerror(error), error);
        str_free(dst);
        return -1;
    case 0:
        s_log(LOG_ERR, "s_connect: s_poll_wait %s:"
            " TIMEOUTconnect exceeded", dst);
        str_free(dst);
        return -1;
    default:
        error=get_socket_error(c->fd);
        if(error) {
            s_log(LOG_ERR, "s_connect: connect %s: %s (%d)",
               dst, s_strerror(error), error);
            str_free(dst);
            return -1;
        }
        if(s_poll_canwrite(c->fds, c->fd)) {
            s_log(LOG_NOTICE, "s_connect: connected %s", dst);
            str_free(dst);
            return 0; /* success */
        }
        s_log(LOG_ERR, "s_connect: s_poll_wait %s: internal error",
            dst);
        str_free(dst);
        return -1;
    }
    return -1; /* should not be possible */
}
Ejemplo n.º 5
0
Archivo: client.c Proyecto: l7s/stunnel
static void make_sockets(CLI *c, int fd[2]) { /* make a pair of connected sockets */
#ifdef INET_SOCKET_PAIR
    SOCKADDR_UNION addr;
    socklen_t addrlen;
    int s; /* temporary socket awaiting for connection */

    s=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#1");
    if(s<0)
        longjmp(c->err, 1);
    c->fd=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#2");
    if(c->fd<0)
        longjmp(c->err, 1);

    addrlen=sizeof addr;
    memset(&addr, 0, addrlen);
    addr.in.sin_family=AF_INET;
    addr.in.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
    addr.in.sin_port=htons(0); /* dynamic port allocation */
    if(bind(s, &addr.sa, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "bind#1");
    if(bind(c->fd, &addr.sa, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "bind#2");

    if(listen(s, 1)) {
        closesocket(s);
        sockerror("listen");
        longjmp(c->err, 1);
    }
    if(getsockname(s, &addr.sa, &addrlen)) {
        closesocket(s);
        sockerror("getsockname");
        longjmp(c->err, 1);
    }
    if(connect_blocking(c, &addr, addr_len(addr))) {
        closesocket(s);
        longjmp(c->err, 1);
    }
    fd[0]=s_accept(s, &addr.sa, &addrlen, 1, "accept");
    if(fd[0]<0) {
        closesocket(s);
        longjmp(c->err, 1);
    }
    fd[1]=c->fd;
    c->fd=-1;
    closesocket(s); /* don't care about the result */
#else
    if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "socketpair"))
        longjmp(c->err, 1);
#endif
}
Ejemplo n.º 6
0
static int make_sockets(int fd[2]) { /* make a pair of connected sockets */
#ifdef INET_SOCKET_PAIR
    SOCKADDR_UNION addr;
    socklen_t addrlen;
    int s; /* temporary socket awaiting for connection */

    if((s=socket(AF_INET, SOCK_STREAM, 0))<0) {
        sockerror("socket#1");
        return -1;
    }
    if((fd[1]=socket(AF_INET, SOCK_STREAM, 0))<0) {
        sockerror("socket#2");
        return -1;
    }
    addrlen=sizeof(SOCKADDR_UNION);
    memset(&addr, 0, addrlen);
    addr.in.sin_family=AF_INET;
    addr.in.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
    addr.in.sin_port=0; /* dynamic port allocation */
    if(bind(s, &addr.sa, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "bind#1");
    if(bind(fd[1], &addr.sa, addrlen))
        log_error(LOG_DEBUG, get_last_socket_error(), "bind#2");
    if(listen(s, 5)) {
        sockerror("listen");
        return -1;
    }
    if(getsockname(s, &addr.sa, &addrlen)) {
        sockerror("getsockname");
        return -1;
    }
    if(connect(fd[1], &addr.sa, addrlen)) {
        sockerror("connect");
        return -1;
    }
    if((fd[0]=accept(s, &addr.sa, &addrlen))<0) {
        sockerror("accept");
        return -1;
    }
    closesocket(s); /* don't care about the result */
#else
    if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
        sockerror("socketpair");
        return -1;
    }
#endif
    return 0;
}
Ejemplo n.º 7
0
    /* returns 0 on close and 1 on non-critical errors */
static int parse_socket_error(CLI *c, const char *text) {
    switch(get_last_socket_error()) {
        /* http://tangentsoft.net/wskfaq/articles/bsd-compatibility.html */
    case 0: /* close on read, or close on write on WIN32 */
#ifndef USE_WIN32
    case EPIPE: /* close on write on Unix */
#endif
    case S_ECONNABORTED:
        s_log(LOG_INFO, "%s: Socket is closed", text);
        return 0;
    case S_EINTR:
        s_log(LOG_DEBUG, "%s: Interrupted by a signal: retrying", text);
        return 1;
    case S_EWOULDBLOCK:
        s_log(LOG_NOTICE, "%s: Would block: retrying", text);
        sleep(1); /* Microsoft bug KB177346 */
        return 1;
#if S_EAGAIN!=S_EWOULDBLOCK
    case S_EAGAIN:
        s_log(LOG_DEBUG,
            "%s: Temporary lack of resources: retrying", text);
        return 1;
#endif
    default:
        sockerror(text);
        longjmp(c->err, 1);
    }
}
Ejemplo n.º 8
0
int
win32_ioctl(int i, unsigned int u, char *data)
{
    u_long u_long_arg; 
    int retval;
    
    if (!wsock_started) {
        Perl_croak_nocontext("ioctl implemented only on sockets");
        /* NOTREACHED */
    }

    /* mauke says using memcpy avoids alignment issues */
    memcpy(&u_long_arg, data, sizeof u_long_arg); 
    retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg);
    memcpy(data, &u_long_arg, sizeof u_long_arg);
    
    if (retval == SOCKET_ERROR) {
        int err = get_last_socket_error();
        if (err == ENOTSOCK) {
            Perl_croak_nocontext("ioctl implemented only on sockets");
            /* NOTREACHED */
        }
        errno = err;
    }
    return retval;
}
Ejemplo n.º 9
0
int
my_fclose (FILE *pf)
{
    int osf;
    if (!wsock_started)		/* No WinSock? */
        return(fclose(pf));	/* Then not a socket. */
    osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */
    if (osf != -1) {
        int err;
        win32_fflush(pf);
        err = closesocket(osf);
        if (err == 0) {
            assert(_osfhnd(win32_fileno(pf)) == osf); /* catch a bad ioinfo struct def */
            /* don't close freed handle */
            _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE);
            return fclose(pf);
        }
        else if (err == SOCKET_ERROR) {
            err = get_last_socket_error();
            if (err != ENOTSOCK) {
                (void)fclose(pf);
                errno = err;
                return EOF;
            }
        }
    }
    return fclose(pf);
}
Ejemplo n.º 10
0
static int print_socket_options(void) {
    int fd, len;
    SOCK_OPT *ptr;
    OPT_UNION val;
    char line[STRLEN];

    fd=socket(AF_INET, SOCK_STREAM, 0);

    log_raw("Socket option defaults:");
    log_raw("    %-16s%-10s%-10s%-10s%-10s",
        "Option", "Accept", "Local", "Remote", "OS default");
    for(ptr=sock_opts; ptr->opt_str; ptr++) {
        /* display option name */
        sprintf(line, "    %-16s", ptr->opt_str);
        /* display stunnel default values */
        print_option(line, ptr->opt_type, ptr->opt_val[0]);
        print_option(line, ptr->opt_type, ptr->opt_val[1]);
        print_option(line, ptr->opt_type, ptr->opt_val[2]);
        /* display OS default value */
        len = sizeof(val);
        if(getsockopt(fd, ptr->opt_level, ptr->opt_name, (void *)&val, &len)) {
            if(get_last_socket_error()!=ENOPROTOOPT) {
                log_raw("%s", line); /* dump the name and assigned values */
                sockerror("getsockopt");
                return 0; /* FAILED */
            }
            safeconcat(line, "    --    "); /* write-only value */
        } else
            print_option(line, ptr->opt_type, &val);
        log_raw("%s", line);
    }
    return 1; /* OK */
}
Ejemplo n.º 11
0
static void local_bind(CLI * c)
{

	if (!c->bind_addr)
		return;
	if (ntohs(c->bind_addr->in.sin_port) >= 1024) {	
		
		if (!bind(c->fd, &c->bind_addr->sa, addr_len(c->bind_addr))) {
			s_log(LOG_INFO,
			      "local_bind succeeded on the original port");
			return;	
		}
		if (get_last_socket_error() != S_EADDRINUSE) {
			sockerror("local_bind (original port)");
			longjmp(c->err, 1);
		}
	}

	c->bind_addr->in.sin_port = htons(0);	
	if (!bind(c->fd, &c->bind_addr->sa, addr_len(c->bind_addr))) {
		s_log(LOG_INFO, "local_bind succeeded on an ephemeral port");
		return;		
	}
	sockerror("local_bind (ephemeral port)");
	longjmp(c->err, 1);
}
Ejemplo n.º 12
0
static int parse_socket_error(CLI * c, const char *text)
{
	switch (get_last_socket_error()) {
		
	case 0:		
	case EPIPE:		
	case S_ECONNABORTED:
		s_log(LOG_INFO, "%s: Socket is closed", text);
		return 0;
	case S_EINTR:
		s_log(LOG_DEBUG, "%s: Interrupted by a signal: retrying", text);
		return 1;
	case S_EWOULDBLOCK:
		s_log(LOG_NOTICE, "%s: Would block: retrying", text);
		sleep(1);	
		return 1;
#if S_EAGAIN!=S_EWOULDBLOCK
	case S_EAGAIN:
		s_log(LOG_DEBUG,
		      "%s: Temporary lack of resources: retrying", text);
		return 1;
#endif
	default:
		sockerror(text);
		longjmp(c->err, 1);
	}
}
Ejemplo n.º 13
0
void daemon_loop(void) {
    SERVICE_OPTIONS *opt;
    int temporary_lack_of_resources;

    while(1) {
        temporary_lack_of_resources=0;
        if(s_poll_wait(fds, -1, -1)>=0) {
            if(s_poll_canread(fds, signal_pipe[0]))
                if(signal_pipe_dispatch()) /* received SIGNAL_TERMINATE */
                    break; /* terminate daemon_loop */
            for(opt=service_options.next; opt; opt=opt->next)
                if(opt->option.accept && s_poll_canread(fds, opt->fd))
                    if(accept_connection(opt))
                        temporary_lack_of_resources=1;
        } else {
            log_error(LOG_NOTICE, get_last_socket_error(),
                "daemon_loop: s_poll_wait");
            temporary_lack_of_resources=1;
        }
        if(temporary_lack_of_resources) {
            s_log(LOG_NOTICE,
                "Accepting new connections suspended for 1 second");
            sleep(1); /* to avoid log trashing */
        }
    }
}
Ejemplo n.º 14
0
int s_poll_wait(s_poll_set *fds, int timeout) {
    int retval, retry;
    struct timeval tv, *tv_ptr;

    do { /* skip "Interrupted system call" errors */
        retry=0;
        memcpy(&fds->orfds, &fds->irfds, sizeof(fd_set));
        memcpy(&fds->owfds, &fds->iwfds, sizeof(fd_set));
        if(timeout<0) { /* infinite timeout */
            tv_ptr=NULL;
        } else {
            tv.tv_sec=timeout;
            tv.tv_usec=0;
            tv_ptr=&tv;
        }
        retval=select(fds->max+1, &fds->orfds, &fds->owfds, NULL, tv_ptr);
#ifndef USE_WIN32
        if(timeout<0 && retval>0 && s_poll_canread(fds, signal_pipe[0])) {
            signal_pipe_empty(); /* no timeout -> main loop */
            retry=1;
        }
#endif
    } while(retry || (retval<0 && get_last_socket_error()==EINTR));
    return retval;
}
Ejemplo n.º 15
0
/*-
 * BIO_accept_ex - Accept new incoming connections
 * @sock: the listening socket
 * @addr: the BIO_ADDR to store the peer address in
 * @options: BIO socket options, applied on the accepted socket.
 *
 */
int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
{
    socklen_t len;
    int accepted_sock;
    BIO_ADDR locaddr;
    BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;

    len = sizeof(*addr);
    accepted_sock = accept(accept_sock,
                           BIO_ADDR_sockaddr_noconst(addr), &len);
    if (accepted_sock == -1) {
        if (!BIO_sock_should_retry(accepted_sock)) {
            SYSerr(SYS_F_ACCEPT, get_last_socket_error());
            BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
        }
        return INVALID_SOCKET;
    }

    if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
        closesocket(accepted_sock);
        return INVALID_SOCKET;
    }

    return accepted_sock;
}
Ejemplo n.º 16
0
static int dgram_write(BIO *b, const char *in, int inl)
	{
	int ret;
	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
	clear_socket_error();

    if ( data->connected )
        ret=writesocket(b->num,in,inl);
    else
#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
        ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer));
#else
        ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer));
#endif

	BIO_clear_retry_flags(b);
	if (ret <= 0)
		{
		if (BIO_sock_should_retry(ret))
			{
			BIO_set_retry_write(b);  
			data->_errno = get_last_socket_error();

#if 0 /* higher layers are responsible for querying MTU, if necessary */
			if ( data->_errno == EMSGSIZE)
				/* retrieve the new MTU */
				BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
#endif
			}
		}
	return(ret);
	}
Ejemplo n.º 17
0
int BIO_accept(int sock, char **ip_port)
{
    BIO_ADDR res;
    int ret = -1;

    ret = BIO_accept_ex(sock, &res, 0);
    if (ret == (int)INVALID_SOCKET) {
        if (BIO_sock_should_retry(ret)) {
            ret = -2;
            goto end;
        }
        SYSerr(SYS_F_ACCEPT, get_last_socket_error());
        BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
        goto end;
    }

    if (ip_port != NULL) {
        char *host = BIO_ADDR_hostname_string(&res, 1);
        char *port = BIO_ADDR_service_string(&res, 1);
        *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
        strcpy(*ip_port, host);
        strcat(*ip_port, ":");
        strcat(*ip_port, port);
        OPENSSL_free(host);
        OPENSSL_free(port);
    }

 end:
    return ret;
}
Ejemplo n.º 18
0
int BIO_fd_should_retry(int i)
#endif
	{
	int err;

	if ((i == 0) || (i == -1))
		{
#ifndef BIO_FD
		err=get_last_socket_error();
#else
		err=get_last_sys_error();
#endif

#if defined(WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */
		if ((i == -1) && (err == 0))
			return(1);
#endif

#ifndef BIO_FD
		return(BIO_sock_non_fatal_error(err));
#else
		return(BIO_fd_non_fatal_error(err));
#endif
		}
	return(0);
	}
Ejemplo n.º 19
0
static int dgram_read(BIO *b, char *out, int outl)
	{
	int ret=0;
	bio_dgram_data *data = (bio_dgram_data *)b->ptr;

	struct sockaddr peer;
	int peerlen = sizeof(peer);

	if (out != NULL)
		{
		clear_socket_error();
		memset(&peer, 0x00, peerlen);
		/* Last arg in recvfrom is signed on some platforms and
		 * unsigned on others. It is of type socklen_t on some
		 * but this is not universal. Cast to (void *) to avoid
		 * compiler warnings.
		 */
		ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen);

		if ( ! data->connected  && ret > 0)
			BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer);

		BIO_clear_retry_flags(b);
		if (ret <= 0)
			{
			if (BIO_dgram_should_retry(ret))
				{
				BIO_set_retry_read(b);
				data->_errno = get_last_socket_error();
				}
			}
		}
	return(ret);
	}
Ejemplo n.º 20
0
int BIO_sock_info(int sock,
                  enum BIO_sock_info_type type, union BIO_sock_info_u *info)
{
    switch (type) {
    case BIO_SOCK_INFO_ADDRESS:
        {
            socklen_t addr_len;
            int ret = 0;
            addr_len = sizeof(*info->addr);
            ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
                              &addr_len);
            if (ret == -1) {
                SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error());
                BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR);
                return 0;
            }
            if ((size_t)addr_len > sizeof(*info->addr)) {
                BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
                return 0;
            }
        }
        break;
    default:
        BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE);
        return 0;
    }
    return 1;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
static int connect_remote(CLI *c) { /* connect to remote host */
    SOCKADDR_UNION bind_addr, addr;
    SOCKADDR_LIST resolved_list, *address_list;
    int error;
    int s; /* destination socket */
    u16 i;

    /* setup address_list */
    if(c->opt->option.delayed_lookup) {
        resolved_list.num=0;
        if(!name2addrlist(&resolved_list,
                c->opt->remote_address, DEFAULT_LOOPBACK))
            return -1; /* no host resolved */
        address_list=&resolved_list;
    } else /* use pre-resolved addresses */
        address_list=&c->opt->remote_addr;

    /* try to connect each host from the list */
    for(i=0; i<address_list->num; i++) {
        memcpy(&addr, address_list->addr + address_list->cur,
            sizeof(SOCKADDR_UNION));
        address_list->cur=(address_list->cur+1)%address_list->num;
        /* race condition is possible, but harmless in this case */

        if((s=socket(addr.sa.sa_family, SOCK_STREAM, 0))<0) {
            sockerror("remote socket");
            return -1;
        }
        if(alloc_fd(s))
            return -1;

        if(c->bind_addr.num) { /* explicit local bind or transparent proxy */
            memcpy(&bind_addr, &c->bind_addr.addr[0], sizeof(SOCKADDR_UNION));
            if(bind(s, &bind_addr.sa, addr_len(bind_addr))<0) {
                sockerror("bind transparent");
                closesocket(s);
                return -1;
            }
        }

        /* try to connect for the 1st time */
        s_ntop(c->connecting_address, &addr);
        s_log(LOG_DEBUG, "%s connecting %s",
            c->opt->servname, c->connecting_address);
        if(!connect(s, &addr.sa, addr_len(addr)))
            return s; /* no error -> success (should not be possible) */
        error=get_last_socket_error();
        if(error!=EINPROGRESS && error!=EWOULDBLOCK) {
            s_log(LOG_ERR, "remote connect (%s): %s (%d)",
                c->connecting_address, my_strerror(error), error);
            closesocket(s);
            continue; /* next IP */
        }
        if(!connect_wait(c, s, c->opt->timeout_connect))
            return s; /* success! */
        closesocket(s); /* error -> next IP */
    }
    return -1;
}
Ejemplo n.º 23
0
NOEXPORT int get_socket_error(const int fd) {
    int err;
    socklen_t optlen=sizeof err;

    if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &optlen))
        err=get_last_socket_error(); /* failed -> ask why */
    return err==S_ENOTSOCK ? 0 : err;
}
Ejemplo n.º 24
0
int s_poll_wait(s_poll_set *fds, int sec, int msec) {
    int retval;

    do { /* skip "Interrupted system call" errors */
        retval=poll(fds->ufds, fds->nfds, sec<0 ? -1 : 1000*sec+msec);
    } while(retval<0 && get_last_socket_error()==S_EINTR);
    return retval;
}
Ejemplo n.º 25
0
static void reset(int fd, char *txt) { /* set lingering on a socket */
    struct linger l;

    l.l_onoff=1;
    l.l_linger=0;
    if(setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof l))
        log_error(LOG_DEBUG, get_last_socket_error(), txt);
}
Ejemplo n.º 26
0
int BIO_get_port(const char *str, unsigned short *port_ptr)
	{
	int i;
	struct servent *s;

	if (str == NULL)
		{
		BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
		return(0);
		}
	i=atoi(str);
	if (i != 0)
		*port_ptr=(unsigned short)i;
	else
		{
		CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
		/* Note: under VMS with SOCKETSHR, it seems like the first
		 * parameter is 'char *', instead of 'const char *'
		 */
 		s=getservbyname(
#ifndef CONST_STRICT
		    (char *)
#endif
		    str,"tcp");
		if(s != NULL)
			*port_ptr=ntohs((unsigned short)s->s_port);
		CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
		if(s == NULL)
			{
			if (strcmp(str,"http") == 0)
				*port_ptr=80;
			else if (strcmp(str,"telnet") == 0)
				*port_ptr=23;
			else if (strcmp(str,"socks") == 0)
				*port_ptr=1080;
			else if (strcmp(str,"https") == 0)
				*port_ptr=443;
			else if (strcmp(str,"ssl") == 0)
				*port_ptr=443;
			else if (strcmp(str,"ftp") == 0)
				*port_ptr=21;
			else if (strcmp(str,"gopher") == 0)
				*port_ptr=70;
#if 0
			else if (strcmp(str,"wais") == 0)
				*port_ptr=21;
#endif
			else
				{
				SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
				ERR_add_error_data(3,"service='",str,"'");
				return(0);
				}
			}
		}
	return(1);
	}
Ejemplo n.º 27
0
static int auth_user(CLI *c) {
    struct servent *s_ent;    /* structure for getservbyname */
    SOCKADDR_UNION ident;     /* IDENT socket name */
    int fd;                   /* IDENT socket descriptor */
    char name[STRLEN];
    int retval;
    int error;

    if(!c->opt->username)
        return 0; /* -u option not specified */
    if((fd=socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM, 0))<0) {
        sockerror("socket (auth_user)");
        return -1;
    }
    if(alloc_fd(fd))
        return -1;
    memcpy(&ident, &c->peer_addr.addr[0], sizeof(SOCKADDR_UNION));
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(connect(fd, &ident.sa, addr_len(ident))) {
        error=get_last_socket_error();
        if(error!=EINPROGRESS && error!=EWOULDBLOCK) {
            sockerror("ident connect (auth_user)");
            closesocket(fd);
            return -1;
        }
        if(connect_wait(c, fd, c->opt->timeout_connect)) { /* error */
            closesocket(fd);
            return -1;
        }
    }
    s_log(LOG_DEBUG, "IDENT server connected");
    if(fdprintf(c, fd, "%u , %u",
            ntohs(c->peer_addr.addr[0].in.sin_port),
            ntohs(c->opt->local_addr.addr[0].in.sin_port))<0) {
        sockerror("fdprintf (auth_user)");
        closesocket(fd);
        return -1;
    }
    if(fdscanf(c, fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) {
        s_log(LOG_ERR, "Incorrect data from IDENT server");
        closesocket(fd);
        return -1;
    }
    closesocket(fd);
    retval=strcmp(name, c->opt->username) ? -1 : 0;
    safestring(name);
    s_log(LOG_INFO, "IDENT resolved remote user to %s", name);
    return retval;
}
Ejemplo n.º 28
0
int BIO_sock_should_retry(int i)
{
    int err;

    if ((i == 0) || (i == -1)) {
        err = get_last_socket_error();

        return (BIO_sock_non_fatal_error(err));
    }
    return (0);
}
static int dgram_read(BIO *b, char *out, int outl)
	{
	int ret=0;
	bio_dgram_data *data = (bio_dgram_data *)b->ptr;

	struct	{
	/*
	 * See commentary in b_sock.c. <appro>
	 */
	union	{ size_t s; int i; } len;
	union	{
		struct TINYCLR_SSL_SOCKADDR sa;
		struct TINYCLR_SSL_SOCKADDR_IN sa_in;
#if OPENSSL_USE_IPV6
		struct sockaddr_in6 sa_in6;
#endif
		} peer;
	} sa;

	sa.len.s=0;
	sa.len.i=sizeof(sa.peer);

	if (out != NULL)
		{
		clear_socket_error();
		TINYCLR_SSL_MEMSET(&sa.peer, 0x00, sizeof(sa.peer));
		dgram_adjust_rcv_timeout(b);
#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_ARM) || defined(OPENSSL_SYS_SH)
		ret=TINYCLR_SSL_RECVFROM(b->num,out,outl,0,&sa.peer.sa,(int *)&sa.len);
#else
		ret=TINYCLR_SSL_RECVFROM(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len);
#endif
		if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0)
			{
			OPENSSL_assert(sa.len.s<=sizeof(sa.peer));
			sa.len.i = (int)sa.len.s;
			}
		dgram_reset_rcv_timeout(b);

		if ( ! data->connected  && ret >= 0)
			BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);

		BIO_clear_retry_flags(b);
		if (ret < 0)
			{
			if (BIO_dgram_should_retry(ret))
				{
				BIO_set_retry_read(b);
				data->_errno = get_last_socket_error();
				}
			}
		}
	return(ret);
	}
Ejemplo n.º 30
0
/*-
 * BIO_connect - connect to an address
 * @sock: the socket to connect with
 * @addr: the address to connect to
 * @options: BIO socket options
 *
 * Connects to the address using the given socket and options.
 *
 * Options can be a combination of the following:
 * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
 * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
 * - BIO_SOCK_NODELAY: don't delay small messages.
 *
 * options holds BIO socket options that can be used
 * You should call this for every address returned by BIO_lookup
 * until the connection is successful.
 *
 * Returns 1 on success or 0 on failure.  On failure errno is set
 * and an error status is added to the OpenSSL error stack.
 */
int BIO_connect(int sock, const BIO_ADDR *addr, int options)
{
    const int on = 1;

    if (sock == -1) {
        BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
        return 0;
    }

    if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
        return 0;

    if (options & BIO_SOCK_KEEPALIVE) {
        if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
                       (const void *)&on, sizeof(on)) != 0) {
            SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
            BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
            return 0;
        }
    }

    if (options & BIO_SOCK_NODELAY) {
        if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
                       (const void *)&on, sizeof(on)) != 0) {
            SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
            BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
            return 0;
        }
    }

    if (connect(sock, BIO_ADDR_sockaddr(addr),
                BIO_ADDR_sockaddr_size(addr)) == -1) {
        if (!BIO_sock_should_retry(-1)) {
            SYSerr(SYS_F_CONNECT, get_last_socket_error());
            BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
        }
        return 0;
    }
    return 1;
}