Exemple #1
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;
}
Exemple #2
0
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
}
/* connect remote host */
NOEXPORT int connect_remote(CLI *c) {
    int fd, ind_start, ind_try, ind_cur;

    setup_connect_addr(c);
    ind_start=c->connect_addr.cur;
    /* the race condition here can be safely ignored */
    if(c->opt->failover==FAILOVER_RR)
        c->connect_addr.cur=(ind_start+1)%c->connect_addr.num;

    /* try to connect each host from the list */
    for(ind_try=0; ind_try<c->connect_addr.num; ind_try++) {
        ind_cur=(ind_start+ind_try)%c->connect_addr.num;
        c->fd=s_socket(c->connect_addr.addr[ind_cur].sa.sa_family,
            SOCK_STREAM, 0, 1, "remote socket");
        if(c->fd<0)
            longjmp(c->err, 1);

        local_bind(c); /* explicit local bind or transparent proxy */

        if(s_connect(c, &c->connect_addr.addr[ind_cur],
                addr_len(&c->connect_addr.addr[ind_cur]))) {
            closesocket(c->fd);
            c->fd=-1;
            continue; /* next IP */
        }
        print_bound_address(c);
        fd=c->fd;
        c->fd=-1;
        return fd; /* success! */
    }
    longjmp(c->err, 1);
    return -1; /* some C compilers require a return value */
}
Exemple #4
0
/* open new ports, update fds */
int bind_ports(void) {
    SERVICE_OPTIONS *opt;
    char *local_address;

#ifdef USE_LIBWRAP
    /* execute after parse_commandline() to know service_options.next,
     * but as early as possible to avoid leaking file descriptors */
    /* retry on each bind_ports() in case stunnel.conf was reloaded
       without "libwrap = no" */
    libwrap_init();
#endif /* USE_LIBWRAP */

    s_poll_init(fds);
    s_poll_add(fds, signal_pipe[0], 1, 0);

    /* allow clean unbind_ports() even though
       bind_ports() was not fully performed */
    for(opt=service_options.next; opt; opt=opt->next)
        if(opt->option.accept)
            opt->fd=-1;

    for(opt=service_options.next; opt; opt=opt->next) {
        if(opt->option.accept) {
            opt->fd=s_socket(opt->local_addr.sa.sa_family,
                SOCK_STREAM, 0, 1, "accept socket");
            if(opt->fd<0)
                return 1;
            if(set_socket_options(opt->fd, 0)<0) {
                closesocket(opt->fd);
                return 1;
            }
            /* local socket can't be unnamed */
            local_address=s_ntop(&opt->local_addr, addr_len(&opt->local_addr));
            if(bind(opt->fd, &opt->local_addr.sa, addr_len(&opt->local_addr))) {
                s_log(LOG_ERR, "Error binding service [%s] to %s",
                    opt->servname, local_address);
                sockerror("bind");
                closesocket(opt->fd);
                str_free(local_address);
                return 1;
            }
            if(listen(opt->fd, SOMAXCONN)) {
                sockerror("listen");
                closesocket(opt->fd);
                str_free(local_address);
                return 1;
            }
            s_poll_add(fds, opt->fd, 1, 0);
            s_log(LOG_DEBUG, "Service [%s] (FD=%d) bound to %s",
                opt->servname, opt->fd, local_address);
            str_free(local_address);
        } else if(opt->option.program && opt->option.remote) {
            /* create exec+connect services */
            create_client(-1, -1,
                alloc_client_session(opt, -1, -1), client_thread);
        }
    }
    return 0; /* OK */
}
Exemple #5
0
/** Create an unbound Socket object.
 *
 * \param name name of the object, used for debugging
 * \param is_tcp  true if TCP, false for UDP XXX: This should be more generic
 * \return a pointer to the SocketInt object, cast as a Socket, with a newly opened system socket
 * \see socket_free, socket_close
 */
Socket* socket_new(char* name, int is_tcp) {
  SocketInt* self = initialize(name);
  self->is_tcp = is_tcp;
  if (!s_socket(self)) {
    socket_free((Socket*)self);
    return NULL;
  }
  return (Socket*)self;
}
Exemple #6
0
static OCSP_RESPONSE *ocsp_get_response(CLI *c, OCSP_REQUEST *req) {
    BIO *bio=NULL;
    OCSP_REQ_CTX *req_ctx=NULL;
    OCSP_RESPONSE *resp=NULL;
    int err;

    /* connect specified OCSP server (responder) */
    c->fd=s_socket(c->opt->ocsp_addr.sa.sa_family, SOCK_STREAM, 0,
        1, "OCSP: socket (auth_user)");
    if(c->fd<0)
        goto cleanup;
    if(connect_blocking(c, &c->opt->ocsp_addr, addr_len(&c->opt->ocsp_addr)))
        goto cleanup;
    bio=BIO_new_fd(c->fd, BIO_NOCLOSE);
    if(!bio)
        goto cleanup;
    s_log(LOG_DEBUG, "OCSP: server connected");

    /* OCSP protocol communication loop */
    req_ctx=OCSP_sendreq_new(bio, c->opt->ocsp_path, req, -1);
    if(!req_ctx) {
        sslerror("OCSP: OCSP_sendreq_new");
        goto cleanup;
    }
    while(OCSP_sendreq_nbio(&resp, req_ctx)==-1) {
        s_poll_init(c->fds);
        s_poll_add(c->fds, c->fd, BIO_should_read(bio), BIO_should_write(bio));
        err=s_poll_wait(c->fds, c->opt->timeout_busy, 0);
        if(err==-1)
            sockerror("OCSP: s_poll_wait");
        if(err==0)
            s_log(LOG_INFO, "OCSP: s_poll_wait: TIMEOUTbusy exceeded");
        if(err<=0)
            goto cleanup;
    }
    /* s_log(LOG_DEBUG, "OCSP: context state: 0x%x", *(int *)req_ctx); */
    /* http://www.mail-archive.com/[email protected]/msg61691.html */
    if(!resp) {
        if(ERR_peek_error())
            sslerror("OCSP: OCSP_sendreq_nbio");
        else /* OpenSSL error: OCSP_sendreq_nbio does not use OCSPerr */
            s_log(LOG_ERR, "OCSP: OCSP_sendreq_nbio: OpenSSL internal error");
    }

cleanup:
    if(req_ctx)
        OCSP_REQ_CTX_free(req_ctx);
    if(bio)
        BIO_free_all(bio);
    if(c->fd>=0) {
        closesocket(c->fd);
        c->fd=-1; /* avoid double close on cleanup */
    }
    return resp;
}
Exemple #7
0
NOEXPORT int signal_pipe_init(void) {
#ifdef USE_WIN32
    if(make_sockets(signal_pipe))
        return 1;
#elif defined(__INNOTEK_LIBC__)
    /* Innotek port of GCC can not use select on a pipe:
     * use local socket instead */
    struct sockaddr_un un;
    fd_set set_pipe;
    int pipe_in;

    FD_ZERO(&set_pipe);
    signal_pipe[0]=s_socket(PF_OS2, SOCK_STREAM, 0, 0, "socket#1");
    signal_pipe[1]=s_socket(PF_OS2, SOCK_STREAM, 0, 0, "socket#2");

    /* connect the two endpoints */
    memset(&un, 0, sizeof un);
    un.sun_len=sizeof un;
    un.sun_family=AF_OS2;
    sprintf(un.sun_path, "\\socket\\stunnel-%u", getpid());
    /* make the first endpoint listen */
    bind(signal_pipe[0], (struct sockaddr *)&un, sizeof un);
    listen(signal_pipe[0], 1);
    connect(signal_pipe[1], (struct sockaddr *)&un, sizeof un);
    FD_SET(signal_pipe[0], &set_pipe);
    if(select(signal_pipe[0]+1, &set_pipe, NULL, NULL, NULL)>0) {
        pipe_in=signal_pipe[0];
        signal_pipe[0]=s_accept(signal_pipe[0], NULL, 0, 0, "accept");
        closesocket(pipe_in);
    } else {
        sockerror("select");
        return 1;
    }
#else /* Unix */
    if(s_pipe(signal_pipe, 1, "signal_pipe"))
        return 1;
#endif /* USE_WIN32 */
    return 0;
}
Exemple #8
0
/** Attempt to reconnect an OComm Socket.
 *
 * \param socket OComm socket
 * \return 0 on failure, the new socket number otherwise
 * \see s_connect
 */
int socket_reconnect(Socket* socket) {
  SocketInt* self = (SocketInt*)socket;

  if (self == NULL) {
    o_log(O_LOG_ERROR, "Missing socket definition\n");
    return 0;
  }

  if (!s_socket(self)) {
    return 0;
  }
  return s_connect(self, NULL, -1);
}
Exemple #9
0
static int connect_remote(CLI *c) { /* connect remote host */
    SOCKADDR_UNION addr;
    SOCKADDR_LIST resolved_list, *address_list;
    int fd, ind_try, ind_cur;

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

    /* try to connect each host from the list */
    for(ind_try=0; ind_try<address_list->num; ind_try++) {
        if(c->opt->failover==FAILOVER_RR) {
            ind_cur=address_list->cur;
            /* the race condition here can be safely ignored */
            address_list->cur=(ind_cur+1)%address_list->num;
        } else { /* FAILOVER_PRIO */
            ind_cur=ind_try; /* ignore address_list->cur */
        }
        memcpy(&addr, address_list->addr+ind_cur, sizeof addr);

        c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "remote socket");
        if(c->fd<0)
            longjmp(c->err, 1);

        if(c->bind_addr.num) /* explicit local bind or transparent proxy */
            local_bind(c);

        if(connect_blocking(c, &addr, addr_len(addr))) {
            closesocket(c->fd);
            c->fd=-1;
            continue; /* next IP */
        }
        print_bound_address(c);
        fd=c->fd;
        c->fd=-1;
        return fd; /* success! */
    }
    longjmp(c->err, 1);
    return -1; /* some C compilers require a return value */
}
user_asyn_tcp_client::ptr user_asyn_tcp_client::create(shared_io s_io,
                                                   const ip::tcp::endpoint &ep,
                                                   const std::string &auth_id,
                                                   const std::string &auth_pwd)
{
    // 创建socket对象
    shared_socket s_socket(new ip::tcp::socket(*s_io));

    // 创建本类对象
    user_asyn_tcp_client::ptr s_obj(new user_asyn_tcp_client(s_socket, s_io, ep, auth_id, auth_pwd));

    // 启动
    s_obj->start();

    // 返回本类对象
    return s_obj;
}
Exemple #11
0
void pkt_to_nowhere(void)
{
    sock *Conn = s_malloc(sizeof(sock));
    pkt *Pkt = pkt_alloc(500);
    uint32_t len = sizeof(Conn->local);
    Conn->sock = s_socket(SOCK_DOMAIN, SOCK_TYPE, DEFAULT_PROTOCOL);
    Conn->local.sin_family = SOCK_DOMAIN;
    Conn->local.sin_addr.s_addr = htonl(INADDR_ANY); //???
    Conn->local.sin_port = htons(DEFAULT_PORT);
    s_bind(Conn->sock, (struct sockaddr *)&(Conn->local),
           sizeof(Conn->local));
    s_getsockname(Conn->sock, (struct sockaddr *)&(Conn->local),
                  (socklen_t *)&len);

    create_pkt(Pkt, 0, 0, NULL, 0);
    send_pkt(Pkt, Conn->sock, Conn->local);
    shutdown(Conn->sock, SHUT_RDWR);
    free(Conn);
}
Exemple #12
0
sock *client_sock(char *remote_address, uint16_t remote_port,
                  uint32_t buffsize, uint32_t window_size)
{
    struct hostent *hp;
    sock *Client = s_malloc(sizeof(sock));

    Client->sock = s_socket(SOCK_DOMAIN, SOCK_TYPE, DEFAULT_PROTOCOL);
    Client->buffsize = buffsize;
    Client->window_size = window_size;

    //Remote Socket Address Set Up
    Client->remote.sin_family = SOCK_DOMAIN;
    hp = s_gethostbyname(remote_address);
    s_memcpy(&(Client->remote.sin_addr), hp->h_addr, hp->h_length);
    Client->remote.sin_port = htons(remote_port);

    Client->seq = 0;

    return Client;
}
Exemple #13
0
sock *server_sock(uint32_t buffsize)
{
    sock *Server = s_malloc(sizeof(sock));
    int len = sizeof(Server->local);
    Server->buffsize = buffsize;

    Server->sock = s_socket(SOCK_DOMAIN, SOCK_TYPE, DEFAULT_PROTOCOL);

    Server->local.sin_family = SOCK_DOMAIN;
    Server->local.sin_addr.s_addr = htonl(INADDR_ANY); //???
    Server->local.sin_port = htons(DEFAULT_PORT);

    s_bind(Server->sock, (struct sockaddr *)&(Server->local),
           sizeof(Server->local));

    s_getsockname(Server->sock, (struct sockaddr *)&(Server->local),
                  (socklen_t *)&len);

    Server->seq = 0;
    return Server;
}
Exemple #14
0
static int connect_transparent(CLI *c) { /* connect the original dst */
    SOCKADDR_UNION addr;
    socklen_t addrlen=sizeof addr;
    int retval;

    if(getsockopt(c->local_rfd.fd, SOL_IP, SO_ORIGINAL_DST,
            &addr, &addrlen)) {
        sockerror("setsockopt SO_ORIGINAL_DST");
        longjmp(c->err, 1);
    }
    c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "remote socket");
    if(c->fd<0)
        longjmp(c->err, 1);
    if(c->bind_addr.num) /* explicit local bind or transparent proxy */
        local_bind(c);
    if(connect_blocking(c, &addr, addr_len(addr)))
        longjmp(c->err, 1); /* socket closed on cleanup */
    print_bound_address(c);
    retval=c->fd;
    c->fd=-1;
    return retval; /* success! */
}
Exemple #15
0
static int connect_remote(CLI * c)
{
	int fd, ind_try, ind_cur;
	SOCKADDR_LIST *remote_addr;	

	remote_addr = dynamic_remote_addr(c);
	
	for (ind_try = 0; ind_try < remote_addr->num; ind_try++) {
		if (c->opt->failover == FAILOVER_RR) {
			ind_cur = remote_addr->cur;
			
			remote_addr->cur = (ind_cur + 1) % remote_addr->num;
		} else {	
			ind_cur = ind_try;	
		}

		c->fd = s_socket(remote_addr->addr[ind_cur].sa.sa_family,
				 SOCK_STREAM, 0, 1, "remote socket");
		if (c->fd < 0)
			longjmp(c->err, 1);

		local_bind(c);	

		if (connect_blocking(c, &remote_addr->addr[ind_cur],
				     addr_len(&remote_addr->addr[ind_cur]))) {
			closesocket(c->fd);
			c->fd = -1;
			continue;	
		}
		print_bound_address(c);
		fd = c->fd;
		c->fd = -1;
		return fd;	
	}
	longjmp(c->err, 1);
	return -1;		
}
Exemple #16
0
/* connect remote host */
static int connect_remote(CLI *c) {
    int fd, ind_try, ind_cur;
    SOCKADDR_LIST *remote_addr; /* list of connect_blocking() targets */

    remote_addr=dynamic_remote_addr(c);
    /* try to connect each host from the list */
    for(ind_try=0; ind_try<remote_addr->num; ind_try++) {
        if(c->opt->failover==FAILOVER_RR) {
            ind_cur=remote_addr->cur;
            /* the race condition here can be safely ignored */
            remote_addr->cur=(ind_cur+1)%remote_addr->num;
        } else { /* FAILOVER_PRIO */
            ind_cur=ind_try; /* ignore remote_addr->cur */
        }

        c->fd=s_socket(remote_addr->addr[ind_cur].sa.sa_family,
            SOCK_STREAM, 0, 1, "remote socket");
        if(c->fd<0)
            longjmp(c->err, 1);

        local_bind(c); /* explicit local bind or transparent proxy */

        if(connect_blocking(c, &remote_addr->addr[ind_cur],
                addr_len(&remote_addr->addr[ind_cur]))) {
            closesocket(c->fd);
            c->fd=-1;
            continue; /* next IP */
        }
        print_bound_address(c);
        fd=c->fd;
        c->fd=-1;
        return fd; /* success! */
    }
    longjmp(c->err, 1);
    return -1; /* some C compilers require a return value */
}
Exemple #17
0
static void auth_user(CLI * c, char *accepted_address)
{
	struct servent *s_ent;	
	SOCKADDR_UNION ident;	
	char *line, *type, *system, *user;

	if (!c->opt->username)
		return;		
	if (c->peer_addr.sa.sa_family == AF_UNIX) {
		s_log(LOG_INFO, "IDENT not supported on Unix sockets");
		return;
	}
	c->fd = s_socket(c->peer_addr.sa.sa_family, SOCK_STREAM,
			 0, 1, "socket (auth_user)");
	if (c->fd < 0)
		longjmp(c->err, 1);
	memcpy(&ident, &c->peer_addr, c->peer_addr_len);
	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_blocking(c, &ident, addr_len(&ident)))
		longjmp(c->err, 1);
	s_log(LOG_DEBUG, "IDENT server connected");
	fd_printf(c, c->fd, "%u , %u",
		  ntohs(c->peer_addr.in.sin_port),
		  ntohs(c->opt->local_addr.in.sin_port));
	line = fd_getline(c, c->fd);
	closesocket(c->fd);
	c->fd = -1;		
	type = strchr(line, ':');
	if (!type) {
		s_log(LOG_ERR, "Malformed IDENT response");
		str_free(line);
		longjmp(c->err, 1);
	}
	*type++ = '\0';
	system = strchr(type, ':');
	if (!system) {
		s_log(LOG_ERR, "Malformed IDENT response");
		str_free(line);
		longjmp(c->err, 1);
	}
	*system++ = '\0';
	if (strcmp(type, " USERID ")) {
		s_log(LOG_ERR, "Incorrect INETD response type");
		str_free(line);
		longjmp(c->err, 1);
	}
	user = strchr(system, ':');
	if (!user) {
		s_log(LOG_ERR, "Malformed IDENT response");
		str_free(line);
		longjmp(c->err, 1);
	}
	*user++ = '\0';
	while (*user == ' ')	
		++user;
	if (strcmp(user, c->opt->username)) {
		safestring(user);
		s_log(LOG_WARNING,
		      "Connection from %s REFUSED by IDENT (user %s)",
		      accepted_address, user);
		str_free(line);
		longjmp(c->err, 1);
	}
	s_log(LOG_INFO, "IDENT authentication passed");
	str_free(line);
}
Exemple #18
0
static void auth_user(CLI *c) {
#ifndef _WIN32_WCE
    struct servent *s_ent;    /* structure for getservbyname */
#endif
    SOCKADDR_UNION ident;     /* IDENT socket name */
    char *line, *type, *system, *user;

    if(!c->opt->username)
        return; /* -u option not specified */
    c->fd=s_socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM,
        0, 1, "socket (auth_user)");
    if(c->fd<0)
        longjmp(c->err, 1);
    memcpy(&ident, &c->peer_addr.addr[0], sizeof ident);
#ifndef _WIN32_WCE
    s_ent=getservbyname("auth", "tcp");
    if(s_ent) {
        ident.in.sin_port=s_ent->s_port;
    } else
#endif
    {
        s_log(LOG_WARNING, "Unknown service 'auth': using default 113");
        ident.in.sin_port=htons(113);
    }
    if(connect_blocking(c, &ident, addr_len(ident)))
        longjmp(c->err, 1);
    s_log(LOG_DEBUG, "IDENT server connected");
    fdprintf(c, c->fd, "%u , %u",
        ntohs(c->peer_addr.addr[0].in.sin_port),
        ntohs(c->opt->local_addr.addr[0].in.sin_port));
    line=fdgetline(c, c->fd);
    closesocket(c->fd);
    c->fd=-1; /* avoid double close on cleanup */
    type=strchr(line, ':');
    if(!type) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *type++='\0';
    system=strchr(type, ':');
    if(!system) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *system++='\0';
    if(strcmp(type, " USERID ")) {
        s_log(LOG_ERR, "Incorrect INETD response type");
        str_free(line);
        longjmp(c->err, 1);
    }
    user=strchr(system, ':');
    if(!user) {
        s_log(LOG_ERR, "Malformed IDENT response");
        str_free(line);
        longjmp(c->err, 1);
    }
    *user++='\0';
    while(*user==' ') /* skip leading spaces */
        ++user;
    if(strcmp(user, c->opt->username)) {
        safestring(user);
        s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)",
            c->accepted_address, user);
        str_free(line);
        longjmp(c->err, 1);
    }
    s_log(LOG_INFO, "IDENT authentication passed");
    str_free(line);
}
Exemple #19
0
NOEXPORT OCSP_RESPONSE *ocsp_get_response(CLI *c,
        OCSP_REQUEST *req, char *url) {
    BIO *bio=NULL;
    OCSP_REQ_CTX *req_ctx=NULL;
    OCSP_RESPONSE *resp=NULL;
    int err;
    char *host=NULL, *port=NULL, *path=NULL;
    SOCKADDR_UNION addr;
    int ssl;

    /* parse the OCSP URL */
    if(!OCSP_parse_url(url, &host, &port, &path, &ssl)) {
        s_log(LOG_ERR, "OCSP: Failed to parse the OCSP URL");
        goto cleanup;
    }
    if(ssl) {
        s_log(LOG_ERR, "OCSP: SSL not supported for OCSP"
            " - additional stunnel service needs to be defined");
        goto cleanup;
    }
    memset(&addr, 0, sizeof addr);
    addr.in.sin_family=AF_INET;
    if(!hostport2addr(&addr, host, port)) {
        s_log(LOG_ERR, "OCSP: Failed to resolve the OCSP server address");
        goto cleanup;
    }

    /* connect specified OCSP server (responder) */
    c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "OCSP: socket");
    if(c->fd<0)
        goto cleanup;
    if(s_connect(c, &addr, addr_len(&addr)))
        goto cleanup;
    bio=BIO_new_fd(c->fd, BIO_NOCLOSE);
    if(!bio)
        goto cleanup;
    s_log(LOG_DEBUG, "OCSP: response retrieved");

    /* OCSP protocol communication loop */
    req_ctx=OCSP_sendreq_new(bio, path, req, -1);
    if(!req_ctx) {
        sslerror("OCSP: OCSP_sendreq_new");
        goto cleanup;
    }
    while(OCSP_sendreq_nbio(&resp, req_ctx)==-1) {
        s_poll_init(c->fds);
        s_poll_add(c->fds, c->fd, BIO_should_read(bio), BIO_should_write(bio));
        err=s_poll_wait(c->fds, c->opt->timeout_busy, 0);
        if(err==-1)
            sockerror("OCSP: s_poll_wait");
        if(err==0)
            s_log(LOG_INFO, "OCSP: s_poll_wait: TIMEOUTbusy exceeded");
        if(err<=0)
            goto cleanup;
    }
#if 0
    s_log(LOG_DEBUG, "OCSP: context state: 0x%x", *(int *)req_ctx);
#endif
    /* http://www.mail-archive.com/[email protected]/msg61691.html */
    if(resp) {
        s_log(LOG_DEBUG, "OCSP: request completed");
    } else {
        if(ERR_peek_error())
            sslerror("OCSP: OCSP_sendreq_nbio");
        else /* OpenSSL error: OCSP_sendreq_nbio does not use OCSPerr */
            s_log(LOG_ERR, "OCSP: OCSP_sendreq_nbio: OpenSSL internal error");
    }

cleanup:
    if(req_ctx)
        OCSP_REQ_CTX_free(req_ctx);
    if(bio)
        BIO_free_all(bio);
    if(c->fd>=0) {
        closesocket(c->fd);
        c->fd=-1; /* avoid double close on cleanup */
    }
    if(host)
        OPENSSL_free(host);
    if(port)
        OPENSSL_free(port);
    if(path)
        OPENSSL_free(path);
    return resp;
}
Exemple #20
0
static int ocsp_check(CLI *c, X509_STORE_CTX *callback_ctx) {
    int error, retval=0;
    SOCKADDR_UNION addr;
    X509 *cert;
    X509 *issuer=NULL;
    OCSP_CERTID *certID;
    BIO *bio=NULL;
    OCSP_REQUEST *request=NULL;
    OCSP_RESPONSE *response=NULL;
    OCSP_BASICRESP *basicResponse=NULL;
    ASN1_GENERALIZEDTIME *revoked_at=NULL,
        *this_update=NULL, *next_update=NULL;
    int status, reason;

    /* connect specified OCSP server (responder) */
    c->fd=s_socket(c->opt->ocsp_addr.addr[0].sa.sa_family, SOCK_STREAM, 0,
        0, "OCSP: socket (auth_user)");
    if(c->fd<0)
        return 0; /* reject connection */
    memcpy(&addr, &c->opt->ocsp_addr.addr[0], sizeof addr);
    if(connect_blocking(c, &addr, addr_len(addr)))
        goto cleanup;
    s_log(LOG_DEBUG, "OCSP: server connected");

    /* get current certificate ID */
    cert=X509_STORE_CTX_get_current_cert(callback_ctx); /* get current cert */
    if(X509_STORE_CTX_get1_issuer(&issuer, callback_ctx, cert)!=1) {
        sslerror("OCSP: X509_STORE_CTX_get1_issuer");
        goto cleanup;
    }
    certID=OCSP_cert_to_id(0, cert, issuer);
    if(!certID) {
        sslerror("OCSP: OCSP_cert_to_id");
        goto cleanup;
    }

    /* build request */
    request=OCSP_REQUEST_new();
    if(!request) {
        sslerror("OCSP: OCSP_REQUEST_new");
        goto cleanup;
    }
    if(!OCSP_request_add0_id(request, certID)) {
        sslerror("OCSP: OCSP_request_add0_id");
        goto cleanup;
    }
    OCSP_request_add1_nonce(request, 0, -1);

    /* send the request and get a response */
    /* FIXME: this code won't work with ucontext threading */
    /* (blocking sockets are used) */
    bio=BIO_new_fd(c->fd, BIO_NOCLOSE);
    response=OCSP_sendreq_bio(bio, c->opt->ocsp_path, request);
    if(!response) {
        sslerror("OCSP: OCSP_sendreq_bio");
        goto cleanup;
    }
    error=OCSP_response_status(response);
    if(error!=OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        s_log(LOG_WARNING, "OCSP: Responder error: %d: %s",
            error, OCSP_response_status_str(error));
        goto cleanup;
    }
    s_log(LOG_DEBUG, "OCSP: Response received");

    /* verify the response */
    basicResponse=OCSP_response_get1_basic(response);
    if(!basicResponse) {
        sslerror("OCSP: OCSP_response_get1_basic");
        goto cleanup;
    }
    if(OCSP_check_nonce(request, basicResponse)<=0) {
        sslerror("OCSP: OCSP_check_nonce");
        goto cleanup;
    }
    if(OCSP_basic_verify(basicResponse, NULL,
            c->opt->revocation_store, c->opt->ocsp_flags)<=0) {
        sslerror("OCSP: OCSP_basic_verify");
        goto cleanup;
    }
    if(!OCSP_resp_find_status(basicResponse, certID, &status, &reason,
            &revoked_at, &this_update, &next_update)) {
        sslerror("OCSP: OCSP_resp_find_status");
        goto cleanup;
    }
    s_log(LOG_NOTICE, "OCSP: Status: %d: %s",
        status, OCSP_cert_status_str(status));
    log_time(LOG_INFO, "OCSP: This update", this_update);
    log_time(LOG_INFO, "OCSP: Next update", next_update);
    /* check if the response is valid for at least one minute */
    if(!OCSP_check_validity(this_update, next_update, 60, -1)) {
        sslerror("OCSP: OCSP_check_validity");
        goto cleanup;
    }
    if(status==V_OCSP_CERTSTATUS_REVOKED) {
        if(reason==-1)
            s_log(LOG_WARNING, "OCSP: Certificate revoked");
        else
            s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s",
                reason, OCSP_crl_reason_str(reason));
        log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at);
        goto cleanup;
    }
    retval=1; /* accept connection */
cleanup:
    if(bio)
        BIO_free_all(bio);
    if(issuer)
        X509_free(issuer);
    if(request)
        OCSP_REQUEST_free(request);
    if(response)
        OCSP_RESPONSE_free(response);
    if(basicResponse)
        OCSP_BASICRESP_free(basicResponse);
    closesocket(c->fd);
    c->fd=-1; /* avoid double close on cleanup */
    return retval;
}
Exemple #21
0
/* open new ports, update fds */
int bind_ports(void) {
    SERVICE_OPTIONS *opt;
    char *local_address;
    int listening_section;

#ifdef USE_LIBWRAP
    /* execute after options_cmdline() to know service_options.next,
     * but as early as possible to avoid leaking file descriptors */
    /* retry on each bind_ports() in case stunnel.conf was reloaded
       without "libwrap = no" */
    libwrap_init();
#endif /* USE_LIBWRAP */

    s_poll_init(fds);
    s_poll_add(fds, signal_pipe[0], 1, 0);

    /* allow clean unbind_ports() even though
       bind_ports() was not fully performed */
    for(opt=service_options.next; opt; opt=opt->next)
        if(opt->option.accept)
            opt->fd=INVALID_SOCKET;

    listening_section=0;
    for(opt=service_options.next; opt; opt=opt->next) {
        if(opt->option.accept) {
            if(listening_section<systemd_fds) {
                opt->fd=(SOCKET)(listen_fds_start+listening_section);
                s_log(LOG_DEBUG,
                    "Listening file descriptor received from systemd (FD=%d)",
                    opt->fd);
            } else {
                opt->fd=s_socket(opt->local_addr.sa.sa_family,
                    SOCK_STREAM, 0, 1, "accept socket");
                if(opt->fd==INVALID_SOCKET)
                    return 1;
                s_log(LOG_DEBUG, "Listening file descriptor created (FD=%d)",
                    opt->fd);
            }
            if(set_socket_options(opt->fd, 0)<0) {
                closesocket(opt->fd);
                opt->fd=INVALID_SOCKET;
                return 1;
            }
            /* local socket can't be unnamed */
            local_address=s_ntop(&opt->local_addr, addr_len(&opt->local_addr));
            /* we don't bind or listen on a socket inherited from systemd */
            if(listening_section>=systemd_fds) {
                if(bind(opt->fd, &opt->local_addr.sa, addr_len(&opt->local_addr))) {
                    s_log(LOG_ERR, "Error binding service [%s] to %s",
                        opt->servname, local_address);
                    sockerror("bind");
                    closesocket(opt->fd);
                    opt->fd=INVALID_SOCKET;
                    str_free(local_address);
                    return 1;
                }
                if(listen(opt->fd, SOMAXCONN)) {
                    sockerror("listen");
                    closesocket(opt->fd);
                    opt->fd=INVALID_SOCKET;
                    str_free(local_address);
                    return 1;
                }
            }
            s_poll_add(fds, opt->fd, 1, 0);
            s_log(LOG_DEBUG, "Service [%s] (FD=%d) bound to %s",
                opt->servname, opt->fd, local_address);
            str_free(local_address);
            ++listening_section;
        } else if(opt->exec_name && opt->connect_addr.names) {
            /* create exec+connect services */
            /* FIXME: needs to be delayed on reload with opt->option.retry set */
            create_client(INVALID_SOCKET, INVALID_SOCKET,
                alloc_client_session(opt, INVALID_SOCKET, INVALID_SOCKET),
                client_thread);
        }
    }
    if(listening_section<systemd_fds) {
        s_log(LOG_ERR,
            "Too many listening file descriptors received from systemd, got %d",
            systemd_fds);
        return 1;
    }
    return 0; /* OK */
}
Exemple #22
0
NOEXPORT void cache_transfer(SSL_CTX *ctx, const u_char type,
        const long timeout,
        const u_char *key, const size_t key_len,
        const u_char *val, const size_t val_len,
        unsigned char **ret, size_t *ret_len) {
    char session_id_txt[2*SSL_MAX_SSL_SESSION_ID_LENGTH+1];
    const char hex[16]="0123456789ABCDEF";
    const char *type_description[]={"new", "get", "remove"};
    unsigned i;
    SOCKET s;
    ssize_t len;
    struct timeval t;
    CACHE_PACKET *packet;
    SERVICE_OPTIONS *section;

    if(ret) /* set error as the default result if required */
        *ret=NULL;

    /* log the request information */
    for(i=0; i<key_len && i<SSL_MAX_SSL_SESSION_ID_LENGTH; ++i) {
        session_id_txt[2*i]=hex[key[i]>>4];
        session_id_txt[2*i+1]=hex[key[i]&0x0f];
    }
    session_id_txt[2*i]='\0';
    s_log(LOG_INFO,
        "cache_transfer: request=%s, timeout=%ld, id=%s, length=%lu",
        type_description[type], timeout, session_id_txt, (long unsigned)val_len);

    /* allocate UDP packet buffer */
    if(key_len>SSL_MAX_SSL_SESSION_ID_LENGTH) {
        s_log(LOG_ERR, "cache_transfer: session id too big (%lu bytes)",
            (unsigned long)key_len);
        return;
    }
    if(val_len>MAX_VAL_LEN) {
        s_log(LOG_ERR, "cache_transfer: encoded session too big (%lu bytes)",
            (unsigned long)key_len);
        return;
    }
    packet=str_alloc(sizeof(CACHE_PACKET));

    /* setup packet */
    packet->version=1;
    packet->type=type;
    packet->timeout=htons((u_short)(timeout<64800?timeout:64800));/* 18 hours */
    memcpy(packet->key, key, key_len);
    memcpy(packet->val, val, val_len);

    /* create the socket */
    s=s_socket(AF_INET, SOCK_DGRAM, 0, 0, "cache_transfer: socket");
    if(s==INVALID_SOCKET) {
        str_free(packet);
        return;
    }

    /* retrieve pointer to the section structure of this ctx */
    section=SSL_CTX_get_ex_data(ctx, index_opt);
    if(sendto(s, (void *)packet,
#ifdef USE_WIN32
            (int)
#endif
            (sizeof(CACHE_PACKET)-MAX_VAL_LEN+val_len),
            0, &section->sessiond_addr.sa,
            addr_len(&section->sessiond_addr))<0) {
        sockerror("cache_transfer: sendto");
        closesocket(s);
        str_free(packet);
        return;
    }

    if(!ret || !ret_len) { /* no response is required */
        closesocket(s);
        str_free(packet);
        return;
    }

    /* set recvfrom timeout to 200ms */
    t.tv_sec=0;
    t.tv_usec=200;
    if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (void *)&t, sizeof t)<0) {
        sockerror("cache_transfer: setsockopt SO_RCVTIMEO");
        closesocket(s);
        str_free(packet);
        return;
    }

    /* retrieve response */
    len=recv(s, (void *)packet, sizeof(CACHE_PACKET), 0);
    closesocket(s);
    if(len<0) {
        if(get_last_socket_error()==S_EWOULDBLOCK ||
                get_last_socket_error()==S_EAGAIN)
            s_log(LOG_INFO, "cache_transfer: recv timeout");
        else
            sockerror("cache_transfer: recv");
        str_free(packet);
        return;
    }

    /* parse results */
    if(len<(int)sizeof(CACHE_PACKET)-MAX_VAL_LEN || /* too short */
            packet->version!=1 || /* wrong version */
            safe_memcmp(packet->key, key, key_len)) { /* wrong session id */
        s_log(LOG_DEBUG, "cache_transfer: malformed packet received");
        str_free(packet);
        return;
    }
    if(packet->type!=CACHE_RESP_OK) {
        s_log(LOG_INFO, "cache_transfer: session not found");
        str_free(packet);
        return;
    }
    *ret_len=(size_t)len-(sizeof(CACHE_PACKET)-MAX_VAL_LEN);
    *ret=str_alloc(*ret_len);
    s_log(LOG_INFO, "cache_transfer: session found");
    memcpy(*ret, packet->val, *ret_len);
    str_free(packet);
}
Exemple #23
0
void server_init(){

	if(signal(SIGUSR1, sig_handler) == SIG_ERR){
  		printf("%s\n", "Error in catching SIGINT");
   	}


	services[0].port = 9997;
	services[1].port = 9998;
	services[2].port = 9999;
	services[0].name = (char*)malloc(sizeof(char)*20);
	services[1].name = (char*)malloc(sizeof(char)*20);
	services[2].name = (char*)malloc(sizeof(char)*20);
	strcpy(services[0].name, "c");
	strcpy(services[1].name, "s");
	strcpy(services[2].name, "e");
	services[0].usfd = 0;
	services[1].usfd = 0;
	services[2].usfd = 0;
	services[0].unsfd = 0;
	services[1].unsfd = 0;
	services[2].unsfd = 0;
	services[0].capacity = 3;
	services[1].capacity = 2;
	services[2].capacity = 1;
	services[0].started = 0;
	services[1].started = 0;
	services[2].started = 0;

	// services[0].name = "upper";
	// services[1].name = "lower";
	// services[2].name = "return";

	// signal (ctrl c) to clean up.


	

 	int i; 
 	for( i = 0; i<MAX_SERVICES; i++ ){
 		services[i].sfd = s_socket(AF_INET, SOCK_STREAM, services[i].port, "");
 		char * sockname = (char*)malloc(sizeof(char)*20);
 		strcpy(sockname, services[i].name);
 		strcat(sockname, ".sock");
 		services[i].usfd = c_socket(AF_LOCAL, SOCK_STREAM, sockname);
		_connect(services[i].usfd, AF_LOCAL, SOCK_STREAM, 0, sockname);
		printf("Connected to the multiplex %s\n", services[i].name);
		/////trying to send pid to the multiplex
		char *msg = (char*)malloc(sizeof(char)*200);
		sprintf(msg, "%d", getpid());
		int s = send(services[i].usfd, msg, strlen(msg), 0);
		print_error(s, "Failed to send initial message");
		// int pid = getpid();
		// send_fd_extra(services[i].usfd, services[i].sfd, (void*)&pid); //sending pid for further signaling.
		sleep(2);

 	}
 	printf("%s\n", "Server is initiated.");
 	


}