tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2016
- 16 participants
- 1665 discussions

04 Nov '16
commit c35c43d7d9df793c890deb14800e24327fbca452
Merge: bd6aa4f c189cb5
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 13:26:37 2016 -0400
Merge branch 'ticket17238_029_02-resquash'
Conflicts:
src/or/rendclient.c
src/or/rendcommon.c
src/or/routerparse.c
src/test/test_dir.c
src/trunnel/ed25519_cert.h
src/or/circuitlist.c | 38 +-
src/or/circuitlist.h | 2 +-
src/or/circuituse.c | 9 +-
src/or/connection.c | 5 +-
src/or/connection_edge.c | 10 +-
src/or/control.c | 21 +-
src/or/directory.c | 179 +++-
src/or/directory.h | 15 +-
src/or/hs_cache.c | 384 ++++++++
src/or/hs_cache.h | 61 ++
src/or/hs_common.c | 280 ++++++
src/or/hs_common.h | 39 +
src/or/hs_descriptor.c | 1939 ++++++++++++++++++++++++++++++++++++++
src/or/hs_descriptor.h | 238 +++++
src/or/include.am | 8 +
src/or/main.c | 4 +-
src/or/or.h | 42 +-
src/or/parsecommon.c | 450 +++++++++
src/or/parsecommon.h | 314 ++++++
src/or/relay.c | 5 +-
src/or/rendcache.c | 79 +-
src/or/rendcache.h | 13 +-
src/or/rendclient.c | 148 +--
src/or/rendclient.h | 2 +-
src/or/rendcommon.c | 149 +--
src/or/rendcommon.h | 24 +-
src/or/rendservice.c | 87 +-
src/or/routerparse.c | 723 +-------------
src/or/torcert.h | 15 +-
src/test/include.am | 2 +
src/test/test.c | 2 +
src/test/test.h | 2 +
src/test/test_connection.c | 12 +-
src/test/test_dir.c | 62 ++
src/test/test_dir_handle_get.c | 13 -
src/test/test_helpers.c | 13 +
src/test/test_helpers.h | 4 +
src/test/test_hs.c | 103 +-
src/test/test_hs_cache.c | 479 ++++++++++
src/test/test_hs_descriptor.c | 1130 ++++++++++++++++++++++
src/test/test_rendcache.c | 57 +-
src/trunnel/ed25519_cert.c | 881 +++++++++++++++++
src/trunnel/ed25519_cert.h | 300 ++++++
src/trunnel/ed25519_cert.trunnel | 7 +-
44 files changed, 7168 insertions(+), 1182 deletions(-)
diff --cc src/or/connection_edge.c
index 0c18de0,2726349..875c911
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@@ -72,9 -27,9 +72,10 @@@
#include "control.h"
#include "dns.h"
#include "dnsserv.h"
+#include "directory.h"
#include "dirserv.h"
#include "hibernate.h"
+ #include "hs_common.h"
#include "main.h"
#include "nodelist.h"
#include "policies.h"
@@@ -1861,11 -1708,12 +1862,12 @@@ connection_ap_handshake_rewrite_and_att
if (rend_data == NULL) {
return -1;
}
+ const char *onion_address = rend_data_get_address(rend_data);
log_info(LD_REND,"Got a hidden service request for ID '%s'",
- safe_str_client(rend_data->onion_address));
+ safe_str_client(onion_address));
- /* Lookup the given onion address. If invalid, stop right now else we
- * might have it in the cache or not, it will be tested later on. */
+ /* Lookup the given onion address. If invalid, stop right now.
+ * Otherwise, we might have it in the cache or not. */
unsigned int refetch_desc = 0;
rend_cache_entry_t *entry = NULL;
const int rend_cache_lookup_result =
diff --cc src/or/directory.h
index f1cdd9f,210d623..acb7394
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@@ -132,11 -132,18 +132,19 @@@ int download_status_get_n_failures(cons
int download_status_get_n_attempts(const download_status_t *dls);
time_t download_status_get_next_attempt_at(const download_status_t *dls);
-int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose);
+int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
+ const char *resource);
+ #ifdef DIRECTORY_PRIVATE
+
+ struct get_handler_args_t;
+ STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn,
+ const struct get_handler_args_t *args);
+
+ #endif
+
#ifdef TOR_UNIT_TESTS
- /* Used only by directory.c and test_dir.c */
+ /* Used only by test_dir.c */
STATIC int parse_http_url(const char *headers, char **url);
STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose,
diff --cc src/or/include.am
index b4554aa,02d67fa..10f8b85
--- a/src/or/include.am
+++ b/src/or/include.am
@@@ -59,8 -62,8 +62,9 @@@ LIBTOR_A_SOURCES =
src/or/shared_random.c \
src/or/shared_random_state.c \
src/or/transports.c \
+ src/or/parsecommon.c \
src/or/periodic.c \
+ src/or/protover.c \
src/or/policies.c \
src/or/reasons.c \
src/or/relay.c \
@@@ -171,9 -177,9 +178,10 @@@ ORHEADERS =
src/or/shared_random.h \
src/or/shared_random_state.h \
src/or/transports.h \
+ src/or/parsecommon.h \
src/or/periodic.h \
src/or/policies.h \
+ src/or/protover.h \
src/or/reasons.h \
src/or/relay.h \
src/or/rendcache.h \
diff --cc src/or/parsecommon.h
index 0000000,be7cba4..3a86c52
mode 000000,100644..100644
--- a/src/or/parsecommon.h
+++ b/src/or/parsecommon.h
@@@ -1,0 -1,306 +1,314 @@@
+ /* Copyright (c) 2016, The Tor Project, Inc. */
+ /* See LICENSE for licensing information */
+
+ /**
+ * \file parsecommon.h
+ * \brief Header file for parsecommon.c
+ **/
+
+ #ifndef TOR_PARSECOMMON_H
+ #define TOR_PARSECOMMON_H
+
+ #include "container.h"
+ #include "crypto.h"
+ #include "memarea.h"
+
+ /** Enumeration of possible token types. The ones starting with K_ correspond
+ * to directory 'keywords'. A_ is for an annotation, R or C is related to
+ * hidden services, ERR_ is an error in the tokenizing process, EOF_ is an
+ * end-of-file marker, and NIL_ is used to encode not-a-token.
+ */
+ typedef enum {
+ K_ACCEPT = 0,
+ K_ACCEPT6,
+ K_DIRECTORY_SIGNATURE,
+ K_RECOMMENDED_SOFTWARE,
+ K_REJECT,
+ K_REJECT6,
+ K_ROUTER,
+ K_SIGNED_DIRECTORY,
+ K_SIGNING_KEY,
+ K_ONION_KEY,
+ K_ONION_KEY_NTOR,
+ K_ROUTER_SIGNATURE,
+ K_PUBLISHED,
+ K_RUNNING_ROUTERS,
+ K_ROUTER_STATUS,
+ K_PLATFORM,
++ K_PROTO,
+ K_OPT,
+ K_BANDWIDTH,
+ K_CONTACT,
+ K_NETWORK_STATUS,
+ K_UPTIME,
+ K_DIR_SIGNING_KEY,
+ K_FAMILY,
+ K_FINGERPRINT,
+ K_HIBERNATING,
+ K_READ_HISTORY,
+ K_WRITE_HISTORY,
+ K_NETWORK_STATUS_VERSION,
+ K_DIR_SOURCE,
+ K_DIR_OPTIONS,
+ K_CLIENT_VERSIONS,
+ K_SERVER_VERSIONS,
++ K_RECOMMENDED_CLIENT_PROTOCOLS,
++ K_RECOMMENDED_RELAY_PROTOCOLS,
++ K_REQUIRED_CLIENT_PROTOCOLS,
++ K_REQUIRED_RELAY_PROTOCOLS,
+ K_OR_ADDRESS,
+ K_ID,
+ K_P,
+ K_P6,
+ K_R,
+ K_A,
+ K_S,
+ K_V,
+ K_W,
+ K_M,
+ K_EXTRA_INFO,
+ K_EXTRA_INFO_DIGEST,
+ K_CACHES_EXTRA_INFO,
+ K_HIDDEN_SERVICE_DIR,
+ K_ALLOW_SINGLE_HOP_EXITS,
+ K_IPV6_POLICY,
+ K_ROUTER_SIG_ED25519,
+ K_IDENTITY_ED25519,
+ K_MASTER_KEY_ED25519,
+ K_ONION_KEY_CROSSCERT,
+ K_NTOR_ONION_KEY_CROSSCERT,
+
+ K_DIRREQ_END,
+ K_DIRREQ_V2_IPS,
+ K_DIRREQ_V3_IPS,
+ K_DIRREQ_V2_REQS,
+ K_DIRREQ_V3_REQS,
+ K_DIRREQ_V2_SHARE,
+ K_DIRREQ_V3_SHARE,
+ K_DIRREQ_V2_RESP,
+ K_DIRREQ_V3_RESP,
+ K_DIRREQ_V2_DIR,
+ K_DIRREQ_V3_DIR,
+ K_DIRREQ_V2_TUN,
+ K_DIRREQ_V3_TUN,
+ K_ENTRY_END,
+ K_ENTRY_IPS,
+ K_CELL_END,
+ K_CELL_PROCESSED,
+ K_CELL_QUEUED,
+ K_CELL_TIME,
+ K_CELL_CIRCS,
+ K_EXIT_END,
+ K_EXIT_WRITTEN,
+ K_EXIT_READ,
+ K_EXIT_OPENED,
+
+ K_DIR_KEY_CERTIFICATE_VERSION,
+ K_DIR_IDENTITY_KEY,
+ K_DIR_KEY_PUBLISHED,
+ K_DIR_KEY_EXPIRES,
+ K_DIR_KEY_CERTIFICATION,
+ K_DIR_KEY_CROSSCERT,
+ K_DIR_ADDRESS,
+ K_DIR_TUNNELLED,
+
+ K_VOTE_STATUS,
+ K_VALID_AFTER,
+ K_FRESH_UNTIL,
+ K_VALID_UNTIL,
+ K_VOTING_DELAY,
+
+ K_KNOWN_FLAGS,
+ K_PARAMS,
+ K_BW_WEIGHTS,
+ K_VOTE_DIGEST,
+ K_CONSENSUS_DIGEST,
+ K_ADDITIONAL_DIGEST,
+ K_ADDITIONAL_SIGNATURE,
+ K_CONSENSUS_METHODS,
+ K_CONSENSUS_METHOD,
+ K_LEGACY_DIR_KEY,
+ K_DIRECTORY_FOOTER,
+ K_SIGNING_CERT_ED,
+ K_SR_FLAG,
+ K_COMMIT,
+ K_PREVIOUS_SRV,
+ K_CURRENT_SRV,
+ K_PACKAGE,
+
+ A_PURPOSE,
+ A_LAST_LISTED,
+ A_UNKNOWN_,
+
+ R_RENDEZVOUS_SERVICE_DESCRIPTOR,
+ R_VERSION,
+ R_PERMANENT_KEY,
+ R_SECRET_ID_PART,
+ R_PUBLICATION_TIME,
+ R_PROTOCOL_VERSIONS,
+ R_INTRODUCTION_POINTS,
+ R_SIGNATURE,
+
+ R_HS_DESCRIPTOR, /* From version 3, this MUST be generic to all future
+ descriptor versions thus making it R_. */
+ R3_DESC_LIFETIME,
+ R3_DESC_SIGNING_CERT,
+ R3_REVISION_COUNTER,
+ R3_ENCRYPTED,
+ R3_SIGNATURE,
+ R3_CREATE2_FORMATS,
+ R3_AUTHENTICATION_REQUIRED,
+ R3_INTRODUCTION_POINT,
+ R3_INTRO_AUTH_KEY,
+ R3_INTRO_ENC_KEY,
+ R3_INTRO_ENC_KEY_CERTIFICATION,
+
+ R_IPO_IDENTIFIER,
+ R_IPO_IP_ADDRESS,
+ R_IPO_ONION_PORT,
+ R_IPO_ONION_KEY,
+ R_IPO_SERVICE_KEY,
+
+ C_CLIENT_NAME,
+ C_DESCRIPTOR_COOKIE,
+ C_CLIENT_KEY,
+
+ ERR_,
+ EOF_,
+ NIL_
+ } directory_keyword;
+
+ /** Structure to hold a single directory token.
+ *
+ * We parse a directory by breaking it into "tokens", each consisting
+ * of a keyword, a line full of arguments, and a binary object. The
+ * arguments and object are both optional, depending on the keyword
+ * type.
+ *
+ * This structure is only allocated in memareas; do not allocate it on
+ * the heap, or token_clear() won't work.
+ */
+ typedef struct directory_token_t {
+ directory_keyword tp; /**< Type of the token. */
+ int n_args:30; /**< Number of elements in args */
+ char **args; /**< Array of arguments from keyword line. */
+
+ char *object_type; /**< -----BEGIN [object_type]-----*/
+ size_t object_size; /**< Bytes in object_body */
+ char *object_body; /**< Contents of object, base64-decoded. */
+
+ crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
+
+ char *error; /**< For ERR_ tokens only. */
+ } directory_token_t;
+
+ /** We use a table of rules to decide how to parse each token type. */
+
+ /** Rules for whether the keyword needs an object. */
+ typedef enum {
+ NO_OBJ, /**< No object, ever. */
+ NEED_OBJ, /**< Object is required. */
+ NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
+ NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
+ NEED_KEY, /**< Object is required, and must be a public key. */
+ OBJ_OK, /**< Object is optional. */
+ } obj_syntax;
+
+ #define AT_START 1
+ #define AT_END 2
+
+ #define TS_ANNOTATIONS_OK 1
+ #define TS_NOCHECK 2
+ #define TS_NO_NEW_ANNOTATIONS 4
+
-/*
++/**
++ * @name macros for defining token rules
++ *
+ * Helper macros to define token tables. 's' is a string, 't' is a
+ * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
+ * object syntax.
- *
+ */
++/**@{*/
+
+ /** Appears to indicate the end of a table. */
+ #define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
+ /** An item with no restrictions: used for obsolete document types */
+ #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
+ /** An item with no restrictions on multiplicity or location. */
+ #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
+ /** An item that must appear exactly once */
+ #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
+ /** An item that must appear exactly once, at the start of the document */
+ #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
+ /** An item that must appear exactly once, at the end of the document */
+ #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
+ /** An item that must appear one or more times */
+ #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
+ /** An item that must appear no more than once */
+ #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
+ /** An annotation that must appear no more than once */
+ #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
+
-/* Argument multiplicity: any number of arguments. */
++/** Argument multiplicity: any number of arguments. */
+ #define ARGS 0,INT_MAX,0
-/* Argument multiplicity: no arguments. */
++/** Argument multiplicity: no arguments. */
+ #define NO_ARGS 0,0,0
-/* Argument multiplicity: concatenate all arguments. */
++/** Argument multiplicity: concatenate all arguments. */
+ #define CONCAT_ARGS 1,1,1
-/* Argument multiplicity: at least <b>n</b> arguments. */
++/** Argument multiplicity: at least <b>n</b> arguments. */
+ #define GE(n) n,INT_MAX,0
-/* Argument multiplicity: exactly <b>n</b> arguments. */
++/** Argument multiplicity: exactly <b>n</b> arguments. */
+ #define EQ(n) n,n,0
++/**@}*/
+
+ /** Determines the parsing rules for a single token type. */
+ typedef struct token_rule_t {
+ /** The string value of the keyword identifying the type of item. */
+ const char *t;
+ /** The corresponding directory_keyword enum. */
+ directory_keyword v;
+ /** Minimum number of arguments for this item */
+ int min_args;
+ /** Maximum number of arguments for this item */
+ int max_args;
+ /** If true, we concatenate all arguments for this item into a single
+ * string. */
+ int concat_args;
+ /** Requirements on object syntax for this item. */
+ obj_syntax os;
+ /** Lowest number of times this item may appear in a document. */
+ int min_cnt;
+ /** Highest number of times this item may appear in a document. */
+ int max_cnt;
+ /** One or more of AT_START/AT_END to limit where the item may appear in a
+ * document. */
+ int pos;
+ /** True iff this token is an annotation. */
+ int is_annotation;
+ } token_rule_t;
+
+ void token_clear(directory_token_t *tok);
+
+ int tokenize_string(memarea_t *area,
+ const char *start, const char *end,
+ smartlist_t *out,
+ token_rule_t *table,
+ int flags);
+ directory_token_t *get_next_token(memarea_t *area,
+ const char **s,
+ const char *eos,
+ token_rule_t *table);
+
+ directory_token_t *find_by_keyword_(smartlist_t *s,
+ directory_keyword keyword,
+ const char *keyword_str);
+
+ #define find_by_keyword(s, keyword) \
+ find_by_keyword_((s), (keyword), #keyword)
+
+ directory_token_t *find_opt_by_keyword(smartlist_t *s,
+ directory_keyword keyword);
+ smartlist_t * find_all_by_keyword(smartlist_t *s, directory_keyword k);
+
+ #endif /* TOR_PARSECOMMON_H */
+
diff --cc src/or/rendclient.c
index a93bc94,0bfc1a1..b0dcf52
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@@ -149,13 -150,15 +151,13 @@@ rend_client_send_introduction(origin_ci
tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY);
tor_assert(introcirc->rend_data);
tor_assert(rendcirc->rend_data);
- tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address,
- rendcirc->rend_data->onion_address));
+ tor_assert(!rend_cmp_service_ids(rend_data_get_address(introcirc->rend_data),
+ rend_data_get_address(rendcirc->rend_data)));
-#ifndef NON_ANONYMOUS_MODE_ENABLED
- tor_assert(!(introcirc->build_state->onehop_tunnel));
- tor_assert(!(rendcirc->build_state->onehop_tunnel));
-#endif
+ assert_circ_anonymity_ok(introcirc, options);
+ assert_circ_anonymity_ok(rendcirc, options);
+ onion_address = rend_data_get_address(introcirc->rend_data);
- r = rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
- &entry);
+ r = rend_cache_lookup_entry(onion_address, -1, &entry);
/* An invalid onion address is not possible else we have a big issue. */
tor_assert(r != -EINVAL);
if (r < 0 || !rend_client_any_intro_points_usable(entry)) {
diff --cc src/or/rendcommon.c
index d9d39b1,125aa0f..1e5d1ab
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@@ -1067,52 -950,32 +950,82 @@@ rend_auth_decode_cookie(const char *coo
return res;
}
+/* Is this a rend client or server that allows direct (non-anonymous)
+ * connections?
+ * Clients must be specifically compiled and configured in this mode.
+ * Onion services can be configured to start in this mode.
+ * Prefer rend_client_allow_non_anonymous_connection() or
+ * rend_service_allow_non_anonymous_connection() whenever possible, so that
+ * checks are specific to Single Onion Services or Tor2web. */
+int
+rend_allow_non_anonymous_connection(const or_options_t* options)
+{
+ return (rend_client_allow_non_anonymous_connection(options)
+ || rend_service_allow_non_anonymous_connection(options));
+}
+
+/* Is this a rend client or server in non-anonymous mode?
+ * Clients must be specifically compiled in this mode.
+ * Onion services can be configured to start in this mode.
+ * Prefer rend_client_non_anonymous_mode_enabled() or
+ * rend_service_non_anonymous_mode_enabled() whenever possible, so that checks
+ * are specific to Single Onion Services or Tor2web. */
+int
+rend_non_anonymous_mode_enabled(const or_options_t *options)
+{
+ return (rend_client_non_anonymous_mode_enabled(options)
+ || rend_service_non_anonymous_mode_enabled(options));
+}
+
+/* Make sure that tor only builds one-hop circuits when they would not
+ * compromise user anonymity.
+ *
+ * One-hop circuits are permitted in Tor2web or Single Onion modes.
+ *
+ * Tor2web or Single Onion modes are also allowed to make multi-hop circuits.
+ * For example, single onion HSDir circuits are 3-hop to prevent denial of
+ * service.
+ */
+void
+assert_circ_anonymity_ok(origin_circuit_t *circ,
+ const or_options_t *options)
+{
+ tor_assert(options);
+ tor_assert(circ);
+ tor_assert(circ->build_state);
+
+ if (circ->build_state->onehop_tunnel) {
+ tor_assert(rend_allow_non_anonymous_connection(options));
+ }
+}
+
+ /* Return 1 iff the given <b>digest</b> of a permenanent hidden service key is
+ * equal to the digest in the origin circuit <b>ocirc</b> of its rend data .
+ * If the rend data doesn't exist, 0 is returned. This function is agnostic to
+ * the rend data version. */
+ int
+ rend_circuit_pk_digest_eq(const origin_circuit_t *ocirc,
+ const uint8_t *digest)
+ {
+ size_t rend_pk_digest_len;
+ const uint8_t *rend_pk_digest;
+
+ tor_assert(ocirc);
+ tor_assert(digest);
+
+ if (ocirc->rend_data == NULL) {
+ goto no_match;
+ }
+
+ rend_pk_digest = rend_data_get_pk_digest(ocirc->rend_data,
+ &rend_pk_digest_len);
+ if (tor_memeq(rend_pk_digest, digest, rend_pk_digest_len)) {
+ goto match;
+ }
+ no_match:
+ return 0;
+ match:
+ return 1;
+ }
+
++
diff --cc src/or/rendservice.c
index 7083051,21e88eb..b6bf63d
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@@ -1681,8 -1474,12 +1682,10 @@@ rend_service_receive_introduction(origi
goto err;
}
-#ifndef NON_ANONYMOUS_MODE_ENABLED
- tor_assert(!(circuit->build_state->onehop_tunnel));
-#endif
+ assert_circ_anonymity_ok(circuit, options);
tor_assert(circuit->rend_data);
+ /* XXX: This is version 2 specific (only one supported). */
+ rend_pk_digest = (char *) rend_data_get_pk_digest(circuit->rend_data, NULL);
/* We'll use this in a bazillion log messages */
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
@@@ -2970,17 -2702,21 +2971,19 @@@ rend_service_intro_has_opened(origin_ci
char auth[DIGEST_LEN + 9];
char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
int reason = END_CIRC_REASON_TORPROTOCOL;
+ const char *rend_pk_digest;
tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
-#ifndef NON_ANONYMOUS_MODE_ENABLED
- tor_assert(!(circuit->build_state->onehop_tunnel));
-#endif
+ assert_circ_anonymity_ok(circuit, get_options());
tor_assert(circuit->cpath);
tor_assert(circuit->rend_data);
+ /* XXX: This is version 2 specific (only on supported). */
+ rend_pk_digest = (char *) rend_data_get_pk_digest(circuit->rend_data, NULL);
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
- circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
+ rend_pk_digest, REND_SERVICE_ID_LEN);
- service = rend_service_get_by_pk_digest(
- circuit->rend_data->rend_pk_digest);
+ service = rend_service_get_by_pk_digest(rend_pk_digest);
if (!service) {
log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %u.",
safe_str_client(serviceid), (unsigned)circuit->base_.n_circ_id);
@@@ -3168,9 -2906,16 +3173,14 @@@ rend_service_rendezvous_has_opened(orig
tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
-#ifndef NON_ANONYMOUS_MODE_ENABLED
- tor_assert(!(circuit->build_state->onehop_tunnel));
-#endif
+ assert_circ_anonymity_ok(circuit, get_options());
tor_assert(circuit->rend_data);
+ /* XXX: This is version 2 specific (only one supported). */
+ rend_pk_digest = (char *) rend_data_get_pk_digest(circuit->rend_data,
+ NULL);
+ rend_cookie = circuit->rend_data->rend_cookie;
+
/* Declare the circuit dirty to avoid reuse, and for path-bias */
if (!circuit->base_.timestamp_dirty)
circuit->base_.timestamp_dirty = time(NULL);
diff --cc src/or/routerparse.c
index cb2bc72,ef6273b..5bc2d39
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@@ -60,8 -16,8 +60,9 @@@
#include "circuitstats.h"
#include "dirserv.h"
#include "dirvote.h"
+ #include "parsecommon.h"
#include "policies.h"
+#include "protover.h"
#include "rendcommon.h"
#include "router.h"
#include "routerlist.h"
diff --cc src/test/test_dir.c
index cf0b94c,4a2538b..c8daa18
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@@ -5698,48 -5346,66 +5698,109 @@@ test_dir_find_dl_schedule(void* data
}
static void
+test_dir_assumed_flags(void *arg)
+{
+ (void)arg;
+ smartlist_t *tokens = smartlist_new();
+ memarea_t *area = memarea_new();
+ routerstatus_t *rs = NULL;
+
+ /* First, we should always assume that the Running flag is set, even
+ * when it isn't listed, since the consensus method is always
+ * higher than 4. */
+ const char *str1 =
+ "r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 "
+ "192.168.0.1 9001 0\n"
+ "m thisoneislongerbecauseitisa256bitmddigest33\n"
+ "s Fast Guard Stable\n";
+
+ const char *cp = str1;
+ rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL,
+ 23, FLAV_MICRODESC);
+ tt_assert(rs);
+ tt_assert(rs->is_flagged_running);
+ tt_assert(! rs->is_valid);
+ tt_assert(! rs->is_exit);
+ tt_assert(rs->is_fast);
+ routerstatus_free(rs);
+
+ /* With method 24 or later, we can assume "valid" is set. */
+ cp = str1;
+ rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL,
+ 24, FLAV_MICRODESC);
+ tt_assert(rs);
+ tt_assert(rs->is_flagged_running);
+ tt_assert(rs->is_valid);
+ tt_assert(! rs->is_exit);
+ tt_assert(rs->is_fast);
+
+ done:
+ smartlist_free(tokens);
+ memarea_drop_all(area);
+ routerstatus_free(rs);
+}
+
++static void
+ test_dir_post_parsing(void *arg)
+ {
+ (void) arg;
+
+ /* Test the version parsing from an HS descriptor publish request. */
+ {
+ const char *end;
+ const char *prefix = "/tor/hs/";
+ int version = parse_hs_version_from_post("/tor/hs//publish", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/a/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/3/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, 3);
+ tt_str_op(end, OP_EQ, "/publish");
+ version = parse_hs_version_from_post("/tor/hs/42/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, 42);
+ tt_str_op(end, OP_EQ, "/publish");
+ version = parse_hs_version_from_post("/tor/hs/18163/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, 18163);
+ tt_str_op(end, OP_EQ, "/publish");
+ version = parse_hs_version_from_post("JUNKJUNKJUNK", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/3/publish", "blah", &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ /* Missing the '/' at the end of the prefix. */
+ version = parse_hs_version_from_post("/tor/hs/3/publish", "/tor/hs", &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/random/blah/tor/hs/3/publish",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/3/publish/random/junk",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, 3);
+ tt_str_op(end, OP_EQ, "/publish/random/junk");
+ version = parse_hs_version_from_post("/tor/hs/-1/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ /* INT_MAX */
+ version = parse_hs_version_from_post("/tor/hs/2147483647/publish",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, INT_MAX);
+ tt_str_op(end, OP_EQ, "/publish");
+ /* INT_MAX + 1*/
+ version = parse_hs_version_from_post("/tor/hs/2147483648/publish",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ }
+
+ done:
+ ;
+ }
+
#define DIR_LEGACY(name) \
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
@@@ -5773,11 -5439,8 +5834,12 @@@ struct testcase_t dir_tests[] =
DIR(fmt_control_ns, 0),
DIR(dirserv_set_routerstatus_testing, 0),
DIR(http_handling, 0),
+ DIR(purpose_needs_anonymity_returns_true_for_bridges, 0),
+ DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0),
+ DIR(purpose_needs_anonymity_returns_true_by_default, 0),
+ DIR(purpose_needs_anonymity_returns_true_for_sensitive_purpose, 0),
+ DIR(purpose_needs_anonymity_ret_false_for_non_sensitive_conn, 0),
+ DIR(post_parsing, 0),
- DIR(purpose_needs_anonymity, 0),
DIR(fetch_type, 0),
DIR(packages, 0),
DIR(download_status_schedule, 0),
diff --cc src/test/test_hs.c
index fd5ab15,3bf4e6d..67ce1cf
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@@ -14,8 -13,8 +14,9 @@@
#include "test.h"
#include "control.h"
#include "config.h"
+ #include "hs_common.h"
#include "rendcommon.h"
+#include "rendservice.h"
#include "routerset.h"
#include "circuitbuild.h"
#include "test_helpers.h"
diff --cc src/test/test_rendcache.c
index a5d3f35,afcd117..7f72e44
--- a/src/test/test_rendcache.c
+++ b/src/test/test_rendcache.c
@@@ -10,9 -10,9 +10,10 @@@
#include "router.h"
#include "routerlist.h"
#include "config.h"
+ #include "hs_common.h"
#include <openssl/rsa.h>
#include "rend_test_helpers.h"
+#include "log_test_helpers.h"
#define NS_MODULE rend_cache
diff --cc src/trunnel/ed25519_cert.c
index a492ada,dc1485d..dd5088b
--- a/src/trunnel/ed25519_cert.c
+++ b/src/trunnel/ed25519_cert.c
@@@ -430,6 -410,557 +430,597 @@@ ed25519_cert_extension_parse(ed25519_ce
}
return result;
}
+ link_specifier_t *
+ link_specifier_new(void)
+ {
+ link_specifier_t *val = trunnel_calloc(1, sizeof(link_specifier_t));
+ if (NULL == val)
+ return NULL;
+ return val;
+ }
+
+ /** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+ static void
+ link_specifier_clear(link_specifier_t *obj)
+ {
+ (void) obj;
+ TRUNNEL_DYNARRAY_WIPE(&obj->un_unrecognized);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->un_unrecognized);
+ }
+
+ void
+ link_specifier_free(link_specifier_t *obj)
+ {
+ if (obj == NULL)
+ return;
+ link_specifier_clear(obj);
+ trunnel_memwipe(obj, sizeof(link_specifier_t));
+ trunnel_free_(obj);
+ }
+
+ uint8_t
+ link_specifier_get_ls_type(link_specifier_t *inp)
+ {
+ return inp->ls_type;
+ }
+ int
+ link_specifier_set_ls_type(link_specifier_t *inp, uint8_t val)
+ {
+ inp->ls_type = val;
+ return 0;
+ }
+ uint8_t
+ link_specifier_get_ls_len(link_specifier_t *inp)
+ {
+ return inp->ls_len;
+ }
+ int
+ link_specifier_set_ls_len(link_specifier_t *inp, uint8_t val)
+ {
+ inp->ls_len = val;
+ return 0;
+ }
+ uint32_t
+ link_specifier_get_un_ipv4_addr(link_specifier_t *inp)
+ {
+ return inp->un_ipv4_addr;
+ }
+ int
+ link_specifier_set_un_ipv4_addr(link_specifier_t *inp, uint32_t val)
+ {
+ inp->un_ipv4_addr = val;
+ return 0;
+ }
+ uint16_t
+ link_specifier_get_un_ipv4_port(link_specifier_t *inp)
+ {
+ return inp->un_ipv4_port;
+ }
+ int
+ link_specifier_set_un_ipv4_port(link_specifier_t *inp, uint16_t val)
+ {
+ inp->un_ipv4_port = val;
+ return 0;
+ }
+ size_t
+ link_specifier_getlen_un_ipv6_addr(const link_specifier_t *inp)
+ {
+ (void)inp; return 16;
+ }
+
+ uint8_t
-link_specifier_get_un_ipv6_addr(const link_specifier_t *inp, size_t idx)
++link_specifier_get_un_ipv6_addr(link_specifier_t *inp, size_t idx)
+ {
+ trunnel_assert(idx < 16);
+ return inp->un_ipv6_addr[idx];
+ }
+
++uint8_t
++link_specifier_getconst_un_ipv6_addr(const link_specifier_t *inp, size_t idx)
++{
++ return link_specifier_get_un_ipv6_addr((link_specifier_t*)inp, idx);
++}
+ int
+ link_specifier_set_un_ipv6_addr(link_specifier_t *inp, size_t idx, uint8_t elt)
+ {
+ trunnel_assert(idx < 16);
+ inp->un_ipv6_addr[idx] = elt;
+ return 0;
+ }
+
+ uint8_t *
+ link_specifier_getarray_un_ipv6_addr(link_specifier_t *inp)
+ {
+ return inp->un_ipv6_addr;
+ }
++const uint8_t *
++link_specifier_getconstarray_un_ipv6_addr(const link_specifier_t *inp)
++{
++ return (const uint8_t *)link_specifier_getarray_un_ipv6_addr((link_specifier_t*)inp);
++}
+ uint16_t
+ link_specifier_get_un_ipv6_port(link_specifier_t *inp)
+ {
+ return inp->un_ipv6_port;
+ }
+ int
+ link_specifier_set_un_ipv6_port(link_specifier_t *inp, uint16_t val)
+ {
+ inp->un_ipv6_port = val;
+ return 0;
+ }
+ size_t
+ link_specifier_getlen_un_legacy_id(const link_specifier_t *inp)
+ {
+ (void)inp; return 20;
+ }
+
+ uint8_t
-link_specifier_get_un_legacy_id(const link_specifier_t *inp, size_t idx)
++link_specifier_get_un_legacy_id(link_specifier_t *inp, size_t idx)
+ {
+ trunnel_assert(idx < 20);
+ return inp->un_legacy_id[idx];
+ }
+
++uint8_t
++link_specifier_getconst_un_legacy_id(const link_specifier_t *inp, size_t idx)
++{
++ return link_specifier_get_un_legacy_id((link_specifier_t*)inp, idx);
++}
+ int
+ link_specifier_set_un_legacy_id(link_specifier_t *inp, size_t idx, uint8_t elt)
+ {
+ trunnel_assert(idx < 20);
+ inp->un_legacy_id[idx] = elt;
+ return 0;
+ }
+
+ uint8_t *
+ link_specifier_getarray_un_legacy_id(link_specifier_t *inp)
+ {
+ return inp->un_legacy_id;
+ }
++const uint8_t *
++link_specifier_getconstarray_un_legacy_id(const link_specifier_t *inp)
++{
++ return (const uint8_t *)link_specifier_getarray_un_legacy_id((link_specifier_t*)inp);
++}
+ size_t
+ link_specifier_getlen_un_ed25519_id(const link_specifier_t *inp)
+ {
+ (void)inp; return 32;
+ }
+
+ uint8_t
-link_specifier_get_un_ed25519_id(const link_specifier_t *inp, size_t idx)
++link_specifier_get_un_ed25519_id(link_specifier_t *inp, size_t idx)
+ {
+ trunnel_assert(idx < 32);
+ return inp->un_ed25519_id[idx];
+ }
+
++uint8_t
++link_specifier_getconst_un_ed25519_id(const link_specifier_t *inp, size_t idx)
++{
++ return link_specifier_get_un_ed25519_id((link_specifier_t*)inp, idx);
++}
+ int
+ link_specifier_set_un_ed25519_id(link_specifier_t *inp, size_t idx, uint8_t elt)
+ {
+ trunnel_assert(idx < 32);
+ inp->un_ed25519_id[idx] = elt;
+ return 0;
+ }
+
+ uint8_t *
+ link_specifier_getarray_un_ed25519_id(link_specifier_t *inp)
+ {
+ return inp->un_ed25519_id;
+ }
++const uint8_t *
++link_specifier_getconstarray_un_ed25519_id(const link_specifier_t *inp)
++{
++ return (const uint8_t *)link_specifier_getarray_un_ed25519_id((link_specifier_t*)inp);
++}
+ size_t
+ link_specifier_getlen_un_unrecognized(const link_specifier_t *inp)
+ {
+ return TRUNNEL_DYNARRAY_LEN(&inp->un_unrecognized);
+ }
+
+ uint8_t
+ link_specifier_get_un_unrecognized(link_specifier_t *inp, size_t idx)
+ {
+ return TRUNNEL_DYNARRAY_GET(&inp->un_unrecognized, idx);
+ }
+
++uint8_t
++link_specifier_getconst_un_unrecognized(const link_specifier_t *inp, size_t idx)
++{
++ return link_specifier_get_un_unrecognized((link_specifier_t*)inp, idx);
++}
+ int
+ link_specifier_set_un_unrecognized(link_specifier_t *inp, size_t idx, uint8_t elt)
+ {
+ TRUNNEL_DYNARRAY_SET(&inp->un_unrecognized, idx, elt);
+ return 0;
+ }
+ int
+ link_specifier_add_un_unrecognized(link_specifier_t *inp, uint8_t elt)
+ {
+ TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unrecognized, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+
+ uint8_t *
+ link_specifier_getarray_un_unrecognized(link_specifier_t *inp)
+ {
+ return inp->un_unrecognized.elts_;
+ }
++const uint8_t *
++link_specifier_getconstarray_un_unrecognized(const link_specifier_t *inp)
++{
++ return (const uint8_t *)link_specifier_getarray_un_unrecognized((link_specifier_t*)inp);
++}
+ int
+ link_specifier_setlen_un_unrecognized(link_specifier_t *inp, size_t newlen)
+ {
+ uint8_t *newptr;
+ newptr = trunnel_dynarray_setlen(&inp->un_unrecognized.allocated_,
+ &inp->un_unrecognized.n_, inp->un_unrecognized.elts_, newlen,
+ sizeof(inp->un_unrecognized.elts_[0]), (trunnel_free_fn_t) NULL,
+ &inp->trunnel_error_code_);
- if (newptr == NULL)
++ if (newlen != 0 && newptr == NULL)
+ goto trunnel_alloc_failed;
+ inp->un_unrecognized.elts_ = newptr;
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ const char *
+ link_specifier_check(const link_specifier_t *obj)
+ {
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ switch (obj->ls_type) {
+
+ case LS_IPV4:
+ break;
+
+ case LS_IPV6:
+ break;
+
+ case LS_LEGACY_ID:
+ break;
+
+ case LS_ED25519_ID:
+ break;
+
+ default:
+ break;
+ }
+ return NULL;
+ }
+
+ ssize_t
+ link_specifier_encoded_len(const link_specifier_t *obj)
+ {
+ ssize_t result = 0;
+
+ if (NULL != link_specifier_check(obj))
+ return -1;
+
+
+ /* Length of u8 ls_type */
+ result += 1;
+
+ /* Length of u8 ls_len */
+ result += 1;
+ switch (obj->ls_type) {
+
+ case LS_IPV4:
+
+ /* Length of u32 un_ipv4_addr */
+ result += 4;
+
+ /* Length of u16 un_ipv4_port */
+ result += 2;
+ break;
+
+ case LS_IPV6:
+
+ /* Length of u8 un_ipv6_addr[16] */
+ result += 16;
+
+ /* Length of u16 un_ipv6_port */
+ result += 2;
+ break;
+
+ case LS_LEGACY_ID:
+
+ /* Length of u8 un_legacy_id[20] */
+ result += 20;
+ break;
+
+ case LS_ED25519_ID:
+
+ /* Length of u8 un_ed25519_id[32] */
+ result += 32;
+ break;
+
+ default:
+
+ /* Length of u8 un_unrecognized[] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
+ break;
+ }
+ return result;
+ }
+ int
+ link_specifier_clear_errors(link_specifier_t *obj)
+ {
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+ }
+ ssize_t
+ link_specifier_encode(uint8_t *output, const size_t avail, const link_specifier_t *obj)
+ {
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+ #ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = link_specifier_encoded_len(obj);
+ #endif
+
+ uint8_t *backptr_ls_len = NULL;
+
+ if (NULL != (msg = link_specifier_check(obj)))
+ goto check_failed;
+
+ #ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+ #endif
+
+ /* Encode u8 ls_type */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->ls_type));
+ written += 1; ptr += 1;
+
+ /* Encode u8 ls_len */
+ backptr_ls_len = ptr;
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->ls_len));
+ written += 1; ptr += 1;
+ {
+ size_t written_before_union = written;
+
+ /* Encode union un[ls_type] */
+ trunnel_assert(written <= avail);
+ switch (obj->ls_type) {
+
+ case LS_IPV4:
+
+ /* Encode u32 un_ipv4_addr */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->un_ipv4_addr));
+ written += 4; ptr += 4;
+
+ /* Encode u16 un_ipv4_port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv4_port));
+ written += 2; ptr += 2;
+ break;
+
+ case LS_IPV6:
+
+ /* Encode u8 un_ipv6_addr[16] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 16)
+ goto truncated;
+ memcpy(ptr, obj->un_ipv6_addr, 16);
+ written += 16; ptr += 16;
+
+ /* Encode u16 un_ipv6_port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv6_port));
+ written += 2; ptr += 2;
+ break;
+
+ case LS_LEGACY_ID:
+
+ /* Encode u8 un_legacy_id[20] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 20)
+ goto truncated;
+ memcpy(ptr, obj->un_legacy_id, 20);
+ written += 20; ptr += 20;
+ break;
+
+ case LS_ED25519_ID:
+
+ /* Encode u8 un_ed25519_id[32] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 32)
+ goto truncated;
+ memcpy(ptr, obj->un_ed25519_id, 32);
+ written += 32; ptr += 32;
+ break;
+
+ default:
+
+ /* Encode u8 un_unrecognized[] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ if (elt_len)
+ memcpy(ptr, obj->un_unrecognized.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+ break;
+ }
+ /* Write the length field back to ls_len */
+ trunnel_assert(written >= written_before_union);
+ #if UINT8_MAX < SIZE_MAX
+ if (written - written_before_union > UINT8_MAX)
+ goto check_failed;
+ #endif
+ trunnel_set_uint8(backptr_ls_len, (written - written_before_union));
+ }
+
+
+ trunnel_assert(ptr == output + written);
+ #ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+ #endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+ }
+
+ /** As link_specifier_parse(), but do not allocate the output object.
+ */
+ static ssize_t
+ link_specifier_parse_into(link_specifier_t *obj, const uint8_t *input, const size_t len_in)
+ {
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 ls_type */
+ CHECK_REMAINING(1, truncated);
+ obj->ls_type = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse u8 ls_len */
+ CHECK_REMAINING(1, truncated);
+ obj->ls_len = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+ {
+ size_t remaining_after;
+ CHECK_REMAINING(obj->ls_len, truncated);
+ remaining_after = remaining - obj->ls_len;
+ remaining = obj->ls_len;
+
+ /* Parse union un[ls_type] */
+ switch (obj->ls_type) {
+
+ case LS_IPV4:
+
+ /* Parse u32 un_ipv4_addr */
+ CHECK_REMAINING(4, fail);
+ obj->un_ipv4_addr = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+
+ /* Parse u16 un_ipv4_port */
+ CHECK_REMAINING(2, fail);
+ obj->un_ipv4_port = trunnel_ntohs(trunnel_get_uint16(ptr));
+ remaining -= 2; ptr += 2;
+ break;
+
+ case LS_IPV6:
+
+ /* Parse u8 un_ipv6_addr[16] */
+ CHECK_REMAINING(16, fail);
+ memcpy(obj->un_ipv6_addr, ptr, 16);
+ remaining -= 16; ptr += 16;
+
+ /* Parse u16 un_ipv6_port */
+ CHECK_REMAINING(2, fail);
+ obj->un_ipv6_port = trunnel_ntohs(trunnel_get_uint16(ptr));
+ remaining -= 2; ptr += 2;
+ break;
+
+ case LS_LEGACY_ID:
+
+ /* Parse u8 un_legacy_id[20] */
+ CHECK_REMAINING(20, fail);
+ memcpy(obj->un_legacy_id, ptr, 20);
+ remaining -= 20; ptr += 20;
+ break;
+
+ case LS_ED25519_ID:
+
+ /* Parse u8 un_ed25519_id[32] */
+ CHECK_REMAINING(32, fail);
+ memcpy(obj->un_ed25519_id, ptr, 32);
+ remaining -= 32; ptr += 32;
+ break;
+
+ default:
+
+ /* Parse u8 un_unrecognized[] */
+ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unrecognized, remaining, {});
+ obj->un_unrecognized.n_ = remaining;
+ if (remaining)
+ memcpy(obj->un_unrecognized.elts_, ptr, remaining);
+ ptr += remaining; remaining -= remaining;
+ break;
+ }
+ if (remaining != 0)
+ goto fail;
+ remaining = remaining_after;
+ }
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ trunnel_alloc_failed:
+ return -1;
+ fail:
+ result = -1;
+ return result;
+ }
+
+ ssize_t
+ link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in)
+ {
+ ssize_t result;
+ *output = link_specifier_new();
+ if (NULL == *output)
+ return -1;
+ result = link_specifier_parse_into(*output, input, len_in);
+ if (result < 0) {
+ link_specifier_free(*output);
+ *output = NULL;
+ }
+ return result;
+ }
ed25519_cert_t *
ed25519_cert_new(void)
{
@@@ -937,3 -1438,283 +1528,293 @@@ ed25519_cert_parse(ed25519_cert_t **out
}
return result;
}
+ link_specifier_list_t *
+ link_specifier_list_new(void)
+ {
+ link_specifier_list_t *val = trunnel_calloc(1, sizeof(link_specifier_list_t));
+ if (NULL == val)
+ return NULL;
+ return val;
+ }
+
+ /** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+ static void
+ link_specifier_list_clear(link_specifier_list_t *obj)
+ {
+ (void) obj;
+ {
+
+ unsigned idx;
+ for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
+ link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
+ }
+ }
+ TRUNNEL_DYNARRAY_WIPE(&obj->spec);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->spec);
+ }
+
+ void
+ link_specifier_list_free(link_specifier_list_t *obj)
+ {
+ if (obj == NULL)
+ return;
+ link_specifier_list_clear(obj);
+ trunnel_memwipe(obj, sizeof(link_specifier_list_t));
+ trunnel_free_(obj);
+ }
+
+ uint8_t
+ link_specifier_list_get_n_spec(link_specifier_list_t *inp)
+ {
+ return inp->n_spec;
+ }
+ int
+ link_specifier_list_set_n_spec(link_specifier_list_t *inp, uint8_t val)
+ {
+ inp->n_spec = val;
+ return 0;
+ }
+ size_t
+ link_specifier_list_getlen_spec(const link_specifier_list_t *inp)
+ {
+ return TRUNNEL_DYNARRAY_LEN(&inp->spec);
+ }
+
+ struct link_specifier_st *
+ link_specifier_list_get_spec(link_specifier_list_t *inp, size_t idx)
+ {
+ return TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
+ }
+
++ const struct link_specifier_st *
++link_specifier_list_getconst_spec(const link_specifier_list_t *inp, size_t idx)
++{
++ return link_specifier_list_get_spec((link_specifier_list_t*)inp, idx);
++}
+ int
+ link_specifier_list_set_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
+ {
+ link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
+ if (oldval && oldval != elt)
+ link_specifier_free(oldval);
+ return link_specifier_list_set0_spec(inp, idx, elt);
+ }
+ int
+ link_specifier_list_set0_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
+ {
+ TRUNNEL_DYNARRAY_SET(&inp->spec, idx, elt);
+ return 0;
+ }
+ int
+ link_specifier_list_add_spec(link_specifier_list_t *inp, struct link_specifier_st * elt)
+ {
+ #if SIZE_MAX >= UINT8_MAX
+ if (inp->spec.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+ #endif
+ TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->spec, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+
+ struct link_specifier_st * *
+ link_specifier_list_getarray_spec(link_specifier_list_t *inp)
+ {
+ return inp->spec.elts_;
+ }
++const struct link_specifier_st * const *
++link_specifier_list_getconstarray_spec(const link_specifier_list_t *inp)
++{
++ return (const struct link_specifier_st * const *)link_specifier_list_getarray_spec((link_specifier_list_t*)inp);
++}
+ int
+ link_specifier_list_setlen_spec(link_specifier_list_t *inp, size_t newlen)
+ {
+ struct link_specifier_st * *newptr;
+ #if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+ #endif
+ newptr = trunnel_dynarray_setlen(&inp->spec.allocated_,
+ &inp->spec.n_, inp->spec.elts_, newlen,
+ sizeof(inp->spec.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
+ &inp->trunnel_error_code_);
- if (newptr == NULL)
++ if (newlen != 0 && newptr == NULL)
+ goto trunnel_alloc_failed;
+ inp->spec.elts_ = newptr;
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ const char *
+ link_specifier_list_check(const link_specifier_list_t *obj)
+ {
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ {
+ const char *msg;
+
+ unsigned idx;
+ for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
+ if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->spec, idx))))
+ return msg;
+ }
+ }
+ if (TRUNNEL_DYNARRAY_LEN(&obj->spec) != obj->n_spec)
+ return "Length mismatch for spec";
+ return NULL;
+ }
+
+ ssize_t
+ link_specifier_list_encoded_len(const link_specifier_list_t *obj)
+ {
+ ssize_t result = 0;
+
+ if (NULL != link_specifier_list_check(obj))
+ return -1;
+
+
+ /* Length of u8 n_spec */
+ result += 1;
+
+ /* Length of struct link_specifier spec[n_spec] */
+ {
+
+ unsigned idx;
+ for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
+ result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
+ }
+ }
+ return result;
+ }
+ int
+ link_specifier_list_clear_errors(link_specifier_list_t *obj)
+ {
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+ }
+ ssize_t
+ link_specifier_list_encode(uint8_t *output, const size_t avail, const link_specifier_list_t *obj)
+ {
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+ #ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = link_specifier_list_encoded_len(obj);
+ #endif
+
+ if (NULL != (msg = link_specifier_list_check(obj)))
+ goto check_failed;
+
+ #ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+ #endif
+
+ /* Encode u8 n_spec */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->n_spec));
+ written += 1; ptr += 1;
+
+ /* Encode struct link_specifier spec[n_spec] */
+ {
+
+ unsigned idx;
+ for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
+ trunnel_assert(written <= avail);
+ result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
+ if (result < 0)
+ goto fail; /* XXXXXXX !*/
+ written += result; ptr += result;
+ }
+ }
+
+
+ trunnel_assert(ptr == output + written);
+ #ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+ #endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+ }
+
+ /** As link_specifier_list_parse(), but do not allocate the output
+ * object.
+ */
+ static ssize_t
+ link_specifier_list_parse_into(link_specifier_list_t *obj, const uint8_t *input, const size_t len_in)
+ {
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 n_spec */
+ CHECK_REMAINING(1, truncated);
+ obj->n_spec = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse struct link_specifier spec[n_spec] */
+ TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->spec, obj->n_spec, {});
+ {
+ link_specifier_t * elt;
+ unsigned idx;
+ for (idx = 0; idx < obj->n_spec; ++idx) {
+ result = link_specifier_parse(&elt, ptr, remaining);
+ if (result < 0)
+ goto relay_fail;
+ trunnel_assert((size_t)result <= remaining);
+ remaining -= result; ptr += result;
+ TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->spec, elt, {link_specifier_free(elt);});
+ }
+ }
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ relay_fail:
+ trunnel_assert(result < 0);
+ return result;
+ trunnel_alloc_failed:
+ return -1;
+ }
+
+ ssize_t
+ link_specifier_list_parse(link_specifier_list_t **output, const uint8_t *input, const size_t len_in)
+ {
+ ssize_t result;
+ *output = link_specifier_list_new();
+ if (NULL == *output)
+ return -1;
+ result = link_specifier_list_parse_into(*output, input, len_in);
+ if (result < 0) {
+ link_specifier_list_free(*output);
+ *output = NULL;
+ }
+ return result;
+ }
diff --cc src/trunnel/ed25519_cert.h
index 9804d84,1893957..571e6d1
--- a/src/trunnel/ed25519_cert.h
+++ b/src/trunnel/ed25519_cert.h
@@@ -157,6 -168,164 +184,196 @@@ const uint8_t * ed25519_cert_extension
* success; return -1 and set the error code on 'inp' on failure.
*/
int ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen);
+ /** Return a newly allocated link_specifier with all elements set to
+ * zero.
+ */
+ link_specifier_t *link_specifier_new(void);
+ /** Release all storage held by the link_specifier in 'victim'. (Do
+ * nothing if 'victim' is NULL.)
+ */
+ void link_specifier_free(link_specifier_t *victim);
+ /** Try to parse a link_specifier from the buffer in 'input', using up
+ * to 'len_in' bytes from the input buffer. On success, return the
+ * number of bytes consumed and set *output to the newly allocated
+ * link_specifier_t. On failure, return -2 if the input appears
+ * truncated, and -1 if the input is otherwise invalid.
+ */
+ ssize_t link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in);
+ /** Return the number of bytes we expect to need to encode the
+ * link_specifier in 'obj'. On failure, return a negative value. Note
+ * that this value may be an overestimate, and can even be an
+ * underestimate for certain unencodeable objects.
+ */
+ ssize_t link_specifier_encoded_len(const link_specifier_t *obj);
+ /** Try to encode the link_specifier from 'input' into the buffer at
+ * 'output', using up to 'avail' bytes of the output buffer. On
+ * success, return the number of bytes used. On failure, return -2 if
+ * the buffer was not long enough, and -1 if the input was invalid.
+ */
+ ssize_t link_specifier_encode(uint8_t *output, size_t avail, const link_specifier_t *input);
+ /** Check whether the internal state of the link_specifier in 'obj' is
+ * consistent. Return NULL if it is, and a short message if it is not.
+ */
+ const char *link_specifier_check(const link_specifier_t *obj);
+ /** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+ int link_specifier_clear_errors(link_specifier_t *obj);
+ /** Return the value of the ls_type field of the link_specifier_t in
+ * 'inp'
+ */
+ uint8_t link_specifier_get_ls_type(link_specifier_t *inp);
+ /** Set the value of the ls_type field of the link_specifier_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+ int link_specifier_set_ls_type(link_specifier_t *inp, uint8_t val);
+ /** Return the value of the ls_len field of the link_specifier_t in
+ * 'inp'
+ */
+ uint8_t link_specifier_get_ls_len(link_specifier_t *inp);
+ /** Set the value of the ls_len field of the link_specifier_t in 'inp'
+ * to 'val'. Return 0 on success; return -1 and set the error code on
+ * 'inp' on failure.
+ */
+ int link_specifier_set_ls_len(link_specifier_t *inp, uint8_t val);
+ /** Return the value of the un_ipv4_addr field of the link_specifier_t
+ * in 'inp'
+ */
+ uint32_t link_specifier_get_un_ipv4_addr(link_specifier_t *inp);
+ /** Set the value of the un_ipv4_addr field of the link_specifier_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+ int link_specifier_set_un_ipv4_addr(link_specifier_t *inp, uint32_t val);
+ /** Return the value of the un_ipv4_port field of the link_specifier_t
+ * in 'inp'
+ */
+ uint16_t link_specifier_get_un_ipv4_port(link_specifier_t *inp);
+ /** Set the value of the un_ipv4_port field of the link_specifier_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+ int link_specifier_set_un_ipv4_port(link_specifier_t *inp, uint16_t val);
+ /** Return the (constant) length of the array holding the un_ipv6_addr
+ * field of the link_specifier_t in 'inp'.
+ */
+ size_t link_specifier_getlen_un_ipv6_addr(const link_specifier_t *inp);
+ /** Return the element at position 'idx' of the fixed array field
+ * un_ipv6_addr of the link_specifier_t in 'inp'.
+ */
-uint8_t link_specifier_get_un_ipv6_addr(const link_specifier_t *inp, size_t idx);
++uint8_t link_specifier_get_un_ipv6_addr(link_specifier_t *inp, size_t idx);
++/** As link_specifier_get_un_ipv6_addr, but take and return a const
++ * pointer
++ */
++uint8_t link_specifier_getconst_un_ipv6_addr(const link_specifier_t *inp, size_t idx);
+ /** Change the element at position 'idx' of the fixed array field
+ * un_ipv6_addr of the link_specifier_t in 'inp', so that it will hold
+ * the value 'elt'.
+ */
+ int link_specifier_set_un_ipv6_addr(link_specifier_t *inp, size_t idx, uint8_t elt);
+ /** Return a pointer to the 16-element array field un_ipv6_addr of
+ * 'inp'.
+ */
+ uint8_t * link_specifier_getarray_un_ipv6_addr(link_specifier_t *inp);
++/** As link_specifier_get_un_ipv6_addr, but take and return a const
++ * pointer
++ */
++const uint8_t * link_specifier_getconstarray_un_ipv6_addr(const link_specifier_t *inp);
+ /** Return the value of the un_ipv6_port field of the link_specifier_t
+ * in 'inp'
+ */
+ uint16_t link_specifier_get_un_ipv6_port(link_specifier_t *inp);
+ /** Set the value of the un_ipv6_port field of the link_specifier_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+ int link_specifier_set_un_ipv6_port(link_specifier_t *inp, uint16_t val);
+ /** Return the (constant) length of the array holding the un_legacy_id
+ * field of the link_specifier_t in 'inp'.
+ */
+ size_t link_specifier_getlen_un_legacy_id(const link_specifier_t *inp);
+ /** Return the element at position 'idx' of the fixed array field
+ * un_legacy_id of the link_specifier_t in 'inp'.
+ */
-uint8_t link_specifier_get_un_legacy_id(const link_specifier_t *inp, size_t idx);
++uint8_t link_specifier_get_un_legacy_id(link_specifier_t *inp, size_t idx);
++/** As link_specifier_get_un_legacy_id, but take and return a const
++ * pointer
++ */
++uint8_t link_specifier_getconst_un_legacy_id(const link_specifier_t *inp, size_t idx);
+ /** Change the element at position 'idx' of the fixed array field
+ * un_legacy_id of the link_specifier_t in 'inp', so that it will hold
+ * the value 'elt'.
+ */
+ int link_specifier_set_un_legacy_id(link_specifier_t *inp, size_t idx, uint8_t elt);
+ /** Return a pointer to the 20-element array field un_legacy_id of
+ * 'inp'.
+ */
+ uint8_t * link_specifier_getarray_un_legacy_id(link_specifier_t *inp);
++/** As link_specifier_get_un_legacy_id, but take and return a const
++ * pointer
++ */
++const uint8_t * link_specifier_getconstarray_un_legacy_id(const link_specifier_t *inp);
+ /** Return the (constant) length of the array holding the
+ * un_ed25519_id field of the link_specifier_t in 'inp'.
+ */
+ size_t link_specifier_getlen_un_ed25519_id(const link_specifier_t *inp);
+ /** Return the element at position 'idx' of the fixed array field
+ * un_ed25519_id of the link_specifier_t in 'inp'.
+ */
-uint8_t link_specifier_get_un_ed25519_id(const link_specifier_t *inp, size_t idx);
++uint8_t link_specifier_get_un_ed25519_id(link_specifier_t *inp, size_t idx);
++/** As link_specifier_get_un_ed25519_id, but take and return a const
++ * pointer
++ */
++uint8_t link_specifier_getconst_un_ed25519_id(const link_specifier_t *inp, size_t idx);
+ /** Change the element at position 'idx' of the fixed array field
+ * un_ed25519_id of the link_specifier_t in 'inp', so that it will
+ * hold the value 'elt'.
+ */
+ int link_specifier_set_un_ed25519_id(link_specifier_t *inp, size_t idx, uint8_t elt);
+ /** Return a pointer to the 32-element array field un_ed25519_id of
+ * 'inp'.
+ */
+ uint8_t * link_specifier_getarray_un_ed25519_id(link_specifier_t *inp);
++/** As link_specifier_get_un_ed25519_id, but take and return a const
++ * pointer
++ */
++const uint8_t * link_specifier_getconstarray_un_ed25519_id(const link_specifier_t *inp);
+ /** Return the length of the dynamic array holding the un_unrecognized
+ * field of the link_specifier_t in 'inp'.
+ */
+ size_t link_specifier_getlen_un_unrecognized(const link_specifier_t *inp);
+ /** Return the element at position 'idx' of the dynamic array field
+ * un_unrecognized of the link_specifier_t in 'inp'.
+ */
+ uint8_t link_specifier_get_un_unrecognized(link_specifier_t *inp, size_t idx);
++/** As link_specifier_get_un_unrecognized, but take and return a const
++ * pointer
++ */
++uint8_t link_specifier_getconst_un_unrecognized(const link_specifier_t *inp, size_t idx);
+ /** Change the element at position 'idx' of the dynamic array field
+ * un_unrecognized of the link_specifier_t in 'inp', so that it will
+ * hold the value 'elt'.
+ */
+ int link_specifier_set_un_unrecognized(link_specifier_t *inp, size_t idx, uint8_t elt);
+ /** Append a new element 'elt' to the dynamic array field
+ * un_unrecognized of the link_specifier_t in 'inp'.
+ */
+ int link_specifier_add_un_unrecognized(link_specifier_t *inp, uint8_t elt);
+ /** Return a pointer to the variable-length array field
+ * un_unrecognized of 'inp'.
+ */
+ uint8_t * link_specifier_getarray_un_unrecognized(link_specifier_t *inp);
++/** As link_specifier_get_un_unrecognized, but take and return a const
++ * pointer
++ */
++const uint8_t * link_specifier_getconstarray_un_unrecognized(const link_specifier_t *inp);
+ /** Change the length of the variable-length array field
+ * un_unrecognized of 'inp' to 'newlen'.Fill extra elements with 0.
+ * Return 0 on success; return -1 and set the error code on 'inp' on
+ * failure.
+ */
+ int link_specifier_setlen_un_unrecognized(link_specifier_t *inp, size_t newlen);
/** Return a newly allocated ed25519_cert with all elements set to
* zero.
*/
@@@ -316,9 -468,81 +533,92 @@@ int ed25519_cert_set_signature(ed25519_
/** Return a pointer to the 64-element array field signature of 'inp'.
*/
uint8_t * ed25519_cert_getarray_signature(ed25519_cert_t *inp);
+/** As ed25519_cert_get_signature, but take and return a const pointer
+ */
+const uint8_t * ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp);
+ /** Return a newly allocated link_specifier_list with all elements set
+ * to zero.
+ */
+ link_specifier_list_t *link_specifier_list_new(void);
+ /** Release all storage held by the link_specifier_list in 'victim'.
+ * (Do nothing if 'victim' is NULL.)
+ */
+ void link_specifier_list_free(link_specifier_list_t *victim);
+ /** Try to parse a link_specifier_list from the buffer in 'input',
+ * using up to 'len_in' bytes from the input buffer. On success,
+ * return the number of bytes consumed and set *output to the newly
+ * allocated link_specifier_list_t. On failure, return -2 if the input
+ * appears truncated, and -1 if the input is otherwise invalid.
+ */
+ ssize_t link_specifier_list_parse(link_specifier_list_t **output, const uint8_t *input, const size_t len_in);
+ /** Return the number of bytes we expect to need to encode the
+ * link_specifier_list in 'obj'. On failure, return a negative value.
+ * Note that this value may be an overestimate, and can even be an
+ * underestimate for certain unencodeable objects.
+ */
+ ssize_t link_specifier_list_encoded_len(const link_specifier_list_t *obj);
+ /** Try to encode the link_specifier_list from 'input' into the buffer
+ * at 'output', using up to 'avail' bytes of the output buffer. On
+ * success, return the number of bytes used. On failure, return -2 if
+ * the buffer was not long enough, and -1 if the input was invalid.
+ */
+ ssize_t link_specifier_list_encode(uint8_t *output, size_t avail, const link_specifier_list_t *input);
+ /** Check whether the internal state of the link_specifier_list in
+ * 'obj' is consistent. Return NULL if it is, and a short message if
+ * it is not.
+ */
+ const char *link_specifier_list_check(const link_specifier_list_t *obj);
+ /** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+ int link_specifier_list_clear_errors(link_specifier_list_t *obj);
+ /** Return the value of the n_spec field of the link_specifier_list_t
+ * in 'inp'
+ */
+ uint8_t link_specifier_list_get_n_spec(link_specifier_list_t *inp);
+ /** Set the value of the n_spec field of the link_specifier_list_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+ int link_specifier_list_set_n_spec(link_specifier_list_t *inp, uint8_t val);
+ /** Return the length of the dynamic array holding the spec field of
+ * the link_specifier_list_t in 'inp'.
+ */
+ size_t link_specifier_list_getlen_spec(const link_specifier_list_t *inp);
+ /** Return the element at position 'idx' of the dynamic array field
+ * spec of the link_specifier_list_t in 'inp'.
+ */
+ struct link_specifier_st * link_specifier_list_get_spec(link_specifier_list_t *inp, size_t idx);
++/** As link_specifier_list_get_spec, but take and return a const
++ * pointer
++ */
++ const struct link_specifier_st * link_specifier_list_getconst_spec(const link_specifier_list_t *inp, size_t idx);
+ /** Change the element at position 'idx' of the dynamic array field
+ * spec of the link_specifier_list_t in 'inp', so that it will hold
+ * the value 'elt'. Free the previous value, if any.
+ */
+ int link_specifier_list_set_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt);
+ /** As link_specifier_list_set_spec, but does not free the previous
+ * value.
+ */
+ int link_specifier_list_set0_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt);
+ /** Append a new element 'elt' to the dynamic array field spec of the
+ * link_specifier_list_t in 'inp'.
+ */
+ int link_specifier_list_add_spec(link_specifier_list_t *inp, struct link_specifier_st * elt);
+ /** Return a pointer to the variable-length array field spec of 'inp'.
+ */
+ struct link_specifier_st * * link_specifier_list_getarray_spec(link_specifier_list_t *inp);
++/** As link_specifier_list_get_spec, but take and return a const
++ * pointer
++ */
++const struct link_specifier_st * const * link_specifier_list_getconstarray_spec(const link_specifier_list_t *inp);
+ /** Change the length of the variable-length array field spec of 'inp'
+ * to 'newlen'.Fill extra elements with NULL; free removed elements.
+ * Return 0 on success; return -1 and set the error code on 'inp' on
+ * failure.
+ */
+ int link_specifier_list_setlen_spec(link_specifier_list_t *inp, size_t newlen);
#endif
1
0

[tor/master] prop224: Rename cert type to follow naming convention
by nickm@torproject.org 04 Nov '16
by nickm@torproject.org 04 Nov '16
04 Nov '16
commit 1263f74a12abfb7f3e9b9627fd1d37cb125b8429
Author: David Goulet <dgoulet(a)torproject.org>
Date: Wed Sep 14 15:05:48 2016 -0400
prop224: Rename cert type to follow naming convention
Signed-off-by: David Goulet <dgoulet(a)torproject.org>
---
src/or/hs_descriptor.c | 10 +++++-----
src/or/torcert.h | 18 +++++++++---------
src/test/test_hs_cache.c | 4 ++--
src/test/test_hs_descriptor.c | 20 ++++++++++----------
4 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/src/or/hs_descriptor.c b/src/or/hs_descriptor.c
index a87a860..7868c05 100644
--- a/src/or/hs_descriptor.c
+++ b/src/or/hs_descriptor.c
@@ -314,7 +314,7 @@ encode_enc_key(const ed25519_keypair_t *sig_key,
&ip->enc_key.curve25519)) {
goto err;
}
- tor_cert_t *cross_cert = tor_cert_create(&curve_kp, CERT_TYPE_HS_IP_ENC,
+ tor_cert_t *cross_cert = tor_cert_create(&curve_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
&sig_key->pubkey, now,
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -748,7 +748,7 @@ desc_encode_v3(const hs_descriptor_t *desc, char **encoded_out)
char *encoded_cert;
/* Encode certificate then create the first line of the descriptor. */
if (desc->plaintext_data.signing_key_cert->cert_type
- != CERT_TYPE_HS_DESC_SIGN) {
+ != CERT_TYPE_SIGNING_HS_DESC) {
log_err(LD_BUG, "HS descriptor signing key has an unexpected cert type "
"(%d)", (int) desc->plaintext_data.signing_key_cert->cert_type);
goto err;
@@ -1237,7 +1237,7 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
/* Parse cert and do some validation. */
if (cert_parse_and_validate(&ip->auth_key_cert, tok->object_body,
- tok->object_size, CERT_TYPE_HS_IP_AUTH,
+ tok->object_size, CERT_TYPE_AUTH_HS_IP_KEY,
"introduction point auth-key") < 0) {
goto err;
}
@@ -1285,7 +1285,7 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
goto err;
}
if (cert_parse_and_validate(&cross_cert, tok->object_body,
- tok->object_size, CERT_TYPE_HS_IP_ENC,
+ tok->object_size, CERT_TYPE_CROSS_HS_IP_KEYS,
"introduction point enc-key-certification") < 0) {
goto err;
}
@@ -1509,7 +1509,7 @@ desc_decode_plaintext_v3(smartlist_t *tokens,
goto err;
}
if (cert_parse_and_validate(&desc->signing_key_cert, tok->object_body,
- tok->object_size, CERT_TYPE_HS_DESC_SIGN,
+ tok->object_size, CERT_TYPE_SIGNING_HS_DESC,
"service descriptor signing key") < 0) {
goto err;
}
diff --git a/src/or/torcert.h b/src/or/torcert.h
index 29bc0fc..b1e26a9 100644
--- a/src/or/torcert.h
+++ b/src/or/torcert.h
@@ -6,15 +6,15 @@
#include "crypto_ed25519.h"
-#define SIGNED_KEY_TYPE_ED25519 0x01
-
-#define CERT_TYPE_ID_SIGNING 0x04
-#define CERT_TYPE_SIGNING_LINK 0x05
-#define CERT_TYPE_SIGNING_AUTH 0x06
-#define CERT_TYPE_HS_DESC_SIGN 0x08
-#define CERT_TYPE_HS_IP_AUTH 0x09
-#define CERT_TYPE_ONION_ID 0x0A
-#define CERT_TYPE_HS_IP_ENC 0x0B
+#define SIGNED_KEY_TYPE_ED25519 0x01
+
+#define CERT_TYPE_ID_SIGNING 0x04
+#define CERT_TYPE_SIGNING_LINK 0x05
+#define CERT_TYPE_SIGNING_AUTH 0x06
+#define CERT_TYPE_SIGNING_HS_DESC 0x08
+#define CERT_TYPE_AUTH_HS_IP_KEY 0x09
+#define CERT_TYPE_ONION_ID 0x0A
+#define CERT_TYPE_CROSS_HS_IP_KEYS 0x0B
#define CERT_FLAG_INCLUDE_SIGNING_KEY 0x1
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index 33887ae..f3776ac 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -48,7 +48,7 @@ helper_build_intro_point(const ed25519_keypair_t *blinded_kp,
ret = ed25519_keypair_generate(&auth_kp, 0);
tt_int_op(ret, ==, 0);
- ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_HS_IP_AUTH,
+ ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_AUTH_HS_IP_KEY,
&auth_kp.pubkey, time(NULL),
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -83,7 +83,7 @@ helper_build_hs_desc(uint64_t revision_counter, uint32_t lifetime,
desc->plaintext_data.signing_key_cert =
tor_cert_create(&desc->plaintext_data.blinded_kp,
- CERT_TYPE_HS_DESC_SIGN,
+ CERT_TYPE_SIGNING_HS_DESC,
&desc->plaintext_data.signing_kp.pubkey, time(NULL),
3600, CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(desc->plaintext_data.signing_key_cert);
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 086d755..dec5268 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -51,7 +51,7 @@ helper_build_intro_point(const ed25519_keypair_t *blinded_kp, time_t now,
ret = ed25519_keypair_generate(&auth_kp, 0);
tt_int_op(ret, ==, 0);
- ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_HS_IP_AUTH,
+ ip->auth_key_cert = tor_cert_create(blinded_kp, CERT_TYPE_AUTH_HS_IP_KEY,
&auth_kp.pubkey, now,
HS_DESC_CERT_LIFETIME,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -91,7 +91,7 @@ helper_build_hs_desc(unsigned int no_ip)
desc->plaintext_data.signing_key_cert =
tor_cert_create(&desc->plaintext_data.blinded_kp,
- CERT_TYPE_HS_DESC_SIGN,
+ CERT_TYPE_SIGNING_HS_DESC,
&desc->plaintext_data.signing_kp.pubkey, now,
3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
@@ -1028,31 +1028,31 @@ test_validate_cert(void *arg)
ret = ed25519_keypair_generate(&kp, 0);
tt_int_op(ret, ==, 0);
- /* Cert of type CERT_TYPE_HS_IP_AUTH. */
- tor_cert_t *cert = tor_cert_create(&kp, CERT_TYPE_HS_IP_AUTH,
+ /* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */
+ tor_cert_t *cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
&kp.pubkey, now, 3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(cert);
/* Test with empty certificate. */
- ret = cert_is_valid(NULL, CERT_TYPE_HS_IP_AUTH, "unicorn");
+ ret = cert_is_valid(NULL, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
tt_int_op(ret, OP_EQ, 0);
/* Test with a bad type. */
- ret = cert_is_valid(cert, CERT_TYPE_HS_DESC_SIGN, "unicorn");
+ ret = cert_is_valid(cert, CERT_TYPE_SIGNING_HS_DESC, "unicorn");
tt_int_op(ret, OP_EQ, 0);
/* Normal validation. */
- ret = cert_is_valid(cert, CERT_TYPE_HS_IP_AUTH, "unicorn");
+ ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
tt_int_op(ret, OP_EQ, 1);
/* Break signing key so signature verification will fails. */
memset(&cert->signing_key, 0, sizeof(cert->signing_key));
- ret = cert_is_valid(cert, CERT_TYPE_HS_IP_AUTH, "unicorn");
+ ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
tt_int_op(ret, OP_EQ, 0);
tor_cert_free(cert);
/* Try a cert without including the signing key. */
- cert = tor_cert_create(&kp, CERT_TYPE_HS_IP_AUTH, &kp.pubkey, now, 3600, 0);
+ cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY, &kp.pubkey, now, 3600, 0);
tt_assert(cert);
/* Test with a bad type. */
- ret = cert_is_valid(cert, CERT_TYPE_HS_IP_AUTH, "unicorn");
+ ret = cert_is_valid(cert, CERT_TYPE_AUTH_HS_IP_KEY, "unicorn");
tt_int_op(ret, OP_EQ, 0);
done:
1
0
commit 791625750ef0c81b035b5c5c91ff9ab8a256df97
Author: David Goulet <dgoulet(a)torproject.org>
Date: Fri Nov 4 14:30:25 2016 -0400
prop224: Remove pointless unit test
Signed-off-by: David Goulet <dgoulet(a)torproject.org>
---
src/test/test_hs_descriptor.c | 28 ----------------------------
1 file changed, 28 deletions(-)
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index e406a80..47e7037 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -913,32 +913,6 @@ test_decode_multiple_intro_points(void *arg)
}
static void
-test_free_objects(void *arg)
-{
- (void) arg;
-
- {
- const char u[] = { 'U', 'U', 'U', 'U' };
- hs_desc_plaintext_data_t *data = tor_malloc_zero(sizeof(*data));
- /* Set a memory marker so we know if the data was properly wiped. */
- memset(&data->version, 'U', sizeof(data->version));
- hs_desc_plaintext_data_free(data);
- tt_mem_op(&data->version, OP_NE, u, sizeof(u));
- }
-
- {
- hs_desc_encrypted_data_t *data = tor_malloc_zero(sizeof(*data));
- /* Set a memory marker so we know if the data was properly wiped. */
- data->create2_ntor = 1;
- hs_desc_encrypted_data_free(data);
- tt_int_op(data->create2_ntor, OP_NE, 1);
- }
-
- done:
- ;
-}
-
-static void
test_decode_plaintext(void *arg)
{
int ret;
@@ -1133,8 +1107,6 @@ struct testcase_t hs_descriptor[] = {
/* Misc. */
{ "version", test_supported_version, TT_FORK,
NULL, NULL },
- { "free_objects", test_free_objects, TT_FORK,
- NULL, NULL },
{ "validate_cert", test_validate_cert, TT_FORK,
NULL, NULL },
{ "desc_signature", test_desc_signature, TT_FORK,
1
0

[tor/master] Fix memory leaks in hs_descriptor/decode_descriptor and in encode_enc_key()
by nickm@torproject.org 04 Nov '16
by nickm@torproject.org 04 Nov '16
04 Nov '16
commit d16b4b3e485526b39e7bdc36bf2d8041080a7201
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 14:27:45 2016 -0400
Fix memory leaks in hs_descriptor/decode_descriptor and in encode_enc_key()
---
src/or/hs_descriptor.c | 4 +++-
src/test/test_hs_descriptor.c | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/or/hs_descriptor.c b/src/or/hs_descriptor.c
index 668862f..92e523e 100644
--- a/src/or/hs_descriptor.c
+++ b/src/or/hs_descriptor.c
@@ -270,7 +270,7 @@ encode_enc_key(const ed25519_keypair_t *sig_key,
char *key_str, b64_cert[256];
ssize_t cert_len;
size_t key_str_len;
- uint8_t *cert_data;
+ uint8_t *cert_data = NULL;
/* Create cross certification cert. */
cert_len = tor_make_rsa_ed25519_crosscert(&sig_key->pubkey,
@@ -284,9 +284,11 @@ encode_enc_key(const ed25519_keypair_t *sig_key,
/* Encode cross cert. */
if (base64_encode(b64_cert, sizeof(b64_cert), (const char *) cert_data,
cert_len, BASE64_ENCODE_MULTILINE) < 0) {
+ tor_free(cert_data);
log_warn(LD_REND, "Unable to encode legacy crosscert.");
goto err;
}
+ tor_free(cert_data);
/* Convert the encryption key to a string. */
if (crypto_pk_write_public_key_to_string(ip->enc_key.legacy, &key_str,
&key_str_len) < 0) {
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 846732c..838d7cd 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -498,6 +498,7 @@ test_decode_descriptor(void *arg)
char *encoded = NULL;
hs_descriptor_t *desc = helper_build_hs_desc(0);
hs_descriptor_t *decoded = NULL;
+ hs_descriptor_t *desc_no_ip = NULL;
(void) arg;
@@ -517,7 +518,7 @@ test_decode_descriptor(void *arg)
/* Decode a descriptor with _no_ introduction points. */
{
- hs_descriptor_t *desc_no_ip = helper_build_hs_desc(1);
+ desc_no_ip = helper_build_hs_desc(1);
tt_assert(desc_no_ip);
tor_free(encoded);
ret = hs_desc_encode_descriptor(desc_no_ip, &encoded);
@@ -531,6 +532,7 @@ test_decode_descriptor(void *arg)
done:
hs_descriptor_free(desc);
+ hs_descriptor_free(desc_no_ip);
hs_descriptor_free(decoded);
tor_free(encoded);
}
1
0

[tor/master] Expose desc_intro_point_free to the tests, and use it.
by nickm@torproject.org 04 Nov '16
by nickm@torproject.org 04 Nov '16
04 Nov '16
commit a4291eef5aeeb9ba8939b563a657ac50d4447b7e
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 14:21:53 2016 -0400
Expose desc_intro_point_free to the tests, and use it.
Also fix another couple of leaks.
---
src/or/hs_descriptor.c | 2 +-
src/or/hs_descriptor.h | 2 +-
src/test/test_hs_descriptor.c | 12 +++++++++---
3 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/or/hs_descriptor.c b/src/or/hs_descriptor.c
index 946418e..668862f 100644
--- a/src/or/hs_descriptor.c
+++ b/src/or/hs_descriptor.c
@@ -77,7 +77,7 @@ static token_rule_t hs_desc_intro_point_v3_token_table[] = {
};
/* Free a descriptor intro point object. */
-static void
+STATIC void
desc_intro_point_free(hs_desc_intro_point_t *ip)
{
if (!ip) {
diff --git a/src/or/hs_descriptor.h b/src/or/hs_descriptor.h
index 0c30a52..8bc7256 100644
--- a/src/or/hs_descriptor.h
+++ b/src/or/hs_descriptor.h
@@ -232,7 +232,7 @@ STATIC int cert_is_valid(tor_cert_t *cert, uint8_t type,
STATIC int desc_sig_is_valid(const char *b64_sig,
const ed25519_keypair_t *signing_kp,
const char *encoded_desc, size_t encoded_len);
-
+STATIC void desc_intro_point_free(hs_desc_intro_point_t *ip);
#endif /* HS_DESCRIPTOR_PRIVATE */
#endif /* TOR_HS_DESCRIPTOR_H */
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 01e32cf..846732c 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -593,7 +593,7 @@ test_decode_intro_point(void *arg)
int ret;
char *encoded_ip = NULL;
size_t len_out;
- hs_desc_intro_point_t *ip;
+ hs_desc_intro_point_t *ip = NULL;
hs_descriptor_t *desc = NULL;
(void) arg;
@@ -673,6 +673,8 @@ test_decode_intro_point(void *arg)
const char *junk = "this is not a descriptor";
ip = decode_introduction_point(desc, junk);
tt_assert(!ip);
+ desc_intro_point_free(ip);
+ ip = NULL;
}
/* Invalid link specifiers. */
@@ -689,6 +691,8 @@ test_decode_intro_point(void *arg)
tt_assert(!ip);
tor_free(encoded_ip);
smartlist_free(lines);
+ desc_intro_point_free(ip);
+ ip = NULL;
}
/* Invalid auth key type. */
@@ -803,6 +807,7 @@ test_decode_intro_point(void *arg)
done:
hs_descriptor_free(desc);
+ desc_intro_point_free(ip);
}
const char encrypted_desc_portion[] = "create2-formats 2\n"
@@ -1027,6 +1032,7 @@ test_validate_cert(void *arg)
int ret;
time_t now = time(NULL);
ed25519_keypair_t kp;
+ tor_cert_t *cert = NULL;
(void) arg;
@@ -1034,7 +1040,7 @@ test_validate_cert(void *arg)
tt_int_op(ret, ==, 0);
/* Cert of type CERT_TYPE_AUTH_HS_IP_KEY. */
- tor_cert_t *cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
+ cert = tor_cert_create(&kp, CERT_TYPE_AUTH_HS_IP_KEY,
&kp.pubkey, now, 3600,
CERT_FLAG_INCLUDE_SIGNING_KEY);
tt_assert(cert);
@@ -1062,7 +1068,7 @@ test_validate_cert(void *arg)
tt_int_op(ret, OP_EQ, 0);
done:
- ;
+ tor_cert_free(cert);
}
static void
1
0

04 Nov '16
commit 1a03edefbaf2f89489df86519b837b5bf8c5f18f
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 14:28:19 2016 -0400
Fix a heap overrun in test_decode_plaintext
---
src/test/test_hs_descriptor.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 838d7cd..e406a80 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -987,6 +987,7 @@ test_decode_plaintext(void *arg)
tt_int_op(HS_DESC_MAX_LEN, <, big);
char *plaintext = tor_malloc_zero(big);
memset(plaintext, 'a', big);
+ plaintext[big - 1] = '\0';
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
tt_int_op(ret, OP_EQ, -1);
1
0

[tor/master] prop224: Use a const pointer for the cache lookup entry
by nickm@torproject.org 04 Nov '16
by nickm@torproject.org 04 Nov '16
04 Nov '16
commit 3f29688bdff3d6aa0b47ee7080995f44dbb579de
Author: David Goulet <dgoulet(a)torproject.org>
Date: Thu Sep 15 14:13:18 2016 -0400
prop224: Use a const pointer for the cache lookup entry
Signed-off-by: David Goulet <dgoulet(a)torproject.org>
---
src/or/directory.c | 4 +---
src/or/hs_cache.c | 16 ++++++++--------
src/or/hs_cache.h | 2 +-
src/test/test_hs_cache.c | 7 ++-----
4 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/src/or/directory.c b/src/or/directory.c
index a3aa276..75fc103 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3400,7 +3400,7 @@ handle_get_hs_descriptor_v3(dir_connection_t *conn,
const get_handler_args_t *args)
{
int retval;
- char *desc_str = NULL;
+ const char *desc_str = NULL;
const char *pubkey_str = NULL;
const char *url = args->url;
@@ -3434,8 +3434,6 @@ handle_get_hs_descriptor_v3(dir_connection_t *conn,
connection_write_to_buf(desc_str, strlen(desc_str), TO_CONN(conn));
done:
- tor_free(desc_str);
-
return 0;
}
diff --git a/src/or/hs_cache.c b/src/or/hs_cache.c
index 6d33201..ec98b47 100644
--- a/src/or/hs_cache.c
+++ b/src/or/hs_cache.c
@@ -142,13 +142,13 @@ cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
return -1;
}
-/* Using the query which is the blinded key for a descriptor version 3, lookup
- * in our directory cache the entry. If found, 1 is returned and desc_out is
- * populated with a newly allocated string being the encoded descriptor. If
- * not found, 0 is returned and desc_out is untouched. On error, a negative
- * value is returned and desc_out is untouched. */
+/* Using the query which is the base64 encoded blinded key of a version 3
+ * descriptor, lookup in our directory cache the entry. If found, 1 is
+ * returned and desc_out is populated with a newly allocated string being the
+ * encoded descriptor. If not found, 0 is returned and desc_out is untouched.
+ * On error, a negative value is returned and desc_out is untouched. */
static int
-cache_lookup_v3_as_dir(const char *query, char **desc_out)
+cache_lookup_v3_as_dir(const char *query, const char **desc_out)
{
int found = 0;
ed25519_public_key_t blinded_key;
@@ -167,7 +167,7 @@ cache_lookup_v3_as_dir(const char *query, char **desc_out)
if (entry != NULL) {
found = 1;
if (desc_out) {
- *desc_out = tor_strdup(entry->encoded_desc);
+ *desc_out = entry->encoded_desc;
}
}
@@ -270,7 +270,7 @@ hs_cache_store_as_dir(const char *desc)
* untouched. */
int
hs_cache_lookup_as_dir(uint32_t version, const char *query,
- char **desc_out)
+ const char **desc_out)
{
int found;
diff --git a/src/or/hs_cache.h b/src/or/hs_cache.h
index 466c33d..88f84c1 100644
--- a/src/or/hs_cache.h
+++ b/src/or/hs_cache.h
@@ -48,7 +48,7 @@ size_t hs_cache_handle_oom(time_t now, size_t min_remove_bytes);
* right function. */
int hs_cache_store_as_dir(const char *desc);
int hs_cache_lookup_as_dir(uint32_t version, const char *query,
- char **desc_out);
+ const char **desc_out);
#ifdef HS_CACHE_PRIVATE
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index f3776ac..e3a3fda 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -131,7 +131,8 @@ test_directory(void *arg)
{
int ret;
size_t oom_size;
- char *desc_out, *desc1_str;
+ char *desc1_str;
+ const char *desc_out;
hs_descriptor_t *desc1;
(void) arg;
@@ -158,7 +159,6 @@ test_directory(void *arg)
ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
tt_int_op(ret, OP_EQ, 1);
tt_str_op(desc_out, OP_EQ, desc1_str);
- tor_free(desc_out);
/* Tell our OOM to run and to at least remove a byte which will result in
* removing the descriptor from our cache. */
oom_size = hs_cache_handle_oom(time(NULL), 1);
@@ -186,7 +186,6 @@ test_directory(void *arg)
ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
tt_int_op(ret, OP_EQ, 1);
tt_str_op(desc_out, OP_EQ, desc1_str);
- tor_free(desc_out);
/* We should NOT find our zero lifetime desc in our cache. */
ret = hs_cache_lookup_as_dir(3,
helper_get_hsdir_query(desc_zero_lifetime),
@@ -221,7 +220,6 @@ test_directory(void *arg)
tt_int_op(ret, OP_EQ, 0);
ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
tt_int_op(ret, OP_EQ, 1);
- tor_free(desc_out);
/* Bump revision counter. */
desc1->plaintext_data.revision_counter++;
ret = hs_desc_encode_descriptor(desc1, &new_desc_str);
@@ -232,7 +230,6 @@ test_directory(void *arg)
ret = hs_cache_lookup_as_dir(3, helper_get_hsdir_query(desc1), &desc_out);
tt_int_op(ret, OP_EQ, 1);
tt_str_op(desc_out, OP_EQ, new_desc_str);
- tor_free(desc_out);
tor_free(new_desc_str);
}
1
0

[tor/master] Check the correct key when checking RSA crosscert in hs_descriptor.c
by nickm@torproject.org 04 Nov '16
by nickm@torproject.org 04 Nov '16
04 Nov '16
commit 09c750cce353d76c6b1e1481150c5dc0166f5a53
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 13:49:05 2016 -0400
Check the correct key when checking RSA crosscert in hs_descriptor.c
Note that the "signed key" in the signing key certificate is the
signing key. The "signing key" in the signing key certificate is
the key that signs the certificate -- that is, the blinded key.
---
src/or/hs_descriptor.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/or/hs_descriptor.c b/src/or/hs_descriptor.c
index f89bd4b..f5dafab 100644
--- a/src/or/hs_descriptor.c
+++ b/src/or/hs_descriptor.c
@@ -1290,10 +1290,10 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
}
if (rsa_ed25519_crosscert_check((const uint8_t *) tok->object_body,
tok->object_size, ip->enc_key.legacy,
- &desc->plaintext_data.signing_key_cert->signing_key,
+ &desc->plaintext_data.signing_key_cert->signed_key,
approx_time()-86400)) {
- log_warn(LD_REND, "Unable to cross certify the introduction point "
- "legacy encryption key.");
+ log_warn(LD_REND, "Unable to check cross-certification on the "
+ "introduction point legacy encryption key.");
goto err;
}
break;
1
0

[tor/master] Fix a bunch of leaks in hs_cache/upload_and_download_hs_desc
by nickm@torproject.org 04 Nov '16
by nickm@torproject.org 04 Nov '16
04 Nov '16
commit 29ae8dcf96532eb5be8023a29de404576d5d2339
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 14:13:30 2016 -0400
Fix a bunch of leaks in hs_cache/upload_and_download_hs_desc
---
src/or/hs_descriptor.c | 2 ++
src/test/test_hs_cache.c | 5 +++++
2 files changed, 7 insertions(+)
diff --git a/src/or/hs_descriptor.c b/src/or/hs_descriptor.c
index 0676c71..3986e8d 100644
--- a/src/or/hs_descriptor.c
+++ b/src/or/hs_descriptor.c
@@ -324,8 +324,10 @@ encode_enc_key(const ed25519_keypair_t *sig_key,
goto err;
}
if (encode_cert(cross_cert, &encoded_cert)) {
+ tor_cert_free(cross_cert);
goto err;
}
+ tor_cert_free(cross_cert);
if (curve25519_public_to_base64(key_fp_b64,
&ip->enc_key.curve25519.pubkey) < 0) {
tor_free(encoded_cert);
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index dc7cf03..e05e1f2 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -6,6 +6,7 @@
* \brief Test hidden service caches.
*/
+#define CONNECTION_PRIVATE
#define HS_CACHE_PRIVATE
#include "ed25519_cert.h"
@@ -322,10 +323,13 @@ helper_fetch_desc_from_hsdir(const ed25519_public_key_t *blinded_key)
fetch_from_buf_http(TO_CONN(conn)->outbuf, &headers, MAX_HEADERS_SIZE,
&received_desc, &body_used, 10000, 0);
+ tor_free(headers);
}
done:
tor_free(hsdir_query_str);
+ if (conn)
+ connection_free_(TO_CONN(conn));
return received_desc;
}
@@ -373,6 +377,7 @@ test_upload_and_download_hs_desc(void *arg)
done:
tor_free(received_desc_str);
tor_free(published_desc_str);
+ hs_descriptor_free(published_desc);
}
/* Test that HSDirs reject outdated descriptors based on their revision
1
0

04 Nov '16
commit dbd01590cc9e6329fab1acd57b7380fb9f30a0ae
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 4 13:30:10 2016 -0400
Fix an assertion failure in hs_cache_free_all().
It's possible for Tor to decide to exit before it's 100% done
initializing. So, don't assert that the initialization is done.
---
src/or/hs_cache.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/or/hs_cache.c b/src/or/hs_cache.c
index 868f936..fe86e04 100644
--- a/src/or/hs_cache.c
+++ b/src/or/hs_cache.c
@@ -379,6 +379,6 @@ hs_cache_init(void)
void
hs_cache_free_all(void)
{
- tor_assert(hs_cache_v3_dir);
digest256map_free(hs_cache_v3_dir, cache_dir_desc_free_);
+ hs_cache_v3_dir = NULL;
}
1
0