}
/** 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;
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:
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);
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);
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;
}
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);
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 */
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);
/* 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();
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()) {
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[]);
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;
}