tor  master
Macros | Typedefs | Enumerations | Functions | Variables
channeltls.c File Reference

A concrete subclass of channel_t using or_connection_t to transfer cells between Tor instances. More...

#include "or.h"
#include "channel.h"
#include "channeltls.h"
#include "circuitmux.h"
#include "circuitmux_ewma.h"
#include "command.h"
#include "config.h"
#include "connection.h"
#include "connection_or.h"
#include "control.h"
#include "entrynodes.h"
#include "link_handshake.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
#include "scheduler.h"
#include "torcert.h"
#include "networkstatus.h"
#include "channelpadding_negotiation.h"
#include "channelpadding.h"
Include dependency graph for channeltls.c:

Macros

#define TOR_CHANNEL_INTERNAL_
 
#define CHANNELTLS_PRIVATE
 
#define MAX_DESCR_LEN   32
 
#define PROCESS_CELL(tp, cl, cn)   channel_tls_process_ ## tp ## _cell(cl, cn)
 
#define NETINFO_NOTICE_SKEW   3600
 
#define MAX_CERT_TYPE_WANTED   CERTTYPE_RSA1024_ID_EDID
 
#define ERR(s)
 
#define ERR(s)
 
#define ERR(s)
 

Typedefs

typedef enum cert_encoding_t cert_encoding_t
 

Enumerations

enum  cert_encoding_t { CERT_ENCODING_UNKNOWN, CERT_ENCODING_X509, CERT_ENCODING_ED25519, CERT_ENCODING_RSA_CROSSCERT }
 

Functions

STATIC void channel_tls_common_init (channel_tls_t *tlschan)
 
channel_tchannel_tls_connect (const tor_addr_t *addr, uint16_t port, const char *id_digest, const ed25519_public_key_t *ed_id)
 
channel_listener_tchannel_tls_get_listener (void)
 
channel_listener_tchannel_tls_start_listener (void)
 
void channel_tls_free_all (void)
 
channel_tchannel_tls_handle_incoming (or_connection_t *orconn)
 
channel_tchannel_tls_to_base (channel_tls_t *tlschan)
 
channel_tls_t * channel_tls_from_base (channel_t *chan)
 
void channel_tls_handle_state_change_on_orconn (channel_tls_t *chan, or_connection_t *conn, uint8_t old_state, uint8_t state)
 
void channel_tls_handle_cell (cell_t *cell, or_connection_t *conn)
 
void channel_tls_handle_var_cell (var_cell_t *var_cell, or_connection_t *conn)
 
void channel_tls_update_marks (or_connection_t *conn)
 
STATIC void channel_tls_process_certs_cell (var_cell_t *cell, channel_tls_t *chan)
 
STATIC void channel_tls_process_auth_challenge_cell (var_cell_t *cell, channel_tls_t *chan)
 
STATIC void channel_tls_process_authenticate_cell (var_cell_t *cell, channel_tls_t *chan)
 

Variables

uint64_t stats_n_padding_cells_processed = 0
 
uint64_t stats_n_versions_cells_processed = 0
 
uint64_t stats_n_netinfo_cells_processed = 0
 
uint64_t stats_n_vpadding_cells_processed = 0
 
uint64_t stats_n_certs_cells_processed = 0
 
uint64_t stats_n_auth_challenge_cells_processed = 0
 
uint64_t stats_n_authenticate_cells_processed = 0
 
uint64_t stats_n_authorize_cells_processed = 0
 

Detailed Description

A concrete subclass of channel_t using or_connection_t to transfer cells between Tor instances.

This module fills in the various function pointers in channel_t, to implement the channel_tls_t channels as used in Tor today. These channels are created from channel_tls_connect() and channel_tls_handle_incoming(). Each corresponds 1:1 to or_connection_t object, as implemented in connection_or.c. These channels transmit cells to the underlying or_connection_t by calling connection_or_write_*_cell_to_buf(), and receive cells from the underlying or_connection_t when connection_or_process_cells_from_inbuf() calls channel_tls_handle_*_cell().

Here we also implement the server (responder) side of the v3+ Tor link handshake, which uses CERTS and AUTHENTICATE cell to negotiate versions, exchange expected and observed IP and time information, and bootstrap a level of authentication higher than we have gotten on the raw TLS handshake.

NOTE: Since there is currently only one type of channel, there are probably more than a few cases where functionality that is currently in channeltls.c, connection_or.c, and channel.c ought to be divided up differently. The right time to do this is probably whenever we introduce our next channel type.

Macro Definition Documentation

◆ ERR [1/3]

#define ERR (   s)
Value:
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
"Received a bad CERTS cell from %s:%d: %s", \
safe_str(chan->conn->base_.address), \
chan->conn->base_.port, (s)); \
connection_or_close_for_error(chan->conn, 0); \
goto err; \
} while (0)
#define LD_PROTOCOL
Definition: torlog.h:66
const char * safe_str(const char *address)
Definition: config.c:1052

◆ ERR [2/3]

#define ERR (   s)
Value:
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
"Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \
safe_str(chan->conn->base_.address), \
chan->conn->base_.port, (s)); \
connection_or_close_for_error(chan->conn, 0); \
goto done; \
} while (0)
#define LD_PROTOCOL
Definition: torlog.h:66
const char * safe_str(const char *address)
Definition: config.c:1052

◆ ERR [3/3]

#define ERR (   s)
Value:
do { \
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
"Received a bad AUTHENTICATE cell from %s:%d: %s", \
safe_str(chan->conn->base_.address), \
chan->conn->base_.port, (s)); \
connection_or_close_for_error(chan->conn, 0); \
var_cell_free(expected_cell); \
return; \
} while (0)
#define LD_PROTOCOL
Definition: torlog.h:66
const char * safe_str(const char *address)
Definition: config.c:1052

Typedef Documentation

◆ cert_encoding_t

Types of certificates that we know how to parse from CERTS cells. Each type corresponds to a different encoding format.

Enumeration Type Documentation

◆ cert_encoding_t

Types of certificates that we know how to parse from CERTS cells. Each type corresponds to a different encoding format.

Enumerator
CERT_ENCODING_UNKNOWN 

We don't recognize this.

CERT_ENCODING_X509 

It's an RSA key, signed with RSA, encoded in x509. (Actually, it might not be RSA. We test that later.)

CERT_ENCODING_ED25519 

It's something signed with an Ed25519 key, encoded asa a tor_cert_t.

CERT_ENCODING_RSA_CROSSCERT 

It's an Ed key signed with an RSA key.

Function Documentation

◆ channel_tls_common_init()

STATIC void channel_tls_common_init ( channel_tls_t *  tlschan)

Do parts of channel_tls_t initialization common to channel_tls_connect() and channel_tls_handle_incoming().

Here is the call graph for this function:

◆ channel_tls_connect()

channel_t* channel_tls_connect ( const tor_addr_t addr,
uint16_t  port,
const char *  id_digest,
const ed25519_public_key_t ed_id 
)

Start a new TLS channel.

Launch a new OR connection to addr:port and expect to handshake with an OR with identity digest id_digest, and wrap it in a channel_tls_t.

Here is the caller graph for this function:

◆ channel_tls_free_all()

void channel_tls_free_all ( void  )

Free everything on shutdown.

Not much to do here, since channel_free_all() takes care of a lot, but let's get rid of the listener.

◆ channel_tls_from_base()

channel_tls_t* channel_tls_from_base ( channel_t chan)

Cast a channel_t to a channel_tls_t, with appropriate type-checking asserts.

◆ channel_tls_get_listener()

channel_listener_t* channel_tls_get_listener ( void  )

Return the current channel_tls_t listener.

Returns the current channel listener for incoming TLS connections, or NULL if none has been established

Here is the caller graph for this function:

◆ channel_tls_handle_cell()

void channel_tls_handle_cell ( cell_t cell,
or_connection_t conn 
)

Handle an incoming cell on a channel_tls_t.

This is called from connection_or.c to handle an arriving cell; it checks for cell types specific to the handshake for this transport protocol and handles them, and queues all other cells to the channel_t layer, which eventually will hand them off to command.c.

The channel layer itself decides whether the cell should be queued or can be handed off immediately to the upper-layer code. It is responsible for copying in the case that it queues; we merely pass pointers through which we get from connection_or_process_cells_from_inbuf().

◆ channel_tls_handle_incoming()

channel_t* channel_tls_handle_incoming ( or_connection_t orconn)

Create a new channel around an incoming or_connection_t.

Here is the caller graph for this function:

◆ channel_tls_handle_state_change_on_orconn()

void channel_tls_handle_state_change_on_orconn ( channel_tls_t *  chan,
or_connection_t conn,
uint8_t  old_state,
uint8_t  state 
)

Handle an orconn state change.

This function will be called by connection_or.c when the or_connection_t associated with this channel_tls_t changes state.

◆ channel_tls_handle_var_cell()

void channel_tls_handle_var_cell ( var_cell_t var_cell,
or_connection_t conn 
)

Handle an incoming variable-length cell on a channel_tls_t.

Process a var_cell that was just received on conn. Keep internal statistics about how many of each cell we've processed so far this second, and the total number of microseconds it took to process each type of cell. All the var_cell commands are handshake- related and live below the channel_t layer, so no variable-length cells ever get delivered in the current implementation, but I've left the mechanism in place for future use.

If we were handing them off to the upper layer, the channel_t queueing code would be responsible for memory management, and we'd just be passing pointers through from connection_or_process_cells_from_inbuf(). That caller always frees them after this function returns, so this function should never free var_cell.

◆ channel_tls_process_auth_challenge_cell()

STATIC void channel_tls_process_auth_challenge_cell ( var_cell_t cell,
channel_tls_t *  chan 
)

Process an AUTH_CHALLENGE cell from a channel_tls_t.

This function is called to handle an incoming AUTH_CHALLENGE cell on a channel_tls_t; if we weren't supposed to get one (for example, because we're not the originator of the channel), or it's ill-formed, or we aren't doing a v3 handshake, mark the channel. If the cell is well-formed but we don't want to authenticate, just drop it. If the cell is well-formed and we want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell.

◆ channel_tls_process_authenticate_cell()

STATIC void channel_tls_process_authenticate_cell ( var_cell_t cell,
channel_tls_t *  chan 
)

Process an AUTHENTICATE cell from a channel_tls_t.

If it's ill-formed or we weren't supposed to get one or we're not doing a v3 handshake, then mark the connection. If it does not authenticate the other side of the connection successfully (because it isn't signed right, we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept the identity of the router on the other side of the connection.

◆ channel_tls_process_certs_cell()

STATIC void channel_tls_process_certs_cell ( var_cell_t cell,
channel_tls_t *  chan 
)

Process a CERTS cell from a channel.

This function is called to process an incoming CERTS cell on a channel_tls_t:

If the other side should not have sent us a CERTS cell, or the cell is malformed, or it is supposed to authenticate the TLS key but it doesn't, then mark the connection.

If the cell has a good cert chain and we're doing a v3 handshake, then store the certificates in or_handshake_state. If this is the client side of the connection, we then authenticate the server or mark the connection. If it's the server side, wait for an AUTHENTICATE cell.

◆ channel_tls_start_listener()

channel_listener_t* channel_tls_start_listener ( void  )

Start a channel_tls_t listener if necessary.

Return the current channel_tls_t listener, or start one if we haven't yet, and return that.

Here is the caller graph for this function:

◆ channel_tls_to_base()

channel_t* channel_tls_to_base ( channel_tls_t *  tlschan)

Cast a channel_tls_t to a channel_t.

Here is the caller graph for this function:

◆ channel_tls_update_marks()

void channel_tls_update_marks ( or_connection_t conn)

Update channel marks after connection_or.c has changed an address.

This is called from connection_or_init_conn_from_address() after the connection's _base.addr or real_addr fields have potentially been changed so we can recalculate the local mark. Notably, this happens when incoming connections are reverse-proxied and we only learn the real address of the remote router by looking it up in the consensus after we finish the handshake and know an authenticated identity digest.

Variable Documentation

◆ stats_n_auth_challenge_cells_processed

uint64_t stats_n_auth_challenge_cells_processed = 0

How many CELL_AUTH_CHALLENGE cells have we received, ever?

◆ stats_n_authenticate_cells_processed

uint64_t stats_n_authenticate_cells_processed = 0

How many CELL_AUTHENTICATE cells have we received, ever?

◆ stats_n_authorize_cells_processed

uint64_t stats_n_authorize_cells_processed = 0

How many CELL_AUTHORIZE cells have we received, ever?

◆ stats_n_certs_cells_processed

uint64_t stats_n_certs_cells_processed = 0

How many CELL_CERTS cells have we received, ever?

◆ stats_n_netinfo_cells_processed

uint64_t stats_n_netinfo_cells_processed = 0

How many CELL_NETINFO cells have we received, ever?

◆ stats_n_padding_cells_processed

uint64_t stats_n_padding_cells_processed = 0

How many CELL_PADDING cells have we received, ever?

◆ stats_n_versions_cells_processed

uint64_t stats_n_versions_cells_processed = 0

How many CELL_VERSIONS cells have we received, ever?

◆ stats_n_vpadding_cells_processed

uint64_t stats_n_vpadding_cells_processed = 0

How many CELL_VPADDING cells have we received, ever?