diff --git a/changes/prop297 b/changes/prop297
new file mode 100644
index 0000000000..4f93b232d2
--- /dev/null
+++ b/changes/prop297
@@ -0,0 +1,7 @@
+ o Minor features (required protocols):
+ - Tor no longer exits if it is missing a required protocol, if the
+ consensus that requires the protocol predates the release date of the
+ version of Tor. This change prevents Tor releases from exiting because
+ of an old cached consensus, on the theory that a newer cached
+ consensus might not require the protocol. Implements proposal 297;
+ closes ticket 27735.
diff --git a/src/core/or/versions.c b/src/core/or/versions.c
index 5d4effcaf8..d978935f4f 100644
--- a/src/core/or/versions.c
+++ b/src/core/or/versions.c
@@ -16,6 +16,25 @@
#include "core/or/tor_version_st.h"
+/**
+ * Return the approximate date when this release came out, or was
+ * scheduled to come out, according to the APPROX_RELEASE_DATE set in
+ * configure.ac
+ **/
+time_t
+tor_get_approx_release_date(void)
+{
+ char tbuf[ISO_TIME_LEN+1];
+ tor_snprintf(tbuf, sizeof(tbuf),
+ "%s 00:00:00", APPROX_RELEASE_DATE);
+ time_t result = 0;
+ int r = parse_iso_time(tbuf, &result);
+ if (BUG(r < 0)) {
+ result = 0;
+ }
+ return result;
+}
+
/** Return VS_RECOMMENDED if myversion is contained in
* versionlist. Else, return VS_EMPTY if versionlist has no
* entries. Else, return VS_OLD if every member of
diff --git a/src/core/or/versions.h b/src/core/or/versions.h
index 4fc50a0018..acd8998918 100644
--- a/src/core/or/versions.h
+++ b/src/core/or/versions.h
@@ -26,6 +26,8 @@ typedef enum version_status_t {
VS_UNKNOWN, /**< We have no idea. */
} version_status_t;
+time_t tor_get_approx_release_date(void);
+
version_status_t tor_version_is_obsolete(const char *myversion,
const char *versionlist);
int tor_version_parse_platform(const char *platform,
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index f1def9afb1..a25a539cd8 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -2684,6 +2684,9 @@ networkstatus_check_required_protocols(const networkstatus_t *ns,
const char *required, *recommended;
char *missing = NULL;
+ const bool consensus_postdates_this_release =
+ ns->valid_after >= tor_get_approx_release_date();
+
tor_assert(warning_out);
if (client_mode) {
@@ -2701,7 +2704,7 @@ networkstatus_check_required_protocols(const networkstatus_t *ns,
"%s on the Tor network. The missing protocols are: %s",
func, missing);
tor_free(missing);
- return 1;
+ return consensus_postdates_this_release ? 1 : 0;
}
if (! protover_all_supported(recommended, &missing)) {