Commit df5c7534 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Move dirserv/routers code out of main.c


svn:r527
parent f694ab23
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ ARMA . add log convention to the HACKING file
          keydir under that with fixed names
ARMA    - tor faq
          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:
        . Redo scheduler
+42 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@ static int the_directory_is_dirty = 1;
static char *the_directory = NULL;
static int the_directory_len = -1;

static int list_running_servers(char **nicknames_out);

/************** Fingerprint handling code ************/

typedef struct fingerprint_entry_t {
@@ -291,6 +293,46 @@ dirserv_init_from_directory_string(const char *dir)
  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
dirserv_dump_directory_to_string(char *s, int maxlen,
                                 crypto_pk_env_t *private_key)
+2 −209
Original line number Diff line number Diff line
@@ -3,9 +3,6 @@
/* $Id$ */

#include "or.h"
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif

/********* 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 *identitykey=NULL;

routerinfo_t *my_routerinfo=NULL;

/********* END VARIABLES ************/

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) {
      /* it's time to fetch a new directory and/or post our descriptor */
      if(options.OnionRouter) {
        if (init_descriptor()<0) {
          log_fn(LOG_WARNING, "Error initializing descriptor. Not uploading desc.");
        } else {
           router_upload_desc_to_dirservers();
      }
      }
      if(!options.DirPort) {
        /* NOTE directory servers do not currently fetch directories.
         * Hope this doesn't bite us later. */
@@ -482,7 +473,7 @@ static int init_keys(void)
  }
  /* 4. Dump router descriptor to 'router.desc' */
  /* Must be called after keys are initialized. */
  if (init_descriptor()<0) {
  if (!(router_get_my_descriptor())) {
    log_fn(LOG_ERR, "Error initializing descriptor.");
    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) {
#ifndef MS_WINDOWS
  /* Fork; parent exits. */
+5 −2
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@ void set_onion_key(crypto_pk_env_t *k);
crypto_pk_env_t *get_onion_key(void);
void set_identity_key(crypto_pk_env_t *k);
crypto_pk_env_t *get_identity_key(void);
crypto_pk_env_t *get_link_key(void);
int connection_add(connection_t *conn);
int connection_remove(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_start_writing(connection_t *conn);

int list_running_servers(char **nicknames_out);

const char *router_get_my_descriptor(void);

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);
int router_compare_to_exit_policy(connection_t *conn);
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 ***************************/
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
+186 −3
Original line number Diff line number Diff line
@@ -13,6 +13,9 @@
 */

#include "or.h"
#ifdef HAVE_UNAME
#include <sys/utsname.h>
#endif

/****************************************************************************/

@@ -20,7 +23,7 @@
static directory_t *directory = NULL;

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 int router_add_exit_policy(routerinfo_t *router, 
                                  directory_token_t *tok);
static int 
router_resolve_directory(directory_t *dir);
static int router_resolve_directory(directory_t *dir);
static int init_descriptor(void);

/****************************************************************************/

@@ -113,6 +116,11 @@ void router_upload_desc_to_dirservers(void) {
  if(!directory)
    return;

  if (!router_get_my_descriptor()) {
    log_fn(LOG_WARNING, "No descriptor; skipping upload");
    return;
  }

  for(i=0;i<directory->n_routers;i++) {
    router = directory->routers[i];
    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:
  mode:c