authcert_parse.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. #include "core/or/or.h"
  7. #include "feature/dirparse/authcert_parse.h"
  8. #include "feature/dirparse/parsecommon.h"
  9. #include "feature/dirparse/sigcommon.h"
  10. #include "feature/dirparse/unparseable.h"
  11. #include "feature/nodelist/authcert.h"
  12. #include "lib/memarea/memarea.h"
  13. #include "feature/nodelist/authority_cert_st.h"
  14. /** List of tokens recognized in V3 authority certificates. */
  15. static token_rule_t dir_key_certificate_table[] = {
  16. #include "feature/dirparse/authcert_members.i"
  17. T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
  18. END_OF_TABLE
  19. };
  20. /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
  21. * the first character after the certificate. */
  22. authority_cert_t *
  23. authority_cert_parse_from_string(const char *s, size_t maxlen,
  24. const char **end_of_string)
  25. {
  26. /** Reject any certificate at least this big; it is probably an overflow, an
  27. * attack, a bug, or some other nonsense. */
  28. #define MAX_CERT_SIZE (128*1024)
  29. authority_cert_t *cert = NULL, *old_cert;
  30. smartlist_t *tokens = NULL;
  31. char digest[DIGEST_LEN];
  32. directory_token_t *tok;
  33. char fp_declared[DIGEST_LEN];
  34. const char *eos;
  35. size_t len;
  36. int found;
  37. memarea_t *area = NULL;
  38. const char *end_of_s = s + maxlen;
  39. const char *s_dup = s;
  40. s = eat_whitespace_eos(s, end_of_s);
  41. eos = tor_memstr(s, end_of_s - s, "\ndir-key-certification");
  42. if (! eos) {
  43. log_warn(LD_DIR, "No signature found on key certificate");
  44. return NULL;
  45. }
  46. eos = tor_memstr(eos, end_of_s - eos, "\n-----END SIGNATURE-----\n");
  47. if (! eos) {
  48. log_warn(LD_DIR, "No end-of-signature found on key certificate");
  49. return NULL;
  50. }
  51. eos = memchr(eos+2, '\n', end_of_s - (eos+2));
  52. tor_assert(eos);
  53. ++eos;
  54. len = eos - s;
  55. if (len > MAX_CERT_SIZE) {
  56. log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); "
  57. "rejecting", (unsigned long)len);
  58. return NULL;
  59. }
  60. tokens = smartlist_new();
  61. area = memarea_new();
  62. if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
  63. log_warn(LD_DIR, "Error tokenizing key certificate");
  64. goto err;
  65. }
  66. if (router_get_hash_impl(s, eos - s, digest, "dir-key-certificate-version",
  67. "\ndir-key-certification", '\n', DIGEST_SHA1) < 0)
  68. goto err;
  69. tok = smartlist_get(tokens, 0);
  70. if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
  71. log_warn(LD_DIR,
  72. "Key certificate does not begin with a recognized version (3).");
  73. goto err;
  74. }
  75. cert = tor_malloc_zero(sizeof(authority_cert_t));
  76. memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
  77. tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
  78. tor_assert(tok->key);
  79. cert->signing_key = tok->key;
  80. tok->key = NULL;
  81. if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
  82. goto err;
  83. tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
  84. tor_assert(tok->key);
  85. cert->identity_key = tok->key;
  86. tok->key = NULL;
  87. tok = find_by_keyword(tokens, K_FINGERPRINT);
  88. tor_assert(tok->n_args);
  89. if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
  90. strlen(tok->args[0])) != DIGEST_LEN) {
  91. log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
  92. escaped(tok->args[0]));
  93. goto err;
  94. }
  95. if (crypto_pk_get_digest(cert->identity_key,
  96. cert->cache_info.identity_digest))
  97. goto err;
  98. if (tor_memneq(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
  99. log_warn(LD_DIR, "Digest of certificate key didn't match declared "
  100. "fingerprint");
  101. goto err;
  102. }
  103. tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
  104. if (tok) {
  105. struct in_addr in;
  106. char *address = NULL;
  107. tor_assert(tok->n_args);
  108. /* XXX++ use some tor_addr parse function below instead. -RD */
  109. if (tor_addr_port_split(LOG_WARN, tok->args[0], &address,
  110. &cert->dir_port) < 0 ||
  111. tor_inet_aton(address, &in) == 0) {
  112. log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
  113. tor_free(address);
  114. goto err;
  115. }
  116. cert->addr = ntohl(in.s_addr);
  117. tor_free(address);
  118. }
  119. tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
  120. if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
  121. goto err;
  122. }
  123. tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
  124. if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
  125. goto err;
  126. }
  127. tok = smartlist_get(tokens, smartlist_len(tokens)-1);
  128. if (tok->tp != K_DIR_KEY_CERTIFICATION) {
  129. log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
  130. goto err;
  131. }
  132. /* If we already have this cert, don't bother checking the signature. */
  133. old_cert = authority_cert_get_by_digests(
  134. cert->cache_info.identity_digest,
  135. cert->signing_key_digest);
  136. found = 0;
  137. if (old_cert) {
  138. /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
  139. * buy us much. */
  140. if (old_cert->cache_info.signed_descriptor_len == len &&
  141. old_cert->cache_info.signed_descriptor_body &&
  142. tor_memeq(s, old_cert->cache_info.signed_descriptor_body, len)) {
  143. log_debug(LD_DIR, "We already checked the signature on this "
  144. "certificate; no need to do so again.");
  145. found = 1;
  146. }
  147. }
  148. if (!found) {
  149. if (check_signature_token(digest, DIGEST_LEN, tok, cert->identity_key, 0,
  150. "key certificate")) {
  151. goto err;
  152. }
  153. tok = find_by_keyword(tokens, K_DIR_KEY_CROSSCERT);
  154. if (check_signature_token(cert->cache_info.identity_digest,
  155. DIGEST_LEN,
  156. tok,
  157. cert->signing_key,
  158. CST_NO_CHECK_OBJTYPE,
  159. "key cross-certification")) {
  160. goto err;
  161. }
  162. }
  163. cert->cache_info.signed_descriptor_len = len;
  164. cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
  165. memcpy(cert->cache_info.signed_descriptor_body, s, len);
  166. cert->cache_info.signed_descriptor_body[len] = 0;
  167. cert->cache_info.saved_location = SAVED_NOWHERE;
  168. if (end_of_string) {
  169. *end_of_string = eat_whitespace(eos);
  170. }
  171. SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
  172. smartlist_free(tokens);
  173. if (area) {
  174. DUMP_AREA(area, "authority cert");
  175. memarea_drop_all(area);
  176. }
  177. return cert;
  178. err:
  179. dump_desc(s_dup, "authority cert");
  180. authority_cert_free(cert);
  181. SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
  182. smartlist_free(tokens);
  183. if (area) {
  184. DUMP_AREA(area, "authority cert");
  185. memarea_drop_all(area);
  186. }
  187. return NULL;
  188. }