diff options
author | Roger Dingledine <arma@torproject.org> | 2003-09-08 10:59:00 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2003-09-08 10:59:00 +0000 |
commit | 0bac4247cabfd790fe470f08d8f11c663ae7db06 (patch) | |
tree | fcfbf850b5f804c519415abea2a2a8a4afb16222 /src/or/connection.c | |
parent | 1a9b5f9de9fd6b3b6d625e0374f31e7d665b9ef2 (diff) | |
download | tor-0bac4247cabfd790fe470f08d8f11c663ae7db06.tar.gz tor-0bac4247cabfd790fe470f08d8f11c663ae7db06.zip |
tls infrastructure now in place, give or take
svn:r434
Diffstat (limited to 'src/or/connection.c')
-rw-r--r-- | src/or/connection.c | 164 |
1 files changed, 108 insertions, 56 deletions
diff --git a/src/or/connection.c b/src/or/connection.c index 884c3fba4b..35f742180a 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -68,6 +68,7 @@ char *conn_state_to_string[][15] = { /********* END VARIABLES ************/ +static int connection_init_accepted_conn(connection_t *conn); /**************************************************************/ @@ -183,7 +184,7 @@ int connection_create_listener(struct sockaddr_in *bindaddr, int type) { return -1; } - log_fn(LOG_DEBUG,"Listening on port %u.",ntohs(bindaddr->sin_port)); + log_fn(LOG_DEBUG,"%s listening on port %u.",conn_type_to_string[type], ntohs(bindaddr->sin_port)); conn->state = LISTENER_STATE_READY; connection_start_reading(conn); @@ -191,7 +192,7 @@ int connection_create_listener(struct sockaddr_in *bindaddr, int type) { return 0; } -int connection_handle_listener_read(connection_t *conn, int new_type, int new_state) { +int connection_handle_listener_read(connection_t *conn, int new_type) { int news; /* the new socket */ connection_t *newconn; @@ -237,12 +238,73 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st return 0; /* no need to tear down the parent */ } - log(LOG_DEBUG,"connection_handle_listener_read(): socket %d entered state %d.",newconn->s, new_state); - newconn->state = new_state; - connection_start_reading(newconn); + if(connection_init_accepted_conn(newconn) < 0) { + connection_free(newconn); + return 0; + } + return 0; +} + +static int connection_init_accepted_conn(connection_t *conn) { + + connection_start_reading(conn); + + switch(conn->type) { + case CONN_TYPE_OR: +#ifdef USE_TLS + if(connection_tls_start_handshake(conn) < 0) + return -1; +#else + conn->state = OR_CONN_STATE_SERVER_AUTH_WAIT; +#endif + break; + case CONN_TYPE_AP: + conn->state = AP_CONN_STATE_SOCKS_WAIT; + break; + case CONN_TYPE_DIR: + conn->state = DIR_CONN_STATE_COMMAND_WAIT; + break; + } + return 0; +} + +#ifdef USE_TLS +int connection_tls_start_handshake(connection_t *conn) { + conn->state = OR_CONN_STATE_HANDSHAKING; + conn->tls = tor_tls_new(conn->s, options.OnionRouter); + if(!conn->tls) { + log_fn(LOG_ERR,"tor_tls_new failed. Closing."); + return -1; + } + connection_start_reading(conn); + if(connection_tls_continue_handshake(conn) < 0) + return -1; + return 0; +} +int connection_tls_continue_handshake(connection_t *conn) { + switch(tor_tls_handshake(conn->tls)) { + case TOR_TLS_ERROR: + case TOR_TLS_CLOSE: + log_fn(LOG_DEBUG,"tls error. breaking."); + return -1; + case TOR_TLS_DONE: + conn->state = OR_CONN_STATE_OPEN; + directory_set_dirty(); + connection_watch_events(conn, POLLIN); + if(!options.OnionRouter) + circuit_n_conn_open(conn); /* send the pending create */ + log_fn(LOG_DEBUG,"tls handshake done, now open."); + return 0; + case TOR_TLS_WANTWRITE: + connection_start_writing(conn); + return 0; + case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */ + return 0; + } return 0; } +#endif /* 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) { @@ -259,14 +321,14 @@ int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16 if(or_listenport) { bindaddr.sin_port = htons(or_listenport); if(!connection_get_by_type(CONN_TYPE_OR_LISTENER)) { - connection_or_create_listener(&bindaddr); + connection_create_listener(&bindaddr, CONN_TYPE_OR_LISTENER); } } if(dir_listenport) { bindaddr.sin_port = htons(dir_listenport); if(!connection_get_by_type(CONN_TYPE_DIR_LISTENER)) { - connection_dir_create_listener(&bindaddr); + connection_create_listener(&bindaddr, CONN_TYPE_DIR_LISTENER); } } @@ -274,7 +336,7 @@ int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16 bindaddr.sin_port = htons(ap_listenport); bindaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* the AP listens only on localhost! */ if(!connection_get_by_type(CONN_TYPE_AP_LISTENER)) { - connection_ap_create_listener(&bindaddr); + connection_create_listener(&bindaddr, CONN_TYPE_AP_LISTENER); } } @@ -289,31 +351,30 @@ int connection_handle_read(connection_t *conn) { switch(conn->type) { case CONN_TYPE_OR_LISTENER: - return connection_or_handle_listener_read(conn); + return connection_handle_listener_read(conn, CONN_TYPE_OR); case CONN_TYPE_AP_LISTENER: - return connection_ap_handle_listener_read(conn); + return connection_handle_listener_read(conn, CONN_TYPE_AP); case CONN_TYPE_DIR_LISTENER: - return connection_dir_handle_listener_read(conn); - default: + return connection_handle_listener_read(conn, CONN_TYPE_DIR); + } - if(connection_read_to_buf(conn) < 0) { - if(conn->type == CONN_TYPE_DIR && conn->state == DIR_CONN_STATE_CONNECTING) { - /* it's a directory server and connecting failed: forget about this router */ - /* XXX I suspect pollerr may make Windows not get to this point. :( */ - router_forget_router(conn->addr,conn->port); - /* FIXME i don't think router_forget_router works. */ - } - return -1; - } - if(connection_process_inbuf(conn) < 0) { - //log_fn(LOG_DEBUG,"connection_process_inbuf returned %d.",retval); - return -1; - } - if(!connection_state_is_open(conn) && conn->receiver_bucket == 0) { - log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing."); - return -1; - } - } /* end switch */ + if(connection_read_to_buf(conn) < 0) { + if(conn->type == CONN_TYPE_DIR && conn->state == DIR_CONN_STATE_CONNECTING) { + /* it's a directory server and connecting failed: forget about this router */ + /* XXX I suspect pollerr may make Windows not get to this point. :( */ + router_forget_router(conn->addr,conn->port); + /* FIXME i don't think router_forget_router works. */ + } + return -1; + } + if(connection_process_inbuf(conn) < 0) { + //log_fn(LOG_DEBUG,"connection_process_inbuf returned %d.",retval); + return -1; + } + if(!connection_state_is_open(conn) && conn->receiver_bucket == 0) { + log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing."); + return -1; + } return 0; } @@ -344,26 +405,22 @@ int connection_read_to_buf(connection_t *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(conn->state == OR_CONN_STATE_HANDSHAKING) + return connection_tls_continue_handshake(conn); + + /* else open, or closing */ + result = read_to_buf_tls(conn->tls, at_most, &conn->inbuf, + &conn->inbuflen, &conn->inbuf_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: + case TOR_TLS_WANTWRITE: connection_start_writing(conn); return 0; - case TOR_TLS_WANT_READ: /* we're already reading */ + case TOR_TLS_WANTREAD: /* we're already reading */ case TOR_TLS_DONE: /* no data read, so nothing to process */ return 0; } @@ -413,7 +470,6 @@ int connection_flush_buf(connection_t *conn) { /* return -1 if you want to break the conn, else return 0 */ int connection_handle_write(connection_t *conn) { struct timeval now; - int result; if(connection_is_listener(conn)) { log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!"); @@ -425,26 +481,20 @@ int connection_handle_write(connection_t *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 = flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen, - &conn->outbuf_flushlen, &conn->outbuf_datalen); - } + if(conn->state == OR_CONN_STATE_HANDSHAKING) + return connection_tls_continue_handshake(conn); - switch(result) { + /* else open, or closing */ + switch(flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen, + &conn->outbuf_flushlen, &conn->outbuf_datalen)) { 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: + case TOR_TLS_WANTWRITE: /* we're already writing */ return 0; - case TOR_TLS_WANT_READ: + case TOR_TLS_WANTREAD: /* Make sure to avoid a loop if the receive buckets are empty. */ if(!connection_is_reading(conn)) { connection_stop_writing(conn); @@ -766,7 +816,9 @@ int connection_process_cell_from_inbuf(connection_t *conn) { /* check if there's a whole cell there. * if yes, pull it off, decrypt it if we're not doing TLS, and process it. */ +#ifndef USE_TLS char networkcell[CELL_NETWORK_SIZE]; +#endif char buf[CELL_NETWORK_SIZE]; // int x; cell_t cell; |