Bladeren bron

Misc small code cleanups; remove exit_server_mode(); change tor_tls_verify behavior

svn:r2073
Nick Mathewson 20 jaren geleden
bovenliggende
commit
334de84cbe
7 gewijzigde bestanden met toevoegingen van 51 en 25 verwijderingen
  1. 32 8
      src/common/tortls.c
  2. 1 1
      src/common/tortls.h
  3. 3 1
      src/or/circuitbuild.c
  4. 11 2
      src/or/connection_or.c
  5. 2 10
      src/or/main.c
  6. 0 1
      src/or/or.h
  7. 2 2
      src/or/router.c

+ 32 - 8
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:

+ 1 - 1
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);

+ 3 - 1
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);

+ 11 - 2
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 */

+ 2 - 10
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()) {

+ 0 - 1
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[]);

+ 2 - 2
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;
 }