diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt index 4ba31e4cd0..fc86c86776 100644 --- a/doc/tor-spec.txt +++ b/doc/tor-spec.txt @@ -188,12 +188,6 @@ TODO: (very soon) onion router in the circuit; the public key hash is the SHA1 hash of the PKCS#1 ASN1 encoding of the next onion router's identity (signing) key. - [XXXX Before 0.0.8, EXTEND cells did not include the public key hash. - Servers running 0.0.8 distinguish the old-style cells based on the - length of payloads. (Servers running 0.0.7 blindly pass on the extend - cell regardless of length.) In a future release, old-style EXTEND - cells will not be supported.] - The payload for a CREATED cell, or the relay payload for an EXTENDED cell, contains: DH data (g^y) [128 bytes] @@ -662,8 +656,6 @@ The items' formats are as follows: over any ten second period in the past day, and another sustained input. The "observed" value is the lesser of these two numbers. - [bandwidth-observed was not present before 0.0.8.] - "platform" string A human-readable string describing the system on which this OR is @@ -680,6 +672,17 @@ The items' formats are as follows: in hex, with spaces after every 4 characters) for this router's identity key. + [We didn't start parsing this line until Tor 0.1.0.6-rc; it should + be marked with "opt" until earlier versions of Tor are obsolete.] + + "hibernating" 0|1 + + If the value is 1, then the Tor server was hibernating when the + descriptor was published, and shouldn't be used to build circuits. + + [We didn't start parsing this line until Tor 0.1.0.6-rc; it should + be marked with "opt" until earlier versions of Tor are obsolete.] + "uptime" The number of seconds that this OR process has been running. @@ -709,17 +712,6 @@ The items' formats are as follows: The router descriptor is invalid unless the signature is performed with the router's identity key. - "dircacheport" port NL - - Same as declaring "port" as this OR's directory port in the 'router' - line. At most one of dircacheport and the directory port in the router - line may be non-zero. - - [Obsolete; will go away once 0.0.8 is dead. Older versions of Tor - did poorly when non-authoritative directories had a non-zero directory - port. To transition, Tor 0.0.8 used dircacheport for - nonauthoritative directories.] - "contact" info NL Describes a way to contact the server's administrator, preferably @@ -743,6 +735,9 @@ The items' formats are as follows: the end of the most recent interval. The numbers are the number of bytes used in the most recent intervals, ordered from oldest to newest. + [We didn't start parsing these lines until Tor 0.1.0.6-rc; they should + be marked with "opt" until earlier versions of Tor are obsolete.] + nickname ::= between 1 and 19 alphanumeric characters, case-insensitive. exitpattern ::= addrspec ":" portspec @@ -764,7 +759,7 @@ line, they must appear in the "ports" lines. A Directory begins with a "signed-directory" item, followed by one each of the following, in any order: "recommended-software", "published", -"router-status", "directory-signing-key". It may include any number of "opt" +"router-status", "dir-signing-key". It may include any number of "opt" items. After these items, a directory includes any number of router descriptors, and a single "directory-signature" item. @@ -776,7 +771,7 @@ descriptors, and a single "directory-signature" item. The time at which this directory was generated and signed, in GMT. - "directory-signing-key" + "dir-signing-key" The key used to sign this directory; see "signing-key" for format. @@ -816,8 +811,6 @@ descriptors, and a single "directory-signature" item. When parsing this line, clients should only mark a router as 'verified' if its nickname AND digest match the one provided. - [XXXX 'router-status' was added in 0.0.9pre5; older directory code - uses 'running-routers' instead.] "directory-signature" nickname-of-dirserver NL Signature diff --git a/src/or/control.c b/src/or/control.c index 32ccbf5967..c1b44df7e2 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -630,7 +630,7 @@ handle_getinfo_helper(const char *question, char **answer) routerlist_t *routerlist; router_get_routerlist(&routerlist); if (!routerlist || !routerlist->routers || - list_server_status(routerlist->routers, NULL, answer) < 0) { + list_server_status(routerlist->routers, answer) < 0) { return -1; } } else if (!strcmpstart(question, "addr-mappings/")) { diff --git a/src/or/dirserv.c b/src/or/dirserv.c index ee2c596917..994a4e6749 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -490,13 +490,11 @@ dirserv_load_from_directory_string(const char *dir) /** * Allocate and return a description of the status of the server desc, - * for use in a running-routers line (if rr_format is true), or in a - * router-status line (if rr_format is false. The server is listed + * for use in a router-status line. The server is listed * as running iff is_live is true. */ static char * -list_single_server_status(routerinfo_t *desc, int is_live, - int rr_format) +list_single_server_status(routerinfo_t *desc, int is_live) { char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */ char *cp; @@ -510,29 +508,21 @@ list_single_server_status(routerinfo_t *desc, int is_live, if (desc->is_verified) { strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf)); cp += strlen(cp); - if (!rr_format) - *cp++ = '='; - } - if (!desc->is_verified || !rr_format) { - *cp++ = '$'; - base16_encode(cp, HEX_DIGEST_LEN+1, desc->identity_digest, - DIGEST_LEN); + *cp++ = '='; } + *cp++ = '$'; + base16_encode(cp, HEX_DIGEST_LEN+1, desc->identity_digest, + DIGEST_LEN); return tor_strdup(buf); } /** Based on the routerinfo_ts in routers, allocate the - * contents of a running-routers line and a router-status line, and - * store them in *running_routers_out and - * *router_status_out respectively. If either is NULL, skip - * it. Return 0 on success, -1 on failure. + * contents of a router-status line, and store it in + * *router_status_out. Return 0 on success, -1 on failure. */ int -list_server_status(smartlist_t *routers, char **running_routers_out, char **router_status_out) +list_server_status(smartlist_t *routers, char **router_status_out) { - /* List of entries in running-routers style: An optional !, then either - * a nickname or a dollar-prefixed hexdigest. */ - smartlist_t *rr_entries; /* List of entries in a router-status style: An optional !, then an optional * equals-suffixed nickname, then a dollar-prefixed hexdigest. */ smartlist_t *rs_entries; @@ -542,9 +532,8 @@ list_server_status(smartlist_t *routers, char **running_routers_out, char **rout * series. */ int authdir_mode = get_options()->AuthoritativeDir; - tor_assert(running_routers_out || router_status_out); + tor_assert(router_status_out); - rr_entries = smartlist_create(); rs_entries = smartlist_create(); SMARTLIST_FOREACH(routers, routerinfo_t *, ri, @@ -562,18 +551,12 @@ list_server_status(smartlist_t *routers, char **running_routers_out, char **rout } else { is_live = ri->is_running; } - smartlist_add(rr_entries, list_single_server_status(ri, is_live, 1)); - smartlist_add(rs_entries, list_single_server_status(ri, is_live, 0)); + smartlist_add(rs_entries, list_single_server_status(ri, is_live)); }); - if (running_routers_out) - *running_routers_out = smartlist_join_strings(rr_entries, " ", 0,NULL); - if (router_status_out) - *router_status_out = smartlist_join_strings(rs_entries, " ", 0,NULL); + *router_status_out = smartlist_join_strings(rs_entries, " ", 0,NULL); - SMARTLIST_FOREACH(rr_entries, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp)); - smartlist_free(rr_entries); smartlist_free(rs_entries); return 0; @@ -613,7 +596,7 @@ dirserv_dump_directory_to_string(char **dir_out, crypto_pk_env_t *private_key) { char *cp; - char *running_routers, *router_status; + char *router_status; char *identity_pkey; /* Identity key, DER64-encoded. */ char *recommended_versions; char digest[20]; @@ -623,6 +606,7 @@ dirserv_dump_directory_to_string(char **dir_out, char *buf = NULL; size_t buf_len; int i; + size_t identity_pkey_len; tor_assert(dir_out); *dir_out = NULL; @@ -630,27 +614,14 @@ dirserv_dump_directory_to_string(char **dir_out, if (!descriptor_list) descriptor_list = smartlist_create(); - if (list_server_status(descriptor_list, &running_routers, &router_status)) + if (list_server_status(descriptor_list, &router_status)) return -1; - /* ASN.1-encode the public key. This is a temporary measure; once - * everyone is running 0.0.9pre3 or later, we can shift to using a - * PEM-encoded key instead. - */ -#if 1 - if (crypto_pk_DER64_encode_public_key(private_key, &identity_pkey)<0) { + if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey, + &identity_pkey_len)<0) { log_fn(LOG_WARN,"write identity_pkey to string failed!"); return -1; } -#else - { - int l; - if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,&l)<0) { - log_fn(LOG_WARN,"write identity_pkey to string failed!"); - return -1; - } - } -#endif { smartlist_t *versions; @@ -669,7 +640,7 @@ dirserv_dump_directory_to_string(char **dir_out, published_on = time(NULL); format_iso_time(published, published_on); - buf_len = 2048+strlen(recommended_versions)+strlen(running_routers)+ + buf_len = 2048+strlen(recommended_versions)+ strlen(router_status); SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, buf_len += strlen(ri->signed_descriptor)); @@ -683,14 +654,12 @@ dirserv_dump_directory_to_string(char **dir_out, "signed-directory\n" "published %s\n" "recommended-software %s\n" - "running-routers %s\n" - "opt router-status %s\n" - "opt dir-signing-key %s\n\n", - published, recommended_versions, running_routers, router_status, + "router-status %s\n" + "dir-signing-key\n%s\n", + published, recommended_versions, router_status, identity_pkey); tor_free(recommended_versions); - tor_free(running_routers); tor_free(router_status); tor_free(identity_pkey); i = strlen(buf); @@ -890,31 +859,19 @@ static int generate_runningrouters(crypto_pk_env_t *private_key) size_t len; time_t published_on; char *identity_pkey; /* Identity key, DER64-encoded. */ + size_t identity_pkey_len; if (!descriptor_list) descriptor_list = smartlist_create(); - if (list_server_status(descriptor_list, NULL, &router_status)) { + if (list_server_status(descriptor_list, &router_status)) { goto err; } - /* ASN.1-encode the public key. This is a temporary measure; once - * everyone is running 0.0.9pre3 or later, we can shift to using a - * PEM-encoded key instead. - */ -#if 1 - if (crypto_pk_DER64_encode_public_key(private_key, &identity_pkey)<0) { + if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey, + &identity_pkey_len)<0) { log_fn(LOG_WARN,"write identity_pkey to string failed!"); goto err; } -#else - { - int l; - if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,&l)<0) { - log_fn(LOG_WARN,"write identity_pkey to string failed!"); - goto err; - } - } -#endif published_on = time(NULL); format_iso_time(published, published_on); @@ -923,7 +880,7 @@ static int generate_runningrouters(crypto_pk_env_t *private_key) tor_snprintf(s, len, "network-status\n" "published %s\n" "router-status %s\n" - "opt dir-signing-key %s\n" + "dir-signing-key\n%s" "directory-signature %s\n" "-----BEGIN SIGNATURE-----\n", published, router_status, identity_pkey, get_options()->Nickname); diff --git a/src/or/or.h b/src/or/or.h index 6df4996cd8..c874e6ffdd 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -699,6 +699,8 @@ typedef struct { smartlist_t *declared_family; /**< Nicknames of router which this router * claims are its family. */ + + char *contact_info; /**< Declared contact info for this router. */ } routerinfo_t; /** Contents of a running-routers list */ @@ -706,7 +708,6 @@ typedef struct running_routers_t { time_t published_on; /**< When was the list marked as published? */ /** Which ORs are on the list? Entries may be prefixed with ! and $. */ smartlist_t *running_routers; - int is_running_routers_format; /**< Are we using the old entry format? */ } running_routers_t; /** Contents of a directory of onion routers. */ @@ -1472,8 +1473,7 @@ const char *dirserv_get_nickname_by_digest(const char *digest); int dirserv_add_descriptor(const char **desc, const char **msg); int dirserv_load_from_directory_string(const char *dir); void dirserv_free_descriptors(void); -int list_server_status(smartlist_t *routers, - char **running_routers_out, char **router_status_out); +int list_server_status(smartlist_t *routers, char **router_status_out); void dirserv_remove_old_servers(int age); int dirserv_dump_directory_to_string(char **dir_out, crypto_pk_env_t *private_key); @@ -1811,12 +1811,10 @@ void routerlist_update_from_runningrouters(routerlist_t *list, running_routers_t *rr); int routers_update_status_from_entry(smartlist_t *routers, time_t list_time, - const char *s, - int rr_format); + const char *s); int router_update_status_from_smartlist(routerinfo_t *r, time_t list_time, - smartlist_t *running_list, - int rr_format); + smartlist_t *running_list); void add_trusted_dir_server(const char *addr, uint16_t port,const char *digest); void clear_trusted_dir_servers(void); diff --git a/src/or/router.c b/src/or/router.c index dc61dea58f..365de0f0e5 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -814,9 +814,9 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, if (router->declared_family && smartlist_len(router->declared_family)) { size_t n; char *s = smartlist_join_strings(router->declared_family, " ", 0, &n); - n += strlen("opt family ") + 2; /* 1 for \n, 1 for \0. */ + n += strlen("family ") + 2; /* 1 for \n, 1 for \0. */ family_line = tor_malloc(n); - tor_snprintf(family_line, n, "opt family %s\n", s); + tor_snprintf(family_line, n, "family %s\n", s); tor_free(s); } else { family_line = tor_strdup(""); @@ -828,7 +828,7 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, "platform %s\n" "published %s\n" "opt fingerprint %s\n" - "opt uptime %ld\n" + "uptime %ld\n" "bandwidth %d %d %d\n" "onion-key\n%s" "signing-key\n%s%s%s%s", @@ -857,7 +857,7 @@ int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, written = result; if (get_options()->ContactInfo && strlen(get_options()->ContactInfo)) { - result = tor_snprintf(s+written,maxlen-written, "opt contact %s\n", + result = tor_snprintf(s+written,maxlen-written, "contact %s\n", get_options()->ContactInfo); if (result<0) return -1; diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 7a2546555d..0184f2c1dc 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -916,8 +916,7 @@ router_load_single_router(const char *s, const char **msg) running_routers_t *rr = routerlist->running_routers; router_update_status_from_smartlist(ri, rr->published_on, - rr->running_routers, - rr->is_running_routers_format); + rr->running_routers); } if (router_add_to_routerlist(ri, msg)<0) { log_fn(LOG_WARN, "Couldn't add router to list; dropping."); @@ -1276,7 +1275,7 @@ void routerlist_update_from_runningrouters(routerlist_t *list, smartlist_add_all(all_routers,list->routers); SMARTLIST_FOREACH(rr->running_routers, const char *, cp, routers_update_status_from_entry(all_routers, rr->published_on, - cp, rr->is_running_routers_format)); + cp)); smartlist_free(all_routers); list->running_routers_updated_on = rr->published_on; } @@ -1302,8 +1301,7 @@ void routerlist_update_from_runningrouters(routerlist_t *list, */ int routers_update_status_from_entry(smartlist_t *routers, time_t list_time, - const char *s, - int rr_format) + const char *s) { int is_running = 1; int is_verified = 0; @@ -1365,16 +1363,9 @@ int routers_update_status_from_entry(smartlist_t *routers, } /* Make sure that the entry was in the right format. */ - if (rr_format) { - if (is_verified == hex_digest_set) { - log_fn(LOG_WARN, "Invalid syntax for running-routers member (%s)", s); - return -1; - } - } else { - if (!hex_digest_set) { - log_fn(LOG_WARN, "Invalid syntax for router-status member (%s)", s); - return -1; - } + if (!hex_digest_set) { + log_fn(LOG_WARN, "Invalid syntax for router-status member (%s)", s); + return -1; } /* Okay, we're done parsing. For all routers that match, update their status. @@ -1383,11 +1374,11 @@ int routers_update_status_from_entry(smartlist_t *routers, { int nickname_matches = is_verified && !strcasecmp(r->nickname, nickname); int digest_matches = !memcmp(digest, r->identity_digest, DIGEST_LEN); - if (nickname_matches && (digest_matches||rr_format)) + if (nickname_matches && digest_matches) r->is_verified = 1; else if (digest_matches) r->is_verified = 0; - if (digest_matches || (nickname_matches&&rr_format)) + if (digest_matches) if (r->status_set_at < list_time) { r->is_running = is_running; r->status_set_at = time(NULL); @@ -1402,14 +1393,13 @@ int routers_update_status_from_entry(smartlist_t *routers, int router_update_status_from_smartlist(routerinfo_t *router, time_t list_time, - smartlist_t *running_list, - int rr_format) + smartlist_t *running_list) { smartlist_t *rl; rl = smartlist_create(); smartlist_add(rl,router); SMARTLIST_FOREACH(running_list, const char *, cp, - routers_update_status_from_entry(rl,list_time,cp,rr_format)); + routers_update_status_from_entry(rl,list_time,cp)); smartlist_free(rl); return 0; } diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 31fed0d418..6e615e4f49 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -38,12 +38,15 @@ typedef enum { K_OPT, K_BANDWIDTH, K_PORTS, - K_DIRCACHEPORT, K_CONTACT, K_NETWORK_STATUS, K_UPTIME, K_DIR_SIGNING_KEY, K_FAMILY, + K_FINGERPRINT, + K_HIBERNATING, + K_READ_HISTORY, + K_WRITE_HISTORY, _UNRECOGNIZED, _ERR, _EOF, @@ -114,12 +117,15 @@ static struct { { "platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ, RTR_ONLY }, { "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ, ANY }, { "opt", K_OPT, CONCAT_ARGS, OBJ_OK, ANY }, - { "dircacheport", K_DIRCACHEPORT, ARGS, NO_OBJ, RTR_ONLY }, { "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ, ANY }, { "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ, DIR_ONLY }, { "uptime", K_UPTIME, ARGS, NO_OBJ, RTR_ONLY }, { "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK, DIR_ONLY }, { "family", K_FAMILY, ARGS, NO_OBJ, RTR_ONLY }, + { "fingerprint", K_FINGERPRINT, ARGS, NO_OBJ, ANY }, + { "hibernating", K_HIBERNATING, ARGS, NO_OBJ, RTR_ONLY }, + { "read-history", K_READ_HISTORY, ARGS, NO_OBJ, RTR_ONLY }, + { "write-history", K_WRITE_HISTORY, ARGS, NO_OBJ, RTR_ONLY }, { NULL, -1, NO_ARGS, NO_OBJ, ANY } }; @@ -358,7 +364,6 @@ router_parse_routerlist_from_directory(const char *str, char digest[DIGEST_LEN]; routerlist_t *new_dir = NULL; char *versions = NULL; - int nickname_list_is_running_routers; smartlist_t *good_nickname_list = NULL; time_t published_on; int i, r; @@ -466,14 +471,11 @@ router_parse_routerlist_from_directory(const char *str, /* Prefer router-status, then running-routers. */ if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) { - if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) { - log_fn(LOG_WARN, - "Missing running-routers/router-status line from directory."); - goto err; - } + log_fn(LOG_WARN, + "Missing router-status line from directory."); + goto err; } - nickname_list_is_running_routers = (tok->tp == K_RUNNING_ROUTERS); good_nickname_list = smartlist_create(); for (i=0; in_args; ++i) { smartlist_add(good_nickname_list, tok->args[i]); @@ -497,7 +499,7 @@ router_parse_routerlist_from_directory(const char *str, routerinfo_t *me = router_get_my_routerinfo(); if (me) { if (router_update_status_from_smartlist(me, - published_on, good_nickname_list, tok->tp==K_RUNNING_ROUTERS)==1 && + published_on, good_nickname_list)==1 && me->is_verified == 0 && !have_warned_about_unverified_status) { log_fn(LOG_WARN,"Dirserver '%s' lists your server as unverified. Please consider sending your identity fingerprint to the tor-ops.", dirnickname); have_warned_about_unverified_status = 1; @@ -510,8 +512,6 @@ router_parse_routerlist_from_directory(const char *str, new_dir->running_routers = tor_malloc_zero(sizeof(running_routers_t)); new_dir->running_routers->published_on = published_on; new_dir->running_routers->running_routers = good_nickname_list; - new_dir->running_routers->is_running_routers_format = - nickname_list_is_running_routers; SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok)); smartlist_free(tokens); @@ -599,7 +599,6 @@ router_parse_runningrouters(const char *str, int write_to_cache) new_list = tor_malloc_zero(sizeof(running_routers_t)); new_list->published_on = published_on; new_list->running_routers = smartlist_create(); - new_list->is_running_routers_format = (tok->tp == K_RUNNING_ROUTERS); for (i=0;in_args;++i) { smartlist_add(new_list->running_routers, tok->args[i]); } @@ -659,6 +658,8 @@ static crypto_pk_env_t *find_dir_signing_key(const char *str) key = tok->key; tok->key = NULL; /* steal reference. */ } else if (tok->n_args >= 1) { + /** XXXX Once all the directories are running 0.1.0.6-rc or later, we + * can remove this logic. */ key = crypto_pk_DER64_decode_public_key(tok->args[0]); if (!key) { log_fn(LOG_WARN, "Unparseable dir-signing-key argument"); @@ -801,8 +802,7 @@ router_parse_list_from_string(const char **s, routerlist_t **dest, if (good_nickname_list) { SMARTLIST_FOREACH(good_nickname_list, const char *, cp, - routers_update_status_from_entry(routers, published_on, - cp, rr_format)); + routers_update_status_from_entry(routers, published_on, cp)); } if (*dest) @@ -893,17 +893,6 @@ routerinfo_t *router_parse_entry_from_string(const char *s, ports_set = 1; } - tok = find_first_by_keyword(tokens, K_DIRCACHEPORT); - if (tok) { - if (router->dir_port) - log_fn(LOG_WARN,"Redundant dircacheport line"); - if (tok->n_args != 1) { - log_fn(LOG_WARN,"Wrong # of arguments to \"dircacheport\""); - goto err; - } - router->dir_port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,NULL,NULL); - } - tok = find_first_by_keyword(tokens, K_BANDWIDTH); if (tok && bw_set) { log_fn(LOG_WARN,"Redundant bandwidth line"); @@ -964,6 +953,10 @@ routerinfo_t *router_parse_entry_from_string(const char *s, router->platform = tor_strdup(tok->args[0]); } + if ((tok = find_first_by_keyword(tokens, K_CONTACT))) { + router->contact_info = tor_strdup(tok->args[0]); + } + exit_policy_tokens = find_all_exitpolicy(tokens); SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t, if (router_add_exit_policy(router,t)<0) { diff --git a/src/or/test.c b/src/or/test.c index 6d2ed4b497..e4b000b965 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -1148,7 +1148,7 @@ test_dir_format(void) "opt fingerprint "); test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1)); strcat(buf2, fingerprint); - strcat(buf2, "\nopt uptime 0\n" + strcat(buf2, "\nuptime 0\n" /* XXX the "0" above is hardcoded, but even if we made it reflect * uptime, that still wouldn't make it right, because the two * descriptors might be made on different seconds... hm. */ @@ -1395,4 +1395,3 @@ main(int c, char**v) { else return 0; } -