Clarify a bunch of log messages
[tor.git] / src / or / connection_or.c
blob45070f87f584acf01da0bb7ddd39e6fc665dc036
1 /* Copyright 2001 Matej Pfajfar.
2 * Copyright 2001-2004 Roger Dingledine.
3 * Copyright 2004 Roger Dingledine, Nick Mathewson. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
7 /**
8 * \file connection_or.c
9 * \brief Functions to handle OR connections, TLS handshaking, and
10 * cells on the network.
11 **/
13 #include "or.h"
15 /** How much clock skew do we tolerate when checking certificates for
16 * known routers? (sec) */
17 #define TIGHT_CERT_ALLOW_SKEW (90*60)
19 static int connection_tls_finish_handshake(connection_t *conn);
20 static int connection_or_process_cells_from_inbuf(connection_t *conn);
22 /**************************************************************/
24 /** Pack the cell_t host-order structure <b>src</b> into network-order
25 * in the buffer <b>dest</b>. See tor-spec.txt for details about the
26 * wire format.
28 static void cell_pack(char *dest, const cell_t *src) {
29 *(uint16_t*)dest = htons(src->circ_id);
30 *(uint8_t*)(dest+2) = src->command;
31 memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE);
34 /** Unpack the network-order buffer <b>src</b> into a host-order
35 * cell_t structure <b>dest</b>.
37 static void cell_unpack(cell_t *dest, const char *src) {
38 dest->circ_id = ntohs(*(uint16_t*)(src));
39 dest->command = *(uint8_t*)(src+2);
40 memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE);
43 int connection_or_reached_eof(connection_t *conn) {
44 log_fn(LOG_INFO,"OR connection reached EOF. Closing.");
45 connection_mark_for_close(conn);
46 return 0;
49 /** Handle any new bytes that have come in on connection <b>conn</b>.
50 * If conn is in 'open' state, hand it to
51 * connection_or_process_cells_from_inbuf()
52 * (else do nothing).
54 int connection_or_process_inbuf(connection_t *conn) {
56 tor_assert(conn);
57 tor_assert(conn->type == CONN_TYPE_OR);
59 if(conn->state != OR_CONN_STATE_OPEN)
60 return 0; /* don't do anything */
61 return connection_or_process_cells_from_inbuf(conn);
64 /** Connection <b>conn</b> has finished writing and has no bytes left on
65 * its outbuf.
67 * Otherwise it's in state "open": stop writing and return.
69 * If <b>conn</b> is broken, mark it for close and return -1, else
70 * return 0.
72 int connection_or_finished_flushing(connection_t *conn) {
73 tor_assert(conn);
74 tor_assert(conn->type == CONN_TYPE_OR);
76 assert_connection_ok(conn,0);
78 if (conn->state != OR_CONN_STATE_OPEN) {
79 log_fn(LOG_WARN,"BUG: called in unexpected state %d",conn->state);
80 return -1;
83 connection_stop_writing(conn);
84 return 0;
87 /** Connected handler for OR connections: begin the TLS handshake.
89 int connection_or_finished_connecting(connection_t *conn)
91 tor_assert(conn);
92 tor_assert(conn->type == CONN_TYPE_OR);
93 tor_assert(conn->state == OR_CONN_STATE_CONNECTING);
95 log_fn(LOG_INFO,"OR connect() to router at %s:%u finished.",
96 conn->address,conn->port);
98 if(connection_tls_start_handshake(conn, 0) < 0) {
99 /* TLS handshaking error of some kind. */
100 connection_mark_for_close(conn);
101 return -1;
103 return 0;
106 /** Initialize <b>conn</b> to include all the relevant data from <b>router</b>.
107 * This function is called either from connection_or_connect(), if
108 * we initiated the connect, or from connection_tls_finish_handshake()
109 * if the other side initiated it.
111 static void
112 connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *router) {
113 conn->addr = router->addr;
114 conn->port = router->or_port;
115 conn->receiver_bucket = conn->bandwidth = router->bandwidthburst;
116 conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
117 crypto_pk_get_digest(conn->identity_pkey, conn->identity_digest);
118 conn->nickname = tor_strdup(router->nickname);
119 tor_free(conn->address);
120 conn->address = tor_strdup(router->address);
123 static void
124 connection_or_init_conn_from_address(connection_t *conn,
125 uint32_t addr, uint16_t port,
126 const char *id_digest)
128 struct in_addr in;
129 const char *n;
130 or_options_t *options = get_options();
131 routerinfo_t *r = router_get_by_digest(id_digest);
132 if (r) {
133 connection_or_init_conn_from_router(conn,r);
134 return;
136 conn->addr = addr;
137 conn->port = port;
138 /* This next part isn't really right, but it's good enough for now. */
139 conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst;
140 memcpy(conn->identity_digest, id_digest, DIGEST_LEN);
141 /* If we're an authoritative directory server, we may know a
142 * nickname for this router. */
143 n = dirserv_get_nickname_by_digest(id_digest);
144 if (n) {
145 conn->nickname = tor_strdup(n);
146 } else {
147 conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
148 conn->nickname[0] = '$';
149 base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
150 conn->identity_digest, DIGEST_LEN);
152 tor_free(conn->address);
153 in.s_addr = htonl(addr);
154 conn->address = tor_strdup(inet_ntoa(in));
157 void
158 connection_or_update_nickname(connection_t *conn)
160 routerinfo_t *r;
161 const char *n;
163 tor_assert(conn);
164 tor_assert(conn->type == CONN_TYPE_OR);
165 n = dirserv_get_nickname_by_digest(conn->identity_digest);
166 if (n) {
167 if (!conn->nickname || strcmp(conn->nickname, n)) {
168 tor_free(conn->nickname);
169 conn->nickname = tor_strdup(n);
171 return;
173 r = router_get_by_digest(conn->identity_digest);
174 if (r && r->is_verified) {
175 if (!conn->nickname || strcmp(conn->nickname, r->nickname)) {
176 tor_free(conn->nickname);
177 conn->nickname = tor_strdup(r->nickname);
179 return;
181 if (conn->nickname[0] != '$') {
182 tor_free(conn->nickname);
183 conn->nickname = tor_malloc(HEX_DIGEST_LEN+1);
184 base16_encode(conn->nickname, HEX_DIGEST_LEN+1,
185 conn->identity_digest, DIGEST_LEN);
189 /** Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to
190 * handshake with an OR with identity digest <b>id_digest</b>.
192 * If <b>id_digest</b> is me, do nothing. If we're already connected to it,
193 * return that connection. If the connect() is in progress, set the
194 * new conn's state to 'connecting' and return it. If connect() succeeds,
195 * call * connection_tls_start_handshake() on it.
197 * This function is called from router_retry_connections(), for
198 * ORs connecting to ORs, and circuit_establish_circuit(), for
199 * OPs connecting to ORs.
201 * Return the launched conn, or NULL if it failed.
203 connection_t *connection_or_connect(uint32_t addr, uint16_t port,
204 const char *id_digest) {
205 connection_t *conn;
206 routerinfo_t *me;
208 tor_assert(id_digest);
210 if(server_mode(get_options()) && (me=router_get_my_routerinfo()) &&
211 !memcmp(me->identity_digest, id_digest,DIGEST_LEN)) {
212 log_fn(LOG_WARN,"Request to connect to myself! Failing.");
213 return NULL;
216 /* this function should never be called if we're already connected to
217 * id_digest, but check first to be sure */
218 /*XXX this is getting called, at least by dirservers. */
219 conn = connection_get_by_identity_digest(id_digest, CONN_TYPE_OR);
220 if(conn) {
221 tor_assert(conn->nickname);
222 log_fn(LOG_WARN,"Asked me to connect to router '%s', but there's already a connection.", conn->nickname);
223 return conn;
226 conn = connection_new(CONN_TYPE_OR);
228 /* set up conn so it's got all the data we need to remember */
229 connection_or_init_conn_from_address(conn, addr, port, id_digest);
230 conn->state = OR_CONN_STATE_CONNECTING;
231 control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED);
233 switch(connection_connect(conn, conn->address, addr, port)) {
234 case -1:
235 router_mark_as_down(conn->identity_digest);
236 control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
237 connection_free(conn);
238 return NULL;
239 case 0:
240 connection_watch_events(conn, POLLIN | POLLOUT | POLLERR);
241 /* writable indicates finish, readable indicates broken link,
242 error indicates broken link on windows */
243 return conn;
244 /* case 1: fall through */
247 if(connection_tls_start_handshake(conn, 0) >= 0)
248 return conn;
250 /* failure */
251 connection_mark_for_close(conn);
252 return NULL;
255 /** Begin the tls handshake with <b>conn</b>. <b>receiving</b> is 0 if
256 * we initiated the connection, else it's 1.
258 * Assign a new tls object to conn->tls, begin reading on <b>conn</b>, and pass
259 * <b>conn</b> to connection_tls_continue_handshake().
261 * Return -1 if <b>conn</b> is broken, else return 0.
263 int connection_tls_start_handshake(connection_t *conn, int receiving) {
264 conn->state = OR_CONN_STATE_HANDSHAKING;
265 conn->tls = tor_tls_new(conn->s, receiving, 0);
266 if(!conn->tls) {
267 log_fn(LOG_WARN,"tor_tls_new failed. Closing.");
268 return -1;
270 connection_start_reading(conn);
271 log_fn(LOG_DEBUG,"starting the handshake");
272 if(connection_tls_continue_handshake(conn) < 0) {
273 return -1;
275 return 0;
278 /** Move forward with the tls handshake. If it finishes, hand
279 * <b>conn</b> to connection_tls_finish_handshake().
281 * Return -1 if <b>conn</b> is broken, else return 0.
283 int connection_tls_continue_handshake(connection_t *conn) {
284 switch(tor_tls_handshake(conn->tls)) {
285 case TOR_TLS_ERROR:
286 case TOR_TLS_CLOSE:
287 log_fn(LOG_INFO,"tls error. breaking.");
288 return -1;
289 case TOR_TLS_DONE:
290 return connection_tls_finish_handshake(conn);
291 case TOR_TLS_WANTWRITE:
292 connection_start_writing(conn);
293 log_fn(LOG_DEBUG,"wanted write");
294 return 0;
295 case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */
296 log_fn(LOG_DEBUG,"wanted read");
297 return 0;
299 return 0;
302 static char ZERO_DIGEST[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
304 int connection_or_nonopen_was_started_here(connection_t *conn)
306 tor_assert(sizeof(ZERO_DIGEST) == DIGEST_LEN);
307 tor_assert(conn->type == CONN_TYPE_OR);
309 if (!memcmp(ZERO_DIGEST, conn->identity_digest, DIGEST_LEN))
310 return 0;
311 else
312 return 1;
315 /** The tls handshake is finished.
317 * Make sure we are happy with the person we just handshaked with:
318 * If it's an OP (that is, it has no certificate), make sure I'm an OR.
319 * If it's an OR (it has a certificate), make sure it has a recognized
320 * nickname, and its cert is signed by the identity key of that nickname.
321 * If I initiated the connection, make sure it's the right guy; and if
322 * he initiated the connection, make sure he's not already connected.
324 * If he initiated the conn, also initialize conn from the information
325 * in router.
327 * If either of us is an OP, set bandwidth to the default OP bandwidth.
329 * If all is successful and he's an OR, then call circuit_n_conn_done()
330 * to handle events that have been pending on the tls handshake
331 * completion, and set the directory to be dirty (only matters if I'm
332 * an authdirserver).
334 static int
335 connection_tls_finish_handshake(connection_t *conn) {
336 routerinfo_t *router;
337 char nickname[MAX_NICKNAME_LEN+1];
338 connection_t *c;
339 crypto_pk_env_t *identity_rcvd=NULL;
340 char digest_rcvd[DIGEST_LEN];
341 or_options_t *options = get_options();
343 conn->state = OR_CONN_STATE_OPEN;
344 connection_watch_events(conn, POLLIN);
345 log_fn(LOG_DEBUG,"tls handshake done. verifying.");
346 if (! tor_tls_peer_has_cert(conn->tls)) { /* It's an old OP. */
347 if (server_mode(options)) { /* I'm an OR; good. */
348 conn->receiver_bucket = conn->bandwidth = DEFAULT_BANDWIDTH_OP;
349 return 0;
350 } else { /* Neither side sent a certificate: ouch. */
351 log_fn(LOG_WARN,"Neither peer sent a cert! Closing.");
352 return -1;
355 /* Okay; the other side is an OR or a post-0.0.8 OP (with a cert). */
356 if (tor_tls_get_peer_cert_nickname(conn->tls, nickname, MAX_NICKNAME_LEN)) {
357 log_fn(LOG_WARN,"Other side (%s:%d) has a cert without a valid nickname. Closing.",
358 conn->address, conn->port);
359 return -1;
361 log_fn(LOG_DEBUG, "Other side (%s:%d) claims to be router '%s'",
362 conn->address, conn->port, nickname);
364 if(tor_tls_verify(conn->tls, &identity_rcvd) < 0) {
365 log_fn(LOG_WARN,"Other side, which claims to be router '%s' (%s:%d), has a cert but it's invalid. Closing.",
366 nickname, conn->address, conn->port);
367 return -1;
369 #if 0
370 if(tor_tls_check_lifetime(conn->tls, LOOSE_CERT_ALLOW_SKEW)<0) {
371 log_fn(LOG_WARN,"Other side '%s' (%s:%d) has a very highly skewed clock, or an expired certificate. Closing.",
372 nickname, conn->address, conn->port);
373 return -1;
375 #endif
376 log_fn(LOG_DEBUG,"The router's cert is valid.");
377 crypto_pk_get_digest(identity_rcvd, digest_rcvd);
379 if (crypto_pk_cmp_keys(get_identity_key(), identity_rcvd)<0) {
380 conn->circ_id_type = CIRC_ID_TYPE_LOWER;
381 } else {
382 conn->circ_id_type = CIRC_ID_TYPE_HIGHER;
384 crypto_free_pk_env(identity_rcvd);
386 router = router_get_by_nickname(nickname);
387 if(router && /* we know this nickname */
388 router->is_verified && /* make sure it's the right guy */
389 memcmp(digest_rcvd, router->identity_digest, DIGEST_LEN) != 0) {
390 log_fn(LOG_WARN, "Identity key not as expected for router claiming to be '%s' (%s:%d) ", nickname, conn->address, conn->port);
391 return -1;
393 if (router_get_by_digest(digest_rcvd)) {
394 /* This is a known router; don't cut it slack with its clock skew. */
395 if(tor_tls_check_lifetime(conn->tls, TIGHT_CERT_ALLOW_SKEW)<0) {
396 log_fn(LOG_WARN,"Router '%s' (%s:%d) has a skewed clock, or an expired certificate; or else our clock is skewed. Closing.",
397 nickname, conn->address, conn->port);
398 return -1;
402 if (connection_or_nonopen_was_started_here(conn)) {
403 /* I initiated this connection. */
404 if (strcasecmp(conn->nickname, nickname)) {
405 log_fn(options->DirPort ? LOG_WARN : LOG_INFO,
406 "Other side (%s:%d) is '%s', but we tried to connect to '%s'",
407 conn->address, conn->port, nickname, conn->nickname);
408 control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
409 return -1;
411 } else {
412 if((c=connection_get_by_identity_digest(digest_rcvd, CONN_TYPE_OR))) {
413 log_fn(LOG_INFO,"Router '%s' is already connected on fd %d. Dropping fd %d.", nickname, c->s, conn->s);
414 return -1;
416 connection_or_init_conn_from_address(conn,conn->addr,conn->port,digest_rcvd);
419 if (!server_mode(options)) { /* If I'm an OP... */
420 conn->receiver_bucket = conn->bandwidth = DEFAULT_BANDWIDTH_OP;
423 directory_set_dirty();
424 circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
425 /* Note the success */
426 rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL));
427 control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED);
428 return 0;
431 /** Pack <b>cell</b> into wire-format, and write it onto <b>conn</b>'s
432 * outbuf.
434 * (Commented out) If it's an OR conn, and an entire TLS record is
435 * ready, then try to flush the record now.
437 void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn) {
438 char networkcell[CELL_NETWORK_SIZE];
439 char *n = networkcell;
441 tor_assert(cell);
442 tor_assert(conn);
443 tor_assert(connection_speaks_cells(conn));
445 cell_pack(n, cell);
447 connection_write_to_buf(n, CELL_NETWORK_SIZE, conn);
449 #if 0 /* commented out -- can we get away with not doing this,
450 * because we're already round-robining in handle_read?
452 #define MIN_TLS_FLUSHLEN 15872
453 /* openssl tls record size is 16383, this is close. The goal here is to
454 * push data out as soon as we know there's enough for a tls record, so
455 * during periods of high load we won't read the entire megabyte from
456 * input before pushing any data out. */
457 if(conn->outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN &&
458 conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
459 int extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN;
460 conn->outbuf_flushlen = MIN_TLS_FLUSHLEN;
461 if(connection_handle_write(conn) < 0) {
462 log_fn(LOG_WARN,"flushing failed.");
463 return;
465 if(extra) {
466 conn->outbuf_flushlen += extra;
467 connection_start_writing(conn);
470 #endif
474 /** Process cells from <b>conn</b>'s inbuf.
476 * Loop: while inbuf contains a cell, pull it off the inbuf, unpack it,
477 * and hand it to command_process_cell().
479 * Always return 0.
481 static int connection_or_process_cells_from_inbuf(connection_t *conn) {
482 char buf[CELL_NETWORK_SIZE];
483 cell_t cell;
485 loop:
486 log_fn(LOG_DEBUG,"%d: starting, inbuf_datalen %d (%d pending in tls object).",
487 conn->s,(int)buf_datalen(conn->inbuf),tor_tls_get_pending_bytes(conn->tls));
488 if(buf_datalen(conn->inbuf) < CELL_NETWORK_SIZE) /* entire response available? */
489 return 0; /* not yet */
491 connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn);
493 /* retrieve cell info from buf (create the host-order struct from the
494 * network-order string) */
495 cell_unpack(&cell, buf);
497 command_process_cell(&cell, conn);
499 goto loop; /* process the remainder of the buffer */
503 Local Variables:
504 mode:c
505 indent-tabs-mode:nil
506 c-basic-offset:2
507 End: