Merge remote-tracking branch 'origin/maint-0.2.2' into release-0.2.2

This commit is contained in:
Nick Mathewson 2011-05-16 11:01:23 -04:00
commit fd105e1048
30 changed files with 451 additions and 90 deletions

13
changes/bug1345 Normal file
View File

@ -0,0 +1,13 @@
o Minor bugfixes:
- On SIGHUP, do not clear out all TrackHostExits mappings, client DNS
cache entries, and virtual address mappings: that's what NEWNYM is
for. Bugfix on Tor 0.1.0.1-rc; fixes bug 1345.
- When TrackHostExits is changed from a controller, remove any
mappings for hosts that should no longer have their exits tracked.
Bugfix on Tor 0.1.0.1-rc.
- When VirtualAddrNetwork option is changed from a controller,
remove any mappings for hosts that were automapped to
that network. Bugfix on 0.1.1.19-rc.
- When one of the AutomapHosts* options is changed from a
controller, remove any mappings for hosts that should no longer be
automapped. Bugfix on 0.2.0.1-alpha.

7
changes/bug2732-simple Normal file
View File

@ -0,0 +1,7 @@
o Minor bugfixes
- Do not reject hidden service descriptors simply because we don't
think we have not been assigned the HSDir flag. Clients and
hidden services can have a more up-to-date view of the network
consensus, and if they think that the directory authorities
list us a HSDir, we might actually be one. Related to bug 2732;
bugfix on 0.2.0.10-alpha.

8
changes/bug2792_checkdir Normal file
View File

@ -0,0 +1,8 @@
o Minor features:
- Tor now refuses to create a ControlSocket in a directory that is
world-readable (or group-readable if ControlSocketsGroupWritable
is 0). This is necessary because some operating systems do not
check the permissions on an AF_UNIX socket when programs try to
connect to it. Checking permissions on the directory holding
the socket, however, seems to work everywhere.

5
changes/bug2972 Normal file
View File

@ -0,0 +1,5 @@
o Minor features:
- Allow ControlSockets to be group-writable when the
ControlSocksGroupWritable configuration option is turned on. Patch
by Jérémy Bobbio; implements ticket 2972.

4
changes/bug3019 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes:
- Do not reset the bridge descriptor download status every time we
re-parse our configuration or get a configuration change. Fixes
bug 3019; bugfix on Tor 0.2.0.3-alpha.

4
changes/bug3026 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes (directory authority)
- Do not upload our own vote or signature set to ourself. It would
tell us nothing new. Also, as of Tor 0.2.2.24-alpha, we started
to warn about receiving duplicate votes. Resolves bug 3026.

7
changes/bug3175 Normal file
View File

@ -0,0 +1,7 @@
o Minor bugfixes:
- Resolve an untriggerable issue in smartlist_string_num_isin(),
where if the function had ever in the future been used to check
for the presence of a too-large number, it would have given an
incorrect result. (Fortunately, we only used it for 16-bit
values.) Fixes bug 3175; bugfix on Tor 0.1.0.1-rc.

View File

@ -167,6 +167,11 @@ Other options can be specified either on the command-line (--option
Like ControlPort, but listens on a Unix domain socket, rather than a TCP
socket. (Unix and Unix-like systems only.)
**ControlSocketsGroupWritable** **0**|**1**::
If this option is set to 0, don't allow the filesystem group to read and
write unix sockets (e.g. ControlSocket). If the option is set to 1, make
the control socket readable and writable by the default GID. (Default: 0)
**HashedControlPassword** __hashed_password__::
Don't allow any connections on the control port except when the other
process knows the password whose one-way hash is __hashed_password__. You

View File

@ -1467,6 +1467,45 @@ get_user_homedir(const char *username)
}
#endif
/** Modify <b>fname</b> to contain the name of the directory */
int
get_parent_directory(char *fname)
{
char *cp;
int at_end = 1;
tor_assert(fname);
#ifdef MS_WINDOWS
/* If we start with, say, c:, then don't consider that the start of the path
*/
if (fname[0] && fname[1] == ':') {
fname += 2;
}
#endif
/* Now we want to remove all path-separators at the end of the string,
* and to remove the end of the string starting with the path separator
* before the last non-path-separator. In perl, this would be
* s#[/]*$##; s#/[^/]*$##;
* on a unixy platform.
*/
cp = fname + strlen(fname);
at_end = 1;
while (--cp > fname) {
int is_sep = (*cp == '/'
#ifdef MS_WINDOWS
|| *cp == '\\'
#endif
);
if (is_sep) {
*cp = '\0';
if (! at_end)
return 0;
} else {
at_end = 0;
}
}
return -1;
}
/** Set *addr to the IP address (in dotted-quad notation) stored in c.
* Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr),
* but works on Windows and Solaris.)

View File

@ -552,6 +552,8 @@ int switch_id(const char *user);
char *get_user_homedir(const char *username);
#endif
int get_parent_directory(char *fname);
int spawn_func(void (*func)(void *), void *data);
void spawn_exit(void) ATTR_NORETURN;

View File

@ -210,11 +210,30 @@ smartlist_string_isin_case(const smartlist_t *sl, const char *element)
int
smartlist_string_num_isin(const smartlist_t *sl, int num)
{
char buf[16];
char buf[32]; /* long enough for 64-bit int, and then some. */
tor_snprintf(buf,sizeof(buf),"%d", num);
return smartlist_string_isin(sl, buf);
}
/** Return true iff the two lists contain the same strings in the same
* order, or if they are both NULL. */
int
smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
{
if (sl1 == NULL)
return sl2 == NULL;
if (sl2 == NULL)
return 0;
if (smartlist_len(sl1) != smartlist_len(sl2))
return 0;
SMARTLIST_FOREACH(sl1, const char *, cp1, {
const char *cp2 = smartlist_get(sl2, cp1_sl_idx);
if (strcmp(cp1, cp2))
return 0;
});
return 1;
}
/** Return true iff <b>sl</b> has some element E such that
* tor_memeq(E,<b>element</b>,DIGEST_LEN)
*/

View File

@ -42,6 +42,8 @@ int smartlist_string_pos(const smartlist_t *, const char *elt) ATTR_PURE;
int smartlist_string_isin_case(const smartlist_t *sl, const char *element)
ATTR_PURE;
int smartlist_string_num_isin(const smartlist_t *sl, int num) ATTR_PURE;
int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
ATTR_PURE;
int smartlist_digest_isin(const smartlist_t *sl, const char *element)
ATTR_PURE;
int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2)
@ -259,7 +261,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
* Example use:
* SMARTLIST_FOREACH_JOIN(routerstatus_list, routerstatus_t *, rs,
* routerinfo_list, routerinfo_t *, ri,
* tor_memcmp(rs->identity_digest, ri->identity_digest, 20),
* tor_memcmp(rs->identity_digest, ri->identity_digest, 20),
* log_info(LD_GENERAL,"No match for %s", ri->nickname)) {
* log_info(LD_GENERAL, "%s matches routerstatus %p", ri->nickname, rs);
* } SMARTLIST_FOREACH_JOIN_END(rs, ri);

View File

@ -3,18 +3,18 @@
/**
* \file di_ops.c
* \brief Functions for data-independent operations
* \brief Functions for data-independent operations.
**/
#include "orconfig.h"
#include "di_ops.h"
/**
* Timing-safe version of memcmp. As memcmp, compare the <b>sz</b> bytes
* at <b>a</b> with the <b>sz</b> bytes at <b>, and returns less than 0 if the
* bytes at <b>a</b> lexically precede those at <b>b</b>, 0 if the byte ranges
* are equal, and greater than zero if the bytes at <b>a</b> lexically follow
* those at <b>.
* Timing-safe version of memcmp. As memcmp, compare the <b>sz</b> bytes at
* <b>a</b> with the <b>sz</b> bytes at <b>b</b>, and return less than 0 if
* the bytes at <b>a</b> lexically precede those at <b>b</b>, 0 if the byte
* ranges are equal, and greater than zero if the bytes at <b>a</b> lexically
* follow those at <b>b</b>.
*
* This implementation differs from memcmp in that its timing behavior is not
* data-dependent: it should return in the same amount of time regardless of
@ -85,7 +85,7 @@ tor_memcmp(const void *a, const void *b, size_t len)
/**
* Timing-safe memory comparison. Return true if the <b>sz</b> bytes at
* <b>a</b> are the same as the <b>sz</b> bytes at <b>, and 0 otherwise.
* <b>a</b> are the same as the <b>sz</b> bytes at <b>b</b>, and 0 otherwise.
*
* This implementation differs from !memcmp(a,b,sz) in that its timing
* behavior is not data-dependent: it should return in the same amount of time

View File

@ -28,3 +28,4 @@ int tor_memeq(const void *a, const void *b, size_t sz);
#define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c)))
#endif

View File

@ -30,6 +30,7 @@
#else
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#endif
/* math.h needs this on Linux */
@ -1664,17 +1665,25 @@ file_status(const char *fname)
return FN_ERROR;
}
/** Check whether dirname exists and is private. If yes return 0. If
* it does not exist, and check==CPD_CREATE is set, try to create it
/** Check whether <b>dirname</b> exists and is private. If yes return 0. If
* it does not exist, and <b>check</b>&CPD_CREATE is set, try to create it
* and return 0 on success. If it does not exist, and
* check==CPD_CHECK, and we think we can create it, return 0. Else
* return -1. */
* <b>check</b>&CPD_CHECK, and we think we can create it, return 0. Else
* return -1. If CPD_GROUP_OK is set, then it's okay if the directory
* is group-readable, but in all cases we create the directory mode 0700.
* If CPD_CHECK_MODE_ONLY is set, then we don't alter the directory permissions
* if they are too permissive: we just return -1.
*/
int
check_private_dir(const char *dirname, cpd_check_t check)
{
int r;
struct stat st;
char *f;
#ifndef MS_WINDOWS
int mask;
#endif
tor_assert(dirname);
f = tor_strdup(dirname);
clean_name_for_stat(f);
@ -1686,10 +1695,7 @@ check_private_dir(const char *dirname, cpd_check_t check)
strerror(errno));
return -1;
}
if (check == CPD_NONE) {
log_warn(LD_FS, "Directory %s does not exist.", dirname);
return -1;
} else if (check == CPD_CREATE) {
if (check & CPD_CREATE) {
log_info(LD_GENERAL, "Creating directory %s", dirname);
#if defined (MS_WINDOWS) && !defined (WINCE)
r = mkdir(dirname);
@ -1701,6 +1707,9 @@ check_private_dir(const char *dirname, cpd_check_t check)
strerror(errno));
return -1;
}
} else if (!(check & CPD_CHECK)) {
log_warn(LD_FS, "Directory %s does not exist.", dirname);
return -1;
}
/* XXXX In the case where check==CPD_CHECK, we should look at the
* parent directory a little harder. */
@ -1728,9 +1737,38 @@ check_private_dir(const char *dirname, cpd_check_t check)
tor_free(process_ownername);
return -1;
}
if (st.st_mode & 0077) {
if ((check & CPD_GROUP_OK) && st.st_gid != getgid()) {
struct group *gr;
char *process_groupname = NULL;
gr = getgrgid(getgid());
process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>");
gr = getgrgid(st.st_gid);
log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group "
"%s (%d). Are you running Tor as the wrong user?",
dirname, process_groupname, (int)getgid(),
gr ? gr->gr_name : "<unknown>", (int)st.st_gid);
tor_free(process_groupname);
return -1;
}
if (check & CPD_GROUP_OK) {
mask = 0027;
} else {
mask = 0077;
}
if (st.st_mode & mask) {
unsigned new_mode;
if (check & CPD_CHECK_MODE_ONLY) {
log_warn(LD_FS, "Permissions on directory %s are too permissive.",
dirname);
return -1;
}
log_warn(LD_FS, "Fixing permissions on directory %s", dirname);
if (chmod(dirname, 0700)) {
new_mode = st.st_mode;
new_mode |= 0700; /* Owner should have rwx */
new_mode &= ~mask; /* Clear the other bits that we didn't want set...*/
if (chmod(dirname, new_mode)) {
log_warn(LD_FS, "Could not chmod directory %s: %s", dirname,
strerror(errno));
return -1;

View File

@ -286,7 +286,12 @@ file_status_t file_status(const char *filename);
/** Possible behaviors for check_private_dir() on encountering a nonexistent
* directory; see that function's documentation for details. */
typedef enum { CPD_NONE, CPD_CREATE, CPD_CHECK } cpd_check_t;
typedef unsigned int cpd_check_t;
#define CPD_NONE 0
#define CPD_CREATE 1
#define CPD_CHECK 2
#define CPD_GROUP_OK 4
#define CPD_CHECK_MODE_ONLY 8
int check_private_dir(const char *dirname, cpd_check_t check);
#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)

View File

@ -4471,6 +4471,9 @@ typedef struct {
tor_addr_t addr;
/** TLS port for the bridge. */
uint16_t port;
/** Boolean: We are re-parsing our bridge list, and we are going to remove
* this one if we don't find it in the list of configured bridges. */
unsigned marked_for_removal : 1;
/** Expected identity digest, or all zero bytes if we don't know what the
* digest should be. */
char identity[DIGEST_LEN];
@ -4479,11 +4482,39 @@ typedef struct {
} bridge_info_t;
/** A list of configured bridges. Whenever we actually get a descriptor
* for one, we add it as an entry guard. */
* for one, we add it as an entry guard. Note that the order of bridges
* in this list does not necessarily correspond to the order of bridges
* in the torrc. */
static smartlist_t *bridge_list = NULL;
/** Initialize the bridge list to empty, creating it if needed. */
/** Mark every entry of the bridge list to be removed on our next call to
* sweep_bridge_list unless it has first been un-marked. */
void
mark_bridge_list(void)
{
if (!bridge_list)
bridge_list = smartlist_create();
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b,
b->marked_for_removal = 1);
}
/** Remove every entry of the bridge list that was marked with
* mark_bridge_list if it has not subsequently been un-marked. */
void
sweep_bridge_list(void)
{
if (!bridge_list)
bridge_list = smartlist_create();
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
if (b->marked_for_removal) {
SMARTLIST_DEL_CURRENT(bridge_list, b);
tor_free(b);
}
} SMARTLIST_FOREACH_END(b);
}
/** Initialize the bridge list to empty, creating it if needed. */
static void
clear_bridge_list(void)
{
if (!bridge_list)
@ -4496,7 +4527,8 @@ clear_bridge_list(void)
* (either by comparing keys if possible, else by comparing addr/port).
* Else return NULL. */
static bridge_info_t *
get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
uint16_t port,
const char *digest)
{
if (!bridge_list)
@ -4537,7 +4569,8 @@ routerinfo_is_a_configured_bridge(routerinfo_t *ri)
* If it was a bridge, and we still don't know its digest, record it.
*/
void
learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest)
learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest)
{
bridge_info_t *bridge =
get_configured_bridge_by_addr_port_digest(addr, port, digest);
@ -4549,11 +4582,20 @@ learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest)
}
/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
* is set, it tells us the identity key too. */
* is set, it tells us the identity key too. If we already had the
* bridge in our list, unmark it, and don't actually add anything new. */
void
bridge_add_from_config(const tor_addr_t *addr, uint16_t port, char *digest)
bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *digest)
{
bridge_info_t *b = tor_malloc_zero(sizeof(bridge_info_t));
bridge_info_t *b;
if ((b = get_configured_bridge_by_addr_port_digest(addr, port, digest))) {
b->marked_for_removal = 0;
return;
}
b = tor_malloc_zero(sizeof(bridge_info_t));
tor_addr_copy(&b->addr, addr);
b->port = port;
if (digest)
@ -4561,6 +4603,7 @@ bridge_add_from_config(const tor_addr_t *addr, uint16_t port, char *digest)
b->fetch_status.schedule = DL_SCHED_BRIDGE;
if (!bridge_list)
bridge_list = smartlist_create();
smartlist_add(bridge_list, b);
}

View File

@ -62,12 +62,13 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
void clear_bridge_list(void);
void mark_bridge_list(void);
void sweep_bridge_list(void);
int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
void
learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest);
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest);
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
char *digest);
const char *digest);
void retry_bridge_descriptor_fetch_directly(const char *digest);
void fetch_bridge_descriptors(or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);

View File

@ -1485,15 +1485,35 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
}
}
/** If an exit wasn't specifically chosen, save the history for future
* use. */
/** Return true iff <b>address</b> is matched by one of the entries in
* TrackHostExits. */
int
hostname_in_track_host_exits(or_options_t *options, const char *address)
{
if (!options->TrackHostExits)
return 0;
SMARTLIST_FOREACH_BEGIN(options->TrackHostExits, const char *, cp) {
if (cp[0] == '.') { /* match end */
if (cp[1] == '\0' ||
!strcasecmpend(address, cp) ||
!strcasecmp(address, &cp[1]))
return 1;
} else if (strcasecmp(cp, address) == 0) {
return 1;
}
} SMARTLIST_FOREACH_END(cp);
return 0;
}
/** If an exit wasn't explicitly specified for <b>conn</b>, consider saving
* the exit that we *did* choose for use by future connections to
* <b>conn</b>'s destination.
*/
static void
consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
{
int found_needle = 0;
or_options_t *options = get_options();
size_t len;
char *new_address;
char *new_address = NULL;
char fp[HEX_DIGEST_LEN+1];
/* Search the addressmap for this conn's destination. */
@ -1503,18 +1523,8 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
options->TrackHostExitsExpire))
return; /* nothing to track, or already mapped */
SMARTLIST_FOREACH(options->TrackHostExits, const char *, cp, {
if (cp[0] == '.') { /* match end */
if (cp[1] == '\0' ||
!strcasecmpend(conn->socks_request->address, cp) ||
!strcasecmp(conn->socks_request->address, &cp[1]))
found_needle = 1;
} else if (strcasecmp(cp, conn->socks_request->address) == 0) {
found_needle = 1;
}
});
if (!found_needle || !circ->build_state->chosen_exit)
if (!hostname_in_track_host_exits(options, conn->socks_request->address) ||
!circ->build_state->chosen_exit)
return;
/* write down the fingerprint of the chosen exit, not the nickname,
@ -1523,12 +1533,7 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
circ->build_state->chosen_exit->identity_digest, DIGEST_LEN);
/* Add this exit/hostname pair to the addressmap. */
len = strlen(conn->socks_request->address) + 1 /* '.' */ +
strlen(fp) + 1 /* '.' */ +
strlen("exit") + 1 /* '\0' */;
new_address = tor_malloc(len);
tor_snprintf(new_address, len, "%s.%s.exit",
tor_asprintf(&new_address, "%s.%s.exit",
conn->socks_request->address, fp);
addressmap_register(conn->socks_request->address, new_address,

View File

@ -51,5 +51,7 @@ int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
crypt_path_t *cpath);
int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
int hostname_in_track_host_exits(or_options_t *options, const char *address);
#endif

View File

@ -209,6 +209,7 @@ static config_var_t _option_vars[] = {
V(ControlPortFileGroupReadable,BOOL, "0"),
V(ControlPortWriteToFile, FILENAME, NULL),
V(ControlSocket, LINELIST, NULL),
V(ControlSocketsGroupWritable, BOOL, "0"),
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
V(CookieAuthFile, STRING, NULL),
@ -952,9 +953,15 @@ options_act_reversible(or_options_t *old_options, char **msg)
}
#ifndef HAVE_SYS_UN_H
if (options->ControlSocket) {
*msg = tor_strdup("Unix domain sockets (ControlSocket) not supported"
" on this OS/with this build.");
if (options->ControlSocket || options->ControlSocketsGroupWritable) {
*msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
"on this OS/with this build.");
goto rollback;
}
#else
if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
*msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
"a ControlSocket makes no sense.");
goto rollback;
}
#endif
@ -1172,7 +1179,7 @@ options_act(or_options_t *old_options)
return -1;
if (options->Bridges) {
clear_bridge_list();
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
if (parse_bridge_line(cl->value, 0)<0) {
log_warn(LD_BUG,
@ -1180,6 +1187,7 @@ options_act(or_options_t *old_options)
return -1;
}
}
sweep_bridge_list();
}
if (running_tor && rend_config_services(options, 0)<0) {
@ -1264,6 +1272,8 @@ options_act(or_options_t *old_options)
/* Check for transitions that need action. */
if (old_options) {
int revise_trackexithosts = 0;
int revise_automap_entries = 0;
if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
!routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes) ||
!routerset_equal(old_options->ExcludeExitNodes,
@ -1276,9 +1286,31 @@ options_act(or_options_t *old_options)
"excluded node lists. Abandoning previous circuits.");
circuit_mark_all_unused_circs();
circuit_expire_all_dirty_circs();
addressmap_clear_excluded_trackexithosts(options);
revise_trackexithosts = 1;
}
if (!smartlist_strings_eq(old_options->TrackHostExits,
options->TrackHostExits))
revise_trackexithosts = 1;
if (revise_trackexithosts)
addressmap_clear_excluded_trackexithosts(options);
if (!options->AutomapHostsOnResolve) {
if (old_options->AutomapHostsOnResolve)
revise_automap_entries = 1;
} else {
if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes,
options->AutomapHostsSuffixes))
revise_automap_entries = 1;
else if (!opt_streq(old_options->VirtualAddrNetwork,
options->VirtualAddrNetwork))
revise_automap_entries = 1;
}
if (revise_automap_entries)
addressmap_clear_invalid_automaps(options);
/* How long should we delay counting bridge stats after becoming a bridge?
* We use this so we don't count people who used our bridge thinking it is
* a relay. If you change this, don't forget to change the log message

View File

@ -853,6 +853,43 @@ warn_too_many_conns(void)
}
}
#ifdef HAVE_SYS_UN_H
/** Check whether we should be willing to open an AF_UNIX socket in
* <b>path</b>. Return 0 if we should go ahead and -1 if we shouldn't. */
static int
check_location_for_unix_socket(or_options_t *options, const char *path)
{
int r = -1;
char *p = tor_strdup(path);
cpd_check_t flags = CPD_CHECK_MODE_ONLY;
if (get_parent_directory(p)<0)
goto done;
if (options->ControlSocketsGroupWritable)
flags |= CPD_GROUP_OK;
if (check_private_dir(p, flags) < 0) {
char *escpath, *escdir;
escpath = esc_for_log(path);
escdir = esc_for_log(p);
log_warn(LD_GENERAL, "Before Tor can create a control socket in %s, the "
"directory %s needs to exist, and to be accessible only by the "
"user%s account that is running Tor. (On some Unix systems, "
"anybody who can list a socket can conect to it, so Tor is "
"being careful.)", escpath, escdir,
options->ControlSocketsGroupWritable ? " and group" : "");
tor_free(escpath);
tor_free(escdir);
goto done;
}
r = 0;
done:
tor_free(p);
return r;
}
#endif
/** Bind a new non-blocking socket listening to the socket described
* by <b>listensockaddr</b>.
*
@ -947,6 +984,9 @@ connection_create_listener(const struct sockaddr *listensockaddr,
* and listeners at the same time */
tor_assert(type == CONN_TYPE_CONTROL_LISTENER);
if (check_location_for_unix_socket(get_options(), address) < 0)
goto err;
log_notice(LD_NET, "Opening %s on %s",
conn_type_to_string(type), address);
@ -966,6 +1006,15 @@ connection_create_listener(const struct sockaddr *listensockaddr,
tor_socket_strerror(tor_socket_errno(s)));
goto err;
}
if (get_options()->ControlSocketsGroupWritable) {
/* We need to use chmod; fchmod doesn't work on sockets on all
* platforms. */
if (chmod(address, 0660) < 0) {
log_warn(LD_FS,"Unable to make %s group-writable.", address);
tor_close_socket(s);
goto err;
}
}
if (listen(s,SOMAXCONN) < 0) {
log_warn(LD_NET, "Could not listen on %s: %s", address,

View File

@ -810,7 +810,8 @@ clear_trackexithost_mappings(const char *exitname)
}
/** Remove all TRACKEXIT mappings from the addressmap for which the target
* host is unknown or no longer allowed. */
* host is unknown or no longer allowed, or for which the source address
* is no longer in trackexithosts. */
void
addressmap_clear_excluded_trackexithosts(or_options_t *options)
{
@ -851,7 +852,8 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
tor_free(nodename);
if (!ri ||
(allow_nodes && !routerset_contains_router(allow_nodes, ri)) ||
routerset_contains_router(exclude_nodes, ri)) {
routerset_contains_router(exclude_nodes, ri) ||
!hostname_in_track_host_exits(options, address)) {
/* We don't know this one, or we want to be rid of it. */
addressmap_ent_remove(address, ent);
MAP_DEL_CURRENT(address);
@ -859,6 +861,49 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
} STRMAP_FOREACH_END;
}
/** Remove all AUTOMAP mappings from the addressmap for which the
* source address no longer matches AutomapHostsSuffixes, which is
* no longer allowed by AutomapHostsOnResolve, or for which the
* target address is no longer in the virtual network. */
void
addressmap_clear_invalid_automaps(or_options_t *options)
{
int clear_all = !options->AutomapHostsOnResolve;
const smartlist_t *suffixes = options->AutomapHostsSuffixes;
if (!addressmap)
return;
if (!suffixes)
clear_all = 1; /* This should be impossible, but let's be sure. */
STRMAP_FOREACH_MODIFY(addressmap, src_address, addressmap_entry_t *, ent) {
int remove = clear_all;
if (ent->source != ADDRMAPSRC_AUTOMAP)
continue; /* not an automap mapping. */
if (!remove) {
int suffix_found = 0;
SMARTLIST_FOREACH(suffixes, const char *, suffix, {
if (!strcasecmpend(src_address, suffix)) {
suffix_found = 1;
break;
}
});
if (!suffix_found)
remove = 1;
}
if (!remove && ! address_is_in_virtual_range(ent->new_address))
remove = 1;
if (remove) {
addressmap_ent_remove(src_address, ent);
MAP_DEL_CURRENT(src_address);
}
} STRMAP_FOREACH_END;
}
/** Remove all entries from the addressmap that were set via the
* configuration file or the command line. */
void
@ -1370,7 +1415,7 @@ addressmap_register_virtual_address(int type, char *new_address)
log_info(LD_APP, "Registering map from %s to %s", *addrp, new_address);
if (vent_needs_to_be_added)
strmap_set(virtaddress_reversemap, new_address, vent);
addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_CONTROLLER);
addressmap_register(*addrp, new_address, 2, ADDRMAPSRC_AUTOMAP);
#if 0
{

View File

@ -62,6 +62,7 @@ int address_is_invalid_destination(const char *address, int client);
void addressmap_init(void);
void addressmap_clear_excluded_trackexithosts(or_options_t *options);
void addressmap_clear_invalid_automaps(or_options_t *options);
void addressmap_clean(time_t now);
void addressmap_clear_configured(void);
void addressmap_clear_transient(void);

View File

@ -279,6 +279,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
int post_via_tor;
smartlist_t *dirservers = router_get_trusted_dir_servers();
int found = 0;
const int exclude_self = (dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES);
tor_assert(dirservers);
/* This tries dirservers which we believe to be down, but ultimately, that's
* harmless, and we may as well err on the side of getting things uploaded.
@ -291,6 +293,9 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
if ((type & ds->type) == 0)
continue;
if (exclude_self && router_digest_is_me(ds->digest))
continue;
if (options->ExcludeNodes && options->StrictNodes &&
routerset_contains_routerstatus(options->ExcludeNodes, rs)) {
log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "

View File

@ -397,8 +397,9 @@ compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
if ((r = fast_memcmp(a->status.identity_digest, b->status.identity_digest,
DIGEST_LEN)))
return r;
if ((r = fast_memcmp(a->status.descriptor_digest, b->status.descriptor_digest,
DIGEST_LEN)))
if ((r = fast_memcmp(a->status.descriptor_digest,
b->status.descriptor_digest,
DIGEST_LEN)))
return r;
if ((r = (int)(b->status.published_on - a->status.published_on)))
return r;
@ -1705,7 +1706,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
if (index[v_sl_idx] < size[v_sl_idx]) {
rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
if (!lowest_id ||
fast_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0)
fast_memcmp(rs->status.identity_digest,
lowest_id, DIGEST_LEN) < 0)
lowest_id = rs->status.identity_digest;
}
});
@ -1769,7 +1771,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
rs = compute_routerstatus_consensus(matching_descs, consensus_method,
microdesc_digest);
/* Copy bits of that into rs_out. */
tor_assert(fast_memeq(lowest_id, rs->status.identity_digest, DIGEST_LEN));
tor_assert(fast_memeq(lowest_id, rs->status.identity_digest,DIGEST_LEN));
memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
DIGEST_LEN);
@ -2211,7 +2213,8 @@ networkstatus_add_detached_signatures(networkstatus_t *target,
}
for (alg = DIGEST_SHA1; alg < N_DIGEST_ALGORITHMS; ++alg) {
if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) {
if (fast_memeq(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) {
if (fast_memeq(target->digests.d[alg], digests->d[alg],
DIGEST256_LEN)) {
++n_matches;
} else {
*msg_out = "Mismatched digest.";

View File

@ -1417,7 +1417,6 @@ do_hup(void)
router_reset_warnings();
routerlist_reset_warnings();
addressmap_clear_transient();
/* first, reload config variables, in case they've changed */
if (options->ReloadTorrcOnSIGHUP) {
/* no need to provide argc/v, they've been cached in init_from_config */

View File

@ -2445,6 +2445,7 @@ typedef struct {
int ControlPort; /**< Port to listen on for control connections. */
config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on
* for control connections. */
int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
int DirPort; /**< Port to listen on for directory connections. */
int DNSPort; /**< Port to listen on for DNS requests. */
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
@ -3150,6 +3151,9 @@ typedef enum setopt_err_t {
typedef enum {
/** We're remapping this address because the controller told us to. */
ADDRMAPSRC_CONTROLLER,
/** We're remapping this address because of an AutomapHostsOnResolve
* configuration. */
ADDRMAPSRC_AUTOMAP,
/** We're remapping this address because our configuration (via torrc, the
* command line, or a SETCONF command) told us to. */
ADDRMAPSRC_TORRC,

View File

@ -2332,8 +2332,8 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
if (n_matches <= 1 || router->is_running)
best_match = router;
} else if (maybedigest &&
tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN)
) {
tor_memeq(digest, router->cache_info.identity_digest,
DIGEST_LEN)) {
if (router_hex_digest_matches(router, nickname))
return router;
/* If we reach this point, we have a ID=name syntax that matches the
@ -5063,8 +5063,9 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
/* The identity must match exactly to have been generated at the same time
* by the same router. */
if (tor_memneq(ri->cache_info.identity_digest, ei->cache_info.identity_digest,
DIGEST_LEN)) {
if (tor_memneq(ri->cache_info.identity_digest,
ei->cache_info.identity_digest,
DIGEST_LEN)) {
if (msg) *msg = "Extrainfo nickname or identity did not match routerinfo";
goto err; /* different servers */
}
@ -5758,8 +5759,6 @@ int
hid_serv_acting_as_directory(void)
{
routerinfo_t *me = router_get_my_routerinfo();
networkstatus_t *c;
routerstatus_t *rs;
if (!me)
return 0;
if (!get_options()->HidServDirectoryV2) {
@ -5767,22 +5766,6 @@ hid_serv_acting_as_directory(void)
"because we have not been configured as such.");
return 0;
}
if (!(c = networkstatus_get_latest_consensus())) {
log_info(LD_REND, "There's no consensus, so I can't tell if I'm a hidden "
"service directory");
return 0;
}
rs = networkstatus_vote_find_entry(c, me->cache_info.identity_digest);
if (!rs) {
log_info(LD_REND, "We're not listed in the consensus, so we're not "
"being a hidden service directory.");
return 0;
}
if (!rs->is_hs_dir) {
log_info(LD_REND, "We're not listed as a hidden service directory in "
"the consensus, so we won't be one.");
return 0;
}
return 1;
}

View File

@ -1195,6 +1195,35 @@ test_util_listdir(void *ptr)
}
}
static void
test_util_parent_dir(void *ptr)
{
char *cp;
(void)ptr;
#define T(input,expect_ok,output) \
do { \
int ok; \
cp = tor_strdup(input); \
ok = get_parent_directory(cp); \
tt_int_op(ok, ==, expect_ok); \
if (ok==0) \
tt_str_op(cp, ==, output); \
tor_free(cp); \
} while (0);
T("/home/wombat/knish", 0, "/home/wombat");
T("/home/wombat/knish/", 0, "/home/wombat");
T("./home/wombat/knish/", 0, "./home/wombat");
T("./wombat", 0, ".");
T("", -1, "");
T("/", -1, "");
T("////", -1, "");
done:
tor_free(cp);
}
#ifdef MS_WINDOWS
static void
test_util_load_win_lib(void *ptr)
@ -1286,6 +1315,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(find_str_at_start_of_line, 0),
UTIL_TEST(asprintf, 0),
UTIL_TEST(listdir, 0),
UTIL_TEST(parent_dir, 0),
#ifdef MS_WINDOWS
UTIL_TEST(load_win_lib, 0),
#endif