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
October 2014
- 26 participants
- 1551 discussions

[tor/master] Merge remote-tracking branch 'public/bug11243_squashed'
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit d950e243328eaac40515b4b16ac328f6748c7a3f
Merge: 032e3b7 9df61d7
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Oct 13 14:32:43 2014 -0400
Merge remote-tracking branch 'public/bug11243_squashed'
changes/ticket11243 | 7 +
scripts/codegen/makedesc.py | 218 +++++++++++++
src/or/directory.c | 3 +
src/or/dirserv.c | 4 +-
src/or/dirvote.c | 4 +-
src/or/microdesc.c | 50 ++-
src/or/networkstatus.c | 16 +-
src/or/networkstatus.h | 17 +-
src/or/or.h | 4 +-
src/or/router.c | 6 +-
src/or/routerlist.c | 100 ++++--
src/or/routerlist.h | 18 +-
src/or/routerparse.c | 89 +++--
src/or/routerparse.h | 12 +-
src/test/example_extrainfo.inc | 192 +++++++++++
src/test/failing_routerdescs.inc | 668 ++++++++++++++++++++++++++++++++++++++
src/test/include.am | 2 +
src/test/test_dir.c | 509 ++++++++++++++++++++++++++++-
src/test/test_microdesc.c | 327 ++++++++++++++++++-
19 files changed, 2168 insertions(+), 78 deletions(-)
1
0

[tor/master] Don't reset the download failure status of any object marked as impossible
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit b8e2be5557287a00905aa30f78eff42519b164d5
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Oct 7 09:34:28 2014 -0400
Don't reset the download failure status of any object marked as impossible
---
src/or/directory.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/or/directory.c b/src/or/directory.c
index 1aaa75c..8e75bfd 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3442,6 +3442,9 @@ download_status_increment_failure(download_status_t *dls, int status_code,
void
download_status_reset(download_status_t *dls)
{
+ if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
+ return; /* Don't reset this. */
+
const smartlist_t *schedule = find_dl_schedule_and_len(
dls, get_options()->DirPort_set);
1
0

[tor/master] Base tests for 11243: test parsing for md, ei, and ri.
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit 24dfbfda1db41d0e9feb5def09e1b7ede350de40
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Oct 6 09:06:04 2014 -0400
Base tests for 11243: test parsing for md, ei, and ri.
We didn't really have test coverage for these parsing functions, so
I went and made some. These tests also verify that the parsing
functions set the list of invalid digests correctly.
---
src/test/example_extrainfo.inc | 191 +++++++++++
src/test/failing_routerdescs.inc | 668 ++++++++++++++++++++++++++++++++++++++
src/test/include.am | 2 +
src/test/test_dir.c | 276 ++++++++++++++++
src/test/test_microdesc.c | 228 +++++++++++++
5 files changed, 1365 insertions(+)
diff --git a/src/test/example_extrainfo.inc b/src/test/example_extrainfo.inc
new file mode 100644
index 0000000..26587c7
--- /dev/null
+++ b/src/test/example_extrainfo.inc
@@ -0,0 +1,191 @@
+static const char EX_EI_MINIMAL[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_MINIMAL_FP[] = "3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B";
+static const char EX_EI_MINIMAL_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALSppIF3t3wOAm4fzxRvK+q/wh1gGAWwS0JEn8d+c/x+rt1oQabGkqsB\n"
+ "GU6rz1z1AN02W0P2+EcyJQVBjGR3gHQNoDGx0KIdnr3caGAw3XmQXrJLPaViEk28\n"
+ "RJMxx6umpP27YKSyEMHgVTDXblKImT0mE7fVOx8tD0EWRYazmp4NAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_MAXIMAL[] =
+ "extra-info bob FF8248FE780A7236D3FA5D62DEA642055135F942\n"
+ "published 2014-10-05 20:07:00\n"
+ "opt foobarbaz\n"
+ "read-history 900 1,2,3\n"
+ "write-history 900 1,2,3\n"
+ "dirreq-v2-ips 1\n"
+ "dirreq-v3-ips 100\n"
+ "dirreq-v3-reqs blahblah\n"
+ "dirreq-v2-share blahblah\n"
+ "dirreq-v3-share blahblah\n"
+ "dirreq-v2-resp djfkdj\n"
+ "dirreq-v3-resp djfkdj\n"
+ "dirreq-v2-direct-dl djfkdj\n"
+ "dirreq-v3-direct-dl djfkdj\n"
+ "dirreq-v2-tunneled-dl djfkdj\n"
+ "dirreq-v3-tunneled-dl djfkdj\n"
+ "dirreq-stats-end foobar\n"
+ "entry-ips jfsdfds\n"
+ "entry-stats-end ksdflkjfdkf\n"
+ "cell-stats-end FOO\n"
+ "cell-processed-cells FOO\n"
+ "cell-queued-cells FOO\n"
+ "cell-time-in-queue FOO\n"
+ "cell-circuits-per-decile FOO\n"
+ "exit-stats-end FOO\n"
+ "exit-kibibytes-written FOO\n"
+ "exit-kibibytes-read FOO\n"
+ "exit-streams-opened FOO\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "ZO79bLlWVNIruCnWW9duDcOKydPWbL5DfrpUv5IRLF4MMFoacMUdJPDUs9e+wY2C\n"
+ "zndHe6i2JK7yKJj+uCOSC8cx61OLG+kVxMLJ/qhA4H5thrYb+GpzMKwbHzQc3PTH\n"
+ "zHRzj041iWXTL7/DMaQlpJOBoac/wTSIKzoV2B00jBw=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_MAXIMAL_FP[] = "FF8248FE780A7236D3FA5D62DEA642055135F942";
+static const char EX_EI_MAXIMAL_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANSpkYhHUW1EqodY4d3JRbvEM1vjjR/vEE8gjONiJ5t2Sten53jzt8bh\n"
+ "8/VJn7pQGs8zR5CIxCw4P68xMtZJJedS3hhjqubheOE/yW1DtpkiCf+zVEaLpeA8\n"
+ "fYQChkRICnR/BZd4W9bbohLVII5ym2PaJt2ihB3FeVZIsGXm4wxhAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_SIG1[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hXXw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_SIG2[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-06 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_SIG3[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_FP[] =
+ "extra-info bob C34293303F0F1E42CB14E593717B834E8E53797D8888\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "IDA8ryUYeMx7+Au/xQmX7Y8fXksoHUOXmePND2JYM4rPfishQJ1LpQ15KrolOZDH\n"
+ "FVIk3RmCefNlJeS1/UgWPcU8u2nGw1YQuRBHF4ViTmZ0OevI1pTsSApl4+oIx2dy\n"
+ "DGgCQmKfMbaOixIK8Ioh1Z2NUfMkjbUUE2WWgFTAsac=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_FP_FP[] = "C34293303F0F1E42CB14E593717B834E8E53797D";
+static const char EX_EI_BAD_FP_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKXMSbif4fG+BW/5lIq5V1tMRondIUfKiNizp0E6EcBw5LvYfQV6zrj8\n"
+ "HmMFbB/WGf9XGVMxIBzxzeQBRvCQJh+0QH7+ju5/isIHJZsACMILepr6ywmCcjVU\n"
+ "iYRtC8zGQLqfkf2cNoo7AhcI5i/YzyW2u1zmbPX5J+8sUErfxydbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_NICKNAME[] =
+ "extra-info bobhasaverylongnameandidontthinkweshouldlethim A4EA2389A52459B3F7C7121A46012F098BDFC2A4\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "e2wLJFThRMGawxKrQPuH2XCLek/LJsg4XOB8waAjE0xdHOrzjur9x1jIxy7DVU6t\n"
+ "z1edbIoL24qucMJvFy2xjSQhFRX4OsyNc0nWr3LfJnTW9aEmxuwXM+mltUD2uFN1\n"
+ "2vYOIQjUmJwS2yfeSKnhXEl2PWVUmgzYL3r4S5kHco4=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_NICKNAME_FP[] = "A4EA2389A52459B3F7C7121A46012F098BDFC2A4";
+static const char EX_EI_BAD_NICKNAME_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKfq7oxD1kMu1+zeG2UVXN4vOu6FDp0V/olA3ttmXpUCgCiBxWTgtwNl\n"
+ "nPf0HcKMaCp/0D9XrbhvIoOsg0OTf1TcJfGsA/zPG7jrWYa4xhD50KYvty9EINK9\n"
+ "/UBWNSyXCFDMqnddb/LZ8+VgttmxfYkpeRzSSmDijN3RbOvYJhhBAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_TOKENS[] =
+ "extra-info\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "e0b8fW9SkB81WwpkqR+/oLvVnNMpW4VwBKlNAnsPdInnNYySFCeILyOmb8A5j/D3\n"
+ "ZRbfKFgXrApya4ViGeh+1QHz+FM8nWaK0+5JE6cNw+DNiQWsUjrvq2bHoZi/Lv+k\n"
+ "RFkpbb0+IPdub9Jj3qn6cZBVSChD1aeCO9RkchV0744=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_TOKENS_FP[] = "1CE7F867C744F0CE635146D82C0A0CC4B3408E0A";
+static const char EX_EI_BAD_TOKENS_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALfrYfnIA7gTGwEC5tPqqTuSnMiINq/hPyMWXOFUEKEBRmctxba9fjiy\n"
+ "JDstxC4ZBpdHc3+uuFn6krGgBVzFCKvBkBHUQXgFmjlANzdcLrG7J78K6gXuPeeq\n"
+ "MbptD7thkuIdkPdVWMko7BrmBEr30EphgrKQqTWjrtBQj+CZ8Sr1AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_START[] =
+ "published 2014-10-05 20:07:00\n"
+ "extra-info bob 5CCCACE71A9BDB5E8E0C942AB3407452350434C0\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "BOiWgexqCAMZ8uyJ7jwBwRkz7Ox8cT4BImkmkV3bQiZgcWvPiYA3EnCm2ye48Ldg\n"
+ "zBST2p6zJM5o4MEDYGMxfViS86Abj/z7DOY1gtLhjmAaVjIIpXc3koxEZtzCecqy\n"
+ "JQz6xEg9/KoEuoT0DRrfYQ+KtQfzBDWrotfOvEa1rvc=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_START_FP[] = "5CCCACE71A9BDB5E8E0C942AB3407452350434C0";
+static const char EX_EI_BAD_START_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAK2OCIfM6Cin/lq99Z3w9tl6HeyGlkBZu9MQEPHxqGIHTq78lIC1UkrC\n"
+ "6NTqlrHBV9dmfzdwJn4GgMWsCZafL0FPIH3HNyNKUxLgyjixyKljHx2rfErSfOxI\n"
+ "bMoOGBKv7m1EZZ0O5uG9ly9MBiNGdJyLdlnVvH7wSCnYciizpO4lAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_PUBLISHED[] =
+ "extra-info bob E67C477E3536BDE348BD407426D9679E5AE0BC16\n"
+ "published 2014-99-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "l45IziBaXRKIjPAIUogMFNjQgH6k6Vm0+6r5+oByr4sP+B3ufNdUA6+WqBs43F0Z\n"
+ "IqcJiT9nFn0DuNd/liOyOCixppDLx5h5NrhoGqcT3ySADEEXhzjlmc35TI3YBNVO\n"
+ "v98fotmwIEg9YRWVGPg6XuIn2PRyiboFyjUpaYGCV0Q=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_PUBLISHED_FP[] = "E67C477E3536BDE348BD407426D9679E5AE0BC16";
+static const char EX_EI_BAD_PUBLISHED_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL7q8GEI18iv8Fo0QbNHmFatQ2FNacalPldpmKUdMJYEVZtdOR0nhcrY\n"
+ "BvG6303md3INygg+KP49RvWEJR/cU4RZ9QfHpORxH2OocMyRedw2rLex2E7jNNSi\n"
+ "52yd1sHFYI8ZQ4aff+ZHUjJUGKRyqpbc8okVbq/Rl7vug0dd12eHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
diff --git a/src/test/failing_routerdescs.inc b/src/test/failing_routerdescs.inc
new file mode 100644
index 0000000..b49d59f
--- /dev/null
+++ b/src/test/failing_routerdescs.inc
@@ -0,0 +1,668 @@
+/* This one actually succeeds */
+static const char EX_RI_MINIMAL[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
+ "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
+ "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
+ "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
+ "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
+ "fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
+ "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
+ "-----END SIGNATURE-----\n";
+
+/* So does this, and it's bigger. */
+static const char EX_RI_MAXIMAL[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANNI56H+b7SW5LMzvXyY5NJzXszsHZZ4O1CPm4CePhBsAz1r0s1JYJ1F\n"
+ "Anrc0mEcLtmj0c5+HnhPBNrfpjO6G94Wp3NZMVykHDhfNVDBRyFZMroG8/GlysYB\n"
+ "MQPGQYR0xBgiuclNHoyk/vygQhZekumamu2O86EIPcfg9LhGIgEbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALvuNVSmg6R9USFbQcNbRjMCJAV0Rwdv0DlS6Rl02ibJgb01G7v391xE\n"
+ "d9Njzgf93n8gOrE195bkUbvS6k/DM3HFGgArq6q9AZ2LTbu3KbAYy1YPsSIh07kB\n"
+ "/8kkvRRGx37X9WGZU3j5VUEuzqI//xDE9lbanlnnFXpnb6ymehDJAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject 127.0.0.1:*\n"
+ "accept *:80\n"
+ "reject *:*\n"
+ "ipv6-policy accept 80,100,101\n"
+ "ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVw\n"
+ "uptime 1000\n"
+ "hibernating 0\n"
+ "unrecognized-keywords are just dandy in this format\n"
+ "platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series\n"
+ "contact O.W.Jones\n"
+ "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
+ "read-history 900 1,2,3,4\n"
+ "write-history 900 1,2,3,4\n"
+ "extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
+ "hidden-service-dir\n"
+ "allow-single-hop-exits\n"
+ "family $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
+ "caches-extra-info\n"
+ "or-address [::1:2:3:4]:9999\n"
+ "or-address 127.0.0.99:10000\n"
+ "opt fred is a fine router\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "x5cxL2h2UsEKk2OVnCTxOF8a89HAe/HwQnSlrBy8+l0YdVCcePDJhm1WyWU7ToHZ\n"
+ "K8auwreuw+u/n14sQHPYrM9NQE689hP4LC9AYOnrCnMHysfVqKuou+DSKYYRgs0D\n"
+ "ySCmJ9p+xekfmms+JBmS5o5DVo48VGlG0VksegoB264=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* I've messed with 12 bits of the signature on this one */
+static const char EX_RI_BAD_SIG1[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
+ "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
+ "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
+ "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
+ "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
+ "fkIprv9UXqkv5iY+pXSYXX12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
+ "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
+ "-----END SIGNATURE-----\n";
+
+/* This is a good signature of the wrong data: I changed 'published' */
+static const char EX_RI_BAD_SIG2[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
+ "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
+ "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
+ "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
+ "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:01\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
+ "fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
+ "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
+ "-----END SIGNATURE-----\n";
+
+/* This one will fail while tokenizing the first line. */
+static const char EX_RI_BAD_TOKENS[] =
+ "router bob\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANGCgvZc+JRtAzuzk3gBD2rH9SHrXzjJ1wqdU3tLKr7FamKCMI2pLwSA\n"
+ "FZUpTuSqB9wJ/iVcYws+/kA3FjLqgPtzJFI0SVLvQcz5oIC1rEWpuP6t88duMlO9\n"
+ "flOUzmYu29sBffrXkQr8pesYvakyXArOJVeRR7fSvouneV5aDYWrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAML+pYZoYc+whKLijupd63xn0gzlEQqe7k07x/lWMqWFT37FfG6YeNr5\n"
+ "fpFoo77FDfuFaL+VfPfI8i88g157hcPKBVX6OyRH54+l5By0tN91S0H+abXjXQpv\n"
+ "U/Bvmul+5QpUeVJa1nPg71HRIauoDnBNexUQ7Xf/Bwb2xCt+IJ6DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "tbxtYYzyVqi6w6jz1k8NPjFvZaSNR0WzixVTTvKKGoMPx/6+Z8QAFK1ILzRUVucB\n"
+ "nRhmZMFaPr3vREMErLRE47ODAzwoBCE9C+vYFvROhgfzuQ3cYXla+4sMaRXYZzjH\n"
+ "PQ82bTwvSbHsR8fTTgePD/Ac082WxXTGpx6HOLBfNsQ=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_PUBLISHED[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMoipSwZgTG6SpSOm6ENbyALS1Ljqqa1LSGmtHSRfGYgUQGWZXERXKQj\n"
+ "P5ql6o7EbGr1wnispGW/KB8Age09jGDvd/oGhQ9TDFluhLZon3obkZSFw7f9iA7Q\n"
+ "s29rNxoeXXLZVyS7+sux70b8x2Dt4CeG8GA8nQLljy1euwU+qYYJAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAPzfzQ+2WFMUvnB3z0xD+zwczWcFyYYNW8Lj7/aRGSNN2DICp5uzSjKq\n"
+ "qkYQ+C8jG21+MR2PE+ZBmq6CL5mvlFKlWKouXUlN7BejwWf2gw0UYag0SYctae1b\n"
+ "bu8NuUEvdeGWg5Odgs+abH7U9S0hEtjKrmE5vvJS5L841IcaPLCFAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 99:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "G92pnwCIXGJ9Q0fI9y4m/fHpWCsD0Hnk81/6T4TmRH3jt77fc0uRdomUOC5id4kz\n"
+ "J2M4vqXwRs5OK+eaPbtxf8Yv6FPmB3OBNCIhwNHIIqzKQStHUhPxD3P6j8uJFwot\n"
+ "/CNGciDN+owZ2DzwrXpszDfzcyp/nmwhApbi3W601vY=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* Bandwidth field isn't an integer. */
+static const char EX_RI_BAD_BANDWIDTH[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAN32LAvXQaq0p554FcL4LVwnxyiZvscfuFnfpXwWTDRJJHd2+JCttWIx\n"
+ "v+eW7dNq+rq/tzSzaZwnp8b4V2skLRojSt6UUHD234eZcsPwUNhSr0y1eMuoZbnV\n"
+ "UBBPevpuXea85aSFEXXRlIpQfvFc43y3/UFoRzo5iMPqReo2uQ4BAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMBuF1GvOyVcRDNjzlEmGHJkTA7qkaWgTp33NSY/DPEJoahg0Qswuh2w\n"
+ "1YCBqem6Txp+/Vl9hoUoUGwb7Vwq0+YDMSyr0z3Ih2NcNjOMZPVtjJuv+3wXrQC8\n"
+ "LPpCpfU9m9QvhQ7f9zprEqUHOQTT0v5j2a5bpfd++6LFxrMUNwbfAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth hello world today\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
+ "SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
+ "ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* Onion key is actually a signature. */
+static const char EX_RI_BAD_ONIONKEY1[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANByIdFOKA3r2nnWyLjdZE8oGHqJE62T1zjW/nsCzCJQ8/kBMRYeGDu4\n"
+ "SeUJJ2rsh2t3PNzkqJM14f4DKmc2q76STsOW0Zcj70Bjhxb9r/OfyELVsi+x3CsE\n"
+ "Zo/W4JtdlVFjqevhODJdyFNLKOvqwG7sZo/K++Hx01Iu0zXLeg8nAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
+ "SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
+ "ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Cc/Y22KFvxXPXZtjvGIyQdjm4EMhXVXJEBwt8PvK7qlO1AgiVjEBPkUrTQQ/paLQ\n"
+ "lmeCN6jEVcZ8lNiVZgzRQ/2mTO3xLBPj26UNSDuouUwZ01tZ4wPENylNYnLKv5hg\n"
+ "gYARg/nXEJiTVe9LHl99Hr9EWWruRG2wFQjjTILaWzI=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* Onion key has exponent 3 */
+static const char EX_RI_BAD_ONIONKEY2[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKP1kWHsH/BZhNSZmn0FyzIrAHtMl1IVPzc7ABbx+kK+IIEMD9k1fy2h\n"
+ "AP2JTm2UmJDUwutVxPsxmndI+9QsRDpu33E5Ai4U1Rb6Qu+2BRj43YAyg414caIu\n"
+ "J5LLn6bOzt7gtz0+q69WHbnwgI4zUgUbwYpwoB7k0dRY97xip9fHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGHAoGBANBKlyoqApWzG7UzmXcxhXM4T370FbN1edPbw4WAczBDXJslXCU9Xk1r\n"
+ "fKfoi/+WiTGvH7RcZWPm7wnThq2u2EAO/IPPcLE9cshLBkK28EvDg5K/WsYedbY9\n"
+ "1Gou+7ZSwMEPv2b13c7eWnSW1YvFa64pVDKu2sKnIjX6Bm0HZGbXAgED\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "cYcBOlapA+R4xq3nn5CjpnzNXdDArMlHuXv4MairjleF1n755ecH8A/R8YIc2ioV\n"
+ "n/C1TACzFVQ12Q9P3iikVOjIXNxYzaz4Lm/L/Lq4sEOPRJC38QEXeIHEaeM51lE6\n"
+ "p6kCqXcGu/51p5vAFCSiXI1ciucmx93N+TH1yGKRLV0=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_PORTS[] =
+ "router fred 127.0.0.1 900001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANVi/MVWhzT5uo3Jxw4ElS7UGmA24dnckdkCLetMhZOcE9e9mg4WcImL\n"
+ "NuBe2L/9YaL4PFVchCGlq73phKG6yFdqJdjDV8Qh9MJdAYWW2ORrjRvCrspPaYPN\n"
+ "BGJrkD2Gd4u3sq7f26TIkzmBx0Acd/FD4PQf8+XOt9YYd36ooS4vAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALtP4cIpAYp9nqo1ak4SxALcndFw4o51U36R4oa+uJS/lYQPHkMMOj6K\n"
+ "+AVnj9sxkDJ1POaU5lsCQ5JPG1t+Tkh7vDlJb6RCUy25vJOuaQCb9GVVY7KQTJqA\n"
+ "E0fU73JdKACNjMlbF36aliQhrG4Fq2Uv+y7yp8qsRxQ8jvzEMES/AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "xzu2T+pMZtdsS5q1cwXM2hMIH2c8mpAV31G2hKIuiQRwtPD1ne4iJsnoVCXhFakd\n"
+ "QTq7eTXM174fGWyIT93wvQx/Uqnp29dGZp/VaNOsxHFdYVB4VIVqkBh757h+PSJ+\n"
+ "VNV5JUm4XQ1QbmniJGdTQp4PLBM++fOXMR3ZNd6rt4o=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_NEG_BANDWIDTH[] =
+ "router fred 100.127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMCG/ZCXNCF02uXRSCP7qWBN75jDMQZ363ubnQWhF9KDDNWWiwj3UiZR\n"
+ "zqsM4zKRgjtarWZvp2qxKABFAODd+j9iq5DvUGRbbXv+aR8TT/ifMtwwxHZQBk1F\n"
+ "1hbsLdwWzGIiyz5k2MVhXnt6JTlklH2hgT++gt9YTHYKxkssaq5TAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM3vk/4kOTB1VXrve29JeHOzNUsPwKruBcjxJf+aatxjf6KO2/RW41bM\n"
+ "gRYq9V7VAYeZTsbS727fy03F5rk3QIBhMJxm9FHatQ6rT/iEDD4Q1UZQsNtm+OLf\n"
+ "/TkZZhgfB3MiDQ4ld/+GKd7qww8HXTE+m/g1rXNyZPKozn8K7YUHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 -1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "bUBBZYZWqCbsH4/7fNXtC/HgIZNGOfDF9v4d9YfKaDs5xDYf2o67hRcwx5imhrgC\n"
+ "IU7n9AI4AGxkFoN6g3Y/t4pqebxdkF678rRDCtrlwwreAiUktgrwnetp9Tpo16xj\n"
+ "V7Uf6LcqQdvu78lRh1dsrY78sf7sb90vusFMPLXGUKM=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_IP[] =
+ "router fred 100.127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMtMrM24AJpJCevxnseIpRlSuAIMksfkfky2+noe7Rok8xn6AMQzMrwx\n"
+ "AiCJ8Jy4DBzIKUiJK4/y1FimyM08qZGR0xeqblCxZ1lbSiXv6OYxoaD2xmWw8zEP\n"
+ "Zgu4jKReHh+gan1D+XpAbFNY0KrANhjRo96ZZ3AQsZQcWBiPKCynAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOPclmBO/amw1RWTSI1y80qY/EPjc0I+sk9HKr0BQOovxqJ0lmy9Gaue\n"
+ "y+MOejQ9H2hNev0nd7z1fPxEogt7SCe22qJHHX3xDf+D9RpKsvVzDYZsk7hVL7T1\n"
+ "mwHzuiV/dtRa7yAMp7+q0vTUGesU2PYFYMOyPvz5skNLSWrXOm05AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "g6besL/zxOp0N6Q5/7QZgai2kmCU5EAWJlvZrf5jyrjKhsv2a4LDkap07m9QRFqW\n"
+ "GGe7g5iiABIqnl0kzv7NLX7ah+d/xxv+IILXyZfVTxSw0e+zFb3uPlQ7f9JsGJ8i\n"
+ "a+w8wyyDBpOAmi8Ny866Cnp9ojVzCyIErUYHFaPvKao=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_DIRPORT[] =
+ "router fred 127.0.0.1 9001 0 bob\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANKcD6DJ16X3yvdq05jatdwgjO+hyoIpckW9sV/OkdfIZwf+S6Q4pZGC\n"
+ "doMw5XeOM52gjpx42kUp6M2WlTGDFEpaNU0VyeZYG/M1CM1xvfj3+1PoebioAGdf\n"
+ "GuhNBCHZdaYNiOGnh9t2GgUomgpE6njdS/lovSrDeTL469hfcUghAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANWeGHig5wE9UijaNnEW5au3B3hZKSlzCi+T6MYDPbbYhm8qJaVoXUXF\n"
+ "EP1EUgzDcX3dPEo9upUA1+91GkjGQCo9eOYlqGib8kHIwKnHZK+hernBc/DnOeUp\n"
+ "Wyk9SW5s+fi12OQhr3NGjbSn76FMY9XU3Qt7m3EviTwWpI3Jr5eRAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "t77wEoLjyfMf9LKgBfjveosgwvJ8Go0nb27Ae3Ng9tGtR4qaJQfmwZ5fOOuVU9QC\n"
+ "3s8ww3aY91KD3NTcN3v3FKngxWtRM8AIfwh4pqT3zW6OSP4+nO3xml7ql0Zf6wfj\n"
+ "TPFV2941O3yplAsmBJ41sRSWizF04wTtZAIgzY7dMLA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_NAME2[] =
+ "router verylongnamethatnevereverendsandgoesontoolong 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL0mcUxg7GJ6oxgciLiBCbo+NuZ/OVKRrERCSM6j6iHERcB9+ciSRgQ5\n"
+ "H6o6FUX2LoRmHYzBk1x7kIjHa9kx9g6CAbBamdZrQbdVnc1y2NrdHB/jvwLj3C48\n"
+ "PgzFIrLg9OlkuoWck/E+YpPllONfF65e0+ualgVjPgpQpXwmz+ktAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOgHvvTAxyjJtHx9W2X7aOI05H9sYDDY+sxhovT/8EpAHrioex54tsMT\n"
+ "ifgtoXTjGIBEOTDi/1ry39nEW5WPbowqvyzRfR2M43pc96WV7e1nhmD/JrnTYgtR\n"
+ "5/15KxcMJxoDhod7WZ/wlXBnHc2VevX8JTaeOe9KYORCj5iNbtVZAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "j/nFT5gyj20cLHWv94O1jmnqy3n6qkO8Av0OdvvfNeXsMK2UHxk84vzFvEwpUF/Y\n"
+ "i+VR3LXY4CjTpuliMtjt7BQGtmJSvB8W0CeIUenIGzfwDxW9dG2o7spDldKDB/OU\n"
+ "C1wyHvKaA6Yss/02RIDa4AxyjsfbgdJ91qK+aAnYAtA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_BANDWIDTH2[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALQDCm9VEopiYILmt4X9kP6DQazfgKnLXv+6rHbc4qtmvQQD3TVYbxMP\n"
+ "F4sEUaz+YHAPnomfDVW3a0YFRYXwDzUm1n47YYCyhUzEaD2f69Mcl/gLpKdg+QOy\n"
+ "boGB1oD4CStWL3y05KhxxTNiTrg+veMzXTqNwryCYm+GoihIAM9fAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALYHwdx6bmYy09AW5ElN/DWh0fHh3mBK97ryiIMi8FImYfzbw2BR6xuT\n"
+ "aQT5omqS3PNJJcNWZt5gOyDtA9kLh03cch7t1PenXSYJshbME2bDrZDJKVJMN6vV\n"
+ "B1v/9HjXsVF50jBzZsJo3j26XCPT5s6u9wqUFWW09QR3E/1HInHVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 -1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "p09ijyuvcW+WKRj4mJA/nkLCvZkRcMzykAWheJi1IHCoqhXFdkFLiIRqjaeDVHRr\n"
+ "zBtD+YCQiGvFcaQJ9IUhh7IleHcyyljmDYlvuBAxWiKvVZstJac0kclCU4W+g8yK\n"
+ "0Qug3PmGKk115x2TllHaCZqMo5OkK4I/WAsKp+DnJ1A=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_UPTIME[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMM0Nubr1VXQ/FcgIQTFxZpZDlAEh2XN8FoJ8d+X5S46VDGijmMoYmyN\n"
+ "oLXqMTGmOaR0RGZOeGLgDzeY8tLrfF821IjfkXeAANZibUjdsHwqHO3wlWD2v+GN\n"
+ "0GBocWXEdAp/os229mQQKgYAATJ0Ib3jKhBdtgm5R444u8VX5XnbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMpyOr4kEtSTZw4H9eSkH2+WmwIlO4VBpY2HkPS00l6L5fM2REjt50Xi\n"
+ "lsNOz8Q6mAn5cMYmsGlv61kg01mCvYc7Z715jGh+1hhVAxMaNS3ED/nSPnslyjhq\n"
+ "BUm51LhYNHD4ktISIqPMurx6aC8B68UYgKzLgCYNzkathFXSBpjRAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "uptime forever-and-a-day\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "NHYeiQOu0nZdrhSy31Xz4F0T6OTU23hPQDzoLax1/zq6iTVrz9xi3HGm7HhOMW1j\n"
+ "YgFGK3+Xm4iJL+DwriunsAIuL5axr3z2hlmFDQHYItP//KyPpOqSrfEOhwcuj/PE\n"
+ "VbWsiVYwz9VJLO8SfHoBeHI6PsjQRQFt2REBKZhYdxA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_BANDWIDTH3[] =
+ "router lucy 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAO6HrITQTEjV/v/rInQ2REmCFZa4dZg8zIh6+B51U/I6hDiZaKGwpNey\n"
+ "9OfjoRqT2DwyLEe3ORm9A2RAz2twLBixrpt5IvC0sbGustmW964BHW7k9VvRupwl\n"
+ "ovujHpLIj5dkLxD15jGXHoTp1yHUVk9NkMGN+ahg6y+QhTbIrWbRAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOEpciJFXauEqs31GMTUTzu6edBj9WtV+sIflhGKvU1KKRfwCgOcuKMx\n"
+ "QiLHHD9AjhMAFGT/qtNbPFkzfYxHKLHw+NLJsxmNtdkYM26FX3ButPiX+69sq9fI\n"
+ "PCHqQy6z/A7hHwtEk6niWgK2PLhAZCg9duAv+mqFVXe2QEBjax/lAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 electric\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Jk0Xk1RMJSjEflNRcp4qznaHKcfe2r0kOc7TdLAnM8zyNDVj6+Bn8HWmyp/oFmf6\n"
+ "xtWKKgkKxriAVIJgqZMchPbr9RuZS+i+cad++FCwpTVkyBP920XWC47jA3ZXSBee\n"
+ "HK6FaoK5LfmUm8XEU9BVhiwISXaUfTdkR8HfzugFbWk=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_NTOR_KEY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKYDCSr0Jh9d/mJKjnGYAHKNBcxR3EJk6GGLwKUrRpN8z/aHRxdWlZF2\n"
+ "lBml6yQNK/VPftcvOekxrKq3/dISrIFBzFYj6XHNtg31d09UgitVkk0VfRarZiGu\n"
+ "O6Yv55GSJ9a3AZDE4YmIp5eBjVuChyVkeDFYKVn0ed4sj9gg35rjAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALXdUQuq1pYHyYP0qU6Ik+oOmwl0eOsuwiLWf9Vd+dsgEszICX4DRWPx\n"
+ "syDxfxyA/g9FEPvlI7Nglx6cKe2MT0AutSRLbbML4smfuRZNIF35Cnfu5qTGVVzL\n"
+ "GWVSA2Ip7p+9S9xLhLBdc6qmrxEXCPL6anEhCR4f8AeybXAsz2JLAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVfjdklsdfjkf\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Yf9axWyzPudnRvQstNdbtBYo7pGpUEIdECMGcJtFb6v/00pxk4Tt3RiOKa84cOBV\n"
+ "7V9NjOLdqlx88pGz0DNCJKqToIrwjZDeQ8Q1yi9XClLDkC32fQRX4y6vNBZ3LXLe\n"
+ "ayVrdRrb41/DP+E7FP4RNPA5czujTfs8xLBMbGew8AA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_FINGERPRINT[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM0wDWF2dBLzsmoIDHRugzosCSR9TSvEE0TkvKu6+agfogGtkQJwQ5zO\n"
+ "sGzZbRR+okO7d+QCED2i3rUs1iikoMUT+pwgvOm8Bxg9R64GK7fl9K5WuAiG11Uj\n"
+ "DQAfSx5Fo30+rhOhe16c9CT7xJhj//ZKDbXUW7BrJI8zpuOnvgD5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKACg1nWM/WjpUiGwlLQsY3Tq1h0RTz/HmOMx/6rTRxS5HLz0KnLg5zV\n"
+ "dvmfhxqQVKBkt1N2+y+qO7x71oFzIsFMfHYWSxOCEo8Nkff1BqAPqxxUHvM0HwJo\n"
+ "d7lswJ/UT1j4+WZNZ4sFIujsIW2/zZqKlxG9xaw0GXJ082Cj9XkPAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "fingerprint 5555\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "mlqyJ/ZGBINKwSNEi7GpNBCMqIVbL0pGAOBYHJF1GbRlU28uRyNyeELIxIK5ZIet\n"
+ "ZzKr7KPvlBxlyolScPhTJfP98TFSubrwYz7NnQv0vLI0bD0OyoBf/9/1GYlzgTso\n"
+ "3mKfnV7THUalpxe9EjQ/x61Yqf26Co0+jYpt8/Ck6tg=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_MISMATCHED_FINGERPRINT[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANUAvwbpGbsAyA+mBwjFkvurtRzdw9btDqNKtPImufIE+q+AFTaCnwPr\n"
+ "kA7vm/O6h6OhgfdYEC2GfYJfwPGM7MDuz+NnuKxUb3qb2DQN2laqow6qWs9La/if\n"
+ "oHKUjC5mNeAgHcbWapx9CygwaFeVW6FBPl6Db6GIRAlywPSX+XMJAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANlSGd+Vm9nLiUk6zgu8dPnSFfw4F0R2GYfmzncIGJWtRFTF9ThW/0av\n"
+ "/9vZAWyVBjjtnpAP5R1BzdJYV2RwimC/6tqoHtkSbCBhdq5Cb/EHG7Xgb8KwNWVJ\n"
+ "NV1EESDwvWnRfSPGTreRw9+2LkdXri17FhDo2GjRxAq/N7YkLK5hAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Y8MwYBeEfMhoAABK/FgpVRYolZ7jQ2BJL+8Lb6i4yAuk+HeVmPKTX7MqQoekUuin\n"
+ "/HdPKP+g/9HPMS5pCiW4FMwnXAF0ZocPXF0ndmsTuh0/7VWVOUGgvBpPbIW6guvt\n"
+ "sLLQ3Cq9a4Kwmd+koatfLB6xSZjhXmOn7nRy7gOdwJ8=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_HAS_ACCEPT6[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAJfPJNA3zZ77v2nlX2j5dXImcB/NhRtkG8XQgF7z+3H17sqoXgBgZ1dq\n"
+ "IbyJmAy2Lrvk/8VkXNFrT5/ErThn1B98V/PsJOOW1x7jGcix6X4zDYn/MvwC+AxA\n"
+ "zNP0ozNcVZ6BzVYq8w4I1V4O3Cd6VJesxRVX6mUeSeNawOb7fBY7AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKBzfB4mDEJjFTnmtqZxDG8G1yAiccVgAtq9ECEREL/BOQyukixUBeBe\n"
+ "j/FgXzbMJ7DZAuopuJZU2ma6h14G63fZs7eNFceDtmdLpuCOsFuvJ5Mlkf3hDZ1u\n"
+ "1KK5q+tiG7MKxgnGrqjPBUO2uubs2Cpx0HmsqBNUalXd/KAkFJbXAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "accept6 *:80\n"
+ "reject6 *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Dp9dLgs9s5beMPxfD0m96as9gNBvlmKhH1RQ/kcOKscia4R8Q42CnUtIqLkCdjOu\n"
+ "zErc2Vj9QzjKOvlqUqHxP+J+l+ZJez6F+E1tcmK/Ydz3exL8cg9f4sAOCSXcpBey\n"
+ "llTFDibz6GkQ2j3/Uc4bN/uLzoyZKunpJbSKZP5nt8Q=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_NO_EXIT_POLICY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAK4fbjTKYqv2fygfjzY53sVTdtbNMjq293/uffKKxFYnOVvPzrHlP6Go\n"
+ "2S19ZcyDxOuH1unbBChPnV0GpxXX6+bgfDkaFh7+jef0RQ3fpJl84hSvdM8J8SCt\n"
+ "Q/F4Oqk3NeKKs+zAHDjhAU1G4LkF9/SZ9WZVXlH4a4pf7xgQtaShAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKahvyDkmh33ob/bLVO1icgz2ntOZN6ZQUfgpMU4Cd6DQtOEwFUGhbVt\n"
+ "gvtMHv2+VbxM31ZfUsyBqJ1rJBLpOqlPvSoYwSac2+twa+w/qjfGqcJYhBjP9TV9\n"
+ "n9y8DzBX85p6vRcCzcuZ4qUJ2nRzdLHwjdgzeLmmCHuPO2dQxQhXAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "ntgCtMC0VrsY42dKts8igGQ2Nu1BpuzUltisIsJz75dDx2LCqTn7p4VpWbTrj1sH\n"
+ "MRNOvEPFxVMs0Lu50ZUGRzeV6GrHmzIRnOIWanb3I/jyrJLM0jTIjCOLwdMRA298\n"
+ "tw8Y9Hnwj4K7K6VvgU8LP4l7MAJNfR6UT46AJ6vkgL0=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_IPV6_EXIT_POLICY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKHJKLHqjYoW9M+1q0CGHJRT5u2CnZWb8Qr1DpLkkusQ6ru+cDAG12so\n"
+ "IpDQh7IyB2JosVJi9ogekYxJ3O1p5WlFUi0X19DMoer9FJ9J7/3s4enGJ/yMBeuu\n"
+ "jLVRkjMJhsfhj3Cykon+8Rrf520wSmBg1dpJQCXTwtb7DARgYRpZAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAPJH61Ir6XSu9/Q9tXGaINbXO1GWQQUXtwh6TX9lxnaCNDLGnxiY+ZZw\n"
+ "+Vqj3LAQoMrz1PpPsF5e0VIxok10Vc8y4cWC+kIitcecut4vWC5FYTtVVP9wtlyg\n"
+ "YCcVOVhtFQxtLiGqprl84+EVxrR7RQVCMLNDUXIgxAfdnS24eBPDAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "ipv6-policy kfdslfdfj sdjfk sdfjsdf\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "XWorzVT5Owg+QcsBtksiUNtpQQ5+IdvbsN+0O9FbFtGZeaeBAbPJ3Poz+KFCUjZY\n"
+ "DeDAiu1cVgODx2St+99LpwEuIBx78HaD8RYU8tHx8LoA+mGC43ogQQS9lmfxzvP5\n"
+ "eT5WXhkOS5AZ8LZOCOmT+tj/LkSXev2x/NC9+Vc1HPo=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_FAMILY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM62QoRxSPnm+ZM4fv9p03Qqbz5SzhXYSNjKWqylBruaofTw6oIM8DtX\n"
+ "7QnrEe/ou/WtfB+swV/2rt/r0EzmeWBWuDmuSUrN5TC2AdOi9brSJMgXVW6VW77X\n"
+ "fuIlLd5DVSId2zs3cKLDqp36CUsooA9sS6I5HrvW9QDf3VS3pGBtAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANg1trpnRzkCi4t4Z4qnBKF612H5A3Zrjg7Jo2b3ajUnON/KEuLPTc3t\n"
+ "PPN0W4qqeCMmVQEuxf3DRbTPS20ycy4B/JDWYfxCNwuj5YAx04REf7T0Hlx7Aee/\n"
+ "sHEQBhIBfasA2idhTh3cAm4DMYn+00BqjxF6jmyRA0hyntEABabrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "family aaaa,bbbb\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "xOgP3liKF/WEvwbbGzUUVRZ5WPrOI7jex8pZU/02UEnHjit7vCf9fsUcvkeo0xjz\n"
+ "n3FQHIO1iAJS7dEaEM4nz6wtPUb2iXSU9QajkGBkJ9/V7NHMFIU3FGfP47PIJJkd\n"
+ "nz5INoS+AsE7PmnDjUMm1H45TCCl8N8y4FO6TtN7p8I=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_EI_DIGEST[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAJ8Sn8AxBRbeIAHUvaKjqmcYOvXz7YFlpYFiVHp/cn+l+KUkIYTOFQXf\n"
+ "K8AtwjmJ4R2qJIbNlY/6oZGFbizt/B+WPuWsTj+8ACEEDlxx0ibg3EJRB8AZYiWv\n"
+ "0zC/loiUvHm6fXF5ghvDr9BQzEUo9kBk5haoHwROtGawr1+vOEiNAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMzok3ZJtLjXOC8RKltXI8xulwn/ctCvQFHImR0+ccA1uBxaZNYgiIcc\n"
+ "q8XngROfV8xEgDbYPiWiLXJOMSwOd7hfs3YzRWF+LKftYs8PuRyMJcCoBjOPZ4QX\n"
+ "HRfTetEvu2SijZMby+lkqpZg2nuF/ipsXUjrabRZdNiIGhC451vdAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "extra-info-digest not-a-digest\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "c/6zAxO04izQvqdM4bZVGE+ak0nna5pz9XZizFkieZEDWGzWQuVMhXyL5sbsFbsx\n"
+ "6Hn7DvNRYR/2nA0teDeRyIHMoMHi76te5X9OFDgaeUVCbyJ8h/KZYfPnN86IDbsR\n"
+ "dCSmj9kX55keu64ccCAH1CqwcN/UsbplXiJJVG5pTfI=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_ZERO_ORPORT[] =
+ "router fred 127.0.0.1 0 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMc4MOhLG3PKPgc+xYVf4eScWzeOf8wq7Cb/JxZm50G0LuvVbhHtHEZX\n"
+ "VOSHI7mLE1ifakJvCFJRLobMU7lU0yhn18/nKl2Cu5NfFHHeF/NieUBSxBGb2wD6\n"
+ "aM1azheXrRqvDVVfbI0DLc/XfQC/YNiohOsQ/c9C6wuffA4+Sg85AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALBWdl9/Vft+NQKQlg5kgvZo+krnhNTRVQojWtUEzom4TFIT+NNKJyMG\n"
+ "reQXcNdzNptTB0aOBGGwqAesqzsZ2Hje699NsDe7hdl7Sb5yhKDqtdQY6yDXJUFt\n"
+ "zqpAUkmYMLe2p3kPiWefNso56KYXrZrlNAiIS/FhQ5cmuMC2jPydAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "gFg08P9A6QNQjURlebfdhU3DSV0BeM0j2SFza1jF9JcBOWDRmT8FvYFK1B3js6jK\n"
+ "8LNV8JOUssv14z5CnUY9CO1BD0xSl+vGlSS4VOXD7rxui8IoWgnqnZsitq+Qzs95\n"
+ "wgFKhHI/49NHyWHX5IMQpeicg0T7Qa6qwnUvspH62p8=\n"
+ "-----END SIGNATURE-----\n"
+ ;
diff --git a/src/test/include.am b/src/test/include.am
index 4020ac4..8d05b3b 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -76,6 +76,8 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
noinst_HEADERS+= \
src/test/test.h \
src/test/test_descriptors.inc \
+ src/test/example_extrainfo.inc \
+ src/test/failing_routerdescs.inc \
src/test/ed25519_vectors.inc
if CURVE25519_ENABLED
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 935c82e..db57c2a 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -294,6 +294,279 @@ test_dir_formats(void *arg)
tor_free(dir2); /* And more !*/
}
+#include "failing_routerdescs.inc"
+
+static void
+test_dir_routerparse_bad(void *arg)
+{
+ (void) arg;
+
+ int again;
+ routerinfo_t *ri = NULL;
+
+#define CHECK_OK(s) \
+ do { \
+ routerinfo_free(ri); \
+ ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, NULL); \
+ tt_assert(ri); \
+ } while (0)
+#define CHECK_FAIL(s, againval) \
+ do { \
+ routerinfo_free(ri); \
+ again = 999; \
+ ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, &again); \
+ tt_assert(ri == NULL); \
+ tt_int_op(again, ==, (againval)); \
+ } while (0)
+
+ CHECK_OK(EX_RI_MINIMAL);
+ CHECK_OK(EX_RI_MAXIMAL);
+
+ /* good annotations prepended */
+ routerinfo_free(ri);
+ ri = router_parse_entry_from_string(EX_RI_MINIMAL, NULL, 0, 0,
+ "@purpose bridge\n", NULL);
+ tt_assert(ri != NULL);
+ tt_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
+ routerinfo_free(ri);
+
+ /* bad annotations prepended. */
+ ri = router_parse_entry_from_string(EX_RI_MINIMAL,
+ NULL, 0, 0, "@purpose\n", NULL);
+ tt_assert(ri == NULL);
+
+ /* bad annotations on router. */
+ ri = router_parse_entry_from_string("@purpose\nrouter x\n", NULL, 0, 1,
+ NULL, NULL);
+ tt_assert(ri == NULL);
+
+ /* unwanted annotations on router. */
+ ri = router_parse_entry_from_string("@purpose foo\nrouter x\n", NULL, 0, 0,
+ NULL, NULL);
+ tt_assert(ri == NULL);
+
+ /* No signature. */
+ ri = router_parse_entry_from_string("router x\n", NULL, 0, 0,
+ NULL, NULL);
+ tt_assert(ri == NULL);
+
+ /* Not a router */
+ routerinfo_free(ri);
+ ri = router_parse_entry_from_string("hello\n", NULL, 0, 0, NULL, NULL);
+ tt_assert(ri == NULL);
+
+ CHECK_FAIL(EX_RI_BAD_SIG1, 1);
+ CHECK_FAIL(EX_RI_BAD_SIG2, 1);
+ CHECK_FAIL(EX_RI_BAD_TOKENS, 0);
+ CHECK_FAIL(EX_RI_BAD_PUBLISHED, 0);
+ CHECK_FAIL(EX_RI_NEG_BANDWIDTH, 0);
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH, 0);
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH2, 0);
+ CHECK_FAIL(EX_RI_BAD_ONIONKEY1, 0);
+ CHECK_FAIL(EX_RI_BAD_ONIONKEY2, 0);
+ CHECK_FAIL(EX_RI_BAD_PORTS, 0);
+ CHECK_FAIL(EX_RI_BAD_IP, 0);
+ CHECK_FAIL(EX_RI_BAD_DIRPORT, 0);
+ CHECK_FAIL(EX_RI_BAD_NAME2, 0);
+ CHECK_FAIL(EX_RI_BAD_UPTIME, 0);
+
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH3, 0);
+ CHECK_FAIL(EX_RI_BAD_NTOR_KEY, 0);
+ CHECK_FAIL(EX_RI_BAD_FINGERPRINT, 0);
+ CHECK_FAIL(EX_RI_MISMATCHED_FINGERPRINT, 0);
+ CHECK_FAIL(EX_RI_BAD_HAS_ACCEPT6, 0);
+ CHECK_FAIL(EX_RI_BAD_NO_EXIT_POLICY, 0);
+ CHECK_FAIL(EX_RI_BAD_IPV6_EXIT_POLICY, 0);
+ CHECK_FAIL(EX_RI_BAD_FAMILY, 0);
+ CHECK_FAIL(EX_RI_ZERO_ORPORT, 0);
+
+ /* This is allowed; we just ignore it. */
+ CHECK_OK(EX_RI_BAD_EI_DIGEST);
+
+#undef CHECK_FAIL
+#undef CHECK_OK
+ done:
+ routerinfo_free(ri);
+}
+
+#include "example_extrainfo.inc"
+
+static void
+test_dir_extrainfo_parsing(void *arg)
+{
+ (void) arg;
+
+#define CHECK_OK(s) \
+ do { \
+ extrainfo_free(ei); \
+ ei = extrainfo_parse_entry_from_string((s), NULL, 0, map, NULL); \
+ tt_assert(ei); \
+ } while (0)
+#define CHECK_FAIL(s, againval) \
+ do { \
+ extrainfo_free(ei); \
+ again = 999; \
+ ei = extrainfo_parse_entry_from_string((s), NULL, 0, map, &again); \
+ tt_assert(ei == NULL); \
+ tt_int_op(again, ==, (againval)); \
+ } while (0)
+#define ADD(name) \
+ do { \
+ ri = tor_malloc_zero(sizeof(routerinfo_t)); \
+ crypto_pk_t *pk = ri->identity_pkey = crypto_pk_new(); \
+ tt_assert(! crypto_pk_read_public_key_from_string(pk, \
+ name##_KEY, strlen(name##_KEY))); \
+ tt_int_op(0,==,base16_decode(d, 20, name##_FP, strlen(name##_FP))); \
+ digestmap_set((digestmap_t*)map, d, ri); \
+ ri = NULL; \
+ } while (0)
+
+ routerinfo_t *ri = NULL;
+ char d[20];
+ struct digest_ri_map_t *map = NULL;
+ extrainfo_t *ei = NULL;
+ int again;
+
+ CHECK_OK(EX_EI_MINIMAL);
+ tt_assert(ei->pending_sig);
+ CHECK_OK(EX_EI_MAXIMAL);
+ tt_assert(ei->pending_sig);
+
+ map = (struct digest_ri_map_t *)digestmap_new();
+ ADD(EX_EI_MINIMAL);
+ ADD(EX_EI_MAXIMAL);
+ ADD(EX_EI_BAD_FP);
+ ADD(EX_EI_BAD_NICKNAME);
+ ADD(EX_EI_BAD_TOKENS);
+ ADD(EX_EI_BAD_START);
+ ADD(EX_EI_BAD_PUBLISHED);
+
+ CHECK_OK(EX_EI_MINIMAL);
+ tt_assert(!ei->pending_sig);
+ CHECK_OK(EX_EI_MAXIMAL);
+ tt_assert(!ei->pending_sig);
+
+ CHECK_FAIL(EX_EI_BAD_SIG1,1);
+ CHECK_FAIL(EX_EI_BAD_SIG2,1);
+ CHECK_FAIL(EX_EI_BAD_SIG3,1);
+ CHECK_FAIL(EX_EI_BAD_FP,0);
+ CHECK_FAIL(EX_EI_BAD_NICKNAME,0);
+ CHECK_FAIL(EX_EI_BAD_TOKENS,0);
+ CHECK_FAIL(EX_EI_BAD_START,0);
+ CHECK_FAIL(EX_EI_BAD_PUBLISHED,0);
+
+#undef CHECK_OK
+#undef CHECK_FAIL
+
+ done:
+ routerinfo_free(ri);
+ /* XXXX elements should get freed too */
+ digestmap_free((digestmap_t*)map, NULL);
+}
+
+static void
+test_dir_parse_router_list(void *arg)
+{
+ (void) arg;
+ smartlist_t *invalid = smartlist_new();
+ smartlist_t *dest = smartlist_new();
+ smartlist_t *chunks = smartlist_new();
+ int dest_has_ri = 1;
+ char *list = NULL;
+ const char *cp;
+ digestmap_t *map = NULL;
+ char *mem_op_hex_tmp = NULL;
+ routerinfo_t *ri = NULL;
+ char d[DIGEST_LEN];
+
+ smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); // ri 0
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); // bad ri 0
+ smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); // ei 0
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_SIG2)); // bad ei --
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));// bad ei 0
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG1)); // bad ri --
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); // bad ei 1
+ smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); // ri 1
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_FAMILY)); // bad ri 1
+ smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); // ei 1
+
+ list = smartlist_join_strings(chunks, "", 0, NULL);
+
+ /* First, parse the routers. */
+ cp = list;
+ tt_int_op(0,==,
+ router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
+ 0, 0, NULL, invalid));
+ tt_int_op(2, ==, smartlist_len(dest));
+ tt_ptr_op(cp, ==, list + strlen(list));
+
+ routerinfo_t *r = smartlist_get(dest, 0);
+ tt_mem_op(r->cache_info.signed_descriptor_body, ==,
+ EX_RI_MINIMAL, strlen(EX_RI_MINIMAL));
+ r = smartlist_get(dest, 1);
+ tt_mem_op(r->cache_info.signed_descriptor_body, ==,
+ EX_RI_MAXIMAL, strlen(EX_RI_MAXIMAL));
+
+ tt_int_op(2, ==, smartlist_len(invalid));
+ test_memeq_hex(smartlist_get(invalid, 0),
+ "ab9eeaa95e7d45740185b4e519c76ead756277a9");
+ test_memeq_hex(smartlist_get(invalid, 1),
+ "9a651ee03b64325959e8f1b46f2b689b30750b4c");
+
+ /* Now tidy up */
+ SMARTLIST_FOREACH(dest, routerinfo_t *, ri, routerinfo_free(ri));
+ SMARTLIST_FOREACH(invalid, uint8_t *, d, tor_free(d));
+ smartlist_clear(dest);
+ smartlist_clear(invalid);
+
+ /* And check extrainfos. */
+ dest_has_ri = 0;
+ map = (digestmap_t*)router_get_routerlist()->identity_map;
+ ADD(EX_EI_MINIMAL);
+ ADD(EX_EI_MAXIMAL);
+ ADD(EX_EI_BAD_NICKNAME);
+ ADD(EX_EI_BAD_PUBLISHED);
+ cp = list;
+ tt_int_op(0,==,
+ router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
+ 1, 0, NULL, invalid));
+ tt_int_op(2, ==, smartlist_len(dest));
+ extrainfo_t *e = smartlist_get(dest, 0);
+ tt_mem_op(e->cache_info.signed_descriptor_body, ==,
+ EX_EI_MAXIMAL, strlen(EX_EI_MAXIMAL));
+ e = smartlist_get(dest, 1);
+ tt_mem_op(e->cache_info.signed_descriptor_body, ==,
+ EX_EI_MINIMAL, strlen(EX_EI_MINIMAL));
+
+ tt_int_op(2, ==, smartlist_len(invalid));
+ test_memeq_hex(smartlist_get(invalid, 0),
+ "d5df4aa62ee9ffc9543d41150c9864908e0390af");
+ test_memeq_hex(smartlist_get(invalid, 1),
+ "f61efd2a7f4531f3687a9043e0de90a862ec64ba");
+
+ done:
+ tor_free(list);
+ if (dest_has_ri)
+ SMARTLIST_FOREACH(dest, routerinfo_t *, rt, routerinfo_free(rt));
+ else
+ SMARTLIST_FOREACH(dest, extrainfo_t *, ei, extrainfo_free(ei));
+ smartlist_free(dest);
+ SMARTLIST_FOREACH(invalid, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ routerinfo_free(ri);
+ /* XXXX this leaks: */
+ if (map) {
+ digestmap_free((digestmap_t*)map, NULL);
+ router_get_routerlist()->identity_map =
+ (struct digest_ri_map_t*)digestmap_new();
+ }
+ tor_free(mem_op_hex_tmp);
+
+#undef ADD
+}
+
static void
test_dir_versions(void *arg)
{
@@ -2393,6 +2666,9 @@ test_dir_http_handling(void *args)
struct testcase_t dir_tests[] = {
DIR_LEGACY(nicknames),
DIR_LEGACY(formats),
+ DIR(routerparse_bad, 0),
+ DIR(extrainfo_parsing, 0),
+ DIR(parse_router_list, TT_FORK),
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index f7e87ac..9073034 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -12,6 +12,10 @@
#include "test.h"
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/pem.h>
+
#ifdef _WIN32
/* For mkdir() */
#include <direct.h>
@@ -391,10 +395,234 @@ test_md_generate(void *arg)
routerinfo_free(ri);
}
+/* Taken at random from my ~/.tor/cached-microdescs file and then
+ * hand-munged */
+static const char MD_PARSE_TEST_DATA[] =
+ /* Good 0 */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANsKd1GRfOuSR1MkcwKqs6SVy4Gi/JXplt/bHDkIGm6Q96TeJ5uyVgUL\n"
+ "DBr/ij6+JqgVFeriuiMzHKREytzjdaTuKsKBFFpLwb+Ppcjr5nMIH/AR6/aHO8hW\n"
+ "T3B9lx5T6Kl7CqZ4yqXxYRHzn50EPTIZuz0y9se4J4gi9mLmL+pHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept 20-23,43,53,79-81,88,110,143,194,220,443,464,531,543-544\n"
+ "id rsa1024 GEo59/iR1GWSIWZDzXTd5QxtqnU\n"
+ /* Bad 0: I've messed with the onion-key in the second one. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMr4o/pflVwscx11vC1AKEADlKEqnhpvCIjAEzNEenMhvGQHRlA0EXLC\n"
+ "7G7O5bhnCwEHqK8Pvg8cuX/fD8v08TF1EVPhwPa0UI6ab8KnPP2F!!!!!!b92DG7EQIk3q\n"
+ "d68Uxp7E9/t3v1WWZjzDqvEe0par6ul+DKW6HMlTGebFo5Q4e8R1AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key 761Dmm27via7lXygNHM3l+oJLrYU2Nye0Uz4pkpipyY=\n"
+ "p accept 53\n"
+ "id rsa1024 3Y4fwXhtgkdGDZ5ef5mtb6TJRQQ\n"
+ /* Good 1 */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANsMSjVi3EX8ZHfm/dvPF6KdVR66k1tVul7Jp+dDbDajBYNhgKRzVCxy\n"
+ "Yac1CBuQjOqK89tKap9PQBnhF087eDrfaZDqYTLwB2W2sBJncVej15WEPXPRBifo\n"
+ "iFZ8337kgczkaY+IOfSuhtbOUyDOoDpRJheIKBNq0ZiTqtLbbadVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key ncfiHJjSgdDEW/gc6q6/7idac7j+x7ejQrRm6i75pGA=\n"
+ "p accept 443,6660-6669,6697,7000-7001\n"
+ "id rsa1024 XXuLzw3mfBELEq3veXoNhdehwD4\n"
+ /* Good 2 */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANQfBlrHrh9F/CAOytrNFgi0ikWMW/HZxuoszF9X+AQ+MudR8bcxxOGl\n"
+ "1RFwb74s8E3uuzrCkNFvSw9Ar1L02F2DOX0gLsxEGuYC4Ave9NUteGqSqDyEJQUJ\n"
+ "KlfxCPn2qC9nvNT7wR/Dg2WRvAEKnJmkpb57N3+WSAOPLjKOFEz3AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
+ "id rsa1024 6y60AEI9a1PUUlRPO0YQT9WzrjI\n"
+ /* Bad 1: Here I've messed with the ntor key */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAPjy2HacU3jDNO5nTOFGSwNa0qKCNn4yhtrDVcAJ5alIQeBWZZGJLZ0q\n"
+ "Cqylw1vYqxu8E09g+QXXFbAgBv1U9TICaATxrIJhIJzc8TJPhqJemp1kq0DvHLDx\n"
+ "mxwlkNnCD/P5NS+JYB3EjOlU9EnSKUWNU61+Co344m2JqhEau40vAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key 4i2Fp9JHTUr1uQs0pxD5j5spl4/RG56S2P0gQxU=\n"
+ "id rsa1024 nMRmNEGysA0NmlALVaUmI7D5jLU\n"
+ /* Good 3: I've added a weird token in this one. This shouldn't prevent
+ * it parsing */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKmosxudyNA/yJNz3S890VqV/ebylzoD11Sc0b/d5tyNNaNZjcYy5vRD\n"
+ "kwyxFRMbP2TLZQ1zRfNwY7IDnYjU2SbW0pxuM6M8WRtsmx/YOE3kHMVAFJNrTUqU\n"
+ "6D1zB3IiRDS5q5+NoRxwqo+hYUck60O3WTwEoqb+l3lvXeu7z9rFAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "flux-capacitor 1.21 GW\n"
+ "ntor-onion-key MWBoEkl+RlBiGX44XKIvTSqbznTNZStOmUYtcYRQQyY=\n"
+ "id rsa1024 R+A5O9qRvRac4FT3C4L2QnFyxsc\n"
+ /* Good 4: Here I've made the 'id rsa' token odd. It should still parse
+ * just fine. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOh+WMkdNe/Pkjb8UjQyfLOlFgpuVFrxAIGnJsmWWx0yBE97DQxGyh2n\n"
+ "h8G5OJZHRarJQyCIf7vpZQAi0oP0OkGGaCaDQsM+D8TnqhnU++RWGnMqY/cXxPrL\n"
+ "MEq+n6aGiLmzkO7ah8yorZpoREk4GqLUIN89/tHHGOhJL3c4CPGjAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
+ "id rsa1234 jlqAKFD2E7uMKv+8TmKSeo7NBho\n"
+ /* Good 5: Extra id type. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMdgPPc5uaw4y/q+SUTN/I8Y+Gvdx9kKgWV4dmDGJ0mxsVZmo1v6+v3F\n"
+ "12M2f9m99G3WB8F8now29C+9XyEv8MBHj1lHRdUFHSQes3YTFvDNlgj+FjLqO5TJ\n"
+ "adOOmfu4DCUUtUEDyQKbNVL4EkMTXY73omTVsjcH3xxFjTx5wixhAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AAVnWZcnDbxasdZwKqb4fL6O9sZV+XsRNHTpNd1YMz8=\n"
+ "id rsa1024 72EfBL11QuwX2vU8y+p9ExGfGEg\n"
+ "id expolding hedgehog 0+A5O9qRvRac4FT3C4L2QnFyxsc\n"
+ /* Good 6: I've given this a bogus policy. It should parse. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALNuufwhPMF8BooxYMNvhYJMPqUB8hQDt8wGmPKphJcD1sVD1i4gAZM2\n"
+ "HIo+zUBlljDrRWL5NzVzd1yxUJAiQxvXS5dRRFY3B70M7wTVpXw53xe0/BM5t1AX\n"
+ "n0MFk7Jl6XIKMlzRalZvmMvE/odtyWXkP4Nd1MyZ1QcIwrQ2iwyrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p condone 1-10\n"
+ "ntor-onion-key 2/nMJ+L4dd/2GpMyTYjz3zC59MvQy4MIzJZhdzKHekg=\n"
+ "id rsa1024 FHyh10glEMA6MCmBb5R9Y+X/MhQ\n"
+ /* Good 7: I've given this one another sort of odd policy. Should parse. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKcd3FmQ8iAADghyvX8eca0ePqtJ2w1IDdUdTlf5Y/8+OMdp//sD01yC\n"
+ "YmiX45LK5ge1O3AzcakYCO6fb3pyIqvXdvm24OjyYZELQ40cmKSLjdhcSf4Fr/N9\n"
+ "uR/CkknR9cEePu1wZ5WBIGmGdXI6s7t3LB+e7XFyBYAx6wMGlnX7AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept frogs-mice\n"
+ "ntor-onion-key AMxvhaQ1Qg7jBJFoyHuPRgETvLbFmJ194hExV24FuAI=\n"
+ "family $D8CFEA0D996F5D1473D2063C041B7910DB23981E\n"
+ "id rsa1024 d0VVZC/cHh1P3y4MMbfKlQHFycc\n"
+ /* Good 8: This one has the ntor-onion-key without terminating =. That's
+ * allowed. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL438YfjrJE2SPqkkXeQwICygu8KNO54Juj6sjqk5hgsiazIWMOBgbaX\n"
+ "LIRqPNGaiSq01xSqwjwCBCfwZYT/nSdDBqj1h9aoR8rnjxZjyQ+m3rWpdDqeCDMx\n"
+ "I3NgZ5w4bNX4poRb42lrV6NmQiFdjzpqszVbv5Lpn2CSKu32CwKVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key UKL6Dnj2KwYsFlkCvOkXVatxvOPB4MaxqwPQQgZMTwI\n"
+ "id rsa1024 FPIXc6k++JnKCtSKWUxaR6oXEKs\n"
+ /* Good 9: Another totally normal one.*/
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANNGIKRd8PFNXkJ2JPV1ohDMFNbJwKbwybeieaQFjtU9KWedHCbr+QD4\n"
+ "B6zNY5ysguNjHNnlq2f6D09+uhnfDBON8tAz0mPQH/6JqnOXm+EiUn+8bN0E8Nke\n"
+ "/i3GEgDeaxJJMNQcpsJvmmSmKFOlYy9Fy7ejAjTGqtAnqOte7BnTAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key gUsq3e5iYgsQQvyxINtLzBpHxmIt5rtuFlEbKfI4gFk=\n"
+ "id rsa1024 jv+LdatDzsMfEW6pLBeL/5uzwCc\n"
+ /* Bad 2: RSA key has bad exponent of 3. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGHAoGBAMMTWtvPxYnUNJ5Y7B+XENcpxzPoGstrdiUszCBS+/42xvluLJ+JDSdR\n"
+ "qJaMD6ax8vKAeLS5C6O17MNdG2VldlPRbtgl41MXsOoUqEJ+nY9e3WG9Snjp47xC\n"
+ "zmWIfeduXSavIsb3a43/MLIz/9qO0TkgAAiuQr79JlwKhLdzCqTLAgED\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key NkRB4wTUFogiVp5jYmjGORe2ffb/y5Kk8Itw8jdzMjA=\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
+ "id rsa1024 fKvYjP7TAjCC1FzYee5bYAwYkoDg\n"
+ /* Bad 3: Bogus annotation */
+ "@last-listed with strange aeons\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALcRBFNCZtpd2TFJysU77/fJMFzKisRQEBOtDGtTZ2Bg4aEGosssa0Id\n"
+ "YtUagRLYle08QVGvGB+EHBI5qf6Ah2yPH7k5QiN2a3Sq+nyh85dXKPazBGBBbM+C\n"
+ "DOfDauV02CAnADNMLJEf1voY3oBVvYyIsmHxn5i1R19ZYIiR8NX5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key m4xcFXMWMjCvZDXq8FT3XmS0EHYseGOeu+fV+6FYDlk=\n"
+ "p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
+ "id rsa1024 SSbfNE9vmaiwRKH+eqNAkiKQhds\n"
+ /* Good 10: Normal, with added ipv6 address and added other address */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
+ "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
+ "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "a [::1:2:3:4]:9090\n"
+ "a 18.0.0.1:9999\n"
+ "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
+ "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
+ "p6 allow 80\n"
+ ;
+
+/** More tests for parsing different kinds of microdescriptors, and getting
+ * invalid digests trackd from them. */
+static void
+test_md_parse(void *arg)
+{
+ (void) arg;
+ char *mem_op_hex_tmp = NULL;
+ smartlist_t *invalid = smartlist_new();
+
+ smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
+ NULL, 1, SAVED_NOWHERE,
+ invalid);
+ tt_int_op(smartlist_len(mds), ==, 11);
+ tt_int_op(smartlist_len(invalid), ==, 4);
+
+ test_memeq_hex(smartlist_get(invalid,0),
+ "5d76bf1c6614e885614a1e0ad074e1ab"
+ "4ea14655ebeefb1736a71b5ed8a15a51");
+ test_memeq_hex(smartlist_get(invalid,1),
+ "2fde0ee3343669c2444cd9d53cbd39c6"
+ "a7d1fc0513513e840ca7f6e68864b36c");
+ test_memeq_hex(smartlist_get(invalid,2),
+ "20d1576c5ab11bbcff0dedb1db4a3cfc"
+ "c8bc8dd839d8cbfef92d00a1a7d7b294");
+ test_memeq_hex(smartlist_get(invalid,3),
+ "074770f394c73dbde7b44412e9692add"
+ "691a478d4727f9804b77646c95420a96");
+
+ /* Spot-check the valid ones. */
+ const microdesc_t *md = smartlist_get(mds, 5);
+ test_memeq_hex(md->digest,
+ "54bb6d733ddeb375d2456c79ae103961"
+ "da0cae29620375ac4cf13d54da4d92b3");
+ tt_int_op(md->last_listed, ==, 0);
+ tt_int_op(md->saved_location, ==, SAVED_NOWHERE);
+ tt_int_op(md->no_save, ==, 0);
+ tt_uint_op(md->held_in_map, ==, 0);
+ tt_uint_op(md->held_by_nodes, ==, 0);
+ tt_assert(md->onion_curve25519_pkey);
+
+ md = smartlist_get(mds, 6);
+ test_memeq_hex(md->digest,
+ "53f740bd222ab37f19f604b1d3759aa6"
+ "5eff1fbce9ac254bd0fa50d4af9b1bae");
+ tt_assert(! md->exit_policy);
+
+ md = smartlist_get(mds, 8);
+ test_memeq_hex(md->digest,
+ "a0a155562d8093d8fd0feb7b93b7226e"
+ "17f056c2142aab7a4ea8c5867a0376d5");
+ tt_assert(md->onion_curve25519_pkey);
+
+ md = smartlist_get(mds, 10);
+ test_memeq_hex(md->digest,
+ "409ebd87d23925a2732bd467a92813c9"
+ "21ca378fcb9ca193d354c51550b6d5e9");
+ tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
+ tt_int_op(md->ipv6_orport, ==, 9090);
+
+ done:
+ SMARTLIST_FOREACH(mds, microdesc_t *, md, microdesc_free(md));
+ smartlist_free(mds);
+ SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
+ smartlist_free(invalid);
+ tor_free(mem_op_hex_tmp);
+}
+
struct testcase_t microdesc_tests[] = {
{ "cache", test_md_cache, TT_FORK, NULL, NULL },
{ "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
{ "generate", test_md_generate, 0, NULL, NULL },
+ { "parse", test_md_parse, 0, NULL, NULL },
END_OF_TESTCASES
};
1
0

[tor/master] Treat unparseable (micro)descriptors and extrainfos as undownloadable
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit a30594605e60d3a581f21c71a7d9e7a062800e3d
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Oct 3 10:55:50 2014 -0400
Treat unparseable (micro)descriptors and extrainfos as undownloadable
One pain point in evolving the Tor design and implementing has been
adding code that makes clients reject directory documents that they
previously would have accepted, if those descriptors actually exist.
When this happened, the clients would get the document, reject it,
and then decide to try downloading it again, ad infinitum. This
problem becomes particularly obnoxious with authorities, since if
some authorities accept a descriptor that others don't, the ones
that don't accept it would go crazy trying to re-fetch it over and
over. (See for example ticket #9286.)
This patch tries to solve this problem by tracking, if a descriptor
isn't parseable, what its digest was, and whether it is invalid
because of some flaw that applies to the portion containing the
digest. (This excludes RSA signature problems: RSA signatures
aren't included in the digest. This means that a directory
authority can still put another directory authority into a loop by
mentioning a descriptor, and then serving that descriptor with an
invalid RSA signatures. But that would also make the misbehaving
directory authority get DoSed by the server it's attacking, so it's
not much of an issue.)
We already have a mechanism to mark something undownloadable with
downloadstatus_mark_impossible(); we use that here for
microdescriptors, extrainfos, and router descriptors.
Unit tests to follow in another patch.
Closes ticket #11243.
---
changes/ticket11243 | 7 ++++
src/or/dirserv.c | 4 +--
src/or/dirvote.c | 4 +--
src/or/microdesc.c | 41 +++++++++++++++++++++--
src/or/networkstatus.c | 2 +-
src/or/or.h | 1 +
src/or/router.c | 6 ++--
src/or/routerlist.c | 55 +++++++++++++++++++++++++++---
src/or/routerparse.c | 82 +++++++++++++++++++++++++++++++++------------
src/or/routerparse.h | 12 ++++---
src/test/test_dir.c | 4 +--
src/test/test_microdesc.c | 2 +-
12 files changed, 178 insertions(+), 42 deletions(-)
diff --git a/changes/ticket11243 b/changes/ticket11243
new file mode 100644
index 0000000..0b470ba
--- /dev/null
+++ b/changes/ticket11243
@@ -0,0 +1,7 @@
+ o Major features (downloading):
+ - Upon receiving a server descriptor, microdescriptor, extrainfo
+ document, or other object that is unparseable, if its digest
+ matches what we expected, then mark it as not to be downloaded
+ again. Previously, when we got a descriptor we didn't like, we
+ would keep trying to download it over and over. Closes ticket
+ 11243.
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 374cfa6..be01e4a 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -478,7 +478,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
s = desc;
list = smartlist_new();
if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0,
- annotation_buf)) {
+ annotation_buf, NULL)) {
SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
msg_out = NULL;
tor_assert(ri->purpose == purpose);
@@ -494,7 +494,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
s = desc;
if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0,
- NULL)) {
+ NULL, NULL)) {
SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
msg_out = NULL;
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 8a0fdf6..6637462 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -3288,8 +3288,8 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
{
smartlist_t *lst = microdescs_parse_from_string(output,
- output+strlen(output), 0,
- SAVED_NOWHERE);
+ output+strlen(output), 0,
+ SAVED_NOWHERE, NULL);
if (smartlist_len(lst) != 1) {
log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse.");
SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md));
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 576fed0..8a2ece2 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -149,10 +149,11 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
{
smartlist_t *descriptors, *added;
const int allow_annotations = (where != SAVED_NOWHERE);
+ smartlist_t *invalid_digests = smartlist_new();
descriptors = microdescs_parse_from_string(s, eos,
allow_annotations,
- where);
+ where, invalid_digests);
if (listed_at != (time_t)-1) {
SMARTLIST_FOREACH(descriptors, microdesc_t *, md,
md->last_listed = listed_at);
@@ -161,8 +162,23 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
digestmap_t *requested; /* XXXX actually we should just use a
digest256map */
requested = digestmap_new();
+ /* Set requested[d] to 1 for every md we requested. */
SMARTLIST_FOREACH(requested_digests256, const char *, cp,
digestmap_set(requested, cp, (void*)1));
+ /* Set requested[d] to 3 for every md we requested which we will never be
+ * able to parse. Remove the ones we didn't request from invalid_digests.
+ */
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, cp) {
+ if (digestmap_get(requested, cp)) {
+ digestmap_set(requested, cp, (void*)3);
+ } else {
+ tor_free(cp);
+ SMARTLIST_DEL_CURRENT(invalid_digests, cp);
+ }
+ } SMARTLIST_FOREACH_END(cp);
+ /* Update requested[d] to 2 for the mds we asked for and got. Delete the
+ * ones we never requested from the 'descriptors' smartlist.
+ */
SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) {
if (digestmap_get(requested, md->digest)) {
digestmap_set(requested, md->digest, (void*)2);
@@ -172,8 +188,11 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
SMARTLIST_DEL_CURRENT(descriptors, md);
}
} SMARTLIST_FOREACH_END(md);
+ /* Remove the ones we got or the invalid ones from requested_digests256.
+ */
SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) {
- if (digestmap_get(requested, cp) == (void*)2) {
+ void *status = digestmap_get(requested, cp);
+ if (status == (void*)2 || status == (void*)3) {
tor_free(cp);
SMARTLIST_DEL_CURRENT(requested_digests256, cp);
}
@@ -181,6 +200,24 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
digestmap_free(requested, NULL);
}
+ /* For every requested microdescriptor that was unparseable, mark it
+ * as not to be retried. */
+ if (smartlist_len(invalid_digests)) {
+ networkstatus_t *ns =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ if (ns) {
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, d) {
+ routerstatus_t *rs =
+ router_get_mutable_consensus_status_by_descriptor_digest(ns, d);
+ if (rs && tor_memeq(d, rs->descriptor_digest, DIGEST256_LEN)) {
+ download_status_mark_impossible(&rs->dl_status);
+ }
+ } SMARTLIST_FOREACH_END(d);
+ }
+ }
+ SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid_digests);
+
added = microdescs_add_list_to_cache(cache, descriptors, where, no_save);
smartlist_free(descriptors);
return added;
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index c7bed9b..e61d1b4 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1123,7 +1123,7 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
- DIGEST_LEN)) {
+ DIGEST_LEN)) { /* XXXX Change this to digest256_len */
/* And the same descriptor too! */
memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t));
}
diff --git a/src/or/or.h b/src/or/or.h
index 54cee46..2f1307d 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1958,6 +1958,7 @@ typedef struct download_status_t {
uint8_t n_download_failures; /**< Number of failures trying to download the
* most recent descriptor. */
download_schedule_bitfield_t schedule : 8;
+
} download_status_t;
/** If n_download_failures is this high, the download can never happen. */
diff --git a/src/or/router.c b/src/or/router.c
index dbe985a..5d1d2ff 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -917,7 +917,7 @@ init_keys(void)
}
if (mydesc) {
was_router_added_t added;
- ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL);
+ ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL, NULL);
if (!ri) {
log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
return -1;
@@ -2447,7 +2447,7 @@ router_dump_router_to_string(routerinfo_t *router,
const char *cp;
routerinfo_t *ri_tmp;
cp = s_dup = tor_strdup(output);
- ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL);
+ ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL, NULL);
if (!ri_tmp) {
log_err(LD_BUG,
"We just generated a router descriptor we can't parse.");
@@ -2729,7 +2729,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
s = smartlist_join_strings(chunks, "", 0, NULL);
cp = s_dup = tor_strdup(s);
- ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL);
+ ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL, NULL);
if (!ei_tmp) {
if (write_stats_to_extrainfo) {
log_warn(LD_GENERAL, "We just generated an extra-info descriptor "
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 22489a4..d8e26b0 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -3251,7 +3251,7 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd)
ri = router_parse_entry_from_string(body,
body+sd->signed_descriptor_len+sd->annotations_len,
- 0, 1, NULL);
+ 0, 1, NULL, NULL);
if (!ri)
return NULL;
memcpy(&ri->cache_info, sd, sizeof(signed_descriptor_t));
@@ -3807,7 +3807,8 @@ router_load_single_router(const char *s, uint8_t purpose, int cache,
"@source controller\n"
"@purpose %s\n", router_purpose_to_string(purpose));
- if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0, annotation_buf))) {
+ if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0,
+ annotation_buf, NULL))) {
log_warn(LD_DIR, "Error parsing router descriptor; dropping.");
*msg = "Couldn't parse router descriptor.";
return -1;
@@ -3871,9 +3872,11 @@ router_load_routers_from_string(const char *s, const char *eos,
int from_cache = (saved_location != SAVED_NOWHERE);
int allow_annotations = (saved_location != SAVED_NOWHERE);
int any_changed = 0;
+ smartlist_t *invalid_digests = smartlist_new();
router_parse_list_from_string(&s, eos, routers, saved_location, 0,
- allow_annotations, prepend_annotations);
+ allow_annotations, prepend_annotations,
+ invalid_digests);
routers_update_status_from_consensus_networkstatus(routers, !from_cache);
@@ -3920,6 +3923,27 @@ router_load_routers_from_string(const char *s, const char *eos,
}
} SMARTLIST_FOREACH_END(ri);
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, const uint8_t *, bad_digest) {
+ /* This digest is never going to be parseable. */
+ base16_encode(fp, sizeof(fp), (char*)bad_digest, DIGEST_LEN);
+ if (requested_fingerprints && descriptor_digests) {
+ if (! smartlist_contains_string(requested_fingerprints, fp)) {
+ /* But we didn't ask for it, so we should assume shennanegans. */
+ continue;
+ }
+ smartlist_string_remove(requested_fingerprints, fp);
+ }
+ download_status_t *dls;
+ dls = router_get_dl_status_by_descriptor_digest((char*)bad_digest);
+ if (dls) {
+ log_info(LD_GENERAL, "Marking router with descriptor %s as unparseable, "
+ "and therefore undownloadable", fp);
+ download_status_mark_impossible(dls);
+ }
+ } SMARTLIST_FOREACH_END(bad_digest);
+ SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid_digests);
+
routerlist_assert_ok(routerlist);
if (any_changed)
@@ -3943,9 +3967,10 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
smartlist_t *extrainfo_list = smartlist_new();
const char *msg;
int from_cache = (saved_location != SAVED_NOWHERE);
+ smartlist_t *invalid_digests = smartlist_new();
router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1, 0,
- NULL);
+ NULL, invalid_digests);
log_info(LD_DIR, "%d elements to add", smartlist_len(extrainfo_list));
@@ -3966,6 +3991,28 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
}
} SMARTLIST_FOREACH_END(ei);
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, const uint8_t *, bad_digest) {
+ /* This digest is never going to be parseable. */
+ char fp[HEX_DIGEST_LEN+1];
+ base16_encode(fp, sizeof(fp), (char*)bad_digest, DIGEST_LEN);
+ if (requested_fingerprints) {
+ if (! smartlist_contains_string(requested_fingerprints, fp)) {
+ /* But we didn't ask for it, so we should assume shennanegans. */
+ continue;
+ }
+ smartlist_string_remove(requested_fingerprints, fp);
+ }
+ signed_descriptor_t *sd =
+ router_get_by_extrainfo_digest((char*)bad_digest);
+ if (sd) {
+ log_info(LD_GENERAL, "Marking extrainfo with descriptor %s as "
+ "unparseable, and therefore undownloadable", fp);
+ download_status_mark_impossible(&sd->ei_dl_status);
+ }
+ } SMARTLIST_FOREACH_END(bad_digest);
+ SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid_digests);
+
routerlist_assert_ok(routerlist);
router_rebuild_store(0, &router_get_routerlist()->extrainfo_store);
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 250d1cd..c7ebba2 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -911,7 +911,8 @@ find_start_of_next_router_or_extrainfo(const char **s_ptr,
* descriptor in the signed_descriptor_body field of each routerinfo_t. If it
* isn't SAVED_NOWHERE, remember the offset of each descriptor.
*
- * Returns 0 on success and -1 on failure.
+ * Returns 0 on success and -1 on failure. Adds a digest to
+ * <b>invalid_digests_out</b> for every entry that was unparseable or invalid.
*/
int
router_parse_list_from_string(const char **s, const char *eos,
@@ -919,7 +920,8 @@ router_parse_list_from_string(const char **s, const char *eos,
saved_location_t saved_location,
int want_extrainfo,
int allow_annotations,
- const char *prepend_annotations)
+ const char *prepend_annotations,
+ smartlist_t *invalid_digests_out)
{
routerinfo_t *router;
extrainfo_t *extrainfo;
@@ -939,6 +941,9 @@ router_parse_list_from_string(const char **s, const char *eos,
tor_assert(eos >= *s);
while (1) {
+ char raw_digest[DIGEST_LEN];
+ int have_raw_digest = 0;
+ int dl_again = 0;
if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
break;
@@ -955,18 +960,20 @@ router_parse_list_from_string(const char **s, const char *eos,
if (have_extrainfo && want_extrainfo) {
routerlist_t *rl = router_get_routerlist();
+ have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
extrainfo = extrainfo_parse_entry_from_string(*s, end,
saved_location != SAVED_IN_CACHE,
- rl->identity_map);
+ rl->identity_map, &dl_again);
if (extrainfo) {
signed_desc = &extrainfo->cache_info;
elt = extrainfo;
}
} else if (!have_extrainfo && !want_extrainfo) {
+ have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
router = router_parse_entry_from_string(*s, end,
saved_location != SAVED_IN_CACHE,
allow_annotations,
- prepend_annotations);
+ prepend_annotations, &dl_again);
if (router) {
log_debug(LD_DIR, "Read router '%s', purpose '%s'",
router_describe(router),
@@ -975,6 +982,9 @@ router_parse_list_from_string(const char **s, const char *eos,
elt = router;
}
}
+ if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
+ smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
+ }
if (!elt) {
*s = end;
continue;
@@ -1068,11 +1078,17 @@ find_single_ipv6_orport(const smartlist_t *list,
* around when caching the router.
*
* Only one of allow_annotations and prepend_annotations may be set.
+ *
+ * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
+ * if it's okay to try to download a descriptor with this same digest again,
+ * and 0 if it isn't. (It might not be okay to download it again if part of
+ * the part covered by the digest is invalid.)
*/
routerinfo_t *
router_parse_entry_from_string(const char *s, const char *end,
int cache_copy, int allow_annotations,
- const char *prepend_annotations)
+ const char *prepend_annotations,
+ int *can_dl_again_out)
{
routerinfo_t *router = NULL;
char digest[128];
@@ -1083,6 +1099,7 @@ router_parse_entry_from_string(const char *s, const char *end,
size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
int ok = 1;
memarea_t *area = NULL;
+ int can_dl_again = 0;
tor_assert(!allow_annotations || !prepend_annotations);
@@ -1389,19 +1406,20 @@ router_parse_entry_from_string(const char *s, const char *end,
verified_digests = digestmap_new();
digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
#endif
- if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
- "router descriptor") < 0)
- goto err;
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
}
+ can_dl_again = 1;
+ if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
+ "router descriptor") < 0)
+ goto err;
+
if (!router->platform) {
router->platform = tor_strdup("<unknown>");
}
-
goto done;
err:
@@ -1418,6 +1436,8 @@ router_parse_entry_from_string(const char *s, const char *end,
DUMP_AREA(area, "routerinfo");
memarea_drop_all(area);
}
+ if (can_dl_again_out)
+ *can_dl_again_out = can_dl_again;
return router;
}
@@ -1426,10 +1446,16 @@ router_parse_entry_from_string(const char *s, const char *end,
* <b>cache_copy</b> is true, make a copy of the extra-info document in the
* cache_info fields of the result. If <b>routermap</b> is provided, use it
* as a map from router identity to routerinfo_t when looking up signing keys.
+ *
+ * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
+ * if it's okay to try to download an extrainfo with this same digest again,
+ * and 0 if it isn't. (It might not be okay to download it again if part of
+ * the part covered by the digest is invalid.)
*/
extrainfo_t *
extrainfo_parse_entry_from_string(const char *s, const char *end,
- int cache_copy, struct digest_ri_map_t *routermap)
+ int cache_copy, struct digest_ri_map_t *routermap,
+ int *can_dl_again_out)
{
extrainfo_t *extrainfo = NULL;
char digest[128];
@@ -1439,6 +1465,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
routerinfo_t *router = NULL;
memarea_t *area = NULL;
const char *s_dup = s;
+ int can_dl_again = 0;
if (!end) {
end = s + strlen(s);
@@ -1498,6 +1525,8 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
goto err;
}
+ can_dl_again = 1;
+
if (routermap &&
(router = digestmap_get((digestmap_t*)routermap,
extrainfo->cache_info.identity_digest))) {
@@ -1540,6 +1569,8 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
DUMP_AREA(area, "extrainfo");
memarea_drop_all(area);
}
+ if (can_dl_again_out)
+ *can_dl_again_out = can_dl_again;
return extrainfo;
}
@@ -4006,12 +4037,15 @@ find_start_of_next_microdesc(const char *s, const char *eos)
* If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
* descriptor in the body field of each microdesc_t.
*
- * Return all newly
- * parsed microdescriptors in a newly allocated smartlist_t. */
+ * Return all newly parsed microdescriptors in a newly allocated
+ * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
+ * microdesc digest to it for every microdesc that we found to be badly
+ * formed. */
smartlist_t *
microdescs_parse_from_string(const char *s, const char *eos,
int allow_annotations,
- saved_location_t where)
+ saved_location_t where,
+ smartlist_t *invalid_digests_out)
{
smartlist_t *tokens;
smartlist_t *result;
@@ -4033,16 +4067,12 @@ microdescs_parse_from_string(const char *s, const char *eos,
tokens = smartlist_new();
while (s < eos) {
+ int okay = 0;
+
start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
if (!start_of_next_microdesc)
start_of_next_microdesc = eos;
- if (tokenize_string(area, s, start_of_next_microdesc, tokens,
- microdesc_token_table, flags)) {
- log_warn(LD_DIR, "Unparseable microdescriptor");
- goto next;
- }
-
md = tor_malloc_zero(sizeof(microdesc_t));
{
const char *cp = tor_memstr(s, start_of_next_microdesc-s,
@@ -4057,6 +4087,13 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->body = (char*)cp;
md->off = cp - start;
}
+ crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
+
+ if (tokenize_string(area, s, start_of_next_microdesc, tokens,
+ microdesc_token_table, flags)) {
+ log_warn(LD_DIR, "Unparseable microdescriptor");
+ goto next;
+ }
if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
if (parse_iso_time(tok->args[0], &md->last_listed)) {
@@ -4113,12 +4150,15 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->ipv6_exit_policy = parse_short_policy(tok->args[0]);
}
- crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
-
smartlist_add(result, md);
+ okay = 1;
md = NULL;
next:
+ if (! okay && invalid_digests_out) {
+ smartlist_add(invalid_digests_out,
+ tor_memdup(md->digest, DIGEST256_LEN));
+ }
microdesc_free(md);
md = NULL;
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index fa275c8..927d0b5 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -29,14 +29,17 @@ int router_parse_list_from_string(const char **s, const char *eos,
saved_location_t saved_location,
int is_extrainfo,
int allow_annotations,
- const char *prepend_annotations);
+ const char *prepend_annotations,
+ smartlist_t *invalid_digests_out);
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
int cache_copy,
int allow_annotations,
- const char *prepend_annotations);
+ const char *prepend_annotations,
+ int *can_dl_again_out);
extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
- int cache_copy, struct digest_ri_map_t *routermap);
+ int cache_copy, struct digest_ri_map_t *routermap,
+ int *can_dl_again_out);
MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
(const char *s, int assume_action));
version_status_t tor_version_is_obsolete(const char *myversion,
@@ -60,7 +63,8 @@ ns_detached_signatures_t *networkstatus_parse_detached_signatures(
smartlist_t *microdescs_parse_from_string(const char *s, const char *eos,
int allow_annotations,
- saved_location_t where);
+ saved_location_t where,
+ smartlist_t *invalid_digests_out);
authority_cert_t *authority_cert_parse_from_string(const char *s,
const char **end_of_string);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 3042ec2..935c82e 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -186,7 +186,7 @@ test_dir_formats(void *arg)
buf = router_dump_router_to_string(r1, pk2);
tt_assert(buf);
cp = buf;
- rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL);
+ rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
tt_assert(rp1);
tt_int_op(rp1->addr,==, r1->addr);
tt_int_op(rp1->or_port,==, r1->or_port);
@@ -231,7 +231,7 @@ test_dir_formats(void *arg)
buf = router_dump_router_to_string(r2, pk1);
cp = buf;
- rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL);
+ rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
tt_assert(rp2);
tt_int_op(rp2->addr,==, r2->addr);
tt_int_op(rp2->or_port,==, r2->or_port);
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 23e636f..f7e87ac 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -367,7 +367,7 @@ test_md_generate(void *arg)
microdesc_t *md = NULL;
(void)arg;
- ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL);
+ ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
md = dirvote_create_microdescriptor(ri, 8);
tt_str_op(md->body, ==, test_md_8);
1
0

[tor/master] Unit tests for 11243: loading ri, ei, mds from lists
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit 3efeb711f104b58b1f8a46c56c56246f0049e3e1
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Oct 7 09:20:44 2014 -0400
Unit tests for 11243: loading ri, ei, mds from lists
These tests make sure that entries are actually marked
undownloadable as appropriate.
---
src/or/networkstatus.c | 14 +--
src/or/networkstatus.h | 17 +--
src/or/routerlist.c | 8 +-
src/or/routerlist.h | 5 +-
src/test/example_extrainfo.inc | 21 ++--
src/test/test_dir.c | 227 ++++++++++++++++++++++++++++++++++++++++
src/test/test_microdesc.c | 97 +++++++++++++++++
7 files changed, 361 insertions(+), 28 deletions(-)
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index e61d1b4..9c49d34 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -595,10 +595,10 @@ networkstatus_vote_find_entry_idx(networkstatus_t *ns,
/** As router_get_consensus_status_by_descriptor_digest, but does not return
* a const pointer. */
-routerstatus_t *
-router_get_mutable_consensus_status_by_descriptor_digest(
+MOCK_IMPL(routerstatus_t *,
+router_get_mutable_consensus_status_by_descriptor_digest,(
networkstatus_t *consensus,
- const char *digest)
+ const char *digest))
{
if (!consensus)
consensus = current_consensus;
@@ -628,8 +628,8 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
/** Given the digest of a router descriptor, return its current download
* status, or NULL if the digest is unrecognized. */
-download_status_t *
-router_get_dl_status_by_descriptor_digest(const char *d)
+MOCK_IMPL(download_status_t *,
+router_get_dl_status_by_descriptor_digest,(const char *d))
{
routerstatus_t *rs;
if (!current_ns_consensus)
@@ -995,8 +995,8 @@ networkstatus_get_latest_consensus(void)
/** Return the latest consensus we have whose flavor matches <b>f</b>, or NULL
* if we don't have one. */
-networkstatus_t *
-networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
+MOCK_IMPL(networkstatus_t *,
+networkstatus_get_latest_consensus_by_flavor,(consensus_flavor_t f))
{
if (f == FLAV_NS)
return current_ns_consensus;
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index be0a86c..344e4de 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -12,6 +12,8 @@
#ifndef TOR_NETWORKSTATUS_H
#define TOR_NETWORKSTATUS_H
+#include "testsupport.h"
+
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
int router_reload_consensus_networkstatus(void);
@@ -35,16 +37,19 @@ routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
-download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
+
+MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
+ (const char *d));
+
const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
routerstatus_t *router_get_mutable_consensus_status_by_id(
const char *digest);
const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
networkstatus_t *consensus,
const char *digest);
-routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
- networkstatus_t *consensus,
- const char *digest);
+MOCK_DECL(routerstatus_t *,
+ router_get_mutable_consensus_status_by_descriptor_digest,
+ (networkstatus_t *consensus, const char *digest));
const routerstatus_t *router_get_consensus_status_by_nickname(
const char *nickname,
int warn_if_unnamed);
@@ -60,8 +65,8 @@ int consensus_is_waiting_for_certs(void);
int client_would_use_router(const routerstatus_t *rs, time_t now,
const or_options_t *options);
networkstatus_t *networkstatus_get_latest_consensus(void);
-networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
- consensus_flavor_t f);
+MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
+ (consensus_flavor_t f));
networkstatus_t *networkstatus_get_live_consensus(time_t now);
networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
int flavor);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index d8e26b0..e851845 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -2615,8 +2615,8 @@ router_get_by_descriptor_digest(const char *digest)
/** Return the signed descriptor for the router in our routerlist whose
* 20-byte extra-info digest is <b>digest</b>. Return NULL if no such router
* is known. */
-signed_descriptor_t *
-router_get_by_extrainfo_digest(const char *digest)
+MOCK_IMPL(signed_descriptor_t *,
+router_get_by_extrainfo_digest,(const char *digest))
{
tor_assert(digest);
@@ -2939,8 +2939,8 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
/** Adds the extrainfo_t <b>ei</b> to the routerlist <b>rl</b>, if there is a
* corresponding router in rl-\>routers or rl-\>old_routers. Return true iff
* we actually inserted <b>ei</b>. Free <b>ei</b> if it isn't inserted. */
-static int
-extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
+MOCK_IMPL(STATIC int,
+extrainfo_insert,(routerlist_t *rl, extrainfo_t *ei))
{
int r = 0;
routerinfo_t *ri = rimap_get(rl->identity_map,
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 52f2303..950320a 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -82,7 +82,8 @@ int hexdigest_to_digest(const char *hexdigest, char *digest);
const routerinfo_t *router_get_by_id_digest(const char *digest);
routerinfo_t *router_get_mutable_by_digest(const char *digest);
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
-signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
+MOCK_DECL(signed_descriptor_t *,router_get_by_extrainfo_digest,
+ (const char *digest));
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
@@ -215,6 +216,8 @@ STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
int seconds));
+MOCK_DECL(STATIC int, extrainfo_insert,(routerlist_t *rl, extrainfo_t *ei));
+
#endif
#endif
diff --git a/src/test/example_extrainfo.inc b/src/test/example_extrainfo.inc
index 26587c7..606279a 100644
--- a/src/test/example_extrainfo.inc
+++ b/src/test/example_extrainfo.inc
@@ -133,23 +133,24 @@ static const char EX_EI_BAD_NICKNAME_KEY[] =
"/UBWNSyXCFDMqnddb/LZ8+VgttmxfYkpeRzSSmDijN3RbOvYJhhBAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
-static const char EX_EI_BAD_TOKENS[] =
- "extra-info\n"
+const char EX_EI_BAD_TOKENS[] =
+ "extra-info bob 6F314FB01A31162BD5E473D4977AC570DC5B86BB\n"
+ "published 2014-10-05 20:07:00\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
- "e0b8fW9SkB81WwpkqR+/oLvVnNMpW4VwBKlNAnsPdInnNYySFCeILyOmb8A5j/D3\n"
- "ZRbfKFgXrApya4ViGeh+1QHz+FM8nWaK0+5JE6cNw+DNiQWsUjrvq2bHoZi/Lv+k\n"
- "RFkpbb0+IPdub9Jj3qn6cZBVSChD1aeCO9RkchV0744=\n"
+ "lhRIafrkKoQmnUoBLiq4XC8XKXrleGJZ5vefkLcgjOJ5IffsvVdIA7Vqq/ISbPrG\n"
+ "b/Zs0sJNL6naHPxJBglgHJqksSyiYHaeOetXg2Rb+vZ1v2S5BrVgk1nPMDhyIzqc\n"
+ "zU7eCxFf/1sXKtWlEKxGdX4LmVfnIln5aI31Bc4xRrE=\n"
"-----END SIGNATURE-----\n"
;
-static const char EX_EI_BAD_TOKENS_FP[] = "1CE7F867C744F0CE635146D82C0A0CC4B3408E0A";
-static const char EX_EI_BAD_TOKENS_KEY[] =
+const char EX_EI_BAD_TOKENS_FP[] = "6F314FB01A31162BD5E473D4977AC570DC5B86BB";
+const char EX_EI_BAD_TOKENS_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
- "MIGJAoGBALfrYfnIA7gTGwEC5tPqqTuSnMiINq/hPyMWXOFUEKEBRmctxba9fjiy\n"
- "JDstxC4ZBpdHc3+uuFn6krGgBVzFCKvBkBHUQXgFmjlANzdcLrG7J78K6gXuPeeq\n"
- "MbptD7thkuIdkPdVWMko7BrmBEr30EphgrKQqTWjrtBQj+CZ8Sr1AgMBAAE=\n"
+ "MIGJAoGBAL7Z8tz45Tb4tnEFS2sAyjubBV/giSfZdmXRkDV8Jo4xqWqhWFJn7+zN\n"
+ "AXBWBThGeVH2WXrpz5seNJXgZJPxMTMsrnSCGcRXZw0Npti2MkLuQ6+prZa+OPwE\n"
+ "OyC6jivtAaY/o9iYQjDC2avLXD3N4LvoygyF418KnNcjbzuFygffAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
static const char EX_EI_BAD_START[] =
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index db57c2a..0499251 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -567,6 +567,231 @@ test_dir_parse_router_list(void *arg)
#undef ADD
}
+static download_status_t dls_minimal;
+static download_status_t dls_maximal;
+static download_status_t dls_bad_fingerprint;
+static download_status_t dls_bad_sig2;
+static download_status_t dls_bad_ports;
+static download_status_t dls_bad_tokens;
+
+static int mock_router_get_dl_status_unrecognized = 0;
+static int mock_router_get_dl_status_calls = 0;
+
+static download_status_t *
+mock_router_get_dl_status(const char *d)
+{
+ ++mock_router_get_dl_status_calls;
+ char hex[HEX_DIGEST_LEN+1];
+ base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
+ if (!strcmp(hex, "3E31D19A69EB719C00B02EC60D13356E3F7A3452")) {
+ return &dls_minimal;
+ } else if (!strcmp(hex, "581D8A368A0FA854ECDBFAB841D88B3F1B004038")) {
+ return &dls_maximal;
+ } else if (!strcmp(hex, "2578AE227C6116CDE29B3F0E95709B9872DEE5F1")) {
+ return &dls_bad_fingerprint;
+ } else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
+ return &dls_bad_sig2;
+ } else if (!strcmp(hex, "AB9EEAA95E7D45740185B4E519C76EAD756277A9")) {
+ return &dls_bad_ports;
+ } else if (!strcmp(hex, "A0CC2CEFAD59DBF19F468BFEE60E0868C804B422")) {
+ return &dls_bad_tokens;
+ } else {
+ ++mock_router_get_dl_status_unrecognized;
+ return NULL;
+ }
+}
+
+static void
+test_dir_load_routers(void *arg)
+{
+ (void) arg;
+ smartlist_t *chunks = smartlist_new();
+ smartlist_t *wanted = smartlist_new();
+ char buf[DIGEST_LEN];
+ char *mem_op_hex_tmp = NULL;
+
+#define ADD(str) \
+ do { \
+ tt_int_op(0,==,router_get_router_hash(str, strlen(str), buf)); \
+ smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
+ } while (0)
+
+ MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status);
+
+ smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_FINGERPRINT));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG2));
+ smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_TOKENS));
+
+ /* not ADDing MINIMIAL */
+ ADD(EX_RI_MAXIMAL);
+ ADD(EX_RI_BAD_FINGERPRINT);
+ ADD(EX_RI_BAD_SIG2);
+ /* Not ADDing BAD_PORTS */
+ ADD(EX_RI_BAD_TOKENS);
+
+ char *list = smartlist_join_strings(chunks, "", 0, NULL);
+ tt_int_op(1, ==,
+ router_load_routers_from_string(list, NULL, SAVED_IN_JOURNAL,
+ wanted, 1, NULL));
+
+ /* The "maximal" router was added. */
+ /* "minimal" was not. */
+ tt_int_op(smartlist_len(router_get_routerlist()->routers),==,1);
+ routerinfo_t *r = smartlist_get(router_get_routerlist()->routers, 0);
+ test_memeq_hex(r->cache_info.signed_descriptor_digest,
+ "581D8A368A0FA854ECDBFAB841D88B3F1B004038");
+ tt_int_op(dls_minimal.n_download_failures, ==, 0);
+ tt_int_op(dls_maximal.n_download_failures, ==, 0);
+
+ /* "Bad fingerprint" and "Bad tokens" should have gotten marked
+ * non-retriable. */
+ tt_want_int_op(mock_router_get_dl_status_calls, ==, 2);
+ tt_want_int_op(mock_router_get_dl_status_unrecognized, ==, 0);
+ tt_int_op(dls_bad_fingerprint.n_download_failures, ==, 255);
+ tt_int_op(dls_bad_tokens.n_download_failures, ==, 255);
+
+ /* bad_sig2 and bad ports" are retriable -- one since only the signature
+ * was bad, and one because we didn't ask for it. */
+ tt_int_op(dls_bad_sig2.n_download_failures, ==, 0);
+ tt_int_op(dls_bad_ports.n_download_failures, ==, 0);
+
+ /* Wanted still contains "BAD_SIG2" */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ tt_str_op(smartlist_get(wanted, 0), ==,
+ "E0A3753CEFD54128EAB239F294954121DB23D2EF");
+
+#undef ADD
+
+ done:
+ tor_free(mem_op_hex_tmp);
+ UNMOCK(router_get_dl_status_by_descriptor_digest);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+}
+
+static int mock_get_by_ei_dd_calls = 0;
+static int mock_get_by_ei_dd_unrecognized = 0;
+
+static signed_descriptor_t sd_ei_minimal;
+static signed_descriptor_t sd_ei_bad_nickname;
+static signed_descriptor_t sd_ei_maximal;
+static signed_descriptor_t sd_ei_bad_tokens;
+static signed_descriptor_t sd_ei_bad_sig2;
+
+static signed_descriptor_t *
+mock_get_by_ei_desc_digest(const char *d)
+{
+
+ ++mock_get_by_ei_dd_calls;
+ char hex[HEX_DIGEST_LEN+1];
+ base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
+
+ if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) {
+ return &sd_ei_minimal;
+ } else if (!strcmp(hex, "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF")) {
+ return &sd_ei_maximal;
+ } else if (!strcmp(hex, "D5DF4AA62EE9FFC9543D41150C9864908E0390AF")) {
+ return &sd_ei_bad_nickname;
+ } else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
+ return &sd_ei_bad_sig2;
+ } else if (!strcmp(hex, "9D90F8C42955BBC57D54FB05E54A3F083AF42E8B")) {
+ return &sd_ei_bad_tokens;
+ } else {
+ ++mock_get_by_ei_dd_unrecognized;
+ return NULL;
+ }
+}
+
+static smartlist_t *mock_ei_insert_list = NULL;
+static int
+mock_ei_insert(routerlist_t *rl, extrainfo_t *ei)
+{
+ (void) rl;
+ smartlist_add(mock_ei_insert_list, ei);
+ return 1;
+}
+
+static void
+test_dir_load_extrainfo(void *arg)
+{
+ (void) arg;
+ smartlist_t *chunks = smartlist_new();
+ smartlist_t *wanted = smartlist_new();
+ char buf[DIGEST_LEN];
+ char *mem_op_hex_tmp = NULL;
+
+#define ADD(str) \
+ do { \
+ tt_int_op(0,==,router_get_extrainfo_hash(str, strlen(str), buf)); \
+ smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
+ } while (0)
+
+ mock_ei_insert_list = smartlist_new();
+ MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest);
+ MOCK(extrainfo_insert, mock_ei_insert);
+
+ smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL));
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));
+ smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL));
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED));
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_TOKENS));
+
+ /* not ADDing MINIMIAL */
+ ADD(EX_EI_MAXIMAL);
+ ADD(EX_EI_BAD_NICKNAME);
+ /* Not ADDing BAD_PUBLISHED */
+ ADD(EX_EI_BAD_TOKENS);
+ ADD(EX_EI_BAD_SIG2);
+
+ char *list = smartlist_join_strings(chunks, "", 0, NULL);
+ router_load_extrainfo_from_string(list, NULL, SAVED_IN_JOURNAL, wanted, 1);
+
+ /* The "maximal" router was added. */
+ /* "minimal" was also added, even though we didn't ask for it, since
+ * that's what we do with extrainfos. */
+ tt_int_op(smartlist_len(mock_ei_insert_list),==,2);
+
+ extrainfo_t *e = smartlist_get(mock_ei_insert_list, 0);
+ test_memeq_hex(e->cache_info.signed_descriptor_digest,
+ "11E0EDF526950739F7769810FCACAB8C882FAEEE");
+
+ e = smartlist_get(mock_ei_insert_list, 1);
+ test_memeq_hex(e->cache_info.signed_descriptor_digest,
+ "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF");
+ tt_int_op(dls_minimal.n_download_failures, ==, 0);
+ tt_int_op(dls_maximal.n_download_failures, ==, 0);
+
+ /* "Bad nickname" and "Bad tokens" should have gotten marked
+ * non-retriable. */
+ tt_want_int_op(mock_get_by_ei_dd_calls, ==, 2);
+ tt_want_int_op(mock_get_by_ei_dd_unrecognized, ==, 0);
+ tt_int_op(sd_ei_bad_nickname.ei_dl_status.n_download_failures, ==, 255);
+ tt_int_op(sd_ei_bad_tokens.ei_dl_status.n_download_failures, ==, 255);
+
+ /* bad_ports is retriable -- because we didn't ask for it. */
+ tt_int_op(dls_bad_ports.n_download_failures, ==, 0);
+
+ /* Wanted still contains "BAD_SIG2" */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ tt_str_op(smartlist_get(wanted, 0), ==,
+ "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C");
+
+#undef ADD
+
+ done:
+ tor_free(mem_op_hex_tmp);
+ UNMOCK(router_get_by_extrainfo_digest);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+}
+
static void
test_dir_versions(void *arg)
{
@@ -2669,6 +2894,8 @@ struct testcase_t dir_tests[] = {
DIR(routerparse_bad, 0),
DIR(extrainfo_parsing, 0),
DIR(parse_router_list, TT_FORK),
+ DIR(load_routers, TT_FORK),
+ DIR(load_extrainfo, TT_FORK),
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 9073034..bc6755b 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -7,6 +7,7 @@
#include "config.h"
#include "dirvote.h"
#include "microdesc.h"
+#include "networkstatus.h"
#include "routerlist.h"
#include "routerparse.h"
@@ -618,11 +619,107 @@ test_md_parse(void *arg)
tor_free(mem_op_hex_tmp);
}
+static int mock_rgsbd_called = 0;
+static routerstatus_t *mock_rgsbd_val_a = NULL;
+static routerstatus_t *mock_rgsbd_val_b = NULL;
+static routerstatus_t *
+mock_router_get_status_by_digest(networkstatus_t *c, const char *d)
+{
+ (void) c;
+ ++mock_rgsbd_called;
+
+ if (fast_memeq(d, "\x5d\x76", 2)) {
+ memcpy(mock_rgsbd_val_a->descriptor_digest, d, 32);
+ return mock_rgsbd_val_a;
+ } else if (fast_memeq(d, "\x20\xd1", 2)) {
+ memcpy(mock_rgsbd_val_b->descriptor_digest, d, 32);
+ return mock_rgsbd_val_b;
+ } else {
+ return NULL;
+ }
+}
+
+static networkstatus_t *mock_ns_val = NULL;
+static networkstatus_t *
+mock_ns_get_by_flavor(consensus_flavor_t f)
+{
+ (void)f;
+ return mock_ns_val;
+}
+
+static void
+test_md_reject_cache(void *arg)
+{
+ (void) arg;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *added = NULL, *wanted = smartlist_new();
+ or_options_t *options = get_options_mutable();
+ char buf[DIGEST256_LEN];
+
+ tor_free(options->DataDirectory);
+ options->DataDirectory = tor_strdup(get_fname("md_datadir_test_rej"));
+ mock_rgsbd_val_a = tor_malloc_zero(sizeof(routerstatus_t));
+ mock_rgsbd_val_b = tor_malloc_zero(sizeof(routerstatus_t));
+ mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
+
+ mock_ns_val->valid_after = time(NULL) - 86400;
+ mock_ns_val->valid_until = time(NULL) + 86400;
+ mock_ns_val->flavor = FLAV_MICRODESC;
+
+#ifdef _WIN32
+ tt_int_op(0, ==, mkdir(options->DataDirectory));
+#else
+ tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
+#endif
+
+ MOCK(router_get_mutable_consensus_status_by_descriptor_digest,
+ mock_router_get_status_by_digest);
+ MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
+
+ mc = get_microdesc_cache();
+#define ADD(hex) \
+ do { \
+ tt_int_op(0,==,base16_decode(buf,sizeof(buf),hex,strlen(hex))); \
+ smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN)); \
+ } while (0)
+
+ /* invalid,0 */
+ ADD("5d76bf1c6614e885614a1e0ad074e1ab4ea14655ebeefb1736a71b5ed8a15a51");
+ /* invalid,2 */
+ ADD("20d1576c5ab11bbcff0dedb1db4a3cfcc8bc8dd839d8cbfef92d00a1a7d7b294");
+ /* valid, 6 */
+ ADD("53f740bd222ab37f19f604b1d3759aa65eff1fbce9ac254bd0fa50d4af9b1bae");
+ /* valid, 8 */
+ ADD("a0a155562d8093d8fd0feb7b93b7226e17f056c2142aab7a4ea8c5867a0376d5");
+
+ added = microdescs_add_to_cache(mc, MD_PARSE_TEST_DATA, NULL,
+ SAVED_NOWHERE, 0, time(NULL), wanted);
+
+ tt_int_op(smartlist_len(added), ==, 2);
+ tt_int_op(mock_rgsbd_called, ==, 2);
+ tt_int_op(mock_rgsbd_val_a->dl_status.n_download_failures, ==, 255);
+ tt_int_op(mock_rgsbd_val_b->dl_status.n_download_failures, ==, 255);
+
+ done:
+ UNMOCK(networkstatus_get_latest_consensus_by_flavor);
+ UNMOCK(router_get_mutable_consensus_status_by_descriptor_digest);
+ if (options)
+ tor_free(options->DataDirectory);
+ microdesc_free_all();
+ smartlist_free(added);
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+ tor_free(mock_rgsbd_val_a);
+ tor_free(mock_rgsbd_val_b);
+ tor_free(mock_ns_val);
+}
+
struct testcase_t microdesc_tests[] = {
{ "cache", test_md_cache, TT_FORK, NULL, NULL },
{ "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
{ "generate", test_md_generate, 0, NULL, NULL },
{ "parse", test_md_parse, 0, NULL, NULL },
+ { "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
1
0

13 Oct '14
commit 032e3b733f7bf304a778459597e7ed7b371234c7
Merge: f1782d9 374b531
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Oct 13 13:22:10 2014 -0400
Merge remote-tracking branch 'isis/bug12951_r1'
src/or/networkstatus.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
1
0

[tor/master] Add `published` line to `@type bridge-network-status` documents.
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit 374b531dba966780f2e59163ca80b1b5a0b8f14c
Author: Isis Lovecruft <isis(a)torproject.org>
Date: Mon Aug 25 23:13:03 2014 +0000
Add `published` line to `@type bridge-network-status` documents.
This modifies the format of the bridge networkstatus documents produced
by the BridgeAuth. The new format adds a `published` line to the header
of the file, before the `flag-thresholds` line. This is done once per
networkstatus file that is written. The timestamp in the `published`
line is the standard ISO 8601 format (with a space as the separator)
used throughout the rest of tor.
* FIXES #12951 https://bugs.torproject.org/12951
---
src/or/networkstatus.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 890da0a..7a14d17 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1672,17 +1672,22 @@ networkstatus_dump_bridge_status_to_file(time_t now)
char *status = networkstatus_getinfo_by_purpose("bridge", now);
const or_options_t *options = get_options();
char *fname = NULL;
- char *thresholds = NULL, *thresholds_and_status = NULL;
+ char *thresholds = NULL;
+ char *published_thresholds_and_status = NULL;
routerlist_t *rl = router_get_routerlist();
+ char published[ISO_TIME_LEN+1];
+
+ format_iso_time(published, now);
dirserv_compute_bridge_flag_thresholds(rl);
thresholds = dirserv_get_flag_thresholds_line();
- tor_asprintf(&thresholds_and_status, "flag-thresholds %s\n%s",
- thresholds, status);
+ tor_asprintf(&published_thresholds_and_status,
+ "published %s\nflag-thresholds %s\n%s",
+ published, thresholds, status);
tor_asprintf(&fname, "%s"PATH_SEPARATOR"networkstatus-bridges",
options->DataDirectory);
- write_str_to_file(fname,thresholds_and_status,0);
+ write_str_to_file(fname,published_thresholds_and_status,0);
tor_free(thresholds);
- tor_free(thresholds_and_status);
+ tor_free(published_thresholds_and_status);
tor_free(fname);
tor_free(status);
}
1
0

[tor/master] Avoid overflow in format_time_interval, create unit tests
by nickm@torproject.org 13 Oct '14
by nickm@torproject.org 13 Oct '14
13 Oct '14
commit f51418aabcc2af47f61a97f818b013ade6e45208
Author: teor <teor2345(a)gmail.com>
Date: Sun Oct 12 20:50:10 2014 +1100
Avoid overflow in format_time_interval, create unit tests
Fix an instance of integer overflow in format_time_interval() when
taking the absolute value of the supplied signed interval value.
Fixes bug 13393.
Create unit tests for format_time_interval().
---
.../bug13393-format-time-interval-overflow-test | 6 +
src/common/util.c | 6 +-
src/test/test_util.c | 423 ++++++++++++++++++++
3 files changed, 434 insertions(+), 1 deletion(-)
diff --git a/changes/bug13393-format-time-interval-overflow-test b/changes/bug13393-format-time-interval-overflow-test
new file mode 100644
index 0000000..cc15572
--- /dev/null
+++ b/changes/bug13393-format-time-interval-overflow-test
@@ -0,0 +1,6 @@
+ o Minor bugfixes:
+ - Fix an instance of integer overflow in format_time_interval().
+ Fixes bug 13393.
+
+ o Minor features (test):
+ - Create unit tests for format_time_interval(). With bug 13393.
diff --git a/src/common/util.c b/src/common/util.c
index f4d293c..0ea7095 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1670,7 +1670,11 @@ format_time_interval(char *out, size_t out_len, long interval)
{
/* We only report seconds if there's no hours. */
long sec = 0, min = 0, hour = 0, day = 0;
- if (interval < 0)
+
+ /* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
+ if (interval < -LONG_MAX)
+ interval = LONG_MAX;
+ else if (interval < 0)
interval = -interval;
if (interval >= 86400) {
diff --git a/src/test/test_util.c b/src/test/test_util.c
index c67aa71..3fed1f7 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -22,6 +22,7 @@
#include <tchar.h>
#endif
#include <math.h>
+#include <ctype.h>
/* XXXX this is a minimal wrapper to make the unit tests compile with the
* changed tor_timegm interface. */
@@ -2068,6 +2069,427 @@ test_util_sscanf(void *arg)
;
}
+#define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
+#define tt_ci_char_op(a,op,b) tt_char_op(tolower(a),op,tolower(b))
+
+static void
+test_util_format_time_interval(void *arg)
+{
+ /* use the same sized buffer and integers as tor uses */
+#define DBUF_SIZE 64
+ char dbuf[DBUF_SIZE];
+#define T_ "%ld"
+ long sec, min, hour, day;
+
+ /* we don't care about the exact spelling of the
+ * second(s), minute(s), hour(s), day(s) labels */
+#define LABEL_SIZE 21
+#define L_ "%20s"
+ char label_s[LABEL_SIZE];
+ char label_m[LABEL_SIZE];
+ char label_h[LABEL_SIZE];
+ char label_d[LABEL_SIZE];
+
+#define TL_ T_ " " L_
+
+ int r;
+
+ (void)arg;
+
+ /* In these tests, we're not picky about
+ * spelling or abbreviations */
+
+ /* seconds: 0, 1, 9, 10, 59 */
+
+ /* ignore exact spelling of "second(s)"*/
+ format_time_interval(dbuf, sizeof(dbuf), 0);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 0);
+
+ format_time_interval(dbuf, sizeof(dbuf), 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 1);
+
+ format_time_interval(dbuf, sizeof(dbuf), 10);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 10);
+
+ format_time_interval(dbuf, sizeof(dbuf), 59);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 59);
+
+ /* negative seconds are reported as their absolute value */
+
+ format_time_interval(dbuf, sizeof(dbuf), -4);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 4);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ format_time_interval(dbuf, sizeof(dbuf), -32);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 32);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
+
+ /* ignore trailing "0 second(s)", if present */
+ format_time_interval(dbuf, sizeof(dbuf), 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &min, label_m);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(min,==, 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ /* ignore exact spelling of "minute(s)," and "second(s)" */
+ format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 1);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 59);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ /* ignore trailing "0 second(s)", if present */
+ format_time_interval(dbuf, sizeof(dbuf), 60*2);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &min, label_m);
+ tt_int_op(r,==, 2);
+ tt_int_op(min,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* ignore exact spelling of "minute(s)," and "second(s)" */
+ format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 1);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 59);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ /* negative minutes are reported as their absolute value */
+
+ /* ignore trailing "0 second(s)", if present */
+ format_time_interval(dbuf, sizeof(dbuf), -3*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &min, label_m);
+ tt_int_op(r,==, 2);
+ tt_int_op(min,==, 3);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* ignore exact spelling of "minute(s)," and "second(s)" */
+ format_time_interval(dbuf, sizeof(dbuf), -96);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 36);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ format_time_interval(dbuf, sizeof(dbuf), -2815);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 46);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 55);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
+ /* always ignore trailing seconds, if present */
+
+ /* ignore trailing "0 minute(s)" etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &hour, label_h);
+ tt_int_op(r,==, 2);
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &hour, label_h);
+ tt_int_op(r,==, 2);
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ /* ignore exact spelling of "hour(s)," etc. */
+ format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 23);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 23);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* negative hours are reported as their absolute value */
+
+ /* ignore exact spelling of "hour(s)," etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &hour, label_h);
+ tt_int_op(r,==, 2);
+ tt_int_op(hour,==, 2);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ format_time_interval(dbuf, sizeof(dbuf), -75804);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 21);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 3);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
+ /* always ignore trailing seconds, if present */
+
+ /* ignore trailing "0 hours(s)" etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &day, label_d);
+ tt_int_op(r,==, 2);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &day, label_d);
+ tt_int_op(r,==, 2);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+
+ /* ignore exact spelling of "days(s)," etc. */
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ if (r == -1) {
+ /* ignore 0 hours(s), if present */
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &day, label_d, &min, label_m);
+ }
+ tt_assert(r == 4 || r == 6);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+ if (r == 6) {
+ tt_int_op(hour,==, 0);
+ tt_ci_char_op(label_h[0],==, 'h');
+ }
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* ignore trailing "0 minutes(s)" etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &day, label_d, &hour, label_h);
+ tt_int_op(r,==, 4);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ /* negative days are reported as their absolute value */
+
+ format_time_interval(dbuf, sizeof(dbuf), -21936184);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 253);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 21);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 23);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* periods > 1 year are reported in days (warn?) */
+
+ /* ignore exact spelling of "days(s)," etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 758635154);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 8780);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 11);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* negative periods > 1 year are reported in days (warn?) */
+
+ format_time_interval(dbuf, sizeof(dbuf), -1427014922);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 16516);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 9);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+#if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
+
+ /* We can try INT32_MIN/MAX */
+ /* Always ignore second(s) */
+
+ /* INT32_MAX */
+ format_time_interval(dbuf, sizeof(dbuf), 2147483647);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 24855);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 3);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 14);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 seconds - ignored */
+
+ /* INT32_MIN: check that we get the absolute value of interval,
+ * which doesn't actually fit in int32_t.
+ * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
+ format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 24855);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 3);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 14);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 or 8 seconds - ignored */
+
+#endif
+
+#if SIZEOF_LONG == 8
+
+ /* We can try INT64_MIN/MAX */
+ /* Always ignore second(s) */
+
+ /* INT64_MAX */
+ format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 106751991167300L);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 15);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 30);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 seconds - ignored */
+
+ /* INT64_MIN: check that we get the absolute value of interval,
+ * which doesn't actually fit in int64_t.
+ * We expect INT64_MAX */
+ format_time_interval(dbuf, sizeof(dbuf),
+ -9223372036854775807L - 1L);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 106751991167300L);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 15);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 30);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 or 8 seconds - ignored */
+
+#endif
+
+
+done:
+ ;
+}
+
+#undef tt_char_op
+#undef tt_ci_char_op
+#undef DBUF_SIZE
+#undef T_
+#undef LABEL_SIZE
+#undef L_
+#undef TL_
+
static void
test_util_path_is_relative(void *arg)
{
@@ -4146,6 +4568,7 @@ struct testcase_t util_tests[] = {
UTIL_LEGACY(mmap),
UTIL_LEGACY(threads),
UTIL_LEGACY(sscanf),
+ UTIL_LEGACY(format_time_interval),
UTIL_LEGACY(path_is_relative),
UTIL_LEGACY(strtok),
UTIL_LEGACY(di_ops),
1
0
commit f1782d9c4c6d0b299d2fb9bb37a58f515aed4abe
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Oct 13 13:20:07 2014 -0400
Clean whitespace in last patch.
---
src/common/util.c | 2 +-
src/test/test_util.c | 99 +++++++++++++++++++++++++-------------------------
2 files changed, 50 insertions(+), 51 deletions(-)
diff --git a/src/common/util.c b/src/common/util.c
index 0ea7095..1d9d99d 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1670,7 +1670,7 @@ format_time_interval(char *out, size_t out_len, long interval)
{
/* We only report seconds if there's no hours. */
long sec = 0, min = 0, hour = 0, day = 0;
-
+
/* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
if (interval < -LONG_MAX)
interval = LONG_MAX;
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 3fed1f7..8855caf 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -2080,7 +2080,7 @@ test_util_format_time_interval(void *arg)
char dbuf[DBUF_SIZE];
#define T_ "%ld"
long sec, min, hour, day;
-
+
/* we don't care about the exact spelling of the
* second(s), minute(s), hour(s), day(s) labels */
#define LABEL_SIZE 21
@@ -2091,16 +2091,16 @@ test_util_format_time_interval(void *arg)
char label_d[LABEL_SIZE];
#define TL_ T_ " " L_
-
+
int r;
-
+
(void)arg;
-
+
/* In these tests, we're not picky about
* spelling or abbreviations */
-
+
/* seconds: 0, 1, 9, 10, 59 */
-
+
/* ignore exact spelling of "second(s)"*/
format_time_interval(dbuf, sizeof(dbuf), 0);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2108,30 +2108,30 @@ test_util_format_time_interval(void *arg)
tt_int_op(r,==, 2);
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(sec,==, 0);
-
+
format_time_interval(dbuf, sizeof(dbuf), 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &sec, label_s);
tt_int_op(r,==, 2);
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(sec,==, 1);
-
+
format_time_interval(dbuf, sizeof(dbuf), 10);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &sec, label_s);
tt_int_op(r,==, 2);
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(sec,==, 10);
-
+
format_time_interval(dbuf, sizeof(dbuf), 59);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &sec, label_s);
tt_int_op(r,==, 2);
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(sec,==, 59);
-
+
/* negative seconds are reported as their absolute value */
-
+
format_time_interval(dbuf, sizeof(dbuf), -4);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &sec, label_s);
@@ -2139,7 +2139,7 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(sec,==, 4);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
-
+
format_time_interval(dbuf, sizeof(dbuf), -32);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &sec, label_s);
@@ -2147,9 +2147,9 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(sec,==, 32);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
-
+
/* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
-
+
/* ignore trailing "0 second(s)", if present */
format_time_interval(dbuf, sizeof(dbuf), 60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2170,7 +2170,7 @@ test_util_format_time_interval(void *arg)
tt_int_op(sec,==, 1);
tt_ci_char_op(label_s[0],==, 's');
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
-
+
format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_,
@@ -2180,7 +2180,7 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_m[0],==, 'm');
tt_int_op(sec,==, 59);
tt_ci_char_op(label_s[0],==, 's');
-
+
/* ignore trailing "0 second(s)", if present */
format_time_interval(dbuf, sizeof(dbuf), 60*2);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2188,7 +2188,7 @@ test_util_format_time_interval(void *arg)
tt_int_op(r,==, 2);
tt_int_op(min,==, 2);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* ignore exact spelling of "minute(s)," and "second(s)" */
format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2199,7 +2199,7 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_m[0],==, 'm');
tt_int_op(sec,==, 1);
tt_ci_char_op(label_s[0],==, 's');
-
+
format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_,
@@ -2209,9 +2209,9 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_m[0],==, 'm');
tt_int_op(sec,==, 59);
tt_ci_char_op(label_s[0],==, 's');
-
+
/* negative minutes are reported as their absolute value */
-
+
/* ignore trailing "0 second(s)", if present */
format_time_interval(dbuf, sizeof(dbuf), -3*60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2219,7 +2219,7 @@ test_util_format_time_interval(void *arg)
tt_int_op(r,==, 2);
tt_int_op(min,==, 3);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* ignore exact spelling of "minute(s)," and "second(s)" */
format_time_interval(dbuf, sizeof(dbuf), -96);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2230,7 +2230,7 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_m[0],==, 'm');
tt_int_op(sec,==, 36);
tt_ci_char_op(label_s[0],==, 's');
-
+
format_time_interval(dbuf, sizeof(dbuf), -2815);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_,
@@ -2240,10 +2240,10 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_m[0],==, 'm');
tt_int_op(sec,==, 55);
tt_ci_char_op(label_s[0],==, 's');
-
+
/* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
/* always ignore trailing seconds, if present */
-
+
/* ignore trailing "0 minute(s)" etc., if present */
format_time_interval(dbuf, sizeof(dbuf), 60*60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2251,14 +2251,14 @@ test_util_format_time_interval(void *arg)
tt_int_op(r,==, 2);
tt_int_op(hour,==, 1);
tt_ci_char_op(label_h[0],==, 'h');
-
+
format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &hour, label_h);
tt_int_op(r,==, 2);
tt_int_op(hour,==, 1);
tt_ci_char_op(label_h[0],==, 'h');
-
+
/* ignore exact spelling of "hour(s)," etc. */
format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2269,7 +2269,7 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 1);
tt_ci_char_op(label_m[0],==, 'm');
-
+
format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_,
@@ -2279,7 +2279,7 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 59);
tt_ci_char_op(label_m[0],==, 'm');
-
+
format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_,
@@ -2289,9 +2289,9 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 59);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* negative hours are reported as their absolute value */
-
+
/* ignore exact spelling of "hour(s)," etc., if present */
format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2299,7 +2299,7 @@ test_util_format_time_interval(void *arg)
tt_int_op(r,==, 2);
tt_int_op(hour,==, 2);
tt_ci_char_op(label_h[0],==, 'h');
-
+
format_time_interval(dbuf, sizeof(dbuf), -75804);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_,
@@ -2309,10 +2309,10 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 3);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
/* always ignore trailing seconds, if present */
-
+
/* ignore trailing "0 hours(s)" etc., if present */
format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2320,14 +2320,14 @@ test_util_format_time_interval(void *arg)
tt_int_op(r,==, 2);
tt_int_op(day,==, 1);
tt_ci_char_op(label_d[0],==, 'd');
-
+
format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_, &day, label_d);
tt_int_op(r,==, 2);
tt_int_op(day,==, 1);
tt_ci_char_op(label_d[0],==, 'd');
-
+
/* ignore exact spelling of "days(s)," etc. */
format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2347,7 +2347,7 @@ test_util_format_time_interval(void *arg)
}
tt_int_op(min,==, 1);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* ignore trailing "0 minutes(s)" etc., if present */
format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2358,9 +2358,9 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_d[0],==, 'd');
tt_int_op(hour,==, 1);
tt_ci_char_op(label_h[0],==, 'h');
-
+
/* negative days are reported as their absolute value */
-
+
format_time_interval(dbuf, sizeof(dbuf), -21936184);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
@@ -2372,9 +2372,9 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 23);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* periods > 1 year are reported in days (warn?) */
-
+
/* ignore exact spelling of "days(s)," etc., if present */
format_time_interval(dbuf, sizeof(dbuf), 758635154);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2387,9 +2387,9 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 59);
tt_ci_char_op(label_m[0],==, 'm');
-
+
/* negative periods > 1 year are reported in days (warn?) */
-
+
format_time_interval(dbuf, sizeof(dbuf), -1427014922);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
@@ -2401,12 +2401,12 @@ test_util_format_time_interval(void *arg)
tt_ci_char_op(label_h[0],==, 'h');
tt_int_op(min,==, 2);
tt_ci_char_op(label_m[0],==, 'm');
-
+
#if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
/* We can try INT32_MIN/MAX */
/* Always ignore second(s) */
-
+
/* INT32_MAX */
format_time_interval(dbuf, sizeof(dbuf), 2147483647);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2420,7 +2420,7 @@ test_util_format_time_interval(void *arg)
tt_int_op(min,==, 14);
tt_ci_char_op(label_m[0],==, 'm');
/* and 7 seconds - ignored */
-
+
/* INT32_MIN: check that we get the absolute value of interval,
* which doesn't actually fit in int32_t.
* We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
@@ -2443,7 +2443,7 @@ test_util_format_time_interval(void *arg)
/* We can try INT64_MIN/MAX */
/* Always ignore second(s) */
-
+
/* INT64_MAX */
format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
@@ -2457,7 +2457,7 @@ test_util_format_time_interval(void *arg)
tt_int_op(min,==, 30);
tt_ci_char_op(label_m[0],==, 'm');
/* and 7 seconds - ignored */
-
+
/* INT64_MIN: check that we get the absolute value of interval,
* which doesn't actually fit in int64_t.
* We expect INT64_MAX */
@@ -2474,11 +2474,10 @@ test_util_format_time_interval(void *arg)
tt_int_op(min,==, 30);
tt_ci_char_op(label_m[0],==, 'm');
/* and 7 or 8 seconds - ignored */
-
+
#endif
-
-done:
+ done:
;
}
1
0

[translation/tails-misc_completed] Update translations for tails-misc_completed
by translation@torproject.org 13 Oct '14
by translation@torproject.org 13 Oct '14
13 Oct '14
commit d62df8b8e6cfcfb19b5bc7c17ef3433f25a5ad59
Author: Translation commit bot <translation(a)torproject.org>
Date: Mon Oct 13 15:45:54 2014 +0000
Update translations for tails-misc_completed
---
cs.po | 115 ++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 67 insertions(+), 48 deletions(-)
diff --git a/cs.po b/cs.po
index e69048e..fe5d62a 100644
--- a/cs.po
+++ b/cs.po
@@ -12,8 +12,8 @@ msgid ""
msgstr ""
"Project-Id-Version: The Tor Project\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-09-24 16:00+0200\n"
-"PO-Revision-Date: 2014-10-09 20:05+0000\n"
+"POT-Creation-Date: 2014-10-10 13:00+0200\n"
+"PO-Revision-Date: 2014-10-13 15:31+0000\n"
"Last-Translator: A5h8d0wf0x <littleslyfoxie28(a)gmail.com>\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/torproject/language/cs/)\n"
"MIME-Version: 1.0\n"
@@ -308,31 +308,6 @@ msgid ""
"You might prefer to restart Tails and disable MAC spoofing. See the <a href='file:///usr/share/doc/first_steps/startup_options/mac_spoofing.en.html'>documentation</a>."
msgstr "MAC spoofing selhalo pro síťovou kartu ${nic_name} (${nic}). Oprava chyb také sehlaha takže je veškerá síťová komunikace odpojena.\nMůžete preferovat restartování Tails a odpojit MAC spoofing. Podívejte se na <a href='file:///usr/share/doc/first_steps/startup_options/mac_spoofing.en.html'>documentation</a>."
-#: config/chroot_local-includes/usr/local/bin/tails-start-i2p:62
-msgid "Starting I2P..."
-msgstr "Startuje I2P..."
-
-#: config/chroot_local-includes/usr/local/bin/tails-start-i2p:63
-msgid "The I2P router console will be opened on start."
-msgstr "Při startu bude otevřena konzole I2P směrovače."
-
-#: config/chroot_local-includes/usr/local/bin/tails-start-i2p:82
-#: config/chroot_local-includes/usr/local/bin/tails-start-i2p:124
-msgid "I2P failed to start"
-msgstr "I2P se nepodařilo spustit"
-
-#: config/chroot_local-includes/usr/local/bin/tails-start-i2p:83
-msgid ""
-"Make sure that you have a working Internet connection, then try to start I2P"
-" again."
-msgstr "Ujistěte se, že máte funkční připojení na Internet, potom zkuste I2P nastartovat znovu."
-
-#: config/chroot_local-includes/usr/local/bin/tails-start-i2p:125
-msgid ""
-"Something went wrong when I2P was starting. Look in the logs in the "
-"following directory for more information:"
-msgstr "Něco se pokazilo, při spuštění I2P. Pro více informací se podívejte do protokolů v následujícím adresáři:"
-
#: config/chroot_local-includes/usr/local/bin/tails-upgrade-frontend-wrapper:19
#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:60
msgid "error:"
@@ -420,46 +395,86 @@ msgstr "Může to nějakou dobu trvat, takže buďte trpěliví."
msgid "Failed to setup chroot."
msgstr "Nepodařilo se nastavit \"chroot\""
-#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:177
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:184
#: ../config/chroot_local-includes/usr/share/applications/unsafe-browser.desktop.in.h:1
msgid "Unsafe Browser"
msgstr "Nebezpečný prohlížeč"
-#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:217
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:240
msgid "Shutting down the Unsafe Browser..."
msgstr "Ukončování nebezpečného prohlížeče..."
-#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:218
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:241
msgid ""
"This may take a while, and you may not restart the Unsafe Browser until it "
"is properly shut down."
msgstr "Tohle může chvíli trvat a nemusíte spustit Nebezpečný Prohlížeč dokud nebude spárvně vypnut."
-#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:230
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:253
msgid "Failed to restart Tor."
msgstr "Znovuspuštění TORu nebylo úspěšné"
-#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:238
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:261
msgid ""
"Another Unsafe Browser is currently running, or being cleaned up. Please "
"retry in a while."
msgstr "Další Nebezpečný Prohlížeč je nyní spuštěn nebo se čistí. Prosíme vraťte se později."
-#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:251
+#: config/chroot_local-includes/usr/local/sbin/unsafe-browser:274
msgid ""
"No DNS server was obtained through DHCP or manually configured in "
"NetworkManager."
msgstr "Nebyl získán prostřednictvím DHCP nebo ručně nastaven v Síťovém správci žádný DNS server."
#: config/chroot_local-includes/usr/share/tails/truecrypt-wrapper.disabled:11
-msgid "TrueCrypt will soon be removed from Tails"
-msgstr "TrueCrypt bude brzy z Tails odstraněn"
+msgid "TrueCrypt will be removed in Tails 1.2.1"
+msgstr "TrueCrypt bude odstraněn v Tails verzi 1.2.1"
#: config/chroot_local-includes/usr/share/tails/truecrypt-wrapper.disabled:12
msgid ""
-"TrueCrypt will soon be removed from Tails due to license and development "
-"concerns."
-msgstr "TrueCrypt bude brzy kvůli licenčním a vývojových problémů z Tails odstraněn."
+"TrueCrypt is no longer maintained and is said to be insecure by its own "
+"authors. Therefore, it will be removed in Tails 1.2.1 (November 25). We "
+"recommend that you learn how to <a "
+"href='file:///usr/share/doc/tails/website/doc/encryption_and_privacy/truecrypt.en.html#cryptsetup'>open"
+" TrueCrypt volumes with cryptsetup</a> as soon as possible."
+msgstr "TrueCrypt už není nadále udržován a jeho autorové jej prohlásili za nedůvěryhodný. Proto bude odstraněn v Tails 1.2.1 (25. listopad) Doporučujeme aby jste se naučili jak <a href='file:///usr/share/doc/tails/website/doc/encryption_and_privacy/truecrypt.en.html#cryptsetup'> otevřít TrueCrypt svazky s cryptsetupem </a> hned jakmile to bude možné."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:30
+msgid "I2P failed to start"
+msgstr "I2P se nepodařilo spustit"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:31
+msgid ""
+"Something went wrong when I2P was starting. Check the logs in /var/log/i2p "
+"for more information."
+msgstr "Něco se pokazilo při startu I2P. Zkontrolujte záznamy ve /var/log/i2p pro více informací."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:42
+msgid "I2P's router console is ready"
+msgstr "I2P konzole routeru je připravena."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:43
+msgid "You can now access I2P's router console on http://127.0.0.1:7657."
+msgstr "Nyní se můžete připojit k I2P konzoli routeru na http://127.0.0.1:7657."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:48
+msgid "I2P is not ready"
+msgstr "I2P není připraveno."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:49
+msgid ""
+"Eepsite tunnel not built within six minutes. Check the router console at "
+"http://127.0.0.1:7657/logs or the logs in /var/log/i2p for more information."
+" Reconnect to the network to try again."
+msgstr "Eepsite tunel nebyl vybudován během šesti minut. Zkontrolujte konzoli routeru na http://127.0.0.1:7657/logs nebo zkontrolujte záznamy ve /var/log/i2p pro více informací. Znovu se připojte k síti a zkuste to prosím znovu."
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:59
+msgid "I2P is ready"
+msgstr "I2P je připraveno"
+
+#: config/chroot_local-includes/usr/local/sbin/tails-i2p:60
+msgid "You can now access services on I2P."
+msgstr "Nyní se můžete připojit ke službám na I2P."
#: ../config/chroot_local-includes/etc/skel/Desktop/Report_an_error.desktop.in.h:1
msgid "Report an error"
@@ -474,17 +489,13 @@ msgstr "Dokumentace Tails"
msgid "Learn how to use Tails"
msgstr "Naučte se používat Tails"
-#: ../config/chroot_local-includes/usr/share/applications/i2p.desktop.in.h:1
-msgid "Anonymous overlay network "
-msgstr "Anonymní překrytí sítě"
-
-#: ../config/chroot_local-includes/usr/share/applications/i2p.desktop.in.h:2
-msgid "i2p"
-msgstr "i2p"
+#: ../config/chroot_local-includes/usr/share/applications/i2p-browser.desktop.in.h:1
+msgid "Anonymous overlay network browser"
+msgstr "Anonymní překrytí síťového prohlížeče"
-#: ../config/chroot_local-includes/usr/share/applications/i2p.desktop.in.h:3
-msgid "Anonymous overlay network"
-msgstr "Anonymní překrytí sítě"
+#: ../config/chroot_local-includes/usr/share/applications/i2p-browser.desktop.in.h:2
+msgid "I2P Browser"
+msgstr "I2P Prohlížeč"
#: ../config/chroot_local-includes/usr/share/applications/tails-about.desktop.in.h:2
msgid "Learn more about Tails"
@@ -506,6 +517,14 @@ msgstr "Vypnout"
msgid "Immediately shut down computer"
msgstr "Okamžitě vypnout počítač"
+#: ../config/chroot_local-includes/usr/share/applications/tor-browser.desktop.in.h:1
+msgid "Tor Browser"
+msgstr "Tor Browser"
+
+#: ../config/chroot_local-includes/usr/share/applications/tor-browser.desktop.in.h:2
+msgid "Anonymous Web Browser"
+msgstr "Anonymní webový prohlížeč"
+
#: ../config/chroot_local-includes/usr/share/applications/unsafe-browser.desktop.in.h:2
msgid "Browse the World Wide Web without anonymity"
msgstr "Procházet World Wide Web bez anonymity"
1
0