mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 12:23:32 +01:00
When parsing certs cells, allow more certs types
Implements the parsing part of #19157
This commit is contained in:
parent
77e2be06f6
commit
986695fb74
@ -33,6 +33,7 @@
|
||||
#include "router.h"
|
||||
#include "routerlist.h"
|
||||
#include "scheduler.h"
|
||||
#include "torcert.h"
|
||||
|
||||
/** How many CELL_PADDING cells have we received, ever? */
|
||||
uint64_t stats_n_padding_cells_processed = 0;
|
||||
@ -1722,6 +1723,41 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
|
||||
assert_connection_ok(TO_CONN(chan->conn),time(NULL));
|
||||
}
|
||||
|
||||
/** Types of certificates that we know how to parse from CERTS cells. Each
|
||||
* type corresponds to a different encoding format. */
|
||||
typedef enum cert_encoding_t {
|
||||
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. */
|
||||
} cert_encoding_t;
|
||||
|
||||
/**
|
||||
* Given one of the certificate type codes used in a CERTS cell,
|
||||
* return the corresponding cert_encoding_t that we should use to parse
|
||||
* the certificate.
|
||||
*/
|
||||
static cert_encoding_t
|
||||
certs_cell_typenum_to_cert_type(int typenum)
|
||||
{
|
||||
switch (typenum) {
|
||||
case CERTTYPE_RSA1024_ID_LINK:
|
||||
case CERTTYPE_RSA1024_ID_ID:
|
||||
case CERTTYPE_RSA1024_ID_AUTH:
|
||||
return CERT_ENCODING_X509;
|
||||
case CERTTYPE_ED_ID_SIGN:
|
||||
case CERTTYPE_ED_SIGN_LINK:
|
||||
case CERTTYPE_ED_SIGN_AUTH:
|
||||
return CERT_ENCODING_ED25519;
|
||||
case CERTTYPE_RSA1024_ID_EDID:
|
||||
return CERT_ENCODING_RSA_CROSSCERT;
|
||||
default:
|
||||
return CERT_ENCODING_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a CERTS cell from a channel.
|
||||
*
|
||||
@ -1741,14 +1777,20 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
|
||||
STATIC void
|
||||
channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
|
||||
{
|
||||
#define MAX_CERT_TYPE_WANTED OR_CERT_TYPE_AUTH_1024
|
||||
tor_x509_cert_t *certs[MAX_CERT_TYPE_WANTED + 1];
|
||||
#define MAX_CERT_TYPE_WANTED CERTTYPE_RSA1024_ID_EDID
|
||||
/* These arrays will be sparse, since a cert type can be at most one
|
||||
* of ed/x509 */
|
||||
tor_x509_cert_t *x509_certs[MAX_CERT_TYPE_WANTED + 1];
|
||||
tor_cert_t *ed_certs[MAX_CERT_TYPE_WANTED + 1];
|
||||
|
||||
rsa_ed_crosscert_t *rsa_crosscert = NULL;
|
||||
int n_certs, i;
|
||||
certs_cell_t *cc = NULL;
|
||||
|
||||
int send_netinfo = 0;
|
||||
|
||||
memset(certs, 0, sizeof(certs));
|
||||
memset(x509_certs, 0, sizeof(x509_certs));
|
||||
memset(ed_certs, 0, sizeof(ed_certs));
|
||||
tor_assert(cell);
|
||||
tor_assert(chan);
|
||||
tor_assert(chan->conn);
|
||||
@ -1792,26 +1834,70 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
|
||||
|
||||
if (cert_type > MAX_CERT_TYPE_WANTED)
|
||||
continue;
|
||||
|
||||
tor_x509_cert_t *cert = tor_x509_cert_decode(cert_body, cert_len);
|
||||
if (!cert) {
|
||||
const cert_encoding_t ct = certs_cell_typenum_to_cert_type(cert_type);
|
||||
switch (ct) {
|
||||
default:
|
||||
case CERT_ENCODING_UNKNOWN:
|
||||
break;
|
||||
case CERT_ENCODING_X509: {
|
||||
tor_x509_cert_t *x509_cert = tor_x509_cert_decode(cert_body, cert_len);
|
||||
if (!x509_cert) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Received undecodable certificate in CERTS cell from %s:%d",
|
||||
safe_str(chan->conn->base_.address),
|
||||
chan->conn->base_.port);
|
||||
} else {
|
||||
if (certs[cert_type]) {
|
||||
tor_x509_cert_free(cert);
|
||||
if (x509_certs[cert_type]) {
|
||||
tor_x509_cert_free(x509_cert);
|
||||
ERR("Duplicate x509 certificate");
|
||||
} else {
|
||||
certs[cert_type] = cert;
|
||||
x509_certs[cert_type] = x509_cert;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CERT_ENCODING_ED25519: {
|
||||
tor_cert_t *ed_cert = tor_cert_parse(cert_body, cert_len);
|
||||
if (!ed_cert) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Received undecodable Ed certificate in CERTS cell from %s:%d",
|
||||
safe_str(chan->conn->base_.address),
|
||||
chan->conn->base_.port);
|
||||
} else {
|
||||
if (ed_certs[cert_type]) {
|
||||
tor_cert_free(ed_cert);
|
||||
ERR("Duplicate Ed25519 certificate");
|
||||
} else {
|
||||
ed_certs[cert_type] = ed_cert;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CERT_ENCODING_RSA_CROSSCERT: {
|
||||
rsa_ed_crosscert_t *cc_cert = NULL;
|
||||
ssize_t n = rsa_ed_crosscert_parse(&cc_cert, cert_body, cert_len);
|
||||
if (n != cert_len) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Received unparseable RS1024-Ed25519 crosscert "
|
||||
" in CERTS cell from %s:%d",
|
||||
safe_str(chan->conn->base_.address),
|
||||
chan->conn->base_.port);
|
||||
} else {
|
||||
if (rsa_crosscert) {
|
||||
rsa_ed_crosscert_free(cc_cert);
|
||||
ERR("Duplicate RSA->Ed25519 crosscert");
|
||||
} else {
|
||||
rsa_crosscert = cc_cert;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tor_x509_cert_t *id_cert = certs[OR_CERT_TYPE_ID_1024];
|
||||
tor_x509_cert_t *auth_cert = certs[OR_CERT_TYPE_AUTH_1024];
|
||||
tor_x509_cert_t *link_cert = certs[OR_CERT_TYPE_TLS_LINK];
|
||||
tor_x509_cert_t *id_cert = x509_certs[OR_CERT_TYPE_ID_1024];
|
||||
tor_x509_cert_t *auth_cert = x509_certs[OR_CERT_TYPE_AUTH_1024];
|
||||
tor_x509_cert_t *link_cert = x509_certs[OR_CERT_TYPE_TLS_LINK];
|
||||
|
||||
if (chan->conn->handshake_state->started_here) {
|
||||
int severity;
|
||||
@ -1862,7 +1948,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
|
||||
safe_str(chan->conn->base_.address), chan->conn->base_.port);
|
||||
|
||||
chan->conn->handshake_state->id_cert = id_cert;
|
||||
certs[OR_CERT_TYPE_ID_1024] = NULL;
|
||||
x509_certs[OR_CERT_TYPE_ID_1024] = NULL;
|
||||
|
||||
if (!public_server_mode(get_options())) {
|
||||
/* If we initiated the connection and we are not a public server, we
|
||||
@ -1889,7 +1975,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
|
||||
|
||||
chan->conn->handshake_state->id_cert = id_cert;
|
||||
chan->conn->handshake_state->auth_cert = auth_cert;
|
||||
certs[OR_CERT_TYPE_ID_1024] = certs[OR_CERT_TYPE_AUTH_1024] = NULL;
|
||||
x509_certs[OR_CERT_TYPE_ID_1024] = x509_certs[OR_CERT_TYPE_AUTH_1024]
|
||||
= NULL;
|
||||
}
|
||||
|
||||
chan->conn->handshake_state->received_certs_cell = 1;
|
||||
@ -1903,9 +1990,13 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
|
||||
}
|
||||
|
||||
err:
|
||||
for (unsigned u = 0; u < ARRAY_LENGTH(certs); ++u) {
|
||||
tor_x509_cert_free(certs[u]);
|
||||
for (unsigned u = 0; u < ARRAY_LENGTH(x509_certs); ++u) {
|
||||
tor_x509_cert_free(x509_certs[u]);
|
||||
}
|
||||
for (unsigned u = 0; u < ARRAY_LENGTH(ed_certs); ++u) {
|
||||
tor_cert_free(ed_certs[u]);
|
||||
}
|
||||
rsa_ed_crosscert_free(rsa_crosscert);
|
||||
certs_cell_free(cc);
|
||||
#undef ERR
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user