mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-13 22:53:44 +01:00
Move dirserv/routers code out of main.c
svn:r527
This commit is contained in:
parent
f694ab23f5
commit
df5c7534b1
2
doc/TODO
2
doc/TODO
@ -60,7 +60,7 @@ ARMA . add log convention to the HACKING file
|
|||||||
keydir under that with fixed names
|
keydir under that with fixed names
|
||||||
ARMA - tor faq
|
ARMA - tor faq
|
||||||
list all other systems, why we're different.
|
list all other systems, why we're different.
|
||||||
NICK - Move (most of) the router/directory code out of main.c
|
o Move (most of) the router/directory code out of main.c
|
||||||
|
|
||||||
Mid-term:
|
Mid-term:
|
||||||
. Redo scheduler
|
. Redo scheduler
|
||||||
|
@ -10,6 +10,8 @@ static int the_directory_is_dirty = 1;
|
|||||||
static char *the_directory = NULL;
|
static char *the_directory = NULL;
|
||||||
static int the_directory_len = -1;
|
static int the_directory_len = -1;
|
||||||
|
|
||||||
|
static int list_running_servers(char **nicknames_out);
|
||||||
|
|
||||||
/************** Fingerprint handling code ************/
|
/************** Fingerprint handling code ************/
|
||||||
|
|
||||||
typedef struct fingerprint_entry_t {
|
typedef struct fingerprint_entry_t {
|
||||||
@ -291,6 +293,46 @@ dirserv_init_from_directory_string(const char *dir)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
list_running_servers(char **nicknames_out)
|
||||||
|
{
|
||||||
|
char *nickname_lst[MAX_ROUTERS_IN_DIR];
|
||||||
|
connection_t **connection_array;
|
||||||
|
int n_conns;
|
||||||
|
connection_t *conn;
|
||||||
|
char *cp;
|
||||||
|
int n = 0, i;
|
||||||
|
int length;
|
||||||
|
*nicknames_out = NULL;
|
||||||
|
nickname_lst[n++] = options.Nickname;
|
||||||
|
|
||||||
|
get_connection_array(&connection_array, &n_conns);
|
||||||
|
for (i = 0; i<n_conns; ++i) {
|
||||||
|
conn = connection_array[i];
|
||||||
|
if (conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN)
|
||||||
|
continue; /* only list successfully handshaked OR's. */
|
||||||
|
if(!conn->nickname) /* it's an OP, don't list it */
|
||||||
|
continue;
|
||||||
|
nickname_lst[n++] = conn->nickname;
|
||||||
|
}
|
||||||
|
length = n + 1; /* spaces + EOS + 1. */
|
||||||
|
for (i = 0; i<n; ++i) {
|
||||||
|
length += strlen(nickname_lst[i]);
|
||||||
|
}
|
||||||
|
*nicknames_out = tor_malloc(length);
|
||||||
|
cp = *nicknames_out;
|
||||||
|
memset(cp,0,length);
|
||||||
|
for (i = 0; i<n; ++i) {
|
||||||
|
if (i)
|
||||||
|
strcat(cp, " ");
|
||||||
|
strcat(cp, nickname_lst[i]);
|
||||||
|
while (*cp)
|
||||||
|
++cp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dirserv_dump_directory_to_string(char *s, int maxlen,
|
dirserv_dump_directory_to_string(char *s, int maxlen,
|
||||||
crypto_pk_env_t *private_key)
|
crypto_pk_env_t *private_key)
|
||||||
|
209
src/or/main.c
209
src/or/main.c
@ -3,9 +3,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
#ifdef HAVE_UNAME
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/********* START PROTOTYPES **********/
|
/********* START PROTOTYPES **********/
|
||||||
|
|
||||||
@ -38,8 +35,6 @@ static crypto_pk_env_t *onionkey=NULL;
|
|||||||
static crypto_pk_env_t *linkkey=NULL;
|
static crypto_pk_env_t *linkkey=NULL;
|
||||||
static crypto_pk_env_t *identitykey=NULL;
|
static crypto_pk_env_t *identitykey=NULL;
|
||||||
|
|
||||||
routerinfo_t *my_routerinfo=NULL;
|
|
||||||
|
|
||||||
/********* END VARIABLES ************/
|
/********* END VARIABLES ************/
|
||||||
|
|
||||||
void set_onion_key(crypto_pk_env_t *k) {
|
void set_onion_key(crypto_pk_env_t *k) {
|
||||||
@ -279,12 +274,8 @@ static int prepare_for_poll(void) {
|
|||||||
if(time_to_fetch_directory < now.tv_sec) {
|
if(time_to_fetch_directory < now.tv_sec) {
|
||||||
/* it's time to fetch a new directory and/or post our descriptor */
|
/* it's time to fetch a new directory and/or post our descriptor */
|
||||||
if(options.OnionRouter) {
|
if(options.OnionRouter) {
|
||||||
if (init_descriptor()<0) {
|
|
||||||
log_fn(LOG_WARNING, "Error initializing descriptor. Not uploading desc.");
|
|
||||||
} else {
|
|
||||||
router_upload_desc_to_dirservers();
|
router_upload_desc_to_dirservers();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(!options.DirPort) {
|
if(!options.DirPort) {
|
||||||
/* NOTE directory servers do not currently fetch directories.
|
/* NOTE directory servers do not currently fetch directories.
|
||||||
* Hope this doesn't bite us later. */
|
* Hope this doesn't bite us later. */
|
||||||
@ -482,7 +473,7 @@ static int init_keys(void)
|
|||||||
}
|
}
|
||||||
/* 4. Dump router descriptor to 'router.desc' */
|
/* 4. Dump router descriptor to 'router.desc' */
|
||||||
/* Must be called after keys are initialized. */
|
/* Must be called after keys are initialized. */
|
||||||
if (init_descriptor()<0) {
|
if (!(router_get_my_descriptor())) {
|
||||||
log_fn(LOG_ERR, "Error initializing descriptor.");
|
log_fn(LOG_ERR, "Error initializing descriptor.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -681,204 +672,6 @@ static void dumpstats(void) { /* dump stats to stdout */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_platform_str(char *platform, int len)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_UNAME
|
|
||||||
struct utsname u;
|
|
||||||
if (!uname(&u)) {
|
|
||||||
snprintf(platform, len-1, "Tor %s on %s %s %s %s %s",
|
|
||||||
VERSION, u.sysname, u.nodename, u.release, u.version, u.machine);
|
|
||||||
platform[len-1] = '\0';
|
|
||||||
return;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
snprintf(platform, len-1, "Tor %s", VERSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
|
||||||
crypto_pk_env_t *ident_key) {
|
|
||||||
char *onion_pkey;
|
|
||||||
char *link_pkey;
|
|
||||||
char *identity_pkey;
|
|
||||||
char platform[256];
|
|
||||||
char digest[20];
|
|
||||||
char signature[128];
|
|
||||||
char published[32];
|
|
||||||
int onion_pkeylen, link_pkeylen, identity_pkeylen;
|
|
||||||
int written;
|
|
||||||
int result=0;
|
|
||||||
struct exit_policy_t *tmpe;
|
|
||||||
|
|
||||||
get_platform_str(platform, sizeof(platform));
|
|
||||||
|
|
||||||
if(crypto_pk_write_public_key_to_string(router->onion_pkey,
|
|
||||||
&onion_pkey,&onion_pkeylen)<0) {
|
|
||||||
log_fn(LOG_WARNING,"write onion_pkey to string failed!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(crypto_pk_write_public_key_to_string(router->identity_pkey,
|
|
||||||
&identity_pkey,&identity_pkeylen)<0) {
|
|
||||||
log_fn(LOG_WARNING,"write identity_pkey to string failed!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(crypto_pk_write_public_key_to_string(router->link_pkey,
|
|
||||||
&link_pkey,&link_pkeylen)<0) {
|
|
||||||
log_fn(LOG_WARNING,"write link_pkey to string failed!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&router->published_on));
|
|
||||||
|
|
||||||
result = snprintf(s, maxlen,
|
|
||||||
"router %s %s %d %d %d %d\n"
|
|
||||||
"platform %s\n"
|
|
||||||
"published %s\n"
|
|
||||||
"onion-key\n%s"
|
|
||||||
"link-key\n%s"
|
|
||||||
"signing-key\n%s",
|
|
||||||
router->nickname,
|
|
||||||
router->address,
|
|
||||||
router->or_port,
|
|
||||||
router->ap_port,
|
|
||||||
router->dir_port,
|
|
||||||
router->bandwidth,
|
|
||||||
platform,
|
|
||||||
published,
|
|
||||||
onion_pkey, link_pkey, identity_pkey);
|
|
||||||
|
|
||||||
free(onion_pkey);
|
|
||||||
free(link_pkey);
|
|
||||||
free(identity_pkey);
|
|
||||||
|
|
||||||
if(result < 0 || result >= maxlen) {
|
|
||||||
/* apparently different glibcs do different things on snprintf error.. so check both */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
written = result;
|
|
||||||
|
|
||||||
for(tmpe=router->exit_policy; tmpe; tmpe=tmpe->next) {
|
|
||||||
result = snprintf(s+written, maxlen-written, "%s %s:%s\n",
|
|
||||||
tmpe->policy_type == EXIT_POLICY_ACCEPT ? "accept" : "reject",
|
|
||||||
tmpe->address, tmpe->port);
|
|
||||||
if(result < 0 || result+written > maxlen) {
|
|
||||||
/* apparently different glibcs do different things on snprintf error.. so check both */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
written += result;
|
|
||||||
}
|
|
||||||
if (written > maxlen-256) /* Not enough room for signature. */
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
strcat(s+written, "router-signature\n");
|
|
||||||
written += strlen(s+written);
|
|
||||||
s[written] = '\0';
|
|
||||||
if (router_get_router_hash(s, digest) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (crypto_pk_private_sign(ident_key, digest, 20, signature) < 0) {
|
|
||||||
log_fn(LOG_WARNING, "Error signing digest");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strcat(s+written, "-----BEGIN SIGNATURE-----\n");
|
|
||||||
written += strlen(s+written);
|
|
||||||
if (base64_encode(s+written, maxlen-written, signature, 128) < 0) {
|
|
||||||
log_fn(LOG_WARNING, "Couldn't base64-encode signature");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
written += strlen(s+written);
|
|
||||||
strcat(s+written, "-----END SIGNATURE-----\n");
|
|
||||||
written += strlen(s+written);
|
|
||||||
|
|
||||||
if (written > maxlen-2)
|
|
||||||
return -1;
|
|
||||||
/* include a last '\n' */
|
|
||||||
s[written] = '\n';
|
|
||||||
s[written+1] = 0;
|
|
||||||
return written+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
list_running_servers(char **nicknames_out)
|
|
||||||
{
|
|
||||||
char *nickname_lst[MAX_ROUTERS_IN_DIR];
|
|
||||||
connection_t *conn;
|
|
||||||
char *cp;
|
|
||||||
int n = 0, i;
|
|
||||||
int length;
|
|
||||||
*nicknames_out = NULL;
|
|
||||||
if (my_routerinfo)
|
|
||||||
nickname_lst[n++] = my_routerinfo->nickname;
|
|
||||||
for (i = 0; i<nfds; ++i) {
|
|
||||||
conn = connection_array[i];
|
|
||||||
if (conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN)
|
|
||||||
continue; /* only list successfully handshaked OR's. */
|
|
||||||
if(!conn->nickname) /* it's an OP, don't list it */
|
|
||||||
continue;
|
|
||||||
nickname_lst[n++] = conn->nickname;
|
|
||||||
}
|
|
||||||
length = n + 1; /* spaces + EOS + 1. */
|
|
||||||
for (i = 0; i<n; ++i) {
|
|
||||||
length += strlen(nickname_lst[i]);
|
|
||||||
}
|
|
||||||
*nicknames_out = tor_malloc(length);
|
|
||||||
cp = *nicknames_out;
|
|
||||||
memset(cp,0,length);
|
|
||||||
for (i = 0; i<n; ++i) {
|
|
||||||
if (i)
|
|
||||||
strcat(cp, " ");
|
|
||||||
strcat(cp, nickname_lst[i]);
|
|
||||||
while (*cp)
|
|
||||||
++cp;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char descriptor[8192];
|
|
||||||
/* XXX should this replace my_routerinfo? */
|
|
||||||
static routerinfo_t *desc_routerinfo;
|
|
||||||
const char *router_get_my_descriptor(void) {
|
|
||||||
log_fn(LOG_DEBUG,"my desc is '%s'",descriptor);
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_descriptor(void) {
|
|
||||||
routerinfo_t *ri;
|
|
||||||
char localhostname[256];
|
|
||||||
char *address = options.Address;
|
|
||||||
|
|
||||||
if(!address) { /* if not specified in config, we find a default */
|
|
||||||
if(gethostname(localhostname,sizeof(localhostname)) < 0) {
|
|
||||||
log_fn(LOG_WARNING,"Error obtaining local hostname");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
address = localhostname;
|
|
||||||
}
|
|
||||||
ri = tor_malloc(sizeof(routerinfo_t));
|
|
||||||
ri->address = strdup(address);
|
|
||||||
ri->nickname = strdup(options.Nickname);
|
|
||||||
/* No need to set addr. */
|
|
||||||
ri->or_port = options.ORPort;
|
|
||||||
ri->ap_port = options.APPort;
|
|
||||||
ri->dir_port = options.DirPort;
|
|
||||||
ri->published_on = time(NULL);
|
|
||||||
ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
|
|
||||||
ri->link_pkey = crypto_pk_dup_key(get_link_key());
|
|
||||||
ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
|
|
||||||
ri->bandwidth = options.TotalBandwidth;
|
|
||||||
ri->exit_policy = NULL; /* XXX implement this. */
|
|
||||||
if (desc_routerinfo)
|
|
||||||
routerinfo_free(desc_routerinfo);
|
|
||||||
desc_routerinfo = ri;
|
|
||||||
if (dump_router_to_string(descriptor, 8192, ri, get_identity_key())<0) {
|
|
||||||
log_fn(LOG_WARNING, "Couldn't dump router to string.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void daemonize(void) {
|
void daemonize(void) {
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
/* Fork; parent exits. */
|
/* Fork; parent exits. */
|
||||||
|
@ -616,6 +616,7 @@ void set_onion_key(crypto_pk_env_t *k);
|
|||||||
crypto_pk_env_t *get_onion_key(void);
|
crypto_pk_env_t *get_onion_key(void);
|
||||||
void set_identity_key(crypto_pk_env_t *k);
|
void set_identity_key(crypto_pk_env_t *k);
|
||||||
crypto_pk_env_t *get_identity_key(void);
|
crypto_pk_env_t *get_identity_key(void);
|
||||||
|
crypto_pk_env_t *get_link_key(void);
|
||||||
int connection_add(connection_t *conn);
|
int connection_add(connection_t *conn);
|
||||||
int connection_remove(connection_t *conn);
|
int connection_remove(connection_t *conn);
|
||||||
void connection_set_poll_socket(connection_t *conn);
|
void connection_set_poll_socket(connection_t *conn);
|
||||||
@ -629,8 +630,6 @@ void connection_start_reading(connection_t *conn);
|
|||||||
void connection_stop_writing(connection_t *conn);
|
void connection_stop_writing(connection_t *conn);
|
||||||
void connection_start_writing(connection_t *conn);
|
void connection_start_writing(connection_t *conn);
|
||||||
|
|
||||||
int list_running_servers(char **nicknames_out);
|
|
||||||
|
|
||||||
const char *router_get_my_descriptor(void);
|
const char *router_get_my_descriptor(void);
|
||||||
|
|
||||||
int main(int argc, char *argv[]);
|
int main(int argc, char *argv[]);
|
||||||
@ -691,6 +690,10 @@ int router_get_dir_from_string_impl(char *s, directory_t **dest,
|
|||||||
routerinfo_t *router_get_entry_from_string(char **s);
|
routerinfo_t *router_get_entry_from_string(char **s);
|
||||||
int router_compare_to_exit_policy(connection_t *conn);
|
int router_compare_to_exit_policy(connection_t *conn);
|
||||||
void routerinfo_free(routerinfo_t *router);
|
void routerinfo_free(routerinfo_t *router);
|
||||||
|
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||||
|
crypto_pk_env_t *ident_key);
|
||||||
|
const routerinfo_t *router_get_desc_routerinfo(void);
|
||||||
|
const char *router_get_my_descriptor(void);
|
||||||
|
|
||||||
/********************************* dirserv.c ***************************/
|
/********************************* dirserv.c ***************************/
|
||||||
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
|
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
|
||||||
|
189
src/or/routers.c
189
src/or/routers.c
@ -13,6 +13,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
|
#ifdef HAVE_UNAME
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
@ -20,7 +23,7 @@
|
|||||||
static directory_t *directory = NULL;
|
static directory_t *directory = NULL;
|
||||||
|
|
||||||
extern or_options_t options; /* command-line and config-file options */
|
extern or_options_t options; /* command-line and config-file options */
|
||||||
extern routerinfo_t *my_routerinfo; /* from main.c */
|
static routerinfo_t *my_routerinfo;
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
@ -35,8 +38,8 @@ static char *find_whitespace(char *s);
|
|||||||
static void router_free_exit_policy(routerinfo_t *router);
|
static void router_free_exit_policy(routerinfo_t *router);
|
||||||
static int router_add_exit_policy(routerinfo_t *router,
|
static int router_add_exit_policy(routerinfo_t *router,
|
||||||
directory_token_t *tok);
|
directory_token_t *tok);
|
||||||
static int
|
static int router_resolve_directory(directory_t *dir);
|
||||||
router_resolve_directory(directory_t *dir);
|
static int init_descriptor(void);
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
@ -113,6 +116,11 @@ void router_upload_desc_to_dirservers(void) {
|
|||||||
if(!directory)
|
if(!directory)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!router_get_my_descriptor()) {
|
||||||
|
log_fn(LOG_WARNING, "No descriptor; skipping upload");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(i=0;i<directory->n_routers;i++) {
|
for(i=0;i<directory->n_routers;i++) {
|
||||||
router = directory->routers[i];
|
router = directory->routers[i];
|
||||||
if(router->dir_port > 0)
|
if(router->dir_port > 0)
|
||||||
@ -1087,6 +1095,181 @@ int router_compare_to_exit_policy(connection_t *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char descriptor[8192];
|
||||||
|
/* XXX should this replace my_routerinfo? */
|
||||||
|
static routerinfo_t *desc_routerinfo = NULL;
|
||||||
|
const char *router_get_my_descriptor(void) {
|
||||||
|
if (!desc_routerinfo) {
|
||||||
|
if (init_descriptor())
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
log_fn(LOG_DEBUG,"my desc is '%s'",descriptor);
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
const routerinfo_t *router_get_desc_routerinfo(void) {
|
||||||
|
if (!desc_routerinfo) {
|
||||||
|
if (init_descriptor())
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return desc_routerinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int init_descriptor(void) {
|
||||||
|
routerinfo_t *ri;
|
||||||
|
char localhostname[256];
|
||||||
|
char *address = options.Address;
|
||||||
|
|
||||||
|
if(!address) { /* if not specified in config, we find a default */
|
||||||
|
if(gethostname(localhostname,sizeof(localhostname)) < 0) {
|
||||||
|
log_fn(LOG_WARNING,"Error obtaining local hostname");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
address = localhostname;
|
||||||
|
}
|
||||||
|
ri = tor_malloc(sizeof(routerinfo_t));
|
||||||
|
ri->address = strdup(address);
|
||||||
|
ri->nickname = strdup(options.Nickname);
|
||||||
|
/* No need to set addr. */
|
||||||
|
ri->or_port = options.ORPort;
|
||||||
|
ri->ap_port = options.APPort;
|
||||||
|
ri->dir_port = options.DirPort;
|
||||||
|
ri->published_on = time(NULL);
|
||||||
|
ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
|
||||||
|
ri->link_pkey = crypto_pk_dup_key(get_link_key());
|
||||||
|
ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
|
||||||
|
ri->bandwidth = options.TotalBandwidth;
|
||||||
|
ri->exit_policy = NULL; /* XXX implement this. */
|
||||||
|
if (desc_routerinfo)
|
||||||
|
routerinfo_free(desc_routerinfo);
|
||||||
|
desc_routerinfo = ri;
|
||||||
|
if (router_dump_router_to_string(descriptor, 8192, ri, get_identity_key())<0) {
|
||||||
|
log_fn(LOG_WARNING, "Couldn't dump router to string.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_platform_str(char *platform, int len)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_UNAME
|
||||||
|
struct utsname u;
|
||||||
|
if (!uname(&u)) {
|
||||||
|
snprintf(platform, len-1, "Tor %s on %s %s %s %s %s",
|
||||||
|
VERSION, u.sysname, u.nodename, u.release, u.version, u.machine);
|
||||||
|
platform[len-1] = '\0';
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
snprintf(platform, len-1, "Tor %s", VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||||
|
crypto_pk_env_t *ident_key) {
|
||||||
|
char *onion_pkey;
|
||||||
|
char *link_pkey;
|
||||||
|
char *identity_pkey;
|
||||||
|
char platform[256];
|
||||||
|
char digest[20];
|
||||||
|
char signature[128];
|
||||||
|
char published[32];
|
||||||
|
int onion_pkeylen, link_pkeylen, identity_pkeylen;
|
||||||
|
int written;
|
||||||
|
int result=0;
|
||||||
|
struct exit_policy_t *tmpe;
|
||||||
|
|
||||||
|
get_platform_str(platform, sizeof(platform));
|
||||||
|
|
||||||
|
if(crypto_pk_write_public_key_to_string(router->onion_pkey,
|
||||||
|
&onion_pkey,&onion_pkeylen)<0) {
|
||||||
|
log_fn(LOG_WARNING,"write onion_pkey to string failed!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(crypto_pk_write_public_key_to_string(router->identity_pkey,
|
||||||
|
&identity_pkey,&identity_pkeylen)<0) {
|
||||||
|
log_fn(LOG_WARNING,"write identity_pkey to string failed!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(crypto_pk_write_public_key_to_string(router->link_pkey,
|
||||||
|
&link_pkey,&link_pkeylen)<0) {
|
||||||
|
log_fn(LOG_WARNING,"write link_pkey to string failed!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&router->published_on));
|
||||||
|
|
||||||
|
result = snprintf(s, maxlen,
|
||||||
|
"router %s %s %d %d %d %d\n"
|
||||||
|
"platform %s\n"
|
||||||
|
"published %s\n"
|
||||||
|
"onion-key\n%s"
|
||||||
|
"link-key\n%s"
|
||||||
|
"signing-key\n%s",
|
||||||
|
router->nickname,
|
||||||
|
router->address,
|
||||||
|
router->or_port,
|
||||||
|
router->ap_port,
|
||||||
|
router->dir_port,
|
||||||
|
router->bandwidth,
|
||||||
|
platform,
|
||||||
|
published,
|
||||||
|
onion_pkey, link_pkey, identity_pkey);
|
||||||
|
|
||||||
|
free(onion_pkey);
|
||||||
|
free(link_pkey);
|
||||||
|
free(identity_pkey);
|
||||||
|
|
||||||
|
if(result < 0 || result >= maxlen) {
|
||||||
|
/* apparently different glibcs do different things on snprintf error.. so check both */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
written = result;
|
||||||
|
|
||||||
|
for(tmpe=router->exit_policy; tmpe; tmpe=tmpe->next) {
|
||||||
|
result = snprintf(s+written, maxlen-written, "%s %s:%s\n",
|
||||||
|
tmpe->policy_type == EXIT_POLICY_ACCEPT ? "accept" : "reject",
|
||||||
|
tmpe->address, tmpe->port);
|
||||||
|
if(result < 0 || result+written > maxlen) {
|
||||||
|
/* apparently different glibcs do different things on snprintf error.. so check both */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
written += result;
|
||||||
|
}
|
||||||
|
if (written > maxlen-256) /* Not enough room for signature. */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
strcat(s+written, "router-signature\n");
|
||||||
|
written += strlen(s+written);
|
||||||
|
s[written] = '\0';
|
||||||
|
if (router_get_router_hash(s, digest) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (crypto_pk_private_sign(ident_key, digest, 20, signature) < 0) {
|
||||||
|
log_fn(LOG_WARNING, "Error signing digest");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strcat(s+written, "-----BEGIN SIGNATURE-----\n");
|
||||||
|
written += strlen(s+written);
|
||||||
|
if (base64_encode(s+written, maxlen-written, signature, 128) < 0) {
|
||||||
|
log_fn(LOG_WARNING, "Couldn't base64-encode signature");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
written += strlen(s+written);
|
||||||
|
strcat(s+written, "-----END SIGNATURE-----\n");
|
||||||
|
written += strlen(s+written);
|
||||||
|
|
||||||
|
if (written > maxlen-2)
|
||||||
|
return -1;
|
||||||
|
/* include a last '\n' */
|
||||||
|
s[written] = '\n';
|
||||||
|
s[written+1] = 0;
|
||||||
|
return written+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode:c
|
mode:c
|
||||||
|
Loading…
Reference in New Issue
Block a user