Merge branch 'maint-0.2.1' into release-0.2.1

This commit is contained in:
Roger Dingledine 2011-05-10 21:26:01 -04:00
commit 75953f9b60
30 changed files with 8608 additions and 4769 deletions

View File

@ -3,6 +3,57 @@ This document summarizes new features and bugfixes in each stable release
of Tor. If you want to see more detailed descriptions of the changes in
each development snapshot, see the ChangeLog file.
Changes in version 0.2.1.30 - 2011-02-23
Tor 0.2.1.30 fixes a variety of less critical bugs. The main other
change is a slight tweak to Tor's TLS handshake that makes relays
and bridges that run this new version reachable from Iran again.
We don't expect this tweak will win the arms race long-term, but it
buys us time until we roll out a better solution.
o Major bugfixes:
- Stop sending a CLOCK_SKEW controller status event whenever
we fetch directory information from a relay that has a wrong clock.
Instead, only inform the controller when it's a trusted authority
that claims our clock is wrong. Bugfix on 0.1.2.6-alpha; fixes
the rest of bug 1074.
- Fix a bounds-checking error that could allow an attacker to
remotely crash a directory authority. Bugfix on 0.2.1.5-alpha.
Found by "piebeer".
- If relays set RelayBandwidthBurst but not RelayBandwidthRate,
Tor would ignore their RelayBandwidthBurst setting,
potentially using more bandwidth than expected. Bugfix on
0.2.0.1-alpha. Reported by Paul Wouters. Fixes bug 2470.
- Ignore and warn if the user mistakenly sets "PublishServerDescriptor
hidserv" in her torrc. The 'hidserv' argument never controlled
publication of hidden service descriptors. Bugfix on 0.2.0.1-alpha.
o Minor features:
- Adjust our TLS Diffie-Hellman parameters to match those used by
Apache's mod_ssl.
- Update to the February 1 2011 Maxmind GeoLite Country database.
o Minor bugfixes:
- Check for and reject overly long directory certificates and
directory tokens before they have a chance to hit any assertions.
Bugfix on 0.2.1.28. Found by "doorss".
- Bring the logic that gathers routerinfos and assesses the
acceptability of circuits into line. This prevents a Tor OP from
getting locked in a cycle of choosing its local OR as an exit for a
path (due to a .exit request) and then rejecting the circuit because
its OR is not listed yet. It also prevents Tor clients from using an
OR running in the same instance as an exit (due to a .exit request)
if the OR does not meet the same requirements expected of an OR
running elsewhere. Fixes bug 1859; bugfix on 0.1.0.1-rc.
o Packaging changes:
- Stop shipping the Tor specs files and development proposal documents
in the tarball. They are now in a separate git repository at
git://git.torproject.org/torspec.git
- Do not include Git version tags as though they are SVN tags when
generating a tarball from inside a repository that has switched
between branches. Bugfix on 0.2.1.15-rc; fixes bug 2402.
Changes in version 0.2.1.29 - 2011-01-15
Tor 0.2.1.29 continues our recent code security audit work. The main
fix resolves a remote heap overflow vulnerability that can allow remote

4
changes/all_descs Normal file
View File

@ -0,0 +1,4 @@
o Major bugfixes (bridge authority)
- Do not allow encrypte requests for "all" bridges to return all
bridges.

9
changes/bug1172 Normal file
View File

@ -0,0 +1,9 @@
o Minor bugfixes:
- When we restart our relay, we might get a successful connection
from the outside before we've started our reachability tests,
triggering a warning: "ORPort found reachable, but I have no
routerinfo yet. Failing to inform controller of success." This
bug was harmless unless Tor is running under a controller
like Vidalia, in which case the controller would never get a
REACHABILITY_SUCCEEDED status event. Bugfix on 0.1.2.6-alpha;
fixes bug 1172.

6
changes/bug2402_redux Normal file
View File

@ -0,0 +1,6 @@
o Minor bugfixes
- Use micro-revision numbers in 0.2.1.x instead: apparently, they
were more used than we had known. (Bugfix on 0.2.1.30).
- Instead of generating our micro-version numbers using SVN revisions,
use git revisions instead. Bugfix on 0.2.1.15-rc; fixes bug 2402.

5
changes/bug2475 Normal file
View File

@ -0,0 +1,5 @@
o Minor bugfixes:
- Avoid signed/unsigned comparisons by making SIZE_T_CEILING unsigned.
(None of the cases where we did this before were wrong, but by making
this change we can avoid warnings.) Fixes bug2475; bugfix on
Tor 0.2.1.28.

5
changes/bug2629 Normal file
View File

@ -0,0 +1,5 @@
o Minor bugfixes
- Fix a crash bug that could occur occasionally when a client was
configured with a large number of bridges. Fixes bug 2629; bugfix
on 0.2.1.2-alpha. Bugfix by trac user "shitlei".

6
changes/bug2750 Normal file
View File

@ -0,0 +1,6 @@
o Minor bugfixes
- Correct the warning displayed when a rendezvous descriptor exceeds
the maximum size. Fixes bug 2750; bugfix on 0.2.1.5-alpha. Found
by John Brooks.

4
changes/bug2933 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes
- Fix an uncommon assertion failure when running with DNSPort under
heavy load. Fixes bug 2933; bugfix on 2.0.1-alpha.

View File

@ -0,0 +1,9 @@
o Security fixes:
- Forget all hidden service descriptors cached as a client when
processing a SIGNAL NEWNYM command. Fixes bug 3000. Bugfix on
0.0.6.
o Code simplifications and refactoring:
- Allow rend_client_send_introduction to fail without closing the
AP connection permanently.

3
changes/geoip-apr2011 Normal file
View File

@ -0,0 +1,3 @@
o Minor features:
- Update to the April 1 2011 Maxmind GeoLite Country database.

3
changes/geoip-mar2011 Normal file
View File

@ -0,0 +1,3 @@
o Minor features:
- Update to the March 1 2011 Maxmind GeoLite Country database.

4
changes/ipv6_crash Normal file
View File

@ -0,0 +1,4 @@
o Major bugfixes:
- Fix a crash in parsing router descriptors containing IPv6
addresses. This one crashed the directory authorities when somebody
fired up some experimental code. Bugfix on 0.2.1.3-alpha.

View File

@ -0,0 +1,3 @@
o Minor bugfixes
- When warning about missing zlib development packages, give the
correct package names. Bugfix on 0.2.0.1-alpha.

View File

@ -336,10 +336,10 @@ AC_SUBST(TOR_OPENSSL_LIBS)
dnl ------------------------------------------------------
dnl Where do you live, zlib? And how do we call you?
tor_openssl_pkg_redhat="zlib"
tor_openssl_pkg_debian="zlib1g"
tor_openssl_devpkg_redhat="zlib-devel"
tor_openssl_devpkg_debian="zlib1g-dev"
tor_zlib_pkg_redhat="zlib"
tor_zlib_pkg_debian="zlib1g"
tor_zlib_devpkg_redhat="zlib-devel"
tor_zlib_devpkg_debian="zlib1g-dev"
TOR_SEARCH_LIBRARY(zlib, $tryzlibdir, [-lz],
[#include <zlib.h>],

View File

@ -452,7 +452,7 @@ crypto_pk_read_private_key_from_string(crypto_pk_env_t *env,
tor_assert(env);
tor_assert(s);
tor_assert(len < INT_MAX && len < SIZE_T_CEILING);
tor_assert(len < INT_MAX && len < SSIZE_T_CEILING);
/* Create a read-only memory BIO, backed by the string 's' */
b = BIO_new_mem_buf((char*)s, (int)len);

View File

@ -330,8 +330,10 @@ typedef uint32_t uintptr_t;
#endif
#endif
/* Any ssize_t larger than this amount is likely to be an underflow. */
#define SSIZE_T_CEILING ((ssize_t)(SSIZE_T_MAX-16))
/* Any size_t larger than this amount is likely to be an underflow. */
#define SIZE_T_CEILING (SSIZE_T_MAX-16)
#define SIZE_T_CEILING ((size_t)(SSIZE_T_MAX-16))
#endif /* __TORINT_H */

File diff suppressed because it is too large Load Diff

View File

@ -55,52 +55,18 @@ noinst_HEADERS = or.h eventdns.h eventdns_tor.h micro-revision.i
tor_main.o: micro-revision.i
micro-revision.i: FORCE
@svkdir=$$SVKROOT; \
if test "x$$svkdir" = x ; then \
svkdir=$$HOME/.svk; \
fi; \
if test -d ../../.git && test -x "`which git 2>&1;true`" ; then \
if test -d ../../.git/svn && test -x "`which git-svn 2>&1;true`" ; then \
git-svn info ../../README | \
sed -n 's/^Revision: \([0-9][0-9]*\).*/"\1"/p' \
> micro-revision.tmp \
|| true; \
fi; \
elif test -d ../../.svn && test -x "`which svn 2>&1;true`" ; then \
svn info ../.. | \
sed -n 's/^Revision: \([0-9][0-9]*\).*/"\1"/p' > micro-revision.tmp \
|| true; \
elif test -x "`which svk 2>&1;true`" && test -d $$svkdir/local; then \
location=../..; \
rev=x; \
while test x$$rev = xx; do \
x=`svk info $$location | \
sed -n 's/^Mirrored From:.*, Rev\. \([0-9][0-9]*\)/\1/p'`; \
if test x$$x != x; then \
rev=$$x; \
break; \
else \
loc=`svk info $$location | \
sed -n 's/^Copied From: \(.*\), Rev\. [0-9][0-9]*/\1/p' | \
head -1`; \
if test x$$loc = x; then \
break; \
else \
location=/$$loc; \
fi; \
fi; \
done; \
if test x$$rev != xx; then \
echo \"$$rev\" > micro-revision.tmp; \
fi; \
fi; \
if test ! -f micro-revision.tmp ; then \
if test ! -f micro-revision.i ; then \
echo '""' > micro-revision.i; \
fi; \
elif test ! -f micro-revision.i || \
test x"`cat micro-revision.tmp`" != x"`cat micro-revision.i`"; then \
mv micro-revision.tmp micro-revision.i; \
@rm -f micro-revision.tmp; \
if test -d ../../.git && test -x "`which git 2>&1;true`"; then \
HASH="`git rev-parse --short=16 HEAD`"; \
echo \"$$HASH\" > micro-revision.tmp; \
fi; \
if test ! -f micro-revision.tmp ; then \
if test ! -f micro-revision.i ; then \
echo '""' > micro-revision.i; \
fi; \
elif test ! -f micro-revision.i || \
test x"`cat micro-revision.tmp`" != x"`cat micro-revision.i`"; then \
mv micro-revision.tmp micro-revision.i; \
fi; true
#Dummy target to ensure that micro-revision.i _always_ gets built.

View File

@ -3200,7 +3200,8 @@ any_pending_bridge_descriptor_fetches(void)
conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
TO_DIR_CONN(conn)->router_purpose == ROUTER_PURPOSE_BRIDGE &&
!conn->marked_for_close &&
conn->linked && !conn->linked_conn->marked_for_close) {
conn->linked &&
conn->linked_conn && !conn->linked_conn->marked_for_close) {
log_debug(LD_DIR, "found one: %s", conn->address);
return 1;
}

View File

@ -1560,14 +1560,21 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
"introduction. (stream %d sec old)",
introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
conn_age);
if (rend_client_send_introduction(introcirc, rendcirc) < 0) {
switch (rend_client_send_introduction(introcirc, rendcirc)) {
case 0: /* success */
rendcirc->_base.timestamp_dirty = time(NULL);
introcirc->_base.timestamp_dirty = time(NULL);
assert_circuit_ok(TO_CIRCUIT(rendcirc));
assert_circuit_ok(TO_CIRCUIT(introcirc));
return 0;
case -1: /* transient error */
return 0;
case -2: /* permanent error */
return -1;
default: /* oops */
tor_fragile_assert();
return -1;
}
rendcirc->_base.timestamp_dirty = time(NULL);
introcirc->_base.timestamp_dirty = time(NULL);
assert_circuit_ok(TO_CIRCUIT(rendcirc));
assert_circuit_ok(TO_CIRCUIT(introcirc));
return 0;
}
}

View File

@ -827,7 +827,16 @@ static char *_version = NULL;
const char *
get_version(void)
{
return VERSION;
if (_version == NULL) {
if (strlen(tor_svn_revision)) {
size_t len = strlen(VERSION)+strlen(tor_svn_revision)+16;
_version = tor_malloc(len);
tor_snprintf(_version, len, "%s (git-%s)", VERSION, tor_svn_revision);
} else {
_version = tor_strdup(VERSION);
}
}
return _version;
}
/** Release additional memory allocated in options

View File

@ -2699,6 +2699,8 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
smartlist_add(fps_out,
tor_memdup(r->cache_info.identity_digest, DIGEST_LEN)));
/* Treat "all" requests as if they were unencrypted */
for_unencrypted_conn = 1;
} else if (!strcmp(key, "authority")) {
routerinfo_t *ri = router_get_my_routerinfo();
if (ri)

View File

@ -1949,7 +1949,7 @@ server_request_free(struct server_request *req)
if (req->port) {
if (req->port->pending_replies == req) {
if (req->next_pending)
if (req->next_pending && req->next_pending != req)
req->port->pending_replies = req->next_pending;
else
req->port->pending_replies = NULL;

View File

@ -785,6 +785,8 @@ signewnym_impl(time_t now)
{
circuit_expire_all_dirty_circs();
addressmap_clear_transient();
rend_cache_purge();
rend_client_cancel_descriptor_fetches();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
}

View File

@ -4039,6 +4039,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
size_t request_len);
void rend_client_refetch_renddesc(const char *query);
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
void rend_client_cancel_descriptor_fetches(void);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const rend_data_t *rend_query);
int rend_client_rendezvous_acked(origin_circuit_t *circ,
@ -4137,6 +4138,7 @@ typedef struct rend_cache_entry_t {
void rend_cache_init(void);
void rend_cache_clean(void);
void rend_cache_clean_v2_descs_as_dir(void);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_valid_service_id(const char *query);
int rend_cache_lookup_desc(const char *query, int version, const char **desc,

View File

@ -880,6 +880,8 @@ exit_policy_is_general_exit(smartlist_t *policy)
for (i = 0; i < 3; ++i) {
SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
if (tor_addr_family(&p->addr) != AF_INET)
continue; /* IPv4 only for now */
if (p->prt_min > ports[i] || p->prt_max < ports[i])
continue; /* Doesn't cover our port. */
if (p->maskbits > 8)

View File

@ -74,10 +74,27 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
&entry) < 1) {
log_warn(LD_REND,
"query %s didn't have valid rend desc in cache. Failing.",
escaped_safe_str(introcirc->rend_data->onion_address));
goto err;
log_info(LD_REND,
"query %s didn't have valid rend desc in cache. "
"Refetching descriptor.",
safe_str(introcirc->rend_data->onion_address));
/* Fetch both v0 and v2 rend descriptors in parallel. Use whichever
* arrives first. Exception: When using client authorization, only
* fetch v2 descriptors.*/
rend_client_refetch_v2_renddesc(introcirc->rend_data);
if (introcirc->rend_data->auth_type == REND_NO_AUTH)
rend_client_refetch_renddesc(introcirc->rend_data->onion_address);
{
connection_t *conn;
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT,
introcirc->rend_data->onion_address, -1))) {
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
}
}
return -1;
}
/* first 20 bytes of payload are the hash of Bob's pk */
@ -115,13 +132,13 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
log_info(LD_REND, "Internal error: could not find intro key; we "
"only have a v2 rend desc with %d intro points.",
num_intro_points);
goto err;
goto perm_err;
}
}
}
if (crypto_pk_get_digest(intro_key, payload)<0) {
log_warn(LD_BUG, "Internal error: couldn't hash public key.");
goto err;
goto perm_err;
}
/* Initialize the pending_final_cpath and start the DH handshake. */
@ -132,11 +149,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
cpath->magic = CRYPT_PATH_MAGIC;
if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
goto err;
goto perm_err;
}
if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) {
log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
goto err;
goto perm_err;
}
}
@ -186,7 +203,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
DH_KEY_LEN)<0) {
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
goto err;
goto perm_err;
}
note_crypto_pk_op(REND_CLIENT);
@ -199,7 +216,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
PK_PKCS1_OAEP_PADDING, 0);
if (r<0) {
log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed.");
goto err;
goto perm_err;
}
payload_len = DIGEST_LEN + r;
@ -212,17 +229,17 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
introcirc->cpath->prev)<0) {
/* introcirc is already marked for close. leave rendcirc alone. */
log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell");
return -1;
return -2;
}
/* Now, we wait for an ACK or NAK on this circuit. */
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
return 0;
err:
perm_err:
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
return -1;
return -2;
}
/** Called when a rendezvous circuit is open; sends a establish
@ -412,7 +429,7 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
tor_assert(rend_query);
/* Determine responsible dirs. Even if we can't get all we want,
* work with the ones we have. If it's empty, we'll notice below. */
(int) hid_serv_get_responsible_directories(responsible_dirs, desc_id);
hid_serv_get_responsible_directories(responsible_dirs, desc_id);
base32_encode(desc_id_base32, sizeof(desc_id_base32),
desc_id, DIGEST_LEN);
@ -557,8 +574,45 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
return;
}
/** Cancel all rendezvous descriptor fetches currently in progress.
*/
void
rend_client_cancel_descriptor_fetches(void)
{
smartlist_t *connection_array = get_connection_array();
SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
(conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
/* It's a rendezvous descriptor fetch in progress -- cancel it
* by marking the connection for close.
*
* Even if this connection has already reached EOF, this is
* enough to make sure that if the descriptor hasn't been
* processed yet, it won't be. See the end of
* connection_handle_read; connection_reached_eof (indirectly)
* processes whatever response the connection received. */
const rend_data_t *rd = (TO_DIR_CONN(conn))->rend_data;
if (!rd) {
log_warn(LD_BUG | LD_REND,
"Marking for close dir conn fetching rendezvous "
"descriptor for unknown service!");
} else {
log_debug(LD_REND, "Marking for close dir conn fetching v%d "
"rendezvous descriptor for service %s",
(int)(rd->rend_desc_version),
safe_str(rd->onion_address));
}
connection_mark_for_close(conn);
}
} SMARTLIST_FOREACH_END(conn);
}
/** Remove failed_intro from ent. If ent now has no intro points, or
* service is unrecognized, then launch a new renddesc fetch.
*
* Return -1 if error, 0 if no intro points remain or service
* unrecognized, 1 if recognized and some intro points remain.

View File

@ -871,6 +871,16 @@ rend_cache_clean(void)
}
}
/** Remove ALL entries from the rendezvous service descriptor cache.
*/
void
rend_cache_purge(void)
{
if (rend_cache)
strmap_free(rend_cache, _rend_cache_entry_free);
rend_cache = strmap_new();
}
/** Remove all old v2 descriptors and those for which this hidden service
* directory is not responsible for any more. */
void

View File

@ -793,19 +793,14 @@ consider_testing_reachability(int test_or, int test_dir)
void
router_orport_found_reachable(void)
{
if (!can_reach_or_port) {
routerinfo_t *me = router_get_my_routerinfo();
routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_or_port && me) {
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty();
if (!me) { /* should never happen */
log_warn(LD_BUG, "ORPort found reachable, but I have no routerinfo "
"yet. Failing to inform controller of success.");
return;
}
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
me->address, me->or_port);
@ -816,18 +811,13 @@ router_orport_found_reachable(void)
void
router_dirport_found_reachable(void)
{
if (!can_reach_dir_port) {
routerinfo_t *me = router_get_my_routerinfo();
routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_dir_port && me) {
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.");
can_reach_dir_port = 1;
if (!me || decide_to_advertise_dirport(get_options(), me->dir_port))
if (decide_to_advertise_dirport(get_options(), me->dir_port))
mark_my_descriptor_dirty();
if (!me) { /* should never happen */
log_warn(LD_BUG, "DirPort found reachable, but I have no routerinfo "
"yet. Failing to inform controller of success.");
return;
}
control_event_server_status(LOG_NOTICE,
"REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
me->address, me->dir_port);
@ -1586,8 +1576,6 @@ router_guess_address_from_dir_headers(uint32_t *guess)
return -1;
}
extern const char tor_svn_revision[]; /* from tor_main.c */
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
* string describing the version of Tor and the operating system we're
* currently running on.

View File

@ -1369,6 +1369,12 @@ router_parse_entry_from_string(const char *s, const char *end,
router->has_old_dnsworkers = 1;
}
if (find_opt_by_keyword(tokens, K_REJECT6) ||
find_opt_by_keyword(tokens, K_ACCEPT6)) {
log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
"older Tors.");
goto err;
}
exit_policy_tokens = find_all_exitpolicy(tokens);
if (!smartlist_len(exit_policy_tokens)) {
log_warn(LD_DIR, "No exit policy tokens in descriptor.");
@ -3622,8 +3628,10 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
eos = eos + 1;
/* Check length. */
if (strlen(desc) > REND_DESC_MAX_SIZE) {
/* XXX023 If we are parsing this descriptor as a server, this
* should be a protocol warning. */
log_warn(LD_REND, "Descriptor length is %i which exceeds "
"maximum rendezvous descriptor size of %i kilobytes.",
"maximum rendezvous descriptor size of %i bytes.",
(int)strlen(desc), REND_DESC_MAX_SIZE);
goto err;
}