authcert_parse.c 6.7 KB

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