aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/address.c11
-rw-r--r--src/common/address.h2
-rw-r--r--src/common/compat.c10
-rw-r--r--src/common/container.c18
-rw-r--r--src/common/container.h1
-rw-r--r--src/common/crypto.c71
-rw-r--r--src/common/crypto.h4
-rw-r--r--src/common/crypto_ed25519.c30
-rw-r--r--src/common/crypto_ed25519.h15
-rw-r--r--src/common/crypto_format.c16
-rw-r--r--src/common/crypto_format.h1
-rw-r--r--src/common/log.c8
-rw-r--r--src/common/sandbox.c2
-rw-r--r--src/common/timers.c14
-rw-r--r--src/common/timers.h2
-rw-r--r--src/common/torlog.h4
-rw-r--r--src/common/tortls.c67
-rw-r--r--src/common/tortls.h10
-rw-r--r--src/common/util.c74
-rw-r--r--src/common/util.h4
-rw-r--r--src/common/util_bug.c2
21 files changed, 294 insertions, 72 deletions
diff --git a/src/common/address.c b/src/common/address.c
index 773e688554..c89e8797c6 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -2100,7 +2100,8 @@ get_interface_address,(int severity, uint32_t *addr))
}
/** Return true if we can tell that <b>name</b> is a canonical name for the
- * loopback address. */
+ * loopback address. Return true also for *.local hostnames, which are
+ * multicast DNS names for hosts on the local network. */
int
tor_addr_hostname_is_local(const char *name)
{
@@ -2121,3 +2122,11 @@ tor_addr_port_new(const tor_addr_t *addr, uint16_t port)
return ap;
}
+/** Return true iff <a>a</b> and <b>b</b> are the same address and port */
+int
+tor_addr_port_eq(const tor_addr_port_t *a,
+ const tor_addr_port_t *b)
+{
+ return tor_addr_eq(&a->addr, &b->addr) && a->port == b->port;
+}
+
diff --git a/src/common/address.h b/src/common/address.h
index 51db42c315..41daf012e6 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -342,6 +342,8 @@ get_interface_address_list(int severity, int include_internal)
}
tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port);
+int tor_addr_port_eq(const tor_addr_port_t *a,
+ const tor_addr_port_t *b);
#ifdef ADDRESS_PRIVATE
MOCK_DECL(smartlist_t *,get_interface_addresses_raw,(int severity,
diff --git a/src/common/compat.c b/src/common/compat.c
index 8d6a491c42..ebf05f59e1 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -204,7 +204,15 @@ tor_rename(const char *path_old, const char *path_new)
sandbox_intern_string(path_new));
}
-#if defined(HAVE_SYS_MMAN_H) || defined(RUNNING_DOXYGEN)
+/* Some MinGW builds have sys/mman.h, but not the corresponding symbols.
+ * Other configs rename the symbols using macros (including getpagesize).
+ * So check for sys/mman.h and unistd.h, and a getpagesize declaration. */
+#if (defined(HAVE_SYS_MMAN_H) && defined(HAVE_UNISTD_H) && \
+ defined(HAVE_DECL_GETPAGESIZE))
+#define COMPAT_HAS_MMAN_AND_PAGESIZE
+#endif
+
+#if defined(COMPAT_HAS_MMAN_AND_PAGESIZE) || defined(RUNNING_DOXYGEN)
/** Try to create a memory mapping for <b>filename</b> and return it. On
* failure, return NULL. Sets errno properly, using ERANGE to mean
* "empty file". */
diff --git a/src/common/container.c b/src/common/container.c
index ec59dccf62..1448ab403c 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -132,6 +132,24 @@ smartlist_remove(smartlist_t *sl, const void *element)
}
}
+/** As <b>smartlist_remove</b>, but do not change the order of
+ * any elements not removed */
+void
+smartlist_remove_keeporder(smartlist_t *sl, const void *element)
+{
+ int i, j, num_used_orig = sl->num_used;
+ if (element == NULL)
+ return;
+
+ for (i=j=0; j < num_used_orig; ++j) {
+ if (sl->list[j] == element) {
+ --sl->num_used;
+ } else {
+ sl->list[i++] = sl->list[j];
+ }
+ }
+}
+
/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
* return NULL. */
void *
diff --git a/src/common/container.h b/src/common/container.h
index 71495b660a..00c3ca81ad 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -33,6 +33,7 @@ void smartlist_clear(smartlist_t *sl);
void smartlist_add(smartlist_t *sl, void *element);
void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
void smartlist_remove(smartlist_t *sl, const void *element);
+void smartlist_remove_keeporder(smartlist_t *sl, const void *element);
void *smartlist_pop_last(smartlist_t *sl);
void smartlist_reverse(smartlist_t *sl);
void smartlist_string_remove(smartlist_t *sl, const char *element);
diff --git a/src/common/crypto.c b/src/common/crypto.c
index fff516cc8e..062179deda 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -1506,7 +1506,7 @@ crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
if (crypto_pk_get_digest(pk, digest)) {
return -1;
}
- if (crypto_digest(hashed_digest, digest, DIGEST_LEN)) {
+ if (crypto_digest(hashed_digest, digest, DIGEST_LEN) < 0) {
return -1;
}
base16_encode(fp_out, FINGERPRINT_LEN + 1, hashed_digest, DIGEST_LEN);
@@ -1700,19 +1700,21 @@ crypto_cipher_decrypt_with_iv(const char *key,
/** Compute the SHA1 digest of the <b>len</b> bytes on data stored in
* <b>m</b>. Write the DIGEST_LEN byte result into <b>digest</b>.
- * Return 0 on success, 1 on failure.
+ * Return 0 on success, -1 on failure.
*/
int
crypto_digest(char *digest, const char *m, size_t len)
{
tor_assert(m);
tor_assert(digest);
- return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
+ if (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL)
+ return -1;
+ return 0;
}
/** Compute a 256-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
* using the algorithm <b>algorithm</b>. Write the DIGEST_LEN256-byte result
- * into <b>digest</b>. Return 0 on success, 1 on failure. */
+ * into <b>digest</b>. Return 0 on success, -1 on failure. */
int
crypto_digest256(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm)
@@ -1720,16 +1722,22 @@ crypto_digest256(char *digest, const char *m, size_t len,
tor_assert(m);
tor_assert(digest);
tor_assert(algorithm == DIGEST_SHA256 || algorithm == DIGEST_SHA3_256);
+
+ int ret = 0;
if (algorithm == DIGEST_SHA256)
- return (SHA256((const uint8_t*)m,len,(uint8_t*)digest) == NULL);
+ ret = (SHA256((const uint8_t*)m,len,(uint8_t*)digest) != NULL);
else
- return (sha3_256((uint8_t *)digest, DIGEST256_LEN,(const uint8_t *)m, len)
- == -1);
+ ret = (sha3_256((uint8_t *)digest, DIGEST256_LEN,(const uint8_t *)m, len)
+ > -1);
+
+ if (!ret)
+ return -1;
+ return 0;
}
/** Compute a 512-bit digest of <b>len</b> bytes in data stored in <b>m</b>,
* using the algorithm <b>algorithm</b>. Write the DIGEST_LEN512-byte result
- * into <b>digest</b>. Return 0 on success, 1 on failure. */
+ * into <b>digest</b>. Return 0 on success, -1 on failure. */
int
crypto_digest512(char *digest, const char *m, size_t len,
digest_algorithm_t algorithm)
@@ -1737,12 +1745,18 @@ crypto_digest512(char *digest, const char *m, size_t len,
tor_assert(m);
tor_assert(digest);
tor_assert(algorithm == DIGEST_SHA512 || algorithm == DIGEST_SHA3_512);
+
+ int ret = 0;
if (algorithm == DIGEST_SHA512)
- return (SHA512((const unsigned char*)m,len,(unsigned char*)digest)
- == NULL);
+ ret = (SHA512((const unsigned char*)m,len,(unsigned char*)digest)
+ != NULL);
else
- return (sha3_512((uint8_t*)digest, DIGEST512_LEN, (const uint8_t*)m, len)
- == -1);
+ ret = (sha3_512((uint8_t*)digest, DIGEST512_LEN, (const uint8_t*)m, len)
+ > -1);
+
+ if (!ret)
+ return -1;
+ return 0;
}
/** Set the common_digests_t in <b>ds_out</b> to contain every digest on the
@@ -2109,6 +2123,35 @@ crypto_hmac_sha256(char *hmac_out,
tor_assert(rv);
}
+/** Compute a MAC using SHA3-256 of <b>msg_len</b> bytes in <b>msg</b> using a
+ * <b>key</b> of length <b>key_len</b> and a <b>salt</b> of length
+ * <b>salt_len</b>. Store the result of <b>len_out</b> bytes in in
+ * <b>mac_out</b>. This function can't fail. */
+void
+crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *msg, size_t msg_len)
+{
+ crypto_digest_t *digest;
+
+ const uint64_t key_len_netorder = tor_htonll(key_len);
+
+ tor_assert(mac_out);
+ tor_assert(key);
+ tor_assert(msg);
+
+ digest = crypto_digest256_new(DIGEST_SHA3_256);
+
+ /* Order matters here that is any subsystem using this function should
+ * expect this very precise ordering in the MAC construction. */
+ crypto_digest_add_bytes(digest, (const char *) &key_len_netorder,
+ sizeof(key_len_netorder));
+ crypto_digest_add_bytes(digest, (const char *) key, key_len);
+ crypto_digest_add_bytes(digest, (const char *) msg, msg_len);
+ crypto_digest_get_digest(digest, (char *) mac_out, len_out);
+ crypto_digest_free(digest);
+}
+
/** Internal state for a eXtendable-Output Function (XOF). */
struct crypto_xof_t {
keccak_state s;
@@ -2628,7 +2671,7 @@ crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len,
for (cp = key_out, i=0; cp < key_out+key_out_len;
++i, cp += DIGEST_LEN) {
tmp[key_in_len] = i;
- if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1))
+ if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1) < 0)
goto exit;
memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out)));
}
@@ -2852,7 +2895,7 @@ crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
size_t n;
for (i = 0; filenames[i]; ++i) {
- log_debug(LD_FS, "Opening %s for entropy", filenames[i]);
+ log_debug(LD_FS, "Considering %s for entropy", filenames[i]);
fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
if (fd<0) continue;
log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 116e0a62fd..bf2fa06aaa 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -255,6 +255,10 @@ void crypto_digest_assign(crypto_digest_t *into,
void crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
+void crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out,
+ const uint8_t *key, size_t key_len,
+ const uint8_t *msg, size_t msg_len);
+
crypto_xof_t *crypto_xof_new(void);
void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 30ed772274..8977e7a325 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/common/crypto_ed25519.c
@@ -211,6 +211,14 @@ ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong)
return 0;
}
+/** Return true iff 'pubkey' is set to zero (eg to indicate that it is not
+ * set). */
+int
+ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
+{
+ return tor_mem_is_zero((char*)pubkey->pubkey, ED25519_PUBKEY_LEN);
+}
+
/* Return a heap-allocated array that contains <b>msg</b> prefixed by the
* string <b>prefix_str</b>. Set <b>final_msg_len_out</b> to the size of the
* final array. If an error occured, return NULL. It's the resonsibility of the
@@ -267,11 +275,11 @@ ed25519_sign(ed25519_signature_t *signature_out,
* Like ed25519_sign(), but also prefix <b>msg</b> with <b>prefix_str</b>
* before signing. <b>prefix_str</b> must be a NUL-terminated string.
*/
-int
-ed25519_sign_prefixed(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t msg_len,
- const char *prefix_str,
- const ed25519_keypair_t *keypair)
+MOCK_IMPL(int,
+ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
+ const uint8_t *msg, size_t msg_len,
+ const char *prefix_str,
+ const ed25519_keypair_t *keypair))
{
int retval;
size_t prefixed_msg_len;
@@ -620,6 +628,18 @@ ed25519_pubkey_eq(const ed25519_public_key_t *key1,
return tor_memeq(key1->pubkey, key2->pubkey, ED25519_PUBKEY_LEN);
}
+/**
+ * Set <b>dest</b> to contain the same key as <b>src</b>.
+ */
+void
+ed25519_pubkey_copy(ed25519_public_key_t *dest,
+ const ed25519_public_key_t *src)
+{
+ tor_assert(dest);
+ tor_assert(src);
+ memcpy(dest, src, sizeof(ed25519_public_key_t));
+}
+
/** Check whether the given Ed25519 implementation seems to be working.
* If so, return 0; otherwise return -1. */
static int
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
index 31afc49ccc..56782cc12e 100644
--- a/src/common/crypto_ed25519.h
+++ b/src/common/crypto_ed25519.h
@@ -55,17 +55,20 @@ int ed25519_checksig(const ed25519_signature_t *signature,
const uint8_t *msg, size_t len,
const ed25519_public_key_t *pubkey);
-int
-ed25519_sign_prefixed(ed25519_signature_t *signature_out,
- const uint8_t *msg, size_t len,
- const char *prefix_str,
- const ed25519_keypair_t *keypair);
+MOCK_DECL(int,
+ed25519_sign_prefixed,(ed25519_signature_t *signature_out,
+ const uint8_t *msg, size_t len,
+ const char *prefix_str,
+ const ed25519_keypair_t *keypair));
+
int
ed25519_checksig_prefixed(const ed25519_signature_t *signature,
const uint8_t *msg, size_t len,
const char *prefix_str,
const ed25519_public_key_t *pubkey);
+int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey);
+
/**
* A collection of information necessary to check an Ed25519 signature. Used
* for batch verification.
@@ -118,6 +121,8 @@ void ed25519_keypair_free(ed25519_keypair_t *kp);
int ed25519_pubkey_eq(const ed25519_public_key_t *key1,
const ed25519_public_key_t *key2);
+void ed25519_pubkey_copy(ed25519_public_key_t *dest,
+ const ed25519_public_key_t *src);
void ed25519_set_impl_params(int use_donna);
void ed25519_init(void);
diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c
index 2f6d847c83..483013ee68 100644
--- a/src/common/crypto_format.c
+++ b/src/common/crypto_format.c
@@ -161,6 +161,22 @@ curve25519_public_from_base64(curve25519_public_key_t *pkey,
}
}
+/** For convenience: Convert <b>pkey</b> to a statically allocated base64
+ * string and return it. Not threadsafe. Subsequent calls invalidate
+ * previous returns. */
+const char *
+ed25519_fmt(const ed25519_public_key_t *pkey)
+{
+ static char formatted[ED25519_BASE64_LEN+1];
+ if (pkey) {
+ int r = ed25519_public_to_base64(formatted, pkey);
+ tor_assert(!r);
+ } else {
+ strlcpy(formatted, "<null>", sizeof(formatted));
+ }
+ return formatted;
+}
+
/** Try to decode the string <b>input</b> into an ed25519 public key. On
* success, store the value in <b>pkey</b> and return 0. Otherwise return
* -1. */
diff --git a/src/common/crypto_format.h b/src/common/crypto_format.h
index 012e228cc4..86c29d319c 100644
--- a/src/common/crypto_format.h
+++ b/src/common/crypto_format.h
@@ -28,6 +28,7 @@ int ed25519_public_from_base64(ed25519_public_key_t *pkey,
const char *input);
int ed25519_public_to_base64(char *output,
const ed25519_public_key_t *pkey);
+const char *ed25519_fmt(const ed25519_public_key_t *pkey);
/* XXXX move these to crypto_format.h */
#define ED25519_SIG_BASE64_LEN 86
diff --git a/src/common/log.c b/src/common/log.c
index 56adc77f84..5f7151bf0c 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -682,7 +682,7 @@ tor_log_get_logfile_names(smartlist_t *out)
continue;
if (lf->filename == NULL)
continue;
- smartlist_add(out, tor_strdup(lf->filename));
+ smartlist_add_strdup(out, lf->filename);
}
UNLOCK_LOGS();
@@ -1177,7 +1177,7 @@ static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
"HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
"OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
- "SCHED", NULL
+ "SCHED", "GUARD", NULL
};
/** Return a bitmask for the log domain for which <b>domain</b> is the name,
@@ -1319,10 +1319,8 @@ parse_log_severity_config(const char **cfg_ptr,
if (got_an_unqualified_range > 1)
return -1;
- space = strchr(cfg, ' ');
+ space = find_whitespace(cfg);
dash = strchr(cfg, '-');
- if (!space)
- space = strchr(cfg, '\0');
if (dash && dash < space) {
sev_lo = tor_strndup(cfg, dash-cfg);
sev_hi = tor_strndup(dash+1, space-(dash+1));
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index ebc843e130..8e72ebf137 100644
--- a/src/common/sandbox.c
+++ b/src/common/sandbox.c
@@ -1542,7 +1542,7 @@ sandbox_getaddrinfo(const char *name, const char *servname,
return err;
}
- /* Otherwise, the sanbox is on. If we have an item, yield its cached
+ /* Otherwise, the sandbox is on. If we have an item, yield its cached
result. */
if (item) {
*res = item->res;
diff --git a/src/common/timers.c b/src/common/timers.c
index 41b2008ac4..e1ad47b15b 100644
--- a/src/common/timers.c
+++ b/src/common/timers.c
@@ -255,6 +255,20 @@ timer_set_cb(tor_timer_t *t, timer_cb_fn_t cb, void *arg)
}
/**
+ * Set *<b>cb_out</b> (if provided) to this timer's callback function,
+ * and *<b>arg_out</b> (if provided) to this timer's callback argument.
+ */
+void
+timer_get_cb(const tor_timer_t *t,
+ timer_cb_fn_t *cb_out, void **arg_out)
+{
+ if (cb_out)
+ *cb_out = t->callback.cb;
+ if (arg_out)
+ *arg_out = t->callback.arg;
+}
+
+/**
* Schedule the timer t to fire at the current time plus a delay of
* <b>delay</b> microseconds. All times are relative to monotime_get().
*/
diff --git a/src/common/timers.h b/src/common/timers.h
index 5f918f8e15..c5246a3335 100644
--- a/src/common/timers.h
+++ b/src/common/timers.h
@@ -13,6 +13,8 @@ typedef void (*timer_cb_fn_t)(tor_timer_t *, void *,
const struct monotime_t *);
tor_timer_t *timer_new(timer_cb_fn_t cb, void *arg);
void timer_set_cb(tor_timer_t *t, timer_cb_fn_t cb, void *arg);
+void timer_get_cb(const tor_timer_t *t,
+ timer_cb_fn_t *cb_out, void **arg_out);
void timer_schedule(tor_timer_t *t, const struct timeval *delay);
void timer_disable(tor_timer_t *t);
void timer_free(tor_timer_t *t);
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 6732a42741..bc957858d9 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -99,8 +99,10 @@
#define LD_CHANNEL (1u<<21)
/** Scheduler */
#define LD_SCHED (1u<<22)
+/** Guard nodes */
+#define LD_GUARD (1u<<23)
/** Number of logging domains in the code. */
-#define N_LOGGING_DOMAINS 23
+#define N_LOGGING_DOMAINS 24
/** This log message is not safe to send to a callback-based logger
* immediately. Used as a flag, not a log domain. */
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 62ed5be344..2efb3baa73 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -136,6 +136,7 @@ static void tor_tls_context_decref(tor_tls_context_t *ctx);
static void tor_tls_context_incref(tor_tls_context_t *ctx);
static int check_cert_lifetime_internal(int severity, const X509 *cert,
+ time_t now,
int past_tolerance, int future_tolerance);
/** Global TLS contexts. We keep them here because nobody else needs
@@ -522,7 +523,8 @@ MOCK_IMPL(STATIC X509 *,
goto error;
if (!X509_set_pubkey(x509, pkey))
goto error;
- if (!X509_sign(x509, sign_pkey, EVP_sha1()))
+
+ if (!X509_sign(x509, sign_pkey, EVP_sha256()))
goto error;
goto done;
@@ -677,6 +679,13 @@ MOCK_IMPL(STATIC tor_x509_cert_t *,
return cert;
}
+/** Return a copy of <b>cert</b> */
+tor_x509_cert_t *
+tor_x509_cert_dup(const tor_x509_cert_t *cert)
+{
+ return tor_x509_cert_new(X509_dup(cert->cert));
+}
+
/** Read a DER-encoded X509 cert, of length exactly <b>certificate_len</b>,
* from a <b>certificate</b>. Return a newly allocated tor_x509_cert_t on
* success and NULL on failure. */
@@ -769,8 +778,8 @@ tor_tls_context_decref(tor_tls_context_t *ctx)
/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
* and ID certificate that we're currently using for our V3 in-protocol
* handshake's certificate chain. If <b>server</b> is true, provide the certs
- * that we use in server mode; otherwise, provide the certs that we use in
- * client mode. */
+ * that we use in server mode (auth, ID); otherwise, provide the certs that we
+ * use in client mode. (link, ID) */
int
tor_tls_get_my_certs(int server,
const tor_x509_cert_t **link_cert_out,
@@ -800,7 +809,7 @@ tor_tls_get_my_client_auth_key(void)
/**
* Return a newly allocated copy of the public key that a certificate
- * certifies. Return NULL if the cert's key is not RSA.
+ * certifies. Watch out! This returns NULL if the cert's key is not RSA.
*/
crypto_pk_t *
tor_tls_cert_get_key(tor_x509_cert_t *cert)
@@ -855,6 +864,7 @@ int
tor_tls_cert_is_valid(int severity,
const tor_x509_cert_t *cert,
const tor_x509_cert_t *signing_cert,
+ time_t now,
int check_rsa_1024)
{
check_no_tls_errors();
@@ -874,7 +884,7 @@ tor_tls_cert_is_valid(int severity,
/* okay, the signature checked out right. Now let's check the check the
* lifetime. */
- if (check_cert_lifetime_internal(severity, cert->cert,
+ if (check_cert_lifetime_internal(severity, cert->cert, now,
48*60*60, 30*24*60*60) < 0)
goto bad;
@@ -1019,6 +1029,8 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
/** The group we should use for ecdhe when none was selected. */
#define NID_tor_default_ecdhe_group NID_X9_62_prime256v1
+#define RSA_LINK_KEY_BITS 2048
+
/** Create a new TLS context for use with Tor TLS handshakes.
* <b>identity</b> should be set to the identity key used to sign the
* certificate.
@@ -1044,7 +1056,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
/* Generate short-term RSA key for use with TLS. */
if (!(rsa = crypto_pk_new()))
goto error;
- if (crypto_pk_generate_key(rsa)<0)
+ if (crypto_pk_generate_key_with_bits(rsa, RSA_LINK_KEY_BITS)<0)
goto error;
if (!is_client) {
/* Generate short-term RSA key for use in the in-protocol ("v3")
@@ -2023,13 +2035,13 @@ tor_tls_get_peer_cert,(tor_tls_t *tls))
/** Warn that a certificate lifetime extends through a certain range. */
static void
-log_cert_lifetime(int severity, const X509 *cert, const char *problem)
+log_cert_lifetime(int severity, const X509 *cert, const char *problem,
+ time_t now)
{
BIO *bio = NULL;
BUF_MEM *buf;
char *s1=NULL, *s2=NULL;
char mytime[33];
- time_t now = time(NULL);
struct tm tm;
size_t n;
@@ -2177,6 +2189,7 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity_key)
*/
int
tor_tls_check_lifetime(int severity, tor_tls_t *tls,
+ time_t now,
int past_tolerance, int future_tolerance)
{
X509 *cert;
@@ -2185,7 +2198,7 @@ tor_tls_check_lifetime(int severity, tor_tls_t *tls,
if (!(cert = SSL_get_peer_certificate(tls->ssl)))
goto done;
- if (check_cert_lifetime_internal(severity, cert,
+ if (check_cert_lifetime_internal(severity, cert, now,
past_tolerance, future_tolerance) < 0)
goto done;
@@ -2201,24 +2214,24 @@ tor_tls_check_lifetime(int severity, tor_tls_t *tls,
/** Helper: check whether <b>cert</b> is expired give or take
* <b>past_tolerance</b> seconds, or not-yet-valid give or take
- * <b>future_tolerance</b> seconds. If it is live, return 0. If it is not
- * live, log a message and return -1. */
+ * <b>future_tolerance</b> seconds. (Relative to the current time
+ * <b>now</b>.) If it is live, return 0. If it is not live, log a message
+ * and return -1. */
static int
check_cert_lifetime_internal(int severity, const X509 *cert,
+ time_t now,
int past_tolerance, int future_tolerance)
{
- time_t now, t;
-
- now = time(NULL);
+ time_t t;
t = now + future_tolerance;
if (X509_cmp_time(X509_get_notBefore_const(cert), &t) > 0) {
- log_cert_lifetime(severity, cert, "not yet valid");
+ log_cert_lifetime(severity, cert, "not yet valid", now);
return -1;
}
t = now - past_tolerance;
if (X509_cmp_time(X509_get_notAfter_const(cert), &t) < 0) {
- log_cert_lifetime(severity, cert, "already expired");
+ log_cert_lifetime(severity, cert, "already expired", now);
return -1;
}
@@ -2443,6 +2456,28 @@ tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out))
return 0;
}
+/** Using the RFC5705 key material exporting construction, and the
+ * provided <b>context</b> (<b>context_len</b> bytes long) and
+ * <b>label</b> (a NUL-terminated string), compute a 32-byte secret in
+ * <b>secrets_out</b> that only the parties to this TLS session can
+ * compute. Return 0 on success and -1 on failure.
+ */
+MOCK_IMPL(int,
+tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out,
+ const uint8_t *context,
+ size_t context_len,
+ const char *label))
+{
+ tor_assert(tls);
+ tor_assert(tls->ssl);
+
+ int r = SSL_export_keying_material(tls->ssl,
+ secrets_out, DIGEST256_LEN,
+ label, strlen(label),
+ context, context_len, 1);
+ return (r == 1) ? 0 : -1;
+}
+
/** Examine the amount of memory used and available for buffers in <b>tls</b>.
* Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
* buffer and *<b>rbuf_bytes</b> to the amount actually used.
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 7c035a2cd5..6510fdbe64 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -176,6 +176,7 @@ extern uint64_t total_bytes_written_by_tls;
#endif /* endif TORTLS_PRIVATE */
+tor_x509_cert_t *tor_x509_cert_dup(const tor_x509_cert_t *cert);
const char *tor_tls_err_to_string(int err);
void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz);
@@ -200,7 +201,8 @@ int tor_tls_peer_has_cert(tor_tls_t *tls);
MOCK_DECL(tor_x509_cert_t *,tor_tls_get_peer_cert,(tor_tls_t *tls));
int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity);
int tor_tls_check_lifetime(int severity,
- tor_tls_t *tls, int past_tolerance,
+ tor_tls_t *tls, time_t now,
+ int past_tolerance,
int future_tolerance);
MOCK_DECL(int, tor_tls_read, (tor_tls_t *tls, char *cp, size_t len));
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
@@ -226,6 +228,11 @@ int tor_tls_used_v1_handshake(tor_tls_t *tls);
int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
int tor_tls_server_got_renegotiate(tor_tls_t *tls);
MOCK_DECL(int,tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out));
+MOCK_DECL(int,tor_tls_export_key_material,(
+ tor_tls_t *tls, uint8_t *secrets_out,
+ const uint8_t *context,
+ size_t context_len,
+ const char *label));
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
*/
@@ -254,6 +261,7 @@ MOCK_DECL(int,tor_tls_cert_matches_key,(const tor_tls_t *tls,
int tor_tls_cert_is_valid(int severity,
const tor_x509_cert_t *cert,
const tor_x509_cert_t *signing_cert,
+ time_t now,
int check_rsa_1024);
const char *tor_tls_get_ciphersuite_name(tor_tls_t *tls);
diff --git a/src/common/util.c b/src/common/util.c
index a7bce2ea6c..9d134c1bb2 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1803,17 +1803,26 @@ format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
* parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
* failure. Ignore extraneous stuff in <b>cp</b> after the end of the time
- * string, unless <b>strict</b> is set. */
+ * string, unless <b>strict</b> is set. If <b>nospace</b> is set,
+ * expect the YYYY-MM-DDTHH:MM:SS format. */
int
-parse_iso_time_(const char *cp, time_t *t, int strict)
+parse_iso_time_(const char *cp, time_t *t, int strict, int nospace)
{
struct tm st_tm;
unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
int n_fields;
- char extra_char;
- n_fields = tor_sscanf(cp, "%u-%2u-%2u %2u:%2u:%2u%c", &year, &month,
- &day, &hour, &minute, &second, &extra_char);
- if (strict ? (n_fields != 6) : (n_fields < 6)) {
+ char extra_char, separator_char;
+ n_fields = tor_sscanf(cp, "%u-%2u-%2u%c%2u:%2u:%2u%c",
+ &year, &month, &day,
+ &separator_char,
+ &hour, &minute, &second, &extra_char);
+ if (strict ? (n_fields != 7) : (n_fields < 7)) {
+ char *esc = esc_for_log(cp);
+ log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
+ tor_free(esc);
+ return -1;
+ }
+ if (separator_char != (nospace ? 'T' : ' ')) {
char *esc = esc_for_log(cp);
log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
tor_free(esc);
@@ -1855,7 +1864,16 @@ parse_iso_time_(const char *cp, time_t *t, int strict)
int
parse_iso_time(const char *cp, time_t *t)
{
- return parse_iso_time_(cp, t, 1);
+ return parse_iso_time_(cp, t, 1, 0);
+}
+
+/**
+ * As parse_iso_time, but parses a time encoded by format_iso_time_nospace().
+ */
+int
+parse_iso_time_nospace(const char *cp, time_t *t)
+{
+ return parse_iso_time_(cp, t, 1, 1);
}
/** Given a <b>date</b> in one of the three formats allowed by HTTP (ugh),
@@ -2270,10 +2288,14 @@ check_private_dir,(const char *dirname, cpd_check_t check,
* permissions on the directory will be checked again below.*/
fd = open(sandbox_intern_string(dirname), O_NOFOLLOW);
- if (fd == -1)
+ if (fd == -1) {
+ log_warn(LD_FS, "Could not reopen recently created directory %s: %s",
+ dirname,
+ strerror(errno));
return -1;
- else
+ } else {
close(fd);
+ }
} else if (!(check & CPD_CHECK)) {
log_warn(LD_FS, "Directory %s does not exist.", dirname);
@@ -2601,6 +2623,14 @@ finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
if (file_data->rename_on_close) {
tor_assert(file_data->tempname && file_data->filename);
+ if (!abort_write) {
+ tor_assert(strcmp(file_data->filename, file_data->tempname));
+ if (replace_file(file_data->tempname, file_data->filename)) {
+ log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
+ strerror(errno));
+ abort_write = r = -1;
+ }
+ }
if (abort_write) {
int res = unlink(file_data->tempname);
if (res != 0) {
@@ -2609,13 +2639,6 @@ finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
file_data->tempname, strerror(errno));
r = -1;
}
- } else {
- tor_assert(strcmp(file_data->filename, file_data->tempname));
- if (replace_file(file_data->tempname, file_data->filename)) {
- log_warn(LD_FS, "Error replacing \"%s\": %s", file_data->filename,
- strerror(errno));
- r = -1;
- }
}
}
@@ -3534,6 +3557,17 @@ smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
smartlist_add(sl, str);
}
+/** Append a copy of string to sl */
+void
+smartlist_add_strdup(struct smartlist_t *sl, const char *string)
+{
+ char *copy;
+
+ copy = tor_strdup(string);
+
+ smartlist_add(sl, copy);
+}
+
/** Return a new list containing the filenames in the directory <b>dirname</b>.
* Return NULL on error or if <b>dirname</b> is not a directory.
*/
@@ -3567,7 +3601,7 @@ tor_listdir, (const char *dirname))
#endif
if (strcmp(name, ".") &&
strcmp(name, "..")) {
- smartlist_add(result, tor_strdup(name));
+ smartlist_add_strdup(result, name);
}
if (!FindNextFile(handle, &findData)) {
DWORD err;
@@ -3593,7 +3627,7 @@ tor_listdir, (const char *dirname))
if (!strcmp(de->d_name, ".") ||
!strcmp(de->d_name, ".."))
continue;
- smartlist_add(result, tor_strdup(de->d_name));
+ smartlist_add_strdup(result, de->d_name);
}
closedir(d);
#endif
@@ -4864,7 +4898,7 @@ get_current_process_environment_variables(void)
char **environ_tmp; /* Not const char ** ? Really? */
for (environ_tmp = get_environment(); *environ_tmp; ++environ_tmp) {
- smartlist_add(sl, tor_strdup(*environ_tmp));
+ smartlist_add_strdup(sl, *environ_tmp);
}
return sl;
@@ -5247,7 +5281,7 @@ tor_get_lines_from_handle, (FILE *handle,
goto done;
if (!lines) lines = smartlist_new();
- smartlist_add(lines, tor_strdup(stdout_buf));
+ smartlist_add_strdup(lines, stdout_buf);
}
done:
diff --git a/src/common/util.h b/src/common/util.h
index 479fc8d610..2b3e48ea8e 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -239,6 +239,7 @@ void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...)
void smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
va_list args)
CHECK_PRINTF(2, 0);
+void smartlist_add_strdup(struct smartlist_t *sl, const char *string);
/* Time helpers */
long tv_udiff(const struct timeval *start, const struct timeval *end);
@@ -254,8 +255,9 @@ void format_local_iso_time(char *buf, time_t t);
void format_iso_time(char *buf, time_t t);
void format_iso_time_nospace(char *buf, time_t t);
void format_iso_time_nospace_usec(char *buf, const struct timeval *tv);
-int parse_iso_time_(const char *cp, time_t *t, int strict);
+int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace);
int parse_iso_time(const char *buf, time_t *t);
+int parse_iso_time_nospace(const char *cp, time_t *t);
int parse_http_time(const char *buf, struct tm *tm);
int format_time_interval(char *out, size_t out_len, long interval);
diff --git a/src/common/util_bug.c b/src/common/util_bug.c
index 08aba47974..c7bfdefe80 100644
--- a/src/common/util_bug.c
+++ b/src/common/util_bug.c
@@ -44,7 +44,7 @@ static void
add_captured_bug(const char *s)
{
--n_bugs_to_capture;
- smartlist_add(bug_messages, tor_strdup(s));
+ smartlist_add_strdup(bug_messages, s);
}
/** Set a callback to be invoked when we get any tor_bug_occurred_
* invocation. We use this in the unit tests so that a nonfatal