[or-cvs] more futzing towards tls

Roger Dingledine arma at seul.org
Sun Sep 7 10:24:42 UTC 2003


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/src/or

Modified Files:
	buffers.c connection.c connection_or.c main.c or.h 
Log Message:
more futzing towards tls
not there yet


Index: buffers.c
===================================================================
RCS file: /home/or/cvsroot/src/or/buffers.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- buffers.c	5 Sep 2003 11:25:23 -0000	1.29
+++ buffers.c	7 Sep 2003 10:24:40 -0000	1.30
@@ -129,6 +129,7 @@
 //    log_fn(LOG_DEBUG,"flushed %d bytes, %d ready to flush, %d remain.",
 //       write_result,*buf_flushlen,*buf_datalen);
     return *buf_flushlen;
+    /* XXX USE_TLS should change to return write_result like any sane function would */
   }
 }
 
@@ -136,8 +137,9 @@
 {
   int r;
   assert(tls && *buf && buflen && buf_datalen);
-  if (*buf_flushlen == 0)
-    return 0;
+
+  /* we want to let tls write even if flushlen is zero, because it might
+   * have a partial record pending */
   r = tor_tls_write(tls, *buf, *buf_flushlen);
   if (r < 0) {
     return r;

Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -d -r1.80 -r1.81
--- connection.c	5 Sep 2003 11:25:23 -0000	1.80
+++ connection.c	7 Sep 2003 10:24:40 -0000	1.81
@@ -92,7 +92,7 @@
   conn->timestamp_lastread = now.tv_sec;
   conn->timestamp_lastwritten = now.tv_sec;
 
-#ifndef TOR_TLS
+#ifndef USE_TLS
   if (connection_speaks_cells(conn)) {
     conn->f_crypto = crypto_new_cipher_env(CONNECTION_CIPHER);
     if (!conn->f_crypto) {
@@ -107,7 +107,6 @@
     }
   }
 #endif
-  conn->done_sending = conn->done_receiving = 0;
   return conn;
 }
 
@@ -123,9 +122,9 @@
 
   if(connection_speaks_cells(conn)) {
     directory_set_dirty();
-#ifdef TOR_TLS
-    if (conn->SSL)
-      crypt_SSL_free(conn->SSL);
+#ifdef USE_TLS
+    if (conn->tls)
+      tor_tls_free(conn->tls);
 #else
     if (conn->f_crypto)
       crypto_free_cipher_env(conn->f_crypto);
@@ -245,10 +244,8 @@
   return 0;
 }
 
+/* start all connections that should be up but aren't */
 int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport) {
-
-  /* start all connections that should be up but aren't */
-
   struct sockaddr_in bindaddr; /* where to bind */
 
   if(or_listenport) {
@@ -316,12 +313,13 @@
         log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing.");
         return -1;
       }
-      return 0;
   } /* end switch */
+  return 0;
 }
 
+/* return -1 if we want to break conn, else return 0 */
 int connection_read_to_buf(connection_t *conn) {
-  int read_result;
+  int result;
   int at_most;
 
   assert((connection_speaks_cells(conn) && conn->receiver_bucket >= 0) ||
@@ -344,27 +342,51 @@
   if(conn->receiver_bucket >= 0 && at_most > conn->receiver_bucket)
     at_most = conn->receiver_bucket;
 
-  read_result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen,
-                            &conn->inbuf_datalen, &conn->inbuf_reached_eof);
-//  log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);
-  if(read_result >= 0) {
-    global_read_bucket -= read_result; assert(global_read_bucket >= 0);
-    if(connection_speaks_cells(conn))
-      conn->receiver_bucket -= read_result;
-    if(conn->receiver_bucket == 0 || global_read_bucket == 0) {
-      log_fn(LOG_DEBUG,"buckets (%d, %d) exhausted. Pausing.", global_read_bucket, conn->receiver_bucket);
-      conn->wants_to_read = 1;
-      connection_stop_reading(conn);
+#ifdef USE_TLS
+  if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) {
+    if(conn->state == OR_CONN_STATE_HANDSHAKING) {
+      result = tor_tls_handshake(conn->tls)
+      if(result == TOR_TLS_DONE) {
+        conn->state = OR_CONN_STATE_OPEN;
+        log_fn(LOG_DEBUG,"tls handshake done, now open.");
+      }
+    } else { /* open, or closing */
+      result = read_to_buf_tls(conn->tls, at_most, &conn->inbuf,
+                                    &conn->inbuflen, &conn->inbuf_datalen);
+    }
 
-      /* If we're not in 'open' state here, then we're never going to finish the
-       * handshake, because we'll never increment the receiver_bucket. But we
-       * can't check for that here, because the buf we just read might have enough
-       * on it to finish the handshake. So we check for that in connection_handle_read().
-       */
+    switch(result) {
+      case TOR_TLS_ERROR:
+      case TOR_TLS_CLOSE:
+        log_fn(LOG_DEBUG,"tls error. breaking.");
+        return -1; /* XXX deal with close better */
+      case TOR_TLS_WANT_WRITE:
+        connection_start_writing(conn);
+        return 0;
+      case TOR_TLS_WANT_READ: /* we're already reading */
+      case TOR_TLS_DONE: /* no data read, so nothing to process */
+        return 0;
     }
+  } else
+#endif
+  {
+    result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen,
+                         &conn->inbuf_datalen, &conn->inbuf_reached_eof);
+//  log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);
+
+    if(result < 0)
+      return -1;
   }
 
-  return read_result;
+  global_read_bucket -= result; assert(global_read_bucket >= 0);
+  if(connection_speaks_cells(conn))
+    conn->receiver_bucket -= result;
+  if(conn->receiver_bucket == 0 || global_read_bucket == 0) {
+    log_fn(LOG_DEBUG,"buckets (%d, %d) exhausted. Pausing.", global_read_bucket, conn->receiver_bucket);
+    conn->wants_to_read = 1;
+    connection_stop_reading(conn);
+  }
+  return 0;
 }
 
 int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
@@ -388,9 +410,10 @@
                    &conn->outbuf_flushlen, &conn->outbuf_datalen);
 }
 
+/* return -1 if you want to break the conn, else return 0 */
 int connection_handle_write(connection_t *conn) {
   struct timeval now;
-  int retval;
+  int result;
 
   if(connection_is_listener(conn)) {
     log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!");
@@ -400,25 +423,57 @@
   my_gettimeofday(&now);
   conn->timestamp_lastwritten = now.tv_sec;
 
-#ifdef TOR_TLS
-  if(connection_speaks_cells(conn)) {
-    retval = flush_buf_SSL(conn->SSL, &conn->outbuf, &conn->outbuflen,
-                           &conn->outbuf_flushlen, &conn->outbuf_datalen);
-    ...
+#ifdef USE_TLS
+  if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING) {
+    if(conn->state == OR_CONN_STATE_HANDSHAKING) {
+      result = tor_tls_handshake(conn->tls)
+      if(result == TOR_TLS_DONE) {
+        conn->state = OR_CONN_STATE_OPEN;
+        log_fn(LOG_DEBUG,"tls handshake done, now open.");
+      }
+    } else { /* open, or closing */
+      result = flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen,
+                             &conn->outbuf_flushlen, &conn->outbuf_datalen);
+    }
 
+    switch(result) {
+      case TOR_TLS_ERROR:
+      case TOR_TLS_CLOSE:
+        log_fn(LOG_DEBUG,"tls error. breaking.");
+        return -1; /* XXX deal with close better */
+      case TOR_TLS_WANT_WRITE:
+        /* we're already writing */
+        return 0;
+      case TOR_TLS_WANT_READ:
+        /* Make sure to avoid a loop if the receive buckets are empty. */
+        if(!connection_is_reading(conn)) {
+          connection_stop_writing(conn);
+          conn->wants_to_write = 1;
+          /* we'll start reading again when the next second arrives,
+           * and then also start writing again.
+           */
+        }
+        /* else no problem, we're already reading */
+        return 0;
+      case TOR_TLS_DONE:
+      /* for TOR_TLS_DONE, fall through to check if the flushlen
+       * is empty, so we can stop writing.
+       */  
+    }
   } else
 #endif
   {
-    retval = flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
-                       &conn->outbuf_flushlen, &conn->outbuf_datalen);
-        /* conns in CONNECTING state will fall through... */
-
-    if(retval == 0) { /* it's done flushing */
-      retval = connection_finished_flushing(conn); /* ...and get handled here. */
-    }
+    if(flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
+                 &conn->outbuf_flushlen, &conn->outbuf_datalen) < 0)
+      return -1;
+      /* conns in CONNECTING state will fall through... */
   }
 
-  return retval;
+  if(!connection_wants_to_flush(conn)) /* it's done flushing */
+    if(connection_finished_flushing(conn) < 0) /* ...and get handled here. */
+      return -1;
+
+  return 0;
 }
 
 int connection_write_to_buf(char *string, int len, connection_t *conn) {
@@ -496,13 +551,16 @@
  
   cell_pack(n, cellp);
 
+#ifndef USE_TLS
   if(connection_encrypt_cell(n,conn)<0) {
     return -1;
   }
+#endif
 
   return connection_write_to_buf(n, CELL_NETWORK_SIZE, conn);
 }
 
+#ifndef USE_TLS
 int connection_encrypt_cell(char *cellp, connection_t *conn) {
   char cryptcell[CELL_NETWORK_SIZE];
 #if 0
@@ -535,6 +593,7 @@
   memcpy(cellp,cryptcell,CELL_NETWORK_SIZE);
   return 0;
 }
+#endif
 
 int connection_process_inbuf(connection_t *conn) {
 
@@ -705,18 +764,20 @@
 
 int connection_process_cell_from_inbuf(connection_t *conn) {
   /* check if there's a whole cell there.
-   * if yes, pull it off, decrypt it, and process it.
+   * if yes, pull it off, decrypt it if we're not doing TLS, and process it.
    */
-  char crypted[CELL_NETWORK_SIZE];
-  char outbuf[1024];
+  char networkcell[CELL_NETWORK_SIZE];
+  char buf[CELL_NETWORK_SIZE];
 //  int x;
   cell_t cell;
 
   if(conn->inbuf_datalen < CELL_NETWORK_SIZE) /* entire response available? */
     return 0; /* not yet */
 
-  connection_fetch_from_buf(crypted,CELL_NETWORK_SIZE,conn);
-
+#ifdef USE_TLS
+  connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn);
+#else
+  connection_fetch_from_buf(networkcell, CELL_NETWORK_SIZE, conn);
 #if 0
   printf("Cell header crypttext: ");
   for(x=0;x<8;x++) {
@@ -725,7 +786,7 @@
   printf("\n");
 #endif
   /* decrypt */
-  if(crypto_cipher_decrypt(conn->b_crypto,crypted,CELL_NETWORK_SIZE,outbuf)) {
+  if(crypto_cipher_decrypt(conn->b_crypto, networkcell, CELL_NETWORK_SIZE, buf)) {
     log_fn(LOG_ERR,"Decryption failed, dropping.");
     return connection_process_inbuf(conn); /* process the remainder of the buffer */
   }
@@ -737,9 +798,10 @@
   }
   printf("\n");
 #endif
+#endif
 
-  /* retrieve cell info from outbuf (create the host-order struct from the network-order string) */
-  cell_unpack(&cell, outbuf);
+  /* retrieve cell info from buf (create the host-order struct from the network-order string) */
+  cell_unpack(&cell, buf);
 
 //  log_fn(LOG_DEBUG,"Decrypted cell is of type %u (ACI %u).",cellp->command,cellp->aci);
   command_process_cell(&cell, conn);

Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- connection_or.c	5 Sep 2003 06:04:03 -0000	1.41
+++ connection_or.c	7 Sep 2003 10:24:40 -0000	1.42
@@ -6,7 +6,7 @@
 
 extern or_options_t options; /* command-line and config-file options */
 
-#ifndef TOR_TLS
+#ifndef USE_TLS
 static int or_handshake_op_send_keys(connection_t *conn);
 static int or_handshake_op_finished_sending_keys(connection_t *conn);
 
@@ -35,17 +35,18 @@
     return -1;
   }
 
+#ifdef USE_TLS
+  assert(conn->state == OR_CONN_STATE_OPEN);
+  return connection_process_cell_from_inbuf(conn);
+#else
 //  log(LOG_DEBUG,"connection_or_process_inbuf(): state %d.",conn->state);
-
   switch(conn->state) {
-#ifndef TOR_TLS
     case OR_CONN_STATE_CLIENT_AUTH_WAIT:
       return or_handshake_client_process_auth(conn);
     case OR_CONN_STATE_SERVER_AUTH_WAIT:
       return or_handshake_server_process_auth(conn);
     case OR_CONN_STATE_SERVER_NONCE_WAIT:
       return or_handshake_server_process_nonce(conn);
-#endif
     case OR_CONN_STATE_OPEN:
       return connection_process_cell_from_inbuf(conn);
     default:
@@ -53,6 +54,7 @@
   }
 
   return 0;
+#endif
 }
 
 int connection_or_finished_flushing(connection_t *conn) {
@@ -61,9 +63,13 @@
   assert(conn && conn->type == CONN_TYPE_OR);
 
   switch(conn->state) {
+#ifndef USE_TLS
     case OR_CONN_STATE_OP_SENDING_KEYS:
       return or_handshake_op_finished_sending_keys(conn);
     case OR_CONN_STATE_CLIENT_CONNECTING:
+#else
+    case OR_CONN_STATE_CONNECTING:
+#endif
       if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, (void*)&e, &len) < 0)  { /* not yet */
         if(!ERRNO_CONN_EINPROGRESS(errno)){
           /* yuck. kill it. */
@@ -78,6 +84,9 @@
       log_fn(LOG_DEBUG,"OR connection to router %s:%u established.",
           conn->address,conn->port);
 
+#ifdef USE_TLS
+      call TLS new, and start the TLS handshake
+#else
       if(options.OnionRouter)
         return or_handshake_client_send_auth(conn);
       else
@@ -98,17 +107,14 @@
       conn->state = OR_CONN_STATE_SERVER_NONCE_WAIT;
       connection_watch_events(conn, POLLIN);
       return 0;
+#endif
     case OR_CONN_STATE_OPEN:
-      /* FIXME down the road, we'll clear out circuits that are pending to close */
       connection_stop_writing(conn);
       return 0;
     default:
-      log_fn(LOG_DEBUG,"BUG: called in unexpected state.");
+      log_fn(LOG_ERR,"BUG: called in unexpected state.");
       return 0;
   }
-
-  return 0;
-
 }
 
 /*********************/
@@ -659,7 +665,7 @@
   connection_watch_events(conn, POLLIN);
 }
 
-#ifndef TOR_TLS
+#ifndef USE_TLS
 static void 
 conn_or_init_crypto(connection_t *conn) {
   //int x;

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -d -r1.87 -r1.88
--- main.c	5 Sep 2003 06:04:03 -0000	1.87
+++ main.c	7 Sep 2003 10:24:40 -0000	1.88
@@ -212,6 +212,10 @@
   poll_array[conn->poll_index].events = events;
 }
 
+int connection_is_reading(connection_t *conn) {
+  return poll_array[conn->poll_index].events & POLLIN;
+}
+
 void connection_stop_reading(connection_t *conn) {
 
   assert(conn && conn->poll_index < nfds);
@@ -312,8 +316,7 @@
 
 static int prepare_for_poll(void) {
   int i;
-//  connection_t *conn = NULL;
-  connection_t *tmpconn;
+  connection_t *conn;
   struct timeval now; //soonest;
   static long current_second = 0; /* from previous calls to gettimeofday */
   static long time_to_fetch_directory = 0;
@@ -355,37 +358,41 @@
 
     /* do housekeeping for each connection */
     for(i=0;i<nfds;i++) {
-      tmpconn = connection_array[i];
-      if(connection_receiver_bucket_should_increase(tmpconn)) {
-        tmpconn->receiver_bucket += tmpconn->bandwidth;
-//        log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, tmpconn->receiver_bucket);
+      conn = connection_array[i];
+      if(connection_receiver_bucket_should_increase(conn)) {
+        conn->receiver_bucket += conn->bandwidth;
+//        log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, conn->receiver_bucket);
       }
 
-      if(tmpconn->wants_to_read == 1 /* it's marked to turn reading back on now */
+      if(conn->wants_to_read == 1 /* it's marked to turn reading back on now */
          && global_read_bucket > 0 /* and we're allowed to read */
-         && tmpconn->receiver_bucket != 0) { /* and either an edge conn or non-empty bucket */
-        tmpconn->wants_to_read = 0;
-        connection_start_reading(tmpconn);
+         && conn->receiver_bucket != 0) { /* and either an edge conn or non-empty bucket */
+        conn->wants_to_read = 0;
+        connection_start_reading(conn);
+	if(conn->wants_to_write == 1) {
+          conn->wants_to_write = 0;
+          connection_start_writing(conn);
+        }
       }
 
       /* check connections to see whether we should send a keepalive, expire, or wait */
-      if(!connection_speaks_cells(tmpconn))
+      if(!connection_speaks_cells(conn))
         continue; /* this conn type doesn't send cells */
-      if(now.tv_sec >= tmpconn->timestamp_lastwritten + options.KeepalivePeriod) {
-        if((!options.OnionRouter && !circuit_get_by_conn(tmpconn)) ||
-           (!connection_state_is_open(tmpconn))) {
+      if(now.tv_sec >= conn->timestamp_lastwritten + options.KeepalivePeriod) {
+        if((!options.OnionRouter && !circuit_get_by_conn(conn)) ||
+           (!connection_state_is_open(conn))) {
           /* we're an onion proxy, with no circuits; or our handshake has expired. kill it. */
           log(LOG_DEBUG,"prepare_for_poll(): Expiring connection to %d (%s:%d).",
-              i,tmpconn->address, tmpconn->port);
-          tmpconn->marked_for_close = 1;
+              i,conn->address, conn->port);
+          conn->marked_for_close = 1;
         } else {
           /* either a full router, or we've got a circuit. send a padding cell. */
 //          log(LOG_DEBUG,"prepare_for_poll(): Sending keepalive to (%s:%d)",
-//              tmpconn->address, tmpconn->port);
+//              conn->address, conn->port);
           memset(&cell,0,sizeof(cell_t));
           cell.command = CELL_PADDING;
-          if(connection_write_cell_to_buf(&cell, tmpconn) < 0)
-            tmpconn->marked_for_close = 1;
+          if(connection_write_cell_to_buf(&cell, conn) < 0)
+            conn->marked_for_close = 1;
         }
       }
     }
@@ -441,6 +448,10 @@
     }
     set_signing_privatekey(prkey);
   }
+
+#ifdef USE_TLS
+  make the tls context here 
+#endif
 
   /* start up the necessary connections based on which ports are
    * non-zero. This is where we try to connect to all the other ORs,

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.113
retrieving revision 1.114
diff -u -d -r1.113 -r1.114
--- or.h	5 Sep 2003 11:25:24 -0000	1.113
+++ or.h	7 Sep 2003 10:24:40 -0000	1.114
@@ -283,6 +283,9 @@
   uint8_t wants_to_read; /* should we start reading again once
                           * the bandwidth throttler allows it?
                           */
+  uint8_t wants_to_write; /* should we start writing again once
+                           * the bandwidth throttler allows reads?
+                           */
   int s; /* our socket */
   int poll_index; /* index of this conn into the poll_array */
   int marked_for_close; /* should we close this conn on the next
@@ -642,7 +645,9 @@
 
 int connection_send_destroy(aci_t aci, connection_t *conn);
 int connection_send_connected(aci_t aci, connection_t *conn);
+#ifndef USE_TLS
 int connection_encrypt_cell(char *cellp, connection_t *conn);
+#endif
 int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn);
 
 int connection_process_inbuf(connection_t *conn);
@@ -751,6 +756,7 @@
 connection_t *connection_get_by_type_state_lastwritten(int type, int state);
 
 void connection_watch_events(connection_t *conn, short events);
+int connection_is_reading(connection_t *conn);
 void connection_stop_reading(connection_t *conn);
 void connection_start_reading(connection_t *conn);
 void connection_stop_writing(connection_t *conn);



More information about the tor-commits mailing list