2007-12-12 21:09:01 +00:00
|
|
|
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2019-01-16 12:33:22 -05:00
|
|
|
* Copyright (c) 2007-2019, The Tor Project, Inc. */
|
2004-11-03 01:32:26 +00:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
2004-11-07 21:37:50 +00:00
|
|
|
/**
|
2004-11-30 06:17:35 +00:00
|
|
|
* \file control.c
|
|
|
|
* \brief Implementation for Tor's control-socket interface.
|
2016-10-14 20:08:51 -04:00
|
|
|
*
|
|
|
|
* A "controller" is an external program that monitors and controls a Tor
|
|
|
|
* instance via a text-based protocol. It connects to Tor via a connection
|
|
|
|
* to a local socket.
|
|
|
|
*
|
|
|
|
* The protocol is line-driven. The controller sends commands terminated by a
|
|
|
|
* CRLF. Tor sends lines that are either <em>replies</em> to what the
|
|
|
|
* controller has said, or <em>events</em> that Tor sends to the controller
|
|
|
|
* asynchronously based on occurrences in the Tor network model.
|
|
|
|
*
|
|
|
|
* See the control-spec.txt file in the torspec.git repository for full
|
|
|
|
* details on protocol.
|
|
|
|
*
|
|
|
|
* This module generally has two kinds of entry points: those based on having
|
|
|
|
* received a command on a controller socket, which are handled in
|
|
|
|
* connection_control_process_inbuf(), and dispatched to individual functions
|
|
|
|
* with names like control_handle_COMMANDNAME(); and those based on events
|
|
|
|
* that occur elsewhere in Tor, which are handled by functions with names like
|
|
|
|
* control_event_EVENTTYPE().
|
|
|
|
*
|
|
|
|
* Controller events are not sent immediately; rather, they are inserted into
|
|
|
|
* the queued_control_events array, and flushed later from
|
|
|
|
* flush_queued_events_cb(). Doing this simplifies our callgraph greatly,
|
|
|
|
* by limiting the number of places in Tor that can call back into the network
|
|
|
|
* stack.
|
2005-06-11 05:31:17 +00:00
|
|
|
**/
|
2004-11-07 21:37:50 +00:00
|
|
|
|
2019-03-25 12:11:59 -04:00
|
|
|
#define CONTROL_MODULE_PRIVATE
|
|
|
|
#define CONTROL_EVENTS_PRIVATE
|
2018-12-16 17:01:25 -06:00
|
|
|
#define OCIRC_EVENT_PRIVATE
|
2007-04-11 13:18:25 +00:00
|
|
|
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "core/or/or.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "app/config/config.h"
|
|
|
|
#include "app/config/confparse.h"
|
|
|
|
#include "app/main/main.h"
|
|
|
|
#include "core/mainloop/connection.h"
|
|
|
|
#include "core/mainloop/mainloop.h"
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "core/or/channel.h"
|
|
|
|
#include "core/or/channeltls.h"
|
|
|
|
#include "core/or/circuitbuild.h"
|
|
|
|
#include "core/or/circuitlist.h"
|
|
|
|
#include "core/or/circuitstats.h"
|
|
|
|
#include "core/or/circuituse.h"
|
|
|
|
#include "core/or/command.h"
|
|
|
|
#include "core/or/connection_edge.h"
|
|
|
|
#include "core/or/connection_or.h"
|
2018-12-16 17:01:25 -06:00
|
|
|
#include "core/or/ocirc_event.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "core/or/policies.h"
|
|
|
|
#include "core/or/reasons.h"
|
2018-10-01 11:22:47 -05:00
|
|
|
#include "core/or/versions.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "core/proto/proto_control0.h"
|
|
|
|
#include "core/proto/proto_http.h"
|
|
|
|
#include "feature/client/addressmap.h"
|
|
|
|
#include "feature/client/bridges.h"
|
|
|
|
#include "feature/client/dnsserv.h"
|
|
|
|
#include "feature/client/entrynodes.h"
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "feature/control/control.h"
|
2019-03-25 14:03:49 -04:00
|
|
|
#include "feature/control/control_auth.h"
|
|
|
|
#include "feature/control/control_cmd.h"
|
2019-03-25 12:11:59 -04:00
|
|
|
#include "feature/control/control_events.h"
|
|
|
|
#include "feature/control/control_fmt.h"
|
2019-03-25 12:48:52 -04:00
|
|
|
#include "feature/control/control_getinfo.h"
|
2018-09-20 08:09:35 -04:00
|
|
|
#include "feature/control/fmt_serverstatus.h"
|
2018-09-27 09:35:47 -04:00
|
|
|
#include "feature/control/getinfo_geoip.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "feature/dircache/dirserv.h"
|
2018-09-21 10:26:57 -04:00
|
|
|
#include "feature/dirclient/dirclient.h"
|
|
|
|
#include "feature/dirclient/dlstatus.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "feature/dircommon/directory.h"
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "feature/hibernate/hibernate.h"
|
|
|
|
#include "feature/hs/hs_cache.h"
|
|
|
|
#include "feature/hs/hs_common.h"
|
|
|
|
#include "feature/hs/hs_control.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "feature/hs_common/shared_random_client.h"
|
|
|
|
#include "feature/nodelist/authcert.h"
|
|
|
|
#include "feature/nodelist/dirlist.h"
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "feature/nodelist/microdesc.h"
|
|
|
|
#include "feature/nodelist/networkstatus.h"
|
|
|
|
#include "feature/nodelist/nodelist.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "feature/nodelist/routerinfo.h"
|
|
|
|
#include "feature/nodelist/routerlist.h"
|
|
|
|
#include "feature/relay/router.h"
|
|
|
|
#include "feature/relay/routermode.h"
|
|
|
|
#include "feature/relay/selftest.h"
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "feature/rend/rendclient.h"
|
|
|
|
#include "feature/rend/rendcommon.h"
|
2018-09-30 23:31:59 -05:00
|
|
|
#include "feature/rend/rendparse.h"
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "feature/rend/rendservice.h"
|
2018-09-27 09:35:47 -04:00
|
|
|
#include "feature/stats/geoip_stats.h"
|
2018-09-27 08:21:17 -04:00
|
|
|
#include "feature/stats/predict_ports.h"
|
2018-11-06 18:05:14 -05:00
|
|
|
#include "lib/buf/buffers.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "lib/crypt_ops/crypto_rand.h"
|
|
|
|
#include "lib/crypt_ops/crypto_util.h"
|
2018-07-01 11:32:11 -04:00
|
|
|
#include "lib/encoding/confline.h"
|
2018-09-25 17:57:58 -04:00
|
|
|
#include "lib/evloop/compat_libevent.h"
|
2018-11-01 12:33:22 -04:00
|
|
|
#include "lib/version/torversion.h"
|
2004-11-03 01:32:26 +00:00
|
|
|
|
2018-07-05 16:34:59 -04:00
|
|
|
#include "feature/dircache/cached_dir_st.h"
|
|
|
|
#include "feature/control/control_connection_st.h"
|
|
|
|
#include "core/or/cpath_build_state_st.h"
|
|
|
|
#include "core/or/entry_connection_st.h"
|
|
|
|
#include "feature/nodelist/extrainfo_st.h"
|
|
|
|
#include "feature/nodelist/networkstatus_st.h"
|
|
|
|
#include "feature/nodelist/node_st.h"
|
|
|
|
#include "core/or/or_connection_st.h"
|
|
|
|
#include "core/or/or_circuit_st.h"
|
|
|
|
#include "core/or/origin_circuit_st.h"
|
|
|
|
#include "feature/nodelist/microdesc_st.h"
|
|
|
|
#include "feature/rend/rend_authorized_client_st.h"
|
|
|
|
#include "feature/rend/rend_encoded_v2_service_descriptor_st.h"
|
|
|
|
#include "feature/rend/rend_service_descriptor_st.h"
|
|
|
|
#include "feature/nodelist/routerinfo_st.h"
|
|
|
|
#include "feature/nodelist/routerlist_st.h"
|
|
|
|
#include "core/or/socks_request_st.h"
|
2018-06-15 10:07:17 -04:00
|
|
|
|
2018-07-01 15:02:01 -04:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
|
|
|
|
2012-01-31 10:59:42 -05:00
|
|
|
#ifndef _WIN32
|
2010-12-22 09:15:24 -08:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#endif
|
|
|
|
|
2018-06-21 12:47:11 -04:00
|
|
|
#include "lib/crypt_ops/crypto_s2k.h"
|
2018-07-05 15:14:04 -04:00
|
|
|
#include "lib/evloop/procmon.h"
|
|
|
|
#include "lib/evloop/compat_libevent.h"
|
2011-05-15 08:23:04 -07:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
/** Convert a connection_t* to an control_connection_t*; assert if the cast is
|
|
|
|
* invalid. */
|
|
|
|
control_connection_t *
|
|
|
|
TO_CONTROL_CONN(connection_t *c)
|
2013-10-21 13:02:25 -04:00
|
|
|
{
|
2019-03-25 14:03:49 -04:00
|
|
|
tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
|
|
|
|
return DOWNCAST(control_connection_t, c);
|
2013-10-21 13:02:25 -04:00
|
|
|
}
|
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
/** Create and add a new controller connection on <b>sock</b>. If
|
|
|
|
* <b>CC_LOCAL_FD_IS_OWNER</b> is set in <b>flags</b>, this Tor process should
|
|
|
|
* exit when the connection closes. If <b>CC_LOCAL_FD_IS_AUTHENTICATED</b>
|
|
|
|
* is set, then the connection does not need to authenticate.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
control_connection_add_local_fd(tor_socket_t sock, unsigned flags)
|
2015-02-19 14:53:41 -05:00
|
|
|
{
|
2019-03-25 14:03:49 -04:00
|
|
|
if (BUG(! SOCKET_OK(sock)))
|
|
|
|
return -1;
|
|
|
|
const int is_owner = !!(flags & CC_LOCAL_FD_IS_OWNER);
|
|
|
|
const int is_authenticated = !!(flags & CC_LOCAL_FD_IS_AUTHENTICATED);
|
|
|
|
control_connection_t *control_conn = control_connection_new(AF_UNSPEC);
|
|
|
|
connection_t *conn = TO_CONN(control_conn);
|
|
|
|
conn->s = sock;
|
|
|
|
tor_addr_make_unspec(&conn->addr);
|
|
|
|
conn->port = 1;
|
|
|
|
conn->address = tor_strdup("<local socket>");
|
2015-04-27 15:08:31 -04:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
/* We take ownership of this socket so that later, when we close it,
|
|
|
|
* we don't freak out. */
|
|
|
|
tor_take_socket_ownership(sock);
|
2015-04-27 15:08:31 -04:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
if (set_socket_nonblocking(sock) < 0 ||
|
|
|
|
connection_add(conn) < 0) {
|
|
|
|
connection_free(conn);
|
|
|
|
return -1;
|
2019-01-14 14:09:53 -05:00
|
|
|
}
|
2015-03-10 16:46:56 -04:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
control_conn->is_owning_control_connection = is_owner;
|
2015-03-22 13:31:53 +00:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
if (connection_init_accepted_conn(conn, NULL) < 0) {
|
|
|
|
connection_mark_for_close(conn);
|
|
|
|
return -1;
|
2017-11-15 14:52:24 -05:00
|
|
|
}
|
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
if (is_authenticated) {
|
|
|
|
conn->state = CONTROL_CONN_STATE_OPEN;
|
2015-03-22 13:31:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
/** Write all of the open control ports to ControlPortWriteToFile */
|
|
|
|
void
|
|
|
|
control_ports_write_to_file(void)
|
2015-04-25 08:23:15 +00:00
|
|
|
{
|
2019-03-25 14:03:49 -04:00
|
|
|
smartlist_t *lines;
|
|
|
|
char *joined = NULL;
|
|
|
|
const or_options_t *options = get_options();
|
2015-04-13 21:08:31 -06:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
if (!options->ControlPortWriteToFile)
|
|
|
|
return;
|
2015-04-25 08:23:15 +00:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
lines = smartlist_new();
|
2015-04-25 08:23:15 +00:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
SMARTLIST_FOREACH_BEGIN(get_connection_array(), const connection_t *, conn) {
|
|
|
|
if (conn->type != CONN_TYPE_CONTROL_LISTENER || conn->marked_for_close)
|
|
|
|
continue;
|
|
|
|
#ifdef AF_UNIX
|
|
|
|
if (conn->socket_family == AF_UNIX) {
|
|
|
|
smartlist_add_asprintf(lines, "UNIX_PORT=%s\n", conn->address);
|
|
|
|
continue;
|
2015-04-25 08:23:15 +00:00
|
|
|
}
|
2019-03-25 14:03:49 -04:00
|
|
|
#endif /* defined(AF_UNIX) */
|
|
|
|
smartlist_add_asprintf(lines, "PORT=%s:%d\n", conn->address, conn->port);
|
|
|
|
} SMARTLIST_FOREACH_END(conn);
|
2015-04-25 08:23:15 +00:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
joined = smartlist_join_strings(lines, "", 0, NULL);
|
2015-04-25 08:23:15 +00:00
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
if (write_str_to_file(options->ControlPortWriteToFile, joined, 0) < 0) {
|
|
|
|
log_warn(LD_CONTROL, "Writing %s failed: %s",
|
|
|
|
options->ControlPortWriteToFile, strerror(errno));
|
2015-04-13 21:08:31 -06:00
|
|
|
}
|
2019-03-25 14:03:49 -04:00
|
|
|
#ifndef _WIN32
|
|
|
|
if (options->ControlPortFileGroupReadable) {
|
|
|
|
if (chmod(options->ControlPortWriteToFile, 0640)) {
|
|
|
|
log_warn(LD_FS,"Unable to make %s group-readable.",
|
|
|
|
options->ControlPortWriteToFile);
|
2015-04-13 21:08:31 -06:00
|
|
|
}
|
|
|
|
}
|
2019-03-25 14:03:49 -04:00
|
|
|
#endif /* !defined(_WIN32) */
|
|
|
|
tor_free(joined);
|
|
|
|
SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
|
|
|
|
smartlist_free(lines);
|
2015-04-13 21:08:31 -06:00
|
|
|
}
|
|
|
|
|
2019-03-25 14:03:49 -04:00
|
|
|
const struct signal_name_t signal_table[] = {
|
|
|
|
{ SIGHUP, "RELOAD" },
|
|
|
|
{ SIGHUP, "HUP" },
|
|
|
|
{ SIGINT, "SHUTDOWN" },
|
|
|
|
{ SIGUSR1, "DUMP" },
|
|
|
|
{ SIGUSR1, "USR1" },
|
|
|
|
{ SIGUSR2, "DEBUG" },
|
|
|
|
{ SIGUSR2, "USR2" },
|
|
|
|
{ SIGTERM, "HALT" },
|
|
|
|
{ SIGTERM, "TERM" },
|
|
|
|
{ SIGTERM, "INT" },
|
|
|
|
{ SIGNEWNYM, "NEWNYM" },
|
|
|
|
{ SIGCLEARDNSCACHE, "CLEARDNSCACHE"},
|
|
|
|
{ SIGHEARTBEAT, "HEARTBEAT"},
|
|
|
|
{ SIGACTIVE, "ACTIVE" },
|
|
|
|
{ SIGDORMANT, "DORMANT" },
|
|
|
|
{ 0, NULL },
|
|
|
|
};
|
2015-04-25 08:23:15 +00:00
|
|
|
|
2004-11-07 21:37:50 +00:00
|
|
|
/** Called when <b>conn</b> has no more bytes left on its outbuf. */
|
|
|
|
int
|
2006-07-26 19:07:26 +00:00
|
|
|
connection_control_finished_flushing(control_connection_t *conn)
|
2005-06-11 18:52:12 +00:00
|
|
|
{
|
2004-11-03 01:32:26 +00:00
|
|
|
tor_assert(conn);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-11-21 10:14:57 +00:00
|
|
|
/** Called when <b>conn</b> has gotten its socket closed. */
|
2005-06-11 18:52:12 +00:00
|
|
|
int
|
2006-07-26 19:07:26 +00:00
|
|
|
connection_control_reached_eof(control_connection_t *conn)
|
2005-06-11 18:52:12 +00:00
|
|
|
{
|
2005-06-17 18:49:55 +00:00
|
|
|
tor_assert(conn);
|
|
|
|
|
2006-02-13 09:02:35 +00:00
|
|
|
log_info(LD_CONTROL,"Control connection reached EOF. Closing.");
|
2006-07-26 19:07:26 +00:00
|
|
|
connection_mark_for_close(TO_CONN(conn));
|
2004-11-21 10:14:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-20 08:21:11 -07:00
|
|
|
/** Shut down this Tor instance in the same way that SIGINT would, but
|
|
|
|
* with a log message appropriate for the loss of an owning controller. */
|
|
|
|
static void
|
|
|
|
lost_owning_controller(const char *owner_type, const char *loss_manner)
|
|
|
|
{
|
2014-02-03 12:54:06 -05:00
|
|
|
log_notice(LD_CONTROL, "Owning controller %s has %s -- exiting now.",
|
|
|
|
owner_type, loss_manner);
|
2011-05-20 08:21:11 -07:00
|
|
|
|
2015-08-13 09:13:21 -04:00
|
|
|
activate_signal(SIGTERM);
|
2011-05-20 08:21:11 -07:00
|
|
|
}
|
|
|
|
|
2011-05-19 16:27:51 -07:00
|
|
|
/** Called when <b>conn</b> is being freed. */
|
|
|
|
void
|
|
|
|
connection_control_closed(control_connection_t *conn)
|
|
|
|
{
|
|
|
|
tor_assert(conn);
|
|
|
|
|
|
|
|
conn->event_mask = 0;
|
|
|
|
control_update_global_event_mask();
|
2011-05-19 16:34:40 -07:00
|
|
|
|
2015-04-25 08:23:15 +00:00
|
|
|
/* Close all ephemeral Onion Services if any.
|
|
|
|
* The list and it's contents are scrubbed/freed in connection_free_.
|
|
|
|
*/
|
|
|
|
if (conn->ephemeral_onion_services) {
|
2017-11-09 14:28:22 -05:00
|
|
|
SMARTLIST_FOREACH_BEGIN(conn->ephemeral_onion_services, char *, cp) {
|
|
|
|
if (rend_valid_v2_service_id(cp)) {
|
|
|
|
rend_service_del_ephemeral(cp);
|
|
|
|
} else if (hs_address_is_valid(cp)) {
|
|
|
|
hs_service_del_ephemeral(cp);
|
|
|
|
} else {
|
|
|
|
/* An invalid .onion in our list should NEVER happen */
|
|
|
|
tor_fragile_assert();
|
|
|
|
}
|
|
|
|
} SMARTLIST_FOREACH_END(cp);
|
2015-04-25 08:23:15 +00:00
|
|
|
}
|
|
|
|
|
2011-05-19 16:34:40 -07:00
|
|
|
if (conn->is_owning_control_connection) {
|
2011-05-20 08:21:11 -07:00
|
|
|
lost_owning_controller("connection", "closed");
|
2011-05-19 16:34:40 -07:00
|
|
|
}
|
2011-05-19 16:27:51 -07:00
|
|
|
}
|
|
|
|
|
2007-08-16 17:31:23 +00:00
|
|
|
/** Return true iff <b>cmd</b> is allowable (or at least forgivable) at this
|
|
|
|
* stage of the protocol. */
|
|
|
|
static int
|
|
|
|
is_valid_initial_command(control_connection_t *conn, const char *cmd)
|
|
|
|
{
|
2012-10-12 12:22:13 -04:00
|
|
|
if (conn->base_.state == CONTROL_CONN_STATE_OPEN)
|
2007-08-16 17:31:23 +00:00
|
|
|
return 1;
|
|
|
|
if (!strcasecmp(cmd, "PROTOCOLINFO"))
|
2012-02-06 10:49:45 -08:00
|
|
|
return (!conn->have_sent_protocolinfo &&
|
|
|
|
conn->safecookie_client_hash == NULL);
|
|
|
|
if (!strcasecmp(cmd, "AUTHCHALLENGE"))
|
|
|
|
return (conn->safecookie_client_hash == NULL);
|
2007-08-16 17:31:23 +00:00
|
|
|
if (!strcasecmp(cmd, "AUTHENTICATE") ||
|
|
|
|
!strcasecmp(cmd, "QUIT"))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-02-05 21:39:49 +00:00
|
|
|
/** Do not accept any control command of more than 1MB in length. Anything
|
|
|
|
* that needs to be anywhere near this long probably means that one of our
|
|
|
|
* interfaces is broken. */
|
|
|
|
#define MAX_COMMAND_LINE_LENGTH (1024*1024)
|
|
|
|
|
2016-08-02 14:02:35 -04:00
|
|
|
/** Wrapper around peek_buf_has_control0 command: presents the same
|
|
|
|
* interface as that underlying functions, but takes a connection_t intead of
|
|
|
|
* a buf_t.
|
2012-06-05 00:17:54 -04:00
|
|
|
*/
|
2009-08-09 11:40:28 -07:00
|
|
|
static int
|
|
|
|
peek_connection_has_control0_command(connection_t *conn)
|
|
|
|
{
|
2016-08-02 13:15:10 -04:00
|
|
|
return peek_buf_has_control0_command(conn->inbuf);
|
2009-08-09 11:40:28 -07:00
|
|
|
}
|
|
|
|
|
2012-02-21 08:52:03 +05:30
|
|
|
static int
|
|
|
|
peek_connection_has_http_command(connection_t *conn)
|
|
|
|
{
|
|
|
|
return peek_buf_has_http_command(conn->inbuf);
|
|
|
|
}
|
|
|
|
|
2017-07-05 15:59:17 -04:00
|
|
|
static const char CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG[] =
|
2017-07-05 11:01:17 -04:00
|
|
|
"HTTP/1.0 501 Tor ControlPort is not an HTTP proxy"
|
|
|
|
"\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n"
|
|
|
|
"<html>\n"
|
|
|
|
"<head>\n"
|
|
|
|
"<title>Tor's ControlPort is not an HTTP proxy</title>\n"
|
|
|
|
"</head>\n"
|
|
|
|
"<body>\n"
|
|
|
|
"<h1>Tor's ControlPort is not an HTTP proxy</h1>\n"
|
|
|
|
"<p>\n"
|
|
|
|
"It appears you have configured your web browser to use Tor's control port"
|
|
|
|
" as an HTTP proxy.\n"
|
|
|
|
"This is not correct: Tor's default SOCKS proxy port is 9050.\n"
|
|
|
|
"Please configure your client accordingly.\n"
|
|
|
|
"</p>\n"
|
|
|
|
"<p>\n"
|
|
|
|
"See <a href=\"https://www.torproject.org/documentation.html\">"
|
|
|
|
"https://www.torproject.org/documentation.html</a> for more "
|
|
|
|
"information.\n"
|
|
|
|
"<!-- Plus this comment, to make the body response more than 512 bytes, so "
|
|
|
|
" IE will be willing to display it. Comment comment comment comment "
|
|
|
|
" comment comment comment comment comment comment comment comment.-->\n"
|
|
|
|
"</p>\n"
|
|
|
|
"</body>\n"
|
|
|
|
"</html>\n";
|
|
|
|
|
2005-09-30 20:04:55 +00:00
|
|
|
/** Called when data has arrived on a v1 control connection: Try to fetch
|
|
|
|
* commands from conn->inbuf, and execute them.
|
|
|
|
*/
|
2007-03-04 21:08:28 +00:00
|
|
|
int
|
|
|
|
connection_control_process_inbuf(control_connection_t *conn)
|
2005-06-11 18:52:12 +00:00
|
|
|
{
|
2005-08-12 17:24:53 +00:00
|
|
|
size_t data_len;
|
2008-02-22 19:09:45 +00:00
|
|
|
uint32_t cmd_data_len;
|
2005-08-12 17:24:53 +00:00
|
|
|
int cmd_len;
|
2005-06-17 20:37:21 +00:00
|
|
|
char *args;
|
2004-11-03 01:32:26 +00:00
|
|
|
|
|
|
|
tor_assert(conn);
|
2012-10-12 12:22:13 -04:00
|
|
|
tor_assert(conn->base_.state == CONTROL_CONN_STATE_OPEN ||
|
|
|
|
conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH);
|
2005-06-17 18:49:55 +00:00
|
|
|
|
|
|
|
if (!conn->incoming_cmd) {
|
|
|
|
conn->incoming_cmd = tor_malloc(1024);
|
|
|
|
conn->incoming_cmd_len = 1024;
|
|
|
|
conn->incoming_cmd_cur_len = 0;
|
|
|
|
}
|
|
|
|
|
2012-10-12 12:22:13 -04:00
|
|
|
if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH &&
|
2009-08-09 11:40:28 -07:00
|
|
|
peek_connection_has_control0_command(TO_CONN(conn))) {
|
2007-03-04 21:08:28 +00:00
|
|
|
/* Detect v0 commands and send a "no more v0" message. */
|
|
|
|
size_t body_len;
|
|
|
|
char buf[128];
|
|
|
|
set_uint16(buf+2, htons(0x0000)); /* type == error */
|
|
|
|
set_uint16(buf+4, htons(0x0001)); /* code == internal error */
|
2007-08-29 19:02:33 +00:00
|
|
|
strlcpy(buf+6, "The v0 control protocol is not supported by Tor 0.1.2.17 "
|
|
|
|
"and later; upgrade your controller.",
|
2007-05-22 15:48:46 +00:00
|
|
|
sizeof(buf)-6);
|
2007-03-04 21:08:28 +00:00
|
|
|
body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
|
|
|
|
set_uint16(buf+0, htons(body_len));
|
2017-08-08 15:16:39 -04:00
|
|
|
connection_buf_add(buf, 4+body_len, TO_CONN(conn));
|
2010-10-13 13:08:38 -04:00
|
|
|
|
|
|
|
connection_mark_and_flush(TO_CONN(conn));
|
2012-02-21 08:52:03 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the user has the HTTP proxy port and the control port confused. */
|
2017-06-21 10:35:35 -04:00
|
|
|
if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH &&
|
2012-02-21 08:52:03 +05:30
|
|
|
peek_connection_has_http_command(TO_CONN(conn))) {
|
2017-07-05 11:01:17 -04:00
|
|
|
connection_write_str_to_buf(CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG, conn);
|
2012-02-21 08:52:03 +05:30
|
|
|
log_notice(LD_CONTROL, "Received HTTP request on ControlPort");
|
|
|
|
connection_mark_and_flush(TO_CONN(conn));
|
2007-03-04 21:08:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-06-17 18:49:55 +00:00
|
|
|
again:
|
|
|
|
while (1) {
|
|
|
|
size_t last_idx;
|
|
|
|
int r;
|
2005-07-15 19:31:11 +00:00
|
|
|
/* First, fetch a line. */
|
2005-06-17 20:37:21 +00:00
|
|
|
do {
|
2005-06-17 18:49:55 +00:00
|
|
|
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
|
2017-08-08 15:16:39 -04:00
|
|
|
r = connection_buf_get_line(TO_CONN(conn),
|
2005-07-15 19:31:11 +00:00
|
|
|
conn->incoming_cmd+conn->incoming_cmd_cur_len,
|
|
|
|
&data_len);
|
2005-06-17 18:49:55 +00:00
|
|
|
if (r == 0)
|
|
|
|
/* Line not all here yet. Wait. */
|
|
|
|
return 0;
|
|
|
|
else if (r == -1) {
|
2008-02-05 21:39:49 +00:00
|
|
|
if (data_len + conn->incoming_cmd_cur_len > MAX_COMMAND_LINE_LENGTH) {
|
2008-02-05 21:39:51 +00:00
|
|
|
connection_write_str_to_buf("500 Line too long.\r\n", conn);
|
2008-02-05 21:39:49 +00:00
|
|
|
connection_stop_reading(TO_CONN(conn));
|
2010-10-13 13:08:38 -04:00
|
|
|
connection_mark_and_flush(TO_CONN(conn));
|
2008-02-05 21:39:49 +00:00
|
|
|
}
|
2007-12-29 02:33:42 +00:00
|
|
|
while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
|
|
|
|
conn->incoming_cmd_len *= 2;
|
|
|
|
conn->incoming_cmd = tor_realloc(conn->incoming_cmd,
|
|
|
|
conn->incoming_cmd_len);
|
2005-06-17 18:49:55 +00:00
|
|
|
}
|
|
|
|
} while (r != 1);
|
|
|
|
|
|
|
|
tor_assert(data_len);
|
|
|
|
|
|
|
|
last_idx = conn->incoming_cmd_cur_len;
|
2008-02-22 19:09:45 +00:00
|
|
|
conn->incoming_cmd_cur_len += (int)data_len;
|
2005-06-17 18:49:55 +00:00
|
|
|
|
|
|
|
/* We have appended a line to incoming_cmd. Is the command done? */
|
|
|
|
if (last_idx == 0 && *conn->incoming_cmd != '+')
|
|
|
|
/* One line command, didn't start with '+'. */
|
|
|
|
break;
|
2007-08-29 19:02:33 +00:00
|
|
|
/* XXXX this code duplication is kind of dumb. */
|
2005-06-17 18:49:55 +00:00
|
|
|
if (last_idx+3 == conn->incoming_cmd_cur_len &&
|
2011-05-10 16:23:43 -04:00
|
|
|
tor_memeq(conn->incoming_cmd + last_idx, ".\r\n", 3)) {
|
2005-07-15 19:31:11 +00:00
|
|
|
/* Just appended ".\r\n"; we're done. Remove it. */
|
2008-03-10 12:13:43 +00:00
|
|
|
conn->incoming_cmd[last_idx] = '\0';
|
2005-07-15 19:31:11 +00:00
|
|
|
conn->incoming_cmd_cur_len -= 3;
|
2005-06-17 18:49:55 +00:00
|
|
|
break;
|
2007-08-29 19:02:33 +00:00
|
|
|
} else if (last_idx+2 == conn->incoming_cmd_cur_len &&
|
2011-05-10 16:23:43 -04:00
|
|
|
tor_memeq(conn->incoming_cmd + last_idx, ".\n", 2)) {
|
2007-08-29 19:02:33 +00:00
|
|
|
/* Just appended ".\n"; we're done. Remove it. */
|
2008-03-10 12:13:43 +00:00
|
|
|
conn->incoming_cmd[last_idx] = '\0';
|
2007-08-29 19:02:33 +00:00
|
|
|
conn->incoming_cmd_cur_len -= 2;
|
|
|
|
break;
|
2005-07-15 19:31:11 +00:00
|
|
|
}
|
2005-06-17 18:49:55 +00:00
|
|
|
/* Otherwise, read another line. */
|
|
|
|
}
|
|
|
|
data_len = conn->incoming_cmd_cur_len;
|
|
|
|
/* Okay, we now have a command sitting on conn->incoming_cmd. See if we
|
|
|
|
* recognize it.
|
|
|
|
*/
|
2005-06-17 20:37:21 +00:00
|
|
|
cmd_len = 0;
|
2005-09-08 06:37:50 +00:00
|
|
|
while ((size_t)cmd_len < data_len
|
|
|
|
&& !TOR_ISSPACE(conn->incoming_cmd[cmd_len]))
|
2005-06-17 18:49:55 +00:00
|
|
|
++cmd_len;
|
|
|
|
|
2005-06-17 20:37:21 +00:00
|
|
|
conn->incoming_cmd[cmd_len]='\0';
|
|
|
|
args = conn->incoming_cmd+cmd_len+1;
|
2010-12-02 13:19:21 -05:00
|
|
|
tor_assert(data_len>(size_t)cmd_len);
|
|
|
|
data_len -= (cmd_len+1); /* skip the command and NUL we added after it */
|
2011-11-16 17:44:20 +01:00
|
|
|
while (TOR_ISSPACE(*args)) {
|
2005-06-17 20:37:21 +00:00
|
|
|
++args;
|
|
|
|
--data_len;
|
|
|
|
}
|
|
|
|
|
2009-06-23 23:14:44 -04:00
|
|
|
/* If the connection is already closing, ignore further commands */
|
|
|
|
if (TO_CONN(conn)->marked_for_close) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Otherwise, Quit is always valid. */
|
2005-08-13 01:55:23 +00:00
|
|
|
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
|
|
|
|
connection_write_str_to_buf("250 closing connection\r\n", conn);
|
2010-10-13 13:08:38 -04:00
|
|
|
connection_mark_and_flush(TO_CONN(conn));
|
2005-08-13 01:55:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-12 12:22:13 -04:00
|
|
|
if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH &&
|
2007-08-16 17:31:23 +00:00
|
|
|
!is_valid_initial_command(conn, conn->incoming_cmd)) {
|
2005-06-17 18:49:55 +00:00
|
|
|
connection_write_str_to_buf("514 Authentication required.\r\n", conn);
|
2007-08-02 01:28:40 +00:00
|
|
|
connection_mark_for_close(TO_CONN(conn));
|
2007-08-02 04:28:29 +00:00
|
|
|
return 0;
|
2005-06-17 18:49:55 +00:00
|
|
|
}
|
|
|
|
|
2008-02-22 19:09:45 +00:00
|
|
|
if (data_len >= UINT32_MAX) {
|
|
|
|
connection_write_str_to_buf("500 A 4GB command? Nice try.\r\n", conn);
|
|
|
|
connection_mark_for_close(TO_CONN(conn));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd_data_len = (uint32_t)data_len;
|
2019-03-25 14:03:49 -04:00
|
|
|
if (handle_control_command(conn, cmd_data_len, args) < 0)
|
|
|
|
return -1;
|
2005-06-17 18:49:55 +00:00
|
|
|
|
|
|
|
conn->incoming_cmd_cur_len = 0;
|
|
|
|
goto again;
|
|
|
|
}
|
2019-03-25 14:03:49 -04:00
|
|
|
|
2019-03-25 12:11:59 -04:00
|
|
|
/** Cached liveness for network liveness events and GETINFO
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int network_is_live = 0;
|
2005-06-17 18:49:55 +00:00
|
|
|
|
2004-11-07 21:37:50 +00:00
|
|
|
int
|
2019-03-25 12:11:59 -04:00
|
|
|
get_cached_network_liveness(void)
|
2004-11-03 01:32:26 +00:00
|
|
|
{
|
2019-03-25 12:11:59 -04:00
|
|
|
return network_is_live;
|
|
|
|
}
|
2018-12-16 17:01:25 -06:00
|
|
|
|
2019-03-25 12:11:59 -04:00
|
|
|
void
|
|
|
|
set_cached_network_liveness(int liveness)
|
|
|
|
{
|
|
|
|
network_is_live = liveness;
|
|
|
|
}
|
2011-08-08 04:38:53 +05:00
|
|
|
|
2011-05-15 08:23:04 -07:00
|
|
|
/** A copy of the process specifier of Tor's owning controller, or
|
|
|
|
* NULL if this Tor instance is not currently owned by a process. */
|
|
|
|
static char *owning_controller_process_spec = NULL;
|
|
|
|
|
|
|
|
/** A process-termination monitor for Tor's owning controller, or NULL
|
|
|
|
* if this Tor instance is not currently owned by a process. */
|
|
|
|
static tor_process_monitor_t *owning_controller_process_monitor = NULL;
|
|
|
|
|
|
|
|
/** Process-termination monitor callback for Tor's owning controller
|
|
|
|
* process. */
|
|
|
|
static void
|
|
|
|
owning_controller_procmon_cb(void *unused)
|
|
|
|
{
|
|
|
|
(void)unused;
|
|
|
|
|
2011-05-20 08:21:11 -07:00
|
|
|
lost_owning_controller("process", "vanished");
|
2011-05-15 08:23:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Set <b>process_spec</b> as Tor's owning controller process.
|
2011-05-16 10:25:59 -07:00
|
|
|
* Exit on failure. */
|
|
|
|
void
|
2011-05-15 08:23:04 -07:00
|
|
|
monitor_owning_controller_process(const char *process_spec)
|
|
|
|
{
|
|
|
|
const char *msg;
|
|
|
|
|
|
|
|
tor_assert((owning_controller_process_spec == NULL) ==
|
|
|
|
(owning_controller_process_monitor == NULL));
|
|
|
|
|
|
|
|
if (owning_controller_process_spec != NULL) {
|
|
|
|
if ((process_spec != NULL) && !strcmp(process_spec,
|
|
|
|
owning_controller_process_spec)) {
|
|
|
|
/* Same process -- return now, instead of disposing of and
|
|
|
|
* recreating the process-termination monitor. */
|
2011-05-16 10:25:59 -07:00
|
|
|
return;
|
2011-05-15 08:23:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We are currently owned by a process, and we should no longer be
|
|
|
|
* owned by it. Free the process-termination monitor. */
|
|
|
|
tor_process_monitor_free(owning_controller_process_monitor);
|
|
|
|
owning_controller_process_monitor = NULL;
|
|
|
|
|
|
|
|
tor_free(owning_controller_process_spec);
|
|
|
|
owning_controller_process_spec = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
tor_assert((owning_controller_process_spec == NULL) &&
|
|
|
|
(owning_controller_process_monitor == NULL));
|
|
|
|
|
|
|
|
if (process_spec == NULL)
|
2011-05-16 10:25:59 -07:00
|
|
|
return;
|
2011-05-15 08:23:04 -07:00
|
|
|
|
|
|
|
owning_controller_process_spec = tor_strdup(process_spec);
|
|
|
|
owning_controller_process_monitor =
|
|
|
|
tor_process_monitor_new(tor_libevent_get_base(),
|
|
|
|
owning_controller_process_spec,
|
|
|
|
LD_CONTROL,
|
|
|
|
owning_controller_procmon_cb, NULL,
|
|
|
|
&msg);
|
|
|
|
|
|
|
|
if (owning_controller_process_monitor == NULL) {
|
2011-05-16 10:25:59 -07:00
|
|
|
log_err(LD_BUG, "Couldn't create process-termination monitor for "
|
|
|
|
"owning controller: %s. Exiting.",
|
|
|
|
msg);
|
|
|
|
owning_controller_process_spec = NULL;
|
2017-10-20 11:15:32 -04:00
|
|
|
tor_shutdown_event_loop_and_exit(1);
|
2011-05-15 08:23:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-04 19:33:48 -05:00
|
|
|
/** Return a longname the node whose identity is <b>id_digest</b>. If
|
|
|
|
* node_get_by_id() returns NULL, base 16 encoding of <b>id_digest</b> is
|
|
|
|
* returned instead.
|
|
|
|
*
|
|
|
|
* This function is not thread-safe. Each call to this function invalidates
|
|
|
|
* previous values returned by this function.
|
|
|
|
*/
|
|
|
|
MOCK_IMPL(const char *,
|
|
|
|
node_describe_longname_by_id,(const char *id_digest))
|
|
|
|
{
|
|
|
|
static char longname[MAX_VERBOSE_NICKNAME_LEN+1];
|
|
|
|
node_get_verbose_nickname_by_id(id_digest, longname);
|
|
|
|
return longname;
|
|
|
|
}
|
|
|
|
|
2013-08-14 17:16:06 +03:00
|
|
|
/** Free any leftover allocated memory of the control.c subsystem. */
|
|
|
|
void
|
|
|
|
control_free_all(void)
|
|
|
|
{
|
2019-03-25 14:03:49 -04:00
|
|
|
control_auth_free_all();
|
2019-03-25 12:11:59 -04:00
|
|
|
control_events_free_all();
|
2019-03-25 14:03:49 -04:00
|
|
|
control_cmd_free_all();
|
2018-11-19 16:24:01 -06:00
|
|
|
control_event_bootstrap_reset();
|
2013-08-25 11:29:03 -04:00
|
|
|
}
|