Tested backends for directory signing and checking. Directory parser completely refactored. Need documentation and integration. Explanitory mail forthcoming.

svn:r271
This commit is contained in:
Nick Mathewson 2003-05-07 18:30:46 +00:00
parent bbddd50082
commit afc0eb2c71
7 changed files with 476 additions and 220 deletions

View File

@ -22,7 +22,7 @@ ARMA - arma claims
NICK . Handle half-open connections
- Figure out what causes connections to close, standardize
when we mark a connection vs when we tear it down
NICK - Look at what ssl does to keep from mutating data streams
o Look at what ssl does to keep from mutating data streams
NICK . On the fly compression of each stream
o Clean up the event loop (optimize and sanitize)
ARMA o Remove that awful concept of 'roles'
@ -55,8 +55,13 @@ SPEC!! D Non-clique topologies
. Directory servers
D Automated reputation management
NICK . Include key in source; sign directories
o Signed directory backend
- Document
ARMA - Integrate
- Add versions to code
NICK . Have directories list recommended-versions
o Include (unused) line in directories
o Check for presence of line.
- Quit if running the wrong version
- Command-line option to override quit
. Add more information to directory server entries

View File

@ -551,10 +551,8 @@ int crypto_pk_public_checksig(crypto_pk_env_t *env, unsigned char *from, int fro
switch(env->type) {
case CRYPTO_PK_RSA:
if (!(((RSA*)env->key)->p))
return -1;
return RSA_public_decrypt(fromlen, from, to, (RSA *)env->key,
RSA_PKCS1_OAEP_PADDING);
RSA_PKCS1_PADDING);
default:
return -1;
}
@ -569,7 +567,7 @@ int crypto_pk_private_sign(crypto_pk_env_t *env, unsigned char *from, int fromle
if (!(((RSA*)env->key)->p))
return -1;
return RSA_private_encrypt(fromlen, from, to, (RSA *)env->key,
RSA_PKCS1_OAEP_PADDING);
RSA_PKCS1_PADDING);
default:
return -1;
}
@ -836,7 +834,7 @@ base64_encode(char *dest, int destlen, char *src, int srclen)
EVP_EncodeInit(&ctx);
EVP_EncodeUpdate(&ctx, dest, &len, src, srclen);
EVP_EncodeFinal(&ctx, dest, &ret);
EVP_EncodeFinal(&ctx, dest+len, &ret);
ret += len;
return ret;
}

View File

@ -65,7 +65,7 @@ int crypto_pk_keysize(crypto_pk_env_t *env);
int crypto_pk_public_encrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding);
int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to, int padding);
int crypto_pk_private_sign(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to);
int crypto_pk_private_checksig(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to);
int crypto_pk_public_checksig(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to);
int base64_encode(char *dest, int destlen, char *src, int srclen);
int base64_decode(char *dest, int destlen, char *src, int srclen);

View File

@ -678,16 +678,17 @@ dump_signed_directory_to_string_impl(char *s, int maxlen, directory_t *dir,
dump_directory_to_string_impl(s+i, maxlen-i, dir);
i = strlen(s);
strncat(s, "directory-signature\n", maxlen-i);
i = strlen(s);
cp = s + i;
if (crypto_SHA_digest(s, i, digest))
return -1;
if (crypto_pk_private_sign(private_key, digest, 20, signature))
if (crypto_pk_private_sign(private_key, digest, 20, signature) < 0)
return -1;
strncpy(cp,
"directory-signature\n-----BEGIN SIGNATURE-----\n", maxlen-i);
"-----BEGIN SIGNATURE-----\n", maxlen-i);
i = strlen(s);
cp = s+i;

View File

@ -739,6 +739,8 @@ int do_main_loop(void);
void dumpstats(void);
void dump_directory_to_string(char *s, int maxlen);
void dump_directory_to_string_impl(char *s, int maxlen, directory_t *directory);
int dump_signed_directory_to_string_impl(char *s, int maxlen, directory_t *dir, crypto_pk_env_t *private_key);
int main(int argc, char *argv[]);
@ -790,10 +792,13 @@ void router_get_directory(directory_t **pdirectory);
int router_is_me(uint32_t addr, uint16_t port);
void router_forget_router(uint32_t addr, uint16_t port);
int router_get_list_from_file(char *routerfile);
int router_resolve(routerinfo_t *router);
int router_get_list_from_string(char *s);
int router_get_list_from_string_impl(char *s, directory_t **dest);
int router_get_dir_from_string(char *s, crypto_pk_env_t *pkey);
int router_get_dir_from_string_impl(char *s, directory_t **dest,
crypto_pk_env_t *pkey);
routerinfo_t *router_get_entry_from_string(char **s);
int router_compare_to_exit_policy(connection_t *conn);
void routerlist_free(routerinfo_t *list);

View File

@ -2,7 +2,10 @@
/* See LICENSE for licensing information */
/* $Id$ */
#define OR_PUBLICKEY_BEGIN_TAG "-----BEGIN RSA PUBLIC KEY-----\n"
#define OR_PUBLICKEY_END_TAG "-----END RSA PUBLIC KEY-----\n"
#define OR_SIGNATURE_BEGIN_TAG "-----BEGIN SIGNATURE-----\n"
#define OR_SIGNATURE_END_TAG "-----END SIGNATURE-----\n"
#include "or.h"
@ -16,14 +19,22 @@ extern routerinfo_t *my_routerinfo; /* from main.c */
/****************************************************************************/
struct directory_token;
typedef struct directory_token directory_token_t;
/* static function prototypes */
void routerlist_free(routerinfo_t *list);
static routerinfo_t **make_rarray(routerinfo_t* list, int *len);
static char *eat_whitespace(char *s);
static char *eat_whitespace_no_nl(char *s);
static char *find_whitespace(char *s);
static int router_resolve(routerinfo_t *router);
static void router_add_exit_policy(routerinfo_t *router, char *string);
static void router_free_exit_policy(routerinfo_t *router);
static routerinfo_t *router_get_entry_from_string_tok(char**s,
directory_token_t *tok);
static int router_get_list_from_string_tok(char **s, directory_t **dest,
directory_token_t *tok);
static int router_add_exit_policy(routerinfo_t *router,
directory_token_t *tok);
/****************************************************************************/
@ -288,62 +299,190 @@ int router_get_list_from_file(char *routerfile)
return 0;
}
int router_get_list_from_string(char *s)
{
return router_get_list_from_string_impl(s, &directory);
}
int router_get_list_from_string_impl(char *s, directory_t **dest)
{
routerinfo_t *routerlist=NULL;
routerinfo_t *router;
routerinfo_t **new_router_array;
int new_rarray_len;
typedef enum {
K_ACCEPT,
K_CLIENT_SOFTWARE,
K_DIRECTORY_SIGNATURE,
K_REJECT,
K_ROUTER,
K_SERVER_SOFTWARE,
K_SIGNED_DIRECTORY,
K_SIGNING_KEY,
_SIGNATURE,
_PUBLIC_KEY,
_ERR,
_EOF
} directory_keyword;
assert(s);
struct token_table_ent { char *t; int v; };
while(*s) { /* while not at the end of the string */
router = router_get_entry_from_string(&s);
if(router == NULL) {
routerlist_free(routerlist);
return -1;
}
if (router_resolve(router)) {
routerlist_free(router);
routerlist_free(routerlist);
return -1;
}
switch(router_is_me(router->addr, router->or_port)) {
case 0: /* it's not me */
router->next = routerlist;
routerlist = router;
break;
case 1: /* it is me */
if(!my_routerinfo) /* save it, so we can use it for directories */
my_routerinfo = router;
else
routerlist_free(router);
break;
default:
log(LOG_ERR,"router_get_list_from_string(): router_is_me returned error.");
routerlist_free(routerlist);
return -1;
}
s = eat_whitespace(s);
}
new_router_array = make_rarray(routerlist, &new_rarray_len);
if(new_router_array) { /* success! replace the old one */
if (*dest)
directory_free(*dest);
*dest = (directory_t*) malloc(sizeof(directory_t));
(*dest)->routers = new_router_array;
(*dest)->n_routers = new_rarray_len;
static struct token_table_ent token_table[] = {
{ "accept", K_ACCEPT },
{ "client-software", K_CLIENT_SOFTWARE },
{ "directory-signature", K_DIRECTORY_SIGNATURE },
{ "reject", K_REJECT },
{ "router", K_ROUTER },
{ "server-software", K_SERVER_SOFTWARE },
{ "signed-directory", K_SIGNED_DIRECTORY },
{ "signing-key", K_SIGNING_KEY },
{ NULL, -1 }
};
#define MAX_ARGS 8
struct directory_token {
directory_keyword tp;
union {
struct {
char *args[MAX_ARGS+1];
int n_args;
} cmd;
char *signature;
char *error;
crypto_pk_env_t *public_key;
} val;
};
static int
_router_get_next_token(char **s, directory_token_t *tok) {
char *next;
crypto_pk_env_t *pkey = NULL;
char *signature = NULL;
int i, done;
tok->tp = _ERR;
tok->val.error = "";
*s = eat_whitespace(*s);
if (!**s) {
tok->tp = _EOF;
return 0;
} else if (**s == '-') {
next = strchr(*s, '\n');
if (! next) { tok->val.error = "No newline at EOF"; return -1; }
++next;
if (! strncmp(*s, OR_PUBLICKEY_BEGIN_TAG, next-*s)) {
next = strstr(*s, OR_PUBLICKEY_END_TAG);
if (!next) { tok->val.error = "No public key end tag found"; return -1; }
next = strchr(next, '\n'); /* Part of OR_PUBLICKEY_END_TAG; can't fail.*/
++next;
if (!(pkey = crypto_new_pk_env(CRYPTO_PK_RSA)))
return -1;
if (crypto_pk_read_public_key_from_string(pkey, *s, next-*s)) {
crypto_free_pk_env(pkey);
tok->val.error = "Couldn't parse public key.";
return -1;
}
tok->tp = _PUBLIC_KEY;
tok->val.public_key = pkey;
*s = next;
return 0;
} else if (! strncmp(*s, OR_SIGNATURE_BEGIN_TAG, next-*s)) {
/* Advance past newline; can't fail. */
*s = strchr(*s, '\n');
++*s;
/* Find end of base64'd data */
next = strstr(*s, OR_SIGNATURE_END_TAG);
if (!next) { tok->val.error = "No signature end tag found"; return -1; }
signature = malloc(256);
i = base64_decode(signature, 256, *s, next-*s);
if (i<0) {
free(signature);
tok->val.error = "Error decoding signature."; return -1;
} else if (i != 128) {
free(signature);
tok->val.error = "Bad length on decoded signature."; return -1;
}
tok->tp = _SIGNATURE;
tok->val.signature = signature;
next = strchr(next, '\n'); /* Part of OR_SIGNATURE_END_TAG; can't fail.*/
*s = next+1;
return 0;
} else {
tok->val.error = "Unrecognized begin line"; return -1;
}
} else {
next = find_whitespace(*s);
if (!next) {
tok->val.error = "Unexpected EOF"; return -1;
}
for (i = 0 ; token_table[i].t ; ++i) {
if (!strncmp(token_table[i].t, *s, next-*s)) {
tok->tp = token_table[i].v;
i = 0;
done = (*next == '\n');
*s = eat_whitespace_no_nl(next);
while (**s != '\n' && i <= MAX_ARGS && !done) {
next = find_whitespace(*s);
if (*next == '\n')
done = 1;
*next = 0;
tok->val.cmd.args[i++] = *s;
*s = eat_whitespace_no_nl(next+1);
};
tok->val.cmd.n_args = i;
if (i > MAX_ARGS) {
tok->tp = _ERR;
tok->val.error = "Too many arguments"; return -1;
}
return 0;
}
}
tok->val.error = "Unrecognized command"; return -1;
}
return -1;
}
static void
router_dump_token(directory_token_t *tok) {
int i;
switch(tok->tp)
{
case _SIGNATURE:
puts("(signature)");
return;
case _PUBLIC_KEY:
puts("(public key)");
return;
case _ERR:
printf("(Error: %s\n)", tok->val.error);
return;
case _EOF:
puts("EOF");
return;
case K_ACCEPT: printf("Accept"); break;
case K_CLIENT_SOFTWARE: printf("Client-Software"); break;
case K_DIRECTORY_SIGNATURE: printf("Directory-Signature"); break;
case K_REJECT: printf("Reject"); break;
case K_ROUTER: printf("Router"); break;
case K_SERVER_SOFTWARE: printf("Server-Software"); break;
case K_SIGNED_DIRECTORY: printf("Signed-Directory"); break;
case K_SIGNING_KEY: printf("Signing-Key"); break;
default:
printf("?????? %d\n", tok->tp); return;
}
for (i = 0; i < tok->val.cmd.n_args; ++i) {
printf(" \"%s\"", tok->val.cmd.args[i]);
}
printf("\n");
return;
}
#ifdef DEBUG_ROUTER_TOKENS
static int
router_get_next_token(char **s, directory_token_t *tok) {
int i;
i = _router_get_next_token(s, tok);
router_dump_token(tok);
return i;
}
#else
#define router_get_next_token _router_get_next_token
#endif
/* return the first char of s that is not whitespace and not a comment */
static char *eat_whitespace(char *s) {
assert(s);
@ -361,6 +500,12 @@ static char *eat_whitespace(char *s) {
return s;
}
static char *eat_whitespace_no_nl(char *s) {
while(*s == ' ' || *s == '\t')
++s;
return s;
}
/* return the first char of s that is whitespace or '#' or '\0 */
static char *find_whitespace(char *s) {
assert(s);
@ -371,6 +516,145 @@ static char *find_whitespace(char *s) {
return s;
}
int router_get_list_from_string(char *s)
{
return router_get_list_from_string_impl(s, &directory);
}
int router_get_list_from_string_impl(char *s, directory_t **dest) {
directory_token_t tok;
if (router_get_next_token(&s, &tok)) {
return NULL;
}
return router_get_list_from_string_tok(&s, dest, &tok);
}
static int router_get_dir_hash(char *s, char *digest)
{
char *start, *end;
start = strstr(s, "signed-directory");
if (!start) return -1;
end = strstr(start, "directory-signature");
if (!end) return -1;
end = strchr(end, '\n');
if (!end) return -1;
++end;
if (crypto_SHA_digest(start, end-start, digest))
return -1;
return 0;
}
int router_get_dir_from_string(char *s, crypto_pk_env_t *pkey)
{
return router_get_dir_from_string_impl(s, &directory, pkey);
}
int router_get_dir_from_string_impl(char *s, directory_t **dest,
crypto_pk_env_t *pkey)
{
directory_token_t tok;
char digest[20];
char signed_digest[128];
#define NEXT_TOK() \
do { \
if (router_get_next_token(&s, &tok)) { \
log(LOG_ERR, "Error reading directory: %s", tok.val.error); \
return -1; \
} } while (0)
#define TOK_IS(type,name) \
do { \
if (tok.tp != type) { \
log(LOG_ERR, "Error reading directory: expected %s", name); \
return -1; \
} } while(0)
if (router_get_dir_hash(s, digest))
return -1;
NEXT_TOK();
TOK_IS(K_SIGNED_DIRECTORY, "signed-directory");
NEXT_TOK();
TOK_IS(K_CLIENT_SOFTWARE, "client-software");
NEXT_TOK();
TOK_IS(K_SERVER_SOFTWARE, "server-software");
NEXT_TOK();
if (router_get_list_from_string_tok(&s, dest, &tok))
return -1;
TOK_IS(K_DIRECTORY_SIGNATURE, "directory-signature");
NEXT_TOK();
TOK_IS(_SIGNATURE, "signature");
if (pkey) {
if (crypto_pk_public_checksig(pkey, tok.val.signature, 128, signed_digest)
!= 20) {
log(LOG_ERR, "Error reading directory: invalid signature.");
free(tok.val.signature);
return -1;
}
if (memcmp(digest, signed_digest, 20)) {
log(LOG_ERR, "Error reading directory: signature does not match.");
free(tok.val.signature);
return -1;
}
}
free(tok.val.signature);
NEXT_TOK();
TOK_IS(_EOF, "end of directory");
return 0;
#undef NEXT_TOK
#undef TOK_IS
}
static int router_get_list_from_string_tok(char **s, directory_t **dest,
directory_token_t *tok)
{
routerinfo_t *routerlist=NULL;
routerinfo_t *router;
routerinfo_t **new_router_array;
int new_rarray_len;
assert(s);
while (tok->tp == K_ROUTER) {
router = router_get_entry_from_string_tok(s, tok);
switch(router_is_me(router->addr, router->or_port)) {
case 0: /* it's not me */
router->next = routerlist;
routerlist = router;
break;
case 1: /* it is me */
if(!my_routerinfo) /* save it, so we can use it for directories */
my_routerinfo = router;
else
routerlist_free(router);
break;
default:
log(LOG_ERR,"router_get_list_from_string(): router_is_me returned error.");
routerlist_free(routerlist);
return -1;
}
}
new_router_array = make_rarray(routerlist, &new_rarray_len);
if(new_router_array) { /* success! replace the old one */
if (*dest)
directory_free(*dest);
*dest = (directory_t*) malloc(sizeof(directory_t));
(*dest)->routers = new_router_array;
(*dest)->n_routers = new_rarray_len;
return 0;
}
return -1;
}
static int
router_resolve(routerinfo_t *router)
{
@ -388,157 +672,102 @@ router_resolve(routerinfo_t *router)
return 0;
}
routerinfo_t *router_get_entry_from_string(char **s) {
directory_token_t tok;
routerinfo_t *router;
if (router_get_next_token(s, &tok)) return NULL;
router = router_get_entry_from_string_tok(s, &tok);
if (tok.tp != _EOF)
return NULL;
return router;
}
/* reads a single router entry from s.
* updates s so it points to after the router it just read.
* mallocs a new router, returns it if all goes well, else returns NULL.
*/
routerinfo_t *router_get_entry_from_string(char **s) {
routerinfo_t *router;
char *next;
static routerinfo_t *router_get_entry_from_string_tok(char**s, directory_token_t *tok) {
routerinfo_t *router = NULL;
/* Make sure that this string really starts with a router entry. */
*s = eat_whitespace(*s);
if (strncasecmp(*s, "router ", 7)) {
#define NEXT_TOKEN() \
do { if (router_get_next_token(s, tok)) goto err; \
} while(0)
#define ARGS tok->val.cmd.args
if (tok->tp != K_ROUTER) {
log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\"");
return NULL;
}
router = malloc(sizeof(routerinfo_t));
if (!router) {
if (!(router = malloc(sizeof(routerinfo_t)))) {
log(LOG_ERR,"router_get_entry_from_string(): Could not allocate memory.");
return NULL;
}
memset(router,0,sizeof(routerinfo_t)); /* zero it out first */
router->next = NULL;
/* Bug: if find_whitespace returns a '#', we'll squish it. */
#define NEXT_TOKEN(s, next) \
*s = eat_whitespace(*s); \
next = find_whitespace(*s); \
if(!*next) { \
goto router_read_failed; \
} \
*next = 0;
if (tok->val.cmd.n_args != 6) {
log(LOG_ERR,"router_get_entry_from_string(): Wrong # of arguments to \"router\"");
goto err;
}
/* Skip the "router" */
NEXT_TOKEN(s, next);
*s = next+1;
/* read router->address */
NEXT_TOKEN(s, next);
router->address = strdup(*s);
*s = next+1;
/* Don't resolve address till later. */
/* read router.address */
if (!(router->address = strdup(ARGS[0])))
goto err;
router->addr = 0;
/* read router->or_port */
NEXT_TOKEN(s, next);
router->or_port = atoi(*s);
/* Read router->or_port */
router->or_port = atoi(ARGS[1]);
if(!router->or_port) {
log(LOG_ERR,"router_get_entry_from_string(): or_port '%s' unreadable or 0. Failing.",*s);
goto router_read_failed;
log(LOG_ERR,"router_get_entry_from_string(): or_port unreadable or 0. Failing.");
goto err;
}
*s = next+1;
/* read router->op_port */
NEXT_TOKEN(s, next);
router->op_port = atoi(*s);
*s = next+1;
/* Router->op_port */
router->op_port = atoi(ARGS[2]);
/* read router->ap_port */
NEXT_TOKEN(s, next);
router->ap_port = atoi(*s);
*s = next+1;
/* Router->ap_port */
router->ap_port = atoi(ARGS[3]);
/* read router->dir_port */
NEXT_TOKEN(s, next);
router->dir_port = atoi(*s);
*s = next+1;
/* Router->dir_port */
router->dir_port = atoi(ARGS[4]);
/* read router->bandwidth */
NEXT_TOKEN(s, next);
router->bandwidth = atoi(*s);
if(!router->bandwidth) {
log(LOG_ERR,"router_get_entry_from_string(): bandwidth '%s' unreadable or 0. Failing.",*s);
goto router_read_failed;
/* Router->bandwidth */
router->bandwidth = atoi(ARGS[5]);
if (!router->bandwidth) {
log(LOG_ERR,"router_get_entry_from_string(): bandwidth unreadable or 0. Failing.");
}
*s = next+1;
log(LOG_DEBUG,"or_port %d, op_port %d, ap_port %d, dir_port %d, bandwidth %d.",
router->or_port, router->op_port, router->ap_port, router->dir_port, router->bandwidth);
*s = eat_whitespace(*s);
next = strstr(*s,OR_PUBLICKEY_END_TAG);
router->pkey = crypto_new_pk_env(CRYPTO_PK_RSA);
if(!next || !router->pkey) {
log(LOG_ERR,"router_get_entry_from_string(): Couldn't find pk in string");
goto router_read_failed;
NEXT_TOKEN();
if (tok->tp != _PUBLIC_KEY) {
log(LOG_ERR,"router_get_entry_from_string(): Missing public key");
goto err;
} /* Check key length */
router->pkey = tok->val.public_key;
NEXT_TOKEN();
if (tok->tp == K_SIGNING_KEY) {
NEXT_TOKEN();
if (tok->tp != _PUBLIC_KEY) {
log(LOG_ERR,"router_get_entry_from_string(): Missing signing key");
goto err;
}
router->signing_pkey = tok->val.public_key;
NEXT_TOKEN();
}
while (tok->tp == K_ACCEPT || tok->tp == K_REJECT) {
router_add_exit_policy(router, tok);
NEXT_TOKEN();
}
/* now advance *s so it's at the end of this public key */
next = strchr(next, '\n');
assert(next); /* can't fail, we just checked it was here */
*next = 0;
// log(LOG_DEBUG,"Key about to be read is: '%s'",*s);
if((crypto_pk_read_public_key_from_string(router->pkey, *s, strlen(*s))<0)) {
log(LOG_ERR,"router_get_entry_from_string(): Couldn't read pk from string");
goto router_read_failed;
}
log(LOG_DEBUG,"router_get_entry_from_string(): Public key size = %u.", crypto_pk_keysize(router->pkey));
if (crypto_pk_keysize(router->pkey) != 128) { /* keys MUST be 1024 bits in size */
log(LOG_ERR,"Key for router %s:%u is not 1024 bits. All keys must be exactly 1024 bits long.",
router->address,router->or_port);
goto router_read_failed;
}
*s = next+1;
*s = eat_whitespace(*s);
if (!strncasecmp(*s, "signing-key", 11)) {
/* We have a signing key */
*s = strchr(*s, '\n');
*s = eat_whitespace(*s);
next = strstr(*s,OR_PUBLICKEY_END_TAG);
router->signing_pkey = crypto_new_pk_env(CRYPTO_PK_RSA);
if (!next || !router->signing_pkey) {
log(LOG_ERR,"router_get_entry_from_string(): Couldn't find signing_pk in string");
goto router_read_failed;
}
next = strchr(next, '\n');
assert(next);
*next = 0;
if ((crypto_pk_read_public_key_from_string(router->signing_pkey, *s,
strlen(*s)))<0) {
log(LOG_ERR,"router_get_entry_from_string(): Couldn't read signing pk from string");
goto router_read_failed;
}
log(LOG_DEBUG,"router_get_entry_from_string(): Signing key size = %u.", crypto_pk_keysize(router->signing_pkey));
if (crypto_pk_keysize(router->signing_pkey) != 128) { /* keys MUST be 1024 bits in size */
log(LOG_ERR,"Signing key for router %s:%u is 1024 bits. All keys must be exactly 1024 bits long.",
router->address,router->or_port);
goto router_read_failed;
}
*s = next+1;
}
// test_write_pkey(router->pkey);
while(**s && **s != '\n') {
/* pull in a line of exit policy */
next = strchr(*s, '\n');
if(!next)
goto router_read_failed;
*next = 0;
router_add_exit_policy(router, *s);
*s = next+1;
}
return router;
router_read_failed:
err:
if(router->address)
free(router->address);
if(router->pkey)
@ -546,6 +775,8 @@ router_read_failed:
router_free_exit_policy(router);
free(router);
return NULL;
#undef ARGS
#undef NEXT_TOKEN
}
static void router_free_exit_policy(routerinfo_t *router) {
@ -576,43 +807,35 @@ void test_write_pkey(crypto_pk_env_t *pkey) {
}
#endif
static void router_add_exit_policy(routerinfo_t *router, char *string) {
static int router_add_exit_policy(routerinfo_t *router,
directory_token_t *tok) {
struct exit_policy_t *tmpe, *newe;
char *n;
char *arg, *colon;
string = eat_whitespace(string);
if(!*string) /* it was all whitespace or comment */
return;
if (tok->val.cmd.n_args != 1)
return -1;
arg = tok->val.cmd.args[0];
newe = malloc(sizeof(struct exit_policy_t));
memset(newe,0,sizeof(struct exit_policy_t));
newe->string = strdup(string);
n = find_whitespace(string);
*n = 0;
if(!strcasecmp(string,"reject")) {
newe->string = malloc(8+strlen(arg));
if (tok->tp == K_REJECT) {
strcpy(newe->string, "reject ");
newe->policy_type = EXIT_POLICY_REJECT;
} else if(!strcasecmp(string,"accept")) {
newe->policy_type = EXIT_POLICY_ACCEPT;
} else {
goto policy_read_failed;
assert(tok->tp == K_ACCEPT);
strcpy(newe->string, "accept ");
newe->policy_type = EXIT_POLICY_ACCEPT;
}
string = eat_whitespace(n+1);
if(!*string) {
strcat(newe->string, arg);
colon = strchr(arg,':');
if(!colon)
goto policy_read_failed;
}
n = strchr(string,':');
if(!n)
goto policy_read_failed;
*n = 0;
newe->address = strdup(string);
string = n+1;
n = find_whitespace(string);
*n = 0;
newe->port = strdup(string);
*colon = 0;
newe->address = strdup(arg);
newe->port = strdup(colon+1);
log(LOG_DEBUG,"router_add_exit_policy(): type %d, address '%s', port '%s'.",
newe->policy_type, newe->address, newe->port);
@ -621,13 +844,13 @@ static void router_add_exit_policy(routerinfo_t *router, char *string) {
if(!router->exit_policy) {
router->exit_policy = newe;
return;
return 0;
}
for(tmpe=router->exit_policy; tmpe->next; tmpe=tmpe->next) ;
tmpe->next = newe;
return;
return 0;
policy_read_failed:
assert(newe->string);
@ -639,8 +862,7 @@ policy_read_failed:
if(newe->port)
free(newe->port);
free(newe);
return;
return -1;
}
/* Return 0 if my exit policy says to allow connection to conn.

View File

@ -405,7 +405,7 @@ test_crypto()
memcpy(data2+1, "XYZZY", 5); /* This has fails ~ once-in-2^40 */
test_eq(-1, crypto_pk_private_decrypt(pk1, data2, 128, data3,
RSA_PKCS1_OAEP_PADDING));
/* File operations: save and load private key */
f = fopen("/tmp/tor_test/pkey1", "wb");
test_assert(! crypto_pk_write_private_key_to_file(pk1, f));
@ -419,11 +419,28 @@ test_crypto()
"/tmp/tor_test/pkey1"));
test_eq(15, crypto_pk_private_decrypt(pk2, data1, 128, data3,
RSA_PKCS1_OAEP_PADDING));
/* Now try signing. */
strcpy(data1, "Ossifrage");
test_eq(128, crypto_pk_private_sign(pk1, data1, 10, data2));
test_eq(10, crypto_pk_public_checksig(pk1, data2, 128, data3));
test_streq(data3, "Ossifrage");
/*XXXX test failed signing*/
crypto_free_pk_env(pk1);
crypto_free_pk_env(pk2);
/* Base64 tests */
strcpy(data1, "Test string that contains 35 chars.");
strcat(data1, " 2nd string that contains 35 chars.");
i = base64_encode(data2, 1024, data1, 71);
j = base64_decode(data3, 1024, data2, i);
test_streq(data3, data1);
test_eq(j, 71);
test_assert(data2[i] == '\0');
free(data1);
free(data2);
free(data3);
@ -512,9 +529,8 @@ test_dir_format()
routerinfo_t r1, r2;
crypto_pk_env_t *pk1 = NULL, *pk2 = NULL;
routerinfo_t *rp1, *rp2;
struct exit_policy_t ex1, ex2, ex3;
int i;
struct exit_policy_t ex1, ex2;
directory_t *dir1 = NULL, *dir2 = NULL;
test_assert( (pk1 = crypto_new_pk_env(CRYPTO_PK_RSA)) );
test_assert( (pk2 = crypto_new_pk_env(CRYPTO_PK_RSA)) );
@ -609,8 +625,15 @@ test_dir_format()
test_assert(rp2->exit_policy->next->next == NULL);
/* Okay, now for the directories. */
dir1 = (directory_t*) malloc(sizeof(directory_t));
dir1->n_routers = 2;
dir1->routers = (routerinfo_t**) malloc(sizeof(routerinfo_t*)*2);
dir1->routers[0] = &r1;
dir1->routers[1] = &r2;
test_assert(! dump_signed_directory_to_string_impl(buf, 2048, dir1, pk1));
/* puts(buf); */
test_assert(! router_get_dir_from_string_impl(buf, &dir2, pk1));
if (pk1_str) free(pk1_str);
if (pk2_str) free(pk2_str);
@ -618,6 +641,8 @@ test_dir_format()
if (pk2) crypto_free_pk_env(pk2);
if (rp1) routerlist_free(rp1);
if (rp2) routerlist_free(rp2);
if (dir1) free(dir1); /* And more !*/
if (dir1) free(dir2); /* And more !*/
}
int