Large diffs are not rendered by default.

@@ -233,6 +233,11 @@ void append_cell_stats_by_command(smartlist_t *event_parts,
void format_cell_stats(char **event_string, circuit_t *circ,
cell_stats_t *cell_stats);
STATIC char *get_bw_samples(void);

STATIC crypto_pk_t *add_onion_helper_keyarg(const char *arg, int discard_pk,
const char **key_new_alg_out,
char **key_new_blob_out,
char **err_msg_out);
#endif

#endif
@@ -1735,6 +1735,9 @@ typedef struct control_connection_t {
* connection. */
unsigned int is_owning_control_connection:1;

/** List of ephemeral onion services belonging to this connection. */
smartlist_t *ephemeral_onion_services;

/** If we have sent an AUTHCHALLENGE reply on this connection and
* have not received a successful AUTHENTICATE command, points to
* the value which the client must send to authenticate itself;

Large diffs are not rendered by default.

@@ -15,6 +15,7 @@
#include "or.h"

typedef struct rend_intro_cell_s rend_intro_cell_t;
typedef struct rend_service_port_config_s rend_service_port_config_t;

#ifdef RENDSERVICE_PRIVATE

@@ -101,5 +102,23 @@ int rend_service_set_connection_addr_port(edge_connection_t *conn,
void rend_service_dump_stats(int severity);
void rend_service_free_all(void);

rend_service_port_config_t *rend_service_parse_port_config(const char *string,
const char *sep,
char **err_msg_out);
void rend_service_port_config_free(rend_service_port_config_t *p);

/** Return value from rend_service_add_ephemeral. */
typedef enum {
RSAE_BADVIRTPORT = -4, /**< Invalid VIRTPORT/TARGET(s) */
RSAE_ADDREXISTS = -3, /**< Onion address collision */
RSAE_BADPRIVKEY = -2, /**< Invalid public key */
RSAE_INTERNAL = -1, /**< Internal error */
RSAE_OKAY = 0 /**< Service added as expected */
} rend_service_add_ephemeral_status_t;
rend_service_add_ephemeral_status_t rend_service_add_ephemeral(crypto_pk_t *pk,
smartlist_t *ports,
char **service_id_out);
int rend_service_del_ephemeral(const char *service_id);

#endif

@@ -56,6 +56,7 @@ src_test_test_SOURCES = \
src/test/test_circuitmux.c \
src/test/test_config.c \
src/test/test_containers.c \
src/test/test_controller.c \
src/test/test_controller_events.c \
src/test/test_crypto.c \
src/test/test_data.c \
@@ -1127,6 +1127,7 @@ extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
extern struct testcase_t config_tests[];
extern struct testcase_t container_tests[];
extern struct testcase_t controller_tests[];
extern struct testcase_t controller_event_tests[];
extern struct testcase_t crypto_tests[];
extern struct testcase_t dir_tests[];
@@ -1171,7 +1172,8 @@ struct testgroup_t testgroups[] = {
{ "circuitmux/", circuitmux_tests },
{ "config/", config_tests },
{ "container/", container_tests },
{ "control/", controller_event_tests },
{ "control/", controller_tests },
{ "control/event/", controller_event_tests },
{ "crypto/", crypto_tests },
{ "dir/", dir_tests },
{ "dir/md/", microdesc_tests },
@@ -0,0 +1,161 @@
/* Copyright (c) 2015, The Tor Project, Inc. */
/* See LICENSE for licensing information */

#define CONTROL_PRIVATE
#include "or.h"
#include "control.h"
#include "rendservice.h"
#include "test.h"

static void
test_add_onion_helper_keyarg(void *arg)
{
crypto_pk_t *pk = NULL;
crypto_pk_t *pk2 = NULL;
const char *key_new_alg = NULL;
char *key_new_blob = NULL;
char *err_msg = NULL;
char *encoded = NULL;
char *arg_str = NULL;

(void) arg;

/* Test explicit RSA1024 key generation. */
pk = add_onion_helper_keyarg("NEW:RSA1024", 0, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(pk);
tt_str_op(key_new_alg, OP_EQ, "RSA1024");
tt_assert(key_new_blob);
tt_assert(!err_msg);

/* Test "BEST" key generation (Assumes BEST = RSA1024). */
crypto_pk_free(pk);
tor_free(key_new_blob);
pk = add_onion_helper_keyarg("NEW:BEST", 0, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(pk);
tt_str_op(key_new_alg, OP_EQ, "RSA1024");
tt_assert(key_new_blob);
tt_assert(!err_msg);

/* Test discarding the private key. */
crypto_pk_free(pk);
tor_free(key_new_blob);
pk = add_onion_helper_keyarg("NEW:BEST", 1, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(pk);
tt_assert(!key_new_alg);
tt_assert(!key_new_blob);
tt_assert(!err_msg);

/* Test generating a invalid key type. */
crypto_pk_free(pk);
pk = add_onion_helper_keyarg("NEW:RSA512", 0, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(!pk);
tt_assert(!key_new_alg);
tt_assert(!key_new_blob);
tt_assert(err_msg);

/* Test loading a RSA1024 key. */
tor_free(err_msg);
pk = pk_generate(0);
tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk, &encoded));
tor_asprintf(&arg_str, "RSA1024:%s", encoded);
pk2 = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(pk2);
tt_assert(!key_new_alg);
tt_assert(!key_new_blob);
tt_assert(!err_msg);
tt_assert(crypto_pk_cmp_keys(pk, pk2) == 0);

/* Test loading a invalid key type. */
tor_free(arg_str);
tor_asprintf(&arg_str, "RSA512:%s", encoded);
pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(!pk);
tt_assert(!key_new_alg);
tt_assert(!key_new_blob);
tt_assert(err_msg);

/* Test loading a invalid key. */
tor_free(arg_str);
tor_free(err_msg);
encoded[strlen(encoded)/2] = '\0';
tor_asprintf(&arg_str, "RSA1024:%s", encoded);
pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob,
&err_msg);
tt_assert(!pk);
tt_assert(!key_new_alg);
tt_assert(!key_new_blob);
tt_assert(err_msg);

done:
crypto_pk_free(pk);
crypto_pk_free(pk2);
tor_free(key_new_blob);
tor_free(err_msg);
tor_free(encoded);
tor_free(arg_str);
}

static void
test_rend_service_parse_port_config(void *arg)
{
const char *sep = ",";
rend_service_port_config_t *cfg = NULL;
char *err_msg = NULL;

(void)arg;

/* Test "VIRTPORT" only. */
cfg = rend_service_parse_port_config("80", sep, &err_msg);
tt_assert(cfg);
tt_assert(!err_msg);

/* Test "VIRTPORT,TARGET" (Target is port). */
rend_service_port_config_free(cfg);
cfg = rend_service_parse_port_config("80,8080", sep, &err_msg);
tt_assert(cfg);
tt_assert(!err_msg);

/* Test "VIRTPORT,TARGET" (Target is IPv4:port). */
rend_service_port_config_free(cfg);
cfg = rend_service_parse_port_config("80,192.0.2.1:8080", sep, &err_msg);
tt_assert(cfg);
tt_assert(!err_msg);

/* Test "VIRTPORT,TARGET" (Target is IPv6:port). */
rend_service_port_config_free(cfg);
cfg = rend_service_parse_port_config("80,[2001:db8::1]:8080", sep, &err_msg);
tt_assert(cfg);
tt_assert(!err_msg);

/* XXX: Someone should add tests for AF_UNIX targets if supported. */

/* Test empty config. */
rend_service_port_config_free(cfg);
cfg = rend_service_parse_port_config("", sep, &err_msg);
tt_assert(!cfg);
tt_assert(err_msg);

/* Test invalid port. */
tor_free(err_msg);
cfg = rend_service_parse_port_config("90001", sep, &err_msg);
tt_assert(!cfg);
tt_assert(err_msg);

done:
rend_service_port_config_free(cfg);
tor_free(err_msg);
}

struct testcase_t controller_tests[] = {
{ "add_onion_helper_keyarg", test_add_onion_helper_keyarg, 0, NULL, NULL },
{ "rend_service_parse_port_config", test_rend_service_parse_port_config, 0,
NULL, NULL },
END_OF_TESTCASES
};

@@ -597,6 +597,42 @@ test_crypto_pk_fingerprints(void *arg)
tor_free(mem_op_hex_tmp);
}

static void
test_crypto_pk_base64(void *arg)
{
crypto_pk_t *pk1 = NULL;
crypto_pk_t *pk2 = NULL;
char *encoded = NULL;

(void)arg;

/* Test Base64 encoding a key. */
pk1 = pk_generate(0);
tt_assert(pk1);
tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk1, &encoded));
tt_assert(encoded);

/* Test decoding a valid key. */
pk2 = crypto_pk_base64_decode(encoded, strlen(encoded));
tt_assert(pk2);
tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
crypto_pk_free(pk2);

/* Test decoding a invalid key (not Base64). */
static const char *invalid_b64 = "The key is in another castle!";
pk2 = crypto_pk_base64_decode(invalid_b64, strlen(invalid_b64));
tt_assert(!pk2);

/* Test decoding a truncated Base64 blob. */
pk2 = crypto_pk_base64_decode(encoded, strlen(encoded)/2);
tt_assert(!pk2);

done:
crypto_pk_free(pk1);
crypto_pk_free(pk2);
tor_free(encoded);
}

/** Sanity check for crypto pk digests */
static void
test_crypto_digests(void *arg)
@@ -1667,6 +1703,7 @@ struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(sha),
CRYPTO_LEGACY(pk),
{ "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL },
{ "pk_base64", test_crypto_pk_base64, TT_FORK, NULL, NULL },
CRYPTO_LEGACY(digests),
CRYPTO_LEGACY(dh),
{ "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup,