/* Helper for disk_state_load_from_disk(). */ STATIC int disk_state_load_from_disk_impl(const char *fname) { int ret; char *content = NULL; sr_state_t *parsed_state = NULL; sr_disk_state_t *disk_state = NULL; /* Read content of file so we can parse it. */ if ((content = read_file_to_str(fname, 0, NULL)) == NULL) { log_warn(LD_FS, "SR: Unable to read SR state file %s", escaped(fname)); ret = -errno; goto error; } { config_line_t *lines = NULL; char *errmsg = NULL; /* Every error in this code path will return EINVAL. */ ret = -EINVAL; if (config_get_lines(content, &lines, 0) < 0) { config_free_lines(lines); goto error; } disk_state = disk_state_new(time(NULL)); config_assign(&state_format, disk_state, lines, 0, &errmsg); config_free_lines(lines); if (errmsg) { log_warn(LD_DIR, "SR: Reading state error: %s", errmsg); tor_free(errmsg); goto error; } } /* So far so good, we've loaded our state file into our disk state. Let's * validate it and then parse it. */ if (disk_state_validate(disk_state) < 0) { ret = -EINVAL; goto error; } parsed_state = disk_state_parse(disk_state); if (parsed_state == NULL) { ret = -EINVAL; goto error; } state_set(parsed_state); disk_state_set(disk_state); tor_free(content); log_info(LD_DIR, "SR: State loaded successfully from file %s", fname); return 0; error: disk_state_free(disk_state); tor_free(content); return ret; }
static void test_config_addressmap(void *arg) { char buf[1024]; char address[256]; time_t expires = TIME_MAX; (void)arg; strlcpy(buf, "MapAddress .invalidwildcard.com *.torserver.exit\n" // invalid "MapAddress *invalidasterisk.com *.torserver.exit\n" // invalid "MapAddress *.google.com *.torserver.exit\n" "MapAddress *.yahoo.com *.google.com.torserver.exit\n" "MapAddress *.cn.com www.cnn.com\n" "MapAddress *.cnn.com www.cnn.com\n" "MapAddress ex.com www.cnn.com\n" "MapAddress ey.com *.cnn.com\n" "MapAddress www.torproject.org 1.1.1.1\n" "MapAddress other.torproject.org " "this.torproject.org.otherserver.exit\n" "MapAddress test.torproject.org 2.2.2.2\n" "MapAddress www.google.com 3.3.3.3\n" "MapAddress www.example.org 4.4.4.4\n" "MapAddress 4.4.4.4 7.7.7.7\n" "MapAddress 4.4.4.4 5.5.5.5\n" "MapAddress www.infiniteloop.org 6.6.6.6\n" "MapAddress 6.6.6.6 www.infiniteloop.org\n" , sizeof(buf)); config_get_lines(buf, &(get_options_mutable()->AddressMap), 0); config_register_addressmaps(get_options()); /* MapAddress .invalidwildcard.com .torserver.exit - no match */ strlcpy(address, "www.invalidwildcard.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* MapAddress *invalidasterisk.com .torserver.exit - no match */ strlcpy(address, "www.invalidasterisk.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Where no mapping for FQDN match on top-level domain */ /* MapAddress .google.com .torserver.exit */ strlcpy(address, "reader.google.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "reader.torserver.exit"); /* MapAddress *.yahoo.com *.google.com.torserver.exit */ strlcpy(address, "reader.yahoo.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "reader.google.com.torserver.exit"); /*MapAddress *.cnn.com www.cnn.com */ strlcpy(address, "cnn.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "www.cnn.com"); /* MapAddress .cn.com www.cnn.com */ strlcpy(address, "www.cn.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "www.cnn.com"); /* MapAddress ex.com www.cnn.com - no match */ strlcpy(address, "www.ex.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* MapAddress ey.com *.cnn.com - invalid expression */ strlcpy(address, "ey.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Where mapping for FQDN match on FQDN */ strlcpy(address, "www.google.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "3.3.3.3"); strlcpy(address, "www.torproject.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "1.1.1.1"); strlcpy(address, "other.torproject.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "this.torproject.org.otherserver.exit"); strlcpy(address, "test.torproject.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "2.2.2.2"); /* Test a chain of address mappings and the order in which they were added: "MapAddress www.example.org 4.4.4.4" "MapAddress 4.4.4.4 7.7.7.7" "MapAddress 4.4.4.4 5.5.5.5" */ strlcpy(address, "www.example.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "5.5.5.5"); /* Test infinite address mapping results in no change */ strlcpy(address, "www.infiniteloop.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "www.infiniteloop.org"); /* Test we don't find false positives */ strlcpy(address, "www.example.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); /* Test top-level-domain matching a bit harder */ addressmap_clear_configured(); strlcpy(buf, "MapAddress *.com *.torserver.exit\n" "MapAddress *.torproject.org 1.1.1.1\n" "MapAddress *.net 2.2.2.2\n" , sizeof(buf)); config_get_lines(buf, &(get_options_mutable()->AddressMap), 0); config_register_addressmaps(get_options()); strlcpy(address, "www.abc.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "www.abc.torserver.exit"); strlcpy(address, "www.def.com", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "www.def.torserver.exit"); strlcpy(address, "www.torproject.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "1.1.1.1"); strlcpy(address, "test.torproject.org", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "1.1.1.1"); strlcpy(address, "torproject.net", sizeof(address)); test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL)); test_streq(address, "2.2.2.2"); /* We don't support '*' as a mapping directive */ addressmap_clear_configured(); strlcpy(buf, "MapAddress * *.torserver.exit\n", sizeof(buf)); config_get_lines(buf, &(get_options_mutable()->AddressMap), 0); config_register_addressmaps(get_options()); strlcpy(address, "www.abc.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); strlcpy(address, "www.def.net", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); strlcpy(address, "www.torproject.org", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); done: ; }
/** Reload the persistent state from disk, generating a new state as needed. * Return 0 on success, less than 0 on failure. */ int or_state_load(void) { or_state_t *new_state = NULL; char *contents = NULL, *fname; char *errmsg = NULL; int r = -1, badstate = 0; fname = get_datadir_fname("state"); switch (file_status(fname)) { case FN_FILE: if (!(contents = read_file_to_str(fname, 0, NULL))) { log_warn(LD_FS, "Unable to read state file \"%s\"", fname); goto done; } break; case FN_NOENT: break; case FN_ERROR: case FN_DIR: default: log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname); goto done; } new_state = tor_malloc_zero(sizeof(or_state_t)); new_state->_magic = OR_STATE_MAGIC; config_init(&state_format, new_state); if (contents) { config_line_t *lines=NULL; int assign_retval; if (config_get_lines(contents, &lines, 0)<0) goto done; assign_retval = config_assign(&state_format, new_state, lines, 0, 0, &errmsg); config_free_lines(lines); if (assign_retval<0) badstate = 1; if (errmsg) { log_warn(LD_GENERAL, "%s", errmsg); tor_free(errmsg); } } if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0) badstate = 1; if (errmsg) { log_warn(LD_GENERAL, "%s", errmsg); tor_free(errmsg); } if (badstate && !contents) { log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state." " This is a bug in Tor."); goto done; } else if (badstate && contents) { or_state_save_broken(fname); tor_free(contents); config_free(&state_format, new_state); new_state = tor_malloc_zero(sizeof(or_state_t)); new_state->_magic = OR_STATE_MAGIC; config_init(&state_format, new_state); } else if (contents) { log_info(LD_GENERAL, "Loaded state from \"%s\"", fname); } else { log_info(LD_GENERAL, "Initialized state"); } if (or_state_set(new_state) == -1) { or_state_save_broken(fname); } new_state = NULL; if (!contents) { global_state->next_write = 0; or_state_save(time(NULL)); } r = 0; done: tor_free(fname); tor_free(contents); if (new_state) config_free(&state_format, new_state); return r; }