Esempio n. 1
0
static void
accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
    struct sockaddr *a, int slen, void *p)
{
	struct bufferevent *b_out, *b_in;
	/* Create two linked bufferevent objects: one to connect, one for the
	 * new connection */
	b_in = bufferevent_socket_new(base, fd,
	    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);

	if (!ssl_ctx || use_wrapper)
		b_out = bufferevent_socket_new(base, -1,
		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
	else {
		SSL *ssl = SSL_new(ssl_ctx);
		b_out = bufferevent_openssl_socket_new(base, -1, ssl,
		    BUFFEREVENT_SSL_CONNECTING,
		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
	}

	assert(b_in && b_out);

	if (bufferevent_socket_connect(b_out,
		(struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) {
		perror("bufferevent_socket_connect");
		bufferevent_free(b_out);
		bufferevent_free(b_in);
		return;
	}

	if (ssl_ctx && use_wrapper) {
		struct bufferevent *b_ssl;
		SSL *ssl = SSL_new(ssl_ctx);
		b_ssl = bufferevent_openssl_filter_new(base,
		    b_out, ssl, BUFFEREVENT_SSL_CONNECTING,
		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
		if (!b_ssl) {
			perror("Bufferevent_openssl_new");
			bufferevent_free(b_out);
			bufferevent_free(b_in);
		}
		b_out = b_ssl;
	}

	bufferevent_setcb(b_in, readcb, NULL, eventcb, b_out);
	bufferevent_setcb(b_out, readcb, NULL, eventcb, b_in);

	bufferevent_enable(b_in, EV_READ|EV_WRITE);
	bufferevent_enable(b_out, EV_READ|EV_WRITE);
}
Esempio n. 2
0
static void
open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
    struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
    evutil_socket_t *fd_pair, struct bufferevent **underlying_pair)
{
	int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
	int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
	if (fd_pair) {
		*bev1_out = bufferevent_openssl_socket_new(
			base, fd_pair[0], ssl1, state1, flags);
		*bev2_out = bufferevent_openssl_socket_new(
			base, fd_pair[1], ssl2, state2, flags);
	} else {
		*bev1_out = bufferevent_openssl_filter_new(
			base, underlying_pair[0], ssl1, state1, flags);
		*bev2_out = bufferevent_openssl_filter_new(
			base, underlying_pair[1], ssl2, state2, flags);

	}
	bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
	    eventcb, (void*)"client");
	bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
	    eventcb, (void*)"server");
}
Esempio n. 3
0
static int
imap_starttls(struct imap_context *ctx, struct imap_request *req, void *priv)
{
    struct bufferevent *bev = ctx->client_bev;
    struct evbuffer *output = bufferevent_get_output(bev);
    SSL *ssl_client_ctx = SSL_new(ctx->driver->ssl_ctx);
    bufferevent_data_cb readcb, writecb;
    bufferevent_event_cb eventcb;
    void *orig_ctx;

    if (ctx->state & IMAP_TLS) {
        evbuffer_add_printf(output, "%s BAD TLS layer already in place" CRLF, req->tag.bv_val);
        return IMAP_OK;
    }

    /* retrieve the callbacks to apply them again on the filtering bev */
    bufferevent_getcb(bev, &readcb, &writecb, &eventcb, &orig_ctx);

    evbuffer_add_printf(output, "%s OK Begin TLS negotiation now" CRLF, req->tag.bv_val);

    bev = bufferevent_openssl_filter_new(ctx->driver->base,
                                         bev, ssl_client_ctx,
                                         BUFFEREVENT_SSL_ACCEPTING,
                                         BEV_OPT_CLOSE_ON_FREE);

    if (!bev) {
        return IMAP_SHUTDOWN;
    }

    bufferevent_setcb(bev, readcb, writecb, eventcb, orig_ctx);
    bufferevent_enable(bev, EV_READ|EV_WRITE);
    ctx->client_bev = bev;
    ctx->state |= IMAP_TLS;

    return IMAP_OK;
}
Esempio n. 4
0
struct bufferevent* red_connect_relay_ssl(const char *ifname,
                                    struct sockaddr_in *addr,
                                    SSL * ssl,
                                    bufferevent_data_cb readcb,
                                    bufferevent_data_cb writecb,
                                    bufferevent_event_cb errorcb,
                                    void *cbarg,
                                    const struct timeval *timeout_write)
{
    struct bufferevent *retval = NULL;
    struct bufferevent *underlying = NULL;
    int relay_fd = -1;
    int error;

    underlying = red_prepare_relay(ifname, NULL, NULL, NULL, NULL);
    if (!underlying)
        goto fail;
    relay_fd = bufferevent_getfd(underlying);
    if (timeout_write)
        bufferevent_set_timeouts(underlying, NULL, timeout_write);

    error = connect(relay_fd, (struct sockaddr*)addr, sizeof(*addr));
    if (error && errno != EINPROGRESS) {
        log_errno(LOG_NOTICE, "connect");
        goto fail;
    }
    retval = bufferevent_openssl_filter_new(bufferevent_get_base(underlying),
                                            underlying,
                                            ssl,
                                            BUFFEREVENT_SSL_CONNECTING,
                                            BEV_OPT_DEFER_CALLBACKS);
    if (!retval) {
        log_errno(LOG_NOTICE, "bufferevent_openssl_filter_new");
        goto fail;
    }
    if (timeout_write)
        bufferevent_set_timeouts(retval, NULL, timeout_write);

    bufferevent_setcb(retval, readcb, writecb, errorcb, cbarg);
    if (writecb) {
        error = bufferevent_enable(retval, EV_WRITE); // we wait for connection...
        if (error) {
            log_errno(LOG_ERR, "bufferevent_enable");
            goto fail;
        }
    }
    return retval;

fail:
    if (retval) {
        bufferevent_disable(retval, EV_READ|EV_WRITE);
        bufferevent_free(retval);
    }
    if (underlying) {
        bufferevent_disable(underlying, EV_READ|EV_WRITE);
        bufferevent_free(underlying);
    }
    if (relay_fd != -1)
        redsocks_close(relay_fd);
    return NULL;
}
Esempio n. 5
0
// This starts a new TCP/TLS connection to notblocked
// It is called both when a new local proxy connection is accepted
// and when we need to re-open an existing telex transport (state->local is reused)
void make_new_telex_conn(struct telex_state *state)
{
    struct telex_conf *conf = state->conf;

    HexDump(LOG_TRACE, state->name, "Opening telex id:", state->remote_conn_id, sizeof(state->remote_conn_id));

	state->remotetcp = bufferevent_socket_new(state->base, -1,
		BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
	if (!state->remotetcp) {
		LogError(state->name, "Could not create remote bufferevent socket");
		StateCleanup(&state);
		return;
	}
	_inc(BEV);

    // TODO: make nonblocking lookup?
    bufferevent_socket_connect_hostname(state->remotetcp, NULL, AF_INET, conf->notblocked_host, conf->notblocked_port);

    // After resolution...
    /*
    struct sockaddr_in sin;
    if (getpeername(bufferevent_getfd(state->remotetcp), (struct sockaddr *)&sin, (socklen_t*)sizeof(sin)) < 0) {
        perror("getpeername");
        LogError("proxy", "getpeername failed");
        StateCleanup(&state);
        return;
    }
    char ip_p[INET_ADDRSTRLEN];
    LogTrace(state->name, "Connecting to %s:%d",
             evutil_inet_ntop(AF_INET, server_ip, ip_p, sizeof(ip_p)), state->conf->notblocked_port);
    //bufferevent_socket_connect(state->remotetcp, ai->ai_addr, (int)ai->ai_addrlen);
    */

	if (ssl_new_telex(state) < 0) {
		ssl_log_errors(LOG_ERROR, state->name);
		LogError(state->name, "Could not create new telex SSL connection object");
		StateCleanup(&state);
		return;
	}
	_inc(SSL);

	state->remote = bufferevent_openssl_filter_new(state->base, state->remotetcp,
		state->ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS);
		// Not BEV_OPT_CLOSE_ON_FREE!
	if (!state->remote) {
		LogError(state->name, "Could not create remote SSL bufferevent filter");
		StateCleanup(&state);
		return;
	}
	_inc(BEV);

    // First, set our read_cb to something that receives the SPTelex init message
	bufferevent_setcb(state->remote, (bufferevent_data_cb)first_read_cb, NULL,
		(bufferevent_event_cb)event_cb, state);

    // Disable until SPTelex init msg
    bufferevent_disable(state->local, EV_READ|EV_WRITE);
	bufferevent_setcb(state->local, (bufferevent_data_cb)read_cb, NULL,
		(bufferevent_event_cb)event_cb, state);

    // Hmm...we should make a second one of these
    state->in_local = 0;
}