Exemple #1
0
/**
 * proto_conn_create(s, sas, decr, nopfs, requirepfs, nokeepalive, K, timeo,
 *     callback_dead, cookie):
 * Create a connection with one end at ${s} and the other end connecting to
 * the target addresses ${sas}.  If ${decr} is 0, encrypt the outgoing data;
 * if ${decr} is nonzero, decrypt the incoming data.  If ${nopfs} is non-zero,
 * don't use perfect forward secrecy.  If ${requirepfs} is non-zero, drop
 * the connection if the other end tries to disable perfect forward secrecy.
 * Enable transport layer keep-alives (if applicable) on both sockets if and
 * only if ${nokeepalive} is zero.  Drop the connection if the handshake or
 * connecting to the target takes more than ${timeo} seconds.  When the
 * connection is dropped, invoke ${callback_dead}(${cookie}).  Free ${sas}
 * once it is no longer needed.  Return a cookie which can be passed to
 * proto_conn_drop.
 */
void *
proto_conn_create(int s, struct sock_addr ** sas, int decr, int nopfs,
    int requirepfs, int nokeepalive, const struct proto_secret * K,
    double timeo, int (* callback_dead)(void *), void * cookie)
{
	struct conn_state * C;

	/* Bake a cookie for this connection. */
	if ((C = malloc(sizeof(struct conn_state))) == NULL)
		goto err0;
	C->callback_dead = callback_dead;
	C->cookie = cookie;
	C->sas = sas;
	C->decr = decr;
	C->nopfs = nopfs;
	C->requirepfs = requirepfs;
	C->nokeepalive = nokeepalive;
	C->K = K;
	C->timeo = timeo;
	C->s = s;
	C->t = -1;
	C->connect_cookie = NULL;
	C->connect_timeout_cookie = NULL;
	C->handshake_cookie = NULL;
	C->handshake_timeout_cookie = NULL;
	C->k_f = C->k_r = NULL;
	C->pipe_f = C->pipe_r = NULL;
	C->stat_f = C->stat_r = 1;

	/* Start the connect timer. */
	if ((C->connect_timeout_cookie = events_timer_register_double(
	    callback_connect_timeout, C, C->timeo)) == NULL)
		goto err1;

	/* Connect to target. */
	if ((C->connect_cookie =
	    network_connect(C->sas, callback_connect_done, C)) == NULL)
		goto err2;

	/* If we're decrypting, start the handshake. */
	if (C->decr) {
		if (starthandshake(C, C->s, C->decr))
			goto err3;
	}

	/* Success! */
	return (C);

err3:
	network_connect_cancel(C->connect_cookie);
err2:
	events_timer_cancel(C->connect_timeout_cookie);
err1:
	free(C);
err0:
	/* Failure! */
	return (NULL);
}
Exemple #2
0
/* We have connected to the target. */
static int
callback_connect_done(void * cookie, int t)
{
	struct conn_state * C = cookie;

	/* This connection attempt is no longer pending. */
	C->connect_cookie = NULL;

	/* Don't need the target address any more. */
	sock_addr_freelist(C->sas);
	C->sas = NULL;

	/* We beat the clock. */
	events_timer_cancel(C->connect_timeout_cookie);
	C->connect_timeout_cookie = NULL;

	/* Did we manage to connect? */
	if ((C->t = t) == -1)
		return (dropconn(C));

	/* If we're encrypting, start the handshake. */
	if (!C->decr) {
		if (starthandshake(C, C->t, C->decr))
			goto err1;
	}

	/* If we have connections and keys, start shuttling data. */
	if ((C->t != -1) && (C->k_f != NULL) && (C->k_r != NULL)) {
		if (launchpipes(C))
			goto err1;
	}

	/* Success! */
	return (0);

err1:
	dropconn(C);

	/* Failure! */
	return (-1);
}
Exemple #3
0
/* Handle an incoming connection. */
static int
callback_gotconn(void * cookie, int s)
{
	struct accept_state * A = cookie;
	struct conn_state * C;

	/* This accept is no longer in progress. */
	A->accept_cookie = NULL;

	/* We have gained a connection. */
	A->nconn += 1;

	/* Bake a cookie for this connection. */
	if ((C = malloc(sizeof(struct conn_state))) == NULL)
		goto err1;
	C->A = A;
	C->s = s;
	C->t = -1;
	C->connect_cookie = NULL;
	C->handshake_cookie = NULL;
	C->connect_timeout_cookie = C->handshake_timeout_cookie = NULL;
	C->k_f = C->k_r = NULL;
	C->pipe_f = C->pipe_r = NULL;
	C->stat_f = C->stat_r = 1;

	/* Start the connect timer. */
	if ((C->connect_timeout_cookie = events_timer_register_double(
	    callback_connect_timeout, C, C->A->timeo)) == NULL)
		goto err2;

	/* Connect to target. */
	if ((C->connect_cookie =
	    network_connect(A->sas, callback_connect_done, C)) == NULL)
		goto err3;

	/* If we're decrypting, start the handshake. */
	if (C->A->decr) {
		if (starthandshake(C, C->s, C->A->decr))
			goto err4;
	}

	/* Accept another connection if we can. */
	if (doaccept(A))
		goto err0;

	/* Success! */
	return (0);

err4:
	network_connect_cancel(C->connect_cookie);
err3:
	events_timer_cancel(C->connect_timeout_cookie);
err2:
	free(C);
err1:
	A->nconn -= 1;
	close(s);
err0:
	/* Failure! */
	return (-1);
}