/* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2015, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ROUTER_PRIVATE #include "or.h" #include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" #include "config.h" #include "connection.h" #include "control.h" #include "crypto_curve25519.h" #include "directory.h" #include "dirserv.h" #include "dns.h" #include "geoip.h" #include "hibernate.h" #include "main.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" #include "relay.h" #include "rephist.h" #include "router.h" #include "routerkeys.h" #include "routerlist.h" #include "routerparse.h" #include "statefile.h" #include "torcert.h" #include "transports.h" #include "routerset.h" /** * \file router.c * \brief OR functionality, including key maintenance, generating * and uploading server descriptors, retrying OR connections. **/ extern long stats_n_seconds_working; /************************************************************/ /***** * Key management: ORs only. *****/ /** Private keys for this OR. There is also an SSL key managed by tortls.c. */ static tor_mutex_t *key_lock=NULL; static time_t onionkey_set_at=0; /**< When was onionkey last changed? */ /** Current private onionskin decryption key: used to decode CREATE cells. */ static crypto_pk_t *onionkey=NULL; /** Previous private onionskin decryption key: used to decode CREATE cells * generated by clients that have an older version of our descriptor. */ static crypto_pk_t *lastonionkey=NULL; /** Current private ntor secret key: used to perform the ntor handshake. */ static curve25519_keypair_t curve25519_onion_key; /** Previous private ntor secret key: used to perform the ntor handshake * with clients that have an older version of our descriptor. */ static curve25519_keypair_t last_curve25519_onion_key; /** Private server "identity key": used to sign directory info and TLS * certificates. Never changes. */ static crypto_pk_t *server_identitykey=NULL; /** Digest of server_identitykey. */ static char server_identitykey_digest[DIGEST_LEN]; /** Private client "identity key": used to sign bridges' and clients' * outbound TLS certificates. Regenerated on startup and on IP address * change. */ static crypto_pk_t *client_identitykey=NULL; /** Signing key used for v3 directory material; only set for authorities. */ static crypto_pk_t *authority_signing_key = NULL; /** Key certificate to authenticate v3 directory material; only set for * authorities. */ static authority_cert_t *authority_key_certificate = NULL; /** For emergency V3 authority key migration: An extra signing key that we use * with our old (obsolete) identity key for a while. */ static crypto_pk_t *legacy_signing_key = NULL; /** For emergency V3 authority key migration: An extra certificate to * authenticate legacy_signing_key with our obsolete identity key.*/ static authority_cert_t *legacy_key_certificate = NULL; /* (Note that v3 authorities also have a separate "authority identity key", * but this key is never actually loaded by the Tor process. Instead, it's * used by tor-gencert to sign new signing keys and make new key * certificates. */ /** Replace the current onion key with k. Does not affect * lastonionkey; to update lastonionkey correctly, call rotate_onion_key(). */ static void set_onion_key(crypto_pk_t *k) { if (onionkey && crypto_pk_eq_keys(onionkey, k)) { /* k is already our onion key; free it and return */ crypto_pk_free(k); return; } tor_mutex_acquire(key_lock); crypto_pk_free(onionkey); onionkey = k; tor_mutex_release(key_lock); mark_my_descriptor_dirty("set onion key"); } /** Return the current onion key. Requires that the onion key has been * loaded or generated. */ crypto_pk_t * get_onion_key(void) { tor_assert(onionkey); return onionkey; } /** Store a full copy of the current onion key into *key, and a full * copy of the most recent onion key into *last. */ void dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last) { tor_assert(key); tor_assert(last); tor_mutex_acquire(key_lock); tor_assert(onionkey); *key = crypto_pk_copy_full(onionkey); if (lastonionkey) *last = crypto_pk_copy_full(lastonionkey); else *last = NULL; tor_mutex_release(key_lock); } /** Return the current secret onion key for the ntor handshake. Must only * be called from the main thread. */ static const curve25519_keypair_t * get_current_curve25519_keypair(void) { return &curve25519_onion_key; } /** Return a map from KEYID (the key itself) to keypairs for use in the ntor * handshake. Must only be called from the main thread. */ di_digest256_map_t * construct_ntor_key_map(void) { di_digest256_map_t *m = NULL; dimap_add_entry(&m, curve25519_onion_key.pubkey.public_key, tor_memdup(&curve25519_onion_key, sizeof(curve25519_keypair_t))); if (!tor_mem_is_zero((const char*) last_curve25519_onion_key.pubkey.public_key, CURVE25519_PUBKEY_LEN)) { dimap_add_entry(&m, last_curve25519_onion_key.pubkey.public_key, tor_memdup(&last_curve25519_onion_key, sizeof(curve25519_keypair_t))); } return m; } /** Helper used to deallocate a di_digest256_map_t returned by * construct_ntor_key_map. */ static void ntor_key_map_free_helper(void *arg) { curve25519_keypair_t *k = arg; memwipe(k, 0, sizeof(*k)); tor_free(k); } /** Release all storage from a keymap returned by construct_ntor_key_map. */ void ntor_key_map_free(di_digest256_map_t *map) { if (!map) return; dimap_free(map, ntor_key_map_free_helper); } /** Return the time when the onion key was last set. This is either the time * when the process launched, or the time of the most recent key rotation since * the process launched. */ time_t get_onion_key_set_at(void) { return onionkey_set_at; } /** Set the current server identity key to k. */ void set_server_identity_key(crypto_pk_t *k) { crypto_pk_free(server_identitykey); server_identitykey = k; crypto_pk_get_digest(server_identitykey, server_identitykey_digest); } /** Make sure that we have set up our identity keys to match or not match as * appropriate, and die with an assertion if we have not. */ static void assert_identity_keys_ok(void) { if (1) return; tor_assert(client_identitykey); if (public_server_mode(get_options())) { /* assert that we have set the client and server keys to be equal */ tor_assert(server_identitykey); tor_assert(crypto_pk_eq_keys(client_identitykey, server_identitykey)); } else { /* assert that we have set the client and server keys to be unequal */ if (server_identitykey) tor_assert(!crypto_pk_eq_keys(client_identitykey, server_identitykey)); } } /** Returns the current server identity key; requires that the key has * been set, and that we are running as a Tor server. */ crypto_pk_t * get_server_identity_key(void) { tor_assert(server_identitykey); tor_assert(server_mode(get_options())); assert_identity_keys_ok(); return server_identitykey; } /** Return true iff we are a server and the server identity key * has been set. */ int server_identity_key_is_set(void) { return server_mode(get_options()) && server_identitykey != NULL; } /** Set the current client identity key to k. */ void set_client_identity_key(crypto_pk_t *k) { crypto_pk_free(client_identitykey); client_identitykey = k; } /** Returns the current client identity key for use on outgoing TLS * connections; requires that the key has been set. */ crypto_pk_t * get_tlsclient_identity_key(void) { tor_assert(client_identitykey); assert_identity_keys_ok(); return client_identitykey; } /** Return true iff the client identity key has been set. */ int client_identity_key_is_set(void) { return client_identitykey != NULL; } /** Return the key certificate for this v3 (voting) authority, or NULL * if we have no such certificate. */ authority_cert_t * get_my_v3_authority_cert(void) { return authority_key_certificate; } /** Return the v3 signing key for this v3 (voting) authority, or NULL * if we have no such key. */ crypto_pk_t * get_my_v3_authority_signing_key(void) { return authority_signing_key; } /** If we're an authority, and we're using a legacy authority identity key for * emergency migration purposes, return the certificate associated with that * key. */ authority_cert_t * get_my_v3_legacy_cert(void) { return legacy_key_certificate; } /** If we're an authority, and we're using a legacy authority identity key for * emergency migration purposes, return that key. */ crypto_pk_t * get_my_v3_legacy_signing_key(void) { return legacy_signing_key; } /** Replace the previous onion key with the current onion key, and generate * a new previous onion key. Immediately after calling this function, * the OR should: * - schedule all previous cpuworkers to shut down _after_ processing * pending work. (This will cause fresh cpuworkers to be generated.) * - generate and upload a fresh routerinfo. */ void rotate_onion_key(void) { char *fname, *fname_prev; crypto_pk_t *prkey = NULL; or_state_t *state = get_or_state(); curve25519_keypair_t new_curve25519_keypair; time_t now; fname = get_datadir_fname2("keys", "secret_onion_key"); fname_prev = get_datadir_fname2("keys", "secret_onion_key.old"); /* There isn't much point replacing an old key with an empty file */ if (file_status(fname) == FN_FILE) { if (replace_file(fname, fname_prev)) goto error; } if (!(prkey = crypto_pk_new())) { log_err(LD_GENERAL,"Error constructing rotated onion key"); goto error; } if (crypto_pk_generate_key(prkey)) { log_err(LD_BUG,"Error generating onion key"); goto error; } if (crypto_pk_write_private_key_to_filename(prkey, fname)) { log_err(LD_FS,"Couldn't write generated onion key to \"%s\".", fname); goto error; } tor_free(fname); tor_free(fname_prev); fname = get_datadir_fname2("keys", "secret_onion_key_ntor"); fname_prev = get_datadir_fname2("keys", "secret_onion_key_ntor.old"); if (curve25519_keypair_generate(&new_curve25519_keypair, 1) < 0) goto error; /* There isn't much point replacing an old key with an empty file */ if (file_status(fname) == FN_FILE) { if (replace_file(fname, fname_prev)) goto error; } if (curve25519_keypair_write_to_file(&new_curve25519_keypair, fname, "onion") < 0) { log_err(LD_FS,"Couldn't write curve25519 onion key to \"%s\".",fname); goto error; } log_info(LD_GENERAL, "Rotating onion key"); tor_mutex_acquire(key_lock); crypto_pk_free(lastonionkey); lastonionkey = onionkey; onionkey = prkey; memcpy(&last_curve25519_onion_key, &curve25519_onion_key, sizeof(curve25519_keypair_t)); memcpy(&curve25519_onion_key, &new_curve25519_keypair, sizeof(curve25519_keypair_t)); now = time(NULL); state->LastRotatedOnionKey = onionkey_set_at = now; tor_mutex_release(key_lock); mark_my_descriptor_dirty("rotated onion key"); or_state_mark_dirty(state, get_options()->AvoidDiskWrites ? now+3600 : 0); goto done; error: log_warn(LD_GENERAL, "Couldn't rotate onion key."); if (prkey) crypto_pk_free(prkey); done: memwipe(&new_curve25519_keypair, 0, sizeof(new_curve25519_keypair)); tor_free(fname); tor_free(fname_prev); } /** Log greeting message that points to new relay lifecycle document the * first time this function has been called. */ static void log_new_relay_greeting(void) { static int already_logged = 0; if (already_logged) return; tor_log(LOG_NOTICE, LD_GENERAL, "You are running a new relay. " "Thanks for helping the Tor network! If you wish to know " "what will happen in the upcoming weeks regarding its usage, " "have a look at https://blog.torproject.org/blog/lifecycle-of" "-a-new-relay"); already_logged = 1; } /** Try to read an RSA key from fname. If fname doesn't exist * and generate is true, create a new RSA key and save it in * fname. Return the read/created key, or NULL on error. Log all * errors at level severity. If log_greeting is non-zero and a * new key was created, log_new_relay_greeting() is called. */ crypto_pk_t * init_key_from_file(const char *fname, int generate, int severity, int log_greeting) { crypto_pk_t *prkey = NULL; if (!(prkey = crypto_pk_new())) { tor_log(severity, LD_GENERAL,"Error constructing key"); goto error; } switch (file_status(fname)) { case FN_DIR: case FN_ERROR: tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname); goto error; /* treat empty key files as if the file doesn't exist, and, * if generate is set, replace the empty file in * crypto_pk_write_private_key_to_filename() */ case FN_NOENT: case FN_EMPTY: if (generate) { if (!have_lockfile()) { if (try_locking(get_options(), 0)<0) { /* Make sure that --list-fingerprint only creates new keys * if there is no possibility for a deadlock. */ tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". " "Not writing any new keys.", fname); /*XXXX The 'other process' might make a key in a second or two; * maybe we should wait for it. */ goto error; } } log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.", fname); if (crypto_pk_generate_key(prkey)) { tor_log(severity, LD_GENERAL,"Error generating onion key"); goto error; } if (crypto_pk_check_key(prkey) <= 0) { tor_log(severity, LD_GENERAL,"Generated key seems invalid"); goto error; } log_info(LD_GENERAL, "Generated key seems valid"); if (log_greeting) { log_new_relay_greeting(); } if (crypto_pk_write_private_key_to_filename(prkey, fname)) { tor_log(severity, LD_FS, "Couldn't write generated key to \"%s\".", fname); goto error; } } else { log_info(LD_GENERAL, "No key found in \"%s\"", fname); } return prkey; case FN_FILE: if (crypto_pk_read_private_key_from_filename(prkey, fname)) { tor_log(severity, LD_GENERAL,"Error loading private key."); goto error; } return prkey; default: tor_assert(0); } error: if (prkey) crypto_pk_free(prkey); return NULL; } /** Load a curve25519 keypair from the file fname, writing it into * keys_out. If the file isn't found, or is empty, and generate * is true, create a new keypair and write it into the file. If there are * errors, log them at level severity. Generate files using tag * in their ASCII wrapper. */ static int init_curve25519_keypair_from_file(curve25519_keypair_t *keys_out, const char *fname, int generate, int severity, const char *tag) { switch (file_status(fname)) { case FN_DIR: case FN_ERROR: tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname); goto error; /* treat empty key files as if the file doesn't exist, and, if generate * is set, replace the empty file in curve25519_keypair_write_to_file() */ case FN_NOENT: case FN_EMPTY: if (generate) { if (!have_lockfile()) { if (try_locking(get_options(), 0)<0) { /* Make sure that --list-fingerprint only creates new keys * if there is no possibility for a deadlock. */ tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". " "Not writing any new keys.", fname); /*XXXX The 'other process' might make a key in a second or two; * maybe we should wait for it. */ goto error; } } log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.", fname); if (curve25519_keypair_generate(keys_out, 1) < 0) goto error; if (curve25519_keypair_write_to_file(keys_out, fname, tag)<0) { tor_log(severity, LD_FS, "Couldn't write generated key to \"%s\".", fname); memwipe(keys_out, 0, sizeof(*keys_out)); goto error; } } else { log_info(LD_GENERAL, "No key found in \"%s\"", fname); } return 0; case FN_FILE: { char *tag_in=NULL; if (curve25519_keypair_read_from_file(keys_out, &tag_in, fname) < 0) { tor_log(severity, LD_GENERAL,"Error loading private key."); tor_free(tag_in); goto error; } if (!tag_in || strcmp(tag_in, tag)) { tor_log(severity, LD_GENERAL,"Unexpected tag %s on private key.", escaped(tag_in)); tor_free(tag_in); goto error; } tor_free(tag_in); return 0; } default: tor_assert(0); } error: return -1; } /** Try to load the vote-signing private key and certificate for being a v3 * directory authority, and make sure they match. If legacy, load a * legacy key/cert set for emergency key migration; otherwise load the regular * key/cert set. On success, store them into *key_out and * *cert_out respectively, and return 0. On failure, return -1. */ static int load_authority_keyset(int legacy, crypto_pk_t **key_out, authority_cert_t **cert_out) { int r = -1; char *fname = NULL, *cert = NULL; const char *eos = NULL; crypto_pk_t *signing_key = NULL; authority_cert_t *parsed = NULL; fname = get_datadir_fname2("keys", legacy ? "legacy_signing_key" : "authority_signing_key"); signing_key = init_key_from_file(fname, 0, LOG_INFO, 0); if (!signing_key) { log_warn(LD_DIR, "No version 3 directory key found in %s", fname); goto done; } tor_free(fname); fname = get_datadir_fname2("keys", legacy ? "legacy_certificate" : "authority_certificate"); cert = read_file_to_str(fname, 0, NULL); if (!cert) { log_warn(LD_DIR, "Signing key found, but no certificate found in %s", fname); goto done; } parsed = authority_cert_parse_from_string(cert, &eos); if (!parsed) { log_warn(LD_DIR, "Unable to parse certificate in %s", fname); goto done; } if (!crypto_pk_eq_keys(signing_key, parsed->signing_key)) { log_warn(LD_DIR, "Stored signing key does not match signing key in " "certificate"); goto done; } crypto_pk_free(*key_out); authority_cert_free(*cert_out); *key_out = signing_key; *cert_out = parsed; r = 0; signing_key = NULL; parsed = NULL; done: tor_free(fname); tor_free(cert); crypto_pk_free(signing_key); authority_cert_free(parsed); return r; } /** Load the v3 (voting) authority signing key and certificate, if they are * present. Return -1 if anything is missing, mismatched, or unloadable; * return 0 on success. */ static int init_v3_authority_keys(void) { if (load_authority_keyset(0, &authority_signing_key, &authority_key_certificate)<0) return -1; if (get_options()->V3AuthUseLegacyKey && load_authority_keyset(1, &legacy_signing_key, &legacy_key_certificate)<0) return -1; return 0; } /** If we're a v3 authority, check whether we have a certificate that's * likely to expire soon. Warn if we do, but not too often. */ void v3_authority_check_key_expiry(void) { time_t now, expires; static time_t last_warned = 0; int badness, time_left, warn_interval; if (!authdir_mode_v3(get_options()) || !authority_key_certificate) return; now = time(NULL); expires = authority_key_certificate->expires; time_left = (int)( expires - now ); if (time_left <= 0) { badness = LOG_ERR; warn_interval = 60*60; } else if (time_left <= 24*60*60) { badness = LOG_WARN; warn_interval = 60*60; } else if (time_left <= 24*60*60*7) { badness = LOG_WARN; warn_interval = 24*60*60; } else if (time_left <= 24*60*60*30) { badness = LOG_WARN; warn_interval = 24*60*60*5; } else { return; } if (last_warned + warn_interval > now) return; if (time_left <= 0) { tor_log(badness, LD_DIR, "Your v3 authority certificate has expired." " Generate a new one NOW."); } else if (time_left <= 24*60*60) { tor_log(badness, LD_DIR, "Your v3 authority certificate expires in %d " "hours; Generate a new one NOW.", time_left/(60*60)); } else { tor_log(badness, LD_DIR, "Your v3 authority certificate expires in %d " "days; Generate a new one soon.", time_left/(24*60*60)); } last_warned = now; } /** Set up Tor's TLS contexts, based on our configuration and keys. Return 0 * on success, and -1 on failure. */ int router_initialize_tls_context(void) { unsigned int flags = 0; const or_options_t *options = get_options(); int lifetime = options->SSLKeyLifetime; if (public_server_mode(options)) flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER; if (options->TLSECGroup) { if (!strcasecmp(options->TLSECGroup, "P256")) flags |= TOR_TLS_CTX_USE_ECDHE_P256; else if (!strcasecmp(options->TLSECGroup, "P224")) flags |= TOR_TLS_CTX_USE_ECDHE_P224; } if (!lifetime) { /* we should guess a good ssl cert lifetime */ /* choose between 5 and 365 days, and round to the day */ unsigned int five_days = 5*24*3600; unsigned int one_year = 365*24*3600; lifetime = crypto_rand_int_range(five_days, one_year); lifetime -= lifetime % (24*3600); if (crypto_rand_int(2)) { /* Half the time we expire at midnight, and half the time we expire * one second before midnight. (Some CAs wobble their expiry times a * bit in practice, perhaps to reduce collision attacks; see ticket * 8443 for details about observed certs in the wild.) */ lifetime--; } } /* It's ok to pass lifetime in as an unsigned int, since * config_parse_interval() checked it. */ return tor_tls_context_init(flags, get_tlsclient_identity_key(), server_mode(options) ? get_server_identity_key() : NULL, (unsigned int)lifetime); } /** Compute fingerprint (or hashed fingerprint if hashed is 1) and write * it to 'fingerprint' (or 'hashed-fingerprint'). Return 0 on success, or * -1 if Tor should die, */ STATIC int router_write_fingerprint(int hashed) { char *keydir = NULL, *cp = NULL; const char *fname = hashed ? "hashed-fingerprint" : "fingerprint"; char fingerprint[FINGERPRINT_LEN+1]; const or_options_t *options = get_options(); char *fingerprint_line = NULL; int result = -1; keydir = get_datadir_fname(fname); log_info(LD_GENERAL,"Dumping %sfingerprint to \"%s\"...", hashed ? "hashed " : "", keydir); if (!hashed) { if (crypto_pk_get_fingerprint(get_server_identity_key(), fingerprint, 0) < 0) { log_err(LD_GENERAL,"Error computing fingerprint"); goto done; } } else { if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(), fingerprint) < 0) { log_err(LD_GENERAL,"Error computing hashed fingerprint"); goto done; } } tor_asprintf(&fingerprint_line, "%s %s\n", options->Nickname, fingerprint); /* Check whether we need to write the (hashed-)fingerprint file. */ cp = read_file_to_str(keydir, RFTS_IGNORE_MISSING, NULL); if (!cp || strcmp(cp, fingerprint_line)) { if (write_str_to_file(keydir, fingerprint_line, 0)) { log_err(LD_FS, "Error writing %sfingerprint line to file", hashed ? "hashed " : ""); goto done; } } log_notice(LD_GENERAL, "Your Tor %s identity key fingerprint is '%s %s'", hashed ? "bridge's hashed" : "server's", options->Nickname, fingerprint); result = 0; done: tor_free(cp); tor_free(keydir); tor_free(fingerprint_line); return result; } static int init_keys_common(void) { if (!key_lock) key_lock = tor_mutex_new(); /* There are a couple of paths that put us here before we've asked * openssl to initialize itself. */ if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, get_options()->AccelDir)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } return 0; } int init_keys_client(void) { crypto_pk_t *prkey; if (init_keys_common() < 0) return -1; if (!(prkey = crypto_pk_new())) return -1; if (crypto_pk_generate_key(prkey)) { crypto_pk_free(prkey); return -1; } set_client_identity_key(prkey); /* Create a TLS context. */ if (router_initialize_tls_context() < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); return -1; } return 0; } /** Initialize all OR private keys, and the TLS context, as necessary. * On OPs, this only initializes the tls context. Return 0 on success, * or -1 if Tor should die. */ int init_keys(void) { char *keydir; const char *mydesc; crypto_pk_t *prkey; char digest[DIGEST_LEN]; char v3_digest[DIGEST_LEN]; const or_options_t *options = get_options(); dirinfo_type_t type; time_t now = time(NULL); dir_server_t *ds; int v3_digest_set = 0; authority_cert_t *cert = NULL; /* OP's don't need persistent keys; just make up an identity and * initialize the TLS context. */ if (!server_mode(options)) { return init_keys_client(); } if (init_keys_common() < 0) return -1; /* Make sure DataDirectory exists, and is private. */ if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) { return -1; } /* Check the key directory. */ keydir = get_datadir_fname("keys"); if (check_private_dir(keydir, CPD_CREATE, options->User)) { tor_free(keydir); return -1; } tor_free(keydir); /* 1a. Read v3 directory authority key/cert information. */ memset(v3_digest, 0, sizeof(v3_digest)); if (authdir_mode_v3(options)) { if (init_v3_authority_keys()<0) { log_err(LD_GENERAL, "We're configured as a V3 authority, but we " "were unable to load our v3 authority keys and certificate! " "Use tor-gencert to generate them. Dying."); return -1; } cert = get_my_v3_authority_cert(); if (cert) { crypto_pk_get_digest(get_my_v3_authority_cert()->identity_key, v3_digest); v3_digest_set = 1; } } /* 1b. Read identity key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_id_key"); log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR, 1); tor_free(keydir); if (!prkey) return -1; set_server_identity_key(prkey); /* 1c. If we are configured as a bridge, generate a client key; * otherwise, set the server identity key as our client identity * key. */ if (public_server_mode(options)) { set_client_identity_key(crypto_pk_dup_key(prkey)); /* set above */ } else { if (!(prkey = crypto_pk_new())) return -1; if (crypto_pk_generate_key(prkey)) { crypto_pk_free(prkey); return -1; } set_client_identity_key(prkey); } /* 1d. Load all ed25519 keys */ if (load_ed_keys(options,now) < 0) return -1; /* 2. Read onion key. Make it if none is found. */ keydir = get_datadir_fname2("keys", "secret_onion_key"); log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR, 1); tor_free(keydir); if (!prkey) return -1; set_onion_key(prkey); if (options->command == CMD_RUN_TOR) { /* only mess with the state file if we're actually running Tor */ or_state_t *state = get_or_state(); if (state->LastRotatedOnionKey > 100 && state->LastRotatedOnionKey < now) { /* We allow for some parsing slop, but we don't want to risk accepting * values in the distant future. If we did, we might never rotate the * onion key. */ onionkey_set_at = state->LastRotatedOnionKey; } else { /* We have no LastRotatedOnionKey set; either we just created the key * or it's a holdover from 0.1.2.4-alpha-dev or earlier. In either case, * start the clock ticking now so that we will eventually rotate it even * if we don't stay up for a full MIN_ONION_KEY_LIFETIME. */ state->LastRotatedOnionKey = onionkey_set_at = now; or_state_mark_dirty(state, options->AvoidDiskWrites ? time(NULL)+3600 : 0); } } keydir = get_datadir_fname2("keys", "secret_onion_key.old"); if (!lastonionkey && file_status(keydir) == FN_FILE) { /* Load keys from non-empty files only. * Missing old keys won't be replaced with freshly generated keys. */ prkey = init_key_from_file(keydir, 0, LOG_ERR, 0); if (prkey) lastonionkey = prkey; } tor_free(keydir); { /* 2b. Load curve25519 onion keys. */ int r; keydir = get_datadir_fname2("keys", "secret_onion_key_ntor"); r = init_curve25519_keypair_from_file(&curve25519_onion_key, keydir, 1, LOG_ERR, "onion"); tor_free(keydir); if (r<0) return -1; keydir = get_datadir_fname2("keys", "secret_onion_key_ntor.old"); if (tor_mem_is_zero((const char *) last_curve25519_onion_key.pubkey.public_key, CURVE25519_PUBKEY_LEN) && file_status(keydir) == FN_FILE) { /* Load keys from non-empty files only. * Missing old keys won't be replaced with freshly generated keys. */ init_curve25519_keypair_from_file(&last_curve25519_onion_key, keydir, 0, LOG_ERR, "onion"); } tor_free(keydir); } /* 3. Initialize link key and TLS context. */ if (router_initialize_tls_context() < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; } /* 3b. Get an ed25519 link certificate. Note that we need to do this * after we set up the TLS context */ if (generate_ed_link_cert(options, now) < 0) { log_err(LD_GENERAL,"Couldn't make link cert"); return -1; } /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); if (authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)) { const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ if (dirserv_add_own_fingerprint(get_server_identity_key())) { log_err(LD_GENERAL,"Error adding own fingerprint to set of relays"); return -1; } if (mydesc) { was_router_added_t added; 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; } added = dirserv_add_descriptor(ri, &m, "self"); if (!WRA_WAS_ADDED(added)) { if (!WRA_WAS_OUTDATED(added)) { log_err(LD_GENERAL, "Unable to add own descriptor to directory: %s", m?m:""); return -1; } else { /* If the descriptor was outdated, that's ok. This can happen * when some config options are toggled that affect workers, but * we don't really need new keys yet so the descriptor doesn't * change and the old one is still fresh. */ log_info(LD_GENERAL, "Couldn't add own descriptor to directory " "after key init: %s This is usually not a problem.", m?m:""); } } } } /* 5. Dump fingerprint and possibly hashed fingerprint to files. */ if (router_write_fingerprint(0)) { log_err(LD_FS, "Error writing fingerprint to file"); return -1; } if (!public_server_mode(options) && router_write_fingerprint(1)) { log_err(LD_FS, "Error writing hashed fingerprint to file"); return -1; } if (!authdir_mode(options)) return 0; /* 6. [authdirserver only] load approved-routers file */ if (dirserv_load_fingerprint_file() < 0) { log_err(LD_GENERAL,"Error loading fingerprints"); return -1; } /* 6b. [authdirserver only] add own key to approved directories. */ crypto_pk_get_digest(get_server_identity_key(), digest); type = ((options->V3AuthoritativeDir ? (V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) | (options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO)); ds = router_get_trusteddirserver_by_digest(digest); if (!ds) { ds = trusted_dir_server_new(options->Nickname, NULL, router_get_advertised_dir_port(options, 0), router_get_advertised_or_port(options), digest, v3_digest, type, 0.0); if (!ds) { log_err(LD_GENERAL,"We want to be a directory authority, but we " "couldn't add ourselves to the authority list. Failing."); return -1; } dir_server_add(ds); } if (ds->type != type) { log_warn(LD_DIR, "Configured authority type does not match authority " "type in DirAuthority list. Adjusting. (%d v %d)", type, ds->type); ds->type = type; } if (v3_digest_set && (ds->type & V3_DIRINFO) && tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "V3 identity key does not match identity declared in " "DirAuthority line. Adjusting."); memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN); } if (cert) { /* add my own cert to the list of known certs */ log_info(LD_DIR, "adding my own v3 cert"); if (trusted_dirs_load_certs_from_string( cert->cache_info.signed_descriptor_body, TRUSTED_DIRS_CERTS_SRC_SELF, 0)<0) { log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing."); return -1; } } return 0; /* success */ } /* Keep track of whether we should upload our server descriptor, * and what type of server we are. */ /** Whether we can reach our ORPort from the outside. */ static int can_reach_or_port = 0; /** Whether we can reach our DirPort from the outside. */ static int can_reach_dir_port = 0; /** Forget what we have learned about our reachability status. */ void router_reset_reachability(void) { can_reach_or_port = can_reach_dir_port = 0; } /** Return 1 if ORPort is known reachable; else return 0. */ int check_whether_orport_reachable(void) { const or_options_t *options = get_options(); return options->AssumeReachable || can_reach_or_port; } /** Return 1 if we don't have a dirport configured, or if it's reachable. */ int check_whether_dirport_reachable(void) { const or_options_t *options = get_options(); return !options->DirPort_set || options->AssumeReachable || net_is_disabled() || can_reach_dir_port; } /** Look at a variety of factors, and return 0 if we don't want to * advertise the fact that we have a DirPort open. Else return the * DirPort we want to advertise. * * Log a helpful message if we change our mind about whether to publish * a DirPort. */ static int decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) { static int advertising=1; /* start out assuming we will advertise */ int new_choice=1; const char *reason = NULL; /* Section one: reasons to publish or not publish that aren't * worth mentioning to the user, either because they're obvious * or because they're normal behavior. */ if (!dir_port) /* short circuit the rest of the function */ return 0; if (authdir_mode(options)) /* always publish */ return dir_port; if (net_is_disabled()) return 0; if (!check_whether_dirport_reachable()) return 0; if (!router_get_advertised_dir_port(options, dir_port)) return 0; /* Section two: reasons to publish or not publish that the user * might find surprising. These are generally config options that * make us choose not to publish. */ if (accounting_is_enabled(options)) { /* Don't spend bytes for directory traffic if we could end up hibernating, * but allow DirPort otherwise. Some people set AccountingMax because * they're confused or to get statistics. */ int interval_length = accounting_get_interval_length(); uint32_t effective_bw = get_effective_bwrate(options); uint64_t acc_bytes; if (!interval_length) { log_warn(LD_BUG, "An accounting interval is not allowed to be zero " "seconds long. Raising to 1."); interval_length = 1; } log_info(LD_GENERAL, "Calculating whether to disable dirport: effective " "bwrate: %u, AccountingMax: "U64_FORMAT", " "accounting interval length %d", effective_bw, U64_PRINTF_ARG(options->AccountingMax), interval_length); acc_bytes = options->AccountingMax; if (get_options()->AccountingRule == ACCT_SUM) acc_bytes /= 2; if (effective_bw >= acc_bytes / interval_length) { new_choice = 0; reason = "AccountingMax enabled"; } #define MIN_BW_TO_ADVERTISE_DIRPORT 51200 } else if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT || (options->RelayBandwidthRate > 0 && options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT)) { /* if we're advertising a small amount */ new_choice = 0; reason = "BandwidthRate under 50KB"; } if (advertising != new_choice) { if (new_choice == 1) { log_notice(LD_DIR, "Advertising DirPort as %d", dir_port); } else { tor_assert(reason); log_notice(LD_DIR, "Not advertising DirPort (Reason: %s)", reason); } advertising = new_choice; } return advertising ? dir_port : 0; } /** Allocate and return a new extend_info_t that can be used to build * a circuit to or through the router r. Use the primary * address of the router unless for_direct_connect is true, in * which case the preferred address is used instead. */ static extend_info_t * extend_info_from_router(const routerinfo_t *r) { tor_addr_port_t ap; tor_assert(r); router_get_prim_orport(r, &ap); return extend_info_new(r->nickname, r->cache_info.identity_digest, r->onion_pkey, r->onion_curve25519_pkey, &ap.addr, ap.port); } /** Some time has passed, or we just got new directory information. * See if we currently believe our ORPort or DirPort to be * unreachable. If so, launch a new test for it. * * For ORPort, we simply try making a circuit that ends at ourselves. * Success is noticed in onionskin_answer(). * * For DirPort, we make a connection via Tor to our DirPort and ask * for our own server descriptor. * Success is noticed in connection_dir_client_reached_eof(). */ void consider_testing_reachability(int test_or, int test_dir) { const routerinfo_t *me = router_get_my_routerinfo(); int orport_reachable = check_whether_orport_reachable(); tor_addr_t addr; const or_options_t *options = get_options(); if (!me) return; if (routerset_contains_router(options->ExcludeNodes, me, -1) && options->StrictNodes) { /* If we've excluded ourself, and StrictNodes is set, we can't test * ourself. */ if (test_or || test_dir) { #define SELF_EXCLUDED_WARN_INTERVAL 3600 static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL); log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC, "Can't peform self-tests for this relay: we have " "listed ourself in ExcludeNodes, and StrictNodes is set. " "We cannot learn whether we are usable, and will not " "be able to advertise ourself."); } return; } if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) { extend_info_t *ei = extend_info_from_router(me); /* XXX IPv6 self testing */ log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.", !orport_reachable ? "reachability" : "bandwidth", fmt_addr32(me->addr), me->or_port); circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei, CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL); extend_info_free(ei); } tor_addr_from_ipv4h(&addr, me->addr); if (test_dir && !check_whether_dirport_reachable() && !connection_get_by_type_addr_port_purpose( CONN_TYPE_DIR, &addr, me->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)) { /* ask myself, via tor, for my server descriptor. */ directory_initiate_command(&addr, me->or_port, me->dir_port, me->cache_info.identity_digest, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_GENERAL, DIRIND_ANON_DIRPORT, "authority.z", NULL, 0, 0); } } /** Annotate that we found our ORPort reachable. */ void router_orport_found_reachable(void) { const routerinfo_t *me = router_get_my_routerinfo(); if (!can_reach_or_port && me) { char *address = tor_dup_ip(me->addr); log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " "the outside. Excellent.%s", get_options()->PublishServerDescriptor_ != NO_DIRINFO && check_whether_dirport_reachable() ? " Publishing server descriptor." : ""); can_reach_or_port = 1; mark_my_descriptor_dirty("ORPort found reachable"); /* This is a significant enough change to upload immediately, * at least in a test network */ if (get_options()->TestingTorNetwork == 1) { reschedule_descriptor_update_check(); } control_event_server_status(LOG_NOTICE, "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d", address, me->or_port); tor_free(address); } } /** Annotate that we found our DirPort reachable. */ void router_dirport_found_reachable(void) { const routerinfo_t *me = router_get_my_routerinfo(); if (!can_reach_dir_port && me) { char *address = tor_dup_ip(me->addr); log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable " "from the outside. Excellent.%s", get_options()->PublishServerDescriptor_ != NO_DIRINFO && check_whether_orport_reachable() ? " Publishing server descriptor." : ""); can_reach_dir_port = 1; if (decide_to_advertise_dirport(get_options(), me->dir_port)) { mark_my_descriptor_dirty("DirPort found reachable"); /* This is a significant enough change to upload immediately, * at least in a test network */ if (get_options()->TestingTorNetwork == 1) { reschedule_descriptor_update_check(); } } control_event_server_status(LOG_NOTICE, "REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d", address, me->dir_port); tor_free(address); } } /** We have enough testing circuits open. Send a bunch of "drop" * cells down each of them, to exercise our bandwidth. */ void router_perform_bandwidth_test(int num_circs, time_t now) { int num_cells = (int)(get_options()->BandwidthRate * 10 / CELL_MAX_NETWORK_SIZE); int max_cells = num_cells < CIRCWINDOW_START ? num_cells : CIRCWINDOW_START; int cells_per_circuit = max_cells / num_circs; origin_circuit_t *circ = NULL; log_notice(LD_OR,"Performing bandwidth self-test...done."); while ((circ = circuit_get_next_by_pk_and_purpose(circ, NULL, CIRCUIT_PURPOSE_TESTING))) { /* dump cells_per_circuit drop cells onto this circ */ int i = cells_per_circuit; if (circ->base_.state != CIRCUIT_STATE_OPEN) continue; circ->base_.timestamp_dirty = now; while (i-- > 0) { if (relay_send_command_from_edge(0, TO_CIRCUIT(circ), RELAY_COMMAND_DROP, NULL, 0, circ->cpath->prev)<0) { return; /* stop if error */ } } } } /** Return true iff our network is in some sense disabled: either we're * hibernating, entering hibernation, or the network is turned off with * DisableNetwork. */ int net_is_disabled(void) { return get_options()->DisableNetwork || we_are_hibernating(); } /** Return true iff we believe ourselves to be an authoritative * directory server. */ int authdir_mode(const or_options_t *options) { return options->AuthoritativeDir != 0; } /** Return true iff we believe ourselves to be a v3 authoritative * directory server. */ int authdir_mode_v3(const or_options_t *options) { return authdir_mode(options) && options->V3AuthoritativeDir != 0; } /** Return true iff we are a v3 directory authority. */ int authdir_mode_any_main(const or_options_t *options) { return options->V3AuthoritativeDir; } /** Return true if we believe ourselves to be any kind of * authoritative directory beyond just a hidserv authority. */ int authdir_mode_any_nonhidserv(const or_options_t *options) { return options->BridgeAuthoritativeDir || authdir_mode_any_main(options); } /** Return true iff we are an authoritative directory server that is * authoritative about receiving and serving descriptors of type * purpose on its dirport. Use -1 for "any purpose". */ int authdir_mode_handles_descs(const or_options_t *options, int purpose) { if (purpose < 0) return authdir_mode_any_nonhidserv(options); else if (purpose == ROUTER_PURPOSE_GENERAL) return authdir_mode_any_main(options); else if (purpose == ROUTER_PURPOSE_BRIDGE) return (options->BridgeAuthoritativeDir); else return 0; } /** Return true iff we are an authoritative directory server that * publishes its own network statuses. */ int authdir_mode_publishes_statuses(const or_options_t *options) { if (authdir_mode_bridge(options)) return 0; return authdir_mode_any_nonhidserv(options); } /** Return true iff we are an authoritative directory server that * tests reachability of the descriptors it learns about. */ int authdir_mode_tests_reachability(const or_options_t *options) { return authdir_mode_handles_descs(options, -1); } /** Return true iff we believe ourselves to be a bridge authoritative * directory server. */ int authdir_mode_bridge(const or_options_t *options) { return authdir_mode(options) && options->BridgeAuthoritativeDir != 0; } /** Return true iff we are trying to be a server. */ MOCK_IMPL(int, server_mode,(const or_options_t *options)) { if (options->ClientOnly) return 0; /* XXXX024 I believe we can kill off ORListenAddress here.*/ return (options->ORPort_set || options->ORListenAddress); } /** Return true iff we are trying to be a non-bridge server. */ MOCK_IMPL(int, public_server_mode,(const or_options_t *options)) { if (!server_mode(options)) return 0; return (!options->BridgeRelay); } /** Return true iff the combination of options in options and parameters * in the consensus mean that we don't want to allow exits from circuits * we got from addresses not known to be servers. */ int should_refuse_unknown_exits(const or_options_t *options) { if (options->RefuseUnknownExits != -1) { return options->RefuseUnknownExits; } else { return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1); } } /** Remember if we've advertised ourselves to the dirservers. */ static int server_is_advertised=0; /** Return true iff we have published our descriptor lately. */ int advertised_server_mode(void) { return server_is_advertised; } /** * Called with a boolean: set whether we have recently published our * descriptor. */ static void set_server_advertised(int s) { server_is_advertised = s; } /** Return true iff we are trying to proxy client connections. */ int proxy_mode(const or_options_t *options) { (void)options; SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) { if (p->type == CONN_TYPE_AP_LISTENER || p->type == CONN_TYPE_AP_TRANS_LISTENER || p->type == CONN_TYPE_AP_DNS_LISTENER || p->type == CONN_TYPE_AP_NATD_LISTENER) return 1; } SMARTLIST_FOREACH_END(p); return 0; } /** Decide if we're a publishable server. We are a publishable server if: * - We don't have the ClientOnly option set * and * - We have the PublishServerDescriptor option set to non-empty * and * - We have ORPort set * and * - We believe both our ORPort and DirPort (if present) are reachable from * the outside; or * - We are an authoritative directory server. */ static int decide_if_publishable_server(void) { const or_options_t *options = get_options(); if (options->ClientOnly) return 0; if (options->PublishServerDescriptor_ == NO_DIRINFO) return 0; if (!server_mode(options)) return 0; if (authdir_mode(options)) return 1; if (!router_get_advertised_or_port(options)) return 0; return check_whether_orport_reachable() && check_whether_dirport_reachable(); } /** Initiate server descriptor upload as reasonable (if server is publishable, * etc). force is as for router_upload_dir_desc_to_dirservers. * * We need to rebuild the descriptor if it's dirty even if we're not * uploading, because our reachability testing *uses* our descriptor to * determine what IP address and ports to test. */ void consider_publishable_server(int force) { int rebuilt; if (!server_mode(get_options())) return; rebuilt = router_rebuild_descriptor(0); if (decide_if_publishable_server()) { set_server_advertised(1); if (rebuilt == 0) router_upload_dir_desc_to_dirservers(force); } else { set_server_advertised(0); } } /** Return the port of the first active listener of type * listener_type. */ /** XXX not a very good interface. it's not reliable when there are multiple listeners. */ uint16_t router_get_active_listener_port_by_type_af(int listener_type, sa_family_t family) { /* Iterate all connections, find one of the right kind and return the port. Not very sophisticated or fast, but effective. */ smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == listener_type && !conn->marked_for_close && conn->socket_family == family) { return conn->port; } } SMARTLIST_FOREACH_END(conn); return 0; } /** Return the port that we should advertise as our ORPort; this is either * the one configured in the ORPort option, or the one we actually bound to * if ORPort is "auto". */ uint16_t router_get_advertised_or_port(const or_options_t *options) { return router_get_advertised_or_port_by_af(options, AF_INET); } /** As router_get_advertised_or_port(), but allows an address family argument. */ uint16_t router_get_advertised_or_port_by_af(const or_options_t *options, sa_family_t family) { int port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER, family); (void)options; /* If the port is in 'auto' mode, we have to use router_get_listener_port_by_type(). */ if (port == CFG_AUTO_PORT) return router_get_active_listener_port_by_type_af(CONN_TYPE_OR_LISTENER, family); return port; } /** Return the port that we should advertise as our DirPort; * this is one of three possibilities: * The one that is passed as dirport if the DirPort option is 0, or * the one configured in the DirPort option, * or the one we actually bound to if DirPort is "auto". */ uint16_t router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) { int dirport_configured = get_primary_dir_port(); (void)options; if (!dirport_configured) return dirport; if (dirport_configured == CFG_AUTO_PORT) return router_get_active_listener_port_by_type_af(CONN_TYPE_DIR_LISTENER, AF_INET); return dirport_configured; } /* * OR descriptor generation. */ /** My routerinfo. */ static routerinfo_t *desc_routerinfo = NULL; /** My extrainfo */ static extrainfo_t *desc_extrainfo = NULL; /** Why did we most recently decide to regenerate our descriptor? Used to * tell the authorities why we're sending it to them. */ static const char *desc_gen_reason = NULL; /** Since when has our descriptor been "clean"? 0 if we need to regenerate it * now. */ static time_t desc_clean_since = 0; /** Why did we mark the descriptor dirty? */ static const char *desc_dirty_reason = NULL; /** Boolean: do we need to regenerate the above? */ static int desc_needs_upload = 0; /** OR only: If force is true, or we haven't uploaded this * descriptor successfully yet, try to upload our signed descriptor to * all the directory servers we know about. */ void router_upload_dir_desc_to_dirservers(int force) { const routerinfo_t *ri; extrainfo_t *ei; char *msg; size_t desc_len, extra_len = 0, total_len; dirinfo_type_t auth = get_options()->PublishServerDescriptor_; ri = router_get_my_routerinfo(); if (!ri) { log_info(LD_GENERAL, "No descriptor; skipping upload"); return; } ei = router_get_my_extrainfo(); if (auth == NO_DIRINFO) return; if (!force && !desc_needs_upload) return; log_info(LD_OR, "Uploading relay descriptor to directory authorities%s", force ? " (forced)" : ""); desc_needs_upload = 0; desc_len = ri->cache_info.signed_descriptor_len; extra_len = ei ? ei->cache_info.signed_descriptor_len : 0; total_len = desc_len + extra_len + 1; msg = tor_malloc(total_len); memcpy(msg, ri->cache_info.signed_descriptor_body, desc_len); if (ei) { memcpy(msg+desc_len, ei->cache_info.signed_descriptor_body, extra_len); } msg[desc_len+extra_len] = 0; directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR, (auth & BRIDGE_DIRINFO) ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL, auth, msg, desc_len, extra_len); tor_free(msg); } /** OR only: Check whether my exit policy says to allow connection to * conn. Return 0 if we accept; non-0 if we reject. */ int router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port) { if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ return -1; /* make sure it's resolved to something. this way we can't get a 'maybe' below. */ if (tor_addr_is_null(addr)) return -1; /* look at desc_routerinfo->exit_policy for both the v4 and the v6 * policies. The exit_policy field in desc_routerinfo is a bit unusual, * in that it contains IPv6 and IPv6 entries. We don't want to look * at desc_routerinfio->ipv6_exit_policy, since that's a port summary. */ if ((tor_addr_family(addr) == AF_INET || tor_addr_family(addr) == AF_INET6)) { return compare_tor_addr_to_addr_policy(addr, port, desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; #if 0 } else if (tor_addr_family(addr) == AF_INET6) { return get_options()->IPv6Exit && desc_routerinfo->ipv6_exit_policy && compare_tor_addr_to_short_policy(addr, port, desc_routerinfo->ipv6_exit_policy) != ADDR_POLICY_ACCEPTED; #endif } else { return -1; } } /** Return true iff my exit policy is reject *:*. Return -1 if we don't * have a descriptor */ int router_my_exit_policy_is_reject_star(void) { if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ return -1; return desc_routerinfo->policy_is_reject_star; } /** Return true iff I'm a server and digest is equal to * my server identity key digest. */ int router_digest_is_me(const char *digest) { return (server_identitykey && tor_memeq(server_identitykey_digest, digest, DIGEST_LEN)); } /** Return my identity digest. */ const uint8_t * router_get_my_id_digest(void) { return (const uint8_t *)server_identitykey_digest; } /** Return true iff I'm a server and digest is equal to * my identity digest. */ int router_extrainfo_digest_is_me(const char *digest) { extrainfo_t *ei = router_get_my_extrainfo(); if (!ei) return 0; return tor_memeq(digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN); } /** A wrapper around router_digest_is_me(). */ int router_is_me(const routerinfo_t *router) { return router_digest_is_me(router->cache_info.identity_digest); } /** Return a routerinfo for this OR, rebuilding a fresh one if * necessary. Return NULL on error, or if called on an OP. */ MOCK_IMPL(const routerinfo_t *, router_get_my_routerinfo,(void)) { if (!server_mode(get_options())) return NULL; if (router_rebuild_descriptor(0)) return NULL; return desc_routerinfo; } /** OR only: Return a signed server descriptor for this OR, rebuilding a fresh * one if necessary. Return NULL on error. */ const char * router_get_my_descriptor(void) { const char *body; if (!router_get_my_routerinfo()) return NULL; /* Make sure this is nul-terminated. */ tor_assert(desc_routerinfo->cache_info.saved_location == SAVED_NOWHERE); body = signed_descriptor_get_body(&desc_routerinfo->cache_info); tor_assert(!body[desc_routerinfo->cache_info.signed_descriptor_len]); log_debug(LD_GENERAL,"my desc is '%s'", body); return body; } /** Return the extrainfo document for this OR, or NULL if we have none. * Rebuilt it (and the server descriptor) if necessary. */ extrainfo_t * router_get_my_extrainfo(void) { if (!server_mode(get_options())) return NULL; if (router_rebuild_descriptor(0)) return NULL; return desc_extrainfo; } /** Return a human-readable string describing what triggered us to generate * our current descriptor, or NULL if we don't know. */ const char * router_get_descriptor_gen_reason(void) { return desc_gen_reason; } /** A list of nicknames that we've warned about including in our family * declaration verbatim rather than as digests. */ static smartlist_t *warned_nonexistent_family = NULL; static int router_guess_address_from_dir_headers(uint32_t *guess); /** Make a current best guess at our address, either because * it's configured in torrc, or because we've learned it from * dirserver headers. Place the answer in *addr and return * 0 on success, else return -1 if we have no guess. */ int router_pick_published_address(const or_options_t *options, uint32_t *addr) { *addr = get_last_resolved_addr(); if (!*addr && resolve_my_address(LOG_INFO, options, addr, NULL, NULL) < 0) { log_info(LD_CONFIG, "Could not determine our address locally. " "Checking if directory headers provide any hints."); if (router_guess_address_from_dir_headers(addr) < 0) { log_info(LD_CONFIG, "No hints from directory headers either. " "Will try again later."); return -1; } } log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr)); return 0; } /** Build a fresh routerinfo, signed server descriptor, and extra-info document * for this OR. Set r to the generated routerinfo, e to the generated * extra-info document. Return 0 on success, -1 on temporary error. Failure to * generate an extra-info document is not an error and is indicated by setting * e to NULL. Caller is responsible for freeing generated documents if 0 is * returned. */ int router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) { routerinfo_t *ri; extrainfo_t *ei; uint32_t addr; char platform[256]; int hibernating = we_are_hibernating(); const or_options_t *options = get_options(); if (router_pick_published_address(options, &addr) < 0) { log_warn(LD_CONFIG, "Don't know my address while generating descriptor"); return -1; } ri = tor_malloc_zero(sizeof(routerinfo_t)); ri->cache_info.routerlist_index = -1; ri->nickname = tor_strdup(options->Nickname); ri->addr = addr; ri->or_port = router_get_advertised_or_port(options); ri->dir_port = router_get_advertised_dir_port(options, 0); ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ ri->onion_curve25519_pkey = tor_memdup(&get_current_curve25519_keypair()->pubkey, sizeof(curve25519_public_key_t)); /* For now, at most one IPv6 or-address is being advertised. */ { const port_cfg_t *ipv6_orport = NULL; SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) { if (p->type == CONN_TYPE_OR_LISTENER && ! p->server_cfg.no_advertise && ! p->server_cfg.bind_ipv4_only && tor_addr_family(&p->addr) == AF_INET6) { if (! tor_addr_is_internal(&p->addr, 0)) { ipv6_orport = p; break; } else { char addrbuf[TOR_ADDR_BUF_LEN]; log_warn(LD_CONFIG, "Unable to use configured IPv6 address \"%s\" in a " "descriptor. Skipping it. " "Try specifying a globally reachable address explicitly. ", tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1)); } } } SMARTLIST_FOREACH_END(p); if (ipv6_orport) { tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr); ri->ipv6_orport = ipv6_orport->port; } } ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key()); if (crypto_pk_get_digest(ri->identity_pkey, ri->cache_info.identity_digest)<0) { routerinfo_free(ri); return -1; } ri->signing_key_cert = tor_cert_dup(get_master_signing_key_cert()); get_platform_str(platform, sizeof(platform)); ri->platform = tor_strdup(platform); /* compute ri->bandwidthrate as the min of various options */ ri->bandwidthrate = get_effective_bwrate(options); /* and compute ri->bandwidthburst similarly */ ri->bandwidthburst = get_effective_bwburst(options); ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess(); if (dns_seems_to_be_broken() || has_dns_init_failed()) { /* DNS is screwed up; don't claim to be an exit. */ policies_exit_policy_append_reject_star(&ri->exit_policy); } else { policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,1, &ri->exit_policy); } ri->policy_is_reject_star = policy_is_reject_star(ri->exit_policy, AF_INET) && policy_is_reject_star(ri->exit_policy, AF_INET6); if (options->IPv6Exit) { char *p_tmp = policy_summarize(ri->exit_policy, AF_INET6); if (p_tmp) ri->ipv6_exit_policy = parse_short_policy(p_tmp); tor_free(p_tmp); } if (options->MyFamily && ! options->BridgeRelay) { smartlist_t *family; if (!warned_nonexistent_family) warned_nonexistent_family = smartlist_new(); family = smartlist_new(); ri->declared_family = smartlist_new(); smartlist_split_string(family, options->MyFamily, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); SMARTLIST_FOREACH_BEGIN(family, char *, name) { const node_t *member; if (!strcasecmp(name, options->Nickname)) goto skip; /* Don't list ourself, that's redundant */ else member = node_get_by_nickname(name, 1); if (!member) { int is_legal = is_legal_nickname_or_hexdigest(name); if (!smartlist_contains_string(warned_nonexistent_family, name) && !is_legal_hexdigest(name)) { if (is_legal) log_warn(LD_CONFIG, "I have no descriptor for the router named \"%s\" in my " "declared family; I'll use the nickname as is, but " "this may confuse clients.", name); else log_warn(LD_CONFIG, "There is a router named \"%s\" in my " "declared family, but that isn't a legal nickname. " "Skipping it.", escaped(name)); smartlist_add(warned_nonexistent_family, tor_strdup(name)); } if (is_legal) { smartlist_add(ri->declared_family, name); name = NULL; } } else if (router_digest_is_me(member->identity)) { /* Don't list ourself in our own family; that's redundant */ /* XXX shouldn't be possible */ } else { char *fp = tor_malloc(HEX_DIGEST_LEN+2); fp[0] = '$'; base16_encode(fp+1,HEX_DIGEST_LEN+1, member->identity, DIGEST_LEN); smartlist_add(ri->declared_family, fp); if (smartlist_contains_string(warned_nonexistent_family, name)) smartlist_string_remove(warned_nonexistent_family, name); } skip: tor_free(name); } SMARTLIST_FOREACH_END(name); /* remove duplicates from the list */ smartlist_sort_strings(ri->declared_family); smartlist_uniq_strings(ri->declared_family); smartlist_free(family); } /* Now generate the extrainfo. */ ei = tor_malloc_zero(sizeof(extrainfo_t)); ei->cache_info.is_extrainfo = 1; strlcpy(ei->nickname, get_options()->Nickname, sizeof(ei->nickname)); ei->cache_info.published_on = ri->cache_info.published_on; ei->signing_key_cert = tor_cert_dup(get_master_signing_key_cert()); memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body, ei, get_server_identity_key(), get_master_signing_keypair()) < 0) { log_warn(LD_BUG, "Couldn't generate extra-info descriptor."); extrainfo_free(ei); ei = NULL; } else { ei->cache_info.signed_descriptor_len = strlen(ei->cache_info.signed_descriptor_body); router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body, ei->cache_info.signed_descriptor_len, ei->cache_info.signed_descriptor_digest); crypto_digest256((char*) ei->digest256, ei->cache_info.signed_descriptor_body, ei->cache_info.signed_descriptor_len, DIGEST_SHA256); } /* Now finish the router descriptor. */ if (ei) { memcpy(ri->cache_info.extra_info_digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN); memcpy(ri->extra_info_digest256, ei->digest256, DIGEST256_LEN); } else { /* ri was allocated with tor_malloc_zero, so there is no need to * zero ri->cache_info.extra_info_digest here. */ } if (! (ri->cache_info.signed_descriptor_body = router_dump_router_to_string(ri, get_server_identity_key(), get_onion_key(), get_current_curve25519_keypair(), get_master_signing_keypair())) ) { log_warn(LD_BUG, "Couldn't generate router descriptor."); routerinfo_free(ri); extrainfo_free(ei); return -1; } ri->cache_info.signed_descriptor_len = strlen(ri->cache_info.signed_descriptor_body); ri->purpose = options->BridgeRelay ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL; if (options->BridgeRelay) { /* Bridges shouldn't be able to send their descriptors unencrypted, anyway, since they don't have a DirPort, and always connect to the bridge authority anonymously. But just in case they somehow think of sending them on an unencrypted connection, don't allow them to try. */ ri->cache_info.send_unencrypted = 0; if (ei) ei->cache_info.send_unencrypted = 0; } else { ri->cache_info.send_unencrypted = 1; if (ei) ei->cache_info.send_unencrypted = 1; } router_get_router_hash(ri->cache_info.signed_descriptor_body, strlen(ri->cache_info.signed_descriptor_body), ri->cache_info.signed_descriptor_digest); if (ei) { tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL)); } *r = ri; *e = ei; return 0; } /** If force is true, or our descriptor is out-of-date, rebuild a fresh * routerinfo, signed server descriptor, and extra-info document for this OR. * Return 0 on success, -1 on temporary error. */ int router_rebuild_descriptor(int force) { routerinfo_t *ri; extrainfo_t *ei; uint32_t addr; const or_options_t *options = get_options(); if (desc_clean_since && !force) return 0; if (router_pick_published_address(options, &addr) < 0 || router_get_advertised_or_port(options) == 0) { /* Stop trying to rebuild our descriptor every second. We'll * learn that it's time to try again when ip_address_changed() * marks it dirty. */ desc_clean_since = time(NULL); return -1; } log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : ""); if (router_build_fresh_descriptor(&ri, &ei) < 0) { return -1; } routerinfo_free(desc_routerinfo); desc_routerinfo = ri; extrainfo_free(desc_extrainfo); desc_extrainfo = ei; desc_clean_since = time(NULL); desc_needs_upload = 1; desc_gen_reason = desc_dirty_reason; desc_dirty_reason = NULL; control_event_my_descriptor_changed(); return 0; } /** If our router descriptor ever goes this long without being regenerated * because something changed, we force an immediate regenerate-and-upload. */ #define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60) /** If our router descriptor seems to be missing or unacceptable according * to the authorities, regenerate and reupload it _this_ often. */ #define FAST_RETRY_DESCRIPTOR_INTERVAL (90*60) /** Mark descriptor out of date if it's been "too long" since we last tried * to upload one. */ void mark_my_descriptor_dirty_if_too_old(time_t now) { networkstatus_t *ns; const routerstatus_t *rs; const char *retry_fast_reason = NULL; /* Set if we should retry frequently */ const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL; const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL; /* If it's already dirty, don't mark it. */ if (! desc_clean_since) return; /* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always * time to rebuild it. */ if (desc_clean_since < slow_cutoff) { mark_my_descriptor_dirty("time for new descriptor"); return; } /* Now we see whether we want to be retrying frequently or no. The * rule here is that we'll retry frequently if we aren't listed in the * live consensus we have, or if the publication time of the * descriptor listed for us in the consensus is very old. */ ns = networkstatus_get_live_consensus(now); if (ns) { rs = networkstatus_vote_find_entry(ns, server_identitykey_digest); if (rs == NULL) retry_fast_reason = "not listed in consensus"; else if (rs->published_on < slow_cutoff) retry_fast_reason = "version listed in consensus is quite old"; } if (retry_fast_reason && desc_clean_since < fast_cutoff) mark_my_descriptor_dirty(retry_fast_reason); } /** Call when the current descriptor is out of date. */ void mark_my_descriptor_dirty(const char *reason) { const or_options_t *options = get_options(); if (server_mode(options) && options->PublishServerDescriptor_) log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason); desc_clean_since = 0; if (!desc_dirty_reason) desc_dirty_reason = reason; } /** How frequently will we republish our descriptor because of large (factor * of 2) shifts in estimated bandwidth? Note: We don't use this constant * if our previous bandwidth estimate was exactly 0. */ #define MAX_BANDWIDTH_CHANGE_FREQ (20*60) /** Check whether bandwidth has changed a lot since the last time we announced * bandwidth. If so, mark our descriptor dirty. */ void check_descriptor_bandwidth_changed(time_t now) { static time_t last_changed = 0; uint64_t prev, cur; if (!desc_routerinfo) return; prev = desc_routerinfo->bandwidthcapacity; cur = we_are_hibernating() ? 0 : rep_hist_bandwidth_assess(); if ((prev != cur && (!prev || !cur)) || cur > prev*2 || cur < prev/2) { if (last_changed+MAX_BANDWIDTH_CHANGE_FREQ < now || !prev) { log_info(LD_GENERAL, "Measured bandwidth has changed; rebuilding descriptor."); mark_my_descriptor_dirty("bandwidth has changed"); last_changed = now; } } } /** Note at log level severity that our best guess of address has changed from * prev to cur. */ static void log_addr_has_changed(int severity, const tor_addr_t *prev, const tor_addr_t *cur, const char *source) { char addrbuf_prev[TOR_ADDR_BUF_LEN]; char addrbuf_cur[TOR_ADDR_BUF_LEN]; if (tor_addr_to_str(addrbuf_prev, prev, sizeof(addrbuf_prev), 1) == NULL) strlcpy(addrbuf_prev, "???", TOR_ADDR_BUF_LEN); if (tor_addr_to_str(addrbuf_cur, cur, sizeof(addrbuf_cur), 1) == NULL) strlcpy(addrbuf_cur, "???", TOR_ADDR_BUF_LEN); if (!tor_addr_is_null(prev)) log_fn(severity, LD_GENERAL, "Our IP Address has changed from %s to %s; " "rebuilding descriptor (source: %s).", addrbuf_prev, addrbuf_cur, source); else log_notice(LD_GENERAL, "Guessed our IP address as %s (source: %s).", addrbuf_cur, source); } /** Check whether our own address as defined by the Address configuration * has changed. This is for routers that get their address from a service * like dyndns. If our address has changed, mark our descriptor dirty. */ void check_descriptor_ipaddress_changed(time_t now) { uint32_t prev, cur; const or_options_t *options = get_options(); const char *method = NULL; char *hostname = NULL; (void) now; if (!desc_routerinfo) return; /* XXXX ipv6 */ prev = desc_routerinfo->addr; if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) { log_info(LD_CONFIG,"options->Address didn't resolve into an IP."); return; } if (prev != cur) { char *source; tor_addr_t tmp_prev, tmp_cur; tor_addr_from_ipv4h(&tmp_prev, prev); tor_addr_from_ipv4h(&tmp_cur, cur); tor_asprintf(&source, "METHOD=%s%s%s", method, hostname ? " HOSTNAME=" : "", hostname ? hostname : ""); log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, source); tor_free(source); ip_address_changed(0); } tor_free(hostname); } /** The most recently guessed value of our IP address, based on directory * headers. */ static tor_addr_t last_guessed_ip = TOR_ADDR_NULL; /** A directory server d_conn told us our IP address is * suggestion. * If this address is different from the one we think we are now, and * if our computer doesn't actually know its IP address, then switch. */ void router_new_address_suggestion(const char *suggestion, const dir_connection_t *d_conn) { tor_addr_t addr; uint32_t cur = 0; /* Current IPv4 address. */ const or_options_t *options = get_options(); /* first, learn what the IP address actually is */ if (tor_addr_parse(&addr, suggestion) == -1) { log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.", escaped(suggestion)); return; } log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion); if (!server_mode(options)) { tor_addr_copy(&last_guessed_ip, &addr); return; } /* XXXX ipv6 */ cur = get_last_resolved_addr(); if (cur || resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) { /* We're all set -- we already know our address. Great. */ tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we need it later */ return; } if (tor_addr_is_internal(&addr, 0)) { /* Don't believe anybody who says our IP is, say, 127.0.0.1. */ return; } if (tor_addr_eq(&d_conn->base_.addr, &addr)) { /* Don't believe anybody who says our IP is their IP. */ log_debug(LD_DIR, "A directory server told us our IP address is %s, " "but he's just reporting his own IP address. Ignoring.", suggestion); return; } /* Okay. We can't resolve our own address, and X-Your-Address-Is is giving * us an answer different from what we had the last time we managed to * resolve it. */ if (!tor_addr_eq(&last_guessed_ip, &addr)) { control_event_server_status(LOG_NOTICE, "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV", suggestion); log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr, d_conn->base_.address); ip_address_changed(0); tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor() will fetch it */ } } /** We failed to resolve our address locally, but we'd like to build * a descriptor and publish / test reachability. If we have a guess * about our address based on directory headers, answer it and return * 0; else return -1. */ static int router_guess_address_from_dir_headers(uint32_t *guess) { if (!tor_addr_is_null(&last_guessed_ip)) { *guess = tor_addr_to_ipv4h(&last_guessed_ip); return 0; } return -1; } /** Set platform (max length len) to a NUL-terminated short * string describing the version of Tor and the operating system we're * currently running on. */ STATIC void get_platform_str(char *platform, size_t len) { tor_snprintf(platform, len, "Tor %s on %s", get_short_version(), get_uname()); } /* XXX need to audit this thing and count fenceposts. maybe * refactor so we don't have to keep asking if we're * near the end of maxlen? */ #define DEBUG_ROUTER_DUMP_ROUTER_TO_STRING /** OR only: Given a routerinfo for this router, and an identity key to sign * with, encode the routerinfo as a signed server descriptor and return a new * string encoding the result, or NULL on failure. */ char * router_dump_router_to_string(routerinfo_t *router, const crypto_pk_t *ident_key, const crypto_pk_t *tap_key, const curve25519_keypair_t *ntor_keypair, const ed25519_keypair_t *signing_keypair) { char *address = NULL; char *onion_pkey = NULL; /* Onion key, PEM-encoded. */ char *identity_pkey = NULL; /* Identity key, PEM-encoded. */ char digest[DIGEST256_LEN]; char published[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; char *extra_info_line = NULL; size_t onion_pkeylen, identity_pkeylen; char *family_line = NULL; char *extra_or_address = NULL; const or_options_t *options = get_options(); smartlist_t *chunks = NULL; char *output = NULL; const int emit_ed_sigs = signing_keypair && router->signing_key_cert; char *ed_cert_line = NULL; char *rsa_tap_cc_line = NULL; char *ntor_cc_line = NULL; /* Make sure the identity key matches the one in the routerinfo. */ if (!crypto_pk_eq_keys(ident_key, router->identity_pkey)) { log_warn(LD_BUG,"Tried to sign a router with a private key that didn't " "match router's public key!"); goto err; } if (emit_ed_sigs) { if (!router->signing_key_cert->signing_key_included || !ed25519_pubkey_eq(&router->signing_key_cert->signed_key, &signing_keypair->pubkey)) { log_warn(LD_BUG, "Tried to sign a router descriptor with a mismatched " "ed25519 key chain %d", router->signing_key_cert->signing_key_included); goto err; } } /* record our fingerprint, so we can include it in the descriptor */ if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) { log_err(LD_BUG,"Error computing fingerprint"); goto err; } if (emit_ed_sigs) { /* Encode ed25519 signing cert */ char ed_cert_base64[256]; char ed_fp_base64[ED25519_BASE64_LEN+1]; if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64), (const char*)router->signing_key_cert->encoded, router->signing_key_cert->encoded_len, BASE64_ENCODE_MULTILINE) < 0) { log_err(LD_BUG,"Couldn't base64-encode signing key certificate!"); goto err; } if (ed25519_public_to_base64(ed_fp_base64, &router->signing_key_cert->signing_key)<0) { log_err(LD_BUG,"Couldn't base64-encode identity key\n"); goto err; } tor_asprintf(&ed_cert_line, "identity-ed25519\n" "-----BEGIN ED25519 CERT-----\n" "%s" "-----END ED25519 CERT-----\n" "master-key-ed25519 %s\n", ed_cert_base64, ed_fp_base64); } /* PEM-encode the onion key */ if (crypto_pk_write_public_key_to_string(router->onion_pkey, &onion_pkey,&onion_pkeylen)<0) { log_warn(LD_BUG,"write onion_pkey to string failed!"); goto err; } /* PEM-encode the identity key */ if (crypto_pk_write_public_key_to_string(router->identity_pkey, &identity_pkey,&identity_pkeylen)<0) { log_warn(LD_BUG,"write identity_pkey to string failed!"); goto err; } /* Cross-certify with RSA key */ if (tap_key && router->signing_key_cert && router->signing_key_cert->signing_key_included) { char buf[256]; int tap_cc_len = 0; uint8_t *tap_cc = make_tap_onion_key_crosscert(tap_key, &router->signing_key_cert->signing_key, router->identity_pkey, &tap_cc_len); if (!tap_cc) { log_warn(LD_BUG,"make_tap_onion_key_crosscert failed!"); goto err; } if (base64_encode(buf, sizeof(buf), (const char*)tap_cc, tap_cc_len, BASE64_ENCODE_MULTILINE) < 0) { log_warn(LD_BUG,"base64_encode(rsa_crosscert) failed!"); tor_free(tap_cc); goto err; } tor_free(tap_cc); tor_asprintf(&rsa_tap_cc_line, "onion-key-crosscert\n" "-----BEGIN CROSSCERT-----\n" "%s" "-----END CROSSCERT-----\n", buf); } /* Cross-certify with onion keys */ if (ntor_keypair && router->signing_key_cert && router->signing_key_cert->signing_key_included) { int sign = 0; char buf[256]; /* XXXX Base the expiration date on the actual onion key expiration time?*/ tor_cert_t *cert = make_ntor_onion_key_crosscert(ntor_keypair, &router->signing_key_cert->signing_key, router->cache_info.published_on, MIN_ONION_KEY_LIFETIME, &sign); if (!cert) { log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!"); goto err; } tor_assert(sign == 0 || sign == 1); if (base64_encode(buf, sizeof(buf), (const char*)cert->encoded, cert->encoded_len, BASE64_ENCODE_MULTILINE)<0) { log_warn(LD_BUG,"base64_encode(ntor_crosscert) failed!"); tor_cert_free(cert); goto err; } tor_cert_free(cert); tor_asprintf(&ntor_cc_line, "ntor-onion-key-crosscert %d\n" "-----BEGIN ED25519 CERT-----\n" "%s" "-----END ED25519 CERT-----\n", sign, buf); } /* Encode the publication time. */ format_iso_time(published, router->cache_info.published_on); if (router->declared_family && smartlist_len(router->declared_family)) { char *family = smartlist_join_strings(router->declared_family, " ", 0, NULL); tor_asprintf(&family_line, "family %s\n", family); tor_free(family); } else { family_line = tor_strdup(""); } if (!tor_digest_is_zero(router->cache_info.extra_info_digest)) { char extra_info_digest[HEX_DIGEST_LEN+1]; base16_encode(extra_info_digest, sizeof(extra_info_digest), router->cache_info.extra_info_digest, DIGEST_LEN); if (!tor_digest256_is_zero(router->extra_info_digest256)) { char d256_64[BASE64_DIGEST256_LEN+1]; digest256_to_base64(d256_64, router->extra_info_digest256); tor_asprintf(&extra_info_line, "extra-info-digest %s %s\n", extra_info_digest, d256_64); } else { tor_asprintf(&extra_info_line, "extra-info-digest %s\n", extra_info_digest); } } if (router->ipv6_orport && tor_addr_family(&router->ipv6_addr) == AF_INET6) { char addr[TOR_ADDR_BUF_LEN]; const char *a; a = tor_addr_to_str(addr, &router->ipv6_addr, sizeof(addr), 1); if (a) { tor_asprintf(&extra_or_address, "or-address %s:%d\n", a, router->ipv6_orport); log_debug(LD_OR, "My or-address line is <%s>", extra_or_address); } } address = tor_dup_ip(router->addr); chunks = smartlist_new(); /* Generate the easy portion of the router descriptor. */ smartlist_add_asprintf(chunks, "router %s %s %d 0 %d\n" "%s" "%s" "platform %s\n" "protocols Link 1 2 Circuit 1\n" "published %s\n" "fingerprint %s\n" "uptime %ld\n" "bandwidth %d %d %d\n" "%s%s" "onion-key\n%s" "signing-key\n%s" "%s%s" "%s%s%s%s", router->nickname, address, router->or_port, decide_to_advertise_dirport(options, router->dir_port), ed_cert_line ? ed_cert_line : "", extra_or_address ? extra_or_address : "", router->platform, published, fingerprint, stats_n_seconds_working, (int) router->bandwidthrate, (int) router->bandwidthburst, (int) router->bandwidthcapacity, extra_info_line ? extra_info_line : "", (options->DownloadExtraInfo || options->V3AuthoritativeDir) ? "caches-extra-info\n" : "", onion_pkey, identity_pkey, rsa_tap_cc_line ? rsa_tap_cc_line : "", ntor_cc_line ? ntor_cc_line : "", family_line, we_are_hibernating() ? "hibernating 1\n" : "", "hidden-service-dir\n", options->AllowSingleHopExits ? "allow-single-hop-exits\n" : ""); if (options->ContactInfo && strlen(options->ContactInfo)) { const char *ci = options->ContactInfo; if (strchr(ci, '\n') || strchr(ci, '\r')) ci = escaped(ci); smartlist_add_asprintf(chunks, "contact %s\n", ci); } if (router->onion_curve25519_pkey) { char kbuf[128]; base64_encode(kbuf, sizeof(kbuf), (const char *)router->onion_curve25519_pkey->public_key, CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE); smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf); } /* Write the exit policy to the end of 's'. */ if (!router->exit_policy || !smartlist_len(router->exit_policy)) { smartlist_add(chunks, tor_strdup("reject *:*\n")); } else if (router->exit_policy) { char *exit_policy = router_dump_exit_policy_to_string(router,1,0); if (!exit_policy) goto err; smartlist_add_asprintf(chunks, "%s\n", exit_policy); tor_free(exit_policy); } if (router->ipv6_exit_policy) { char *p6 = write_short_policy(router->ipv6_exit_policy); if (p6 && strcmp(p6, "reject 1-65535")) { smartlist_add_asprintf(chunks, "ipv6-policy %s\n", p6); } tor_free(p6); } /* Sign the descriptor with Ed25519 */ if (emit_ed_sigs) { smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); crypto_digest_smartlist_prefix(digest, DIGEST256_LEN, ED_DESC_SIGNATURE_PREFIX, chunks, "", DIGEST_SHA256); ed25519_signature_t sig; char buf[ED25519_SIG_BASE64_LEN+1]; if (ed25519_sign(&sig, (const uint8_t*)digest, DIGEST256_LEN, signing_keypair) < 0) goto err; if (ed25519_signature_to_base64(buf, &sig) < 0) goto err; smartlist_add_asprintf(chunks, "%s\n", buf); } /* Sign the descriptor with RSA */ smartlist_add(chunks, tor_strdup("router-signature\n")); crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); note_crypto_pk_op(SIGN_RTR); { char *sig; if (!(sig = router_get_dirobj_signature(digest, DIGEST_LEN, ident_key))) { log_warn(LD_BUG, "Couldn't sign router descriptor"); goto err; } smartlist_add(chunks, sig); } /* include a last '\n' */ smartlist_add(chunks, tor_strdup("\n")); output = smartlist_join_strings(chunks, "", 0, NULL); #ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING { char *s_dup; 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, NULL); if (!ri_tmp) { log_err(LD_BUG, "We just generated a router descriptor we can't parse."); log_err(LD_BUG, "Descriptor was: <<%s>>", output); goto err; } tor_free(s_dup); routerinfo_free(ri_tmp); } #endif goto done; err: tor_free(output); /* sets output to NULL */ done: if (chunks) { SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); smartlist_free(chunks); } tor_free(address); tor_free(family_line); tor_free(onion_pkey); tor_free(identity_pkey); tor_free(extra_or_address); tor_free(ed_cert_line); tor_free(rsa_tap_cc_line); tor_free(ntor_cc_line); tor_free(extra_info_line); return output; } /** * OR only: Given router, produce a string with its exit policy. * If include_ipv4 is true, include IPv4 entries. * If include_ipv6 is true, include IPv6 entries. */ char * router_dump_exit_policy_to_string(const routerinfo_t *router, int include_ipv4, int include_ipv6) { smartlist_t *exit_policy_strings; char *policy_string = NULL; if ((!router->exit_policy) || (router->policy_is_reject_star)) { return tor_strdup("reject *:*"); } exit_policy_strings = smartlist_new(); SMARTLIST_FOREACH_BEGIN(router->exit_policy, addr_policy_t *, tmpe) { char *pbuf; int bytes_written_to_pbuf; if ((tor_addr_family(&tmpe->addr) == AF_INET6) && (!include_ipv6)) { continue; /* Don't include IPv6 parts of address policy */ } if ((tor_addr_family(&tmpe->addr) == AF_INET) && (!include_ipv4)) { continue; /* Don't include IPv4 parts of address policy */ } pbuf = tor_malloc(POLICY_BUF_LEN); bytes_written_to_pbuf = policy_write_item(pbuf,POLICY_BUF_LEN, tmpe, 1); if (bytes_written_to_pbuf < 0) { log_warn(LD_BUG, "router_dump_exit_policy_to_string ran out of room!"); tor_free(pbuf); goto done; } smartlist_add(exit_policy_strings,pbuf); } SMARTLIST_FOREACH_END(tmpe); policy_string = smartlist_join_strings(exit_policy_strings, "\n", 0, NULL); done: SMARTLIST_FOREACH(exit_policy_strings, char *, str, tor_free(str)); smartlist_free(exit_policy_strings); return policy_string; } /** Copy the primary (IPv4) OR port (IP address and TCP port) for * router into *ap_out. */ void router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out) { tor_assert(ap_out != NULL); tor_addr_from_ipv4h(&ap_out->addr, router->addr); ap_out->port = router->or_port; } /** Return 1 if any of router's addresses are addr. * Otherwise return 0. */ int router_has_addr(const routerinfo_t *router, const tor_addr_t *addr) { return tor_addr_eq_ipv4h(addr, router->addr) || tor_addr_eq(&router->ipv6_addr, addr); } int router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport) { return (tor_addr_eq_ipv4h(&orport->addr, router->addr) && orport->port == router->or_port) || (tor_addr_eq(&orport->addr, &router->ipv6_addr) && orport->port == router->ipv6_orport); } /** Load the contents of filename, find the last line starting with * end_line, ensure that its timestamp is not more than 25 hours in * the past or more than 1 hour in the future with respect to now, * and write the file contents starting with that line to *out. * Return 1 for success, 0 if the file does not exist or is empty, or -1 * if the file does not contain a line matching these criteria or other * failure. */ static int load_stats_file(const char *filename, const char *end_line, time_t now, char **out) { int r = -1; char *fname = get_datadir_fname(filename); char *contents, *start = NULL, *tmp, timestr[ISO_TIME_LEN+1]; time_t written; switch (file_status(fname)) { case FN_FILE: /* X022 Find an alternative to reading the whole file to memory. */ if ((contents = read_file_to_str(fname, 0, NULL))) { tmp = strstr(contents, end_line); /* Find last block starting with end_line */ while (tmp) { start = tmp; tmp = strstr(tmp + 1, end_line); } if (!start) goto notfound; if (strlen(start) < strlen(end_line) + 1 + sizeof(timestr)) goto notfound; strlcpy(timestr, start + 1 + strlen(end_line), sizeof(timestr)); if (parse_iso_time(timestr, &written) < 0) goto notfound; if (written < now - (25*60*60) || written > now + (1*60*60)) goto notfound; *out = tor_strdup(start); r = 1; } notfound: tor_free(contents); break; /* treat empty stats files as if the file doesn't exist */ case FN_NOENT: case FN_EMPTY: r = 0; break; case FN_ERROR: case FN_DIR: default: break; } tor_free(fname); return r; } /** Write the contents of extrainfo and aggregated statistics to * *s_out, signing them with ident_key. Return 0 on * success, negative on failure. */ int extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, crypto_pk_t *ident_key, const ed25519_keypair_t *signing_keypair) { const or_options_t *options = get_options(); char identity[HEX_DIGEST_LEN+1]; char published[ISO_TIME_LEN+1]; char digest[DIGEST_LEN]; char *bandwidth_usage; int result; static int write_stats_to_extrainfo = 1; char sig[DIROBJ_MAX_SIG_LEN+1]; char *s = NULL, *pre, *contents, *cp, *s_dup = NULL; time_t now = time(NULL); smartlist_t *chunks = smartlist_new(); extrainfo_t *ei_tmp = NULL; const int emit_ed_sigs = signing_keypair && extrainfo->signing_key_cert; char *ed_cert_line = NULL; base16_encode(identity, sizeof(identity), extrainfo->cache_info.identity_digest, DIGEST_LEN); format_iso_time(published, extrainfo->cache_info.published_on); bandwidth_usage = rep_hist_get_bandwidth_lines(); if (emit_ed_sigs) { if (!extrainfo->signing_key_cert->signing_key_included || !ed25519_pubkey_eq(&extrainfo->signing_key_cert->signed_key, &signing_keypair->pubkey)) { log_warn(LD_BUG, "Tried to sign a extrainfo descriptor with a " "mismatched ed25519 key chain %d", extrainfo->signing_key_cert->signing_key_included); goto err; } char ed_cert_base64[256]; if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64), (const char*)extrainfo->signing_key_cert->encoded, extrainfo->signing_key_cert->encoded_len, BASE64_ENCODE_MULTILINE) < 0) { log_err(LD_BUG,"Couldn't base64-encode signing key certificate!"); goto err; } tor_asprintf(&ed_cert_line, "identity-ed25519\n" "-----BEGIN ED25519 CERT-----\n" "%s" "-----END ED25519 CERT-----\n", ed_cert_base64); } else { ed_cert_line = tor_strdup(""); } tor_asprintf(&pre, "extra-info %s %s\n%spublished %s\n%s", extrainfo->nickname, identity, ed_cert_line, published, bandwidth_usage); smartlist_add(chunks, pre); if (geoip_is_loaded(AF_INET)) smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", geoip_db_digest(AF_INET)); if (geoip_is_loaded(AF_INET6)) smartlist_add_asprintf(chunks, "geoip6-db-digest %s\n", geoip_db_digest(AF_INET6)); if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { log_info(LD_GENERAL, "Adding stats to extra-info descriptor."); if (options->DirReqStatistics && load_stats_file("stats"PATH_SEPARATOR"dirreq-stats", "dirreq-stats-end", now, &contents) > 0) { smartlist_add(chunks, contents); } if (options->HiddenServiceStatistics && load_stats_file("stats"PATH_SEPARATOR"hidserv-stats", "hidserv-stats-end", now, &contents) > 0) { smartlist_add(chunks, contents); } if (options->EntryStatistics && load_stats_file("stats"PATH_SEPARATOR"entry-stats", "entry-stats-end", now, &contents) > 0) { smartlist_add(chunks, contents); } if (options->CellStatistics && load_stats_file("stats"PATH_SEPARATOR"buffer-stats", "cell-stats-end", now, &contents) > 0) { smartlist_add(chunks, contents); } if (options->ExitPortStatistics && load_stats_file("stats"PATH_SEPARATOR"exit-stats", "exit-stats-end", now, &contents) > 0) { smartlist_add(chunks, contents); } if (options->ConnDirectionStatistics && load_stats_file("stats"PATH_SEPARATOR"conn-stats", "conn-bi-direct", now, &contents) > 0) { smartlist_add(chunks, contents); } } /* Add information about the pluggable transports we support. */ if (options->ServerTransportPlugin) { char *pluggable_transports = pt_get_extra_info_descriptor_string(); if (pluggable_transports) smartlist_add(chunks, pluggable_transports); } if (should_record_bridge_info(options) && write_stats_to_extrainfo) { const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now); if (bridge_stats) { smartlist_add(chunks, tor_strdup(bridge_stats)); } } if (emit_ed_sigs) { char digest[DIGEST256_LEN]; smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); crypto_digest_smartlist_prefix(digest, DIGEST256_LEN, ED_DESC_SIGNATURE_PREFIX, chunks, "", DIGEST_SHA256); ed25519_signature_t sig; char buf[ED25519_SIG_BASE64_LEN+1]; if (ed25519_sign(&sig, (const uint8_t*)digest, DIGEST256_LEN, signing_keypair) < 0) goto err; if (ed25519_signature_to_base64(buf, &sig) < 0) goto err; smartlist_add_asprintf(chunks, "%s\n", buf); } smartlist_add(chunks, tor_strdup("router-signature\n")); s = smartlist_join_strings(chunks, "", 0, NULL); while (strlen(s) > MAX_EXTRAINFO_UPLOAD_SIZE - DIROBJ_MAX_SIG_LEN) { /* So long as there are at least two chunks (one for the initial * extra-info line and one for the router-signature), we can keep removing * things. */ if (smartlist_len(chunks) > 2) { /* We remove the next-to-last element (remember, len-1 is the last element), since we need to keep the router-signature element. */ int idx = smartlist_len(chunks) - 2; char *e = smartlist_get(chunks, idx); smartlist_del_keeporder(chunks, idx); log_warn(LD_GENERAL, "We just generated an extra-info descriptor " "with statistics that exceeds the 50 KB " "upload limit. Removing last added " "statistics."); tor_free(e); tor_free(s); s = smartlist_join_strings(chunks, "", 0, NULL); } else { log_warn(LD_BUG, "We just generated an extra-info descriptors that " "exceeds the 50 KB upload limit."); goto err; } } memset(sig, 0, sizeof(sig)); if (router_get_extrainfo_hash(s, strlen(s), digest) < 0 || router_append_dirobj_signature(sig, sizeof(sig), digest, DIGEST_LEN, ident_key) < 0) { log_warn(LD_BUG, "Could not append signature to extra-info " "descriptor."); goto err; } smartlist_add(chunks, tor_strdup(sig)); tor_free(s); s = smartlist_join_strings(chunks, "", 0, NULL); cp = s_dup = tor_strdup(s); 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 " "with statistics that we can't parse. Not " "adding statistics to this or any future " "extra-info descriptors."); write_stats_to_extrainfo = 0; result = extrainfo_dump_to_string(s_out, extrainfo, ident_key, signing_keypair); goto done; } else { log_warn(LD_BUG, "We just generated an extrainfo descriptor we " "can't parse."); goto err; } } *s_out = s; s = NULL; /* prevent free */ result = 0; goto done; err: result = -1; done: tor_free(s); SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); smartlist_free(chunks); tor_free(s_dup); tor_free(ed_cert_line); extrainfo_free(ei_tmp); tor_free(bandwidth_usage); return result; } /** Return true iff s is a valid server nickname. (That is, a string * containing between 1 and MAX_NICKNAME_LEN characters from * LEGAL_NICKNAME_CHARACTERS.) */ int is_legal_nickname(const char *s) { size_t len; tor_assert(s); len = strlen(s); return len > 0 && len <= MAX_NICKNAME_LEN && strspn(s,LEGAL_NICKNAME_CHARACTERS) == len; } /** Return true iff s is a valid server nickname or * hex-encoded identity-key digest. */ int is_legal_nickname_or_hexdigest(const char *s) { if (*s!='$') return is_legal_nickname(s); else return is_legal_hexdigest(s); } /** Return true iff s is a valid hex-encoded identity-key * digest. (That is, an optional $, followed by 40 hex characters, * followed by either nothing, or = or ~ followed by a nickname, or * a character other than =, ~, or a hex character.) */ int is_legal_hexdigest(const char *s) { size_t len; tor_assert(s); if (s[0] == '$') s++; len = strlen(s); if (len > HEX_DIGEST_LEN) { if (s[HEX_DIGEST_LEN] == '=' || s[HEX_DIGEST_LEN] == '~') { if (!is_legal_nickname(s+HEX_DIGEST_LEN+1)) return 0; } else { return 0; } } return (len >= HEX_DIGEST_LEN && strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN); } /** Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to * hold a human-readable description of a node with identity digest * id_digest, named-status is_named, nickname nickname, * and address addr or addr32h. * * The nickname and addr fields are optional and may be set to * NULL. The addr32h field is optional and may be set to 0. * * Return a pointer to the front of buf. */ const char * format_node_description(char *buf, const char *id_digest, int is_named, const char *nickname, const tor_addr_t *addr, uint32_t addr32h) { char *cp; if (!buf) return ""; buf[0] = '$'; base16_encode(buf+1, HEX_DIGEST_LEN+1, id_digest, DIGEST_LEN); cp = buf+1+HEX_DIGEST_LEN; if (nickname) { buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~'; strlcpy(buf+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1); cp += strlen(cp); } if (addr32h || addr) { memcpy(cp, " at ", 4); cp += 4; if (addr) { tor_addr_to_str(cp, addr, TOR_ADDR_BUF_LEN, 0); } else { struct in_addr in; in.s_addr = htonl(addr32h); tor_inet_ntoa(&in, cp, INET_NTOA_BUF_LEN); } } return buf; } /** Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to * hold a human-readable description of ri. * * * Return a pointer to the front of buf. */ const char * router_get_description(char *buf, const routerinfo_t *ri) { if (!ri) return ""; return format_node_description(buf, ri->cache_info.identity_digest, router_is_named(ri), ri->nickname, NULL, ri->addr); } /** Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to * hold a human-readable description of node. * * Return a pointer to the front of buf. */ const char * node_get_description(char *buf, const node_t *node) { const char *nickname = NULL; uint32_t addr32h = 0; int is_named = 0; if (!node) return ""; if (node->rs) { nickname = node->rs->nickname; is_named = node->rs->is_named; addr32h = node->rs->addr; } else if (node->ri) { nickname = node->ri->nickname; addr32h = node->ri->addr; } return format_node_description(buf, node->identity, is_named, nickname, NULL, addr32h); } /** Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to * hold a human-readable description of rs. * * Return a pointer to the front of buf. */ const char * routerstatus_get_description(char *buf, const routerstatus_t *rs) { if (!rs) return ""; return format_node_description(buf, rs->identity_digest, rs->is_named, rs->nickname, NULL, rs->addr); } /** Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to * hold a human-readable description of ei. * * Return a pointer to the front of buf. */ const char * extend_info_get_description(char *buf, const extend_info_t *ei) { if (!ei) return ""; return format_node_description(buf, ei->identity_digest, 0, ei->nickname, &ei->addr, 0); } /** Return a human-readable description of the routerinfo_t ri. * * This function is not thread-safe. Each call to this function invalidates * previous values returned by this function. */ const char * router_describe(const routerinfo_t *ri) { static char buf[NODE_DESC_BUF_LEN]; return router_get_description(buf, ri); } /** Return a human-readable description of the node_t node. * * This function is not thread-safe. Each call to this function invalidates * previous values returned by this function. */ const char * node_describe(const node_t *node) { static char buf[NODE_DESC_BUF_LEN]; return node_get_description(buf, node); } /** Return a human-readable description of the routerstatus_t rs. * * This function is not thread-safe. Each call to this function invalidates * previous values returned by this function. */ const char * routerstatus_describe(const routerstatus_t *rs) { static char buf[NODE_DESC_BUF_LEN]; return routerstatus_get_description(buf, rs); } /** Return a human-readable description of the extend_info_t ri. * * This function is not thread-safe. Each call to this function invalidates * previous values returned by this function. */ const char * extend_info_describe(const extend_info_t *ei) { static char buf[NODE_DESC_BUF_LEN]; return extend_info_get_description(buf, ei); } /** Set buf (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the * verbose representation of the identity of router. The format is: * A dollar sign. * The upper-case hexadecimal encoding of the SHA1 hash of router's identity. * A "=" if the router is named; a "~" if it is not. * The router's nickname. **/ void router_get_verbose_nickname(char *buf, const routerinfo_t *router) { const char *good_digest = networkstatus_get_router_digest_by_nickname( router->nickname); int is_named = good_digest && tor_memeq(good_digest, router->cache_info.identity_digest, DIGEST_LEN); buf[0] = '$'; base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest, DIGEST_LEN); buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~'; strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1); } /** Forget that we have issued any router-related warnings, so that we'll * warn again if we see the same errors. */ void router_reset_warnings(void) { if (warned_nonexistent_family) { SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp)); smartlist_clear(warned_nonexistent_family); } } /** Given a router purpose, convert it to a string. Don't call this on * ROUTER_PURPOSE_UNKNOWN: The whole point of that value is that we don't * know its string representation. */ const char * router_purpose_to_string(uint8_t p) { switch (p) { case ROUTER_PURPOSE_GENERAL: return "general"; case ROUTER_PURPOSE_BRIDGE: return "bridge"; case ROUTER_PURPOSE_CONTROLLER: return "controller"; default: tor_assert(0); } return NULL; } /** Given a string, convert it to a router purpose. */ uint8_t router_purpose_from_string(const char *s) { if (!strcmp(s, "general")) return ROUTER_PURPOSE_GENERAL; else if (!strcmp(s, "bridge")) return ROUTER_PURPOSE_BRIDGE; else if (!strcmp(s, "controller")) return ROUTER_PURPOSE_CONTROLLER; else return ROUTER_PURPOSE_UNKNOWN; } /** Release all static resources held in router.c */ void router_free_all(void) { crypto_pk_free(onionkey); crypto_pk_free(lastonionkey); crypto_pk_free(server_identitykey); crypto_pk_free(client_identitykey); tor_mutex_free(key_lock); routerinfo_free(desc_routerinfo); extrainfo_free(desc_extrainfo); crypto_pk_free(authority_signing_key); authority_cert_free(authority_key_certificate); crypto_pk_free(legacy_signing_key); authority_cert_free(legacy_key_certificate); memwipe(&curve25519_onion_key, 0, sizeof(curve25519_onion_key)); memwipe(&last_curve25519_onion_key, 0, sizeof(last_curve25519_onion_key)); if (warned_nonexistent_family) { SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp)); smartlist_free(warned_nonexistent_family); } } /** Return a smartlist of tor_addr_port_t's with all the OR ports of ri. Note that freeing of the items in the list as well as the smartlist itself is the callers responsibility. XXX duplicating code from node_get_all_orports(). */ smartlist_t * router_get_all_orports(const routerinfo_t *ri) { smartlist_t *sl = smartlist_new(); tor_assert(ri); if (ri->addr != 0) { tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); tor_addr_from_ipv4h(&ap->addr, ri->addr); ap->port = ri->or_port; smartlist_add(sl, ap); } if (!tor_addr_is_null(&ri->ipv6_addr)) { tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); tor_addr_copy(&ap->addr, &ri->ipv6_addr); ap->port = ri->or_port; smartlist_add(sl, ap); } return sl; }