remove popt dependency, consolidate config stuff

reformat parts of onion.c


svn:r136
This commit is contained in:
Roger Dingledine
2002-11-23 06:49:01 +00:00
parent 121d029584
commit 00a9e3732e
15 changed files with 605 additions and 1024 deletions
+15 -8
View File
@@ -3,8 +3,12 @@ described in a bit more detail at http://www.onion-router.net/. You
can read list archives, and subscribe to the mailing list, at can read list archives, and subscribe to the mailing list, at
http://archives.seul.org/or/dev/. http://archives.seul.org/or/dev/.
Is your question in the FAQ? Should it be?
Quickstart version: Quickstart version:
0) Download the absolute newest version. No, really.
http://freehaven.net/or/.
1) ./configure (or do the two-line version below, if you're on bsd) 1) ./configure (or do the two-line version below, if you're on bsd)
2) make 2) make
3) cd src/config 3) cd src/config
@@ -12,9 +16,11 @@ Quickstart version:
5) download privoxy (www.privoxy.org), and add the line 5) download privoxy (www.privoxy.org), and add the line
"forward-socks4a / localhost:9050 ." (without the quotes) to its "forward-socks4a / localhost:9050 ." (without the quotes) to its
config file. config file.
6) point your mozilla (or whatever) to proxy at localhost:8118 (this 6) point your mozilla (or whatever) to http proxy at localhost:8118 (this
points it through Privoxy, so you now get good data-scrubbing too.) points it through Privoxy, so you now get good data-scrubbing too.)
7) browse some web pages 7) make sure you've set it up correctly: go to
http://www.junkbusters.com/cgi-bin/privacy and see what IP it says
you're coming from.
More detailed version: More detailed version:
@@ -23,10 +29,11 @@ Dependencies:
You're going to need Privoxy (www.privoxy.org) installed, and configured You're going to need Privoxy (www.privoxy.org) installed, and configured
to point at a socks4a proxy -- see below. to point at a socks4a proxy -- see below.
For tor itself, you're going to need openssl (0.9.5 or later) and popt For tor itself, you're going to need openssl (0.9.5 or later
(1.6 or later). If you're on Linux, everything will probably work -- including the dev stuff and includes). If you're on Linux,
fine. OS X and BSD (but see below under troubleshooting) now work everything will probably work fine. OS X and BSD (but see below under
too. Let us know if you get it working elsewhere. troubleshooting) now work too. Let us know if you get it working
elsewhere.
If you got the source from cvs: If you got the source from cvs:
@@ -41,10 +48,10 @@ If you got the source from a tarball:
If this doesn't work for you / troubleshooting: If this doesn't work for you / troubleshooting:
If you couldn't find popt (eg you're on BSD), try If you have problems finding libraries, try
CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" \ CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" \
./configure ./configure
rather than simply ./configure. And install popt if you don't have it. rather than simply ./configure.
Check out the list archives at http://archives.seul.org/or/dev/ and see Check out the list archives at http://archives.seul.org/or/dev/ and see
if somebody else has reported your problem. If not, please subscribe if somebody else has reported your problem. If not, please subscribe
+1 -2
View File
@@ -1,4 +1,3 @@
[First four are all equally first. [First four are all equally first.
Others follow in order of priority.] Others follow in order of priority.]
@@ -34,7 +33,7 @@ and directory/network state monitoring.
debian / red hat spec file debian / red hat spec file
handle starting things as a system daemon handle starting things as a system daemon
transition addr to sin_addr transition addr to sin_addr
get proxy to choose the same conn if it's open
Obvious things I'd like to do that won't break anything: Obvious things I'd like to do that won't break anything:
-1
View File
@@ -1,3 +1,2 @@
#undef HAVE_POPT
#undef HAVE_OPENSSL #undef HAVE_OPENSSL
-8
View File
@@ -16,14 +16,6 @@ AC_PROG_MAKE_SET
AC_PROG_RANLIB AC_PROG_RANLIB
dnl AC_DEFINE([HAVE_OPENSSL], 0, [Define if OpenSSL was found.]) dnl AC_DEFINE([HAVE_OPENSSL], 0, [Define if OpenSSL was found.])
dnl AC_DEFINE([HAVE_POPT], 0, [Define if popt was found.])
AC_CHECK_LIB(popt,poptParseArgvString,
AC_DEFINE(HAVE_POPT),
AC_MSG_ERROR(required library not found: popt)
)
LIBS="$LIBS -lpopt"
# The big search for OpenSSL # The big search for OpenSSL
# copied from openssh's configure.ac # copied from openssh's configure.ac
+2 -4
View File
@@ -3,9 +3,7 @@ noinst_LIBRARIES = libor.a
#CFLAGS = -Wall -Wpointer-arith -O2 #CFLAGS = -Wall -Wpointer-arith -O2
libor_a_SOURCES = config.c log.c utils.c crypto.c fakepoll.c libor_a_SOURCES = log.c utils.c crypto.c fakepoll.c
noinst_HEADERS = config.h log.h \ noinst_HEADERS = log.h policies.h utils.h ss.h version.h crypto.h fakepoll.h
policies.h utils.h \
ss.h version.h crypto.h fakepoll.h
-415
View File
@@ -1,415 +0,0 @@
/*
* config.c
* Functions for the manipulation of configuration files.
*
* Matej Pfajfar <mp292@cam.ac.uk>
*/
/*
* Changes :
* $Log$
* Revision 1.5 2002/07/15 19:05:12 montrose
* bug-fix. poptReadDefaultOptions() should find and load ~/.<cmd>rc files now.
*
* Revision 1.4 2002/07/09 19:51:41 montrose
* Miscellaneous bug fixes / activated "make check" for src/or
*
* Revision 1.3 2002/07/03 16:31:22 montrose
* Added getoptions() and made minor adjustment to poptReadDefaultOptions()
*
* Revision 1.2 2002/06/28 18:14:55 montrose
* Added poptReadOptions() and poptReadDefaultOptions()
*
* Revision 1.1.1.1 2002/06/26 22:45:50 arma
* initial commit: current code
*
* Revision 1.7 2002/04/02 14:27:11 badbytes
* Final finishes.
*
* Revision 1.6 2002/01/27 19:23:03 mp292
* Fixed a bug in parameter checking.
*
* Revision 1.5 2002/01/26 18:42:15 mp292
* Reviewed according to Secure-Programs-HOWTO.
*
* Revision 1.4 2002/01/21 21:07:56 mp292
* Parameter checking was missing in some functions.
*
* Revision 1.3 2001/12/07 09:38:03 badbytes
* Tested.
*
* Revision 1.2 2001/12/06 15:43:50 badbytes
* config.c compiles. Proceeding to test it.
*
* Revision 1.1 2001/11/22 01:20:27 mp292
* Functions for dealing with configuration files.
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <popt.h>
#include <limits.h>
#include "config.h"
#include "log.h"
/* open configuration file for reading */
FILE *open_config(const unsigned char *filename)
{
FILE *f;
if (filename) /* non-NULL filename */
{
if (strspn(filename,CONFIG_LEGAL_FILENAME_CHARACTERS) == strlen(filename)) /* filename consists of legal characters only */
{
f = fopen(filename, "r");
return f;
} /* filename consists of legal characters only */
else /* illegal values in filename */
{
return NULL;
} /* illegal values in filename */
} /* non-NULL filename */
else /* NULL filename */
return NULL;
}
/* close configuration file */
int close_config(FILE *f)
{
int retval = 0;
if (f) /* valid file descriptor */
{
retval = fclose(f);
return retval;
} /* valid file descriptor */
else
return -1;
}
/* parse the config file and obtain the required option values */
int parse_config(FILE *f, config_opt_t *option)
{
unsigned char keyword[CONFIG_KEYWORD_MAXLEN+1]; /* for storing the option keyword */
unsigned char *buffer = NULL; /* option value */
size_t buflen = 0;
char *errtest = NULL; /* used for testing correctness of strtol() etc. */
unsigned int i_keyword = 0; /* current position within keyword */
unsigned int i_buf = 0; /* current position within buffer */
char c=0; /* input char */
unsigned int state=0; /* internal state
* 0 - trying to find a keyword
* 1 - reading a keyword
* 2 - keyword read and recognized, looking for the option value
* 3 - reading the option value
* 4 - option value read
* 5 - inside a comment
*/
int retval=0; /* return value */
int lineno=1; /* current line number */
int curopt=-1; /* current option, as an indexed in config_opt_t */
int i;
if ( (f==NULL) || (option==NULL) ) /* invalid parameters */
return -1;
fseek(f,0,SEEK_SET); /* make sure we start at the beginning of file */
for (;;) /* infinite loop */
{
c = getc(f);
if ((c == '\n') || (c == EOF))
{
if (state == 1) /* reading a keyboard */
{
log(LOG_ERR,"Error parsing the configuration file on line %d.", lineno);
i_keyword = 0;
state = 0;
retval = -1;
break;
} /* reading a keyboard */
else if (state == 2) /* keyword read and recognized */
{
log(LOG_ERR,"Error parsing option %s on line %d.",option[curopt].keyword, lineno);
i_keyword = 0;
state = 0;
option[curopt].err=-1;
retval = -1;
break;
} /* keyboard read and recognized */
else if (state == 3) /* reading the option value */
{
buffer[i_buf++] = 0; /* add NULL character to terminate the string */
state = 4;
/* conversion and copying the value into config_opt_t is done later on */
} /* reading the option value */
else if (state == 5) /* reached end of comment */
state = 0;
if (c == EOF)
{
log(LOG_DEBUG,"parse_config() : Reached eof on line %d.",lineno);
break;
}
else
{
log(LOG_DEBUG,"parse_config() : Reached eol on line %d.", lineno);
lineno++;
}
}
else if ( (state==0) && (c == '#') ) /* lines beginning with # are ignored */
{
log(LOG_DEBUG,"parse_config() : Line %d begins with #.",lineno);
state = 5;
}
else if ( (state==0) && (isspace(c)) ) /* leading whitespace is ignored */
;
else if ( (state==1) && (isspace(c)) ) /* have apparently read in all of the keyword */
{
keyword[i_keyword++] = 0;
curopt = -1;
for (i=0;option[i].keyword != NULL;i++) /* try and identify the keyword */
{
if (!strncmp(keyword,option[i].keyword,CONFIG_KEYWORD_MAXLEN))
{
curopt = i;
break;
}
} /* try and identify the keyword */
if (curopt == -1) /* can't recognise the keyword */
{
log(LOG_ERR,"Error parsing the configuration file. Cannot recognize keyword %s on line %d.",keyword,lineno);
retval=-1;
break;
}
else
state = 2;
}
else if ( (state==2) && (isspace(c)) ) /* whitespace separating keyword and value is ignored */
;
else if ( (state==3) && (isspace(c)) ) /* have apparently finished reading the option value */
{
buffer[i_buf++]=0;
state = 4;
}
else /* all other characters */
{
if (state == 0) /* first character of the keyword */
{
log(LOG_DEBUG, "parse_config() : %c is the start of a keyword on line %d.",c,lineno);
state = 1;
i_keyword = 0;
keyword[i_keyword++] = c;
}
else if (state == 1) /* keep on reading the keyword */
{
log(LOG_DEBUG,"parse_config() : %c is a character in the keyword on line %d.",c,lineno);
if (i_keyword < CONFIG_KEYWORD_MAXLEN) /* check for buffer overflow */
keyword[i_keyword++] = c;
else
{
log(LOG_ERR,"Error parsing the configuration file. Keyword on line %d exceeds %d characters.",lineno,CONFIG_KEYWORD_MAXLEN);
retval=-1;
break;
}
}
else if (state == 2) /* first character of the value */
{
log(LOG_DEBUG,"parse_config() : %c is the first character of the option value on line %d.",c,lineno);
state = 3;
i_buf=0;
buflen = CONFIG_VALUE_MAXLEN+1; /* allocate memory for the value buffer */
buffer = (char *)malloc(buflen);
if (!buffer)
{
log(LOG_ERR,"Could not allocate memory.");
retval=-1;
break;
} else
buffer[i_buf++]=c;
}
else if (state == 3) /* keep on reading the value */
{
log(LOG_DEBUG,"parse_config() : %c is a character in the value of the keyword on line %d.",c,lineno);
if (i_buf >= buflen)
{
log(LOG_ERR,"Length of keyword value on line %u exceeds the length limit (%u).",lineno, CONFIG_VALUE_MAXLEN);
retval=-1;
break;
}
buffer[i_buf++]=c;
}
else if (state == 5)
; /* character is part of a comment, skip */
else /* unexpected error */
{
log(LOG_ERR,"Unexpected error while parsing the configuration file.");
log(LOG_DEBUG,"parse_config() : Encountered a non-delimiter character while not in states 0,1,2 or 3!");
break;
}
}
if (state==4) /* convert the value of the option to the appropriate type and write into OPT */
{
switch(option[curopt].r_type) /* consider each type separately */
{
case CONFIG_TYPE_STRING:
/* resize the buffer to fit the data exactly */
buffer = (char *)realloc(buffer,i_buf);
if (!buffer)
{
log(LOG_ERR,"Could not allocate memory.");
return -1;
}
option[curopt].r.str = buffer;
option[curopt].err = 1;
break;
case CONFIG_TYPE_CHAR:
option[curopt].r.c = *buffer;
option[curopt].err = 1;
break;
case CONFIG_TYPE_INT:
errtest = NULL;
option[curopt].r.i = (int)strtol(buffer,&errtest,0);
if ((unsigned char *)errtest == buffer)
{
log(LOG_ERR, "Error parsing configuration file. Option %s on line %d does not seem to be of the required type.\n",option[curopt].keyword,--lineno);
option[curopt].err = -1;
if (buffer)
free(buffer);
return -1;
}
else
option[curopt].err = 1;
break;
case CONFIG_TYPE_LONG:
errtest = NULL;
option[curopt].r.l = strtol(buffer,&errtest,0);
if ((unsigned char *)errtest == buffer)
{
log(LOG_ERR, "Error parsing configuration file. Option %s on line %d does not seem to be of the required type.\n",option[curopt].keyword,--lineno);
option[curopt].err = -1;
if (buffer)
free(buffer);
return -1;
}
else
option[curopt].err = 1;
break;
case CONFIG_TYPE_DOUBLE:
errtest = NULL;
option[curopt].r.d = strtod(buffer,&errtest);
if ((unsigned char *)errtest == buffer)
{
log(LOG_ERR, "Error parsing configuration file. Option %s on line %d does not seem to be of the required type.\n",option[curopt].keyword,--lineno);
option[curopt].err = -1;
if (buffer)
free(buffer);
return -1;
}
else
option[curopt].err = 1;
break;
default: /* unexpected type */
log(LOG_ERR, "Error parsing configuration file. Unrecognized option type!");
if (buffer)
free(buffer);
return -1;
}
/* clean up */
if (option[curopt].r_type != CONFIG_TYPE_STRING)
{
if (buffer)
free(buffer);
buflen=0;
}
state = 0;
curopt = -1;
i_buf=0;
i_keyword=0;
}
} /* infinite loop */
return retval;
}
int poptReadOptions(poptContext optCon, const unsigned char *fname)
/**
poptReadOptions reads popt-style options from the specified filename.
RETURN VALUE: INT_MIN = problem opening config file, else standard poptGetNextOpt() return value
**/
{
FILE *fp;
int argc, c, n;
char **argv;
char line[1024];
line[0] = line[1] = '-'; /* prepend expected long name option flag */
fp = fopen(fname,"r");
if ( fp == NULL ) return INT_MIN;
c = 0;
while ( c >= -1 )
{
if ( fscanf(fp,"%*[ \n]%n",&n) == EOF ) break; /* eat leading whitespace */
if ( fscanf(fp, "%[^\n]",&line[2]) == EOF ) break; /* read a line */
switch ( line[2] )
{
case '#': /* comments begin with this */
case '[': /* section header. ignore for now. maybe do something special in future version... */
continue;/* ignore */
default: /* we got a bite, lets reel it in now */
poptParseArgvString(line,&argc,(const char ***)&argv); /* Argv-ify what we found */
poptStuffArgs(optCon,(const char **)argv); /* stuff new arguments so they can be interpreted */
free(argv); /* free storage allocated by poptParseArgvString */
c = poptGetNextOpt(optCon); /* interpret option read from config file */
}
}
fclose(fp);
return c;
}
int poptReadDefaultOptions(const char *cmd, poptContext optCon)
/**
reads popt-style options from /etc/<cmd>rc and ~/.<cmd>rc
RETURN VALUE: same as poptReadOptions()
**/
{
char fname[256];
int c;
sprintf(fname,"/etc/%src",cmd);
c = poptReadOptions(optCon,fname);
if ( c == INT_MIN || c >= -1 )
{
sprintf(fname,"%s/.%src",getenv("HOME"),cmd);
c = poptReadOptions(optCon,fname);
}
return (c == INT_MIN) ? -1 : c;
}
-102
View File
@@ -1,102 +0,0 @@
/*
* config.h
* Functions for the manipulation of configuration files.
*
* Matej Pfajfar <mp292@cam.ac.uk>
*/
/*
* Changes :
* $Log$
* Revision 1.3 2002/07/10 10:11:13 badbytes
* Bugfix - the list of valid characters in a filename didn't include an n .
*
* Revision 1.2 2002/07/03 16:31:22 montrose
* Added getoptions() and made minor adjustment to poptReadDefaultOptions()
*
* Revision 1.1.1.1 2002/06/26 22:45:50 arma
* initial commit: current code
*
* Revision 1.7 2002/04/02 14:27:11 badbytes
* Final finishes.
*
* Revision 1.6 2002/01/26 18:42:15 mp292
* Reviewed according to Secure-Programs-HOWTO.
*
* Revision 1.5 2002/01/21 21:07:56 mp292
* Parameter checking was missing in some functions.
*
* Revision 1.4 2001/12/18 10:37:47 badbytes
* Header files now only apply if they were not previously included from somewhere else.
*
* Revision 1.3 2001/12/07 09:38:03 badbytes
* Tested.
*
* Revision 1.2 2001/12/06 15:43:50 badbytes
* config.c compiles. Proceeding to test it.
*
* Revision 1.1 2001/11/22 01:20:27 mp292
* Functions for dealing with configuration files.
*
*
*/
#ifndef __CONFIG_H
# include <stdio.h>
#include <popt.h>
/* enumeration of types which option values can take */
#define CONFIG_TYPE_STRING 0
#define CONFIG_TYPE_CHAR 1
#define CONFIG_TYPE_INT 2
#define CONFIG_TYPE_LONG 3
#define CONFIG_TYPE_DOUBLE 4
/* max. length of an option keyword */
#define CONFIG_KEYWORD_MAXLEN 255
/* max. length (in characters) of an option value */
#define CONFIG_VALUE_MAXLEN 255
/* legal characters in a filename */
#define CONFIG_LEGAL_FILENAME_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/"
typedef struct
{
unsigned char *keyword; /* option keyword */
unsigned int r_type; /* return type as defined above */
union /* return value */
{
char *str;
char c;
int i;
long l;
double d;
} r;
int err; /* 1 OK
* 0 keyword not found
* -1 error while parsing */
} config_opt_t;
/* open configuration file for reading */
FILE *open_config(const unsigned char *filename);
/* close configuration file */
int close_config(FILE *f);
/* parse the config file and obtain required option values */
int parse_config(FILE *f, config_opt_t *option);
/* parse popt-style options in a config file */
int poptReadOptions(poptContext optCon, const unsigned char *fname);
/* parse popt-style options from /etc/<cmd>rc and ~/.<cmd>rc */
int poptReadDefaultOptions(const char *cmd, poptContext optCon);
#define __CONFIG_H
#endif
+1 -1
View File
@@ -15,7 +15,7 @@
#include <assert.h> #include <assert.h>
#include "crypto.h" #include "crypto.h"
#include "config.h" #include "../or/or.h"
#include "log.h" #include "log.h"
#if OPENSSL_VERSION_NUMBER < 0x00905000l #if OPENSSL_VERSION_NUMBER < 0x00905000l
-7
View File
@@ -27,13 +27,6 @@ oB3OzW6VxWIiht3da/3K0ywiBOOCcf6BabKoMdiPpH7NIeu6XRmBYK2uqW13gBgh
xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8= xJbQBb58Nx8Fr05XkvLG6i+vTDY3MZOW3E2/DwSe/jFzuHSD5b3nAgMA//8=
-----END RSA PUBLIC KEY----- -----END RSA PUBLIC KEY-----
town-square.reputation.com 9004 9014 9024 0 100000
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAKD2BDZQpGq/aAbZ7t+/7qktZVEbhUGe097gIjWH9gXcIOIm0CJMe3rN
MsBJsQMi5Uwqrz+Invb5n6bswrNlJp/bCKBhGTvUCfxg7c8xZy71PPSIPnTg1qXl
p5fyAkgCYkZNgEEZzQDHv1GRvLCs92kURjSJE5y8QU0dXfbzms8PAgMA//8=
-----END RSA PUBLIC KEY-----
moria.mit.edu 9004 9014 9024 0 100000 moria.mit.edu 9004 9014 9024 0 100000
-----BEGIN RSA PUBLIC KEY----- -----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAKD2BDZQpGq/aAbZ7t+/7qktZVEbhUGe097gIjWH9gXcIOIm0CJMe3rN MIGJAoGBAKD2BDZQpGq/aAbZ7t+/7qktZVEbhUGe097gIjWH9gXcIOIm0CJMe3rN
-1
View File
@@ -13,4 +13,3 @@ szn+47Sby8S/55Svqvz93VNcNV2gD1LgJ7r+5xT0zsIxfD4ORF6H+n2/ztUTDnVJ
BiUS4KvXQCNBE/Pl9wJAMnYAfMOolyh96NWCH9ZN3OJmWojpgXjMlw5H02kkRKpZ BiUS4KvXQCNBE/Pl9wJAMnYAfMOolyh96NWCH9ZN3OJmWojpgXjMlw5H02kkRKpZ
HWnksj3ErNlCo5juXaaOwESBZBB/5+ngsIMPwWT0lg== HWnksj3ErNlCo5juXaaOwESBZBB/5+ngsIMPwWT0lg==
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----
+362 -285
View File
@@ -2,22 +2,9 @@
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
/* $Id$ */ /* $Id$ */
/**
* config.c
* Routines for loading the configuration file.
*
* Matej Pfajfar <mp292@cam.ac.uk>
*/
#include "or.h" #include "or.h"
#ifndef POPT_TABLEEND /* handle popt 1.6 before 1.6.2 */ const char *basename(const char *filename) {
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
#endif
const char *
basename(const char *filename)
{
char *result; char *result;
/* XXX This won't work on windows. */ /* XXX This won't work on windows. */
result = strrchr(filename, '/'); result = strrchr(filename, '/');
@@ -27,279 +14,369 @@ basename(const char *filename)
return filename; return filename;
} }
/* loads the configuration file */ /* open configuration file for reading */
int getconfig(char *conf_filename, config_opt_t *options) FILE *config_open(const unsigned char *filename) {
{ assert(filename);
FILE *cf = NULL; if (strspn(filename,CONFIG_LEGAL_FILENAME_CHARACTERS) != strlen(filename)) {
int retval = 0; /* filename has illegal letters */
return NULL;
if ((!conf_filename) || (!options))
return -1;
/* load config file */
cf = open_config(conf_filename);
if (!cf)
{
log(LOG_ERR,"Could not open configuration file %s.",conf_filename);
return -1;
} }
retval = parse_config(cf,options); return fopen(filename, "r");
if (retval)
return -1;
return 0;
} }
int getoptions(int argc, char **argv, or_options_t *options) /* close configuration file */
/** int config_close(FILE *f) {
assert(f);
A replacement for getargs() and getconfig() which uses the <popt> library to parse return fclose(f);
both command-line arguments and configuration files. A specific configuration file }
may be specified using the --ConfigFile option. If one is not specified, then the
configuration files at /etc/<cmd>rc and ~/.<cmd>rc will be loaded in that order so struct config_line *config_get_commandlines(int argc, char **argv) {
user preferences will override the ones specified in /etc. struct config_line *new;
struct config_line *front = NULL;
The --ConfigFile (-f) option may only be used on the command-line. All other command-line char *s;
options may also be specified in configuration files. <popt> aliases are enabled int i = 1;
so a user can define their own options in the /etc/popt or ~/.popt files as outlined
in "man popt" pages. while(i < argc-1) {
if(!strcmp(argv[i],"-f")) {
RETURN VALUE: 0 on success, non-zero on error // log(LOG_DEBUG,"Commandline: skipping over -f.");
**/ i+=2; /* this is the config file option. ignore it. */
{ continue;
char *ConfigFile; }
int Verbose;
int code; new = malloc(sizeof(struct config_line));
poptContext optCon; s = argv[i];
const char *cmd; while(*s == '-')
struct poptOption opt_tab[] = s++;
{ new->key = strdup(s);
{ "APPort", 'a', POPT_ARG_INT, &options->APPort, new->value = strdup(argv[i+1]);
0, "application proxy port", "<port>" },
{ "CoinWeight", 'w', POPT_ARG_FLOAT, &options->CoinWeight, log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
0, "coin weight used in determining routes", "<weight>" }, new->key, new->value);
{ "ConfigFile", 'f', POPT_ARG_STRING, &ConfigFile, new->next = front;
0, "user specified configuration file", "<file>" }, front = new;
{ "LogLevel", 'l', POPT_ARG_STRING, &options->LogLevel, i += 2;
0, "emerg|alert|crit|err|warning|notice|info|debug", "<level>" }, }
{ "MaxConn", 'm', POPT_ARG_INT, &options->MaxConn, return front;
0, "maximum number of incoming connections", "<max>" }, }
{ "OPPort", 'o', POPT_ARG_INT, &options->OPPort,
0, "onion proxy port", "<port>" }, /* parse the config file and strdup into key/value strings. Return list.
{ "ORPort", 'p', POPT_ARG_INT, &options->ORPort, * * Warn and ignore mangled lines. */
0, "onion router port", "<port>" }, struct config_line *config_get_lines(FILE *f) {
{ "DirPort", 'd', POPT_ARG_INT, &options->DirPort, struct config_line *new;
0, "directory server port", "<port>" }, struct config_line *front = NULL;
{ "PrivateKeyFile", 'k', POPT_ARG_STRING, &options->PrivateKeyFile, char line[CONFIG_LINE_MAXLEN];
0, "maximum number of incoming connections", "<file>" }, int lineno=0; /* current line number */
{ "RouterFile", 'r', POPT_ARG_STRING, &options->RouterFile, char *s;
0, "local port on which the onion proxy is running", "<file>" }, char *start, *end;
{ "TrafficShaping", 't', POPT_ARG_INT, &options->TrafficShaping,
0, "which traffic shaping policy to use", "<policy>" }, assert(f);
{ "LinkPadding", 'P', POPT_ARG_INT, &options->LinkPadding,
0, "whether to use link padding", "<padding>" }, fseek(f,0,SEEK_SET); /* make sure we start at the beginning of file */
{ "DirRebuildPeriod",'D', POPT_ARG_INT, &options->DirRebuildPeriod,
0, "how many seconds between directory rebuilds", "<rebuildperiod>" }, while(fgets(line, CONFIG_LINE_MAXLEN, f)) {
{ "DirFetchPeriod", 'F', POPT_ARG_INT, &options->DirFetchPeriod, lineno++;
0, "how many seconds between directory fetches", "<fetchperiod>" },
{ "KeepalivePeriod", 'K', POPT_ARG_INT, &options->KeepalivePeriod, /* first strip comments */
0, "how many seconds between keepalives", "<keepaliveperiod>" }, s = strchr(line,'#');
// { "ReconnectPeriod", 'e', POPT_ARG_INT, &options->ReconnectPeriod, if(s) {
// 0, "how many seconds between retrying all OR connections", "<reconnectperiod>" }, *s = 0; /* stop the line there */
{ "Role", 'R', POPT_ARG_INT, &options->Role, }
0, "4-bit global role id", "<role>" },
{ "Verbose", 'v', POPT_ARG_NONE, &Verbose, /* walk to the end, remove end whitespace */
0, "display options selected before execution", NULL }, s = index(line, 0); /* now we're at the null */
POPT_AUTOHELP /* handles --usage and --help automatically */ do {
POPT_TABLEEND /* marks end of table */ *s = 0;
}; s--;
cmd = basename(argv[0]); } while (isspace(*s));
optCon = poptGetContext(cmd,argc,(const char **)argv,opt_tab,0);
start = line;
poptReadDefaultConfig(optCon,0); /* read <popt> alias definitions */ while(isspace(*start))
start++;
/* assign default option values */ if(*start == 0)
continue; /* this line has nothing on it */
bzero(options,sizeof(or_options_t));
options->LogLevel = "debug"; end = start;
options->loglevel = LOG_DEBUG; while(*end && !isspace(*end))
options->CoinWeight = 0.8; end++;
options->LinkPadding = 0; s = end;
options->DirRebuildPeriod = 600; while(*s && isspace(*s))
options->DirFetchPeriod = 6000; s++;
options->KeepalivePeriod = 300; if(!*end || !*s) { /* only a keyword on this line. no value. */
// options->ReconnectPeriod = 6001; log(LOG_WARNING,"Config line %d has keyword '%s' but no value. Skipping.",lineno,s);
options->Role = ROLE_OR_LISTEN | ROLE_OR_CONNECT_ALL | ROLE_OP_LISTEN | ROLE_AP_LISTEN; }
*end = 0; /* null it out */
code = poptGetNextOpt(optCon); /* first we handle command-line args */
if ( code == -1 ) /* prepare to parse the string into key / value */
{ new = malloc(sizeof(struct config_line));
if ( ConfigFile ) /* handle user-specified config file */ new->key = strdup(start);
code = poptReadOptions(optCon,ConfigFile); new->value = strdup(s);
else /* load Default configuration files */
code = poptReadDefaultOptions(cmd,optCon); log(LOG_DEBUG,"Config line %d: parsed keyword '%s', value '%s'",
} lineno, new->key, new->value);
new->next = front;
switch(code) /* error checking */ front = new;
{ }
case INT_MIN:
log(LOG_ERR, "%s: Unable to open configuration file.\n", ConfigFile); return front;
break; }
case -1:
code = 0; void config_free_lines(struct config_line *front) {
break; struct config_line *tmp;
default:
poptPrintUsage(optCon, stderr, 0); while(front) {
log(LOG_ERR, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(code)); tmp = front;
break; front = tmp->next;
}
free(tmp->key);
poptFreeContext(optCon); free(tmp->value);
free(tmp);
if ( code ) return code; /* return here if we encountered any problems */ }
}
/* Display options upon user request */
int config_compare(struct config_line *c, char *key, int type, void *arg) {
if ( Verbose )
{ if(strncasecmp(c->key,key,strlen(c->key)))
printf("LogLevel=%s, Role=%d\n", return 0;
options->LogLevel,
options->Role); /* it's a match. cast and assign. */
printf("RouterFile=%s, PrivateKeyFile=%s\n", log(LOG_DEBUG,"config_compare(): Recognized keyword '%s' as %s, using value '%s'.",c->key,key,c->value);
options->RouterFile,
options->PrivateKeyFile); switch(type) {
printf("ORPort=%d, OPPort=%d, APPort=%d DirPort=%d\n", case CONFIG_TYPE_INT:
options->ORPort,options->OPPort, *(int *)arg = atoi(c->value);
options->APPort,options->DirPort); break;
printf("CoinWeight=%6.4f, MaxConn=%d, TrafficShaping=%d, LinkPadding=%d\n", case CONFIG_TYPE_STRING:
options->CoinWeight, *(char **)arg = strdup(c->value);
options->MaxConn, break;
options->TrafficShaping, case CONFIG_TYPE_DOUBLE:
options->LinkPadding); *(double *)arg = atof(c->value);
printf("DirRebuildPeriod=%d, DirFetchPeriod=%d KeepalivePeriod=%d\n", break;
options->DirRebuildPeriod, }
options->DirFetchPeriod, return 1;
options->KeepalivePeriod); }
}
void config_assign(or_options_t *options, struct config_line *list) {
/* Validate options */
/* iterate through list. for each item convert as appropriate and assign to 'options'. */
if ( options->LogLevel )
{ while(list) {
if (!strcmp(options->LogLevel,"emerg")) if(
options->loglevel = LOG_EMERG;
else if (!strcmp(options->LogLevel,"alert")) /* order matters here! abbreviated arguments use the first match. */
options->loglevel = LOG_ALERT;
else if (!strcmp(options->LogLevel,"crit")) /* string options */
options->loglevel = LOG_CRIT; config_compare(list, "LogLevel", CONFIG_TYPE_STRING, &options->LogLevel) ||
else if (!strcmp(options->LogLevel,"err")) config_compare(list, "PrivateKeyFile", CONFIG_TYPE_STRING, &options->PrivateKeyFile) ||
options->loglevel = LOG_ERR; config_compare(list, "RouterFile", CONFIG_TYPE_STRING, &options->RouterFile) ||
else if (!strcmp(options->LogLevel,"warning"))
options->loglevel = LOG_WARNING; /* int options */
else if (!strcmp(options->LogLevel,"notice")) config_compare(list, "Role", CONFIG_TYPE_INT, &options->Role) ||
options->loglevel = LOG_NOTICE; config_compare(list, "MaxConn", CONFIG_TYPE_INT, &options->MaxConn) ||
else if (!strcmp(options->LogLevel,"info")) config_compare(list, "APPort", CONFIG_TYPE_INT, &options->APPort) ||
options->loglevel = LOG_INFO; config_compare(list, "OPPort", CONFIG_TYPE_INT, &options->OPPort) ||
else if (!strcmp(options->LogLevel,"debug")) config_compare(list, "ORPort", CONFIG_TYPE_INT, &options->ORPort) ||
options->loglevel = LOG_DEBUG; config_compare(list, "DirPort", CONFIG_TYPE_INT, &options->DirPort) ||
else config_compare(list, "TrafficShaping", CONFIG_TYPE_INT, &options->TrafficShaping) ||
{ config_compare(list, "LinkPadding", CONFIG_TYPE_INT, &options->LinkPadding) ||
log(LOG_ERR,"LogLevel must be one of emerg|alert|crit|err|warning|notice|info|debug."); config_compare(list, "DirRebuildPeriod",CONFIG_TYPE_INT, &options->DirRebuildPeriod) ||
code = -1; config_compare(list, "DirFetchPeriod", CONFIG_TYPE_INT, &options->DirFetchPeriod) ||
} config_compare(list, "KeepalivePeriod", CONFIG_TYPE_INT, &options->KeepalivePeriod) ||
}
/* float options */
if ( options->Role < 0 || options->Role > 63 ) config_compare(list, "CoinWeight", CONFIG_TYPE_DOUBLE, &options->CoinWeight)
{
log(LOG_ERR,"Role option must be an integer between 0 and 63 (inclusive)."); ) {
code = -1; /* then we're ok. it matched something. */
} } else {
log(LOG_WARNING,"config_assign(): Ignoring unknown keyword '%s'.",list->key);
if ( options->RouterFile == NULL ) }
{
log(LOG_ERR,"RouterFile option required, but not found."); list = list->next;
code = -1; }
} }
if ( ROLE_IS_OR(options->Role) && options->PrivateKeyFile == NULL ) /* return 0 if success, <0 if failure. */
{ int getconfig(int argc, char **argv, or_options_t *options) {
log(LOG_ERR,"PrivateKeyFile option required for OR, but not found."); struct config_line *cl;
code = -1; FILE *cf;
} char fname[256];
int i;
if ( (options->Role & ROLE_OR_LISTEN) && options->ORPort < 1 ) const char *cmd;
{ int result = 0;
log(LOG_ERR,"ORPort option required and must be a positive integer value.");
code = -1; /* give reasonable defaults for each option */
} memset(options,0,sizeof(or_options_t));
options->LogLevel = "debug";
if ( (options->Role & ROLE_OP_LISTEN) && options->OPPort < 1 ) options->loglevel = LOG_DEBUG;
{ options->CoinWeight = 0.8;
log(LOG_ERR,"OPPort option required and must be a positive integer value."); options->LinkPadding = 0;
code = -1; options->DirRebuildPeriod = 600;
} options->DirFetchPeriod = 6000;
options->KeepalivePeriod = 300;
if ( (options->Role & ROLE_AP_LISTEN) && options->APPort < 1 ) // options->ReconnectPeriod = 6001;
{ options->Role = ROLE_OR_LISTEN | ROLE_OR_CONNECT_ALL | ROLE_OP_LISTEN | ROLE_AP_LISTEN;
log(LOG_ERR,"APPort option required and must be a positive integer value.");
code = -1; /* get config lines from /etc/torrc and assign them */
} cmd = basename(argv[0]);
snprintf(fname,256,"/etc/%src",cmd);
if ( (options->Role & ROLE_DIR_LISTEN) && options->DirPort < 1 )
{ cf = config_open(fname);
log(LOG_ERR,"DirPort option required and must be a positive integer value."); if(cf) {
code = -1; /* we got it open. pull out the config lines. */
} cl = config_get_lines(cf);
config_assign(options,cl);
if ( (options->Role & ROLE_AP_LISTEN) && config_free_lines(cl);
(options->CoinWeight < 0.0 || options->CoinWeight >= 1.0) ) config_close(cf);
{ }
log(LOG_ERR,"CoinWeight option must be a value from 0.0 upto 1.0, but not including 1.0."); /* if we failed to open it, ignore */
code = -1;
} /* learn config file name, get config lines, assign them */
i = 1;
if ( options->MaxConn <= 0 ) while(i < argc-1 && strcmp(argv[i],"-f")) {
{ // log(LOG_DEBUG,"examining arg %d (%s), it's not -f.",i,argv[i]);
log(LOG_ERR,"MaxConn option must be a non-zero positive integer."); i++;
code = -1; }
} if(i < argc-1) { /* we found one */
log(LOG_DEBUG,"Opening specified config file '%s'",argv[i+1]);
if ( options->MaxConn >= MAXCONNECTIONS ) cf = config_open(argv[i+1]);
{ if(!cf) { /* it's defined but not there. that's no good. */
log(LOG_ERR,"MaxConn option must be less than %d.", MAXCONNECTIONS); log(LOG_ERR, "Unable to open configuration file '%s'.",argv[i+1]);
code = -1; return -1;
} }
cl = config_get_lines(cf);
if ( options->TrafficShaping != 0 && options->TrafficShaping != 1 ) config_assign(options,cl);
{ config_free_lines(cl);
log(LOG_ERR,"TrafficShaping option must be either 0 or 1."); config_close(cf);
code = -1; }
}
/* go through command-line variables too */
if ( options->LinkPadding != 0 && options->LinkPadding != 1 ) cl = config_get_commandlines(argc,argv);
{ config_assign(options,cl);
log(LOG_ERR,"LinkPadding option must be either 0 or 1."); config_free_lines(cl);
code = -1;
} /* print config */
if (options->loglevel == LOG_DEBUG) {
if ( options->DirRebuildPeriod < 1) printf("LogLevel=%s, Role=%d\n",
{ options->LogLevel,
log(LOG_ERR,"DirRebuildPeriod option must be positive."); options->Role);
code = -1; printf("RouterFile=%s, PrivateKeyFile=%s\n",
} options->RouterFile ? options->RouterFile : "(undefined)",
options->PrivateKeyFile ? options->PrivateKeyFile : "(undefined)");
if ( options->DirFetchPeriod < 1) printf("ORPort=%d, OPPort=%d, APPort=%d DirPort=%d\n",
{ options->ORPort,options->OPPort,
log(LOG_ERR,"DirFetchPeriod option must be positive."); options->APPort,options->DirPort);
code = -1; printf("CoinWeight=%6.4f, MaxConn=%d, TrafficShaping=%d, LinkPadding=%d\n",
} options->CoinWeight,
options->MaxConn,
if ( options->KeepalivePeriod < 1) options->TrafficShaping,
{ options->LinkPadding);
log(LOG_ERR,"KeepalivePeriod option must be positive."); printf("DirRebuildPeriod=%d, DirFetchPeriod=%d KeepalivePeriod=%d\n",
code = -1; options->DirRebuildPeriod,
} options->DirFetchPeriod,
options->KeepalivePeriod);
return code; }
/* Validate options */
if(options->LogLevel) {
if(!strcmp(options->LogLevel,"emerg"))
options->loglevel = LOG_EMERG;
else if(!strcmp(options->LogLevel,"alert"))
options->loglevel = LOG_ALERT;
else if(!strcmp(options->LogLevel,"crit"))
options->loglevel = LOG_CRIT;
else if(!strcmp(options->LogLevel,"err"))
options->loglevel = LOG_ERR;
else if(!strcmp(options->LogLevel,"warning"))
options->loglevel = LOG_WARNING;
else if(!strcmp(options->LogLevel,"notice"))
options->loglevel = LOG_NOTICE;
else if(!strcmp(options->LogLevel,"info"))
options->loglevel = LOG_INFO;
else if(!strcmp(options->LogLevel,"debug"))
options->loglevel = LOG_DEBUG;
else {
log(LOG_ERR,"LogLevel must be one of emerg|alert|crit|err|warning|notice|info|debug.");
result = -1;
}
}
if(options->Role < 0 || options->Role > 63) {
log(LOG_ERR,"Role option must be an integer between 0 and 63 (inclusive).");
result = -1;
}
if(options->RouterFile == NULL) {
log(LOG_ERR,"RouterFile option required, but not found.");
result = -1;
}
if(ROLE_IS_OR(options->Role) && options->PrivateKeyFile == NULL) {
log(LOG_ERR,"PrivateKeyFile option required for OR, but not found.");
result = -1;
}
if((options->Role & ROLE_OR_LISTEN) && options->ORPort < 1) {
log(LOG_ERR,"ORPort option required and must be a positive integer value.");
result = -1;
}
if((options->Role & ROLE_OP_LISTEN) && options->OPPort < 1) {
log(LOG_ERR,"OPPort option required and must be a positive integer value.");
result = -1;
}
if((options->Role & ROLE_AP_LISTEN) && options->APPort < 1) {
log(LOG_ERR,"APPort option required and must be a positive integer value.");
result = -1;
}
if((options->Role & ROLE_DIR_LISTEN) && options->DirPort < 1) {
log(LOG_ERR,"DirPort option required and must be a positive integer value.");
result = -1;
}
if((options->Role & ROLE_AP_LISTEN) &&
(options->CoinWeight < 0.0 || options->CoinWeight >= 1.0)) {
log(LOG_ERR,"CoinWeight option must be a value from 0.0 upto 1.0, but not including 1.0.");
result = -1;
}
if(options->MaxConn <= 0) {
log(LOG_ERR,"MaxConn option must be a non-zero positive integer.");
result = -1;
}
if(options->MaxConn >= MAXCONNECTIONS) {
log(LOG_ERR,"MaxConn option must be less than %d.", MAXCONNECTIONS);
result = -1;
}
if(options->TrafficShaping != 0 && options->TrafficShaping != 1) {
log(LOG_ERR,"TrafficShaping option must be either 0 or 1.");
result = -1;
}
if(options->LinkPadding != 0 && options->LinkPadding != 1) {
log(LOG_ERR,"LinkPadding option must be either 0 or 1.");
result = -1;
}
if(options->DirRebuildPeriod < 1) {
log(LOG_ERR,"DirRebuildPeriod option must be positive.");
result = -1;
}
if(options->DirFetchPeriod < 1) {
log(LOG_ERR,"DirFetchPeriod option must be positive.");
result = -1;
}
if(options->KeepalivePeriod < 1) {
log(LOG_ERR,"KeepalivePeriod option must be positive.");
result = -1;
}
return result;
} }
+3 -2
View File
@@ -645,9 +645,10 @@ int main(int argc, char *argv[]) {
signal (SIGUSR1, catch); /* to dump stats to stdout */ signal (SIGUSR1, catch); /* to dump stats to stdout */
signal (SIGHUP, catch); /* to reload directory */ signal (SIGHUP, catch); /* to reload directory */
if ( getoptions(argc,argv,&options) ) exit(1); if(getconfig(argc,argv,&options))
exit(1);
log(options.loglevel,NULL); /* assign logging severity level from options */ log(options.loglevel,NULL); /* assign logging severity level from options */
global_role = options.Role; /* assign global_role from options. FIX: remove from global namespace later. */ global_role = options.Role; /* assign global_role from options. FIXME: remove from global namespace later. */
crypto_global_init(); crypto_global_init();
retval = do_main_loop(); retval = do_main_loop();
+178 -179
View File
@@ -208,139 +208,144 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int
unsigned char *buf; unsigned char *buf;
routerinfo_t *router; routerinfo_t *router;
unsigned char iv[16]; unsigned char iv[16];
struct in_addr netaddr;
assert(rarray && route && len && routelen); assert(rarray && route && len && routelen);
/* calculate the size of the onion */ /* calculate the size of the onion */
*len = routelen * 28 + 100; /* 28 bytes per layer + 100 bytes padding for the innermost layer */ *len = routelen * 28 + 100; /* 28 bytes per layer + 100 bytes padding for the innermost layer */
log(LOG_DEBUG,"create_onion() : Size of the onion is %u.",*len); log(LOG_DEBUG,"create_onion() : Size of the onion is %u.",*len);
/* allocate memory for the onion */ /* allocate memory for the onion */
buf = (unsigned char *)malloc(*len); buf = (unsigned char *)malloc(*len);
if (!buf) { if (!buf) {
log(LOG_ERR,"Error allocating memory."); log(LOG_ERR,"Error allocating memory.");
return NULL;
}
log(LOG_DEBUG,"create_onion() : Allocated memory for the onion.");
for (i=0; i<routelen;i++) {
log(LOG_DEBUG,"create_onion() : %u : %s:%u, %u/%u",routelen-i,inet_ntoa(*((struct in_addr *)&((rarray[route[i]])->addr))),(rarray[route[i]])->or_port,(rarray[route[i]])->pkey,crypto_pk_keysize((rarray[route[i]])->pkey));
}
layer = (onion_layer_t *)(buf + *len - 128); /* pointer to innermost layer */
/* create the onion layer by layer, starting with the innermost */
for (i=0;i<routelen;i++) {
router = rarray[route[i]];
log(LOG_DEBUG,"create_onion() : %u",router);
log(LOG_DEBUG,"create_onion() : This router is %s:%u",inet_ntoa(*((struct in_addr *)&router->addr)),router->or_port);
log(LOG_DEBUG,"create_onion() : Key pointer = %u.",router->pkey);
log(LOG_DEBUG,"create_onion() : Key size = %u.",crypto_pk_keysize(router->pkey));
/* 0 bit */
layer->zero = 0;
/* version */
layer->version = OR_VERSION;
/* Back F + Forw F both use DES OFB*/
layer->backf = ONION_DEFAULT_CIPHER;
layer->forwf = ONION_DEFAULT_CIPHER;
/* Dest Port */
if (i) /* not last hop */
layer->port = rarray[route[i-1]]->or_port;
else
layer->port = 0;
/* Dest Addr */
if (i) /* not last hop */
layer->addr = rarray[route[i-1]]->addr;
else
layer->addr = 0;
/* Expiration Time */
layer->expire = time(NULL) + 3600; /* NOW + 1 hour */
/* Key Seed Material */
if (crypto_rand(16, layer->keyseed)) /* error */
{
log(LOG_ERR,"Error generating random data.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Onion layer %u built : %u, %u, %u, %s, %u.",i+1,layer->zero,layer->backf,layer->forwf,inet_ntoa(*((struct in_addr *)&layer->addr)),layer->port);
/* build up the crypt_path */
if (cpath)
{
cpath[i] = (crypt_path_t *)malloc(sizeof(crypt_path_t));
if (!cpath[i]) {
log(LOG_ERR,"Error allocating memory.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
hop = cpath[i];
/* set crypto functions */
hop->backf = layer->backf;
hop->forwf = layer->forwf;
/* calculate keys */
crypto_SHA_digest(layer->keyseed,16,hop->digest3);
log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
crypto_SHA_digest(hop->digest3,20,hop->digest2);
log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
crypto_SHA_digest(hop->digest2,20,hop->digest3);
log(LOG_DEBUG,"create_onion() : Third SHA pass performed.");
log(LOG_DEBUG,"create_onion() : Keys generated.");
/* set IV to zero */
memset((void *)iv,0,16);
/* initialize cipher engines */
if (! (hop->f_crypto = create_onion_cipher(hop->forwf, hop->digest3, iv, 1))) {
/* cipher initialization failed */
log(LOG_ERR,"Could not create a crypto environment.");
goto error;
}
if (! (hop->b_crypto = create_onion_cipher(hop->backf, hop->digest2, iv, 0))) {
/* cipher initialization failed */
log(LOG_ERR,"Could not create a crypto environment.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Built corresponding crypt path hop.");
}
/* padding if this is the innermost layer */
if (!i) {
if (crypto_pseudo_rand(100, (unsigned char *)layer + 28)) { /* error */
log(LOG_ERR,"Error generating pseudo-random data.");
goto error;
}
log(LOG_DEBUG,"create_onion() : This is the innermost layer. Adding 100 bytes of padding.");
}
/* encrypt */
if (! encrypt_onion(layer,128+(i*28),router->pkey)) {
log(LOG_ERR,"Error encrypting onion layer.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Encrypted layer.");
/* calculate pointer to next layer */
layer = (onion_layer_t *)(buf + (routelen-i-2)*sizeof(onion_layer_t));
}
return buf;
error:
if (buf)
free((void *)buf);
if (cpath) {
for (j=0;j<i;j++) {
if (cpath[i]->f_crypto)
crypto_free_cipher_env(cpath[i]->f_crypto);
if (cpath[i]->b_crypto)
crypto_free_cipher_env(cpath[i]->b_crypto);
free((void *)cpath[i]);
}
}
return NULL; return NULL;
}
log(LOG_DEBUG,"create_onion() : Allocated memory for the onion.");
for (i=0; i<routelen;i++) {
netaddr.s_addr = htonl((rarray[route[i]])->addr);
log(LOG_DEBUG,"create_onion(): %u : %s:%u, %u/%u",routelen-i,
inet_ntoa(netaddr),
(rarray[route[i]])->or_port,
(rarray[route[i]])->pkey,
crypto_pk_keysize((rarray[route[i]])->pkey));
}
layer = (onion_layer_t *)(buf + *len - 128); /* pointer to innermost layer */
/* create the onion layer by layer, starting with the innermost */
for (i=0;i<routelen;i++) {
router = rarray[route[i]];
// log(LOG_DEBUG,"create_onion() : %u",router);
// log(LOG_DEBUG,"create_onion() : This router is %s:%u",inet_ntoa(*((struct in_addr *)&router->addr)),router->or_port);
// log(LOG_DEBUG,"create_onion() : Key pointer = %u.",router->pkey);
// log(LOG_DEBUG,"create_onion() : Key size = %u.",crypto_pk_keysize(router->pkey));
/* 0 bit */
layer->zero = 0;
/* version */
layer->version = OR_VERSION;
/* Back F + Forw F both use DES OFB*/
layer->backf = ONION_DEFAULT_CIPHER;
layer->forwf = ONION_DEFAULT_CIPHER;
/* Dest Port */
if (i) /* not last hop */
layer->port = rarray[route[i-1]]->or_port;
else
layer->port = 0;
/* Dest Addr */
if (i) /* not last hop */
layer->addr = rarray[route[i-1]]->addr;
else
layer->addr = 0;
/* Expiration Time */
layer->expire = time(NULL) + 3600; /* NOW + 1 hour */
/* Key Seed Material */
if(crypto_rand(16, layer->keyseed)) { /* error */
log(LOG_ERR,"Error generating random data.");
goto error;
}
// log(LOG_DEBUG,"create_onion() : Onion layer %u built : %u, %u, %u, %s, %u.",i+1,layer->zero,layer->backf,layer->forwf,inet_ntoa(*((struct in_addr *)&layer->addr)),layer->port);
/* build up the crypt_path */
if(cpath) {
cpath[i] = (crypt_path_t *)malloc(sizeof(crypt_path_t));
if(!cpath[i]) {
log(LOG_ERR,"Error allocating memory.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
hop = cpath[i];
/* set crypto functions */
hop->backf = layer->backf;
hop->forwf = layer->forwf;
/* calculate keys */
crypto_SHA_digest(layer->keyseed,16,hop->digest3);
log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
crypto_SHA_digest(hop->digest3,20,hop->digest2);
log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
crypto_SHA_digest(hop->digest2,20,hop->digest3);
log(LOG_DEBUG,"create_onion() : Third SHA pass performed.");
log(LOG_DEBUG,"create_onion() : Keys generated.");
/* set IV to zero */
memset((void *)iv,0,16);
/* initialize cipher engines */
if (! (hop->f_crypto = create_onion_cipher(hop->forwf, hop->digest3, iv, 1))) {
/* cipher initialization failed */
log(LOG_ERR,"Could not create a crypto environment.");
goto error;
}
if (! (hop->b_crypto = create_onion_cipher(hop->backf, hop->digest2, iv, 0))) {
/* cipher initialization failed */
log(LOG_ERR,"Could not create a crypto environment.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Built corresponding crypt path hop.");
}
/* padding if this is the innermost layer */
if (!i) {
if (crypto_pseudo_rand(100, (unsigned char *)layer + 28)) { /* error */
log(LOG_ERR,"Error generating pseudo-random data.");
goto error;
}
log(LOG_DEBUG,"create_onion() : This is the innermost layer. Adding 100 bytes of padding.");
}
/* encrypt */
if(! encrypt_onion(layer,128+(i*28),router->pkey)) {
log(LOG_ERR,"Error encrypting onion layer.");
goto error;
}
log(LOG_DEBUG,"create_onion() : Encrypted layer.");
/* calculate pointer to next layer */
layer = (onion_layer_t *)(buf + (routelen-i-2)*sizeof(onion_layer_t));
}
return buf;
error:
if (buf)
free((void *)buf);
if (cpath) {
for (j=0;j<i;j++) {
if(cpath[i]->f_crypto)
crypto_free_cipher_env(cpath[i]->f_crypto);
if(cpath[i]->b_crypto)
crypto_free_cipher_env(cpath[i]->b_crypto);
free((void *)cpath[i]);
}
}
return NULL;
} }
/* encrypts 128 bytes of the onion with the specified public key, the rest with /* encrypts 128 bytes of the onion with the specified public key, the rest with
@@ -353,60 +358,54 @@ unsigned char *encrypt_onion(onion_layer_t *onion, uint32_t onionlen, crypto_pk_
crypto_cipher_env_t *crypt_env = NULL; /* crypto environment */ crypto_cipher_env_t *crypt_env = NULL; /* crypto environment */
if ( (onion) && (pkey) ) /* valid parameters */ assert(onion && pkey);
{
memset((void *)iv,0,8);
log(LOG_DEBUG,"Onion layer : %u, %u, %u, %s, %u.",onion->zero,onion->backf,onion->forwf,inet_ntoa(*((struct in_addr *)&onion->addr)),onion->port); memset((void *)iv,0,8);
/* allocate space for tmpbuf */
tmpbuf = (unsigned char *)malloc(onionlen);
if (!tmpbuf)
{
log(LOG_ERR,"Could not allocate memory.");
return NULL;
}
log(LOG_DEBUG,"encrypt_onion() : allocated %u bytes of memory for the encrypted onion (at %u).",onionlen,tmpbuf);
/* get key1 = SHA1(KeySeed) */ log(LOG_DEBUG,"Onion layer : %u, %u, %u, %s, %u.",onion->zero,onion->backf,onion->forwf,inet_ntoa(*((struct in_addr *)&onion->addr)),onion->port);
if (crypto_SHA_digest(((onion_layer_t *)onion)->keyseed,16,digest)) /* allocate space for tmpbuf */
{ tmpbuf = (unsigned char *)malloc(onionlen);
log(LOG_ERR,"Error computing SHA1 digest."); if (!tmpbuf) {
goto error; log(LOG_ERR,"Could not allocate memory.");
}
log(LOG_DEBUG,"encrypt_onion() : Computed DES key.");
log(LOG_DEBUG,"encrypt_onion() : Trying to RSA encrypt.");
/* encrypt 128 bytes with RSA *pkey */
if (crypto_pk_public_encrypt(pkey, (unsigned char *)onion, 128, tmpbuf, RSA_NO_PADDING) == -1) {
log(LOG_ERR,"Error RSA-encrypting data :%s",crypto_perror());
goto error;
}
log(LOG_DEBUG,"encrypt_onion() : RSA encrypted first 128 bytes of the onion.");
/* now encrypt the rest with DES OFB */
crypt_env = crypto_create_init_cipher(CRYPTO_CIPHER_DES, digest, iv, 1);
if (!crypt_env)
{
log(LOG_ERR,"Error creating the crypto environment.");
goto error;
}
if (crypto_cipher_encrypt(crypt_env,(unsigned char *)onion+128, onionlen-128, (unsigned char *)tmpbuf+128)) { /* error */
log(LOG_ERR,"Error performing DES encryption:%s",crypto_perror());
goto error;
}
log(LOG_DEBUG,"encrypt_onion() : DES OFB encrypted the rest of the onion.");
/* now copy tmpbuf to onion */
memcpy((void *)onion,(void *)tmpbuf,onionlen);
log(LOG_DEBUG,"encrypt_onion() : Copied cipher to original onion buffer.");
free((void *)tmpbuf);
crypto_free_cipher_env(crypt_env);
return (unsigned char *)onion;
} /* valid parameters */
else
return NULL; return NULL;
}
log(LOG_DEBUG,"encrypt_onion() : allocated %u bytes of memory for the encrypted onion (at %u).",onionlen,tmpbuf);
/* get key1 = SHA1(KeySeed) */
if (crypto_SHA_digest(((onion_layer_t *)onion)->keyseed,16,digest)) {
log(LOG_ERR,"Error computing SHA1 digest.");
goto error;
}
log(LOG_DEBUG,"encrypt_onion() : Computed DES key.");
log(LOG_DEBUG,"encrypt_onion() : Trying to RSA encrypt.");
/* encrypt 128 bytes with RSA *pkey */
if (crypto_pk_public_encrypt(pkey, (unsigned char *)onion, 128, tmpbuf, RSA_NO_PADDING) == -1) {
log(LOG_ERR,"Error RSA-encrypting data :%s",crypto_perror());
goto error;
}
log(LOG_DEBUG,"encrypt_onion() : RSA encrypted first 128 bytes of the onion.");
/* now encrypt the rest with DES OFB */
crypt_env = crypto_create_init_cipher(CRYPTO_CIPHER_DES, digest, iv, 1);
if (!crypt_env) {
log(LOG_ERR,"Error creating the crypto environment.");
goto error;
}
if (crypto_cipher_encrypt(crypt_env,(unsigned char *)onion+128, onionlen-128, (unsigned char *)tmpbuf+128)) { /* error */
log(LOG_ERR,"Error performing DES encryption:%s",crypto_perror());
goto error;
}
log(LOG_DEBUG,"encrypt_onion() : DES OFB encrypted the rest of the onion.");
/* now copy tmpbuf to onion */
memcpy((void *)onion,(void *)tmpbuf,onionlen);
log(LOG_DEBUG,"encrypt_onion() : Copied cipher to original onion buffer.");
free((void *)tmpbuf);
crypto_free_cipher_env(crypt_env);
return (unsigned char *)onion;
error: error:
if (tmpbuf) if (tmpbuf)
+40 -6
View File
@@ -37,7 +37,6 @@
#include <assert.h> #include <assert.h>
#include <time.h> #include <time.h>
#include "../common/config.h"
#include "../common/crypto.h" #include "../common/crypto.h"
#include "../common/log.h" #include "../common/log.h"
#include "../common/ss.h" #include "../common/ss.h"
@@ -147,6 +146,24 @@
#define CELL_PAYLOAD_SIZE 120 #define CELL_PAYLOAD_SIZE 120
#define CELL_NETWORK_SIZE 128 #define CELL_NETWORK_SIZE 128
/* enumeration of types which option values can take */
#define CONFIG_TYPE_STRING 0
#define CONFIG_TYPE_CHAR 1
#define CONFIG_TYPE_INT 2
#define CONFIG_TYPE_LONG 3
#define CONFIG_TYPE_DOUBLE 4
#define CONFIG_LINE_MAXLEN 1024
/* legal characters in a filename */
#define CONFIG_LEGAL_FILENAME_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/"
struct config_line {
char *key;
char *value;
struct config_line *next;
};
typedef uint16_t aci_t; typedef uint16_t aci_t;
/* cell definition */ /* cell definition */
@@ -348,7 +365,7 @@ typedef struct
char *LogLevel; char *LogLevel;
char *RouterFile; char *RouterFile;
char *PrivateKeyFile; char *PrivateKeyFile;
float CoinWeight; double CoinWeight;
int ORPort; int ORPort;
int OPPort; int OPPort;
int APPort; int APPort;
@@ -444,11 +461,28 @@ void command_process_connected_cell(cell_t *cell, connection_t *conn);
/********************************* config.c ***************************/ /********************************* config.c ***************************/
/* loads the configuration file */ const char *basename(const char *filename);
int getconfig(char *filename, config_opt_t *options);
/* create or_options_t from command-line args and config files(s) */ /* open configuration file for reading */
int getoptions(int argc, char **argv, or_options_t *options); FILE *config_open(const unsigned char *filename);
/* close configuration file */
int config_close(FILE *f);
struct config_line *config_get_commandlines(int argc, char **argv);
/* parse the config file and strdup into key/value strings. Return list.
* * * Warn and ignore mangled lines. */
struct config_line *config_get_lines(FILE *f);
void config_free_lines(struct config_line *front);
int config_compare(struct config_line *c, char *key, int type, void *arg);
void config_assign(or_options_t *options, struct config_line *list);
/* return 0 if success, <0 if failure. */
int getconfig(int argc, char **argv, or_options_t *options);
/********************************* connection.c ***************************/ /********************************* connection.c ***************************/
+2 -2
View File
@@ -6,7 +6,7 @@ int main(int ac, char **av)
int argc, rtn_val, failures, total; int argc, rtn_val, failures, total;
char fname[512]; char fname[512];
FILE *pipe; FILE *pipe;
char *argv[] = { "or", "-v", "-f", fname, NULL }; char *argv[] = { "or", "-f", fname, NULL };
argc = 4; argc = 4;
failures = total = 0; failures = total = 0;
printf("Config file test suite...\n\n"); printf("Config file test suite...\n\n");
@@ -15,7 +15,7 @@ int main(int ac, char **av)
{ {
fname[strlen(fname)-1] = '\0'; fname[strlen(fname)-1] = '\0';
printf("%s\n--------------------\n", fname); printf("%s\n--------------------\n", fname);
rtn_val = getoptions(argc,argv,&options); rtn_val = getconfig(argc,argv,&options);
++total; ++total;
if ( rtn_val) if ( rtn_val)
{ {