⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 control.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    goto ok;
  }

  if (options->CookieAuthentication) {
    int also_password = options->HashedControlPassword != NULL ||
      options->HashedControlSessionPassword != NULL;
    if (password_len != AUTHENTICATION_COOKIE_LEN) {
      if (!also_password) {
        log_warn(LD_CONTROL, "Got authentication cookie with wrong length "
                 "(%d)", (int)password_len);
        errstr = "Wrong length on authentication cookie.";
        goto err;
      }
      bad_cookie = 1;
    } else if (memcmp(authentication_cookie, password, password_len)) {
      if (!also_password) {
        log_warn(LD_CONTROL, "Got mismatched authentication cookie");
        errstr = "Authentication cookie did not match expected value.";
        goto err;
      }
      bad_cookie = 1;
    } else {
      goto ok;
    }
  }

  if (options->HashedControlPassword ||
      options->HashedControlSessionPassword) {
    int bad = 0;
    smartlist_t *sl_tmp;
    char received[DIGEST_LEN];
    int also_cookie = options->CookieAuthentication;
    sl = smartlist_create();
    if (options->HashedControlPassword) {
      sl_tmp = decode_hashed_passwords(options->HashedControlPassword);
      if (!sl_tmp)
        bad = 1;
      else {
        smartlist_add_all(sl, sl_tmp);
        smartlist_free(sl_tmp);
      }
    }
    if (options->HashedControlSessionPassword) {
      sl_tmp = decode_hashed_passwords(options->HashedControlSessionPassword);
      if (!sl_tmp)
        bad = 1;
      else {
        smartlist_add_all(sl, sl_tmp);
        smartlist_free(sl_tmp);
      }
    }
    if (bad) {
      if (!also_cookie) {
        log_warn(LD_CONTROL,
                 "Couldn't decode HashedControlPassword: invalid base16");
        errstr="Couldn't decode HashedControlPassword value in configuration.";
      }
      bad_password = 1;
      SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
      smartlist_free(sl);
    } else {
      SMARTLIST_FOREACH(sl, char *, expected,
      {
        secret_to_key(received,DIGEST_LEN,password,password_len,expected);
        if (!memcmp(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN))
          goto ok;
      });
      SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
      smartlist_free(sl);

      if (used_quoted_string)
        errstr = "Password did not match HashedControlPassword value from "
          "configuration";
      else
        errstr = "Password did not match HashedControlPassword value from "
          "configuration. Maybe you tried a plain text password? "
          "If so, the standard requires that you put it in double quotes.";
      bad_password = 1;
      if (!also_cookie)
        goto err;
    }
  }

  /** We only get here if both kinds of authentication failed. */
  tor_assert(bad_password && bad_cookie);
  log_warn(LD_CONTROL, "Bad password or authentication cookie on controller.");
  errstr = "Password did not match HashedControlPassword *or* authentication "
    "cookie.";

 err:
  tor_free(password);
  if (!errstr)
    errstr = "Unknown reason.";
  connection_printf_to_buf(conn, "515 Authentication failed: %s\r\n",
                           errstr);
  connection_mark_for_close(TO_CONN(conn));
  return 0;
 ok:
  log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->_base.s);
  send_control_done(conn);
  conn->_base.state = CONTROL_CONN_STATE_OPEN;
  tor_free(password);
  if (sl) { /* clean up */
    SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
    smartlist_free(sl);
  }
  return 0;
}

/** Called when we get a SAVECONF command. Try to flush the current options to
 * disk, and report success or failure. */
static int
handle_control_saveconf(control_connection_t *conn, uint32_t len,
                        const char *body)
{
  (void) len;
  (void) body;
  if (options_save_current()<0) {
    connection_write_str_to_buf(
      "551 Unable to write configuration to disk.\r\n", conn);
  } else {
    send_control_done(conn);
  }
  return 0;
}

/** Called when we get a SIGNAL command. React to the provided signal, and
 * report success or failure. (If the signal results in a shutdown, success
 * may not be reported.) */
static int
handle_control_signal(control_connection_t *conn, uint32_t len,
                      const char *body)
{
  int sig;
  int n = 0;
  char *s;

  (void) len;

  while (body[n] && ! TOR_ISSPACE(body[n]))
    ++n;
  s = tor_strndup(body, n);
  if (!strcasecmp(s, "RELOAD") || !strcasecmp(s, "HUP"))
    sig = SIGHUP;
  else if (!strcasecmp(s, "SHUTDOWN") || !strcasecmp(s, "INT"))
    sig = SIGINT;
  else if (!strcasecmp(s, "DUMP") || !strcasecmp(s, "USR1"))
    sig = SIGUSR1;
  else if (!strcasecmp(s, "DEBUG") || !strcasecmp(s, "USR2"))
    sig = SIGUSR2;
  else if (!strcasecmp(s, "HALT") || !strcasecmp(s, "TERM"))
    sig = SIGTERM;
  else if (!strcasecmp(s, "NEWNYM"))
    sig = SIGNEWNYM;
  else if (!strcasecmp(s, "CLEARDNSCACHE"))
    sig = SIGCLEARDNSCACHE;
  else {
    connection_printf_to_buf(conn, "552 Unrecognized signal code \"%s\"\r\n",
                             s);
    sig = -1;
  }
  tor_free(s);
  if (sig<0)
    return 0;

  send_control_done(conn);
  /* Flush the "done" first if the signal might make us shut down. */
  if (sig == SIGTERM || sig == SIGINT)
    connection_handle_write(TO_CONN(conn), 1);
  control_signal_act(sig);
  return 0;
}

/** Called when we get a MAPADDRESS command; try to bind all listed addresses,
 * and report success or failrue. */
static int
handle_control_mapaddress(control_connection_t *conn, uint32_t len,
                          const char *body)
{
  smartlist_t *elts;
  smartlist_t *lines;
  smartlist_t *reply;
  char *r;
  size_t sz;
  (void) len; /* body is nul-terminated, so it's safe to ignore the length. */

  lines = smartlist_create();
  elts = smartlist_create();
  reply = smartlist_create();
  smartlist_split_string(lines, body, " ",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  SMARTLIST_FOREACH(lines, char *, line,
  {
    tor_strlower(line);
    smartlist_split_string(elts, line, "=", 0, 2);
    if (smartlist_len(elts) == 2) {
      const char *from = smartlist_get(elts,0);
      const char *to = smartlist_get(elts,1);
      size_t anslen = strlen(line)+512;
      char *ans = tor_malloc(anslen);
      if (address_is_invalid_destination(to, 1)) {
        tor_snprintf(ans, anslen,
                     "512-syntax error: invalid address '%s'", to);
        smartlist_add(reply, ans);
        log_warn(LD_CONTROL,
                 "Skipping invalid argument '%s' in MapAddress msg", to);
      } else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0")) {
        const char *address = addressmap_register_virtual_address(
              !strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4,
               tor_strdup(to));
        if (!address) {
          tor_snprintf(ans, anslen,
                       "451-resource exhausted: skipping '%s'", line);
          smartlist_add(reply, ans);
          log_warn(LD_CONTROL,
                   "Unable to allocate address for '%s' in MapAddress msg",
                   safe_str(line));
        } else {
          tor_snprintf(ans, anslen, "250-%s=%s", address, to);
          smartlist_add(reply, ans);
        }
      } else {
        addressmap_register(from, tor_strdup(to), 1, ADDRMAPSRC_CONTROLLER);
        tor_snprintf(ans, anslen, "250-%s", line);
        smartlist_add(reply, ans);
      }
    } else {
      size_t anslen = strlen(line)+256;
      char *ans = tor_malloc(anslen);
      tor_snprintf(ans, anslen, "512-syntax error: mapping '%s' is "
                   "not of expected form 'foo=bar'.", line);
      smartlist_add(reply, ans);
      log_info(LD_CONTROL, "Skipping MapAddress '%s': wrong "
                           "number of items.", safe_str(line));
    }
    SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
    smartlist_clear(elts);
  });
  SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
  smartlist_free(lines);
  smartlist_free(elts);

  if (smartlist_len(reply)) {
    ((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
    r = smartlist_join_strings(reply, "\r\n", 1, &sz);
    connection_write_to_buf(r, sz, TO_CONN(conn));
    tor_free(r);
  } else {
    const char *response =
      "512 syntax error: not enough arguments to mapaddress.\r\n";
    connection_write_to_buf(response, strlen(response), TO_CONN(conn));
  }

  SMARTLIST_FOREACH(reply, char *, cp, tor_free(cp));
  smartlist_free(reply);
  return 0;
}

/** Implementation helper for GETINFO: knows the answers for various
 * trivial-to-implement questions. */
static int
getinfo_helper_misc(control_connection_t *conn, const char *question,
                    char **answer)
{
  (void) conn;
  if (!strcmp(question, "version")) {
    *answer = tor_strdup(get_version());
  } else if (!strcmp(question, "config-file")) {
    *answer = tor_strdup(get_torrc_fname());
  } else if (!strcmp(question, "info/names")) {
    *answer = list_getinfo_options();
  } else if (!strcmp(question, "events/names")) {
    *answer = tor_strdup("CIRC STREAM ORCONN BW DEBUG INFO NOTICE WARN ERR "
                         "NEWDESC ADDRMAP AUTHDIR_NEWDESCS DESCCHANGED "
                         "NS STATUS_GENERAL STATUS_CLIENT STATUS_SERVER "
                         "GUARD STREAM_BW");
  } else if (!strcmp(question, "features/names")) {
    *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
  } else if (!strcmp(question, "address")) {
    uint32_t addr;
    if (router_pick_published_address(get_options(), &addr) < 0)
      return -1;
    *answer = tor_dup_addr(addr);
  } else if (!strcmp(question, "dir-usage")) {
    *answer = directory_dump_request_log();
  } else if (!strcmp(question, "fingerprint")) {
    routerinfo_t *me = router_get_my_routerinfo();
    if (!me)
      return -1;
    *answer = tor_malloc(HEX_DIGEST_LEN+1);
    base16_encode(*answer, HEX_DIGEST_LEN+1, me->cache_info.identity_digest,
                  DIGEST_LEN);
  }
  return 0;
}

/** Awful hack: return a newly allocated string based on a routerinfo and
 * (possibly) an extrainfo, sticking the read-history and write-history from
 * <b>ei</b> into the resulting string.  The thing you get back won't
 * necessarily have a valid signature.
 *
 * New code should never use this; it's for backward compatibiliy.
 *
 * NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
 * not be NUL-terminated. */
static char *
munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri,
                                signed_descriptor_t *ei)
{
  char *out = NULL, *outp;
  int i;
  const char *router_sig;
  const char *ei_body = signed_descriptor_get_body(ei);
  size_t ri_len = ri->signed_descriptor_len;
  size_t ei_len = ei->signed_descriptor_len;
  if (!ei_body)
    goto bail;

  outp = out = tor_malloc(ri_len+ei_len+1);
  if (!(router_sig = tor_memstr(ri_body, ri_len, "\nrouter-signature")))
    goto bail;
  ++router_sig;
  memcpy(out, ri_body, router_sig-ri_body);
  outp += router_sig-ri_body;

  for (i=0; i < 2; ++i) {
    const char *kwd = i?"\nwrite-history ":"\nread-history ";
    const char *cp, *eol;
    if (!(cp = tor_memstr(ei_body, ei_len, kwd)))
      continue;
    ++cp;
    eol = memchr(cp, '\n', ei_len - (cp-ei_body));
    memcpy(outp, cp, eol-cp+1);
    outp += eol-cp+1;
  }
  memcpy(outp, router_sig, ri_len - (router_sig-ri_body));
  *outp++ = '\0';
  tor_assert(outp-out < (int)(ri_len+ei_len+1));

  return out;
 bail:
  tor_free(out);
  return tor_strndup(ri_body, ri->signed_descriptor_len);
}

/** Implementation helper for GETINFO: knows the answers for questions about
 * directory information. */
static int
getinfo_helper_dir(control_connection_t *control_conn,
                   const char *question, char **answer)
{
  if (!strcmpstart(question, "desc/id/")) {
    routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
    if (ri) {
      const char *body = signed_descriptor_get_body(&ri->cache_info);
      if (body)
        *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
    }
  } else if (!strcmpstart(question, "desc/name/")) {
    routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
    if (ri) {
      const char *body = signed_descriptor_get_body(&ri->cache_info);
      if (body)
        *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -