[or-cvs] r16566: {tor} Merge with trunk once more. (in tor/branches/121-hs-authorization: doc src/common src/or)
kloesing at seul.org
kloesing at seul.org
Sat Aug 16 11:36:09 UTC 2008
Author: kloesing
Date: 2008-08-16 07:36:09 -0400 (Sat, 16 Aug 2008)
New Revision: 16566
Modified:
tor/branches/121-hs-authorization/doc/tor.1.in
tor/branches/121-hs-authorization/src/common/address.c
tor/branches/121-hs-authorization/src/common/address.h
tor/branches/121-hs-authorization/src/common/crypto.c
tor/branches/121-hs-authorization/src/common/crypto.h
tor/branches/121-hs-authorization/src/common/mempool.c
tor/branches/121-hs-authorization/src/or/buffers.c
tor/branches/121-hs-authorization/src/or/config.c
tor/branches/121-hs-authorization/src/or/connection.c
tor/branches/121-hs-authorization/src/or/connection_edge.c
tor/branches/121-hs-authorization/src/or/connection_or.c
tor/branches/121-hs-authorization/src/or/control.c
tor/branches/121-hs-authorization/src/or/cpuworker.c
tor/branches/121-hs-authorization/src/or/directory.c
tor/branches/121-hs-authorization/src/or/dirserv.c
tor/branches/121-hs-authorization/src/or/dirvote.c
tor/branches/121-hs-authorization/src/or/dnsserv.c
tor/branches/121-hs-authorization/src/or/main.c
tor/branches/121-hs-authorization/src/or/networkstatus.c
tor/branches/121-hs-authorization/src/or/or.h
tor/branches/121-hs-authorization/src/or/policies.c
tor/branches/121-hs-authorization/src/or/rendclient.c
tor/branches/121-hs-authorization/src/or/rendservice.c
tor/branches/121-hs-authorization/src/or/routerlist.c
tor/branches/121-hs-authorization/src/or/routerparse.c
tor/branches/121-hs-authorization/src/or/test.c
Log:
Merge with trunk once more.
Modified: tor/branches/121-hs-authorization/doc/tor.1.in
===================================================================
--- tor/branches/121-hs-authorization/doc/tor.1.in 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/doc/tor.1.in 2008-08-16 11:36:09 UTC (rev 16566)
@@ -422,10 +422,18 @@
.LP
.TP
\fBExcludeNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
-A list of identity fingerprints or nicknames of nodes to never use when
-building a circuit.
+A list of identity fingerprints, nicknames, and address patterns of
+nodes to never use when building a circuit. (Example: ExcludeNodes
+SlowServer, $ABCDEFFFFFFFFFFFFFFF, 255.254.0.0/8)
.LP
.TP
+\fBExcludeExitNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
+A list of identity fingerprints, nicknames, and address patterns of
+nodes to never use when picking an exit node. Note that any node
+listed in ExcludeNodes is automatically considered to be part of this
+list.
+.LP
+.TP
\fBEntryNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
A list of identity fingerprints or nicknames of preferred nodes to use for the
first hop in the circuit.
@@ -552,16 +560,6 @@
.\" .TP
.LP
.TP
-\fBRendNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
-A list of identity fingerprints or nicknames of preferred nodes to use for the
-rendezvous point, if possible.
-.LP
-.TP
-\fBRendExcludeNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
-A list of identity fingerprints or nicknames of nodes to never use when
-choosing a rendezvous point.
-.LP
-.TP
\fBSocksPort \fR\fIPORT\fP
Advertise this port to listen for connections from Socks-speaking
applications. Set this to 0 if you don't want to allow application
@@ -588,12 +586,6 @@
(Default: 2 minutes.)
.LP
.TP
-\fBTestVia \fR\fInode\fR,\fInode\fR,\fI...\fP
-A list of identity fingerprints or nicknames of nodes to prefer for your middle
-hop when building testing circuits. This option is mainly for debugging
-reachability problems.
-.LP
-.TP
\fBTrackHostExits \fR\fIhost\fR,\fI.domain\fR,\fI...\fR\fP
For each value in the comma separated list, Tor will track recent connections
to hosts that match this value and attempt to
@@ -724,7 +716,7 @@
address that ends with one of the suffixes in
\fBAutomapHostsSuffixes\fP, we map an unused virtual address to that
address, and return the new virtual address. This is handy for making
-.onion addresses work with applications that resolve an address and
+".onion" addresses work with applications that resolve an address and
then connect to it.
(Default: 0).
.LP
@@ -1274,19 +1266,6 @@
one of the TARGETs from those lines will be chosen at random.
.LP
.TP
-\fBHiddenServiceNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
-If possible, use the specified nodes, defined by their identity fingerprints or
-nicknames, as introduction points for the hidden service. If this is left
-unset, Tor will be smart and pick some reasonable ones; most people can leave
-this unset.
-.LP
-.TP
-\fBHiddenServiceExcludeNodes \fR\fInode\fR,\fInode\fR,\fI...\fP
-Do not use the specified nodes, defined by their identity fingerprints or
-nicknames, as introduction points for the hidden service. In normal use there
-is no reason to set this.
-.LP
-.TP
\fBPublishHidServDescriptors \fR\fB0\fR|\fB1\fR\fP
If set to 0, Tor will run any hidden services you configure, but it won't
advertise them to the rendezvous directory. This option is only useful
Modified: tor/branches/121-hs-authorization/src/common/address.c
===================================================================
--- tor/branches/121-hs-authorization/src/common/address.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/common/address.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -94,7 +94,8 @@
/** Set the tor_addr_t in <b>a</b> to contain the socket address contained in
* <b>sa</b>. */
int
-tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa)
+tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
+ uint16_t *port_out)
{
tor_assert(a);
tor_assert(sa);
@@ -103,10 +104,14 @@
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
a->family = AF_INET;
a->addr.in_addr.s_addr = sin->sin_addr.s_addr;
+ if (port_out)
+ *port_out = ntohs(sin->sin_port);
} else if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
a->family = AF_INET6;
memcpy(&a->addr.in6_addr, &sin6->sin6_addr, sizeof(struct in6_addr));
+ if (port_out)
+ *port_out = ntohs(sin6->sin6_port);
} else {
a->family = AF_UNSPEC;
return -1;
@@ -630,6 +635,13 @@
memcpy(dest->addr.in6_addr.s6_addr, ipv6_bytes, 16);
}
+/** DOCDOC */
+void
+tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
+{
+ tor_addr_from_ipv6_bytes(dest, (const char*)in6->s6_addr);
+}
+
/** Copy a tor_addr_t from <b>src</b> to <b>dest</b>.
*/
void
Modified: tor/branches/121-hs-authorization/src/common/address.h
===================================================================
--- tor/branches/121-hs-authorization/src/common/address.h 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/common/address.h 2008-08-16 11:36:09 UTC (rev 16566)
@@ -40,7 +40,8 @@
static INLINE int tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u);
socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port,
struct sockaddr *sa_out, socklen_t len);
-int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa);
+int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa,
+ uint16_t *port_out);
void tor_addr_make_unspec(tor_addr_t *a);
static INLINE const struct in6_addr *
@@ -126,7 +127,8 @@
* order. */
#define tor_addr_from_ipv4h(dest, v4addr) \
tor_addr_from_ipv4n((dest), htonl(v4addr))
-void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *byets);
+void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
+void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
int tor_addr_is_null(const tor_addr_t *addr);
int tor_addr_is_loopback(const tor_addr_t *addr);
Modified: tor/branches/121-hs-authorization/src/common/crypto.c
===================================================================
--- tor/branches/121-hs-authorization/src/common/crypto.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/common/crypto.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -474,17 +474,14 @@
return 0;
}
-/** PEM-encode the public key portion of <b>env</b> and write it to a
- * newly allocated string. On success, set *<b>dest</b> to the new
- * string, *<b>len</b> to the string's length, and return 0. On
- * failure, return -1.
- */
-int
-crypto_pk_write_public_key_to_string(crypto_pk_env_t *env, char **dest,
- size_t *len)
+/** Helper function to implement crypto_pk_write_*_key_to_string. */
+static int
+crypto_pk_write_key_to_string_impl(crypto_pk_env_t *env, char **dest,
+ size_t *len, int is_public)
{
BUF_MEM *buf;
BIO *b;
+ int r;
tor_assert(env);
tor_assert(env->key);
@@ -495,8 +492,13 @@
/* Now you can treat b as if it were a file. Just use the
* PEM_*_bio_* functions instead of the non-bio variants.
*/
- if (!PEM_write_bio_RSAPublicKey(b, env->key)) {
- crypto_log_errors(LOG_WARN, "writing public key to string");
+ if (is_public)
+ r = PEM_write_bio_RSAPublicKey(b, env->key);
+ else
+ r = PEM_write_bio_RSAPrivateKey(b, env->key, NULL,NULL,0,NULL,NULL);
+
+ if (!r) {
+ crypto_log_errors(LOG_WARN, "writing RSA key to string");
BIO_free(b);
return -1;
}
@@ -515,6 +517,18 @@
return 0;
}
+/** PEM-encode the public key portion of <b>env</b> and write it to a
+ * newly allocated string. On success, set *<b>dest</b> to the new
+ * string, *<b>len</b> to the string's length, and return 0. On
+ * failure, return -1.
+ */
+int
+crypto_pk_write_public_key_to_string(crypto_pk_env_t *env, char **dest,
+ size_t *len)
+{
+ return crypto_pk_write_key_to_string_impl(env, dest, len, 1);
+}
+
/** PEM-encode the private key portion of <b>env</b> and write it to a
* newly allocated string. On success, set *<b>dest</b> to the new
* string, *<b>len</b> to the string's length, and return 0. On
@@ -524,36 +538,7 @@
crypto_pk_write_private_key_to_string(crypto_pk_env_t *env, char **dest,
size_t *len)
{
- BUF_MEM *buf;
- BIO *b;
-
- tor_assert(env);
- tor_assert(env->key);
- tor_assert(dest);
-
- b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
-
- /* Now you can treat b as if it were a file. Just use the
- * PEM_*_bio_* functions instead of the non-bio variants.
- */
- if (!PEM_write_bio_RSAPrivateKey(b, env->key, NULL,NULL,0,NULL,NULL)) {
- crypto_log_errors(LOG_WARN, "writing private key to string");
- BIO_free(b);
- return -1;
- }
-
- BIO_get_mem_ptr(b, &buf);
- (void)BIO_set_close(b, BIO_NOCLOSE); /* so BIO_free doesn't free buf */
- BIO_free(b);
-
- tor_assert(buf->length >= 0);
- *dest = tor_malloc(buf->length+1);
- memcpy(*dest, buf->data, buf->length);
- (*dest)[buf->length] = 0; /* nul terminate it */
- *len = buf->length;
- BUF_MEM_free(buf);
-
- return 0;
+ return crypto_pk_write_key_to_string_impl(env, dest, len, 0);
}
/** Read a PEM-encoded public key from the first <b>len</b> characters of
@@ -634,6 +619,15 @@
return r;
}
+/** Return true iff <b>key</b> contains the private-key portion of the RSA
+ * key. */
+int
+crypto_pk_key_is_private(const crypto_pk_env_t *key)
+{
+ tor_assert(key);
+ return PRIVATE_KEY_OK(key);
+}
+
/** Compare the public-key components of a and b. Return -1 if a\<b, 0
* if a==b, and 1 if a\>b.
*/
Modified: tor/branches/121-hs-authorization/src/common/crypto.h
===================================================================
--- tor/branches/121-hs-authorization/src/common/crypto.h 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/common/crypto.h 2008-08-16 11:36:09 UTC (rev 16566)
@@ -92,6 +92,7 @@
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
size_t crypto_pk_keysize(crypto_pk_env_t *env);
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
+int crypto_pk_key_is_private(const crypto_pk_env_t *key);
int crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to,
const char *from, size_t fromlen, int padding);
Modified: tor/branches/121-hs-authorization/src/common/mempool.c
===================================================================
--- tor/branches/121-hs-authorization/src/common/mempool.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/common/mempool.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -144,7 +144,7 @@
};
/** Number of extra bytes needed beyond mem_size to allocate a chunk. */
-#define CHUNK_OVERHEAD (sizeof(mp_chunk_t)-1)
+#define CHUNK_OVERHEAD STRUCT_OFFSET(mp_chunk_t, mem[0])
/** Given a pointer to a mp_allocated_t, return a pointer to the memory
* item it holds. */
Modified: tor/branches/121-hs-authorization/src/or/buffers.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/buffers.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/buffers.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -1309,7 +1309,8 @@
int log_sockstype, int safe_socks)
{
unsigned int len;
- char tmpbuf[INET_NTOA_BUF_LEN];
+ char tmpbuf[TOR_ADDR_BUF_LEN+1];
+ tor_addr_t destaddr;
uint32_t destip;
uint8_t socksver;
enum {socks4, socks4a} socks4_prot = socks4a;
@@ -1374,13 +1375,20 @@
}
switch (*(buf->head->data+3)) { /* address type */
case 1: /* IPv4 address */
+ case 4: /* IPv6 address */ {
+ const int is_v6 = *(buf->head->data+3) == 4;
+ const unsigned addrlen = is_v6 ? 16 : 4;
log_debug(LD_APP,"socks5: ipv4 address type");
- if (buf->datalen < 10) /* ip/port there? */
+ if (buf->datalen < 6+addrlen) /* ip/port there? */
return 0; /* not yet */
- destip = ntohl(*(uint32_t*)(buf->head->data+4));
- in.s_addr = htonl(destip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ if (is_v6)
+ tor_addr_from_ipv6_bytes(&destaddr, buf->head->data+4);
+ else
+ tor_addr_from_ipv4n(&destaddr, get_uint32(buf->head->data+4));
+
+ tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
+
if (strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
log_warn(LD_APP,
"socks5 IP takes %d bytes, which doesn't fit in %d. "
@@ -1389,8 +1397,8 @@
return -1;
}
strlcpy(req->address,tmpbuf,sizeof(req->address));
- req->port = ntohs(*(uint16_t*)(buf->head->data+8));
- buf_remove_from_front(buf, 10);
+ req->port = ntohs(get_uint16(buf->head->data+4+addrlen));
+ buf_remove_from_front(buf, 6+addrlen);
if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
!addressmap_have_mapping(req->address) &&
!have_warned_about_unsafe_socks) {
@@ -1410,6 +1418,7 @@
return -1;
}
return 1;
+ }
case 3: /* fqdn */
log_debug(LD_APP,"socks5: fqdn address type");
if (req->command == SOCKS_COMMAND_RESOLVE_PTR) {
Modified: tor/branches/121-hs-authorization/src/or/config.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/config.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/config.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -227,7 +227,7 @@
VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
- VAR("HidServAuth", LINELIST_S, ClientSideHidServs, NULL),
+ V(HidServAuth, LINELIST, NULL),
V(HSAuthoritativeDir, BOOL, "0"),
V(HSAuthorityRecordStats, BOOL, "0"),
V(HttpProxy, STRING, NULL),
@@ -1061,6 +1061,16 @@
}
}
+#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
+ /* Open /dev/pf before dropping privileges. */
+ if (options->TransPort) {
+ if (get_pf_socket() < 0) {
+ *msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
+ goto rollback;
+ }
+ }
+#endif
+
/* Setuid/setgid as appropriate */
if (options->User || options->Group) {
/* XXXX021 We should only do this the first time through, not on
@@ -1182,6 +1192,12 @@
return -1;
}
+ if (running_tor && rend_parse_service_authorization(options, 0) < 0) {
+ log_warn(LD_BUG, "Previously validated client authorization for "
+ "hidden services could not be added!");
+ return -1;
+ }
+
if (running_tor && directory_caches_v2_dir_info(options)) {
len = strlen(options->DataDirectory)+32;
fn = tor_malloc(len);
@@ -3145,16 +3161,6 @@
options->MinUptimeHidServDirectoryV2 = 0;
}
- /* Parse client-side authorization for hidden services. */
- if (options->ClientSideHidServs) {
- for (cl = options->ClientSideHidServs; cl; cl = cl->next) {
- if (!rend_parse_client_auth(cl->value)) {
- log_warn(LD_CONFIG, "HidServAuth contains illegal value: '%s'. "
- "Discarding.", cl->value);
- }
- }
- }
-
if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds."
" Clipping.", MIN_REND_POST_PERIOD);
@@ -3403,6 +3409,11 @@
if (rend_config_services(options, 1) < 0)
REJECT("Failed to configure rendezvous options. See logs for details.");
+ /* Parse client-side authorization for hidden services. */
+ if (rend_parse_service_authorization(options, 1) < 0)
+ REJECT("Failed to configure client authorization for hidden services. "
+ "See logs for details.");
+
if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0)
return -1;
Modified: tor/branches/121-hs-authorization/src/or/connection.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/connection.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/connection.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -166,7 +166,8 @@
connection_t *
connection_new(int type, int socket_family)
{
- static uint32_t n_connections_allocated = 1;
+ static uint64_t n_connections_allocated = 1;
+
connection_t *conn;
time_t now = time(NULL);
size_t length;
@@ -200,6 +201,7 @@
conn->magic = magic;
conn->s = -1; /* give it a default of 'not used' */
conn->conn_array_index = -1; /* also default to 'not used' */
+ conn->global_identifier = n_connections_allocated++;
conn->type = type;
conn->socket_family = socket_family;
@@ -211,9 +213,6 @@
TO_EDGE_CONN(conn)->socks_request =
tor_malloc_zero(sizeof(socks_request_t));
}
- if (CONN_IS_EDGE(conn)) {
- TO_EDGE_CONN(conn)->global_identifier = n_connections_allocated++;
- }
if (type == CONN_TYPE_OR) {
TO_OR_CONN(conn)->timestamp_last_added_nonpadding = now;
TO_OR_CONN(conn)->next_circ_id = crypto_rand_int(1<<15);
@@ -759,6 +758,21 @@
};
#endif /* HAVE_SYS_UN_H */
+static void
+warn_too_many_conns(void)
+{
+#define WARN_TOO_MANY_CONNS_INTERVAL (6*60*60)
+ time_t last_warned = 0, now = time(NULL);
+ int n_conns = get_n_open_sockets();
+ if (last_warned + WARN_TOO_MANY_CONNS_INTERVAL < now) {
+ log_warn(LD_NET,"Failing because we have %d connections already. Please "
+ "raise your ulimit -n.", n_conns);
+ last_warned = now;
+ }
+ control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d",
+ n_conns);
+}
+
/** Bind a new non-blocking socket listening to the socket described
* by <b>listensockaddr</b>.
*
@@ -776,11 +790,7 @@
int start_reading = 0;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
- int n_conns = get_n_open_sockets();
- log_warn(LD_NET,"Failing because we have %d connections already. Please "
- "raise your ulimit -n.", n_conns);
- control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d",
- n_conns);
+ warn_too_many_conns();
return NULL;
}
@@ -1034,12 +1044,7 @@
return 0;
}
- tor_addr_from_sockaddr(&addr, remote);
- if (remote->sa_family == AF_INET)
- port = ((struct sockaddr_in *)remote)->sin_port;
- else
- port = ((struct sockaddr_in6 *)remote)->sin6_port;
- port = ntohs(port);
+ tor_addr_from_sockaddr(&addr, remote, &port);
/* process entrance policies here, before we even create the connection */
if (new_type == CONN_TYPE_AP) {
@@ -1157,11 +1162,7 @@
int protocol_family;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
- int n_conns = get_n_open_sockets();
- log_warn(LD_NET,"Failing because we have %d connections already. Please "
- "raise your ulimit -n.", n_conns);
- control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d",
- n_conns);
+ warn_too_many_conns();
return -1;
}
@@ -2437,28 +2438,6 @@
}
}
-/** Return the conn to addr/port that has the most recent
- * timestamp_created, or NULL if no such conn exists. */
-or_connection_t *
-connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
-{
- /* XXXX021 IP6 make this take a tor_addr_t, or deprecate it. */
-
- or_connection_t *best=NULL;
- smartlist_t *conns = get_connection_array();
-
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
- if (conn->type == CONN_TYPE_OR &&
- tor_addr_eq_ipv4h(&conn->addr, addr) &&
- conn->port == port &&
- !conn->marked_for_close &&
- (!best || best->_base.timestamp_created < conn->timestamp_created))
- best = TO_OR_CONN(conn);
- });
- return best;
-}
-
/** Return a connection with given type, address, port, and purpose;
* or NULL if no such connection exists. */
connection_t *
@@ -2482,18 +2461,14 @@
/** Return the stream with id <b>id</b> if it is not already marked for
* close.
*/
-edge_connection_t *
-connection_get_by_global_id(uint32_t id)
+connection_t *
+connection_get_by_global_id(uint64_t id)
{
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
- if (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->global_identifier == id) {
- if (!conn->marked_for_close)
- return TO_EDGE_CONN(conn);
- else
- return NULL;
- }
+ if (conn->global_identifier == id)
+ return conn;
});
return NULL;
}
Modified: tor/branches/121-hs-authorization/src/or/connection_edge.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/connection_edge.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/connection_edge.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -14,6 +14,9 @@
#include "or.h"
+#ifdef HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif
#ifdef HAVE_LINUX_NETFILTER_IPV4_H
#include <linux/netfilter_ipv4.h>
#define TRANS_NETFILTER
@@ -1618,7 +1621,7 @@
rep_hist_note_used_internal(now, 0, 1);
/* Look up if we have client authorization for it. */
- client_auth = lookup_client_auth(conn->rend_query);
+ client_auth = rend_client_lookup_service_authorization(conn->rend_query);
if (client_auth) {
log_info(LD_REND, "Using previously configured client authorization "
"for hidden service.");
@@ -1669,11 +1672,11 @@
#ifdef TRANS_PF
static int pf_socket = -1;
-static int
+int
get_pf_socket(void)
{
int pf;
- /* Ideally, this should be opened before dropping privs. */
+ /* This should be opened before dropping privs. */
if (pf_socket >= 0)
return pf_socket;
@@ -1708,9 +1711,9 @@
{
#ifdef TRANS_NETFILTER
/* Linux 2.4+ */
- struct sockaddr_in orig_dst;
+ struct sockaddr_storage orig_dst;
socklen_t orig_dst_len = sizeof(orig_dst);
- char tmpbuf[INET_NTOA_BUF_LEN];
+ tor_addr_t addr;
if (getsockopt(conn->_base.s, SOL_IP, SO_ORIGINAL_DST,
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
@@ -1719,16 +1722,16 @@
return -1;
}
- tor_inet_ntoa(&orig_dst.sin_addr, tmpbuf, sizeof(tmpbuf));
- strlcpy(req->address, tmpbuf, sizeof(req->address));
- req->port = ntohs(orig_dst.sin_port);
+ tor_addr_from_sockaddr(&addr, (struct sockaddr*)&orig_dst, &req->port);
+ tor_addr_to_str(req->address, &addr, sizeof(req->address), 0);
return 0;
#elif defined(TRANS_PF)
- struct sockaddr_in proxy_addr;
+ struct sockaddr_storage proxy_addr;
socklen_t proxy_addr_len = sizeof(proxy_addr);
- char tmpbuf[INET_NTOA_BUF_LEN];
+ struct sockaddr *proxy_sa = (struct sockaddr*) &proxy_addr;
struct pfioc_natlook pnl;
+ tor_addr_t addr;
int pf = -1;
if (getsockname(conn->_base.s, (struct sockaddr*)&proxy_addr,
@@ -1740,13 +1743,28 @@
}
memset(&pnl, 0, sizeof(pnl));
- pnl.af = AF_INET;
pnl.proto = IPPROTO_TCP;
pnl.direction = PF_OUT;
- pnl.saddr.v4.s_addr = htonl(conn->_base.addr);
- pnl.sport = htons(conn->_base.port);
- pnl.daddr.v4.s_addr = proxy_addr.sin_addr.s_addr;
- pnl.dport = proxy_addr.sin_port;
+ if (proxy_sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)proxy_sa;
+ pnl.af = AF_INET;
+ pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&conn->_base.addr);
+ pnl.sport = htons(conn->_base.port);
+ pnl.daddr.v4.s_addr = sin->sin_addr.s_addr;
+ pnl.dport = sin->sin_port;
+ } else if (proxy_sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)proxy_sa;
+ pnl.af = AF_INET6;
+ memcpy(&pnl.saddr.v6, tor_addr_to_in6(&conn->_base.addr),
+ sizeof(struct in6_addr));
+ pnl.sport = htons(conn->_base.port);
+ memcpy(&pnl.daddr.v6, &sin6->sin6_addr, sizeof(struct in6_addr));
+ pnl.dport = sin6->sin6_port;
+ } else {
+ log_warn(LD_NET, "getsockname() gave an unexpected address family (%d)",
+ (int)proxy_sa->sa_family);
+ return -1;
+ }
pf = get_pf_socket();
if (pf<0)
@@ -1757,8 +1775,16 @@
return -1;
}
- tor_inet_ntoa(&pnl.rdaddr.v4, tmpbuf, sizeof(tmpbuf));
- strlcpy(req->address, tmpbuf, sizeof(req->address));
+ if (pnl.af == AF_INET) {
+ tor_addr_from_ipv4n(&addr, pnl.rdaddr.v4.s_addr);
+ } else if (pnl.af == AF_INET6) {
+ tor_addr_from_in6(&addr, &pnl.rdaddr.v6);
+ } else {
+ tor_fragile_assert();
+ return -1;
+ }
+
+ tor_addr_to_str(req->address, &addr, sizeof(req->address), 0);
req->port = ntohs(pnl.rdport);
return 0;
Modified: tor/branches/121-hs-authorization/src/or/connection_or.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/connection_or.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/connection_or.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -837,7 +837,7 @@
int started_here = connection_or_nonopen_was_started_here(conn);
log_debug(LD_OR,"tls handshake with %s done. verifying.",
- conn->_base.address);
+ safe_str(conn->_base.address));
directory_set_dirty();
Modified: tor/branches/121-hs-authorization/src/or/control.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/control.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/control.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -656,16 +656,16 @@
static edge_connection_t *
get_stream(const char *id)
{
- uint32_t n_id;
+ uint64_t n_id;
int ok;
- edge_connection_t *conn;
- n_id = (uint32_t) tor_parse_ulong(id, 10, 0, UINT32_MAX, &ok, NULL);
+ connection_t *conn;
+ n_id = tor_parse_uint64(id, 10, 0, UINT64_MAX, &ok, NULL);
if (!ok)
return NULL;
conn = connection_get_by_global_id(n_id);
- if (!conn || conn->_base.type != CONN_TYPE_AP)
+ if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close)
return NULL;
- return conn;
+ return TO_EDGE_CONN(conn);
}
/** Helper for setconf and resetconf. Acts like setconf, except
@@ -1648,8 +1648,7 @@
smartlist_t *conns = get_connection_array();
smartlist_t *status = smartlist_create();
char buf[256];
- SMARTLIST_FOREACH(conns, connection_t *, base_conn,
- {
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
const char *state;
edge_connection_t *conn;
char *s;
@@ -1691,12 +1690,12 @@
slen = strlen(buf)+strlen(state)+32;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %lu %s",
- (unsigned long) conn->global_identifier,state,
+ (unsigned long) conn->_base.global_identifier,state,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf);
smartlist_add(status, s);
- });
+ } SMARTLIST_FOREACH_END(base_conn);
*answer = smartlist_join_strings(status, "\r\n", 0, NULL);
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
smartlist_free(status);
@@ -3136,8 +3135,8 @@
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control_event_extended(EVENT_STREAM_STATUS, ALL_NAMES,
- "650 STREAM %lu %s %lu %s@%s%s%s\r\n",
- (unsigned long)conn->global_identifier, status,
+ "650 STREAM "U64_FORMAT" %s %lu %s@%s%s%s\r\n",
+ U64_PRINTF_ARG(conn->_base.global_identifier), status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf, reason_buf, addrport_buf, purpose);
@@ -3242,7 +3241,7 @@
smartlist_t *conns = get_connection_array();
edge_connection_t *edge_conn;
- SMARTLIST_FOREACH(conns, connection_t *, conn,
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn)
{
if (conn->type != CONN_TYPE_AP)
continue;
@@ -3251,13 +3250,14 @@
continue;
send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_NAMES,
- "650 STREAM_BW %lu %lu %lu\r\n",
- (unsigned long)edge_conn->global_identifier,
+ "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n",
+ U64_PRINTF_ARG(edge_conn->_base.global_identifier),
(unsigned long)edge_conn->n_read,
(unsigned long)edge_conn->n_written);
edge_conn->n_written = edge_conn->n_read = 0;
- });
+ }
+ SMARTLIST_FOREACH_END(conn);
}
return 0;
Modified: tor/branches/121-hs-authorization/src/or/cpuworker.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/cpuworker.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/cpuworker.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -23,7 +23,7 @@
#define MIN_CPUWORKERS 1
/** The tag specifies which circuit this onionskin was from. */
-#define TAG_LEN 8
+#define TAG_LEN 10
/** How many bytes are sent from the cpuworker back to tor? */
#define LEN_ONION_RESPONSE \
(1+TAG_LEN+ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN)
@@ -60,33 +60,23 @@
return 0;
}
-/** Pack addr,port,and circ_id; set *tag to the result. (See note on
+/** Pack global_id and circ_id; set *tag to the result. (See note on
* cpuworker_main for wire format.) */
static void
-tag_pack(char *tag, const tor_addr_t *addr, uint16_t port, circid_t circ_id)
+tag_pack(char *tag, uint64_t conn_id, circid_t circ_id)
{
/*XXXX RETHINK THIS WHOLE MESS !!!! !NM NM NM NM*/
- *(uint32_t *)tag = tor_addr_to_ipv4h(addr);
- *(uint16_t *)(tag+4) = port;
- *(uint16_t *)(tag+6) = circ_id;
+ *(uint64_t *)tag = conn_id;
+ *(uint16_t *)(tag+8) = circ_id;
}
/** Unpack <b>tag</b> into addr, port, and circ_id.
*/
static void
-tag_unpack(const char *tag, uint32_t *addr, uint16_t *port, circid_t *circ_id)
+tag_unpack(const char *tag, uint64_t *conn_id, circid_t *circ_id)
{
- struct in_addr in;
- char addrbuf[INET_NTOA_BUF_LEN];
-
- *addr = *(const uint32_t *)tag;
- *port = *(const uint16_t *)(tag+4);
- *circ_id = *(const uint16_t *)(tag+6);
-
- in.s_addr = htonl(*addr);
- tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf));
- log_debug(LD_OR,
- "onion was from %s:%d, circ_id %d.", addrbuf, *port, *circ_id);
+ *conn_id = *(const uint64_t *)tag;
+ *circ_id = *(const uint16_t *)(tag+8);
}
/** Called when the onion key has changed and we need to spawn new
@@ -136,10 +126,10 @@
{
char success;
char buf[LEN_ONION_RESPONSE];
- uint32_t addr;
- uint16_t port;
+ uint64_t conn_id;
circid_t circ_id;
- or_connection_t *p_conn;
+ connection_t *tmp_conn;
+ or_connection_t *p_conn = NULL;
circuit_t *circ;
tor_assert(conn);
@@ -157,14 +147,13 @@
connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);
/* parse out the circ it was talking about */
- tag_unpack(buf, &addr, &port, &circ_id);
+ tag_unpack(buf, &conn_id, &circ_id);
circ = NULL;
- /* (Here we use connection_or_exact_get_by_addr_port rather than
- * get_by_identity_digest: we want a specific port here in
- * case there are multiple connections.) */
- /* XXXX021 This is dumb. We don't want just any connection with a matching
- * IP and port: we want the exact one that sent us this CREATE cell. */
- p_conn = connection_or_exact_get_by_addr_port(addr,port);
+ tmp_conn = connection_get_by_global_id(conn_id);
+ if (tmp_conn && !tmp_conn->marked_for_close &&
+ tmp_conn->type == CONN_TYPE_OR)
+ p_conn = TO_OR_CONN(tmp_conn);
+
if (p_conn)
circ = circuit_get_by_circid_orconn(circ_id, p_conn);
@@ -471,7 +460,7 @@
tor_free(onionskin);
return -1;
}
- tag_pack(tag, &circ->p_conn->_base.addr, circ->p_conn->_base.port,
+ tag_pack(tag, circ->p_conn->_base.global_identifier,
circ->p_circ_id);
cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
Modified: tor/branches/121-hs-authorization/src/or/directory.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/directory.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/directory.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -2947,7 +2947,7 @@
}while(0);
if (!strcmp(url,"/tor/mallinfo.txt") &&
- (conn->_base.addr == 0x7f000001ul)) {
+ (tor_addr_eq_ipv4h(&conn->_base.addr, 0x7f000001ul))) {
char *result;
size_t len;
struct mallinfo mi;
Modified: tor/branches/121-hs-authorization/src/or/dirserv.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/dirserv.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/dirserv.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -1861,11 +1861,15 @@
int
routerstatus_format_entry(char *buf, size_t buf_len,
routerstatus_t *rs, const char *version,
- int first_line_only)
+ int first_line_only, int v2_format)
+/* XXX: first_line_only and v2_format should probably be be both
+ * replaced by a single purpose parameter.
+ */
{
int r;
struct in_addr in;
char *cp;
+ char *summary;
char published[ISO_TIME_LEN+1];
char ipaddr[INET_NTOA_BUF_LEN];
@@ -1893,6 +1897,7 @@
}
if (first_line_only)
return 0;
+
cp = buf + strlen(buf);
/* NOTE: Whenever this list expands, be sure to increase MAX_FLAG_LINE_LEN*/
r = tor_snprintf(cp, buf_len - (cp-buf),
@@ -1924,8 +1929,62 @@
log_warn(LD_BUG, "Unable to print router version.");
return -1;
}
+ cp += strlen(cp);
}
+ if (!v2_format) {
+ routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
+
+ /* Blow up more or less nicely if we didn't get anything or not the
+ * thing we expected.
+ */
+ if (!desc) {
+ char id[HEX_DIGEST_LEN+1];
+ char dd[HEX_DIGEST_LEN+1];
+
+ base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN);
+ base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN);
+ log_warn(LD_BUG, "Cannot get the descriptor with digest %s for %s.",
+ id, dd);
+ return -1;
+ };
+ if (memcmp(desc->cache_info.signed_descriptor_digest,
+ rs->descriptor_digest,
+ DIGEST_LEN)) {
+ char rl_d[HEX_DIGEST_LEN+1];
+ char rs_d[HEX_DIGEST_LEN+1];
+
+ base16_encode(rl_d, sizeof(rl_d),
+ desc->cache_info.signed_descriptor_digest, DIGEST_LEN);
+ base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN);
+ log_err(LD_BUG, "descriptor digest in routerlist does not match "
+ "the one in routerstatus: %s vs %s\n",
+ rl_d, rs_d);
+
+ tor_assert(!memcmp(desc->cache_info.signed_descriptor_digest,
+ rs->descriptor_digest,
+ DIGEST_LEN));
+ };
+
+ r = tor_snprintf(cp, buf_len - (cp-buf),
+ "w Bandwidth=%d\n",
+ router_get_advertised_bandwidth_capped(desc) / 1024);
+ if (r<0) {
+ log_warn(LD_BUG, "Not enough space in buffer.");
+ return -1;
+ }
+ cp += strlen(cp);
+
+ summary = policy_summarize(desc->exit_policy);
+ r = tor_snprintf(cp, buf_len - (cp-buf), "p %s\n", summary);
+ if (r<0) {
+ log_warn(LD_BUG, "Not enough space in buffer.");
+ return -1;
+ }
+ cp += strlen(cp);
+ tor_free(summary);
+ }
+
return 0;
}
@@ -2431,7 +2490,7 @@
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(&rs);
- if (routerstatus_format_entry(outp, endp-outp, &rs, version, 0)) {
+ if (routerstatus_format_entry(outp, endp-outp, &rs, version, 0, 1)) {
log_warn(LD_BUG, "Unable to print router status.");
tor_free(version);
goto done;
Modified: tor/branches/121-hs-authorization/src/or/dirvote.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/dirvote.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/dirvote.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -106,7 +106,7 @@
tor_snprintf(status, len,
"network-status-version 3\n"
"vote-status %s\n"
- "consensus-methods 1 2 3 4\n"
+ "consensus-methods 1 2 3 4 5\n"
"published %s\n"
"valid-after %s\n"
"fresh-until %s\n"
@@ -145,7 +145,7 @@
SMARTLIST_FOREACH(v3_ns->routerstatus_list, vote_routerstatus_t *, vrs,
{
if (routerstatus_format_entry(outp, endp-outp, &vrs->status,
- vrs->version, 0) < 0) {
+ vrs->version, 0, 0) < 0) {
log_warn(LD_BUG, "Unable to print router status.");
goto err;
}
@@ -452,7 +452,7 @@
static int
consensus_method_is_supported(int method)
{
- return (method >= 1) && (method <= 4);
+ return (method >= 1) && (method <= 5);
}
/** Given a list of vote networkstatus_t in <b>votes</b>, our public
@@ -688,6 +688,9 @@
smartlist_t *matching_descs = smartlist_create();
smartlist_t *chosen_flags = smartlist_create();
smartlist_t *versions = smartlist_create();
+ smartlist_t *exitsummaries = smartlist_create();
+ uint32_t *bandwidths = tor_malloc(sizeof(uint32_t) * smartlist_len(votes));
+ int num_bandwidths;
int *n_voter_flags; /* n_voter_flags[j] is the number of flags that
* votes[j] knows about. */
@@ -797,6 +800,7 @@
const char *lowest_id = NULL;
const char *chosen_version;
const char *chosen_name = NULL;
+ int exitsummary_disagreement = 0;
int is_named = 0, is_unnamed = 0, is_running = 0;
int naming_conflict = 0;
int n_listing = 0;
@@ -819,6 +823,7 @@
smartlist_clear(matching_descs);
smartlist_clear(chosen_flags);
smartlist_clear(versions);
+ num_bandwidths = 0;
/* Okay, go through all the entries for this digest. */
SMARTLIST_FOREACH(votes, networkstatus_t *, v, {
@@ -850,6 +855,10 @@
}
chosen_name = rs->status.nickname;
}
+
+ /* count bandwidths */
+ if (rs->status.has_bandwidth)
+ bandwidths[num_bandwidths++] = rs->status.bandwidth;
});
/* We don't include this router at all unless more than half of
@@ -922,9 +931,99 @@
chosen_version = NULL;
}
+ /* Pick a bandwidth */
+ if (consensus_method >= 5 && num_bandwidths > 0) {
+ rs_out.has_bandwidth = 1;
+ rs_out.bandwidth = median_uint32(bandwidths, num_bandwidths);
+ }
+
+ /* Ok, we already picked a descriptor digest we want to list
+ * previously. Now we want to use the exit policy summary from
+ * that descriptor. If everybody plays nice all the voters who
+ * listed that descriptor will have the same summary. If not then
+ * something is fishy and we'll use the most common one (breaking
+ * ties in favor of lexigraphically larger one (only because it
+ * lets me reuse more existing code.
+ *
+ * The other case that can happen is that no authority that voted
+ * for that descriptor has an exit policy summary. That's
+ * probably quite unlikely but can happen. In that case we use
+ * the policy that was most often listed in votes, again breaking
+ * ties like in the previous case.
+ */
+ if (consensus_method >= 5) {
+ /* Okay, go through all the votes for this router. We prepared
+ * that list previously */
+ const char *chosen_exitsummary = NULL;
+ smartlist_clear(exitsummaries);
+ SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
+ /* Check if the vote where this status comes from had the
+ * proper descriptor */
+ tor_assert(!memcmp(rs_out.identity_digest,
+ vsr->status.identity_digest,
+ DIGEST_LEN));
+ if (vsr->status.has_exitsummary &&
+ !memcmp(rs_out.descriptor_digest,
+ vsr->status.descriptor_digest,
+ DIGEST_LEN)) {
+ tor_assert(vsr->status.exitsummary);
+ smartlist_add(exitsummaries, vsr->status.exitsummary);
+ if (!chosen_exitsummary) {
+ chosen_exitsummary = vsr->status.exitsummary;
+ } else if (strcmp(chosen_exitsummary, vsr->status.exitsummary)) {
+ /* Great. There's disagreement among the voters. That
+ * really shouldn't be */
+ exitsummary_disagreement = 1;
+ }
+ }
+ });
+
+ if (exitsummary_disagreement) {
+ char id[HEX_DIGEST_LEN+1];
+ char dd[HEX_DIGEST_LEN+1];
+ base16_encode(id, sizeof(dd), rs_out.identity_digest, DIGEST_LEN);
+ base16_encode(dd, sizeof(dd), rs_out.descriptor_digest, DIGEST_LEN);
+ log_warn(LD_DIR, "The voters disgreed on the exit policy summary for"
+ " router %s with descriptor %s. This really shouldn't"
+ " have happened.", id, dd);
+
+ smartlist_sort_strings(exitsummaries);
+ chosen_exitsummary = get_most_frequent_member(exitsummaries);
+ } else if (!chosen_exitsummary) {
+ char id[HEX_DIGEST_LEN+1];
+ char dd[HEX_DIGEST_LEN+1];
+ base16_encode(id, sizeof(dd), rs_out.identity_digest, DIGEST_LEN);
+ base16_encode(dd, sizeof(dd), rs_out.descriptor_digest, DIGEST_LEN);
+ log_warn(LD_DIR, "Not one of the voters that made us select"
+ "descriptor %s for router %s had an exit policy"
+ "summary", dd, id);
+
+ /* Ok, none of those voting for the digest we chose had an
+ * exit policy for us. Well, that kinda sucks.
+ */
+ smartlist_clear(exitsummaries);
+ SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
+ if (vsr->status.has_exitsummary)
+ smartlist_add(exitsummaries, vsr->status.exitsummary);
+ });
+ smartlist_sort_strings(exitsummaries);
+ chosen_exitsummary = get_most_frequent_member(exitsummaries);
+
+ if (!chosen_exitsummary)
+ log_warn(LD_DIR, "Wow, not one of the voters had an exit "
+ "policy summary for %s. Wow.", id);
+ }
+
+ if (chosen_exitsummary) {
+ rs_out.has_exitsummary = 1;
+ /* yea, discards the const */
+ rs_out.exitsummary = (char *)chosen_exitsummary;
+ }
+ }
+
/* Okay!! Now we can write the descriptor... */
/* First line goes into "buf". */
- routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1);
+ routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1, 0);
smartlist_add(chunks, tor_strdup(buf));
/* Second line is all flags. The "\n" is missing. */
smartlist_add(chunks,
@@ -935,6 +1034,25 @@
smartlist_add(chunks, tor_strdup(chosen_version));
}
smartlist_add(chunks, tor_strdup("\n"));
+ /* Now the weight line. */
+ if (rs_out.has_bandwidth) {
+ int r = tor_snprintf(buf, sizeof(buf),
+ "w Bandwidth=%d\n", rs_out.bandwidth);
+ if (r<0) {
+ log_warn(LD_BUG, "Not enough space in buffer for weight line.");
+ *buf = '\0';
+ }
+ smartlist_add(chunks, tor_strdup(buf));
+ };
+ /* Now the exitpolicy summary line. */
+ if (rs_out.has_exitsummary) {
+ int r = tor_snprintf(buf, sizeof(buf), "p %s\n", rs_out.exitsummary);
+ if (r<0) {
+ log_warn(LD_BUG, "Not enough space in buffer for exitpolicy line.");
+ *buf = '\0';
+ }
+ smartlist_add(chunks, tor_strdup(buf));
+ };
/* And the loop is over and we move on to the next router */
}
@@ -953,6 +1071,7 @@
smartlist_free(matching_descs);
smartlist_free(chosen_flags);
smartlist_free(versions);
+ smartlist_free(exitsummaries);
}
/* Add a signature. */
Modified: tor/branches/121-hs-authorization/src/or/dnsserv.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/dnsserv.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/dnsserv.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -46,7 +46,7 @@
}
(void) addrlen;
sa = (struct sockaddr*) &addr;
- if (tor_addr_from_sockaddr(&tor_addr, sa)<0) {
+ if (tor_addr_from_sockaddr(&tor_addr, sa, &port)<0) {
log_warn(LD_APP, "Requesting address wasn't recognized.");
evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
return;
@@ -58,12 +58,6 @@
return;
}
- if (sa->sa_family == AF_INET)
- port = ((struct sockaddr_in *)sa)->sin_port;
- else
- port = ((struct sockaddr_in6 *)sa)->sin6_port;
- port = ntohs(port);
-
/* Now, let's find the first actual question of a type we can answer in this
* DNS request. It makes us a little noncompliant to act like this; we
* should fix that eventually if it turns out to make a difference for
Modified: tor/branches/121-hs-authorization/src/or/main.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/main.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/main.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -1873,6 +1873,7 @@
dirserv_free_all();
rend_service_free_all();
rend_cache_free_all();
+ rend_service_authorization_free_all();
rep_hist_free_all();
hs_usage_free_all();
dns_free_all();
Modified: tor/branches/121-hs-authorization/src/or/networkstatus.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/networkstatus.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/networkstatus.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -1779,7 +1779,7 @@
networkstatus_getinfo_helper_single(routerstatus_t *rs)
{
char buf[RS_ENTRY_LEN+1];
- routerstatus_format_entry(buf, sizeof(buf), rs, NULL, 0);
+ routerstatus_format_entry(buf, sizeof(buf), rs, NULL, 0, 0);
return tor_strdup(buf);
}
Modified: tor/branches/121-hs-authorization/src/or/or.h
===================================================================
--- tor/branches/121-hs-authorization/src/or/or.h 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/or.h 2008-08-16 11:36:09 UTC (rev 16566)
@@ -612,6 +612,9 @@
/** Length of 'y' portion of 'y.onion' URL. */
#define REND_SERVICE_ID_LEN_BASE32 16
+/** Length of 'y.onion' including '.onion' URL. */
+#define REND_SERVICE_ADDRESS_LEN (16+1+5)
+
/** Length of a binary-encoded rendezvous service ID. */
#define REND_SERVICE_ID_LEN 10
@@ -656,6 +659,9 @@
#define REND_LEGAL_CLIENTNAME_CHARACTERS \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-_"
+/** Maximum length of authorized client names for a hidden service. */
+#define REND_CLIENTNAME_MAX_LEN 16
+
#define CELL_DIRECTION_IN 1
#define CELL_DIRECTION_OUT 2
@@ -901,6 +907,9 @@
/** Another connection that's connected to this one in lieu of a socket. */
struct connection_t *linked_conn;
+ /** Unique identifier for this connection. */
+ uint64_t global_identifier;
+
/* XXXX021 move this into a subtype. */
struct evdns_server_port *dns_server_port;
@@ -1011,10 +1020,6 @@
/** The reason why this connection is closing; passed to the controller. */
uint16_t end_reason;
- /** Quasi-global identifier for this connection; used for control.c */
- /* XXXX NM This can get re-used after 2**32 streams */
- uint32_t global_identifier;
-
/** Bytes read since last call to control_event_stream_bandwidth_used() */
uint32_t n_read;
@@ -1413,7 +1418,7 @@
* an exit node. */
unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
* underpowered, or otherwise useless? */
- unsigned int is_hs_dir:1; /** True iff this router is a v2-or-later hidden
+ unsigned int is_hs_dir:1; /**< True iff this router is a v2-or-later hidden
* service directory. */
/** True iff we know version info for this router. (i.e., a "v" entry was
* included.) We'll replace all these with a big tor_version_t or a char[]
@@ -1430,6 +1435,14 @@
* we can get v3 downloads from. */
unsigned int version_supports_v3_dir:1;
+ unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
+ unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
+
+ uint32_t bandwidth; /**< Bandwidth (capacity) of the router as reported in
+ * the vote/consensus, in kilobytes/sec. */
+ char *exitsummary; /**< exit policy summary -
+ * XXX weasel: this probably should not stay a string. */
+
/* ---- The fields below aren't derived from the networkstatus; they
* hold local information only. */
@@ -2266,8 +2279,8 @@
* other ORs are running. */
config_line_t *RendConfigLines; /**< List of configuration lines
* for rendezvous services. */
- config_line_t *ClientSideHidServs; /** List of configuration lines for
- * client-side authorizations for hidden services */
+ config_line_t *HidServAuth; /**< List of configuration lines for client-side
+ * authorizations for hidden services */
char *ContactInfo; /**< Contact info to be published in the directory. */
char *HttpProxy; /**< hostname[:port] to use as http proxy, if any. */
@@ -2874,9 +2887,7 @@
_connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1);
}
-or_connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
- uint16_t port);
-edge_connection_t *connection_get_by_global_id(uint32_t id);
+connection_t *connection_get_by_global_id(uint64_t id);
connection_t *connection_get_by_type(int type);
connection_t *connection_get_by_type_purpose(int type, int purpose);
@@ -2982,6 +2993,10 @@
} hostname_type_t;
hostname_type_t parse_extended_hostname(char *address);
+#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
+int get_pf_socket(void);
+#endif
+
/********************************* connection_or.c ***************************/
void connection_or_remove_from_identity_map(or_connection_t *conn);
@@ -3228,11 +3243,19 @@
}
/********************************* dirserv.c ***************************/
+/** Maximum length of an exit policy summary. */
+#define MAX_EXITPOLICY_SUMMARY_LEN (1000)
+
/** Maximum allowable length of a version line in a networkstatus. */
#define MAX_V_LINE_LEN 128
/** Length of "r Authority BadDirectory BadExit Exit Fast Guard HSDir Named
* Running Stable Unnamed V2Dir Valid\n". */
#define MAX_FLAG_LINE_LEN 96
+/** Length of "w" line for weighting. Currently at most
+ * "w Bandwidth=<uint32t>\n" */
+#define MAX_WEIGHT_LINE_LEN (13+10)
+/** Maximum length of an exit policy summary line. */
+#define MAX_POLICY_LINE_LEN (3+MAX_EXITPOLICY_SUMMARY_LEN)
/** Amount of space to allocate for each entry: r, s, and v lines. */
#define RS_ENTRY_LEN \
( /* first line */ \
@@ -3240,6 +3263,10 @@
5*2 /* ports */ + 10 /* punctuation */ + \
/* second line */ \
MAX_FLAG_LINE_LEN + \
+ /* weight line */ \
+ MAX_WEIGHT_LINE_LEN + \
+ /* p line. */ \
+ MAX_POLICY_LINE_LEN + \
/* v line. */ \
MAX_V_LINE_LEN \
)
@@ -3309,7 +3336,7 @@
int compressed);
int routerstatus_format_entry(char *buf, size_t buf_len,
routerstatus_t *rs, const char *platform,
- int first_line_only);
+ int first_line_only, int v2_format);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
cached_dir_t *new_cached_dir(char *s, time_t published);
@@ -3686,6 +3713,8 @@
void addr_policy_free(addr_policy_t *p);
void policies_free_all(void);
+char *policy_summarize(smartlist_t *policy);
+
/********************************* reasons.c ***************************/
const char *stream_end_reason_to_control_string(int reason);
@@ -3832,25 +3861,36 @@
int rend_client_send_introduction(origin_circuit_t *introcirc,
origin_circuit_t *rendcirc);
-int rend_parse_client_auth(char *config_line);
+/** Client authorization type that a hidden service performs. */
+typedef enum rend_auth_type_t {
+ REND_NO_AUTH = 0,
+ REND_BASIC_AUTH = 1,
+ REND_STEALTH_AUTH = 2,
+} rend_auth_type_t;
+
+/** Client-side configuration of authorization for a hidden service. */
+typedef struct rend_service_authorization_t {
+ char descriptor_cookie[REND_DESC_COOKIE_LEN];
+ char onion_address[REND_SERVICE_ADDRESS_LEN+1];
+ rend_auth_type_t auth_type;
+} rend_service_authorization_t;
+
+int rend_parse_service_authorization(or_options_t *options,
+ int validate_only);
+rend_service_authorization_t *rend_client_lookup_service_authorization(
+ const char *onion_address);
+void rend_service_authorization_free_all(void);
+
/********************************* rendcommon.c ***************************/
-/** Hidden-service-side configuration of client authorization. */
+/** Hidden-service side configuration of client authorization. */
typedef struct rend_authorized_client_t {
char *client_name;
char descriptor_cookie[REND_DESC_COOKIE_LEN];
crypto_pk_env_t *client_key;
} rend_authorized_client_t;
-/** Client-side configuration of authorization for a hidden service. */
-typedef struct rend_service_authorization_t {
- char *service_name;
- char descriptor_cookie[REND_DESC_COOKIE_LEN];
- char onion_address[REND_SERVICE_ID_LEN_BASE32+1+5+1];
- int auth_type;
-} rend_service_authorization_t;
-
/** ASCII-encoded v2 hidden service descriptor. */
typedef struct rend_encoded_v2_service_descriptor_t {
char desc_id[DIGEST_LEN]; /**< Descriptor ID. */
@@ -3928,7 +3968,6 @@
void rend_get_descriptor_id_bytes(char *descriptor_id_out,
const char *service_id,
const char *secret_id_part);
-rend_service_authorization_t *lookup_client_auth(char *onion_address);
/********************************* rendservice.c ***************************/
@@ -4120,6 +4159,7 @@
int router_is_unreliable(routerinfo_t *router, int need_uptime,
int need_capacity, int need_guard);
uint32_t router_get_advertised_bandwidth(routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router);
typedef enum {
NO_WEIGHTING, WEIGHT_FOR_EXIT, WEIGHT_FOR_GUARD
Modified: tor/branches/121-hs-authorization/src/or/policies.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/policies.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/policies.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -38,16 +38,32 @@
* to directories at. */
static smartlist_t *reachable_dir_addr_policy = NULL;
+/** Element of an exit policy summary */
+typedef struct policy_summary_item_t {
+ uint16_t prt_min; /**< Lowest port number to accept/reject. */
+ uint16_t prt_max; /**< Highest port number to accept/reject. */
+ uint64_t reject_count; /**< Number of IP-Addresses that are rejected to
+ this portrange. */
+ int accepted:1; /** Has this port already been accepted */
+} policy_summary_item_t;
+
+/** Private networks. This list is used in two places, once to expand the
+ * "private" keyword when parsing our own exit policy, secondly to ignore
+ * just such networks when building exit policy summaries. It is important
+ * that all authorities agree on that list when creating summaries, so don't
+ * just change this without a proper migration plan and a proposal and stuff.
+ */
+static const char *private_nets[] = {
+ "0.0.0.0/8", "169.254.0.0/16",
+ "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12",
+ // "fc00::/7", "fe80::/10", "fec0::/10", "::/127",
+ NULL };
+
/** Replace all "private" entries in *<b>policy</b> with their expanded
* equivalents. */
void
policy_expand_private(smartlist_t **policy)
{
- static const char *private_nets[] = {
- "0.0.0.0/8", "169.254.0.0/16",
- "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12",
- // "fc00::/7", "fe80::/10", "fec0::/10", "::/127",
- NULL };
uint16_t port_min, port_max;
int i;
@@ -904,6 +920,280 @@
return (int)written;
}
+/** Create a new exit policy summary, initially only with a single
+ * port 1-64k item */
+/* XXXX This entire thing will do most stuff in O(N^2), or worse. Use an
+ * RB-tree if that turns out to matter. */
+static smartlist_t *
+policy_summary_create(void)
+{
+ smartlist_t *summary;
+ policy_summary_item_t* item;
+
+ item = tor_malloc_zero(sizeof(policy_summary_item_t));
+ item->prt_min = 1;
+ item->prt_max = 65535;
+ item->reject_count = 0;
+ item->accepted = 0;
+
+ summary = smartlist_create();
+ smartlist_add(summary, item);
+
+ return summary;
+}
+
+/** Split the summary item in <b>item</b> at the port <b>new_starts</b>.
+ * The current item is changed to end at new-starts - 1, the new item
+ * copies reject_count and accepted from the old item,
+ * starts at new_starts and ends at the port where the original item
+ * previously ended.
+ */
+static policy_summary_item_t*
+policy_summary_item_split(policy_summary_item_t* old, uint16_t new_starts)
+{
+ policy_summary_item_t* new;
+
+ new = tor_malloc_zero(sizeof(policy_summary_item_t));
+ new->prt_min = new_starts;
+ new->prt_max = old->prt_max;
+ new->reject_count = old->reject_count;
+ new->accepted = old->accepted;
+
+ old->prt_max = new_starts-1;
+
+ tor_assert(old->prt_min <= old->prt_max);
+ tor_assert(new->prt_min <= new->prt_max);
+ return new;
+}
+
+/* XXXX Nick says I'm going to hell for this. If he feels charitably towards
+ * my immortal soul, he can clean it up himself. */
+#define AT(x) ((policy_summary_item_t*)smartlist_get(summary, x))
+
+#define REJECT_CUTOFF_COUNT (1<<25)
+/* Split an exit policy summary so that prt_min and prt_max
+ * fall at exactly the start and end of an item respectively.
+ */
+static int
+policy_summary_split(smartlist_t *summary,
+ uint16_t prt_min, uint16_t prt_max)
+{
+ int start_at_index;
+
+ int i = 0;
+ /* XXXX Do a binary search if run time matters */
+ while (AT(i)->prt_max < prt_min)
+ i++;
+ if (AT(i)->prt_min != prt_min) {
+ policy_summary_item_t* new_item;
+ new_item = policy_summary_item_split(AT(i), prt_min);
+ smartlist_insert(summary, i+1, new_item);
+ i++;
+ }
+ start_at_index = i;
+
+ while (AT(i)->prt_max < prt_max)
+ i++;
+ if (AT(i)->prt_max != prt_max) {
+ policy_summary_item_t* new_item;
+ new_item = policy_summary_item_split(AT(i), prt_max+1);
+ smartlist_insert(summary, i+1, new_item);
+ }
+
+ return start_at_index;
+}
+
+/** Mark port ranges as accepted if they are below the reject_count */
+static void
+policy_summary_accept(smartlist_t *summary,
+ uint16_t prt_min, uint16_t prt_max)
+{
+ int i = policy_summary_split(summary, prt_min, prt_max);
+ while (i < smartlist_len(summary) &&
+ AT(i)->prt_max <= prt_max) {
+ if (!AT(i)->accepted &&
+ AT(i)->reject_count <= REJECT_CUTOFF_COUNT)
+ AT(i)->accepted = 1;
+ i++;
+ }
+ tor_assert(i < smartlist_len(summary) || prt_max==65535);
+}
+
+/** Count the number of addresses in a network with prefixlen maskbits
+ * against the given portrange. */
+static void
+policy_summary_reject(smartlist_t *summary,
+ maskbits_t maskbits,
+ uint16_t prt_min, uint16_t prt_max)
+{
+ int i = policy_summary_split(summary, prt_min, prt_max);
+ /* XXX: ipv4 specific */
+ uint64_t count = (U64_LITERAL(1) << (32-maskbits));
+ while (i < smartlist_len(summary) &&
+ AT(i)->prt_max <= prt_max) {
+ AT(i)->reject_count += count;
+ i++;
+ }
+ tor_assert(i < smartlist_len(summary) || prt_max==65535);
+}
+
+/** Add a single exit policy item to our summary:
+ * If it is an accept ignore it unless it is for all IP addresses
+ * ("*"), i.e. it's prefixlen/maskbits is 0, else call
+ * policy_summary_accept().
+ * If it's a reject ignore it if it is about one of the private
+ * networks, else call policy_summary_reject().
+ */
+static void
+policy_summary_add_item(smartlist_t *summary, addr_policy_t *p)
+{
+ if (p->policy_type == ADDR_POLICY_ACCEPT) {
+ if (p->maskbits == 0) {
+ policy_summary_accept(summary, p->prt_min, p->prt_max);
+ }
+ } else if (p->policy_type == ADDR_POLICY_REJECT) {
+
+ int is_private = 0;
+ int i;
+ for (i = 0; private_nets[i]; ++i) {
+ tor_addr_t addr;
+ maskbits_t maskbits;
+ if (tor_addr_parse_mask_ports(private_nets[i], &addr,
+ &maskbits, NULL, NULL)<0) {
+ tor_assert(0);
+ }
+ if (tor_addr_compare(&p->addr, &addr, CMP_EXACT) == 0 &&
+ p->maskbits == maskbits) {
+ is_private = 1;
+ break;
+ }
+ }
+
+ if (!is_private) {
+ policy_summary_reject(summary, p->maskbits, p->prt_min, p->prt_max);
+ }
+ } else
+ tor_assert(0);
+}
+
+/** Create a string representing a summary for an exit policy.
+ * The summary will either be an "accept" plus a comma-seperated list of port
+ * ranges or a "reject" plus portranges, depending on which is shorter.
+ *
+ * If no exits are allowed at all then NULL is returned, if no ports
+ * are blocked instead of "reject " we return "accept 1-65535" (this
+ * is an exception to the shorter-representation-wins rule).
+ */
+char *
+policy_summarize(smartlist_t *policy)
+{
+ smartlist_t *summary = policy_summary_create();
+ smartlist_t *accepts, *rejects;
+ int i, last, start_prt;
+ size_t accepts_len, rejects_len, shorter_len, final_size;
+ char *accepts_str = NULL, *rejects_str = NULL, *shorter_str, *result;
+ const char *prefix;
+
+ tor_assert(policy);
+
+ /* Create the summary list */
+ SMARTLIST_FOREACH(policy, addr_policy_t *, p, {
+ policy_summary_add_item(summary, p);
+ });
+
+ /* Now create two lists of strings, one for accepted and one
+ * for rejected ports. We take care to merge ranges so that
+ * we avoid getting stuff like "1-4,5-9,10", instead we want
+ * "1-10"
+ */
+ i = 0;
+ start_prt = 1;
+ accepts = smartlist_create();
+ rejects = smartlist_create();
+ while (1) {
+ last = i == smartlist_len(summary)-1;
+ if (last ||
+ AT(i)->accepted != AT(i+1)->accepted) {
+ char buf[POLICY_BUF_LEN];
+
+ if (start_prt == AT(i)->prt_max)
+ tor_snprintf(buf, sizeof(buf), "%d", start_prt);
+ else
+ tor_snprintf(buf, sizeof(buf), "%d-%d", start_prt, AT(i)->prt_max);
+
+ if (AT(i)->accepted)
+ smartlist_add(accepts, tor_strdup(buf));
+ else
+ smartlist_add(rejects, tor_strdup(buf));
+
+ if (last)
+ break;
+
+ start_prt = AT(i+1)->prt_min;
+ };
+ i++;
+ };
+
+ /* Figure out which of the two stringlists will be shorter and use
+ * that to build the result
+ */
+ if (smartlist_len(accepts) == 0) { /* no exits at all */
+ result = tor_strdup("reject 1-65535");
+ goto cleanup;
+ }
+ if (smartlist_len(rejects) == 0) { /* no rejects at all */
+ result = tor_strdup("accept 1-65535");
+ goto cleanup;
+ }
+
+ accepts_str = smartlist_join_strings(accepts, ",", 0, &accepts_len);
+ rejects_str = smartlist_join_strings(rejects, ",", 0, &rejects_len);
+
+ if (rejects_len > MAX_EXITPOLICY_SUMMARY_LEN &&
+ accepts_len > MAX_EXITPOLICY_SUMMARY_LEN) {
+ char *c;
+ shorter_str = accepts_str;
+ prefix = "accept";
+
+ c = shorter_str + (MAX_EXITPOLICY_SUMMARY_LEN-strlen(prefix)-1);
+ while (*c != ',' && c >= shorter_str)
+ c--;
+ tor_assert(c >= shorter_str);
+ tor_assert(*c == ',');
+ *c = '\0';
+
+ shorter_len = strlen(shorter_str);
+ } else if (rejects_len < accepts_len) {
+ shorter_str = rejects_str;
+ shorter_len = rejects_len;
+ prefix = "reject";
+ } else {
+ shorter_str = accepts_str;
+ shorter_len = accepts_len;
+ prefix = "accept";
+ }
+
+ final_size = strlen(prefix)+1+shorter_len+1;
+ tor_assert(final_size <= MAX_EXITPOLICY_SUMMARY_LEN+1);
+ result = malloc(final_size);
+ tor_snprintf(result, final_size, "%s %s", prefix, shorter_str);
+
+cleanup:
+ /* cleanup */
+ SMARTLIST_FOREACH(summary, policy_summary_item_t *, s, tor_free(s));
+ smartlist_clear(summary);
+
+ tor_free(accepts_str);
+ SMARTLIST_FOREACH(accepts, char *, s, tor_free(s));
+ smartlist_clear(accepts);
+
+ tor_free(rejects_str);
+ SMARTLIST_FOREACH(rejects, char *, s, tor_free(s));
+ smartlist_clear(rejects);
+
+ return result;
+}
+
/** Implementation for GETINFO control command: knows the answer for questions
* about "exit-policy/..." */
int
Modified: tor/branches/121-hs-authorization/src/or/rendclient.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/rendclient.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/rendclient.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -20,7 +20,7 @@
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
tor_assert(circ->cpath);
- log_info(LD_REND, "introcirc is open");
+ log_info(LD_REND,"introcirc is open");
connection_ap_attach_pending();
}
@@ -773,7 +773,7 @@
* <b>onion_address</b>. Return NULL if no authorization is available for
* that address. */
rend_service_authorization_t*
-lookup_client_auth(char *onion_address)
+rend_client_lookup_service_authorization(const char *onion_address)
{
tor_assert(onion_address);
if (!auth_hid_servs) return NULL;
@@ -784,104 +784,117 @@
static void
rend_service_authorization_free(rend_service_authorization_t *auth)
{
- if (!auth) return;
- tor_free(auth->service_name);
tor_free(auth);
}
+/** Helper for strmap_free. */
+static void
+rend_service_authorization_strmap_item_free(void *service_auth)
+{
+ rend_service_authorization_free(service_auth);
+}
+
+/** Release all the storage held in auth_hid_servs.
+ */
+void
+rend_service_authorization_free_all(void)
+{
+ if (!auth_hid_servs) {
+ return;
+ }
+ strmap_free(auth_hid_servs, rend_service_authorization_strmap_item_free);
+ auth_hid_servs = NULL;
+}
+
/** Parse <b>config_line</b> as a client-side authorization for a hidden
* service and add it to the local map of hidden service authorizations.
- * Return 1 for success and 0 for failure. */
+ * Return 0 for success and -1 for failure. */
int
-rend_parse_client_auth(char *config_line)
+rend_parse_service_authorization(or_options_t *options, int validate_only)
{
- char *service_name, *onion_address, *descriptor_cookie;
- char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
- char descriptor_cookie_base64ext[REND_DESC_COOKIE_LEN_BASE64+2+1];
+ config_line_t *line;
+ int res = -1;
+ strmap_t *parsed = strmap_new();
smartlist_t *sl = smartlist_create();
- rend_service_authorization_t *auth = NULL;
- int res = 0, auth_type = 0;
- size_t len;
- tor_assert(config_line);
- smartlist_split_string(sl, config_line, " ",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- if (smartlist_len(sl) != 3) {
- log_warn(LD_CONFIG, "Configuration line does not consist of "
- "\"service-name client-key descriptor-cookie\": '%s'",
- config_line);
- goto free;
+
+ for (line = options->HidServAuth; line; line = line->next) {
+ char *onion_address, *descriptor_cookie;
+ char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
+ char descriptor_cookie_base64ext[REND_DESC_COOKIE_LEN_BASE64+2+1];
+ rend_service_authorization_t *auth = NULL;
+ int auth_type_val = 0;
+ SMARTLIST_FOREACH(sl, char *, c, tor_free(c););
+ smartlist_clear(sl);
+ smartlist_split_string(sl, line->value, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
+ if (smartlist_len(sl) < 2) {
+ log_warn(LD_CONFIG, "Configuration line does not consist of "
+ "\"onion-address authorization-cookie [service-name]\": "
+ "'%s'", line->value);
+ goto err;
+ }
+ auth = tor_malloc_zero(sizeof(rend_service_authorization_t));
+ /* Parse onion address. */
+ onion_address = smartlist_get(sl, 0);
+ if (strlen(onion_address) != REND_SERVICE_ADDRESS_LEN ||
+ strcmpend(onion_address, ".onion")) {
+ log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
+ onion_address);
+ goto err;
+ }
+ strlcpy(auth->onion_address, onion_address, REND_SERVICE_ID_LEN_BASE32+1);
+ if (!rend_valid_service_id(auth->onion_address)) {
+ log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
+ onion_address);
+ goto err;
+ }
+ /* Parse descriptor cookie. */
+ descriptor_cookie = smartlist_get(sl, 1);
+ if (strlen(descriptor_cookie) != REND_DESC_COOKIE_LEN_BASE64) {
+ log_warn(LD_CONFIG, "Authorization cookie has wrong length: '%s'",
+ descriptor_cookie);
+ goto err;
+ }
+ /* Add trailing zero bytes (AA) to make base64-decoding happy. */
+ tor_snprintf(descriptor_cookie_base64ext,
+ REND_DESC_COOKIE_LEN_BASE64+2+1,
+ "%sAA", descriptor_cookie);
+ if (base64_decode(descriptor_cookie_tmp, sizeof(descriptor_cookie_tmp),
+ descriptor_cookie_base64ext,
+ strlen(descriptor_cookie_base64ext)) < 0) {
+ log_warn(LD_CONFIG, "Decoding authorization cookie failed: '%s'",
+ descriptor_cookie);
+ goto err;
+ }
+ auth_type_val = (descriptor_cookie_tmp[16] >> 4) + 1;
+ if (auth_type_val < 1 || auth_type_val > 2) {
+ log_warn(LD_CONFIG, "Authorization cookie has unknown authorization "
+ "type encoded.");
+ goto err;
+ }
+ auth->auth_type = auth_type_val == 1 ? REND_BASIC_AUTH : REND_STEALTH_AUTH;
+ memcpy(auth->descriptor_cookie, descriptor_cookie_tmp,
+ REND_DESC_COOKIE_LEN);
+ if (strmap_get(parsed, auth->onion_address)) {
+ log_warn(LD_CONFIG, "Duplicate authorization for the same hidden "
+ "service.");
+ goto err;
+ }
+ strmap_set(parsed, auth->onion_address, auth);
}
- /* Parse service name (rather meant for use in a GUI controller). */
- service_name = smartlist_get(sl, 0);
- auth = tor_malloc_zero(sizeof(rend_service_authorization_t));
- auth->service_name = strdup(smartlist_get(sl, 0));
- len = strlen(auth->service_name);
- if (len < 1 || len > 19 ||
- strspn(auth->service_name, REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
- log_warn(LD_CONFIG, "HidServAuth contains an illegal service name: "
- "'%s'. (Length must be between 1 and 19, and "
- "valid characters are [A-Za-z0-9+-_].)",
- auth->service_name);
- goto free;
+ res = 0;
+ goto done;
+ err:
+ res = -1;
+ done:
+ SMARTLIST_FOREACH(sl, char *, c, tor_free(c););
+ smartlist_free(sl);
+ if (!validate_only && res == 0) {
+ rend_service_authorization_free_all();
+ auth_hid_servs = parsed;
+ } else {
+ strmap_free(parsed, rend_service_authorization_strmap_item_free);
}
- if (auth_hid_servs && strmap_get(auth_hid_servs, auth->service_name)) {
- log_warn(LD_CONFIG, "Duplicate service name for configuration line: "
- "'%s'", auth->service_name);
- goto free;
- }
- /* Parse onion address. */
- onion_address = smartlist_get(sl, 1);
- if (strlen(onion_address) != 16+1+5 ||
- strstr(onion_address, ".onion") != onion_address + 16) {
- log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
- onion_address);
- goto free;
- }
- strlcpy(auth->onion_address, onion_address, 16+1);
- if (!rend_valid_service_id(auth->onion_address)) {
- log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
- onion_address);
- goto free;
- }
- /* Parse descriptor cookie. */
- descriptor_cookie = smartlist_get(sl, 2);
- if (strlen(descriptor_cookie) != 22) {
- log_warn(LD_CONFIG, "Descriptor cookie has wrong length: '%s'",
- descriptor_cookie);
- goto free;
- }
- /* Add trailing zero bytes (AA) to make base64-decoding happy. */
- tor_snprintf(descriptor_cookie_base64ext,
- REND_DESC_COOKIE_LEN_BASE64+2+1,
- "%sAA", descriptor_cookie);
- if (base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
- descriptor_cookie_base64ext,
- strlen(descriptor_cookie_base64ext)) < 0) {
- log_warn(LD_CONFIG, "Decoding descriptor cookie failed: '%s'",
- descriptor_cookie);
- goto free;
- }
- auth_type = (descriptor_cookie_tmp[16] >> 4) + 1;
- if (auth_type < 1 || auth_type > 2) {
- log_warn(LD_CONFIG, "Descriptor cookie has unknown authorization type "
- "encoded.");
- goto free;
- }
- auth->auth_type = auth_type;
- memcpy(auth->descriptor_cookie, descriptor_cookie_tmp,
- REND_DESC_COOKIE_LEN);
- /* Add parsed client authorization to local map. */
- if (!auth_hid_servs)
- auth_hid_servs = strmap_new();
- strmap_set(auth_hid_servs, auth->onion_address, auth);
- auth = NULL;
- res = 1;
- free:
- if (sl)
- SMARTLIST_FOREACH(sl, char *, c, tor_free(c););
- smartlist_free(sl);
- if (auth)
- rend_service_authorization_free(auth);
return res;
}
Modified: tor/branches/121-hs-authorization/src/or/rendservice.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/rendservice.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/rendservice.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -45,6 +45,13 @@
/* Fields specified in config file */
char *directory; /**< where in the filesystem it stores it */
smartlist_t *ports; /**< List of rend_service_port_config_t */
+ int descriptor_version; /**< Rendezvous descriptor version that will be
+ * published. */
+ rend_auth_type_t auth_type; /**< Client authorization type or 0 if no client
+ * authorization is performed. */
+ smartlist_t *clients; /**< List of rend_authorized_client_t's of
+ * clients that may access our service. Can be NULL
+ * if no client authorization is peformed. */
/* Other fields */
crypto_pk_env_t *private_key; /**< Permanent hidden-service key. */
char service_id[REND_SERVICE_ID_LEN_BASE32+1]; /**< Onion address without
@@ -62,12 +69,6 @@
* up-to-date. */
time_t next_upload_time; /**< Scheduled next hidden service descriptor
* upload time. */
- int descriptor_version; /**< Rendezvous descriptor version that will be
- * published. */
- int auth_type; /**< Client authorization type or 0 if no client
- * authorization is performed. */
- smartlist_t *clients; /**< List of rend_authorized_client_t's for
- * clients that may access our service. */
smartlist_t *accepted_intros; /**< List of client_access_event_t's for
* accepted and answered INTRODUCE2 cells. */
} rend_service_t;
@@ -93,16 +94,22 @@
/** Helper: free storage held by a single service authorized client entry. */
static void
-rend_authorized_client_free(void *authorized_client)
+rend_authorized_client_free(rend_authorized_client_t *client)
{
- rend_authorized_client_t *client = authorized_client;
- if (!authorized_client) return;
+ if (!client) return;
if (client->client_key)
crypto_free_pk_env(client->client_key);
tor_free(client->client_name);
tor_free(client);
}
+/** Helper for strmap_free. */
+static void
+rend_authorized_client_strmap_item_free(void *authorized_client)
+{
+ rend_authorized_client_free(authorized_client);
+}
+
/** Release the storage held by <b>service</b>.
*/
static void
@@ -155,10 +162,9 @@
/* If the service is configured to publish unversioned (v0) and versioned
* descriptors (v2 or higher), split it up into two separate services
- * (unless it is configured to perform client authorization in which case
- * ). */
+ * (unless it is configured to perform client authorization). */
if (service->descriptor_version == -1) {
- if (!service->auth_type) {
+ if (service->auth_type == REND_NO_AUTH) {
rend_service_t *v0_service = tor_malloc_zero(sizeof(rend_service_t));
v0_service->directory = tor_strdup(service->directory);
v0_service->ports = smartlist_create();
@@ -170,23 +176,24 @@
});
v0_service->intro_period_started = service->intro_period_started;
v0_service->descriptor_version = 0; /* Unversioned descriptor. */
- v0_service->auth_type = 0;
+ v0_service->auth_type = REND_NO_AUTH;
rend_add_service(v0_service);
}
service->descriptor_version = 2; /* Versioned descriptor. */
}
- if (service->auth_type && !service->descriptor_version) {
+ if (service->auth_type != REND_NO_AUTH && !service->descriptor_version) {
log_warn(LD_CONFIG, "Hidden service with client authorization and "
"version 0 descriptors configured; ignoring.");
rend_service_free(service);
return;
}
- if (service->auth_type && smartlist_len(service->clients) == 0) {
+ if (service->auth_type != REND_NO_AUTH &&
+ smartlist_len(service->clients) == 0) {
log_warn(LD_CONFIG, "Hidden service with client authorization but no "
- "clients; ignoring.");
+ "clients; ignoring.");
rend_service_free(service);
return;
}
@@ -320,19 +327,20 @@
}
smartlist_add(service->ports, portcfg);
} else if (!strcasecmp(line->key, "HiddenServiceAuthorizeClient")) {
- /* Parse comma-separated list of client names and add a
+ /* Parse auth type and comma-separated list of client names and add a
* rend_authorized_client_t for each client to the service's list
* of authorized clients. */
smartlist_t *type_names_split, *clients;
- if (service->auth_type) {
+ const char *authname;
+ int num_clients;
+ if (service->auth_type != REND_NO_AUTH) {
log_warn(LD_CONFIG, "Got multiple HiddenServiceAuthorizeClient "
"lines for a single service.");
rend_service_free(service);
return -1;
}
- service->clients = smartlist_create();
type_names_split = smartlist_create();
- smartlist_split_string(type_names_split, line->value, " ", 0, 0);
+ smartlist_split_string(type_names_split, line->value, " ", 0, 2);
if (smartlist_len(type_names_split) < 1) {
log_warn(LD_BUG, "HiddenServiceAuthorizeClient has no value. This "
"should have been prevented when parsing the "
@@ -341,66 +349,54 @@
rend_service_free(service);
return -1;
}
- service->auth_type = (int) tor_parse_long(
- smartlist_get(type_names_split, 0), 10, 1, 2, NULL, NULL);
- if (!service->auth_type) {
+ authname = smartlist_get(type_names_split, 0);
+ if (!strcasecmp(authname, "basic")) {
+ service->auth_type = REND_BASIC_AUTH;
+ } else if (!strcasecmp(authname, "stealth")) {
+ service->auth_type = REND_STEALTH_AUTH;
+ } else {
log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
- "unrecognized auth-type '%s'. Only 1 or 2 are recognized.",
+ "unrecognized auth-type '%s'. Only 'basic' or 'stealth' "
+ "are recognized.",
(char *) smartlist_get(type_names_split, 0));
SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
smartlist_free(type_names_split);
rend_service_free(service);
return -1;
}
+ service->clients = smartlist_create();
if (smartlist_len(type_names_split) < 2) {
log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
- "authorization type %d, but no client names.",
- service->auth_type);
+ "auth-type '%s', but no client names.",
+ service->auth_type == 1 ? "basic" : "stealth");
SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
smartlist_free(type_names_split);
continue;
}
- if (smartlist_len(type_names_split) > 2) {
- log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
- "illegal value '%s'. Must be formatted "
- "as 'HiddenServiceAuthorizeClient auth-type "
- "client-name,client-name,...' (without "
- "additional spaces in client-separated client "
- "list).",
- line->value);
- SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
- smartlist_free(type_names_split);
- rend_service_free(service);
- return -1;
- }
clients = smartlist_create();
smartlist_split_string(clients, smartlist_get(type_names_split, 1),
- ",", 0, 0);
+ ",", SPLIT_SKIP_SPACE, 0);
SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
smartlist_free(type_names_split);
- if ((service->auth_type == 1 && smartlist_len(clients) > 512) ||
- (service->auth_type == 2 && smartlist_len(clients) > 16)) {
- log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
- "client authorization entries, but only a "
- "maximum of %d entries is allowed for "
- "authorization type %d.",
- smartlist_len(clients),
- service->auth_type == 1 ? 512 : 16,
- service->auth_type);
- SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
- smartlist_free(clients);
- rend_service_free(service);
- return -1;
+ /* Remove duplicate client names. */
+ num_clients = smartlist_len(clients);
+ smartlist_sort_strings(clients);
+ smartlist_uniq_strings(clients);
+ if (smartlist_len(clients) < num_clients) {
+ log_info(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
+ "duplicate client name(s); removing.",
+ num_clients - smartlist_len(clients));
+ num_clients = smartlist_len(clients);
}
- SMARTLIST_FOREACH(clients, char *, client_name, {
+ SMARTLIST_FOREACH_BEGIN(clients, const char *, client_name)
+ {
rend_authorized_client_t *client;
size_t len = strlen(client_name);
- int found_duplicate = 0;
- if (len < 1 || len > 19) {
+ if (len < 1 || len > REND_CLIENTNAME_MAX_LEN) {
log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
"illegal client name: '%s'. Length must be "
- "between 1 and 19 characters.",
- client_name);
+ "between 1 and %d characters.",
+ client_name, REND_CLIENTNAME_MAX_LEN);
SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
smartlist_free(clients);
rend_service_free(service);
@@ -416,24 +412,29 @@
rend_service_free(service);
return -1;
}
- /* Check if client name is duplicate. */
- SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, c, {
- if (!strcmp(c->client_name, client_name)) {
- log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
- "duplicate client name: '%s'; ignoring.", client_name);
- found_duplicate = 1;
- break;
- }
- });
- if (found_duplicate)
- continue;
client = tor_malloc_zero(sizeof(rend_authorized_client_t));
- client->client_name = strdup(client_name);
+ client->client_name = tor_strdup(client_name);
smartlist_add(service->clients, client);
log_debug(LD_REND, "Adding client name '%s'", client_name);
- });
+ }
+ SMARTLIST_FOREACH_END(client_name);
SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
smartlist_free(clients);
+ /* Ensure maximum number of clients. */
+ if ((service->auth_type == REND_BASIC_AUTH &&
+ smartlist_len(service->clients) > 512) ||
+ (service->auth_type == REND_STEALTH_AUTH &&
+ smartlist_len(service->clients) > 16)) {
+ log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
+ "client authorization entries, but only a "
+ "maximum of %d entries is allowed for "
+ "authorization type '%s'.",
+ smartlist_len(service->clients),
+ service->auth_type == REND_BASIC_AUTH ? 512 : 16,
+ service->auth_type == 1 ? "basic" : "stealth");
+ rend_service_free(service);
+ return -1;
+ }
} else {
smartlist_t *versions;
char *version_str;
@@ -522,13 +523,11 @@
int
rend_service_load_keys(void)
{
- int i;
- rend_service_t *s;
+ int r = 0;
char fname[512];
char buf[1500];
- for (i=0; i < smartlist_len(rend_service_list); ++i) {
- s = smartlist_get(rend_service_list,i);
+ SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
if (s->private_key)
continue;
log_info(LD_REND, "Loading hidden-service keys from \"%s\"",
@@ -573,26 +572,26 @@
}
/* If client authorization is configured, load or generate keys. */
- if (s->auth_type) {
- char *client_keys_str;
+ if (s->auth_type != REND_NO_AUTH) {
+ char *client_keys_str = NULL;
strmap_t *parsed_clients = strmap_new();
char cfname[512];
+ FILE *cfile, *hfile;
+ open_file_t *open_cfile = NULL, *open_hfile = NULL;
/* Load client keys and descriptor cookies, if available. */
- if (strlcpy(cfname,s->directory,sizeof(cfname)) >= sizeof(cfname) ||
- strlcat(cfname,PATH_SEPARATOR"client_keys",sizeof(cfname))
- >= sizeof(cfname)) {
+ if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys",
+ s->directory)<0) {
log_warn(LD_CONFIG, "Directory name too long to store client keys "
"file: \"%s\".", s->directory);
- return -1;
+ goto err;
}
client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL);
if (client_keys_str) {
if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) {
log_warn(LD_CONFIG, "Previously stored client_keys file could not "
"be parsed.");
- tor_free(client_keys_str);
- return -1;
+ goto err;
} else {
log_info(LD_CONFIG, "Parsed %d previously stored client entries.",
strmap_size(parsed_clients));
@@ -601,18 +600,22 @@
}
/* Prepare client_keys and hostname files. */
- if (write_str_to_file(cfname, "", 0) < 0) {
- log_warn(LD_CONFIG, "Could not clear client_keys file.");
- return -1;
+ if (!(cfile = start_writing_to_stdio_file(cfname, OPEN_FLAGS_REPLACE,
+ 0600, &open_cfile))) {
+ log_warn(LD_CONFIG, "Could not open client_keys file %s",
+ escaped(cfname));
+ goto err;
}
- if (write_str_to_file(fname, "", 0) < 0) {
- log_warn(LD_CONFIG, "Could not clear hostname file.");
- return -1;
+ if (!(hfile = start_writing_to_stdio_file(fname, OPEN_FLAGS_REPLACE,
+ 0600, &open_hfile))) {
+ log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(fname));
+ goto err;
}
/* Either use loaded keys for configured clients or generate new
* ones if a client is new. */
- SMARTLIST_FOREACH(s->clients, rend_authorized_client_t *, client, {
+ SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client)
+ {
char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1];
char service_id[16+1];
rend_authorized_client_t *parsed =
@@ -630,30 +633,27 @@
client->descriptor_cookie,
REND_DESC_COOKIE_LEN) < 0) {
log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
- strmap_free(parsed_clients, rend_authorized_client_free);
+ strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
return -1;
}
/* Copy client key from parsed entry or create new one if required. */
if (parsed && parsed->client_key) {
client->client_key = crypto_pk_dup_key(parsed->client_key);
- } else if (s->auth_type == 2) {
+ } else if (s->auth_type == REND_STEALTH_AUTH) {
/* Create private key for client. */
crypto_pk_env_t *prkey = NULL;
if (!(prkey = crypto_new_pk_env())) {
log_warn(LD_BUG,"Error constructing client key");
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
if (crypto_pk_generate_key(prkey)) {
log_warn(LD_BUG,"Error generating client key");
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
if (crypto_pk_check_key(prkey) <= 0) {
log_warn(LD_BUG,"Generated client key seems invalid");
crypto_free_pk_env(prkey);
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
client->client_key = prkey;
}
@@ -664,8 +664,7 @@
client->client_name, desc_cook_out);
if (written < 0) {
log_warn(LD_BUG, "Could not write client entry.");
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
if (client->client_key) {
char *client_key_out;
@@ -673,47 +672,71 @@
&client_key_out, &len);
if (rend_get_service_id(client->client_key, service_id)<0) {
log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
written = tor_snprintf(buf + written, sizeof(buf) - written,
- "client-key\n%s",
- client_key_out);
+ "client-key\n%s", client_key_out);
if (written < 0) {
log_warn(LD_BUG, "Could not write client entry.");
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
}
- append_bytes_to_file(cfname, buf, strlen(buf), 0);
+
+ if (fputs(buf, cfile) < 0) {
+ log_warn(LD_FS, "Could not append client entry to file: %s",
+ strerror(errno));
+ goto err;
+ }
+
/* Add line to hostname file. */
- if (s->auth_type == 2) {
+ if (s->auth_type == REND_BASIC_AUTH) {
+ /* Remove == signs (newline has been removed above). */
+ desc_cook_out[strlen(desc_cook_out)-2] = '\0';
+ tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
+ s->service_id, desc_cook_out, client->client_name);
+ } else {
char extended_desc_cookie[REND_DESC_COOKIE_LEN+1];
memcpy(extended_desc_cookie, client->descriptor_cookie,
REND_DESC_COOKIE_LEN);
- extended_desc_cookie[REND_DESC_COOKIE_LEN] = (s->auth_type - 1) << 4;
+ extended_desc_cookie[REND_DESC_COOKIE_LEN] =
+ ((int)s->auth_type - 1) << 4;
if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
extended_desc_cookie,
REND_DESC_COOKIE_LEN+1) < 0) {
log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
- strmap_free(parsed_clients, rend_authorized_client_free);
- return -1;
+ goto err;
}
desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and
newline. */
tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
service_id, desc_cook_out, client->client_name);
- } else {
- /* Remove == signs (newline has been removed above). */
- desc_cook_out[strlen(desc_cook_out)-2] = '\0';
- tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
- s->service_id, desc_cook_out, client->client_name);
}
- append_bytes_to_file(fname, buf, strlen(buf), 0);
- });
+
+ if (fputs(buf, hfile)<0) {
+ log_warn(LD_FS, "Could not append host entry to file: %s",
+ strerror(errno));
+ goto err;
+ }
+ }
+ SMARTLIST_FOREACH_END(client);
+
+ goto done;
+ err:
+ r = -1;
+ done:
+ tor_free(client_keys_str);
+ strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
+ if (r<0) {
+ abort_writing_to_file(open_cfile);
+ abort_writing_to_file(open_hfile);
+ return r;
+ } else {
+ finish_writing_to_file(open_cfile);
+ finish_writing_to_file(open_hfile);
+ }
}
- }
- return 0;
+ } SMARTLIST_FOREACH_END(s);
+ return r;
}
/** Return the service whose public key has a digest of <b>digest</b> and
Modified: tor/branches/121-hs-authorization/src/or/routerlist.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/routerlist.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/routerlist.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -1431,6 +1431,19 @@
* routers by bandwidth. */
#define DEFAULT_MAX_BELIEVABLE_BANDWIDTH 10000000 /* 10 MB/sec */
+/** Return the smaller of the router's configured BandwidthRate
+ * and its advertised capacity, capped by max-believe-bw. */
+uint32_t
+router_get_advertised_bandwidth_capped(routerinfo_t *router)
+{
+ uint32_t result = router->bandwidthcapacity;
+ if (result > router->bandwidthrate)
+ result = router->bandwidthrate;
+ if (result > DEFAULT_MAX_BELIEVABLE_BANDWIDTH)
+ result = DEFAULT_MAX_BELIEVABLE_BANDWIDTH;
+ return result;
+}
+
/** Eventually, the number we return will come from the directory
* consensus, so clients can dynamically update to better numbers.
*
Modified: tor/branches/121-hs-authorization/src/or/routerparse.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/routerparse.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/routerparse.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -53,9 +53,11 @@
K_DIR_OPTIONS,
K_CLIENT_VERSIONS,
K_SERVER_VERSIONS,
+ K_P,
K_R,
K_S,
K_V,
+ K_W,
K_EVENTDNS,
K_EXTRA_INFO,
K_EXTRA_INFO_DIGEST,
@@ -145,6 +147,7 @@
typedef enum {
NO_OBJ, /**< No object, ever. */
NEED_OBJ, /**< Object is required. */
+ NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
NEED_KEY, /**< Object is required, and must be a public key. */
OBJ_OK, /**< Object is optional. */
@@ -263,9 +266,11 @@
/** List of tokens allowable in the body part of v2 and v3 networkstatus
* documents. */
static token_rule_t rtrstatus_token_table[] = {
+ T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
T1( "r", K_R, GE(8), NO_OBJ ),
T1( "s", K_S, ARGS, NO_OBJ ),
T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
+ T01("w", K_W, ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
END_OF_TABLE
};
@@ -361,7 +366,7 @@
static token_rule_t client_keys_token_table[] = {
T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
- T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_KEY_1024),
+ T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
END_OF_TABLE
};
@@ -1862,6 +1867,40 @@
}
}
+ /* handle weighting/bandwidth info */
+ if ((tok = find_first_by_keyword(tokens, K_W))) {
+ int i;
+ for (i=0; i < tok->n_args; ++i) {
+ if (!strcmpstart(tok->args[i], "Bandwidth=")) {
+ int ok;
+ rs->bandwidth = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10,
+ 0, UINT32_MAX, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
+ goto err;
+ }
+ rs->has_bandwidth = 1;
+ }
+ }
+ }
+
+ /* parse exit policy summaries */
+ if ((tok = find_first_by_keyword(tokens, K_P))) {
+ tor_assert(tok->n_args == 1);
+ if (strcmpstart(tok->args[0], "accept ") &&
+ strcmpstart(tok->args[0], "reject ")) {
+ log_err(LD_DIR, "Unknown exit policy summary type %s.",
+ escaped(tok->args[0]));
+ goto err;
+ }
+ /* XXX weasel: parse this into ports and represent them somehow smart,
+ * maybe not here but somewhere on if we need it for the client.
+ * we should still parse it here to check it's valid tho.
+ */
+ rs->exitsummary = tor_strdup(tok->args[0]);
+ rs->has_exitsummary = 1;
+ }
+
if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
rs->is_named = 0;
@@ -2092,6 +2131,7 @@
struct in_addr in;
int i, inorder, n_signatures = 0;
memarea_t *area = NULL, *rs_area = NULL;
+ tor_assert(s);
if (router_get_networkstatus_v3_hash(s, ns_digest)) {
log_warn(LD_DIR, "Unable to compute digest of network-status");
@@ -2802,6 +2842,7 @@
}
break;
case NEED_KEY_1024:
+ case NEED_SKEY_1024:
if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
kwd, (int)crypto_pk_keysize(tok->key));
@@ -2812,6 +2853,19 @@
if (!tok->key) {
tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
}
+ if (o_syn != NEED_SKEY_1024) {
+ if (crypto_pk_key_is_private(tok->key)) {
+ tor_snprintf(ebuf, sizeof(ebuf),
+ "Private key given for %s, which wants a public key", kwd);
+ RET_ERR(ebuf);
+ }
+ } else { /* o_syn == NEED_SKEY_1024 */
+ if (!crypto_pk_key_is_private(tok->key)) {
+ tor_snprintf(ebuf, sizeof(ebuf),
+ "Public key given for %s, which wants a private key", kwd);
+ RET_ERR(ebuf);
+ }
+ }
break;
case OBJ_OK:
break;
@@ -3849,7 +3903,7 @@
goto err;
}
parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
- parsed_entry->client_name = strdup(tok->args[0]);
+ parsed_entry->client_name = tor_strdup(tok->args[0]);
strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
/* Parse client key. */
tok = find_first_by_keyword(tokens, C_CLIENT_KEY);
@@ -3864,11 +3918,11 @@
tor_assert(tok->n_args == 1);
if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
- tok->args[0]);
+ escaped(tok->args[0]));
goto err;
}
- /* The size of descriptor_cookie_tmp needs to REND_DESC_COOKIE_LEN+2,
- * because a base64 of length 24 does not fit into 16 bytes in all
+ /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
+ * because a base64 encoding of length 24 does not fit into 16 bytes in all
* cases. */
if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
Modified: tor/branches/121-hs-authorization/src/or/test.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/test.c 2008-08-15 21:58:51 UTC (rev 16565)
+++ tor/branches/121-hs-authorization/src/or/test.c 2008-08-16 11:36:09 UTC (rev 16566)
@@ -1328,7 +1328,7 @@
sin->sin_family = AF_INET;
sin->sin_port = 9090;
sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/
- tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin);
+ tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL);
test_eq(tor_addr_family(&t1), AF_INET);
test_eq(tor_addr_to_ipv4h(&t1), 0x7f7f0102);
@@ -1344,7 +1344,7 @@
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(7070);
sin6->sin6_addr.s6_addr[0] = 128;
- tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6);
+ tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL);
test_eq(tor_addr_family(&t1), AF_INET6);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
test_streq(p1, "8000::");
@@ -2862,12 +2862,35 @@
#undef median
}
+static routerinfo_t *
+generate_ri_from_rs(const vote_routerstatus_t *vrs)
+{
+ routerinfo_t *r;
+ const routerstatus_t *rs = &vrs->status;
+ static time_t published = 0;
+
+ r = tor_malloc_zero(sizeof(routerinfo_t));
+ memcpy(r->cache_info.identity_digest, rs->identity_digest, DIGEST_LEN);
+ memcpy(r->cache_info.signed_descriptor_digest, rs->descriptor_digest,
+ DIGEST_LEN);
+ r->cache_info.do_not_cache = 1;
+ r->cache_info.routerlist_index = -1;
+ r->cache_info.signed_descriptor_body =
+ tor_strdup("123456789012345678901234567890123");
+ r->cache_info.signed_descriptor_len =
+ strlen(r->cache_info.signed_descriptor_body);
+ r->exit_policy = smartlist_create();
+ r->cache_info.published_on = ++published + time(NULL);
+ return r;
+};
+
static void
test_v3_networkstatus(void)
{
authority_cert_t *cert1, *cert2, *cert3;
crypto_pk_env_t *sign_skey_1, *sign_skey_2, *sign_skey_3;
crypto_pk_env_t *sign_skey_leg1;
+ const char *msg=NULL;
time_t now = time(NULL);
networkstatus_voter_info_t *voter;
@@ -2944,6 +2967,8 @@
/* all flags but running cleared */
rs->is_running = 1;
smartlist_add(vote->routerstatus_list, vrs);
+ test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
+
/* add the second routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
@@ -2958,6 +2983,8 @@
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running =
rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
+ test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
+
/* add the third routerstatus. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
@@ -2965,13 +2992,15 @@
rs->published_on = now-1000;
strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
memset(rs->identity_digest, 33, DIGEST_LEN);
- memset(rs->descriptor_digest, 78, DIGEST_LEN);
+ memset(rs->descriptor_digest, 79, DIGEST_LEN);
rs->addr = 0xAA009901;
rs->or_port = 400;
rs->dir_port = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
rs->is_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
+ test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
+
/* add a fourth routerstatus that is not running. */
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
@@ -2985,6 +3014,7 @@
rs->dir_port = 1999;
/* Running flag (and others) cleared */
smartlist_add(vote->routerstatus_list, vrs);
+ test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
/* dump the vote and try to parse it. */
v1_text = format_networkstatus_vote(sign_skey_1, vote);
@@ -3108,6 +3138,7 @@
tor_free(vrs);
vrs = smartlist_get(vote->routerstatus_list, 0);
memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN);
+ test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
v3_text = format_networkstatus_vote(sign_skey_3, vote);
test_assert(v3_text);
@@ -3327,12 +3358,37 @@
}
static void
+test_policy_summary_helper(const char *policy_str,
+ const char *expected_summary)
+{
+ config_line_t line;
+ smartlist_t *policy;
+ char *summary;
+
+ policy = NULL;
+ line.key = (char*)"foo";
+ line.value = (char *)policy_str;
+ line.next = NULL;
+
+ test_assert(0 == policies_parse_exit_policy(&line, &policy, 0, NULL));
+ summary = policy_summarize(policy);
+
+ test_assert(summary != NULL);
+ test_streq(summary, expected_summary);
+ tor_free(summary);
+ addr_policy_list_free(policy);
+}
+
+static void
test_policies(void)
{
+ int i;
smartlist_t *policy, *policy2;
addr_policy_t *p;
tor_addr_t tar;
config_line_t line;
+ smartlist_t *sm;
+ char *policy_str;
policy = smartlist_create();
@@ -3386,6 +3442,92 @@
test_eq(smartlist_len(policy), 2);
addr_policy_list_free(policy);
+
+ /* test policy summaries */
+ /* check if we properly ignore private IP addresses */
+ test_policy_summary_helper("reject 192.168.0.0/16:*,"
+ "reject 0.0.0.0/8:*,"
+ "reject 10.0.0.0/8:*,"
+ "accept *:10-30,"
+ "accept *:90,"
+ "reject *:*",
+ "accept 10-30,90");
+ /* check all accept policies, and proper counting of rejects */
+ test_policy_summary_helper("reject 11.0.0.0/9:80,"
+ "reject 12.0.0.0/9:80,"
+ "reject 13.0.0.0/9:80,"
+ "reject 14.0.0.0/9:80,"
+ "accept *:*", "accept 1-65535");
+ test_policy_summary_helper("reject 11.0.0.0/9:80,"
+ "reject 12.0.0.0/9:80,"
+ "reject 13.0.0.0/9:80,"
+ "reject 14.0.0.0/9:80,"
+ "reject 15.0.0.0:81,"
+ "accept *:*", "accept 1-65535");
+ test_policy_summary_helper("reject 11.0.0.0/9:80,"
+ "reject 12.0.0.0/9:80,"
+ "reject 13.0.0.0/9:80,"
+ "reject 14.0.0.0/9:80,"
+ "reject 15.0.0.0:80,"
+ "accept *:*",
+ "reject 80");
+ /* no exits */
+ test_policy_summary_helper("accept 11.0.0.0/9:80,"
+ "reject *:*",
+ "reject 1-65535");
+ /* port merging */
+ test_policy_summary_helper("accept *:80,"
+ "accept *:81,"
+ "accept *:100-110,"
+ "accept *:111,"
+ "reject *:*",
+ "accept 80-81,100-111");
+ /* border ports */
+ test_policy_summary_helper("accept *:1,"
+ "accept *:3,"
+ "accept *:65535,"
+ "reject *:*",
+ "accept 1,3,65535");
+ /* holes */
+ test_policy_summary_helper("accept *:1,"
+ "accept *:3,"
+ "accept *:5,"
+ "accept *:7,"
+ "reject *:*",
+ "accept 1,3,5,7");
+ test_policy_summary_helper("reject *:1,"
+ "reject *:3,"
+ "reject *:5,"
+ "reject *:7,"
+ "accept *:*",
+ "reject 1,3,5,7");
+ /* truncation ports */
+ sm = smartlist_create();
+ for (i=1; i<2000; i+=2) {
+ char buf[POLICY_BUF_LEN];
+ tor_snprintf(buf, sizeof(buf), "reject *:%d", i);
+ smartlist_add(sm, tor_strdup(buf));
+ }
+ smartlist_add(sm, tor_strdup("accept *:*"));
+ policy_str = smartlist_join_strings(sm, ",", 0, NULL);
+ test_policy_summary_helper( policy_str,
+ "accept 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,"
+ "46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,"
+ "92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,"
+ "130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,"
+ "166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,"
+ "202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,"
+ "238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,"
+ "274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,"
+ "310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,"
+ "346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380,"
+ "382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412,414,416,"
+ "418,420,422,424,426,428,430,432,434,436,438,440,442,444,446,448,450,452,"
+ "454,456,458,460,462,464,466,468,470,472,474,476,478,480,482,484,486,488,"
+ "490,492,494,496,498,500,502,504,506,508,510,512,514,516,518,520,522");
+ tor_free(policy_str);
+ SMARTLIST_FOREACH(sm, char *, s, tor_free(s));
+ smartlist_clear(sm);
}
static void
More information about the tor-commits
mailing list