|
@@ -672,79 +672,6 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
|
|
|
return seconds_valid;
|
|
|
}
|
|
|
|
|
|
-/** Parse a service descriptor at <b>str</b> (<b>len</b> bytes). On
|
|
|
- * success, return a newly alloced service_descriptor_t. On failure,
|
|
|
- * return NULL.
|
|
|
- */
|
|
|
-rend_service_descriptor_t *
|
|
|
-rend_parse_service_descriptor(const char *str, size_t len)
|
|
|
-{
|
|
|
- rend_service_descriptor_t *result = NULL;
|
|
|
- int i, n_intro_points;
|
|
|
- size_t keylen, asn1len;
|
|
|
- const char *end, *cp, *eos;
|
|
|
- rend_intro_point_t *intro;
|
|
|
-
|
|
|
- result = tor_malloc_zero(sizeof(rend_service_descriptor_t));
|
|
|
- cp = str;
|
|
|
- end = str+len;
|
|
|
- if (end-cp<2) goto truncated;
|
|
|
- result->version = 0;
|
|
|
- if (end-cp < 2) goto truncated;
|
|
|
- asn1len = ntohs(get_uint16(cp));
|
|
|
- cp += 2;
|
|
|
- if ((size_t)(end-cp) < asn1len) goto truncated;
|
|
|
- result->pk = crypto_pk_asn1_decode(cp, asn1len);
|
|
|
- if (!result->pk) goto truncated;
|
|
|
- cp += asn1len;
|
|
|
- if (end-cp < 4) goto truncated;
|
|
|
- result->timestamp = (time_t) ntohl(get_uint32(cp));
|
|
|
- cp += 4;
|
|
|
- result->protocols = 1<<2; /* always use intro format 2 */
|
|
|
- if (end-cp < 2) goto truncated;
|
|
|
- n_intro_points = ntohs(get_uint16(cp));
|
|
|
- cp += 2;
|
|
|
-
|
|
|
- result->intro_nodes = smartlist_new();
|
|
|
- for (i=0;i<n_intro_points;++i) {
|
|
|
- if (end-cp < 2) goto truncated;
|
|
|
- eos = (const char *)memchr(cp,'\0',end-cp);
|
|
|
- if (!eos) goto truncated;
|
|
|
- /* Write nickname to extend info, but postpone the lookup whether
|
|
|
- * we know that router. It's not part of the parsing process. */
|
|
|
- intro = tor_malloc_zero(sizeof(rend_intro_point_t));
|
|
|
- intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
|
|
|
- strlcpy(intro->extend_info->nickname, cp,
|
|
|
- sizeof(intro->extend_info->nickname));
|
|
|
- smartlist_add(result->intro_nodes, intro);
|
|
|
- cp = eos+1;
|
|
|
- }
|
|
|
- keylen = crypto_pk_keysize(result->pk);
|
|
|
- tor_assert(end-cp >= 0);
|
|
|
- if ((size_t)(end-cp) < keylen) goto truncated;
|
|
|
- if ((size_t)(end-cp) > keylen) {
|
|
|
- log_warn(LD_PROTOCOL,
|
|
|
- "Signature is %d bytes too long on service descriptor.",
|
|
|
- (int)((size_t)(end-cp) - keylen));
|
|
|
- goto error;
|
|
|
- }
|
|
|
- note_crypto_pk_op(REND_CLIENT);
|
|
|
- if (crypto_pk_public_checksig_digest(result->pk,
|
|
|
- (char*)str,cp-str, /* data */
|
|
|
- (char*)cp,end-cp /* signature*/
|
|
|
- )<0) {
|
|
|
- log_warn(LD_PROTOCOL, "Bad signature on service descriptor.");
|
|
|
- goto error;
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
- truncated:
|
|
|
- log_warn(LD_PROTOCOL, "Truncated service descriptor.");
|
|
|
- error:
|
|
|
- rend_service_descriptor_free(result);
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
/** Sets <b>out</b> to the first 10 bytes of the digest of <b>pk</b>,
|
|
|
* base32 encoded. NUL-terminates out. (We use this string to
|
|
|
* identify services in directory requests and .onion URLs.)
|