mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
Merge flagday into main branch.
svn:r1683
This commit is contained in:
parent
83081f5ad6
commit
c44016e86e
@ -127,13 +127,18 @@ RSA *_crypto_pk_env_get_rsa(crypto_pk_env_t *env)
|
||||
}
|
||||
|
||||
/* used by tortls.c */
|
||||
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env)
|
||||
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private)
|
||||
{
|
||||
RSA *key = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
assert(env->key);
|
||||
if (private) {
|
||||
if (!(key = RSAPrivateKey_dup(env->key)))
|
||||
goto error;
|
||||
} else {
|
||||
if (!(key = RSAPublicKey_dup(env->key)))
|
||||
goto error;
|
||||
}
|
||||
if (!(pkey = EVP_PKEY_new()))
|
||||
goto error;
|
||||
if (!(EVP_PKEY_assign_RSA(pkey, key)))
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
/* How long do certificates live? (sec) */
|
||||
#define CERT_LIFETIME (365*24*60*60)
|
||||
/* How long do identity certificates live? (sec) */
|
||||
#define IDENTITY_CERT_LIFETIME (365*24*60*60)
|
||||
/* How much clock skew do we tolerate when checking certificates? (sec) */
|
||||
#define CERT_ALLOW_SKEW (90*60)
|
||||
|
||||
@ -44,7 +44,10 @@ struct tor_tls_st {
|
||||
};
|
||||
|
||||
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
const char *nickname);
|
||||
crypto_pk_env_t *rsa_sign,
|
||||
const char *cname,
|
||||
const char *cname_sign,
|
||||
unsigned int lifetime);
|
||||
|
||||
/* global tls context, keep it here because nobody else needs to touch it */
|
||||
static tor_tls_context *global_tls_context = NULL;
|
||||
@ -54,7 +57,7 @@ static int tls_library_is_initialized = 0;
|
||||
#define _TOR_TLS_ZERORETURN -5
|
||||
|
||||
/* These functions are declared in crypto.c but not exported. */
|
||||
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env);
|
||||
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private);
|
||||
crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa);
|
||||
DH *_crypto_dh_env_get_dh(crypto_dh_env_t *dh);
|
||||
|
||||
@ -129,26 +132,32 @@ static int always_accept_verify_cb(int preverify_ok,
|
||||
}
|
||||
|
||||
/* Generate a self-signed certificate with the private key 'rsa' and
|
||||
* commonName 'nickname', and write it, PEM-encoded, to the file named
|
||||
* by 'certfile'. Return 0 on success, -1 for failure.
|
||||
* identity key 'identity and commonName 'nickname'. Return a certificate
|
||||
* on success, NULL on failure.
|
||||
* DOCDOC
|
||||
*/
|
||||
X509 *
|
||||
tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
const char *nickname)
|
||||
crypto_pk_env_t *rsa_sign,
|
||||
const char *cname,
|
||||
const char *cname_sign,
|
||||
unsigned int cert_lifetime)
|
||||
{
|
||||
time_t start_time, end_time;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
|
||||
X509 *x509 = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
X509_NAME *name = NULL, *name_issuer=NULL;
|
||||
int nid;
|
||||
|
||||
tor_tls_init();
|
||||
|
||||
start_time = time(NULL);
|
||||
|
||||
assert(rsa && nickname);
|
||||
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
|
||||
return NULL;
|
||||
assert(rsa && cname && rsa_sign && cname_sign);
|
||||
if (!(sign_pkey = _crypto_pk_env_get_evp_pkey(rsa_sign,1)))
|
||||
goto error;
|
||||
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,0)))
|
||||
goto error;
|
||||
if (!(x509 = X509_new()))
|
||||
goto error;
|
||||
if (!(X509_set_version(x509, 2)))
|
||||
@ -163,20 +172,29 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
"TOR", -1, -1, 0))) goto error;
|
||||
if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
|
||||
if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
|
||||
(char*)nickname, -1, -1, 0))) goto error;
|
||||
|
||||
if (!(X509_set_issuer_name(x509, name)))
|
||||
goto error;
|
||||
(char*)cname, -1, -1, 0))) goto error;
|
||||
if (!(X509_set_subject_name(x509, name)))
|
||||
goto error;
|
||||
|
||||
if (!(name_issuer = X509_NAME_new()))
|
||||
goto error;
|
||||
if ((nid = OBJ_txt2nid("organizationName")) == NID_undef) goto error;
|
||||
if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
|
||||
"TOR", -1, -1, 0))) goto error;
|
||||
if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
|
||||
if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
|
||||
(char*)cname_sign, -1, -1, 0))) goto error;
|
||||
if (!(X509_set_issuer_name(x509, name_issuer)))
|
||||
goto error;
|
||||
|
||||
if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
|
||||
goto error;
|
||||
end_time = start_time + CERT_LIFETIME;
|
||||
end_time = start_time + cert_lifetime;
|
||||
if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
|
||||
goto error;
|
||||
if (!X509_set_pubkey(x509, pkey))
|
||||
goto error;
|
||||
if (!X509_sign(x509, pkey, EVP_sha1()))
|
||||
if (!X509_sign(x509, sign_pkey, EVP_sha1()))
|
||||
goto error;
|
||||
|
||||
goto done;
|
||||
@ -186,10 +204,14 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
x509 = NULL;
|
||||
}
|
||||
done:
|
||||
if (sign_pkey)
|
||||
EVP_PKEY_free(sign_pkey);
|
||||
if (pkey)
|
||||
EVP_PKEY_free(pkey);
|
||||
if (name)
|
||||
X509_NAME_free(name);
|
||||
if (name_issuer)
|
||||
X509_NAME_free(name_issuer);
|
||||
return x509;
|
||||
}
|
||||
|
||||
@ -210,26 +232,37 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
#endif
|
||||
|
||||
/* Create a new TLS context. If we are going to be using it as a
|
||||
* server, it must have isServer set to true, certfile set to a
|
||||
* filename for a certificate file, and RSA set to the private key
|
||||
* used for that certificate. Return -1 if failure, else 0.
|
||||
* server, it must have isServer set to true, 'identity' set to the
|
||||
* identity key used to sign that certificate, and 'nickname' set to
|
||||
* the server's nickname. Return -1 if failure, else 0.
|
||||
*/
|
||||
int
|
||||
tor_tls_context_new(crypto_pk_env_t *rsa,
|
||||
int isServer, const char *nickname)
|
||||
tor_tls_context_new(crypto_pk_env_t *identity,
|
||||
int isServer, const char *nickname,
|
||||
unsigned int key_lifetime)
|
||||
{
|
||||
crypto_pk_env_t *rsa = NULL;
|
||||
crypto_dh_env_t *dh = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
tor_tls_context *result;
|
||||
X509 *cert = NULL;
|
||||
tor_tls_context *result = NULL;
|
||||
X509 *cert = NULL, *idcert = NULL;
|
||||
char nn2[1024];
|
||||
sprintf(nn2, "%s <identity>", nickname);
|
||||
|
||||
tor_tls_init();
|
||||
|
||||
if (rsa) {
|
||||
cert = tor_tls_create_certificate(rsa, nickname);
|
||||
if (!cert) {
|
||||
if (isServer) {
|
||||
if (!(rsa = crypto_new_pk_env()))
|
||||
goto error;
|
||||
if (crypto_pk_generate_key(rsa)<0)
|
||||
goto error;
|
||||
cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
|
||||
key_lifetime);
|
||||
idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
|
||||
IDENTITY_CERT_LIFETIME);
|
||||
if (!cert || !idcert) {
|
||||
log(LOG_WARN, "Error creating certificate");
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,9 +282,12 @@ tor_tls_context_new(crypto_pk_env_t *rsa,
|
||||
goto error;
|
||||
if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
|
||||
goto error;
|
||||
if (idcert && !SSL_CTX_add_extra_chain_cert(result->ctx,idcert))
|
||||
goto error;
|
||||
SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
|
||||
if (rsa) {
|
||||
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
|
||||
if (isServer) {
|
||||
assert(rsa);
|
||||
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
|
||||
goto error;
|
||||
if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
|
||||
goto error;
|
||||
@ -283,13 +319,15 @@ tor_tls_context_new(crypto_pk_env_t *rsa,
|
||||
error:
|
||||
if (pkey)
|
||||
EVP_PKEY_free(pkey);
|
||||
if (rsa)
|
||||
crypto_free_pk_env(rsa);
|
||||
if (dh)
|
||||
crypto_dh_free(dh);
|
||||
if (result && result->ctx)
|
||||
SSL_CTX_free(result->ctx);
|
||||
if (result)
|
||||
free(result);
|
||||
|
||||
/* leak certs XXXX ? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -509,19 +547,19 @@ tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen)
|
||||
}
|
||||
|
||||
/* If the provided tls connection is authenticated and has a
|
||||
* certificate that is currently valid and is correctly self-signed,
|
||||
* return its public key. Otherwise return NULL.
|
||||
* certificate that is currently valid and is correctly signed by
|
||||
* identity_key, return 0. Else, return -1.
|
||||
*/
|
||||
crypto_pk_env_t *
|
||||
tor_tls_verify(tor_tls *tls)
|
||||
int
|
||||
tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
RSA *rsa = NULL;
|
||||
EVP_PKEY *id_pkey = NULL;
|
||||
time_t now, t;
|
||||
crypto_pk_env_t *r = NULL;
|
||||
int r = -1;
|
||||
|
||||
if (!(cert = SSL_get_peer_certificate(tls->ssl)))
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
now = time(NULL);
|
||||
t = now + CERT_ALLOW_SKEW;
|
||||
@ -536,33 +574,19 @@ tor_tls_verify(tor_tls *tls)
|
||||
}
|
||||
|
||||
/* Get the public key. */
|
||||
if (!(pkey = X509_get_pubkey(cert))) {
|
||||
log_fn(LOG_WARN,"X509_get_pubkey returned null");
|
||||
goto done;
|
||||
}
|
||||
if (X509_verify(cert, pkey) <= 0) {
|
||||
if (!(id_pkey = _crypto_pk_env_get_evp_pkey(identity_key,0)) ||
|
||||
X509_verify(cert, id_pkey) <= 0) {
|
||||
log_fn(LOG_WARN,"X509_verify on cert and pkey returned <= 0");
|
||||
goto done;
|
||||
}
|
||||
|
||||
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
pkey = NULL;
|
||||
if (!rsa) {
|
||||
log_fn(LOG_WARN,"EVP_PKEY_get1_RSA(pkey) returned null");
|
||||
goto done;
|
||||
}
|
||||
|
||||
r = _crypto_new_pk_env_rsa(rsa);
|
||||
rsa = NULL;
|
||||
r = 0;
|
||||
|
||||
done:
|
||||
if (cert)
|
||||
X509_free(cert);
|
||||
if (pkey)
|
||||
EVP_PKEY_free(pkey);
|
||||
if (rsa)
|
||||
RSA_free(rsa);
|
||||
if (id_pkey)
|
||||
EVP_PKEY_free(id_pkey);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,13 @@ typedef struct tor_tls_st tor_tls;
|
||||
#define TOR_TLS_DONE 0
|
||||
|
||||
/* X509* tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickname); */
|
||||
int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer, const char *nickname);
|
||||
int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer,
|
||||
const char *nickname, unsigned int key_lifetime);
|
||||
tor_tls *tor_tls_new(int sock, int isServer);
|
||||
void tor_tls_free(tor_tls *tls);
|
||||
int tor_tls_peer_has_cert(tor_tls *tls);
|
||||
int tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen);
|
||||
crypto_pk_env_t *tor_tls_verify(tor_tls *tls);
|
||||
int tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity);
|
||||
int tor_tls_read(tor_tls *tls, char *cp, int len);
|
||||
int tor_tls_write(tor_tls *tls, char *cp, int n);
|
||||
int tor_tls_handshake(tor_tls *tls);
|
||||
|
@ -655,6 +655,10 @@ int getconfig(int argc, char **argv, or_options_t *options) {
|
||||
log(LOG_WARN,"DirFetchPostPeriod option must be positive.");
|
||||
result = -1;
|
||||
}
|
||||
if(options->DirFetchPostPeriod > MIN_ONION_KEY_LIFETIME/2) {
|
||||
log(LOG_WARN,"DirFetchPostPeriod is too large; clipping.");
|
||||
options->DirFetchPostPeriod = MIN_ONION_KEY_LIFETIME/2;
|
||||
}
|
||||
|
||||
if(options->KeepalivePeriod < 1) {
|
||||
log(LOG_WARN,"KeepalivePeriod option must be positive.");
|
||||
|
@ -116,8 +116,6 @@ void connection_free(connection_t *conn) {
|
||||
|
||||
if (conn->onion_pkey)
|
||||
crypto_free_pk_env(conn->onion_pkey);
|
||||
if (conn->link_pkey)
|
||||
crypto_free_pk_env(conn->link_pkey);
|
||||
if (conn->identity_pkey)
|
||||
crypto_free_pk_env(conn->identity_pkey);
|
||||
tor_free(conn->nickname);
|
||||
|
@ -84,7 +84,6 @@ void connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *route
|
||||
conn->port = router->or_port;
|
||||
conn->receiver_bucket = conn->bandwidth = router->bandwidthburst;
|
||||
conn->onion_pkey = crypto_pk_dup_key(router->onion_pkey);
|
||||
conn->link_pkey = crypto_pk_dup_key(router->link_pkey);
|
||||
conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
|
||||
conn->nickname = tor_strdup(router->nickname);
|
||||
tor_free(conn->address);
|
||||
@ -178,7 +177,6 @@ int connection_tls_continue_handshake(connection_t *conn) {
|
||||
}
|
||||
|
||||
static int connection_tls_finish_handshake(connection_t *conn) {
|
||||
crypto_pk_env_t *pk;
|
||||
routerinfo_t *router;
|
||||
char nickname[MAX_NICKNAME_LEN+1];
|
||||
connection_t *c;
|
||||
@ -203,42 +201,34 @@ static int connection_tls_finish_handshake(connection_t *conn) {
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_DEBUG, "Other side claims to be '%s'", nickname);
|
||||
pk = tor_tls_verify(conn->tls);
|
||||
if(!pk) {
|
||||
router = router_get_by_nickname(nickname);
|
||||
if (!router) {
|
||||
log_fn(LOG_INFO, "Unrecognized router with nickname '%s'", nickname);
|
||||
return -1;
|
||||
}
|
||||
if(tor_tls_verify(conn->tls, router->identity_pkey)<0) {
|
||||
log_fn(LOG_WARN,"Other side '%s' (%s:%d) has a cert but it's invalid. Closing.",
|
||||
nickname, conn->address, conn->port);
|
||||
return -1;
|
||||
}
|
||||
router = router_get_by_link_pk(pk);
|
||||
if (!router) {
|
||||
log_fn(LOG_INFO,"Unrecognized public key from peer '%s' (%s:%d). Closing.",
|
||||
nickname, conn->address, conn->port);
|
||||
crypto_free_pk_env(pk);
|
||||
return -1;
|
||||
}
|
||||
if(conn->link_pkey) { /* I initiated this connection. */
|
||||
if(crypto_pk_cmp_keys(conn->link_pkey, pk)) {
|
||||
log_fn(LOG_WARN,"We connected to '%s' (%s:%d) but he gave us a different key. Closing.",
|
||||
nickname, conn->address, conn->port);
|
||||
crypto_free_pk_env(pk);
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_DEBUG,"The router's pk matches the one we meant to connect to. Good.");
|
||||
} else {
|
||||
if((c=connection_exact_get_by_addr_port(router->addr,router->or_port))) {
|
||||
log_fn(LOG_INFO,"Router %s is already connected on fd %d. Dropping fd %d.", router->nickname, c->s, conn->s);
|
||||
crypto_free_pk_env(pk);
|
||||
return -1;
|
||||
}
|
||||
connection_or_init_conn_from_router(conn, router);
|
||||
}
|
||||
crypto_free_pk_env(pk);
|
||||
log_fn(LOG_DEBUG,"The router's cert is valid.");
|
||||
|
||||
if (conn->nickname) {
|
||||
/* I initiated this connection. */
|
||||
if (strcmp(conn->nickname, nickname)) {
|
||||
log_fn(options.DirPort ? LOG_WARN : LOG_INFO,
|
||||
"Other side claims to be '%s', but we expected '%s'",
|
||||
"Other side is '%s', but we tried to connect to '%s'",
|
||||
nickname, conn->nickname);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if((c=connection_exact_get_by_addr_port(router->addr,router->or_port))) {
|
||||
log_fn(LOG_INFO,"Router %s is already connected on fd %d. Dropping fd %d.", router->nickname, c->s, conn->s);
|
||||
return -1;
|
||||
}
|
||||
connection_or_init_conn_from_router(conn,router);
|
||||
}
|
||||
|
||||
if (!options.ORPort) { /* If I'm an OP... */
|
||||
conn->receiver_bucket = conn->bandwidth = DEFAULT_BANDWIDTH_OP;
|
||||
}
|
||||
|
@ -12,8 +12,9 @@ extern or_options_t options; /* command-line and config-file options */
|
||||
#define LEN_ONION_QUESTION (1+TAG_LEN+ONIONSKIN_CHALLENGE_LEN)
|
||||
#define LEN_ONION_RESPONSE (1+TAG_LEN+ONIONSKIN_REPLY_LEN+40+32)
|
||||
|
||||
int num_cpuworkers=0;
|
||||
int num_cpuworkers_busy=0;
|
||||
static int num_cpuworkers=0;
|
||||
static int num_cpuworkers_busy=0;
|
||||
static time_t last_rotation_time=0;
|
||||
|
||||
int cpuworker_main(void *data);
|
||||
static int spawn_cpuworker(void);
|
||||
@ -21,6 +22,7 @@ static void spawn_enough_cpuworkers(void);
|
||||
static void process_pending_task(connection_t *cpuworker);
|
||||
|
||||
void cpu_init(void) {
|
||||
last_rotation_time=time(NULL);
|
||||
spawn_enough_cpuworkers();
|
||||
}
|
||||
|
||||
@ -47,6 +49,18 @@ static void tag_unpack(char *tag, uint32_t *addr, uint16_t *port, uint16_t *circ
|
||||
log_fn(LOG_DEBUG,"onion was from %s:%d, circ_id %d.", inet_ntoa(in), *port, *circ_id);
|
||||
}
|
||||
|
||||
void cpuworkers_rotate(void)
|
||||
{
|
||||
connection_t *cpuworker;
|
||||
while ((cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER,
|
||||
CPUWORKER_STATE_IDLE))) {
|
||||
connection_mark_for_close(cpuworker,0);
|
||||
--num_cpuworkers;
|
||||
}
|
||||
last_rotation_time = time(NULL);
|
||||
spawn_enough_cpuworkers();
|
||||
}
|
||||
|
||||
int connection_cpu_process_inbuf(connection_t *conn) {
|
||||
char success;
|
||||
unsigned char buf[LEN_ONION_RESPONSE];
|
||||
@ -111,7 +125,13 @@ int connection_cpu_process_inbuf(connection_t *conn) {
|
||||
done_processing:
|
||||
conn->state = CPUWORKER_STATE_IDLE;
|
||||
num_cpuworkers_busy--;
|
||||
if (conn->timestamp_created < last_rotation_time) {
|
||||
connection_mark_for_close(conn,0);
|
||||
num_cpuworkers--;
|
||||
spawn_enough_cpuworkers();
|
||||
} else {
|
||||
process_pending_task(conn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -126,6 +146,7 @@ int cpuworker_main(void *data) {
|
||||
unsigned char reply_to_proxy[ONIONSKIN_REPLY_LEN];
|
||||
unsigned char buf[LEN_ONION_RESPONSE];
|
||||
char tag[TAG_LEN];
|
||||
crypto_pk_env_t *onion_key = NULL, *last_onion_key = NULL;
|
||||
|
||||
close(fdarray[0]); /* this is the side of the socketpair the parent uses */
|
||||
fd = fdarray[1]; /* this side is ours */
|
||||
@ -133,27 +154,32 @@ int cpuworker_main(void *data) {
|
||||
connection_free_all(); /* so the child doesn't hold the parent's fd's open */
|
||||
#endif
|
||||
|
||||
/* XXXX WINDOWS lock here. */
|
||||
onion_key = crypto_pk_dup_key(get_onion_key());
|
||||
if (get_previous_onion_key())
|
||||
last_onion_key = crypto_pk_dup_key(get_previous_onion_key());
|
||||
|
||||
for(;;) {
|
||||
|
||||
if(recv(fd, &question_type, 1, 0) != 1) {
|
||||
// log_fn(LOG_ERR,"read type failed. Exiting.");
|
||||
log_fn(LOG_INFO,"cpuworker exiting because tor process died.");
|
||||
spawn_exit();
|
||||
goto end;
|
||||
}
|
||||
assert(question_type == CPUWORKER_TASK_ONION);
|
||||
|
||||
if(read_all(fd, tag, TAG_LEN, 1) != TAG_LEN) {
|
||||
log_fn(LOG_ERR,"read tag failed. Exiting.");
|
||||
spawn_exit();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) != ONIONSKIN_CHALLENGE_LEN) {
|
||||
log_fn(LOG_ERR,"read question failed. Exiting.");
|
||||
spawn_exit();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(question_type == CPUWORKER_TASK_ONION) {
|
||||
if(onion_skin_server_handshake(question, get_onion_key(),
|
||||
if(onion_skin_server_handshake(question, onion_key, last_onion_key,
|
||||
reply_to_proxy, keys, 40+32) < 0) {
|
||||
/* failure */
|
||||
log_fn(LOG_WARN,"onion_skin_server_handshake failed.");
|
||||
@ -173,6 +199,12 @@ int cpuworker_main(void *data) {
|
||||
log_fn(LOG_DEBUG,"finished writing response.");
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (onion_key)
|
||||
crypto_free_pk_env(onion_key);
|
||||
if (last_onion_key)
|
||||
crypto_free_pk_env(last_onion_key);
|
||||
spawn_exit();
|
||||
return 0; /* windows wants this function to return an int */
|
||||
}
|
||||
|
||||
@ -263,7 +295,7 @@ int assign_to_cpuworker(connection_t *cpuworker, unsigned char question_type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!cpuworker)
|
||||
if (!cpuworker)
|
||||
cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER, CPUWORKER_STATE_IDLE);
|
||||
|
||||
assert(cpuworker);
|
||||
|
@ -437,8 +437,13 @@ dirserv_dump_directory_to_string(char *s, int maxlen,
|
||||
/* These multiple strlcat calls are inefficient, but dwarfed by the RSA
|
||||
signature.
|
||||
*/
|
||||
if (strlcat(s, "directory-signature\n", maxlen) >= maxlen)
|
||||
if (strlcat(s, "directory-signature ", maxlen) >= maxlen)
|
||||
goto truncated;
|
||||
if (strlcat(s, options.Nickname, maxlen) >= maxlen)
|
||||
goto truncated;
|
||||
if (strlcat(s, "\n", maxlen) >= maxlen)
|
||||
goto truncated;
|
||||
|
||||
|
||||
if (router_get_dir_hash(s,digest)) {
|
||||
log_fn(LOG_WARN,"couldn't compute digest");
|
||||
|
@ -53,6 +53,7 @@ int has_completed_circuit=0;
|
||||
****************************************************************************/
|
||||
|
||||
int connection_add(connection_t *conn) {
|
||||
assert(conn);
|
||||
|
||||
if(nfds >= options.MaxConn-1) {
|
||||
log_fn(LOG_WARN,"failing because nfds is too high.");
|
||||
@ -345,9 +346,38 @@ static void run_connection_housekeeping(int i, time_t now) {
|
||||
static void run_scheduled_events(time_t now) {
|
||||
static long time_to_fetch_directory = 0;
|
||||
static time_t last_uploaded_services = 0;
|
||||
static time_t last_rotated_certificate = 0;
|
||||
int i;
|
||||
|
||||
/* 1. Every DirFetchPostPeriod seconds, we get a new directory and upload
|
||||
|
||||
/* 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys,
|
||||
* shut down and restart all cpuworkers, and update the directory if
|
||||
* necessary.
|
||||
*/
|
||||
if (options.ORPort && get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME < now) {
|
||||
rotate_onion_key();
|
||||
cpuworkers_rotate();
|
||||
if (router_rebuild_descriptor()<0) {
|
||||
log_fn(LOG_WARN, "Couldn't rebuild router descriptor");
|
||||
}
|
||||
router_rebuild_descriptor();
|
||||
router_upload_dir_desc_to_dirservers();
|
||||
}
|
||||
|
||||
/* 1b. Every MAX_LINK_KEY_LIFETIME seconds, we change our TLS context. */
|
||||
if (!last_rotated_certificate)
|
||||
last_rotated_certificate = now;
|
||||
if (options.ORPort && last_rotated_certificate+MAX_SSL_KEY_LIFETIME < now) {
|
||||
if (tor_tls_context_new(get_identity_key(), 1, options.Nickname,
|
||||
MAX_SSL_KEY_LIFETIME) < 0) {
|
||||
log_fn(LOG_WARN, "Error reinitializing TLS context");
|
||||
}
|
||||
last_rotated_certificate = now;
|
||||
/* XXXX We should rotate TLS connections as well; this code doesn't change
|
||||
* XXXX them at all. */
|
||||
}
|
||||
|
||||
/* 1c. Every DirFetchPostPeriod seconds, we get a new directory and upload
|
||||
* our descriptor (if any). */
|
||||
if(time_to_fetch_directory < now) {
|
||||
/* it's time to fetch a new directory and/or post our descriptor */
|
||||
@ -371,6 +401,7 @@ static void run_scheduled_events(time_t now) {
|
||||
time_to_fetch_directory = now + options.DirFetchPostPeriod;
|
||||
}
|
||||
|
||||
|
||||
/* 2. Every second, we examine pending circuits and prune the
|
||||
* ones which have been pending for more than a few seconds.
|
||||
* We do this before step 3, so it can try building more if
|
||||
|
@ -576,9 +576,6 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout
|
||||
[16 bytes] Symmetric key for encrypting blob past RSA
|
||||
[112 bytes] g^x part 1 (inside the RSA)
|
||||
[16 bytes] g^x part 2 (symmetrically encrypted)
|
||||
[ 6 bytes] Meeting point (IP/port)
|
||||
[ 8 bytes] Meeting cookie
|
||||
[16 bytes] End-to-end authentication [optional]
|
||||
|
||||
* Stores the DH private key into handshake_state_out for later completion
|
||||
* of the handshake.
|
||||
@ -604,7 +601,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
||||
pkbytes = crypto_pk_keysize(dest_router_key);
|
||||
assert(dhbytes == 128);
|
||||
assert(pkbytes == 128);
|
||||
challenge = tor_malloc_zero(ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN);
|
||||
challenge = tor_malloc_zero(DH_KEY_LEN);
|
||||
|
||||
if (crypto_dh_get_public(dh, challenge, dhbytes))
|
||||
goto err;
|
||||
@ -626,8 +623,8 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
||||
|
||||
/* set meeting point, meeting cookie, etc here. Leave zero for now. */
|
||||
if (crypto_pk_public_hybrid_encrypt(dest_router_key, challenge,
|
||||
ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN,
|
||||
onion_skin_out, PK_NO_PADDING, 1)<0)
|
||||
DH_KEY_LEN,
|
||||
onion_skin_out, PK_PKCS1_OAEP_PADDING, 1)<0)
|
||||
goto err;
|
||||
|
||||
tor_free(challenge);
|
||||
@ -648,6 +645,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
||||
int
|
||||
onion_skin_server_handshake(char *onion_skin, /* ONIONSKIN_CHALLENGE_LEN bytes */
|
||||
crypto_pk_env_t *private_key,
|
||||
crypto_pk_env_t *prev_private_key,
|
||||
char *handshake_reply_out, /* ONIONSKIN_REPLY_LEN bytes */
|
||||
char *key_out,
|
||||
int key_out_len)
|
||||
@ -656,11 +654,28 @@ onion_skin_server_handshake(char *onion_skin, /* ONIONSKIN_CHALLENGE_LEN bytes *
|
||||
crypto_dh_env_t *dh = NULL;
|
||||
int len;
|
||||
char *key_material=NULL;
|
||||
int i;
|
||||
crypto_pk_env_t *k;
|
||||
|
||||
if (crypto_pk_private_hybrid_decrypt(private_key,
|
||||
len = -1;
|
||||
for (i=0;i<2;++i) {
|
||||
k = i==0?private_key:prev_private_key;
|
||||
if (!k)
|
||||
break;
|
||||
len = crypto_pk_private_hybrid_decrypt(k,
|
||||
onion_skin, ONIONSKIN_CHALLENGE_LEN,
|
||||
challenge, PK_NO_PADDING)<0)
|
||||
challenge, PK_PKCS1_OAEP_PADDING);
|
||||
if (len>0)
|
||||
break;
|
||||
}
|
||||
if (len<0) {
|
||||
log_fn(LOG_WARN, "Couldn't decrypt onionskin");
|
||||
goto err;
|
||||
} else if (len != DH_KEY_LEN) {
|
||||
log_fn(LOG_WARN, "Unexpected onionskin length after decryption: %d",
|
||||
len);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dh = crypto_dh_new();
|
||||
if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN))
|
||||
|
18
src/or/or.h
18
src/or/or.h
@ -112,6 +112,9 @@
|
||||
#define MAX_DNS_ENTRY_AGE (15*60)
|
||||
#endif
|
||||
|
||||
#define MIN_ONION_KEY_LIFETIME (120*60)
|
||||
#define MAX_SSL_KEY_LIFETIME (120*60)
|
||||
|
||||
#define CIRC_ID_TYPE_LOWER 0
|
||||
#define CIRC_ID_TYPE_HIGHER 1
|
||||
|
||||
@ -381,7 +384,6 @@ struct connection_t {
|
||||
* strdup into this, because free_connection frees it
|
||||
*/
|
||||
crypto_pk_env_t *onion_pkey; /* public RSA key for the other side's onions */
|
||||
crypto_pk_env_t *link_pkey; /* public RSA key for the other side's TLS */
|
||||
crypto_pk_env_t *identity_pkey; /* public RSA key for the other side's signing */
|
||||
char *nickname;
|
||||
|
||||
@ -445,7 +447,6 @@ typedef struct {
|
||||
time_t published_on;
|
||||
|
||||
crypto_pk_env_t *onion_pkey; /* public RSA key for onions */
|
||||
crypto_pk_env_t *link_pkey; /* public RSA key for TLS */
|
||||
crypto_pk_env_t *identity_pkey; /* public RSA key for signing */
|
||||
|
||||
int is_running;
|
||||
@ -492,8 +493,10 @@ struct crypt_path_t {
|
||||
};
|
||||
|
||||
#define DH_KEY_LEN DH_BYTES
|
||||
#define ONIONSKIN_CHALLENGE_LEN (16+DH_KEY_LEN)
|
||||
#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+20)
|
||||
#define ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
|
||||
CIPHER_KEY_LEN+\
|
||||
DH_KEY_LEN)
|
||||
#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
|
||||
#define REND_COOKIE_LEN DIGEST_LEN
|
||||
|
||||
typedef struct crypt_path_t crypt_path_t;
|
||||
@ -882,6 +885,7 @@ void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
|
||||
/********************************* cpuworker.c *****************************/
|
||||
|
||||
void cpu_init(void);
|
||||
void cpuworkers_rotate(void);
|
||||
int connection_cpu_finished_flushing(connection_t *conn);
|
||||
int connection_cpu_process_inbuf(connection_t *conn);
|
||||
int cpuworker_main(void *data);
|
||||
@ -948,6 +952,7 @@ int onion_skin_create(crypto_pk_env_t *router_key,
|
||||
|
||||
int onion_skin_server_handshake(char *onion_skin,
|
||||
crypto_pk_env_t *private_key,
|
||||
crypto_pk_env_t *prev_private_key,
|
||||
char *handshake_reply_out,
|
||||
char *key_out,
|
||||
int key_out_len);
|
||||
@ -964,11 +969,13 @@ cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose,
|
||||
|
||||
void set_onion_key(crypto_pk_env_t *k);
|
||||
crypto_pk_env_t *get_onion_key(void);
|
||||
crypto_pk_env_t *get_previous_onion_key(void);
|
||||
time_t get_onion_key_set_at(void);
|
||||
void set_identity_key(crypto_pk_env_t *k);
|
||||
crypto_pk_env_t *get_identity_key(void);
|
||||
crypto_pk_env_t *get_link_key(void);
|
||||
int init_keys(void);
|
||||
crypto_pk_env_t *init_key_from_file(const char *fname);
|
||||
void rotate_onion_key(void);
|
||||
|
||||
void router_retry_connections(void);
|
||||
void router_upload_dir_desc_to_dirservers(void);
|
||||
@ -989,7 +996,6 @@ routerinfo_t *router_choose_random_node(routerlist_t *dir,
|
||||
char *preferred, char *excluded,
|
||||
struct smartlist_t *excludedsmartlist);
|
||||
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
|
||||
routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk);
|
||||
routerinfo_t *router_get_by_nickname(char *nickname);
|
||||
void router_get_routerlist(routerlist_t **prouterlist);
|
||||
void routerinfo_free(routerinfo_t *router);
|
||||
|
@ -11,12 +11,14 @@ extern or_options_t options; /* command-line and config-file options */
|
||||
/************************************************************/
|
||||
|
||||
/* private keys */
|
||||
static time_t onionkey_set_at=0;
|
||||
static crypto_pk_env_t *onionkey=NULL;
|
||||
static crypto_pk_env_t *linkkey=NULL;
|
||||
static crypto_pk_env_t *lastonionkey=NULL;
|
||||
static crypto_pk_env_t *identitykey=NULL;
|
||||
|
||||
void set_onion_key(crypto_pk_env_t *k) {
|
||||
onionkey = k;
|
||||
onionkey_set_at = time(NULL);
|
||||
}
|
||||
|
||||
crypto_pk_env_t *get_onion_key(void) {
|
||||
@ -24,15 +26,12 @@ crypto_pk_env_t *get_onion_key(void) {
|
||||
return onionkey;
|
||||
}
|
||||
|
||||
void set_link_key(crypto_pk_env_t *k)
|
||||
{
|
||||
linkkey = k;
|
||||
crypto_pk_env_t *get_previous_onion_key(void) {
|
||||
return lastonionkey;
|
||||
}
|
||||
|
||||
crypto_pk_env_t *get_link_key(void)
|
||||
{
|
||||
assert(linkkey);
|
||||
return linkkey;
|
||||
time_t get_onion_key_set_at(void) {
|
||||
return onionkey_set_at;
|
||||
}
|
||||
|
||||
void set_identity_key(crypto_pk_env_t *k) {
|
||||
@ -46,6 +45,46 @@ crypto_pk_env_t *get_identity_key(void) {
|
||||
|
||||
/************************************************************/
|
||||
|
||||
/* Replace the previous onion key with the current onion key, and generate
|
||||
* a new previous onion key. Immediately after calling this function,
|
||||
* the OR should:
|
||||
* a) shedule all previous cpuworker to shut down _after_ processing
|
||||
* pending work. (This will cause fresh cpuworkers to be generated.)
|
||||
* b) generate and upload a fresh routerinfo.
|
||||
*/
|
||||
void rotate_onion_key(void)
|
||||
{
|
||||
char fname[512];
|
||||
crypto_pk_env_t *prkey;
|
||||
sprintf(fname,"%s/keys/onion.key",options.DataDirectory);
|
||||
if (!(prkey = crypto_new_pk_env())) {
|
||||
log(LOG_ERR, "Error creating crypto environment.");
|
||||
goto error;
|
||||
}
|
||||
if (crypto_pk_generate_key(onionkey)) {
|
||||
log(LOG_ERR, "Error generating key: %s", crypto_perror());
|
||||
goto error;
|
||||
}
|
||||
if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
|
||||
log(LOG_ERR, "Couldn't write generated key to %s.", fname);
|
||||
goto error;
|
||||
}
|
||||
if (lastonionkey)
|
||||
crypto_free_pk_env(lastonionkey);
|
||||
/* XXXX WINDOWS on windows, we need to protect this next bit with a lock.
|
||||
*/
|
||||
lastonionkey = onionkey;
|
||||
set_onion_key(prkey);
|
||||
if (router_rebuild_descriptor() <0) {
|
||||
goto error;
|
||||
}
|
||||
router_upload_dir_desc_to_dirservers();
|
||||
/* Mark all CPU workers to close. */
|
||||
return;
|
||||
error:
|
||||
log_fn(LOG_WARN, "Couldn't rotate onion key.");
|
||||
}
|
||||
|
||||
/* Try to read an RSA key from 'fname'. If 'fname' doesn't exist, create a new
|
||||
* RSA key and save it in 'fname'. Return the read/created key, or NULL on
|
||||
* error.
|
||||
@ -112,7 +151,7 @@ int init_keys(void) {
|
||||
/* OP's don't need keys. Just initialize the TLS context.*/
|
||||
if (!options.ORPort) {
|
||||
assert(!options.DirPort);
|
||||
if (tor_tls_context_new(NULL, 0, NULL)<0) {
|
||||
if (tor_tls_context_new(NULL, 0, NULL, 0)<0) {
|
||||
log_fn(LOG_ERR, "Error creating TLS context for OP.");
|
||||
return -1;
|
||||
}
|
||||
@ -146,12 +185,10 @@ int init_keys(void) {
|
||||
set_onion_key(prkey);
|
||||
|
||||
/* 3. Initialize link key and TLS context. */
|
||||
strcpy(cp, "/link.key");
|
||||
log_fn(LOG_INFO,"Reading/making link key %s...",keydir);
|
||||
prkey = init_key_from_file(keydir);
|
||||
if (!prkey) return -1;
|
||||
set_link_key(prkey);
|
||||
if (tor_tls_context_new(prkey, 1, options.Nickname) < 0) {
|
||||
/* XXXX use actual rotation interval as cert lifetime, once we do
|
||||
* connection rotation. */
|
||||
if (tor_tls_context_new(get_identity_key(), 1, options.Nickname,
|
||||
MAX_SSL_KEY_LIFETIME) < 0) {
|
||||
log_fn(LOG_ERR, "Error initializing TLS context");
|
||||
return -1;
|
||||
}
|
||||
@ -370,7 +407,6 @@ int router_rebuild_descriptor(void) {
|
||||
ri->dir_port = options.DirPort;
|
||||
ri->published_on = time(NULL);
|
||||
ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
|
||||
ri->link_pkey = crypto_pk_dup_key(get_link_key());
|
||||
ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
|
||||
get_platform_str(platform, sizeof(platform));
|
||||
ri->platform = tor_strdup(platform);
|
||||
@ -403,13 +439,12 @@ void get_platform_str(char *platform, int len)
|
||||
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||
crypto_pk_env_t *ident_key) {
|
||||
char *onion_pkey;
|
||||
char *link_pkey;
|
||||
char *identity_pkey;
|
||||
struct in_addr in;
|
||||
char digest[20];
|
||||
char signature[128];
|
||||
char published[32];
|
||||
int onion_pkeylen, link_pkeylen, identity_pkeylen;
|
||||
int onion_pkeylen, identity_pkeylen;
|
||||
int written;
|
||||
int result=0;
|
||||
struct exit_policy_t *tmpe;
|
||||
@ -436,33 +471,28 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(crypto_pk_write_public_key_to_string(router->link_pkey,
|
||||
&link_pkey,&link_pkeylen)<0) {
|
||||
log_fn(LOG_WARN,"write link_pkey to string failed!");
|
||||
return -1;
|
||||
}
|
||||
strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&router->published_on));
|
||||
|
||||
/* XXXX eventually, don't include link key */
|
||||
result = snprintf(s, maxlen,
|
||||
"router %s %s %d %d %d %d\n"
|
||||
"router %s %s %d %d %d\n"
|
||||
"platform %s\n"
|
||||
"published %s\n"
|
||||
"bandwidth %d %d\n"
|
||||
"onion-key\n%s"
|
||||
"link-key\n%s"
|
||||
"signing-key\n%s",
|
||||
router->nickname,
|
||||
router->address,
|
||||
router->or_port,
|
||||
router->socks_port,
|
||||
router->dir_port,
|
||||
(int) router->bandwidthrate,
|
||||
/* XXXBC also write bandwidthburst */
|
||||
router->platform,
|
||||
published,
|
||||
onion_pkey, link_pkey, identity_pkey);
|
||||
(int) router->bandwidthrate,
|
||||
(int) router->bandwidthburst,
|
||||
onion_pkey, identity_pkey);
|
||||
|
||||
free(onion_pkey);
|
||||
free(link_pkey);
|
||||
free(identity_pkey);
|
||||
|
||||
if(result < 0 || result >= maxlen) {
|
||||
|
@ -30,7 +30,7 @@ typedef enum {
|
||||
K_SIGNED_DIRECTORY,
|
||||
K_SIGNING_KEY,
|
||||
K_ONION_KEY,
|
||||
K_LINK_KEY,
|
||||
K_LINK_KEY, /* XXXX obsolete */
|
||||
K_ROUTER_SIGNATURE,
|
||||
K_PUBLISHED,
|
||||
K_RUNNING_ROUTERS,
|
||||
@ -83,7 +83,7 @@ static struct {
|
||||
char *t; int v; arg_syntax s; obj_syntax os; where_syntax ws;
|
||||
} token_table[] = {
|
||||
{ "accept", K_ACCEPT, ARGS, NO_OBJ, RTR_ONLY },
|
||||
{ "directory-signature", K_DIRECTORY_SIGNATURE, NO_ARGS, NEED_OBJ, DIR_ONLY},
|
||||
{ "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ, DIR_ONLY},
|
||||
{ "reject", K_REJECT, ARGS, NO_OBJ, RTR_ONLY },
|
||||
{ "router", K_ROUTER, ARGS, NO_OBJ, RTR_ONLY },
|
||||
{ "recommended-software", K_RECOMMENDED_SOFTWARE, ARGS, NO_OBJ, DIR_ONLY },
|
||||
@ -305,21 +305,6 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk)
|
||||
{
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
|
||||
assert(routerlist);
|
||||
|
||||
for(i=0;i<smartlist_len(routerlist->routers);i++) {
|
||||
router = smartlist_get(routerlist->routers, i);
|
||||
if (0 == crypto_pk_cmp_keys(router->link_pkey, pk))
|
||||
return router;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
routerinfo_t *router_get_by_nickname(char *nickname)
|
||||
{
|
||||
int i;
|
||||
@ -354,8 +339,6 @@ void routerinfo_free(routerinfo_t *router)
|
||||
tor_free(router->platform);
|
||||
if (router->onion_pkey)
|
||||
crypto_free_pk_env(router->onion_pkey);
|
||||
if (router->link_pkey)
|
||||
crypto_free_pk_env(router->link_pkey);
|
||||
if (router->identity_pkey)
|
||||
crypto_free_pk_env(router->identity_pkey);
|
||||
while (router->exit_policy) {
|
||||
@ -380,8 +363,6 @@ routerinfo_t *routerinfo_copy(const routerinfo_t *router)
|
||||
r->platform = tor_strdup(r->platform);
|
||||
if (r->onion_pkey)
|
||||
r->onion_pkey = crypto_pk_dup_key(r->onion_pkey);
|
||||
if (r->link_pkey)
|
||||
r->link_pkey = crypto_pk_dup_key(r->link_pkey);
|
||||
if (r->identity_pkey)
|
||||
r->identity_pkey = crypto_pk_dup_key(r->identity_pkey);
|
||||
e = &r->exit_policy;
|
||||
@ -949,10 +930,10 @@ routerinfo_t *router_get_entry_from_string(const char *s,
|
||||
}
|
||||
|
||||
router = tor_malloc_zero(sizeof(routerinfo_t));
|
||||
router->onion_pkey = router->identity_pkey = router->link_pkey = NULL;
|
||||
router->onion_pkey = router->identity_pkey = NULL;
|
||||
ports_set = bw_set = 0;
|
||||
|
||||
if (tok->n_args == 2 || tok->n_args == 6) {
|
||||
if (tok->n_args == 2 || tok->n_args == 5 || tok->n_args == 6) {
|
||||
router->nickname = tor_strdup(tok->args[0]);
|
||||
if (strlen(router->nickname) > MAX_NICKNAME_LEN) {
|
||||
log_fn(LOG_WARN,"Router nickname too long.");
|
||||
@ -966,15 +947,20 @@ routerinfo_t *router_get_entry_from_string(const char *s,
|
||||
router->address = tor_strdup(tok->args[1]);
|
||||
router->addr = 0;
|
||||
|
||||
if (tok->n_args == 6) {
|
||||
if (tok->n_args >= 5) {
|
||||
router->or_port = atoi(tok->args[2]);
|
||||
router->socks_port = atoi(tok->args[3]);
|
||||
router->dir_port = atoi(tok->args[4]);
|
||||
ports_set = 1;
|
||||
/* XXXX Remove this after everyone has moved to 0.0.6 */
|
||||
if (tok->n_args == 6) {
|
||||
router->bandwidthrate = atoi(tok->args[5]);
|
||||
ports_set = bw_set = 1;
|
||||
router->bandwidthburst = router->bandwidthrate * 10;
|
||||
bw_set = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_fn(LOG_WARN,"Wrong # of arguments to \"router\"");
|
||||
log_fn(LOG_WARN,"Wrong # of arguments to \"router\" (%d)",tok->n_args);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -998,11 +984,12 @@ routerinfo_t *router_get_entry_from_string(const char *s,
|
||||
log_fn(LOG_WARN,"Redundant bandwidth line");
|
||||
goto err;
|
||||
} else if (tok) {
|
||||
if (tok->n_args < 1) {
|
||||
if (tok->n_args < 2) {
|
||||
log_fn(LOG_WARN,"Not enough arguments to \"bandwidth\"");
|
||||
goto err;
|
||||
}
|
||||
router->bandwidthrate = atoi(tok->args[0]);
|
||||
router->bandwidthburst = atoi(tok->args[1]);
|
||||
bw_set = 1;
|
||||
}
|
||||
|
||||
@ -1020,12 +1007,9 @@ routerinfo_t *router_get_entry_from_string(const char *s,
|
||||
router->onion_pkey = tok->key;
|
||||
tok->key = NULL; /* Prevent free */
|
||||
|
||||
if (!(tok = find_first_by_keyword(tokens, K_LINK_KEY))) {
|
||||
log_fn(LOG_WARN, "Missing onion key"); goto err;
|
||||
if ((tok = find_first_by_keyword(tokens, K_LINK_KEY))) {
|
||||
log_fn(LOG_INFO, "Skipping obsolete link-key"); goto err;
|
||||
}
|
||||
/* XXX Check key length */
|
||||
router->link_pkey = tok->key;
|
||||
tok->key = NULL; /* Prevent free */
|
||||
|
||||
if (!(tok = find_first_by_keyword(tokens, K_SIGNING_KEY))) {
|
||||
log_fn(LOG_WARN, "Missing onion key"); goto err;
|
||||
@ -1077,16 +1061,6 @@ routerinfo_t *router_get_entry_from_string(const char *s,
|
||||
router->platform = tor_strdup("<unknown>");
|
||||
}
|
||||
|
||||
#if XXXBC
|
||||
router->bandwidthburst = atoi(ARGS[6]);
|
||||
if (!router->bandwidthburst) {
|
||||
log_fn(LOG_WARN,"bandwidthburst unreadable or 0. Failing.");
|
||||
goto err;
|
||||
}
|
||||
#else
|
||||
router->bandwidthburst = 10*router->bandwidthrate;
|
||||
#endif
|
||||
|
||||
log_fn(LOG_DEBUG,"or_port %d, socks_port %d, dir_port %d, bandwidthrate %u, bandwidthburst %u.",
|
||||
router->or_port, router->socks_port, router->dir_port,
|
||||
(unsigned) router->bandwidthrate, (unsigned) router->bandwidthburst);
|
||||
|
@ -650,7 +650,7 @@ test_onion_handshake() {
|
||||
/* server handshake */
|
||||
memset(s_buf, 0, ONIONSKIN_REPLY_LEN);
|
||||
memset(s_keys, 0, 40);
|
||||
test_assert(! onion_skin_server_handshake(c_buf, pk, s_buf, s_keys, 40));
|
||||
test_assert(! onion_skin_server_handshake(c_buf, pk, NULL, s_buf, s_keys, 40));
|
||||
|
||||
/* client handshake 2 */
|
||||
memset(c_keys, 0, 40);
|
||||
@ -701,8 +701,8 @@ test_dir_format()
|
||||
r1.dir_port = 9003;
|
||||
r1.onion_pkey = pk1;
|
||||
r1.identity_pkey = pk2;
|
||||
r1.link_pkey = pk3;
|
||||
r1.bandwidthrate = r1.bandwidthburst = 1000;
|
||||
r1.bandwidthrate = 1000;
|
||||
r1.bandwidthburst = 5000;
|
||||
r1.exit_policy = NULL;
|
||||
r1.nickname = "Magri";
|
||||
r1.platform = tor_strdup(platform);
|
||||
@ -727,7 +727,6 @@ test_dir_format()
|
||||
r2.dir_port = 0;
|
||||
r2.onion_pkey = pk2;
|
||||
r2.identity_pkey = pk1;
|
||||
r2.link_pkey = pk2;
|
||||
r2.bandwidthrate = r2.bandwidthburst = 3000;
|
||||
r2.exit_policy = &ex1;
|
||||
r2.nickname = "Fred";
|
||||
@ -742,15 +741,14 @@ test_dir_format()
|
||||
memset(buf, 0, 2048);
|
||||
test_assert(router_dump_router_to_string(buf, 2048, &r1, pk2)>0);
|
||||
|
||||
strcpy(buf2, "router Magri testaddr1.foo.bar 9000 9002 9003 1000\n"
|
||||
strcpy(buf2, "router Magri testaddr1.foo.bar 9000 9002 9003\n"
|
||||
"platform Tor "VERSION" on ");
|
||||
strcat(buf2, get_uname());
|
||||
strcat(buf2, "\n"
|
||||
"published 1970-01-01 00:00:00\n"
|
||||
"bandwidth 1000 5000\n"
|
||||
"onion-key\n");
|
||||
strcat(buf2, pk1_str);
|
||||
strcat(buf2, "link-key\n");
|
||||
strcat(buf2, pk3_str);
|
||||
strcat(buf2, "signing-key\n");
|
||||
strcat(buf2, pk2_str);
|
||||
strcat(buf2, "router-signature\n");
|
||||
@ -767,9 +765,8 @@ test_dir_format()
|
||||
test_eq(rp1->socks_port, r1.socks_port);
|
||||
test_eq(rp1->dir_port, r1.dir_port);
|
||||
test_eq(rp1->bandwidthrate, r1.bandwidthrate);
|
||||
// test_eq(rp1->bandwidthburst, r1.bandwidthburst);
|
||||
test_eq(rp1->bandwidthburst, r1.bandwidthburst);
|
||||
test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0);
|
||||
test_assert(crypto_pk_cmp_keys(rp1->link_pkey, pk3) == 0);
|
||||
test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0);
|
||||
test_assert(rp1->exit_policy == NULL);
|
||||
|
||||
@ -908,7 +905,7 @@ main(int c, char**v){
|
||||
test_onion();
|
||||
test_onion_handshake();
|
||||
puts("\n========================= Directory Formats ===============");
|
||||
// add_stream_log(LOG_DEBUG, NULL, stdout);
|
||||
/* add_stream_log(LOG_DEBUG, NULL, stdout); */
|
||||
test_dir_format();
|
||||
puts("\n========================= Rendezvous functionality ========");
|
||||
test_rend_fns();
|
||||
|
Loading…
Reference in New Issue
Block a user