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

📄 control.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    log_warn(LD_CONTROL,"Controller gave us config lines we can't parse.");
    connection_write_str_to_buf("551 Couldn't parse configuration\r\n",
                                conn);
    tor_free(config);
    return 0;
  }
  tor_free(config);

  if ((opt_err=options_trial_assign(lines, use_defaults,
                              clear_first, &errstring)) != SETOPT_OK) {
    const char *msg;
    log_warn(LD_CONTROL,
             "Controller gave us config lines that didn't validate: %s",
             errstring);
    switch (opt_err) {
      case SETOPT_ERR_MISC:
        msg = "552 Unrecognized option";
        break;
      case SETOPT_ERR_PARSE:
        msg = "513 Unacceptable option value";
        break;
      case SETOPT_ERR_TRANSITION:
        msg = "553 Transition not allowed";
        break;
      case SETOPT_ERR_SETTING:
      default:
        msg = "553 Unable to set option";
        break;
      case SETOPT_OK:
        msg = "551 Internal error";
        tor_fragile_assert();
        break;
    }
    connection_printf_to_buf(conn, "%s: %s\r\n", msg, errstring);
    config_free_lines(lines);
    tor_free(errstring);
    return 0;
  }
  config_free_lines(lines);
  send_control_done(conn);
  return 0;
}

/** Called when we receive a SETCONF message: parse the body and try
 * to update our configuration.  Reply with a DONE or ERROR message.
 * Modifies the contents of body.*/
static int
handle_control_setconf(control_connection_t *conn, uint32_t len, char *body)
{
  return control_setconf_helper(conn, len, body, 0);
}

/** Called when we receive a RESETCONF message: parse the body and try
 * to update our configuration.  Reply with a DONE or ERROR message.
 * Modifies the contents of body. */
static int
handle_control_resetconf(control_connection_t *conn, uint32_t len, char *body)
{
  return control_setconf_helper(conn, len, body, 1);
}

/** Called when we receive a GETCONF message.  Parse the request, and
 * reply with a CONFVALUE or an ERROR message */
static int
handle_control_getconf(control_connection_t *conn, uint32_t body_len,
                       const char *body)
{
  smartlist_t *questions = NULL;
  smartlist_t *answers = NULL;
  smartlist_t *unrecognized = NULL;
  char *msg = NULL;
  size_t msg_len;
  or_options_t *options = get_options();
  int i, len;

  questions = smartlist_create();
  (void) body_len; /* body is nul-terminated; so we can ignore len. */
  smartlist_split_string(questions, body, " ",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  answers = smartlist_create();
  unrecognized = smartlist_create();
  SMARTLIST_FOREACH(questions, char *, q,
  {
    if (!option_is_recognized(q)) {
      smartlist_add(unrecognized, q);
    } else {
      config_line_t *answer = option_get_assignment(options,q);
      if (!answer) {
        const char *name = option_get_canonical_name(q);
        size_t alen = strlen(name)+8;
        char *astr = tor_malloc(alen);
        tor_snprintf(astr, alen, "250-%s\r\n", name);
        smartlist_add(answers, astr);
      }

      while (answer) {
        config_line_t *next;
        size_t alen = strlen(answer->key)+strlen(answer->value)+8;
        char *astr = tor_malloc(alen);
        tor_snprintf(astr, alen, "250-%s=%s\r\n",
                     answer->key, answer->value);
        smartlist_add(answers, astr);

        next = answer->next;
        tor_free(answer->key);
        tor_free(answer->value);
        tor_free(answer);
        answer = next;
      }
    }
  });

  if ((len = smartlist_len(unrecognized))) {
    for (i=0; i < len-1; ++i)
      connection_printf_to_buf(conn,
                               "552-Unrecognized configuration key \"%s\"\r\n",
                               (char*)smartlist_get(unrecognized, i));
    connection_printf_to_buf(conn,
                             "552 Unrecognized configuration key \"%s\"\r\n",
                             (char*)smartlist_get(unrecognized, len-1));
  } else if ((len = smartlist_len(answers))) {
    char *tmp = smartlist_get(answers, len-1);
    tor_assert(strlen(tmp)>4);
    tmp[3] = ' ';
    msg = smartlist_join_strings(answers, "", 0, &msg_len);
    connection_write_to_buf(msg, msg_len, TO_CONN(conn));
  } else {
    connection_write_str_to_buf("250 OK\r\n", conn);
  }

  if (answers) {
    SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp));
    smartlist_free(answers);
  }
  if (questions) {
    SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp));
    smartlist_free(questions);
  }
  smartlist_free(unrecognized);
  tor_free(msg);

  return 0;
}

/** Called when we get a +LOADCONF message. */
static int
handle_control_loadconf(control_connection_t *conn, uint32_t len,
                         const char *body)
{
  setopt_err_t retval;
  char *errstring = NULL;
  const char *msg = NULL;
  (void) len;

  retval = options_init_from_string(body, CMD_RUN_TOR, NULL, &errstring);

  if (retval != SETOPT_OK) {
    log_warn(LD_CONTROL,
             "Controller gave us config file that didn't validate: %s",
             errstring);
    switch (retval) {
      case SETOPT_ERR_PARSE:
        msg = "552 Invalid config file";
        break;
      case SETOPT_ERR_TRANSITION:
        msg = "553 Transition not allowed";
        break;
      case SETOPT_ERR_SETTING:
        msg = "553 Unable to set option";
        break;
      case SETOPT_ERR_MISC:
      default:
        msg = "550 Unable to load config";
        break;
      case SETOPT_OK:
        tor_fragile_assert();
        break;
    }
    if (*errstring)
      connection_printf_to_buf(conn, "%s: %s\r\n", msg, errstring);
    else
      connection_printf_to_buf(conn, "%s\r\n", msg);
    tor_free(errstring);
    return 0;
  }
  send_control_done(conn);
  return 0;
}

/** Called when we get a SETEVENTS message: update conn->event_mask,
 * and reply with DONE or ERROR. */
static int
handle_control_setevents(control_connection_t *conn, uint32_t len,
                         const char *body)
{
  uint16_t event_code;
  uint32_t event_mask = 0;
  unsigned int extended = 0;
  smartlist_t *events = smartlist_create();

  (void) len;

  smartlist_split_string(events, body, " ",
                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  SMARTLIST_FOREACH(events, const char *, ev,
    {
      if (!strcasecmp(ev, "EXTENDED")) {
        extended = 1;
        continue;
      } else if (!strcasecmp(ev, "CIRC"))
        event_code = EVENT_CIRCUIT_STATUS;
      else if (!strcasecmp(ev, "STREAM"))
        event_code = EVENT_STREAM_STATUS;
      else if (!strcasecmp(ev, "ORCONN"))
        event_code = EVENT_OR_CONN_STATUS;
      else if (!strcasecmp(ev, "BW"))
        event_code = EVENT_BANDWIDTH_USED;
      else if (!strcasecmp(ev, "DEBUG"))
        event_code = EVENT_DEBUG_MSG;
      else if (!strcasecmp(ev, "INFO"))
        event_code = EVENT_INFO_MSG;
      else if (!strcasecmp(ev, "NOTICE"))
        event_code = EVENT_NOTICE_MSG;
      else if (!strcasecmp(ev, "WARN"))
        event_code = EVENT_WARN_MSG;
      else if (!strcasecmp(ev, "ERR"))
        event_code = EVENT_ERR_MSG;
      else if (!strcasecmp(ev, "NEWDESC"))
        event_code = EVENT_NEW_DESC;
      else if (!strcasecmp(ev, "ADDRMAP"))
        event_code = EVENT_ADDRMAP;
      else if (!strcasecmp(ev, "AUTHDIR_NEWDESCS"))
        event_code = EVENT_AUTHDIR_NEWDESCS;
      else if (!strcasecmp(ev, "DESCCHANGED"))
        event_code = EVENT_DESCCHANGED;
      else if (!strcasecmp(ev, "NS"))
        event_code = EVENT_NS;
      else if (!strcasecmp(ev, "STATUS_GENERAL"))
        event_code = EVENT_STATUS_GENERAL;
      else if (!strcasecmp(ev, "STATUS_CLIENT"))
        event_code = EVENT_STATUS_CLIENT;
      else if (!strcasecmp(ev, "STATUS_SERVER"))
        event_code = EVENT_STATUS_SERVER;
      else if (!strcasecmp(ev, "GUARD"))
        event_code = EVENT_GUARD;
      else if (!strcasecmp(ev, "GUARDS")) {
        /* XXXX021 This check is here to tolerate the controllers that
         * depended on the buggy spec in 0.1.2.5-alpha through 0.1.2.10-rc.
         * Once those versions are obsolete, stop supporting this. */
        log_warn(LD_CONTROL, "Controller used obsolete 'GUARDS' event name; "
                 "use GUARD instead.");
        event_code = EVENT_GUARD;
      } else if (!strcasecmp(ev, "STREAM_BW"))
        event_code = EVENT_STREAM_BANDWIDTH_USED;
      else {
        connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
                                 ev);
        SMARTLIST_FOREACH(events, char *, e, tor_free(e));
        smartlist_free(events);
        return 0;
      }
      event_mask |= (1 << event_code);
    });
  SMARTLIST_FOREACH(events, char *, e, tor_free(e));
  smartlist_free(events);

  conn->event_mask = event_mask;
  if (extended)
    conn->use_extended_events = 1;

  control_update_global_event_mask();
  send_control_done(conn);
  return 0;
}

/** Decode the hashed, base64'd passwords stored in <b>passwords</b>.
 * Return a smartlist of acceptable passwords (unterminated strings of
 * length S2K_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on failure.
 */
smartlist_t *
decode_hashed_passwords(config_line_t *passwords)
{
  char decoded[64];
  config_line_t *cl;
  smartlist_t *sl = smartlist_create();

  tor_assert(passwords);

  for (cl = passwords; cl; cl = cl->next) {
    const char *hashed = cl->value;

    if (!strcmpstart(hashed, "16:")) {
      if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))<0
          || strlen(hashed+3) != (S2K_SPECIFIER_LEN+DIGEST_LEN)*2) {
        goto err;
      }
    } else {
        if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
            != S2K_SPECIFIER_LEN+DIGEST_LEN) {
          goto err;
        }
    }
    smartlist_add(sl, tor_memdup(decoded, S2K_SPECIFIER_LEN+DIGEST_LEN));
  }

  return sl;

 err:
  SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
  smartlist_free(sl);
  return NULL;
}

/** Called when we get an AUTHENTICATE message.  Check whether the
 * authentication is valid, and if so, update the connection's state to
 * OPEN.  Reply with DONE or ERROR.
 */
static int
handle_control_authenticate(control_connection_t *conn, uint32_t len,
                            const char *body)
{
  int used_quoted_string = 0;
  or_options_t *options = get_options();
  const char *errstr = NULL;
  char *password;
  size_t password_len;
  const char *cp;
  int i;
  int bad_cookie=0, bad_password=0;
  smartlist_t *sl = NULL;

  if (TOR_ISXDIGIT(body[0])) {
    cp = body;
    while (TOR_ISXDIGIT(*cp))
      ++cp;
    i = (int)(cp - body);
    tor_assert(i>0);
    password_len = i/2;
    password = tor_malloc(password_len + 1);
    if (base16_decode(password, password_len+1, body, i)<0) {
      connection_write_str_to_buf(
            "551 Invalid hexadecimal encoding.  Maybe you tried a plain text "
            "password?  If so, the standard requires that you put it in "
            "double quotes.\r\n", conn);
      connection_mark_for_close(TO_CONN(conn));
      tor_free(password);
      return 0;
    }
  } else if (TOR_ISSPACE(body[0])) {
    password = tor_strdup("");
    password_len = 0;
  } else {
    if (!decode_escaped_string(body, len, &password, &password_len)) {
      connection_write_str_to_buf("551 Invalid quoted string.  You need "
            "to put the password in double quotes.\r\n", conn);
      connection_mark_for_close(TO_CONN(conn));
      return 0;
    }
    used_quoted_string = 1;
  }

  if (!options->CookieAuthentication && !options->HashedControlPassword &&
      !options->HashedControlSessionPassword) {
    /* if Tor doesn't demand any stronger authentication, then
     * the controller can get in with anything. */

⌨️ 快捷键说明

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