mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 12:23:32 +01:00
Start implementing control interface.
svn:r2652
This commit is contained in:
parent
d63d420930
commit
347d3f9d62
2
doc/TODO
2
doc/TODO
@ -45,7 +45,7 @@ N - Windows installer
|
|||||||
- Review website; make important info more prominent.
|
- Review website; make important info more prominent.
|
||||||
|
|
||||||
Beyond 0.0.9:
|
Beyond 0.0.9:
|
||||||
- Check getrlimit(RLIMIT_[N]OFILE), sysconf(OPEN_MAX) on start-up, and
|
o Check getrlimit(RLIMIT_[N]OFILE), sysconf(OPEN_MAX) on start-up, and
|
||||||
warn if we're running as a server with a low limit.
|
warn if we're running as a server with a low limit.
|
||||||
- Implement If-Modified-Since for directories.
|
- Implement If-Modified-Since for directories.
|
||||||
N - Handle rendezvousing with unverified nodes.
|
N - Handle rendezvousing with unverified nodes.
|
||||||
|
@ -59,6 +59,8 @@ the message.
|
|||||||
0x0005 Unauthorized user
|
0x0005 Unauthorized user
|
||||||
0x0006 Failed authentication attempt
|
0x0006 Failed authentication attempt
|
||||||
|
|
||||||
|
The rest of the body should be a human-readable description of the error.
|
||||||
|
|
||||||
3.2. DONE (Type 0x0001)
|
3.2. DONE (Type 0x0001)
|
||||||
|
|
||||||
Sent from server to client in response to a request that was successfully
|
Sent from server to client in response to a request that was successfully
|
||||||
@ -76,7 +78,7 @@ the message.
|
|||||||
|
|
||||||
Request the value of a configuration variable. The body contains a
|
Request the value of a configuration variable. The body contains a
|
||||||
nul-terminated string for a configuration key. The server replies with a
|
nul-terminated string for a configuration key. The server replies with a
|
||||||
CONFVALUE message
|
CONFVALUE message.
|
||||||
|
|
||||||
3.5. CONFVALUE (Type 0x0004)
|
3.5. CONFVALUE (Type 0x0004)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ bin_PROGRAMS = tor
|
|||||||
|
|
||||||
tor_SOURCES = buffers.c circuitbuild.c circuitlist.c \
|
tor_SOURCES = buffers.c circuitbuild.c circuitlist.c \
|
||||||
circuituse.c command.c config.c \
|
circuituse.c command.c config.c \
|
||||||
connection.c connection_edge.c connection_or.c \
|
connection.c connection_edge.c connection_or.c control.c \
|
||||||
cpuworker.c directory.c dirserv.c dns.c hibernate.c main.c \
|
cpuworker.c directory.c dirserv.c dns.c hibernate.c main.c \
|
||||||
onion.c relay.c rendcommon.c rendclient.c rendmid.c \
|
onion.c relay.c rendcommon.c rendclient.c rendmid.c \
|
||||||
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
||||||
@ -16,7 +16,7 @@ tor_LDADD = ../common/libor.a ../common/libor-crypto.a -lz -lssl -lcrypto
|
|||||||
|
|
||||||
test_SOURCES = buffers.c circuitbuild.c circuitlist.c \
|
test_SOURCES = buffers.c circuitbuild.c circuitlist.c \
|
||||||
circuituse.c command.c config.c \
|
circuituse.c command.c config.c \
|
||||||
connection.c connection_edge.c connection_or.c \
|
connection.c connection_edge.c connection_or.c control.c \
|
||||||
cpuworker.c directory.c dirserv.c dns.c hibernate.c main.c \
|
cpuworker.c directory.c dirserv.c dns.c hibernate.c main.c \
|
||||||
onion.c relay.c rendcommon.c rendclient.c rendmid.c \
|
onion.c relay.c rendcommon.c rendclient.c rendmid.c \
|
||||||
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
||||||
|
@ -636,6 +636,38 @@ int fetch_from_buf_socks(buf_t *buf, socks_request_t *req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DOCDOC: 1 if complete, 0 if pending, -1 on error. */
|
||||||
|
int fetch_from_buf_control(buf_t *buf, uint16_t *len_out, uint16_t *type_out,
|
||||||
|
char **body_out)
|
||||||
|
{
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
|
tor_assert(buf);
|
||||||
|
tor_assert(len_out);
|
||||||
|
tor_assert(type_out);
|
||||||
|
tor_assert(body_out);
|
||||||
|
|
||||||
|
if (buf->datalen < 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = ntohs(get_uint16(buf->mem));
|
||||||
|
if (buf->datalen < 4 + (unsigned)len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*len_out = len;
|
||||||
|
*type_out = ntohs(get_uint16(buf->mem+2));
|
||||||
|
if (len) {
|
||||||
|
*body_out = tor_malloc(len);
|
||||||
|
memcpy(*body_out, buf->mem+4, len);
|
||||||
|
} else {
|
||||||
|
*body_out = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_remove_from_front(buf, 4+len);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** Log an error and exit if <b>buf</b> is corrupted.
|
/** Log an error and exit if <b>buf</b> is corrupted.
|
||||||
*/
|
*/
|
||||||
void assert_buf_ok(buf_t *buf)
|
void assert_buf_ok(buf_t *buf)
|
||||||
|
@ -28,6 +28,8 @@ const char *conn_type_to_string[] = {
|
|||||||
"Dir", /* 9 */
|
"Dir", /* 9 */
|
||||||
"DNS worker", /* 10 */
|
"DNS worker", /* 10 */
|
||||||
"CPU worker", /* 11 */
|
"CPU worker", /* 11 */
|
||||||
|
"Control listener", /* 12 */
|
||||||
|
"Control", /* 13 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Array of string arrays to make {conn-\>type,conn-\>state} human-readable. */
|
/** Array of string arrays to make {conn-\>type,conn-\>state} human-readable. */
|
||||||
@ -70,6 +72,10 @@ const char *conn_state_to_string[][_CONN_TYPE_MAX+1] = {
|
|||||||
"idle", /* 1 */
|
"idle", /* 1 */
|
||||||
"busy with onion", /* 2 */
|
"busy with onion", /* 2 */
|
||||||
"busy with handshake" }, /* 3 */
|
"busy with handshake" }, /* 3 */
|
||||||
|
{ "ready" }, /* control listener, 0 */
|
||||||
|
{ "", /* control, 0 */
|
||||||
|
"ready", /* 1 */
|
||||||
|
"waiting for authentication", }, /* 2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/********* END VARIABLES ************/
|
/********* END VARIABLES ************/
|
||||||
@ -459,6 +465,9 @@ static int connection_init_accepted_conn(connection_t *conn) {
|
|||||||
conn->purpose = DIR_PURPOSE_SERVER;
|
conn->purpose = DIR_PURPOSE_SERVER;
|
||||||
conn->state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
|
conn->state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
|
||||||
break;
|
break;
|
||||||
|
case CONN_TYPE_CONTROL:
|
||||||
|
/* XXXX009 NM control */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -543,7 +552,8 @@ static void listener_close_if_present(int type) {
|
|||||||
int i,n;
|
int i,n;
|
||||||
tor_assert(type == CONN_TYPE_OR_LISTENER ||
|
tor_assert(type == CONN_TYPE_OR_LISTENER ||
|
||||||
type == CONN_TYPE_AP_LISTENER ||
|
type == CONN_TYPE_AP_LISTENER ||
|
||||||
type == CONN_TYPE_DIR_LISTENER);
|
type == CONN_TYPE_DIR_LISTENER ||
|
||||||
|
type == CONN_TYPE_CONTROL_LISTENER);
|
||||||
get_connection_array(&carray,&n);
|
get_connection_array(&carray,&n);
|
||||||
for(i=0;i<n;i++) {
|
for(i=0;i<n;i++) {
|
||||||
conn = carray[i];
|
conn = carray[i];
|
||||||
@ -636,6 +646,7 @@ int retry_all_listeners(int force) {
|
|||||||
if (retry_listeners(CONN_TYPE_AP_LISTENER, options.SocksBindAddress,
|
if (retry_listeners(CONN_TYPE_AP_LISTENER, options.SocksBindAddress,
|
||||||
options.SocksPort, "127.0.0.1", force)<0)
|
options.SocksPort, "127.0.0.1", force)<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
/* XXXX009 control NM */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -787,6 +798,8 @@ int connection_handle_read(connection_t *conn) {
|
|||||||
return connection_handle_listener_read(conn, CONN_TYPE_AP);
|
return connection_handle_listener_read(conn, CONN_TYPE_AP);
|
||||||
case CONN_TYPE_DIR_LISTENER:
|
case CONN_TYPE_DIR_LISTENER:
|
||||||
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
|
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
|
||||||
|
case CONN_TYPE_CONTROL_LISTENER:
|
||||||
|
return connection_handle_listener_read(conn, CONN_TYPE_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(connection_read_to_buf(conn) < 0) {
|
if(connection_read_to_buf(conn) < 0) {
|
||||||
@ -1151,7 +1164,8 @@ connection_t *connection_get_by_type_rendquery(int type, const char *rendquery)
|
|||||||
int connection_is_listener(connection_t *conn) {
|
int connection_is_listener(connection_t *conn) {
|
||||||
if(conn->type == CONN_TYPE_OR_LISTENER ||
|
if(conn->type == CONN_TYPE_OR_LISTENER ||
|
||||||
conn->type == CONN_TYPE_AP_LISTENER ||
|
conn->type == CONN_TYPE_AP_LISTENER ||
|
||||||
conn->type == CONN_TYPE_DIR_LISTENER)
|
conn->type == CONN_TYPE_DIR_LISTENER ||
|
||||||
|
conn->type == CONN_TYPE_CONTROL_LISTENER)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1167,7 +1181,8 @@ int connection_state_is_open(connection_t *conn) {
|
|||||||
|
|
||||||
if((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
|
if((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
|
||||||
(conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
|
(conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
|
||||||
(conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN))
|
(conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN) ||
|
||||||
|
(conn->type == CONN_TYPE_CONTROL && conn->state ==CONTROL_CONN_STATE_OPEN))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1232,6 +1247,8 @@ static int connection_process_inbuf(connection_t *conn) {
|
|||||||
return connection_dns_process_inbuf(conn);
|
return connection_dns_process_inbuf(conn);
|
||||||
case CONN_TYPE_CPUWORKER:
|
case CONN_TYPE_CPUWORKER:
|
||||||
return connection_cpu_process_inbuf(conn);
|
return connection_cpu_process_inbuf(conn);
|
||||||
|
case CONN_TYPE_CONTROL:
|
||||||
|
return connection_control_process_inbuf(conn);
|
||||||
default:
|
default:
|
||||||
log_fn(LOG_WARN,"got unexpected conn->type %d.", conn->type);
|
log_fn(LOG_WARN,"got unexpected conn->type %d.", conn->type);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1262,6 +1279,8 @@ static int connection_finished_flushing(connection_t *conn) {
|
|||||||
return connection_dns_finished_flushing(conn);
|
return connection_dns_finished_flushing(conn);
|
||||||
case CONN_TYPE_CPUWORKER:
|
case CONN_TYPE_CPUWORKER:
|
||||||
return connection_cpu_finished_flushing(conn);
|
return connection_cpu_finished_flushing(conn);
|
||||||
|
case CONN_TYPE_CONTROL:
|
||||||
|
return connection_control_finished_flushing(conn);
|
||||||
default:
|
default:
|
||||||
log_fn(LOG_WARN,"got unexpected conn->type %d.", conn->type);
|
log_fn(LOG_WARN,"got unexpected conn->type %d.", conn->type);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1384,6 +1403,7 @@ void assert_connection_ok(connection_t *conn, time_t now)
|
|||||||
case CONN_TYPE_OR_LISTENER:
|
case CONN_TYPE_OR_LISTENER:
|
||||||
case CONN_TYPE_AP_LISTENER:
|
case CONN_TYPE_AP_LISTENER:
|
||||||
case CONN_TYPE_DIR_LISTENER:
|
case CONN_TYPE_DIR_LISTENER:
|
||||||
|
case CONN_TYPE_CONTROL_LISTENER:
|
||||||
tor_assert(conn->state == LISTENER_STATE_READY);
|
tor_assert(conn->state == LISTENER_STATE_READY);
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
@ -1413,6 +1433,11 @@ void assert_connection_ok(connection_t *conn, time_t now)
|
|||||||
tor_assert(conn->state >= _CPUWORKER_STATE_MIN);
|
tor_assert(conn->state >= _CPUWORKER_STATE_MIN);
|
||||||
tor_assert(conn->state <= _CPUWORKER_STATE_MAX);
|
tor_assert(conn->state <= _CPUWORKER_STATE_MAX);
|
||||||
break;
|
break;
|
||||||
|
case CONN_TYPE_CONTROL:
|
||||||
|
tor_assert(conn->state >= _CONTROL_CONN_STATE_MIN);
|
||||||
|
tor_assert(conn->state <= _CONTROL_CONN_STATE_MAX);
|
||||||
|
/* XXXX009 NM */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tor_assert(0);
|
tor_assert(0);
|
||||||
}
|
}
|
||||||
|
333
src/or/control.c
Normal file
333
src/or/control.c
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/* Copyright 2004 Nick Mathewson */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#include "or.h"
|
||||||
|
|
||||||
|
#define CONTROL_CMD_ERROR 0x0000
|
||||||
|
#define CONTROL_CMD_DONE 0x0001
|
||||||
|
#define CONTROL_CMD_SETCONF 0x0002
|
||||||
|
#define CONTROL_CMD_GETCONF 0x0003
|
||||||
|
#define CONTROL_CMD_CONFVALUE 0x0004
|
||||||
|
#define CONTROL_CMD_SETEVENTS 0x0005
|
||||||
|
#define CONTROL_CMD_EVENT 0x0006
|
||||||
|
#define CONTROL_CMD_AUTHENTICATE 0x0007
|
||||||
|
#define _CONTROL_CMD_MAX_RECOGNIZED 0x0007
|
||||||
|
|
||||||
|
#define ERR_UNSPECIFIED 0x0000
|
||||||
|
#define ERR_UNRECOGNIZED_TYPE 0x0001
|
||||||
|
#define ERR_UNRECOGNIZED_CONFIG_KEY 0x0002
|
||||||
|
#define ERR_INVALID_CONFIG_VALUE 0x0003
|
||||||
|
#define ERR_UNRECOGNIZED_EVENT_CODE 0x0004
|
||||||
|
#define ERR_UNAUTHORIZED_USER 0x0005
|
||||||
|
#define ERR_FAILED_AUTHENTICATION 0x0006
|
||||||
|
|
||||||
|
#define _EVENT_MIN 0x0001
|
||||||
|
#define EVENT_CIRCUIT_STATUS 0x0001
|
||||||
|
#define EVENT_STREAM_STATUS 0x0002
|
||||||
|
#define EVENT_OR_CONN_STATUS 0x0003
|
||||||
|
#define EVENT_BANDWIDTH_USED 0x0004
|
||||||
|
#define EVENT_WARNING 0x0005
|
||||||
|
#define _EVENT_MAX 0x0005
|
||||||
|
|
||||||
|
#define EVENT_IS_INTERESTING(e) (global_event_mask & (1<<(e)))
|
||||||
|
|
||||||
|
static const char *CONTROL_COMMANDS[] = {
|
||||||
|
"error",
|
||||||
|
"done",
|
||||||
|
"setconf",
|
||||||
|
"getconf",
|
||||||
|
"confvalue",
|
||||||
|
"setevents",
|
||||||
|
"events",
|
||||||
|
"authenticate",
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t global_event_mask = 0;
|
||||||
|
|
||||||
|
static void update_global_event_mask(void);
|
||||||
|
static void send_control_message(connection_t *conn, uint16_t type,
|
||||||
|
uint16_t len, const char *body);
|
||||||
|
static void send_control_done(connection_t *conn);
|
||||||
|
static void send_control_error(connection_t *conn, uint16_t error,
|
||||||
|
const char *message);
|
||||||
|
static void send_control_event(uint16_t event, uint16_t len, const char *body);
|
||||||
|
static int handle_control_setconf(connection_t *conn, uint16_t len,
|
||||||
|
const char *body);
|
||||||
|
static int handle_control_getconf(connection_t *conn, uint16_t len,
|
||||||
|
const char *body);
|
||||||
|
static int handle_control_setevents(connection_t *conn, uint16_t len,
|
||||||
|
const char *body);
|
||||||
|
static int handle_control_authenticate(connection_t *conn, uint16_t len,
|
||||||
|
const char *body);
|
||||||
|
|
||||||
|
static INLINE const char *
|
||||||
|
control_cmd_to_string(uint16_t cmd)
|
||||||
|
{
|
||||||
|
return (cmd<=_CONTROL_CMD_MAX_RECOGNIZED) ? CONTROL_COMMANDS[cmd] : "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_global_event_mask(void)
|
||||||
|
{
|
||||||
|
connection_t **conns;
|
||||||
|
int n_conns, i;
|
||||||
|
|
||||||
|
global_event_mask = 0;
|
||||||
|
get_connection_array(&conns, &n_conns);
|
||||||
|
for (i = 0; i < n_conns; ++i) {
|
||||||
|
if (conns[i]->type == CONN_TYPE_CONTROL &&
|
||||||
|
conns[i]->state == CONTROL_CONN_STATE_OPEN) {
|
||||||
|
global_event_mask |= conns[i]->event_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_control_message(connection_t *conn, uint16_t type, uint16_t len,
|
||||||
|
const char *body)
|
||||||
|
{
|
||||||
|
char buf[4];
|
||||||
|
tor_assert(conn);
|
||||||
|
tor_assert(len || !body);
|
||||||
|
tor_assert(type <= _CONTROL_CMD_MAX_RECOGNIZED);
|
||||||
|
set_uint32(buf, htons(len));
|
||||||
|
set_uint32(buf+2, htons(type));
|
||||||
|
connection_write_to_buf(buf, 4, conn);
|
||||||
|
if (len)
|
||||||
|
connection_write_to_buf(body, len, conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_control_done(connection_t *conn)
|
||||||
|
{
|
||||||
|
send_control_message(conn, CONTROL_CMD_DONE, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_control_error(connection_t *conn, uint16_t error, const char *message)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
size_t len;
|
||||||
|
set_uint16(buf, htons(error));
|
||||||
|
len = strlen(message);
|
||||||
|
tor_assert(len < (256-2));
|
||||||
|
memcpy(buf+2, message, len);
|
||||||
|
send_control_message(conn, CONTROL_CMD_ERROR, len+2, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_control_event(uint16_t event, uint16_t len, const char *body)
|
||||||
|
{
|
||||||
|
connection_t **conns;
|
||||||
|
int n_conns, i;
|
||||||
|
|
||||||
|
get_connection_array(&conns, &n_conns);
|
||||||
|
for (i = 0; i < n_conns; ++i) {
|
||||||
|
if (conns[i]->type == CONN_TYPE_CONTROL &&
|
||||||
|
conns[i]->state == CONTROL_CONN_STATE_OPEN &&
|
||||||
|
conns[i]->event_mask & (1<<event)) {
|
||||||
|
send_control_message(conns[i], CONTROL_CMD_EVENT, len, body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handle_control_setconf(connection_t *conn, uint16_t len,
|
||||||
|
const char *body)
|
||||||
|
{
|
||||||
|
/* XXXX009 NM */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int handle_control_getconf(connection_t *conn, uint16_t len,
|
||||||
|
const char *body)
|
||||||
|
{
|
||||||
|
/* XXXX009 NM */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int handle_control_setevents(connection_t *conn, uint16_t len,
|
||||||
|
const char *body)
|
||||||
|
{
|
||||||
|
uint16_t event_code;
|
||||||
|
uint32_t event_mask = 0;
|
||||||
|
if (len % 2) {
|
||||||
|
send_control_error(conn, ERR_UNSPECIFIED,
|
||||||
|
"Odd number of bytes in setevents message");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; len; len -= 2, body += 2) {
|
||||||
|
event_code = ntohs(get_uint16(body));
|
||||||
|
if (event_code < _EVENT_MIN || event_code > _EVENT_MAX) {
|
||||||
|
send_control_error(conn, ERR_UNRECOGNIZED_EVENT_CODE,
|
||||||
|
"Unrecognized event code");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
event_mask |= (1 << event_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->event_mask = event_mask;
|
||||||
|
|
||||||
|
update_global_event_mask();
|
||||||
|
send_control_done(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int handle_control_authenticate(connection_t *conn, uint16_t len,
|
||||||
|
const char *body)
|
||||||
|
{
|
||||||
|
if (0/* XXXX009 NM */) {
|
||||||
|
send_control_done(conn);
|
||||||
|
conn->state = CONTROL_CONN_STATE_OPEN;
|
||||||
|
} else {
|
||||||
|
send_control_error(conn, ERR_FAILED_AUTHENTICATION,"Authentication failed");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connection_control_finished_flushing(connection_t *conn) {
|
||||||
|
tor_assert(conn);
|
||||||
|
tor_assert(conn->type == CONN_TYPE_CONTROL);
|
||||||
|
|
||||||
|
connection_stop_writing(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connection_control_process_inbuf(connection_t *conn) {
|
||||||
|
uint16_t body_len, command_type;
|
||||||
|
char *body;
|
||||||
|
|
||||||
|
tor_assert(conn);
|
||||||
|
tor_assert(conn->type == CONN_TYPE_CONTROL);
|
||||||
|
|
||||||
|
again:
|
||||||
|
switch(fetch_from_buf_control(conn->inbuf, &body_len, &command_type, &body))
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
log_fn(LOG_WARN, "Error in control command. Failing.");
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
/* Control command not all here yet. Wait. */
|
||||||
|
return 0;
|
||||||
|
case 1:
|
||||||
|
/* We got a command. Process it. */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tor_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We got a command. If we need authentication, only authentication
|
||||||
|
* commands will be considered. */
|
||||||
|
if (conn->state == CONTROL_CONN_STATE_NEEDAUTH &&
|
||||||
|
command_type != CONTROL_CMD_AUTHENTICATE) {
|
||||||
|
log_fn(LOG_WARN, "Rejecting '%s' command; authentication needed.",
|
||||||
|
control_cmd_to_string(command_type));
|
||||||
|
send_control_error(conn, ERR_UNAUTHORIZED_USER, "Authentication required");
|
||||||
|
tor_free(body);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(command_type)
|
||||||
|
{
|
||||||
|
case CONTROL_CMD_SETCONF:
|
||||||
|
if (handle_control_setconf(conn, body_len, body))
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case CONTROL_CMD_GETCONF:
|
||||||
|
if (handle_control_getconf(conn, body_len, body))
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case CONTROL_CMD_SETEVENTS:
|
||||||
|
if (handle_control_setevents(conn, body_len, body))
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case CONTROL_CMD_AUTHENTICATE:
|
||||||
|
if (handle_control_authenticate(conn, body_len, body))
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case CONTROL_CMD_ERROR:
|
||||||
|
case CONTROL_CMD_DONE:
|
||||||
|
case CONTROL_CMD_CONFVALUE:
|
||||||
|
case CONTROL_CMD_EVENT:
|
||||||
|
log_fn(LOG_WARN, "Received client-only '%s' command; ignoring.",
|
||||||
|
control_cmd_to_string(command_type));
|
||||||
|
send_control_error(conn, ERR_UNRECOGNIZED_TYPE,
|
||||||
|
"Command type only valid from server tor client");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_fn(LOG_WARN, "Received unrecognized command type %d; ignoring.",
|
||||||
|
(int)command_type);
|
||||||
|
send_control_error(conn, ERR_UNRECOGNIZED_TYPE,
|
||||||
|
"Unrecognized command type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tor_free(body);
|
||||||
|
goto again; /* There might be more data. */
|
||||||
|
}
|
||||||
|
|
||||||
|
int control_event_circuit_status(circuit_t *circ)
|
||||||
|
{
|
||||||
|
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* XXXXX009 NM */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int control_event_stream_status(connection_t *conn)
|
||||||
|
{
|
||||||
|
tor_assert(conn->type == CONN_TYPE_AP);
|
||||||
|
|
||||||
|
if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* XXXXX009 NM */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int control_event_or_conn_status(connection_t *conn)
|
||||||
|
{
|
||||||
|
tor_assert(conn->type == CONN_TYPE_OR);
|
||||||
|
|
||||||
|
if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* XXXXX009 NM */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written)
|
||||||
|
{
|
||||||
|
char buf[8];
|
||||||
|
|
||||||
|
if (!EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
set_uint32(buf, htonl(n_read));
|
||||||
|
set_uint32(buf+4, htonl(n_read));
|
||||||
|
send_control_event(EVENT_BANDWIDTH_USED, 8, buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int control_event_warning(const char *msg)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
if (!EVENT_IS_INTERESTING(EVENT_WARNING))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = strlen(msg);
|
||||||
|
send_control_event(EVENT_WARNING, len+1, msg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variabls:
|
||||||
|
mode:c
|
||||||
|
indent-tabs-mode:nil
|
||||||
|
c-basic-offset:2
|
||||||
|
End:
|
||||||
|
*/
|
26
src/or/or.h
26
src/or/or.h
@ -171,7 +171,11 @@
|
|||||||
#define CONN_TYPE_DNSWORKER 10
|
#define CONN_TYPE_DNSWORKER 10
|
||||||
/** Type for connections to local cpuworker processes. */
|
/** Type for connections to local cpuworker processes. */
|
||||||
#define CONN_TYPE_CPUWORKER 11
|
#define CONN_TYPE_CPUWORKER 11
|
||||||
#define _CONN_TYPE_MAX 11
|
/** Type for listenting for connections from user interface process */
|
||||||
|
#define CONN_TYPE_CONTROL_LISTENER 12
|
||||||
|
/** Type for connections from user interface process */
|
||||||
|
#define CONN_TYPE_CONTROL 13
|
||||||
|
#define _CONN_TYPE_MAX 13
|
||||||
|
|
||||||
/** State for any listener connection. */
|
/** State for any listener connection. */
|
||||||
#define LISTENER_STATE_READY 0
|
#define LISTENER_STATE_READY 0
|
||||||
@ -247,6 +251,11 @@
|
|||||||
#define DIR_CONN_STATE_SERVER_WRITING 5
|
#define DIR_CONN_STATE_SERVER_WRITING 5
|
||||||
#define _DIR_CONN_STATE_MAX 5
|
#define _DIR_CONN_STATE_MAX 5
|
||||||
|
|
||||||
|
#define _CONTROL_CONN_STATE_MIN 1
|
||||||
|
#define CONTROL_CONN_STATE_OPEN 1
|
||||||
|
#define CONTROL_CONN_STATE_NEEDAUTH 2
|
||||||
|
#define _CONTROL_CONN_STATE_MAX 2
|
||||||
|
|
||||||
#define _DIR_PURPOSE_MIN 1
|
#define _DIR_PURPOSE_MIN 1
|
||||||
/** Purpose for connection to directory server: download a directory. */
|
/** Purpose for connection to directory server: download a directory. */
|
||||||
#define DIR_PURPOSE_FETCH_DIR 1
|
#define DIR_PURPOSE_FETCH_DIR 1
|
||||||
@ -546,6 +555,9 @@ struct connection_t {
|
|||||||
/* Used only by AP connections */
|
/* Used only by AP connections */
|
||||||
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
|
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
|
||||||
* only.) */
|
* only.) */
|
||||||
|
|
||||||
|
/* Used only by control connections */
|
||||||
|
uint32_t event_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct connection_t connection_t;
|
typedef struct connection_t connection_t;
|
||||||
@ -981,6 +993,8 @@ int fetch_from_buf_http(buf_t *buf,
|
|||||||
char **headers_out, size_t max_headerlen,
|
char **headers_out, size_t max_headerlen,
|
||||||
char **body_out, size_t *body_used, size_t max_bodylen);
|
char **body_out, size_t *body_used, size_t max_bodylen);
|
||||||
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req);
|
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req);
|
||||||
|
int fetch_from_buf_control(buf_t *buf, uint16_t *len_out, uint16_t *type_out,
|
||||||
|
char **body_out);
|
||||||
|
|
||||||
void assert_buf_ok(buf_t *buf);
|
void assert_buf_ok(buf_t *buf);
|
||||||
|
|
||||||
@ -1186,6 +1200,16 @@ int connection_tls_continue_handshake(connection_t *conn);
|
|||||||
void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
|
void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
|
||||||
void connection_or_update_nickname(connection_t *conn);
|
void connection_or_update_nickname(connection_t *conn);
|
||||||
|
|
||||||
|
/********************************* control.c ***************************/
|
||||||
|
|
||||||
|
int connection_control_finished_flushing(connection_t *conn);
|
||||||
|
int connection_control_process_inbuf(connection_t *conn);
|
||||||
|
|
||||||
|
int control_event_circuit_status(circuit_t *circ);
|
||||||
|
int control_event_stream_status(connection_t *conn);
|
||||||
|
int control_event_or_conn_status(connection_t *conn);
|
||||||
|
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);
|
||||||
|
int control_event_warning(const char *msg);
|
||||||
|
|
||||||
/********************************* cpuworker.c *****************************/
|
/********************************* cpuworker.c *****************************/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user