Back to index

tor  0.2.3.18-rc
rendcommon.c
Go to the documentation of this file.
00001 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00002  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00003 /* See LICENSE for licensing information */
00004 
00011 #include "or.h"
00012 #include "circuitbuild.h"
00013 #include "config.h"
00014 #include "rendclient.h"
00015 #include "rendcommon.h"
00016 #include "rendmid.h"
00017 #include "rendservice.h"
00018 #include "rephist.h"
00019 #include "routerlist.h"
00020 #include "routerparse.h"
00021 
00023 int
00024 rend_cmp_service_ids(const char *one, const char *two)
00025 {
00026   return strcasecmp(one,two);
00027 }
00028 
00031 void
00032 rend_service_descriptor_free(rend_service_descriptor_t *desc)
00033 {
00034   if (!desc)
00035     return;
00036   if (desc->pk)
00037     crypto_pk_free(desc->pk);
00038   if (desc->intro_nodes) {
00039     SMARTLIST_FOREACH(desc->intro_nodes, rend_intro_point_t *, intro,
00040       rend_intro_point_free(intro););
00041     smartlist_free(desc->intro_nodes);
00042   }
00043   if (desc->successful_uploads) {
00044     SMARTLIST_FOREACH(desc->successful_uploads, char *, c, tor_free(c););
00045     smartlist_free(desc->successful_uploads);
00046   }
00047   tor_free(desc);
00048 }
00049 
00052 #define REND_DESC_COOKIE_LEN 16
00053 
00056 #define REND_REPLICA_LEN 1
00057 
00062 void
00063 rend_get_descriptor_id_bytes(char *descriptor_id_out,
00064                              const char *service_id,
00065                              const char *secret_id_part)
00066 {
00067   crypto_digest_t *digest = crypto_digest_new();
00068   crypto_digest_add_bytes(digest, service_id, REND_SERVICE_ID_LEN);
00069   crypto_digest_add_bytes(digest, secret_id_part, DIGEST_LEN);
00070   crypto_digest_get_digest(digest, descriptor_id_out, DIGEST_LEN);
00071   crypto_digest_free(digest);
00072 }
00073 
00079 static void
00080 get_secret_id_part_bytes(char *secret_id_part, uint32_t time_period,
00081                          const char *descriptor_cookie, uint8_t replica)
00082 {
00083   crypto_digest_t *digest = crypto_digest_new();
00084   time_period = htonl(time_period);
00085   crypto_digest_add_bytes(digest, (char*)&time_period, sizeof(uint32_t));
00086   if (descriptor_cookie) {
00087     crypto_digest_add_bytes(digest, descriptor_cookie,
00088                             REND_DESC_COOKIE_LEN);
00089   }
00090   crypto_digest_add_bytes(digest, (const char *)&replica, REND_REPLICA_LEN);
00091   crypto_digest_get_digest(digest, secret_id_part, DIGEST_LEN);
00092   crypto_digest_free(digest);
00093 }
00094 
00098 static uint32_t
00099 get_time_period(time_t now, uint8_t deviation, const char *service_id)
00100 {
00101   /* The time period is the number of REND_TIME_PERIOD_V2_DESC_VALIDITY
00102    * intervals that have passed since the epoch, offset slightly so that
00103    * each service's time periods start and end at a fraction of that
00104    * period based on their first byte. */
00105   return (uint32_t)
00106     (now + ((uint8_t) *service_id) * REND_TIME_PERIOD_V2_DESC_VALIDITY / 256)
00107     / REND_TIME_PERIOD_V2_DESC_VALIDITY + deviation;
00108 }
00109 
00112 static uint32_t
00113 get_seconds_valid(time_t now, const char *service_id)
00114 {
00115   uint32_t result = REND_TIME_PERIOD_V2_DESC_VALIDITY -
00116     ((uint32_t)
00117      (now + ((uint8_t) *service_id) * REND_TIME_PERIOD_V2_DESC_VALIDITY / 256)
00118      % REND_TIME_PERIOD_V2_DESC_VALIDITY);
00119   return result;
00120 }
00121 
00128 int
00129 rend_compute_v2_desc_id(char *desc_id_out, const char *service_id,
00130                         const char *descriptor_cookie, time_t now,
00131                         uint8_t replica)
00132 {
00133   char service_id_binary[REND_SERVICE_ID_LEN];
00134   char secret_id_part[DIGEST_LEN];
00135   uint32_t time_period;
00136   if (!service_id ||
00137       strlen(service_id) != REND_SERVICE_ID_LEN_BASE32) {
00138     log_warn(LD_REND, "Could not compute v2 descriptor ID: "
00139                       "Illegal service ID: %s",
00140              safe_str(service_id));
00141     return -1;
00142   }
00143   if (replica >= REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) {
00144     log_warn(LD_REND, "Could not compute v2 descriptor ID: "
00145                       "Replica number out of range: %d", replica);
00146     return -1;
00147   }
00148   /* Convert service ID to binary. */
00149   if (base32_decode(service_id_binary, REND_SERVICE_ID_LEN,
00150                     service_id, REND_SERVICE_ID_LEN_BASE32) < 0) {
00151     log_warn(LD_REND, "Could not compute v2 descriptor ID: "
00152                       "Illegal characters in service ID: %s",
00153              safe_str_client(service_id));
00154     return -1;
00155   }
00156   /* Calculate current time-period. */
00157   time_period = get_time_period(now, 0, service_id_binary);
00158   /* Calculate secret-id-part = h(time-period + replica). */
00159   get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie,
00160                            replica);
00161   /* Calculate descriptor ID. */
00162   rend_get_descriptor_id_bytes(desc_id_out, service_id_binary, secret_id_part);
00163   return 0;
00164 }
00165 
00169 static int
00170 rend_encode_v2_intro_points(char **encoded, rend_service_descriptor_t *desc)
00171 {
00172   size_t unenc_len;
00173   char *unenc = NULL;
00174   size_t unenc_written = 0;
00175   int i;
00176   int r = -1;
00177   /* Assemble unencrypted list of introduction points. */
00178   unenc_len = smartlist_len(desc->intro_nodes) * 1000; /* too long, but ok. */
00179   unenc = tor_malloc_zero(unenc_len);
00180   for (i = 0; i < smartlist_len(desc->intro_nodes); i++) {
00181     char id_base32[REND_INTRO_POINT_ID_LEN_BASE32 + 1];
00182     char *onion_key = NULL;
00183     size_t onion_key_len;
00184     crypto_pk_t *intro_key;
00185     char *service_key = NULL;
00186     char *address = NULL;
00187     size_t service_key_len;
00188     int res;
00189     rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i);
00190     /* Obtain extend info with introduction point details. */
00191     extend_info_t *info = intro->extend_info;
00192     /* Encode introduction point ID. */
00193     base32_encode(id_base32, sizeof(id_base32),
00194                   info->identity_digest, DIGEST_LEN);
00195     /* Encode onion key. */
00196     if (crypto_pk_write_public_key_to_string(info->onion_key, &onion_key,
00197                                              &onion_key_len) < 0) {
00198       log_warn(LD_REND, "Could not write onion key.");
00199       goto done;
00200     }
00201     /* Encode intro key. */
00202     intro_key = intro->intro_key;
00203     if (!intro_key ||
00204       crypto_pk_write_public_key_to_string(intro_key, &service_key,
00205                                            &service_key_len) < 0) {
00206       log_warn(LD_REND, "Could not write intro key.");
00207       tor_free(onion_key);
00208       goto done;
00209     }
00210     /* Assemble everything for this introduction point. */
00211     address = tor_dup_addr(&info->addr);
00212     res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written,
00213                          "introduction-point %s\n"
00214                          "ip-address %s\n"
00215                          "onion-port %d\n"
00216                          "onion-key\n%s"
00217                          "service-key\n%s",
00218                        id_base32,
00219                        address,
00220                        info->port,
00221                        onion_key,
00222                        service_key);
00223     tor_free(address);
00224     tor_free(onion_key);
00225     tor_free(service_key);
00226     if (res < 0) {
00227       log_warn(LD_REND, "Not enough space for writing introduction point "
00228                         "string.");
00229       goto done;
00230     }
00231     /* Update total number of written bytes for unencrypted intro points. */
00232     unenc_written += res;
00233   }
00234   /* Finalize unencrypted introduction points. */
00235   if (unenc_len < unenc_written + 2) {
00236     log_warn(LD_REND, "Not enough space for finalizing introduction point "
00237                       "string.");
00238     goto done;
00239   }
00240   unenc[unenc_written++] = '\n';
00241   unenc[unenc_written++] = 0;
00242   *encoded = unenc;
00243   r = 0;
00244  done:
00245   if (r<0)
00246     tor_free(unenc);
00247   return r;
00248 }
00249 
00254 static int
00255 rend_encrypt_v2_intro_points_basic(char **encrypted_out,
00256                                    size_t *encrypted_len_out,
00257                                    const char *encoded,
00258                                    smartlist_t *client_cookies)
00259 {
00260   int r = -1, i, pos, enclen, client_blocks;
00261   size_t len, client_entries_len;
00262   char *enc = NULL, iv[CIPHER_IV_LEN], *client_part = NULL,
00263        session_key[CIPHER_KEY_LEN];
00264   smartlist_t *encrypted_session_keys = NULL;
00265   crypto_digest_t *digest;
00266   crypto_cipher_t *cipher;
00267   tor_assert(encoded);
00268   tor_assert(client_cookies && smartlist_len(client_cookies) > 0);
00269 
00270   /* Generate session key. */
00271   if (crypto_rand(session_key, CIPHER_KEY_LEN) < 0) {
00272     log_warn(LD_REND, "Unable to generate random session key to encrypt "
00273                       "introduction point string.");
00274     goto done;
00275   }
00276 
00277   /* Determine length of encrypted introduction points including session
00278    * keys. */
00279   client_blocks = 1 + ((smartlist_len(client_cookies) - 1) /
00280                        REND_BASIC_AUTH_CLIENT_MULTIPLE);
00281   client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
00282                        REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
00283   len = 2 + client_entries_len + CIPHER_IV_LEN + strlen(encoded);
00284   if (client_blocks >= 256) {
00285     log_warn(LD_REND, "Too many clients in introduction point string.");
00286     goto done;
00287   }
00288   enc = tor_malloc_zero(len);
00289   enc[0] = 0x01; /* type of authorization. */
00290   enc[1] = (uint8_t)client_blocks;
00291 
00292   /* Encrypt with random session key. */
00293   enclen = crypto_cipher_encrypt_with_iv(session_key,
00294       enc + 2 + client_entries_len,
00295       CIPHER_IV_LEN + strlen(encoded), encoded, strlen(encoded));
00296 
00297   if (enclen < 0) {
00298     log_warn(LD_REND, "Could not encrypt introduction point string.");
00299     goto done;
00300   }
00301   memcpy(iv, enc + 2 + client_entries_len, CIPHER_IV_LEN);
00302 
00303   /* Encrypt session key for cookies, determine client IDs, and put both
00304    * in a smartlist. */
00305   encrypted_session_keys = smartlist_new();
00306   SMARTLIST_FOREACH_BEGIN(client_cookies, const char *, cookie) {
00307     client_part = tor_malloc_zero(REND_BASIC_AUTH_CLIENT_ENTRY_LEN);
00308     /* Encrypt session key. */
00309     cipher = crypto_cipher_new(cookie);
00310     if (crypto_cipher_encrypt(cipher, client_part +
00311                                   REND_BASIC_AUTH_CLIENT_ID_LEN,
00312                               session_key, CIPHER_KEY_LEN) < 0) {
00313       log_warn(LD_REND, "Could not encrypt session key for client.");
00314       crypto_cipher_free(cipher);
00315       tor_free(client_part);
00316       goto done;
00317     }
00318     crypto_cipher_free(cipher);
00319 
00320     /* Determine client ID. */
00321     digest = crypto_digest_new();
00322     crypto_digest_add_bytes(digest, cookie, REND_DESC_COOKIE_LEN);
00323     crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
00324     crypto_digest_get_digest(digest, client_part,
00325                              REND_BASIC_AUTH_CLIENT_ID_LEN);
00326     crypto_digest_free(digest);
00327 
00328     /* Put both together. */
00329     smartlist_add(encrypted_session_keys, client_part);
00330   } SMARTLIST_FOREACH_END(cookie);
00331 
00332   /* Add some fake client IDs and encrypted session keys. */
00333   for (i = (smartlist_len(client_cookies) - 1) %
00334            REND_BASIC_AUTH_CLIENT_MULTIPLE;
00335        i < REND_BASIC_AUTH_CLIENT_MULTIPLE - 1; i++) {
00336     client_part = tor_malloc_zero(REND_BASIC_AUTH_CLIENT_ENTRY_LEN);
00337     if (crypto_rand(client_part, REND_BASIC_AUTH_CLIENT_ENTRY_LEN) < 0) {
00338       log_warn(LD_REND, "Unable to generate fake client entry.");
00339       tor_free(client_part);
00340       goto done;
00341     }
00342     smartlist_add(encrypted_session_keys, client_part);
00343   }
00344   /* Sort smartlist and put elements in result in order. */
00345   smartlist_sort_digests(encrypted_session_keys);
00346   pos = 2;
00347   SMARTLIST_FOREACH(encrypted_session_keys, const char *, entry, {
00348     memcpy(enc + pos, entry, REND_BASIC_AUTH_CLIENT_ENTRY_LEN);
00349     pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
00350   });
00351   *encrypted_out = enc;
00352   *encrypted_len_out = len;
00353   enc = NULL; /* prevent free. */
00354   r = 0;
00355  done:
00356   tor_free(enc);
00357   if (encrypted_session_keys) {
00358     SMARTLIST_FOREACH(encrypted_session_keys, char *, d, tor_free(d););
00359     smartlist_free(encrypted_session_keys);
00360   }
00361   return r;
00362 }
00363 
00369 static int
00370 rend_encrypt_v2_intro_points_stealth(char **encrypted_out,
00371                                      size_t *encrypted_len_out,
00372                                      const char *encoded,
00373                                      const char *descriptor_cookie)
00374 {
00375   int r = -1, enclen;
00376   char *enc;
00377   tor_assert(encoded);
00378   tor_assert(descriptor_cookie);
00379 
00380   enc = tor_malloc_zero(1 + CIPHER_IV_LEN + strlen(encoded));
00381   enc[0] = 0x02; /* Auth type */
00382   enclen = crypto_cipher_encrypt_with_iv(descriptor_cookie,
00383                                          enc + 1,
00384                                          CIPHER_IV_LEN+strlen(encoded),
00385                                          encoded, strlen(encoded));
00386   if (enclen < 0) {
00387     log_warn(LD_REND, "Could not encrypt introduction point string.");
00388     goto done;
00389   }
00390   *encrypted_out = enc;
00391   *encrypted_len_out = enclen;
00392   enc = NULL; /* prevent free */
00393   r = 0;
00394  done:
00395   tor_free(enc);
00396   return r;
00397 }
00398 
00401 static int
00402 rend_desc_v2_is_parsable(rend_encoded_v2_service_descriptor_t *desc)
00403 {
00404   rend_service_descriptor_t *test_parsed = NULL;
00405   char test_desc_id[DIGEST_LEN];
00406   char *test_intro_content = NULL;
00407   size_t test_intro_size;
00408   size_t test_encoded_size;
00409   const char *test_next;
00410   int res = rend_parse_v2_service_descriptor(&test_parsed, test_desc_id,
00411                                          &test_intro_content,
00412                                          &test_intro_size,
00413                                          &test_encoded_size,
00414                                          &test_next, desc->desc_str);
00415   rend_service_descriptor_free(test_parsed);
00416   tor_free(test_intro_content);
00417   return (res >= 0);
00418 }
00419 
00421 void
00422 rend_encoded_v2_service_descriptor_free(
00423   rend_encoded_v2_service_descriptor_t *desc)
00424 {
00425   if (!desc)
00426     return;
00427   tor_free(desc->desc_str);
00428   tor_free(desc);
00429 }
00430 
00432 void
00433 rend_intro_point_free(rend_intro_point_t *intro)
00434 {
00435   if (!intro)
00436     return;
00437 
00438   extend_info_free(intro->extend_info);
00439   crypto_pk_free(intro->intro_key);
00440 
00441   if (intro->accepted_intro_rsa_parts != NULL) {
00442     digestmap_free(intro->accepted_intro_rsa_parts, _tor_free);
00443   }
00444 
00445   tor_free(intro);
00446 }
00447 
00456 int
00457 rend_encode_v2_descriptors(smartlist_t *descs_out,
00458                            rend_service_descriptor_t *desc, time_t now,
00459                            uint8_t period, rend_auth_type_t auth_type,
00460                            crypto_pk_t *client_key,
00461                            smartlist_t *client_cookies)
00462 {
00463   char service_id[DIGEST_LEN];
00464   uint32_t time_period;
00465   char *ipos_base64 = NULL, *ipos = NULL, *ipos_encrypted = NULL,
00466        *descriptor_cookie = NULL;
00467   size_t ipos_len = 0, ipos_encrypted_len = 0;
00468   int k;
00469   uint32_t seconds_valid;
00470   crypto_pk_t *service_key;
00471   if (!desc) {
00472     log_warn(LD_BUG, "Could not encode v2 descriptor: No desc given.");
00473     return -1;
00474   }
00475   service_key = (auth_type == REND_STEALTH_AUTH) ? client_key : desc->pk;
00476   tor_assert(service_key);
00477   if (auth_type == REND_STEALTH_AUTH) {
00478     descriptor_cookie = smartlist_get(client_cookies, 0);
00479     tor_assert(descriptor_cookie);
00480   }
00481   /* Obtain service_id from public key. */
00482   crypto_pk_get_digest(service_key, service_id);
00483   /* Calculate current time-period. */
00484   time_period = get_time_period(now, period, service_id);
00485   /* Determine how many seconds the descriptor will be valid. */
00486   seconds_valid = period * REND_TIME_PERIOD_V2_DESC_VALIDITY +
00487                   get_seconds_valid(now, service_id);
00488   /* Assemble, possibly encrypt, and encode introduction points. */
00489   if (smartlist_len(desc->intro_nodes) > 0) {
00490     if (rend_encode_v2_intro_points(&ipos, desc) < 0) {
00491       log_warn(LD_REND, "Encoding of introduction points did not succeed.");
00492       return -1;
00493     }
00494     switch (auth_type) {
00495       case REND_NO_AUTH:
00496         ipos_len = strlen(ipos);
00497         break;
00498       case REND_BASIC_AUTH:
00499         if (rend_encrypt_v2_intro_points_basic(&ipos_encrypted,
00500                                                &ipos_encrypted_len, ipos,
00501                                                client_cookies) < 0) {
00502           log_warn(LD_REND, "Encrypting of introduction points did not "
00503                             "succeed.");
00504           tor_free(ipos);
00505           return -1;
00506         }
00507         tor_free(ipos);
00508         ipos = ipos_encrypted;
00509         ipos_len = ipos_encrypted_len;
00510         break;
00511       case REND_STEALTH_AUTH:
00512         if (rend_encrypt_v2_intro_points_stealth(&ipos_encrypted,
00513                                                  &ipos_encrypted_len, ipos,
00514                                                  descriptor_cookie) < 0) {
00515           log_warn(LD_REND, "Encrypting of introduction points did not "
00516                             "succeed.");
00517           tor_free(ipos);
00518           return -1;
00519         }
00520         tor_free(ipos);
00521         ipos = ipos_encrypted;
00522         ipos_len = ipos_encrypted_len;
00523         break;
00524       default:
00525         log_warn(LD_REND|LD_BUG, "Unrecognized authorization type %d",
00526                  (int)auth_type);
00527         tor_free(ipos);
00528         return -1;
00529     }
00530     /* Base64-encode introduction points. */
00531     ipos_base64 = tor_malloc_zero(ipos_len * 2);
00532     if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len)<0) {
00533       log_warn(LD_REND, "Could not encode introduction point string to "
00534                "base64. length=%d", (int)ipos_len);
00535       tor_free(ipos_base64);
00536       tor_free(ipos);
00537       return -1;
00538     }
00539     tor_free(ipos);
00540   }
00541   /* Encode REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS descriptors. */
00542   for (k = 0; k < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; k++) {
00543     char secret_id_part[DIGEST_LEN];
00544     char secret_id_part_base32[REND_SECRET_ID_PART_LEN_BASE32 + 1];
00545     char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
00546     char *permanent_key = NULL;
00547     size_t permanent_key_len;
00548     char published[ISO_TIME_LEN+1];
00549     int i;
00550     char protocol_versions_string[16]; /* max len: "0,1,2,3,4,5,6,7\0" */
00551     size_t protocol_versions_written;
00552     size_t desc_len;
00553     char *desc_str = NULL;
00554     int result = 0;
00555     size_t written = 0;
00556     char desc_digest[DIGEST_LEN];
00557     rend_encoded_v2_service_descriptor_t *enc =
00558       tor_malloc_zero(sizeof(rend_encoded_v2_service_descriptor_t));
00559     /* Calculate secret-id-part = h(time-period + cookie + replica). */
00560     get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie,
00561                              k);
00562     base32_encode(secret_id_part_base32, sizeof(secret_id_part_base32),
00563                   secret_id_part, DIGEST_LEN);
00564     /* Calculate descriptor ID. */
00565     rend_get_descriptor_id_bytes(enc->desc_id, service_id, secret_id_part);
00566     base32_encode(desc_id_base32, sizeof(desc_id_base32),
00567                   enc->desc_id, DIGEST_LEN);
00568     /* PEM-encode the public key */
00569     if (crypto_pk_write_public_key_to_string(service_key, &permanent_key,
00570                                              &permanent_key_len) < 0) {
00571       log_warn(LD_BUG, "Could not write public key to string.");
00572       rend_encoded_v2_service_descriptor_free(enc);
00573       goto err;
00574     }
00575     /* Encode timestamp. */
00576     format_iso_time(published, desc->timestamp);
00577     /* Write protocol-versions bitmask to comma-separated value string. */
00578     protocol_versions_written = 0;
00579     for (i = 0; i < 8; i++) {
00580       if (desc->protocols & 1 << i) {
00581         tor_snprintf(protocol_versions_string + protocol_versions_written,
00582                      16 - protocol_versions_written, "%d,", i);
00583         protocol_versions_written += 2;
00584       }
00585     }
00586     if (protocol_versions_written)
00587       protocol_versions_string[protocol_versions_written - 1] = '\0';
00588     else
00589       protocol_versions_string[0]= '\0';
00590     /* Assemble complete descriptor. */
00591     desc_len = 2000 + smartlist_len(desc->intro_nodes) * 1000; /* far too long,
00592                                                                   but okay.*/
00593     enc->desc_str = desc_str = tor_malloc_zero(desc_len);
00594     result = tor_snprintf(desc_str, desc_len,
00595              "rendezvous-service-descriptor %s\n"
00596              "version 2\n"
00597              "permanent-key\n%s"
00598              "secret-id-part %s\n"
00599              "publication-time %s\n"
00600              "protocol-versions %s\n",
00601         desc_id_base32,
00602         permanent_key,
00603         secret_id_part_base32,
00604         published,
00605         protocol_versions_string);
00606     tor_free(permanent_key);
00607     if (result < 0) {
00608       log_warn(LD_BUG, "Descriptor ran out of room.");
00609       rend_encoded_v2_service_descriptor_free(enc);
00610       goto err;
00611     }
00612     written = result;
00613     /* Add introduction points. */
00614     if (ipos_base64) {
00615       result = tor_snprintf(desc_str + written, desc_len - written,
00616                             "introduction-points\n"
00617                             "-----BEGIN MESSAGE-----\n%s"
00618                             "-----END MESSAGE-----\n",
00619                             ipos_base64);
00620       if (result < 0) {
00621         log_warn(LD_BUG, "could not write introduction points.");
00622         rend_encoded_v2_service_descriptor_free(enc);
00623         goto err;
00624       }
00625       written += result;
00626     }
00627     /* Add signature. */
00628     strlcpy(desc_str + written, "signature\n", desc_len - written);
00629     written += strlen(desc_str + written);
00630     if (crypto_digest(desc_digest, desc_str, written) < 0) {
00631       log_warn(LD_BUG, "could not create digest.");
00632       rend_encoded_v2_service_descriptor_free(enc);
00633       goto err;
00634     }
00635     if (router_append_dirobj_signature(desc_str + written,
00636                                        desc_len - written,
00637                                        desc_digest, DIGEST_LEN,
00638                                        service_key) < 0) {
00639       log_warn(LD_BUG, "Couldn't sign desc.");
00640       rend_encoded_v2_service_descriptor_free(enc);
00641       goto err;
00642     }
00643     written += strlen(desc_str+written);
00644     if (written+2 > desc_len) {
00645         log_warn(LD_BUG, "Could not finish desc.");
00646         rend_encoded_v2_service_descriptor_free(enc);
00647         goto err;
00648     }
00649     desc_str[written++] = '\n';
00650     desc_str[written++] = 0;
00651     /* Check if we can parse our own descriptor. */
00652     if (!rend_desc_v2_is_parsable(enc)) {
00653       log_warn(LD_BUG, "Could not parse my own descriptor: %s", desc_str);
00654       rend_encoded_v2_service_descriptor_free(enc);
00655       goto err;
00656     }
00657     smartlist_add(descs_out, enc);
00658   }
00659 
00660   log_info(LD_REND, "Successfully encoded a v2 descriptor and "
00661                     "confirmed that it is parsable.");
00662   goto done;
00663 
00664  err:
00665   SMARTLIST_FOREACH(descs_out, rend_encoded_v2_service_descriptor_t *, d,
00666                     rend_encoded_v2_service_descriptor_free(d););
00667   smartlist_clear(descs_out);
00668   seconds_valid = -1;
00669 
00670  done:
00671   tor_free(ipos_base64);
00672   return seconds_valid;
00673 }
00674 
00679 rend_service_descriptor_t *
00680 rend_parse_service_descriptor(const char *str, size_t len)
00681 {
00682   rend_service_descriptor_t *result = NULL;
00683   int i, n_intro_points;
00684   size_t keylen, asn1len;
00685   const char *end, *cp, *eos;
00686   rend_intro_point_t *intro;
00687 
00688   result = tor_malloc_zero(sizeof(rend_service_descriptor_t));
00689   cp = str;
00690   end = str+len;
00691   if (end-cp<2) goto truncated;
00692   result->version = 0;
00693   if (end-cp < 2) goto truncated;
00694   asn1len = ntohs(get_uint16(cp));
00695   cp += 2;
00696   if ((size_t)(end-cp) < asn1len) goto truncated;
00697   result->pk = crypto_pk_asn1_decode(cp, asn1len);
00698   if (!result->pk) goto truncated;
00699   cp += asn1len;
00700   if (end-cp < 4) goto truncated;
00701   result->timestamp = (time_t) ntohl(get_uint32(cp));
00702   cp += 4;
00703   result->protocols = 1<<2; /* always use intro format 2 */
00704   if (end-cp < 2) goto truncated;
00705   n_intro_points = ntohs(get_uint16(cp));
00706   cp += 2;
00707 
00708   result->intro_nodes = smartlist_new();
00709   for (i=0;i<n_intro_points;++i) {
00710     if (end-cp < 2) goto truncated;
00711     eos = (const char *)memchr(cp,'\0',end-cp);
00712     if (!eos) goto truncated;
00713     /* Write nickname to extend info, but postpone the lookup whether
00714      * we know that router. It's not part of the parsing process. */
00715     intro = tor_malloc_zero(sizeof(rend_intro_point_t));
00716     intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
00717     strlcpy(intro->extend_info->nickname, cp,
00718             sizeof(intro->extend_info->nickname));
00719     smartlist_add(result->intro_nodes, intro);
00720     cp = eos+1;
00721   }
00722   keylen = crypto_pk_keysize(result->pk);
00723   tor_assert(end-cp >= 0);
00724   if ((size_t)(end-cp) < keylen) goto truncated;
00725   if ((size_t)(end-cp) > keylen) {
00726     log_warn(LD_PROTOCOL,
00727              "Signature is %d bytes too long on service descriptor.",
00728              (int)((size_t)(end-cp) - keylen));
00729     goto error;
00730   }
00731   note_crypto_pk_op(REND_CLIENT);
00732   if (crypto_pk_public_checksig_digest(result->pk,
00733                                        (char*)str,cp-str, /* data */
00734                                        (char*)cp,end-cp  /* signature*/
00735                                        )<0) {
00736     log_warn(LD_PROTOCOL, "Bad signature on service descriptor.");
00737     goto error;
00738   }
00739 
00740   return result;
00741  truncated:
00742   log_warn(LD_PROTOCOL, "Truncated service descriptor.");
00743  error:
00744   rend_service_descriptor_free(result);
00745   return NULL;
00746 }
00747 
00752 int
00753 rend_get_service_id(crypto_pk_t *pk, char *out)
00754 {
00755   char buf[DIGEST_LEN];
00756   tor_assert(pk);
00757   if (crypto_pk_get_digest(pk, buf) < 0)
00758     return -1;
00759   base32_encode(out, REND_SERVICE_ID_LEN_BASE32+1, buf, REND_SERVICE_ID_LEN);
00760   return 0;
00761 }
00762 
00763 /* ==== Rendezvous service descriptor cache. */
00764 
00767 #define REND_CACHE_MAX_AGE (2*24*60*60)
00768 
00770 #define REND_CACHE_MAX_SKEW (24*60*60)
00771 
00774 static strmap_t *rend_cache = NULL;
00775 
00778 static digestmap_t *rend_cache_v2_dir = NULL;
00779 
00782 void
00783 rend_cache_init(void)
00784 {
00785   rend_cache = strmap_new();
00786   rend_cache_v2_dir = digestmap_new();
00787 }
00788 
00790 static void
00791 rend_cache_entry_free(rend_cache_entry_t *e)
00792 {
00793   if (!e)
00794     return;
00795   rend_service_descriptor_free(e->parsed);
00796   tor_free(e->desc);
00797   tor_free(e);
00798 }
00799 
00802 static void
00803 _rend_cache_entry_free(void *p)
00804 {
00805   rend_cache_entry_free(p);
00806 }
00807 
00809 void
00810 rend_cache_free_all(void)
00811 {
00812   strmap_free(rend_cache, _rend_cache_entry_free);
00813   digestmap_free(rend_cache_v2_dir, _rend_cache_entry_free);
00814   rend_cache = NULL;
00815   rend_cache_v2_dir = NULL;
00816 }
00817 
00820 void
00821 rend_cache_clean(time_t now)
00822 {
00823   strmap_iter_t *iter;
00824   const char *key;
00825   void *val;
00826   rend_cache_entry_t *ent;
00827   time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
00828   for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) {
00829     strmap_iter_get(iter, &key, &val);
00830     ent = (rend_cache_entry_t*)val;
00831     if (ent->parsed->timestamp < cutoff) {
00832       iter = strmap_iter_next_rmv(rend_cache, iter);
00833       rend_cache_entry_free(ent);
00834     } else {
00835       iter = strmap_iter_next(rend_cache, iter);
00836     }
00837   }
00838 }
00839 
00842 void
00843 rend_cache_purge(void)
00844 {
00845   if (rend_cache) {
00846     log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache");
00847     strmap_free(rend_cache, _rend_cache_entry_free);
00848   }
00849   rend_cache = strmap_new();
00850 }
00851 
00854 void
00855 rend_cache_clean_v2_descs_as_dir(time_t now)
00856 {
00857   digestmap_iter_t *iter;
00858   time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
00859   for (iter = digestmap_iter_init(rend_cache_v2_dir);
00860        !digestmap_iter_done(iter); ) {
00861     const char *key;
00862     void *val;
00863     rend_cache_entry_t *ent;
00864     digestmap_iter_get(iter, &key, &val);
00865     ent = val;
00866     if (ent->parsed->timestamp < cutoff ||
00867         !hid_serv_responsible_for_desc_id(key)) {
00868       char key_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
00869       base32_encode(key_base32, sizeof(key_base32), key, DIGEST_LEN);
00870       log_info(LD_REND, "Removing descriptor with ID '%s' from cache",
00871                safe_str_client(key_base32));
00872       iter = digestmap_iter_next_rmv(rend_cache_v2_dir, iter);
00873       rend_cache_entry_free(ent);
00874     } else {
00875       iter = digestmap_iter_next(rend_cache_v2_dir, iter);
00876     }
00877   }
00878 }
00879 
00884 int
00885 rend_id_is_in_interval(const char *a, const char *b, const char *c)
00886 {
00887   int a_b, b_c, c_a;
00888   tor_assert(a);
00889   tor_assert(b);
00890   tor_assert(c);
00891 
00892   /* There are five cases in which a is outside the interval ]b,c]: */
00893   a_b = tor_memcmp(a,b,DIGEST_LEN);
00894   if (a_b == 0)
00895     return 0; /* 1. a == b (b is excluded) */
00896   b_c = tor_memcmp(b,c,DIGEST_LEN);
00897   if (b_c == 0)
00898     return 0; /* 2. b == c (interval is empty) */
00899   else if (a_b <= 0 && b_c < 0)
00900     return 0; /* 3. a b c */
00901   c_a = tor_memcmp(c,a,DIGEST_LEN);
00902   if (c_a < 0 && a_b <= 0)
00903     return 0; /* 4. c a b */
00904   else if (b_c < 0 && c_a < 0)
00905     return 0; /* 5. b c a */
00906 
00907   /* In the other cases (a c b; b a c; c b a), a is inside the interval. */
00908   return 1;
00909 }
00910 
00913 int
00914 rend_valid_service_id(const char *query)
00915 {
00916   if (strlen(query) != REND_SERVICE_ID_LEN_BASE32)
00917     return 0;
00918 
00919   if (strspn(query, BASE32_CHARS) != REND_SERVICE_ID_LEN_BASE32)
00920     return 0;
00921 
00922   return 1;
00923 }
00924 
00931 int
00932 rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
00933 {
00934   char key[REND_SERVICE_ID_LEN_BASE32+2]; /* <version><query>\0 */
00935   tor_assert(rend_cache);
00936   if (!rend_valid_service_id(query))
00937     return -1;
00938   *e = NULL;
00939   if (version != 0) {
00940     tor_snprintf(key, sizeof(key), "2%s", query);
00941     *e = strmap_get_lc(rend_cache, key);
00942   }
00943   if (!*e && version != 2) {
00944     tor_snprintf(key, sizeof(key), "0%s", query);
00945     *e = strmap_get_lc(rend_cache, key);
00946   }
00947   if (!*e)
00948     return 0;
00949   tor_assert((*e)->parsed && (*e)->parsed->intro_nodes);
00950   /* XXX023 hack for now, to return "not found" if there are no intro
00951    * points remaining. See bug 997. */
00952   if (! rend_client_any_intro_points_usable(*e))
00953     return 0;
00954   return 1;
00955 }
00956 
00965 int
00966 rend_cache_lookup_desc(const char *query, int version, const char **desc,
00967                        size_t *desc_len)
00968 {
00969   rend_cache_entry_t *e;
00970   int r;
00971   r = rend_cache_lookup_entry(query,version,&e);
00972   if (r <= 0) return r;
00973   *desc = e->desc;
00974   *desc_len = e->len;
00975   return 1;
00976 }
00977 
00982 int
00983 rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
00984 {
00985   rend_cache_entry_t *e;
00986   char desc_id_digest[DIGEST_LEN];
00987   tor_assert(rend_cache_v2_dir);
00988   if (base32_decode(desc_id_digest, DIGEST_LEN,
00989                     desc_id, REND_DESC_ID_V2_LEN_BASE32) < 0) {
00990     log_fn(LOG_PROTOCOL_WARN, LD_REND,
00991            "Rejecting v2 rendezvous descriptor request -- descriptor ID "
00992            "contains illegal characters: %s",
00993            safe_str(desc_id));
00994     return -1;
00995   }
00996   /* Lookup descriptor and return. */
00997   e = digestmap_get(rend_cache_v2_dir, desc_id_digest);
00998   if (e) {
00999     *desc = e->desc;
01000     return 1;
01001   }
01002   return 0;
01003 }
01004 
01023 int
01024 rend_cache_store(const char *desc, size_t desc_len, int published,
01025                  const char *service_id)
01026 {
01027   rend_cache_entry_t *e;
01028   rend_service_descriptor_t *parsed;
01029   char query[REND_SERVICE_ID_LEN_BASE32+1];
01030   char key[REND_SERVICE_ID_LEN_BASE32+2]; /* 0<query>\0 */
01031   time_t now;
01032   tor_assert(rend_cache);
01033   parsed = rend_parse_service_descriptor(desc,desc_len);
01034   if (!parsed) {
01035     log_warn(LD_PROTOCOL,"Couldn't parse service descriptor.");
01036     return -2;
01037   }
01038   if (rend_get_service_id(parsed->pk, query)<0) {
01039     log_warn(LD_BUG,"Couldn't compute service ID.");
01040     rend_service_descriptor_free(parsed);
01041     return -2;
01042   }
01043   if ((service_id != NULL) && strcmp(query, service_id)) {
01044     log_warn(LD_REND, "Received service descriptor for service ID %s; "
01045              "expected descriptor for service ID %s.",
01046              query, safe_str(service_id));
01047     rend_service_descriptor_free(parsed);
01048     return -2;
01049   }
01050   now = time(NULL);
01051   if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
01052     log_fn(LOG_PROTOCOL_WARN, LD_REND,
01053            "Service descriptor %s is too old.",
01054            safe_str_client(query));
01055     rend_service_descriptor_free(parsed);
01056     return -2;
01057   }
01058   if (parsed->timestamp > now+REND_CACHE_MAX_SKEW) {
01059     log_fn(LOG_PROTOCOL_WARN, LD_REND,
01060            "Service descriptor %s is too far in the future.",
01061            safe_str_client(query));
01062     rend_service_descriptor_free(parsed);
01063     return -2;
01064   }
01065   /* Do we have a v2 descriptor and fetched this descriptor as a client? */
01066   tor_snprintf(key, sizeof(key), "2%s", query);
01067   if (!published && strmap_get_lc(rend_cache, key)) {
01068     log_info(LD_REND, "We already have a v2 descriptor for service %s.",
01069              safe_str_client(query));
01070     rend_service_descriptor_free(parsed);
01071     return -1;
01072   }
01073   tor_snprintf(key, sizeof(key), "0%s", query);
01074   e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key);
01075   if (e && e->parsed->timestamp > parsed->timestamp) {
01076     log_info(LD_REND,"We already have a newer service descriptor %s with the "
01077              "same ID and version.",
01078              safe_str_client(query));
01079     rend_service_descriptor_free(parsed);
01080     return 0;
01081   }
01082   if (e && e->len == desc_len && tor_memeq(desc,e->desc,desc_len)) {
01083     log_info(LD_REND,"We already have this service descriptor %s.",
01084              safe_str_client(query));
01085     e->received = time(NULL);
01086     rend_service_descriptor_free(parsed);
01087     return 0;
01088   }
01089   if (!e) {
01090     e = tor_malloc_zero(sizeof(rend_cache_entry_t));
01091     strmap_set_lc(rend_cache, key, e);
01092   } else {
01093     rend_service_descriptor_free(e->parsed);
01094     tor_free(e->desc);
01095   }
01096   e->received = time(NULL);
01097   e->parsed = parsed;
01098   e->len = desc_len;
01099   e->desc = tor_malloc(desc_len);
01100   memcpy(e->desc, desc, desc_len);
01101 
01102   log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
01103             safe_str_client(query), (int)desc_len);
01104   return 1;
01105 }
01106 
01118 int
01119 rend_cache_store_v2_desc_as_dir(const char *desc)
01120 {
01121   rend_service_descriptor_t *parsed;
01122   char desc_id[DIGEST_LEN];
01123   char *intro_content;
01124   size_t intro_size;
01125   size_t encoded_size;
01126   char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
01127   int number_parsed = 0, number_stored = 0;
01128   const char *current_desc = desc;
01129   const char *next_desc;
01130   rend_cache_entry_t *e;
01131   time_t now = time(NULL);
01132   tor_assert(rend_cache_v2_dir);
01133   tor_assert(desc);
01134   if (!hid_serv_acting_as_directory()) {
01135     /* Cannot store descs, because we are (currently) not acting as
01136      * hidden service directory. */
01137     log_info(LD_REND, "Cannot store descs: Not acting as hs dir");
01138     return -2;
01139   }
01140   while (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
01141                                           &intro_size, &encoded_size,
01142                                           &next_desc, current_desc) >= 0) {
01143     number_parsed++;
01144     /* We don't care about the introduction points. */
01145     tor_free(intro_content);
01146     /* For pretty log statements. */
01147     base32_encode(desc_id_base32, sizeof(desc_id_base32),
01148                   desc_id, DIGEST_LEN);
01149     /* Is desc ID in the range that we are (directly or indirectly) responsible
01150      * for? */
01151     if (!hid_serv_responsible_for_desc_id(desc_id)) {
01152       log_info(LD_REND, "Service descriptor with desc ID %s is not in "
01153                         "interval that we are responsible for.",
01154                safe_str_client(desc_id_base32));
01155       goto skip;
01156     }
01157     /* Is descriptor too old? */
01158     if (parsed->timestamp < now - REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
01159       log_info(LD_REND, "Service descriptor with desc ID %s is too old.",
01160                safe_str(desc_id_base32));
01161       goto skip;
01162     }
01163     /* Is descriptor too far in the future? */
01164     if (parsed->timestamp > now + REND_CACHE_MAX_SKEW) {
01165       log_info(LD_REND, "Service descriptor with desc ID %s is too far in the "
01166                         "future.",
01167                safe_str(desc_id_base32));
01168       goto skip;
01169     }
01170     /* Do we already have a newer descriptor? */
01171     e = digestmap_get(rend_cache_v2_dir, desc_id);
01172     if (e && e->parsed->timestamp > parsed->timestamp) {
01173       log_info(LD_REND, "We already have a newer service descriptor with the "
01174                         "same desc ID %s and version.",
01175                safe_str(desc_id_base32));
01176       goto skip;
01177     }
01178     /* Do we already have this descriptor? */
01179     if (e && !strcmp(desc, e->desc)) {
01180       log_info(LD_REND, "We already have this service descriptor with desc "
01181                         "ID %s.", safe_str(desc_id_base32));
01182       e->received = time(NULL);
01183       goto skip;
01184     }
01185     /* Store received descriptor. */
01186     if (!e) {
01187       e = tor_malloc_zero(sizeof(rend_cache_entry_t));
01188       digestmap_set(rend_cache_v2_dir, desc_id, e);
01189     } else {
01190       rend_service_descriptor_free(e->parsed);
01191       tor_free(e->desc);
01192     }
01193     e->received = time(NULL);
01194     e->parsed = parsed;
01195     e->desc = tor_strndup(current_desc, encoded_size);
01196     e->len = encoded_size;
01197     log_info(LD_REND, "Successfully stored service descriptor with desc ID "
01198                       "'%s' and len %d.",
01199              safe_str(desc_id_base32), (int)encoded_size);
01200     number_stored++;
01201     goto advance;
01202   skip:
01203     rend_service_descriptor_free(parsed);
01204   advance:
01205     /* advance to next descriptor, if available. */
01206     current_desc = next_desc;
01207     /* check if there is a next descriptor. */
01208     if (!current_desc ||
01209         strcmpstart(current_desc, "rendezvous-service-descriptor "))
01210       break;
01211   }
01212   if (!number_parsed) {
01213     log_info(LD_REND, "Could not parse any descriptor.");
01214     return -1;
01215   }
01216   log_info(LD_REND, "Parsed %d and added %d descriptor%s.",
01217            number_parsed, number_stored, number_stored != 1 ? "s" : "");
01218   return number_stored;
01219 }
01220 
01236 int
01237 rend_cache_store_v2_desc_as_client(const char *desc,
01238                                    const rend_data_t *rend_query)
01239 {
01240   /*XXXX this seems to have a bit of duplicate code with
01241    * rend_cache_store_v2_desc_as_dir().  Fix that. */
01242   /* Though having similar elements, both functions were separated on
01243    * purpose:
01244    * - dirs don't care about encoded/encrypted introduction points, clients
01245    *   do.
01246    * - dirs store descriptors in a separate cache by descriptor ID, whereas
01247    *   clients store them by service ID; both caches are different data
01248    *   structures and have different access methods.
01249    * - dirs store a descriptor only if they are responsible for its ID,
01250    *   clients do so in every way (because they have requested it before).
01251    * - dirs can process multiple concatenated descriptors which is required
01252    *   for replication, whereas clients only accept a single descriptor.
01253    * Thus, combining both methods would result in a lot of if statements
01254    * which probably would not improve, but worsen code readability. -KL */
01255   rend_service_descriptor_t *parsed = NULL;
01256   char desc_id[DIGEST_LEN];
01257   char *intro_content = NULL;
01258   size_t intro_size;
01259   size_t encoded_size;
01260   const char *next_desc;
01261   time_t now = time(NULL);
01262   char key[REND_SERVICE_ID_LEN_BASE32+2];
01263   char service_id[REND_SERVICE_ID_LEN_BASE32+1];
01264   rend_cache_entry_t *e;
01265   int retval;
01266   tor_assert(rend_cache);
01267   tor_assert(desc);
01268   /* Parse the descriptor. */
01269   if (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
01270                                        &intro_size, &encoded_size,
01271                                        &next_desc, desc) < 0) {
01272     log_warn(LD_REND, "Could not parse descriptor.");
01273     retval = -2;
01274     goto err;
01275   }
01276   /* Compute service ID from public key. */
01277   if (rend_get_service_id(parsed->pk, service_id)<0) {
01278     log_warn(LD_REND, "Couldn't compute service ID.");
01279     retval = -2;
01280     goto err;
01281   }
01282   if (strcmp(rend_query->onion_address, service_id)) {
01283     log_warn(LD_REND, "Received service descriptor for service ID %s; "
01284              "expected descriptor for service ID %s.",
01285              service_id, safe_str(rend_query->onion_address));
01286     retval = -2;
01287     goto err;
01288   }
01289   /* Decode/decrypt introduction points. */
01290   if (intro_content) {
01291     if (rend_query->auth_type != REND_NO_AUTH &&
01292         !tor_mem_is_zero(rend_query->descriptor_cookie,
01293                          sizeof(rend_query->descriptor_cookie))) {
01294       char *ipos_decrypted = NULL;
01295       size_t ipos_decrypted_size;
01296       if (rend_decrypt_introduction_points(&ipos_decrypted,
01297                                            &ipos_decrypted_size,
01298                                            rend_query->descriptor_cookie,
01299                                            intro_content,
01300                                            intro_size) < 0) {
01301         log_warn(LD_REND, "Failed to decrypt introduction points. We are "
01302                  "probably unable to parse the encoded introduction points.");
01303       } else {
01304         /* Replace encrypted with decrypted introduction points. */
01305         log_info(LD_REND, "Successfully decrypted introduction points.");
01306         tor_free(intro_content);
01307         intro_content = ipos_decrypted;
01308         intro_size = ipos_decrypted_size;
01309       }
01310     }
01311     if (rend_parse_introduction_points(parsed, intro_content,
01312                                        intro_size) <= 0) {
01313       log_warn(LD_REND, "Failed to parse introduction points. Either the "
01314                "service has published a corrupt descriptor or you have "
01315                "provided invalid authorization data.");
01316       retval = -2;
01317       goto err;
01318     }
01319   } else {
01320     log_info(LD_REND, "Descriptor does not contain any introduction points.");
01321     parsed->intro_nodes = smartlist_new();
01322   }
01323   /* We don't need the encoded/encrypted introduction points any longer. */
01324   tor_free(intro_content);
01325   /* Is descriptor too old? */
01326   if (parsed->timestamp < now - REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
01327     log_warn(LD_REND, "Service descriptor with service ID %s is too old.",
01328              safe_str_client(service_id));
01329     retval = -2;
01330     goto err;
01331   }
01332   /* Is descriptor too far in the future? */
01333   if (parsed->timestamp > now + REND_CACHE_MAX_SKEW) {
01334     log_warn(LD_REND, "Service descriptor with service ID %s is too far in "
01335                       "the future.", safe_str_client(service_id));
01336     retval = -2;
01337     goto err;
01338   }
01339   /* Do we have a v0 descriptor? */
01340   tor_snprintf(key, sizeof(key), "0%s", service_id);
01341   if (strmap_get_lc(rend_cache, key)) {
01342     log_info(LD_REND, "We already have a v0 descriptor for service ID %s.",
01343              safe_str_client(service_id));
01344     retval = -1;
01345     goto err;
01346   }
01347   /* Do we already have a newer descriptor? */
01348   tor_snprintf(key, sizeof(key), "2%s", service_id);
01349   e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key);
01350   if (e && e->parsed->timestamp > parsed->timestamp) {
01351     log_info(LD_REND, "We already have a newer service descriptor for "
01352                       "service ID %s with the same desc ID and version.",
01353              safe_str_client(service_id));
01354     retval = 0;
01355     goto err;
01356   }
01357   /* Do we already have this descriptor? */
01358   if (e && !strcmp(desc, e->desc)) {
01359     log_info(LD_REND,"We already have this service descriptor %s.",
01360              safe_str_client(service_id));
01361     e->received = time(NULL);
01362     retval = 0;
01363     goto err;
01364   }
01365   if (!e) {
01366     e = tor_malloc_zero(sizeof(rend_cache_entry_t));
01367     strmap_set_lc(rend_cache, key, e);
01368   } else {
01369     rend_service_descriptor_free(e->parsed);
01370     tor_free(e->desc);
01371   }
01372   e->received = time(NULL);
01373   e->parsed = parsed;
01374   e->desc = tor_malloc_zero(encoded_size + 1);
01375   strlcpy(e->desc, desc, encoded_size + 1);
01376   e->len = encoded_size;
01377   log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
01378             safe_str_client(service_id), (int)encoded_size);
01379   return 1;
01380 
01381  err:
01382   rend_service_descriptor_free(parsed);
01383   tor_free(intro_content);
01384   return retval;
01385 }
01386 
01389 void
01390 rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
01391                         int command, size_t length,
01392                         const uint8_t *payload)
01393 {
01394   or_circuit_t *or_circ = NULL;
01395   origin_circuit_t *origin_circ = NULL;
01396   int r = -2;
01397   if (CIRCUIT_IS_ORIGIN(circ)) {
01398     origin_circ = TO_ORIGIN_CIRCUIT(circ);
01399     if (!layer_hint || layer_hint != origin_circ->cpath->prev) {
01400       log_fn(LOG_PROTOCOL_WARN, LD_APP,
01401              "Relay cell (rend purpose %d) from wrong hop on origin circ",
01402              command);
01403       origin_circ = NULL;
01404     }
01405   } else {
01406     or_circ = TO_OR_CIRCUIT(circ);
01407   }
01408 
01409   switch (command) {
01410     case RELAY_COMMAND_ESTABLISH_INTRO:
01411       if (or_circ)
01412         r = rend_mid_establish_intro(or_circ,payload,length);
01413       break;
01414     case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
01415       if (or_circ)
01416         r = rend_mid_establish_rendezvous(or_circ,payload,length);
01417       break;
01418     case RELAY_COMMAND_INTRODUCE1:
01419       if (or_circ)
01420         r = rend_mid_introduce(or_circ,payload,length);
01421       break;
01422     case RELAY_COMMAND_INTRODUCE2:
01423       if (origin_circ)
01424         r = rend_service_introduce(origin_circ,payload,length);
01425       break;
01426     case RELAY_COMMAND_INTRODUCE_ACK:
01427       if (origin_circ)
01428         r = rend_client_introduction_acked(origin_circ,payload,length);
01429       break;
01430     case RELAY_COMMAND_RENDEZVOUS1:
01431       if (or_circ)
01432         r = rend_mid_rendezvous(or_circ,payload,length);
01433       break;
01434     case RELAY_COMMAND_RENDEZVOUS2:
01435       if (origin_circ)
01436         r = rend_client_receive_rendezvous(origin_circ,payload,length);
01437       break;
01438     case RELAY_COMMAND_INTRO_ESTABLISHED:
01439       if (origin_circ)
01440         r = rend_service_intro_established(origin_circ,payload,length);
01441       break;
01442     case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
01443       if (origin_circ)
01444         r = rend_client_rendezvous_acked(origin_circ,payload,length);
01445       break;
01446     default:
01447       tor_fragile_assert();
01448   }
01449 
01450   if (r == -2)
01451     log_info(LD_PROTOCOL, "Dropping cell (type %d) for wrong circuit type.",
01452              command);
01453 }
01454 
01456 int
01457 rend_cache_size(void)
01458 {
01459   return strmap_size(rend_cache);
01460 }
01461 
01464 rend_data_t *
01465 rend_data_dup(const rend_data_t *data)
01466 {
01467   tor_assert(data);
01468   return tor_memdup(data, sizeof(rend_data_t));
01469 }
01470