diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/tortls.c | 40 | ||||
-rw-r--r-- | src/common/tortls.h | 2 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 4 | ||||
-rw-r--r-- | src/or/connection_or.c | 13 | ||||
-rw-r--r-- | src/or/main.c | 12 | ||||
-rw-r--r-- | src/or/or.h | 1 | ||||
-rw-r--r-- | src/or/router.c | 4 |
7 files changed, 51 insertions, 25 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c index f2b8ae039..c3ba4ae83 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -602,19 +602,39 @@ 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 signed by - * <b>identity_key</b>, return 0. Else, return -1. + * certificate that is currently valid and signed, then set + * *<b>identity_key</b> to the identity certificate's key and return + * 0. Else, return -1. */ int -tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key) +tor_tls_verify(tor_tls *tls, crypto_pk_env_t **identity_key) { - X509 *cert = NULL; + X509 *cert = NULL, *id_cert = NULL; + STACK_OF(X509) *chain = NULL; EVP_PKEY *id_pkey = NULL; + RSA *rsa; time_t now, t; - int r = -1; + int r = -1, i; + + *identity_key = NULL; if (!(cert = SSL_get_peer_certificate(tls->ssl))) - return -1; + goto done; + if (!(chain = SSL_get_peer_cert_chain(tls->ssl))) + goto done; + if (sk_X509_num(chain) != 2) { + log_fn(LOG_WARN,"Unexpected number of certificates in chain"); + goto done; + } + for (i=0; i<2; ++i) { + id_cert = sk_X509_value(chain, i); + if (X509_cmp(id_cert, cert) != 0) + break; + } + if (!id_cert) { + log_fn(LOG_WARN,"No distinct identity certificate found"); + goto done; + } now = time(NULL); t = now + CERT_ALLOW_SKEW; @@ -628,14 +648,18 @@ tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key) goto done; } - /* Get the public key. */ - if (!(id_pkey = _crypto_pk_env_get_evp_pkey(identity_key,0)) || + if (!(id_pkey = X509_get_pubkey(id_cert)) || X509_verify(cert, id_pkey) <= 0) { log_fn(LOG_WARN,"X509_verify on cert and pkey returned <= 0"); tls_log_errors(LOG_WARN,"verifying certificate"); goto done; } + rsa = EVP_PKEY_get1_RSA(id_pkey); + if (!rsa) + goto done; + *identity_key = _crypto_new_pk_env_rsa(rsa); + r = 0; done: diff --git a/src/common/tortls.h b/src/common/tortls.h index f9ffb0edc..02dbeb7a7 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -28,7 +28,7 @@ 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); -int tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity); +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); diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 1ed6b029a..980c4410c 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -114,7 +114,9 @@ void circuit_rep_hist_note_result(circuit_t *circ) { return; } if (server_mode()) { - prev_digest = router_get_my_routerinfo()->identity_digest; + routerinfo_t *me = router_get_my_routerinfo(); + tor_assert(me); + prev_digest = me->identity_digest; } do { router = router_get_by_digest(hop->identity_digest); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index d60a7f53f..860eaff4b 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -155,10 +155,12 @@ connection_or_init_conn_from_address(connection_t *conn, connection_t *connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest) { connection_t *conn; + routerinfo_t *me; tor_assert(id_digest); - if(server_mode() && 0) { /* XXX008 if I'm an OR and id_digest is my digest */ + if(server_mode() && (me=router_get_my_routerinfo()) && + !memcmp(me->identity_digest, id_digest,DIGEST_LEN)) { log_fn(LOG_WARN,"Request to connect to myself! Failing."); return NULL; } @@ -267,6 +269,7 @@ connection_tls_finish_handshake(connection_t *conn) { routerinfo_t *router; char nickname[MAX_NICKNAME_LEN+1]; connection_t *c; + crypto_pk_env_t *identity_rcvd=NULL; conn->state = OR_CONN_STATE_OPEN; connection_watch_events(conn, POLLIN); @@ -298,12 +301,18 @@ connection_tls_finish_handshake(connection_t *conn) { nickname, conn->address, conn->port); return -1; } - if(tor_tls_verify(conn->tls, router->identity_pkey)<0) { + if(tor_tls_verify(conn->tls, &identity_rcvd)<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; } log_fn(LOG_DEBUG,"The router's cert is valid."); + if(crypto_pk_cmp_keys(identity_rcvd, router->identity_pkey) != 0) { + crypto_free_pk_env(identity_rcvd); + log_fn(LOG_WARN, "Identity key not as expected for %s", nickname); + return -1; + } + crypto_free_pk_env(identity_rcvd); /* XXXX008 This isn't right; fix this one we launch by identity digest * XXXX008 rather than by nickname */ diff --git a/src/or/main.c b/src/or/main.c index 618d4a59a..9ed1dd14e 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -473,14 +473,6 @@ int advertised_server_mode(void) { return (options.ORPort != 0); } -/** Return true iff we are trying to be an exit server. - */ -int exit_server_mode(void) { - /* XXX008 NM: non-exit servers still answer resolve requests, right? How - * is this to be used? */ - return (options.ORPort != 0); -} - /** Return true iff we are trying to be a socks proxy. */ int proxy_mode(void) { return (options.SocksPort != 0); @@ -747,7 +739,7 @@ static int do_hup(void) { /* Restart cpuworker and dnsworker processes, so they get up-to-date * configuration options. */ cpuworkers_rotate(); - if (exit_server_mode()) + if (server_mode()) dnsworkers_rotate(); /* Rebuild fresh descriptor as needed. */ router_rebuild_descriptor(); @@ -1011,7 +1003,7 @@ int tor_init(int argc, char *argv[]) { log_fn(LOG_WARN,"You are running Tor as root. You don't need to, and you probably shouldn't."); #endif - if(exit_server_mode()) { /* only spawn dns handlers if we're a router */ + if(server_mode()) { /* only spawn dns handlers if we're a router */ dns_init(); /* initialize the dns resolve tree, and spawn workers */ } if(proxy_mode()) { diff --git a/src/or/or.h b/src/or/or.h index ee231bd6d..95b40e840 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1198,7 +1198,6 @@ int authdir_mode(void); int clique_mode(void); int server_mode(void); int advertised_server_mode(void); -int exit_server_mode(void); int proxy_mode(void); int main(int argc, char *argv[]); diff --git a/src/or/router.c b/src/or/router.c index f9b413db0..578370893 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -516,8 +516,8 @@ int router_rebuild_descriptor(void) { log_fn(LOG_WARN, "Couldn't dump router to string."); return -1; } - ri->is_trusted_dir = ri->dir_port && - router_digest_is_trusted_dir(ri->identity_digest); + ri->is_trusted_dir = (ri->dir_port && + router_digest_is_trusted_dir(ri->identity_digest)); return 0; } |