diff --git a/src/or/Makefile.am b/src/or/Makefile.am index e1092f4181..9c937ae0a0 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -5,14 +5,14 @@ noinst_PROGRAMS = test bin_PROGRAMS = or or_SOURCES = buffers.c circuit.c command.c connection.c \ - connection_exit.c connection_ap.c connection_op.c connection_or.c config.c \ + connection_exit.c connection_ap.c connection_or.c config.c \ onion.c routers.c directory.c dns.c connection_edge.c \ main.c tor_main.c or_LDADD = ../common/libor.a -lz test_SOURCES = buffers.c circuit.c command.c connection.c \ - connection_exit.c connection_ap.c connection_op.c connection_or.c config.c \ + connection_exit.c connection_ap.c connection_or.c config.c \ onion.c routers.c directory.c dns.c connection_edge.c \ main.c test.c diff --git a/src/or/circuit.c b/src/or/circuit.c index e3e42dbd55..a05c440e1b 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -683,14 +683,14 @@ int circuit_establish_circuit(void) { if(!n_conn || n_conn->state != OR_CONN_STATE_OPEN) { /* not currently connected */ circ->n_addr = firsthop->addr; circ->n_port = firsthop->or_port; - if(options.ORPort) { /* we would be connected if he were up. but he's not. */ + if(options.OnionRouter) { /* we would be connected if he were up. but he's not. */ log(LOG_DEBUG,"circuit_establish_circuit(): Route's firsthop isn't connected."); circuit_close(circ); return -1; } if(!n_conn) { /* launch the connection */ - n_conn = connection_or_connect_as_op(firsthop); + n_conn = connection_or_connect(firsthop); if(!n_conn) { /* connect failed, forget the whole thing */ log(LOG_DEBUG,"circuit_establish_circuit(): connect to firsthop failed. Closing."); circuit_close(circ); diff --git a/src/or/config.c b/src/or/config.c index 6107a7eeb6..8ef150b05b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -182,7 +182,6 @@ void config_assign(or_options_t *options, struct config_line *list) { /* int options */ config_compare(list, "MaxConn", CONFIG_TYPE_INT, &options->MaxConn) || config_compare(list, "APPort", CONFIG_TYPE_INT, &options->APPort) || - config_compare(list, "OPPort", CONFIG_TYPE_INT, &options->OPPort) || config_compare(list, "ORPort", CONFIG_TYPE_INT, &options->ORPort) || config_compare(list, "DirPort", CONFIG_TYPE_INT, &options->DirPort) || config_compare(list, "DirFetchPeriod", CONFIG_TYPE_INT, &options->DirFetchPeriod) || @@ -190,6 +189,7 @@ void config_assign(or_options_t *options, struct config_line *list) { config_compare(list, "MaxOnionsPending",CONFIG_TYPE_INT, &options->MaxOnionsPending) || config_compare(list, "NewCircuitPeriod",CONFIG_TYPE_INT, &options->NewCircuitPeriod) || + config_compare(list, "OnionRouter", CONFIG_TYPE_BOOL, &options->OnionRouter) || config_compare(list, "Daemon", CONFIG_TYPE_BOOL, &options->Daemon) || config_compare(list, "TrafficShaping", CONFIG_TYPE_BOOL, &options->TrafficShaping) || config_compare(list, "LinkPadding", CONFIG_TYPE_BOOL, &options->LinkPadding) || @@ -276,8 +276,8 @@ int getconfig(int argc, char **argv, or_options_t *options) { options->RouterFile ? options->RouterFile : "(undefined)", options->PrivateKeyFile ? options->PrivateKeyFile : "(undefined)", options->SigningPrivateKeyFile ? options->SigningPrivateKeyFile : "(undefined)"); - printf("ORPort=%d, OPPort=%d, APPort=%d DirPort=%d\n", - options->ORPort,options->OPPort, + printf("ORPort=%d, APPort=%d DirPort=%d\n", + options->ORPort, options->APPort,options->DirPort); printf("CoinWeight=%6.4f, MaxConn=%d, TrafficShaping=%d, LinkPadding=%d\n", options->CoinWeight, @@ -321,12 +321,17 @@ int getconfig(int argc, char **argv, or_options_t *options) { } if(options->ORPort < 0) { - log(LOG_ERR,"ORPort option required and must be a positive integer value."); + log(LOG_ERR,"ORPort option can't be negative."); result = -1; } - if(options->ORPort > 0 && options->PrivateKeyFile == NULL) { - log(LOG_ERR,"PrivateKeyFile option required for OR, but not found."); + if(options->OnionRouter && options->ORPort == 0) { + log(LOG_ERR,"If OnionRouter is set, then ORPort must be positive."); + result = -1; + } + + if(options->OnionRouter && options->PrivateKeyFile == NULL) { + log(LOG_ERR,"PrivateKeyFile option required for OnionRouter, but not found."); result = -1; } @@ -335,11 +340,6 @@ int getconfig(int argc, char **argv, or_options_t *options) { result = -1; } - if(options->OPPort < 0) { - log(LOG_ERR,"OPPort option can't be negative."); - result = -1; - } - if(options->APPort < 0) { log(LOG_ERR,"APPort option can't be negative."); result = -1; diff --git a/src/or/connection.c b/src/or/connection.c index f8fd2f5f69..80be8664a5 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -242,8 +242,7 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st return 0; } -int retry_all_connections(uint16_t or_listenport, - uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport) { +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 */ @@ -264,13 +263,6 @@ int retry_all_connections(uint16_t or_listenport, } } - if(op_listenport) { - bindaddr.sin_port = htons(op_listenport); - if(!connection_get_by_type(CONN_TYPE_OP_LISTENER)) { - connection_op_create_listener(&bindaddr); - } - } - if(dir_listenport) { bindaddr.sin_port = htons(dir_listenport); if(!connection_get_by_type(CONN_TYPE_DIR_LISTENER)) { @@ -450,18 +442,8 @@ void connection_increment_receiver_bucket(connection_t *conn) { } } -int connection_speaks_cells(connection_t *conn) { - assert(conn); - - if(conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_OP) - return 1; - - return 0; -} - int connection_is_listener(connection_t *conn) { - if(conn->type == CONN_TYPE_OP_LISTENER || - conn->type == CONN_TYPE_OR_LISTENER || + if(conn->type == CONN_TYPE_OR_LISTENER || conn->type == CONN_TYPE_AP_LISTENER || conn->type == CONN_TYPE_DIR_LISTENER) return 1; @@ -472,7 +454,6 @@ int connection_state_is_open(connection_t *conn) { assert(conn); if((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) || - (conn->type == CONN_TYPE_OP && conn->state == OP_CONN_STATE_OPEN) || (conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) || (conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN)) return 1; @@ -629,8 +610,6 @@ int connection_process_inbuf(connection_t *conn) { assert(conn); switch(conn->type) { - case CONN_TYPE_OP: - return connection_op_process_inbuf(conn); case CONN_TYPE_OR: return connection_or_process_inbuf(conn); case CONN_TYPE_EXIT: @@ -787,8 +766,6 @@ int connection_finished_flushing(connection_t *conn) { // log(LOG_DEBUG,"connection_finished_flushing() entered. Socket %u.", conn->s); switch(conn->type) { - case CONN_TYPE_OP: - return connection_op_finished_flushing(conn); case CONN_TYPE_OR: return connection_or_finished_flushing(conn); case CONN_TYPE_AP: diff --git a/src/or/connection_op.c b/src/or/connection_op.c deleted file mode 100644 index 38f334d6dd..0000000000 --- a/src/or/connection_op.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */ -/* See LICENSE for licensing information */ -/* $Id$ */ - -#include "or.h" - -int connection_op_process_inbuf(connection_t *conn) { - - assert(conn && conn->type == CONN_TYPE_OP); - - if(conn->inbuf_reached_eof) { - /* eof reached, kill it. */ - log(LOG_DEBUG,"connection_op_process_inbuf(): conn reached eof. Closing."); - return -1; - } - - log(LOG_DEBUG,"connection_op_process_inbuf(): state %d.",conn->state); - - switch(conn->state) { - case OP_CONN_STATE_AWAITING_KEYS: - return op_handshake_process_keys(conn); - case OP_CONN_STATE_OPEN: - return connection_process_cell_from_inbuf(conn); - default: - log(LOG_DEBUG,"connection_op_process_inbuf() called in state where I'm writing. Ignoring buf for now.") -; - } - - return 0; -} - -int op_handshake_process_keys(connection_t *conn) { - int retval; - //int x; - unsigned char iv[16]; - - /* key exchange message */ - unsigned char auth_cipher[128]; - unsigned char auth_plain[128]; - - assert(conn); - - log(LOG_DEBUG,"op_handshake_process_keys() entered."); - - if(conn->inbuf_datalen < 128) /* entire response available? */ - return 0; /* not yet */ - - if(connection_fetch_from_buf(auth_cipher,128,conn) < 0) { - return -1; - } - log(LOG_DEBUG,"op_handshake_process_keys() : Received auth."); - - /* decrypt response */ - retval = crypto_pk_private_decrypt(get_privatekey(), auth_cipher, 128, auth_plain,RSA_PKCS1_PADDING); - if (retval == -1) - { - log(LOG_ERR,"Decrypting keys from new OP failed."); - log(LOG_DEBUG,"op_handshake_process_keys() : Reason : %s.", - crypto_perror()); - return -1; - } - /* XXXX Check length */ - - log(LOG_DEBUG,"Successfully decrypted keys from new OP."); - - conn->bandwidth = ntohl(*((uint32_t *)auth_plain)); - log(LOG_DEBUG,"op_handshake_process_keys(): Bandwidth %d requested.",conn->bandwidth); - - crypto_cipher_set_key(conn->b_crypto, auth_plain+4); - crypto_cipher_set_key(conn->f_crypto, auth_plain+20); -#if 0 - printf("f_session_key: "); - for(x=0;x<8;x++) { - printf("%d ",conn->f_crypto->key[x]); - } - printf("\nb_session_key: "); - for(x=0;x<8;x++) { - printf("%d ",conn->b_crypto->key[x]); - } - printf("\n"); -#endif - - memset(iv, 0, 16); - crypto_cipher_set_iv(conn->b_crypto, iv); - crypto_cipher_set_iv(conn->f_crypto, iv); - - crypto_cipher_encrypt_init_cipher(conn->b_crypto); - crypto_cipher_decrypt_init_cipher(conn->f_crypto); - - conn->state = OP_CONN_STATE_OPEN; - connection_init_timeval(conn); - connection_watch_events(conn, POLLIN); - - return connection_process_inbuf(conn); /* in case they sent some cells along with the keys */ -} - -int connection_op_finished_flushing(connection_t *conn) { - - assert(conn && conn->type == CONN_TYPE_OP); - - switch(conn->state) { - case OP_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(LOG_DEBUG,"Bug: connection_op_finished_flushing() called in unexpected state."); - return 0; - } - - return 0; - -} - -int connection_op_create_listener(struct sockaddr_in *bindaddr) { - log(LOG_DEBUG,"connection_create_op_listener starting"); - return connection_create_listener(bindaddr, CONN_TYPE_OP_LISTENER); -} - -int connection_op_handle_listener_read(connection_t *conn) { - log(LOG_NOTICE,"OP: Received a connection request. Waiting for keys."); - return connection_handle_listener_read(conn, CONN_TYPE_OP, OP_CONN_STATE_AWAITING_KEYS); -} - -/* - Local Variables: - mode:c - indent-tabs-mode:nil - c-basic-offset:2 - End: -*/ diff --git a/src/or/connection_or.c b/src/or/connection_or.c index d2446014c8..0644009125 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -3,8 +3,9 @@ /* $Id$ */ #include "or.h" +extern or_options_t options; /* command-line and config-file options */ -/* +/* * * these two functions are the main ways 'in' to connection_or * @@ -44,22 +45,6 @@ int connection_or_finished_flushing(connection_t *conn) { assert(conn && conn->type == CONN_TYPE_OR); switch(conn->state) { - case OR_CONN_STATE_OP_CONNECTING: - if (getsockopt(conn->s, SOL_SOCKET, SO_ERROR, &e, &len) < 0) { /* not yet */ - if(errno != EINPROGRESS){ - /* yuck. kill it. */ - log(LOG_DEBUG,"connection_or_finished_flushing(): in-progress connect failed. Removing."); - return -1; - } else { - return 0; /* no change, see if next time is better */ - } - } - /* the connect has finished. */ - - log(LOG_DEBUG,"connection_or_finished_flushing() : OP connection to router %s:%u established.", - conn->address,conn->port); - - return or_handshake_op_send_keys(conn); case OR_CONN_STATE_OP_SENDING_KEYS: return or_handshake_op_finished_sending_keys(conn); case OR_CONN_STATE_CLIENT_CONNECTING: @@ -77,7 +62,10 @@ int connection_or_finished_flushing(connection_t *conn) { log(LOG_DEBUG,"connection_or_finished_flushing() : OR connection to router %s:%u established.", conn->address,conn->port); - return or_handshake_client_send_auth(conn); + if(options.OnionRouter) + return or_handshake_client_send_auth(conn); + else + return or_handshake_op_send_keys(conn); case OR_CONN_STATE_CLIENT_SENDING_AUTH: log(LOG_DEBUG,"connection_or_finished_flushing(): client finished sending auth."); conn->state = OR_CONN_STATE_CLIENT_AUTH_WAIT; @@ -121,38 +109,35 @@ void conn_or_init_crypto(connection_t *conn) { unsigned char iv[16]; assert(conn); -#if 0 - printf("f_session_key: "); - for(x=0;x<8;x++) { - printf("%d ",conn->f_crypto->key[x]); - } - printf("\nb_session_key: "); - for(x=0;x<8;x++) { - printf("%d ",conn->b_crypto->key[x]); - } - printf("\n"); -#endif memset((void *)iv, 0, 16); crypto_cipher_set_iv(conn->f_crypto, iv); crypto_cipher_set_iv(conn->b_crypto, iv); - + crypto_cipher_encrypt_init_cipher(conn->f_crypto); crypto_cipher_decrypt_init_cipher(conn->b_crypto); /* always encrypt with f, always decrypt with b */ - } -/* helper function for connection_or_connect_as_or and _as_op. - * returns NULL if the connection fails. If it succeeds, it sets - * *result to 1 if connect() returned before completing, or to 2 - * if it completed, and returns the new conn. - */ -connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *result) { +connection_t *connection_or_connect(routerinfo_t *router) { connection_t *conn; struct sockaddr_in router_addr; int s; + assert(router); + + if(router_is_me(router->addr, router->or_port)) { + /* this is me! don't connect to me. */ + log(LOG_DEBUG,"connection_or_connect(): This is me. Skipping."); + return NULL; + } + + /* this function should never be called if we're already connected to router, but */ + /* check first to be sure */ + conn = connection_exact_get_by_addr_port(router->addr,router->or_port); + if(conn) + return conn; + conn = connection_new(CONN_TYPE_OR); if(!conn) { return NULL; @@ -160,14 +145,13 @@ connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *re /* set up conn so it's got all the data we need to remember */ conn->addr = router->addr; - conn->port = router->or_port; /* NOTE we store or_port here always */ + conn->port = router->or_port; conn->bandwidth = router->bandwidth; conn->pkey = crypto_pk_dup_key(router->pkey); conn->address = strdup(router->address); s=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); - if (s < 0) - { + if (s < 0) { log(LOG_ERR,"Error creating network socket."); connection_free(conn); return NULL; @@ -176,11 +160,10 @@ connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *re memset((void *)&router_addr,0,sizeof(router_addr)); router_addr.sin_family = AF_INET; - router_addr.sin_port = htons(port); + router_addr.sin_port = htons(router->or_port); router_addr.sin_addr.s_addr = htonl(router->addr); - log(LOG_DEBUG,"connection_or_connect() : Trying to connect to %s:%u.",router->address,port); - + log(LOG_DEBUG,"connection_or_connect() : Trying to connect to %s:%u.",router->address,router->or_port); if(connect(s,(struct sockaddr *)&router_addr,sizeof(router_addr)) < 0){ if(errno != EINPROGRESS){ /* yuck. kill it. */ @@ -197,9 +180,8 @@ connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *re log(LOG_DEBUG,"connection_or_connect() : connect in progress."); connection_watch_events(conn, POLLIN | POLLOUT); /* writable indicates finish, readable indicates broken link */ - *result = 1; /* connecting */ + conn->state = OR_CONN_STATE_CLIENT_CONNECTING; return conn; - } } @@ -211,62 +193,21 @@ connection_t *connection_or_connect(routerinfo_t *router, uint16_t port, int *re return NULL; } - log(LOG_DEBUG,"connection_or_connect() : Connection to router %s:%u established.",router->address,port); + log(LOG_DEBUG,"connection_or_connect() : Connection to router %s:%u established.", + router->address, router->or_port); - *result = 2; /* connection finished */ - return(conn); -} + if((options.OnionRouter && or_handshake_client_send_auth(conn) >= 0) || + (!options.OnionRouter && or_handshake_op_send_keys(conn) >= 0)) + return conn; /* success! */ -/* - * - * handshake for connecting to the op_port of an onion router - * - */ - -connection_t *connection_or_connect_as_op(routerinfo_t *router) { - connection_t *conn; - int result=0; /* so connection_or_connect() can tell us what happened */ - - assert(router); - - if(router_is_me(router->addr, router->or_port)) { - /* this is me! don't connect to me. */ - log(LOG_WARNING,"connection_or_connect_as_op(): You just asked me to connect to myself."); - return NULL; - } - - /* this function should never be called if we're already connected to router, but */ - /* check first to be sure */ - conn = connection_exact_get_by_addr_port(router->addr,router->or_port); - if(conn) - return conn; - - conn = connection_or_connect(router, router->op_port, &result); - if(!conn) - return NULL; - - assert(result != 0); /* if conn is defined, then it must have set result */ - - /* now we know it succeeded */ - if(result == 1) { - conn->state = OR_CONN_STATE_OP_CONNECTING; - return conn; - } - - if(result == 2) { - /* move to the next step in the handshake */ - if(or_handshake_op_send_keys(conn) < 0) { - connection_remove(conn); - connection_free(conn); - return NULL; - } - return conn; - } - return NULL; /* shouldn't get here; to keep gcc happy */ + /* failure */ + connection_remove(conn); + connection_free(conn); + return NULL; } int or_handshake_op_send_keys(connection_t *conn) { - unsigned char message[36]; /* bandwidth(32bits), forward key(128bits), backward key(128bits) */ + unsigned char message[38]; /* flag(16bits), bandwidth(32bits), forward key(128bits), backward key(128bits) */ unsigned char cipher[128]; int retval; @@ -282,24 +223,13 @@ int or_handshake_op_send_keys(connection_t *conn) { } log(LOG_DEBUG,"or_handshake_op_send_keys() : Generated 3DES keys."); /* compose the message */ - *(uint32_t *)message = htonl(conn->bandwidth); - memcpy((void *)(message + 4), (void *)conn->f_crypto->key, 16); - memcpy((void *)(message + 20), (void *)conn->b_crypto->key, 16); - -#if 0 - printf("f_session_key: "); - for(x=0;x<16;x++) { - printf("%d ",conn->f_crypto->key[x]); - } - printf("\nb_session_key: "); - for(x=0;x<16;x++) { - printf("%d ",conn->b_crypto->key[x]); - } - printf("\n"); -#endif + *(uint16_t *)(message) = htons(HANDSHAKE_AS_OP); + *(uint32_t *)(message+2) = htonl(conn->bandwidth); + memcpy((void *)(message+6), (void *)conn->f_crypto->key, 16); + memcpy((void *)(message+22), (void *)conn->b_crypto->key, 16); /* encrypt with RSA */ - if(crypto_pk_public_encrypt(conn->pkey, message, 36, cipher, RSA_PKCS1_PADDING) < 0) { + if(crypto_pk_public_encrypt(conn->pkey, message, 38, cipher, RSA_PKCS1_PADDING) < 0) { log(LOG_ERR,"or_handshake_op_send_keys(): Public key encryption failed."); return -1; } @@ -338,49 +268,9 @@ int or_handshake_op_finished_sending_keys(connection_t *conn) { return 0; } -/* - * - * auth handshake, as performed by OR *initiating* the connection - * - */ - -connection_t *connection_or_connect_as_or(routerinfo_t *router) { - connection_t *conn; - int result=0; /* so connection_or_connect() can tell us what happened */ - - assert(router); - - if(router_is_me(router->addr, router->or_port)) { - /* this is me! don't connect to me. */ - log(LOG_DEBUG,"connection_or_connect_as_or(): This is me. Skipping."); - return NULL; - } - - conn = connection_or_connect(router, router->or_port, &result); - if(!conn) - return NULL; - - /* now we know it succeeded */ - if(result == 1) { - conn->state = OR_CONN_STATE_CLIENT_CONNECTING; - return conn; - } - - if(result == 2) { - /* move to the next step in the handshake */ - if(or_handshake_client_send_auth(conn) < 0) { - connection_remove(conn); - connection_free(conn); - return NULL; - } - return conn; - } - return NULL; /* shouldn't get here; to keep gcc happy */ -} - int or_handshake_client_send_auth(connection_t *conn) { int retval; - char buf[48]; + char buf[50]; char cipher[128]; struct sockaddr_in me; /* my router identity */ @@ -398,17 +288,18 @@ int or_handshake_client_send_auth(connection_t *conn) { log(LOG_DEBUG,"or_handshake_client_send_auth() : Generated DES keys."); /* generate first message */ - *(uint32_t*)buf = me.sin_addr.s_addr; /* local address, network order */ - *(uint16_t*)(buf+4) = me.sin_port; /* local port, network order */ - *(uint32_t*)(buf+6) = htonl(conn->addr); /* remote address */ - *(uint16_t*)(buf+10) = htons(conn->port); /* remote port */ - memcpy(buf+12,conn->f_crypto->key,16); /* keys */ - memcpy(buf+28,conn->b_crypto->key,16); - *(uint32_t *)(buf+44) = htonl(conn->bandwidth); /* max link utilisation */ + *(uint16_t*)buf = htons(HANDSHAKE_AS_OR); + *(uint32_t*)(buf+2) = me.sin_addr.s_addr; /* local address, network order */ + *(uint16_t*)(buf+6) = me.sin_port; /* local port, network order */ + *(uint32_t*)(buf+8) = htonl(conn->addr); /* remote address */ + *(uint16_t*)(buf+12) = htons(conn->port); /* remote port */ + memcpy(buf+14,conn->f_crypto->key,16); /* keys */ + memcpy(buf+30,conn->b_crypto->key,16); + *(uint32_t *)(buf+46) = htonl(conn->bandwidth); /* max link utilisation */ log(LOG_DEBUG,"or_handshake_client_send_auth() : Generated first authentication message."); /* encrypt message */ - retval = crypto_pk_public_encrypt(conn->pkey, buf, 48, cipher,RSA_PKCS1_PADDING); + retval = crypto_pk_public_encrypt(conn->pkey, buf, 50, cipher,RSA_PKCS1_PADDING); if (retval == -1) /* error */ { log(LOG_ERR,"Public-key encryption failed during authentication to %s:%u.",conn->address,conn->port); @@ -550,9 +441,11 @@ int or_handshake_client_process_auth(connection_t *conn) { int or_handshake_server_process_auth(connection_t *conn) { int retval; - char buf[128]; /* only 48 of this is expected to be used */ + char buf[128]; /* 50 of this is expected to be used for OR, 38 for OP */ char cipher[128]; + unsigned char iv[16]; + uint32_t addr; uint16_t port; @@ -573,101 +466,130 @@ int or_handshake_server_process_auth(connection_t *conn) { /* decrypt response */ retval = crypto_pk_private_decrypt(get_privatekey(), cipher, 128, buf, RSA_PKCS1_PADDING); - if (retval == -1) - { + if (retval == -1) { log(LOG_ERR,"or_handshake_server_process_auth: Public-key decryption failed."); log(LOG_DEBUG,"or_handshake_server_process_auth() : Reason : %s.", crypto_perror()); return -1; } - else if (retval != 48) - { - log(LOG_ERR,"or_handshake_server_process_auth(): received an incorrect authentication request."); - return -1; - } - log(LOG_DEBUG,"or_handshake_server_process_auth() : Decrypted authentication message."); - /* identify the router */ - addr = ntohl(*(uint32_t*)buf); /* save the IP address */ - port = ntohs(*(uint16_t*)(buf+4)); /* save the port */ + if (retval == 50) { - router = router_get_by_addr_port(addr,port); - if (!router) - { - log(LOG_DEBUG,"or_handshake_server_process_auth() : unknown router '%s:%d'. Will drop.", conn->address, port); - return -1; - } - log(LOG_DEBUG,"or_handshake_server_process_auth() : Router identified as %s:%u.", - router->address,router->or_port); + log(LOG_DEBUG,"or_handshake_server_process_auth(): Decrypted OR-style auth message."); + if(ntohs(*(uint16_t*)buf) != HANDSHAKE_AS_OR) { + log(LOG_DEBUG,"or_handshake_server_process_auth(): ...but wasn't labelled OR. Dropping."); + return -1; + } - if(connection_exact_get_by_addr_port(addr,port)) { - log(LOG_DEBUG,"or_handshake_server_process_auth(): That router is already connected. Dropping."); - return -1; - } + /* identify the router */ + addr = ntohl(*(uint32_t*)(buf+2)); /* save the IP address */ + port = ntohs(*(uint16_t*)(buf+6)); /* save the port */ - /* save keys */ - crypto_cipher_set_key(conn->b_crypto,buf+12); - crypto_cipher_set_key(conn->f_crypto,buf+28); + router = router_get_by_addr_port(addr,port); + if (!router) { + log(LOG_DEBUG,"or_handshake_server_process_auth() : unknown router '%s:%d'. Will drop.", conn->address, port); + return -1; + } + log(LOG_DEBUG,"or_handshake_server_process_auth() : Router identified as %s:%u.", + router->address,router->or_port); - /* update link info */ - bandwidth = ntohl(*(uint32_t *)(buf+44)); + if(connection_exact_get_by_addr_port(addr,port)) { + log(LOG_DEBUG,"or_handshake_server_process_auth(): That router is already connected. Dropping."); + return -1; + } - conn->bandwidth = router->bandwidth; + /* save keys */ + crypto_cipher_set_key(conn->b_crypto,buf+14); + crypto_cipher_set_key(conn->f_crypto,buf+30); - if (conn->bandwidth > bandwidth) - conn->bandwidth = bandwidth; + /* update link info */ + bandwidth = ntohl(*(uint32_t *)(buf+46)); - /* copy all relevant info to conn */ - conn->addr = router->addr, conn->port = router->or_port; - conn->pkey = crypto_pk_dup_key(router->pkey); - conn->address = strdup(router->address); + conn->bandwidth = router->bandwidth; - /* generate a nonce */ - retval = crypto_pseudo_rand(8, conn->nonce); - if (retval) /* error */ - { - log(LOG_ERR,"Cannot generate a nonce."); - return -1; - } - log(LOG_DEBUG,"or_handshake_server_process_auth() : Nonce generated."); + if (conn->bandwidth > bandwidth) + conn->bandwidth = bandwidth; - *(uint32_t *)(buf+44) = htonl(conn->bandwidth); /* send max link utilisation */ - memcpy(buf+48,conn->nonce,8); /* append the nonce to the end of the message */ + /* copy all relevant info to conn */ + conn->addr = router->addr, conn->port = router->or_port; + conn->pkey = crypto_pk_dup_key(router->pkey); + conn->address = strdup(router->address); - /* encrypt message */ - retval = crypto_pk_public_encrypt(conn->pkey, buf, 56, cipher,RSA_PKCS1_PADDING); - if (retval == -1) /* error */ - { - log(LOG_ERR,"Public-key encryption failed during authentication to %s:%u.",conn->address,conn->port); - log(LOG_DEBUG,"or_handshake_server_process_auth() : Reason : %s.",crypto_perror()); - return -1; - } - log(LOG_DEBUG,"or_handshake_server_process_auth() : Reply encrypted."); + /* generate a nonce */ + retval = crypto_pseudo_rand(8, conn->nonce); + if (retval) { /* error */ + log(LOG_ERR,"Cannot generate a nonce."); + return -1; + } + log(LOG_DEBUG,"or_handshake_server_process_auth(): Nonce generated."); - /* send message */ + memmove(buf, buf+2, 46); + *(uint32_t *)(buf+44) = htonl(conn->bandwidth); /* send max link utilisation */ + memcpy(buf+48,conn->nonce,8); /* append the nonce to the end of the message */ - if(connection_write_to_buf(cipher, 128, conn) < 0) { - log(LOG_DEBUG,"or_handshake_server_process_auth(): my outbuf is full. Oops."); - return -1; - } - retval = connection_flush_buf(conn); - if(retval < 0) { - log(LOG_DEBUG,"or_handshake_server_process_auth(): bad socket while flushing."); - return -1; - } - if(retval > 0) { - /* still stuff on the buffer. */ - conn->state = OR_CONN_STATE_SERVER_SENDING_AUTH; - connection_watch_events(conn, POLLOUT | POLLIN); + /* encrypt message */ + retval = crypto_pk_public_encrypt(conn->pkey, buf, 56, cipher,RSA_PKCS1_PADDING); + if (retval == -1) { /* error */ + log(LOG_ERR,"Public-key encryption failed during authentication to %s:%u.",conn->address,conn->port); + log(LOG_DEBUG,"or_handshake_server_process_auth() : Reason : %s.",crypto_perror()); + return -1; + } + log(LOG_DEBUG,"or_handshake_server_process_auth() : Reply encrypted."); + + /* send message */ + + if(connection_write_to_buf(cipher, 128, conn) < 0) { + log(LOG_DEBUG,"or_handshake_server_process_auth(): my outbuf is full. Oops."); + return -1; + } + retval = connection_flush_buf(conn); + if(retval < 0) { + log(LOG_DEBUG,"or_handshake_server_process_auth(): bad socket while flushing."); + return -1; + } + if(retval > 0) { + /* still stuff on the buffer. */ + conn->state = OR_CONN_STATE_SERVER_SENDING_AUTH; + connection_watch_events(conn, POLLOUT | POLLIN); + return 0; + } + + /* it finished sending */ + log(LOG_DEBUG,"or_handshake_server_process_auth(): Finished sending auth."); + conn->state = OR_CONN_STATE_SERVER_NONCE_WAIT; + connection_watch_events(conn, POLLIN); return 0; } - /* it finished sending */ - log(LOG_DEBUG,"or_handshake_server_process_auth(): Finished sending auth."); - conn->state = OR_CONN_STATE_SERVER_NONCE_WAIT; - connection_watch_events(conn, POLLIN); - return 0; + if(retval == 38) { + log(LOG_DEBUG,"or_handshake_server_process_auth(): Decrypted OP-style auth message."); + if(ntohs(*(uint16_t*)buf) != HANDSHAKE_AS_OP) { + log(LOG_DEBUG,"or_handshake_server_process_auth(): ...but wasn't labelled OP. Dropping."); + return -1; + } + conn->bandwidth = ntohl(*((uint32_t *)(buf+2))); + log(LOG_DEBUG,"or_handshake_server_process_auth(): Bandwidth %d requested.",conn->bandwidth); + + crypto_cipher_set_key(conn->b_crypto, buf+6); + crypto_cipher_set_key(conn->f_crypto, buf+22); + + memset(iv, 0, 16); + crypto_cipher_set_iv(conn->b_crypto, iv); + crypto_cipher_set_iv(conn->f_crypto, iv); + + crypto_cipher_encrypt_init_cipher(conn->b_crypto); + crypto_cipher_decrypt_init_cipher(conn->f_crypto); + + conn->state = OR_CONN_STATE_OPEN; + connection_init_timeval(conn); + connection_watch_events(conn, POLLIN); + + return connection_process_inbuf(conn); /* in case they sent some cells along with the keys */ + } + + log(LOG_ERR,"or_handshake_server_process_auth(): received an incorrect authentication request."); + return -1; } int or_handshake_server_process_nonce(connection_t *conn) { diff --git a/src/or/directory.c b/src/or/directory.c index bb48e63370..34d9a1797e 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -158,7 +158,7 @@ int connection_dir_process_inbuf(connection_t *conn) { conn->pkey ? "authenticated" : "unauthenticated"); } - if(options.ORPort) { /* connect to them all */ + if(options.OnionRouter) { /* connect to them all */ router_retry_connections(); } return -1; diff --git a/src/or/main.c b/src/or/main.c index 2e0a355883..4171186e3b 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -217,9 +217,7 @@ void check_conn_read(int i) { assert(conn); // log(LOG_DEBUG,"check_conn_read(): socket %d has something to read.",conn->s); - if (conn->type == CONN_TYPE_OP_LISTENER) { - retval = connection_op_handle_listener_read(conn); - } else if (conn->type == CONN_TYPE_OR_LISTENER) { + if (conn->type == CONN_TYPE_OR_LISTENER) { retval = connection_or_handle_listener_read(conn); } else if (conn->type == CONN_TYPE_AP_LISTENER) { retval = connection_ap_handle_listener_read(conn); @@ -352,7 +350,7 @@ int prepare_for_poll(int *timeout) { if(!connection_speaks_cells(tmpconn)) continue; /* this conn type doesn't send cells */ if(now.tv_sec >= tmpconn->timestamp_lastwritten + options.KeepalivePeriod) { - if((!options.ORPort && !circuit_get_by_conn(tmpconn)) || + if((!options.OnionRouter && !circuit_get_by_conn(tmpconn)) || (!connection_state_is_open(tmpconn))) { /* 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).", @@ -435,7 +433,7 @@ int do_main_loop(void) { } /* load the private key, if we're supposed to have one */ - if(options.ORPort) { + if(options.OnionRouter) { prkey = crypto_new_pk_env(CRYPTO_PK_RSA); if (!prkey) { log(LOG_ERR,"Error creating a crypto environment."); @@ -466,8 +464,7 @@ int do_main_loop(void) { * non-zero. This is where we try to connect to all the other ORs, * and start the listeners */ - retry_all_connections(options.ORPort, - options.OPPort, options.APPort, options.DirPort); + retry_all_connections(options.ORPort, options.APPort, options.DirPort); for(;;) { if(please_dumpstats) { @@ -788,7 +785,7 @@ int tor_main(int argc, char *argv[]) { if (options.Daemon) daemonize(); - if(options.ORPort) { /* only spawn dns handlers if we're a router */ + if(options.OnionRouter) { /* only spawn dns handlers if we're a router */ if(dns_master_start() < 0) { log(LOG_ERR,"main(): We're running without a dns handler. Bad news."); } diff --git a/src/or/onion.c b/src/or/onion.c index 7809127ad9..803fe3be15 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -298,7 +298,7 @@ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *r log(LOG_DEBUG,"new_route(): Contemplating router %u.",choice); if(choice == oldchoice || (oldchoice < rarray_len && !crypto_pk_cmp_keys(rarray[choice]->pkey, rarray[oldchoice]->pkey)) || - (options.ORPort && !connection_twin_get_by_addr_port(rarray[choice]->addr, rarray[choice]->or_port))) { + (options.OnionRouter && !connection_twin_get_by_addr_port(rarray[choice]->addr, rarray[choice]->or_port))) { /* Same router as last choice, or router twin, * or no routers with that key are connected to us. * Try again. */ @@ -321,7 +321,7 @@ static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) { for(i=0;iaddr, rarray[i]->or_port); if(!conn || conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN) { log(LOG_DEBUG,"Nope, %d is not connected.",i); diff --git a/src/or/or.h b/src/or/or.h index 435c0a2d52..59ee03e674 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -53,12 +53,13 @@ #define MAX_BUF_SIZE (640*1024) #define DEFAULT_BANDWIDTH_OP (1024 * 1000) +#define HANDSHAKE_AS_OP 1 +#define HANDSHAKE_AS_OR 2 + #define ACI_TYPE_LOWER 0 #define ACI_TYPE_HIGHER 1 #define ACI_TYPE_BOTH 2 -#define CONN_TYPE_OP_LISTENER 1 -#define CONN_TYPE_OP 2 #define CONN_TYPE_OR_LISTENER 3 #define CONN_TYPE_OR 4 #define CONN_TYPE_EXIT 5 @@ -72,16 +73,13 @@ #define DNSMASTER_STATE_OPEN 0 -#define OP_CONN_STATE_AWAITING_KEYS 0 -#define OP_CONN_STATE_OPEN 1 - /* how to read these states: * foo_CONN_STATE_bar_baz: * "I am acting as a bar, currently in stage baz of talking with a foo." */ -#define OR_CONN_STATE_OP_CONNECTING 0 /* an application proxy wants me to connect to this OR */ +//#define OR_CONN_STATE_OP_CONNECTING 0 /* an application proxy wants me to connect to this OR */ #define OR_CONN_STATE_OP_SENDING_KEYS 1 -#define OR_CONN_STATE_CLIENT_CONNECTING 2 /* I'm connecting to this OR as an OR */ +#define OR_CONN_STATE_CLIENT_CONNECTING 2 /* connecting to this OR */ #define OR_CONN_STATE_CLIENT_SENDING_AUTH 3 /* sending address and info */ #define OR_CONN_STATE_CLIENT_AUTH_WAIT 4 /* have sent address and info, waiting */ #define OR_CONN_STATE_CLIENT_SENDING_NONCE 5 /* sending nonce, last piece of handshake */ @@ -405,10 +403,10 @@ typedef struct { double CoinWeight; int Daemon; int ORPort; - int OPPort; int APPort; int DirPort; int MaxConn; + int OnionRouter; int TrafficShaping; int LinkPadding; int DirRebuildPeriod; @@ -574,8 +572,7 @@ int connection_create_listener(struct sockaddr_in *bindaddr, int type); int connection_handle_listener_read(connection_t *conn, int new_type, int new_state); /* start all connections that should be up but aren't */ -int retry_all_connections(uint16_t or_listenport, - uint16_t op_listenport, uint16_t ap_listenport, uint16_t dir_listenport); +int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport); int connection_read_to_buf(connection_t *conn); @@ -602,7 +599,7 @@ void connection_increment_receiver_bucket (connection_t *conn); void connection_increment_send_timeval(connection_t *conn); void connection_init_timeval(connection_t *conn); -int connection_speaks_cells(connection_t *conn); +#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR) int connection_is_listener(connection_t *conn); int connection_state_is_open(connection_t *conn); @@ -676,9 +673,7 @@ int or_handshake_client_send_auth(connection_t *conn); int or_handshake_server_process_auth(connection_t *conn); int or_handshake_server_process_nonce(connection_t *conn); -connection_t *connect_to_router_as_or(routerinfo_t *router); -connection_t *connection_or_connect_as_or(routerinfo_t *router); -connection_t *connection_or_connect_as_op(routerinfo_t *router); +connection_t *connection_or_connect(routerinfo_t *router); int connection_or_create_listener(struct sockaddr_in *bindaddr); int connection_or_handle_listener_read(connection_t *conn); diff --git a/src/or/routers.c b/src/or/routers.c index 94e5911dd0..ff14138569 100644 --- a/src/or/routers.c +++ b/src/or/routers.c @@ -70,7 +70,7 @@ void router_retry_connections(void) { router = directory->routers[i]; if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */ log_fn(LOG_DEBUG,"connecting to OR %s:%u.",router->address,router->or_port); - connection_or_connect_as_or(router); + connection_or_connect(router); } } } @@ -119,7 +119,7 @@ int router_is_me(uint32_t addr, uint16_t port) /* XXXX Should this check the key too? */ struct sockaddr_in me; /* my router identity */ - if(!options.ORPort) { + if(!options.OnionRouter) { /* we're not an OR. This obviously isn't us. */ return 0; }