More work on directories. Signed directories not yet tested. No support for checking sigs yet
svn:r268
This commit is contained in:
parent
3416a10627
commit
d0ff485e1b
4
doc/TODO
4
doc/TODO
|
@ -83,8 +83,8 @@ SPEC!! - Handle socks commands other than connect, eg, bind?
|
|||
o Cells
|
||||
. Better comments for functions!
|
||||
- Tests
|
||||
NICK o Testing harness/infrastructure
|
||||
. Unit tests
|
||||
o Testing harness/infrastructure
|
||||
NICK . Unit tests
|
||||
D System tests (how?)
|
||||
- Performance tests, so we know when we've improved
|
||||
. webload infrastructure (Bruce)
|
||||
|
|
|
@ -545,6 +545,36 @@ int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fro
|
|||
}
|
||||
}
|
||||
|
||||
int crypto_pk_public_checksig(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to)
|
||||
{
|
||||
assert(env && from && to);
|
||||
|
||||
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);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int crypto_pk_private_sign(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to)
|
||||
{
|
||||
assert(env && from && to);
|
||||
|
||||
switch(env->type) {
|
||||
case CRYPTO_PK_RSA:
|
||||
if (!(((RSA*)env->key)->p))
|
||||
return -1;
|
||||
return RSA_private_encrypt(fromlen, from, to, (RSA *)env->key,
|
||||
RSA_PKCS1_OAEP_PADDING);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* symmetric crypto */
|
||||
int crypto_cipher_generate_key(crypto_cipher_env_t *env)
|
||||
{
|
||||
|
@ -779,3 +809,38 @@ char *crypto_perror()
|
|||
return (char *)ERR_reason_error_string(ERR_get_error());
|
||||
}
|
||||
|
||||
int
|
||||
base64_encode(char *dest, int destlen, char *src, int srclen)
|
||||
{
|
||||
EVP_ENCODE_CTX ctx;
|
||||
int len, ret;
|
||||
|
||||
/* 48 bytes of input -> 64 bytes of output plus newline.
|
||||
Plus one more byte, in case I'm wrong.
|
||||
*/
|
||||
if (destlen < ((srclen/48)+1)*66)
|
||||
return -1;
|
||||
|
||||
EVP_EncodeInit(&ctx);
|
||||
EVP_EncodeUpdate(&ctx, dest, &len, src, srclen);
|
||||
EVP_EncodeFinal(&ctx, dest, &ret);
|
||||
ret += len;
|
||||
return ret;
|
||||
}
|
||||
int
|
||||
base64_decode(char *dest, int destlen, char *src, int srclen)
|
||||
{
|
||||
EVP_ENCODE_CTX ctx;
|
||||
int len, ret;
|
||||
/* 64 bytes of input -> *up to* 48 bytes of output.
|
||||
Plus one more byte, in caes I'm wrong.
|
||||
*/
|
||||
if (destlen < ((srclen/64)+1)*49)
|
||||
return -1;
|
||||
|
||||
EVP_DecodeInit(&ctx);
|
||||
EVP_DecodeUpdate(&ctx, dest, &len, src, srclen);
|
||||
EVP_DecodeFinal(&ctx, dest, &ret);
|
||||
ret += len;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,11 @@ 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 base64_encode(char *dest, int destlen, char *src, int srclen);
|
||||
int base64_decode(char *dest, int destlen, char *src, int srclen);
|
||||
|
||||
/* Key negotiation */
|
||||
typedef struct crypto_dh_env_st crypto_dh_env_t;
|
||||
|
|
103
src/or/main.c
103
src/or/main.c
|
@ -555,7 +555,8 @@ void dumpstats(void) { /* dump stats to stdout */
|
|||
|
||||
int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) {
|
||||
char *pkey;
|
||||
int pkeylen;
|
||||
char *signing_pkey, *signing_pkey_tag;
|
||||
int pkeylen, signing_pkeylen;
|
||||
int written;
|
||||
int result=0;
|
||||
struct exit_policy_t *tmpe;
|
||||
|
@ -565,16 +566,30 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
result = snprintf(s, maxlen, "router %s %d %d %d %d %d\n%s",
|
||||
signing_pkey = "";
|
||||
signing_pkey_tag = "";
|
||||
if (router->signing_pkey) {
|
||||
if(crypto_pk_write_public_key_to_string(router->signing_pkey,
|
||||
&signing_pkey,&signing_pkeylen)<0) {
|
||||
log(LOG_ERR,"dump_router_to_string(): write signing_pkey to string failed!");
|
||||
return 0;
|
||||
}
|
||||
signing_pkey_tag = "signing-key\n";
|
||||
}
|
||||
|
||||
result = snprintf(s, maxlen, "router %s %d %d %d %d %d\n%s%s%s",
|
||||
router->address,
|
||||
router->or_port,
|
||||
router->op_port,
|
||||
router->ap_port,
|
||||
router->dir_port,
|
||||
router->bandwidth,
|
||||
pkey);
|
||||
pkey,
|
||||
signing_pkey_tag, signing_pkey);
|
||||
|
||||
free(pkey);
|
||||
if (*signing_pkey)
|
||||
free(signing_pkey);
|
||||
|
||||
if(result < 0 || result > maxlen) {
|
||||
/* apparently different glibcs do different things on snprintf error.. so check both */
|
||||
|
@ -607,21 +622,23 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) {
|
|||
|
||||
}
|
||||
|
||||
void dump_directory_to_string(char *s, int maxlen) {
|
||||
int i;
|
||||
void dump_directory_to_string(char *s, int maxlen)
|
||||
{
|
||||
directory_t dir;
|
||||
routerinfo_t **routers = NULL;;
|
||||
connection_t *conn;
|
||||
routerinfo_t *router;
|
||||
int written;
|
||||
int i, n = 0;
|
||||
|
||||
/* first write my own info */
|
||||
if(my_routerinfo) {
|
||||
written = dump_router_to_string(s, maxlen, my_routerinfo);
|
||||
maxlen -= written;
|
||||
s += written;
|
||||
routers = (routerinfo_t**) malloc(sizeof(routerinfo_t*) * (nfds+1));
|
||||
if (!routers) {
|
||||
/* freak out XXX */
|
||||
return;
|
||||
}
|
||||
|
||||
/* now write info for other routers */
|
||||
for(i=0;i<nfds;i++) {
|
||||
if (my_routerinfo) {
|
||||
routers[n++] = my_routerinfo;
|
||||
}
|
||||
for(i = 0; i<nfds; ++i) {
|
||||
conn = connection_array[i];
|
||||
|
||||
if(conn->type != CONN_TYPE_OR)
|
||||
|
@ -633,7 +650,64 @@ void dump_directory_to_string(char *s, int maxlen) {
|
|||
log(LOG_ERR,"dump_directory_to_string(): couldn't find router %d:%d!",conn->addr,conn->port);
|
||||
continue;
|
||||
}
|
||||
routers[n++] = router;
|
||||
}
|
||||
dir.routers = routers;
|
||||
dir.n_routers = n;
|
||||
|
||||
dump_directory_to_string_impl(s, maxlen, &dir);
|
||||
}
|
||||
|
||||
int
|
||||
dump_signed_directory_to_string_impl(char *s, int maxlen, directory_t *dir,
|
||||
crypto_pk_env_t *private_key)
|
||||
{
|
||||
char *cp;
|
||||
char digest[20];
|
||||
char signature[128];
|
||||
int i;
|
||||
strncpy(s,
|
||||
"signed-directory\n"
|
||||
"client-software x y z\n" /* XXX make this real */
|
||||
"server-software a b c\n\n" /* XXX make this real */
|
||||
, maxlen);
|
||||
/* These multiple strlen calls are inefficient, but dwarfed by the RSA
|
||||
signature.
|
||||
*/
|
||||
i = strlen(s);
|
||||
|
||||
dump_directory_to_string_impl(s+i, maxlen-i, dir);
|
||||
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))
|
||||
return -1;
|
||||
|
||||
|
||||
strncpy(cp,
|
||||
"directory-signature\n-----BEGIN SIGNATURE-----\n", maxlen-i);
|
||||
|
||||
i = strlen(s);
|
||||
cp = s+i;
|
||||
if (base64_encode(cp, maxlen-i, signature, 128) < 0)
|
||||
return -1;
|
||||
|
||||
i = strlen(s);
|
||||
cp = s+i;
|
||||
strcat(cp, "-----END SIGNATURE-----\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_directory_to_string_impl(char *s, int maxlen, directory_t *directory) {
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
int written;
|
||||
|
||||
for (i = 0; i < directory->n_routers; ++i) {
|
||||
router = directory->routers[i];
|
||||
written = dump_router_to_string(s, maxlen, router);
|
||||
|
||||
if(written < 0) {
|
||||
|
@ -645,7 +719,6 @@ void dump_directory_to_string(char *s, int maxlen) {
|
|||
maxlen -= written;
|
||||
s += written;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void daemonize(void) {
|
||||
|
|
|
@ -320,6 +320,7 @@ typedef struct {
|
|||
uint16_t dir_port;
|
||||
|
||||
crypto_pk_env_t *pkey; /* public RSA key */
|
||||
crypto_pk_env_t *signing_pkey; /* May be null */
|
||||
|
||||
/* link info */
|
||||
uint32_t bandwidth;
|
||||
|
@ -737,6 +738,7 @@ 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 main(int argc, char *argv[]);
|
||||
|
||||
|
@ -793,6 +795,7 @@ int router_get_list_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 routerlist_free(routerinfo_t *list);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ extern routerinfo_t *my_routerinfo; /* from main.c */
|
|||
/****************************************************************************/
|
||||
|
||||
/* static function prototypes */
|
||||
static void routerlist_free(routerinfo_t *list);
|
||||
void routerlist_free(routerinfo_t *list);
|
||||
static routerinfo_t **make_rarray(routerinfo_t* list, int *len);
|
||||
static char *eat_whitespace(char *s);
|
||||
static char *find_whitespace(char *s);
|
||||
|
@ -124,7 +124,7 @@ int router_is_me(uint32_t addr, uint16_t port)
|
|||
}
|
||||
|
||||
/* delete a list of routers from memory */
|
||||
static void routerlist_free(routerinfo_t *list)
|
||||
void routerlist_free(routerinfo_t *list)
|
||||
{
|
||||
routerinfo_t *tmp = NULL;
|
||||
struct exit_policy_t *e = NULL, *etmp = NULL;
|
||||
|
@ -402,7 +402,6 @@ routerinfo_t *router_get_entry_from_string(char **s) {
|
|||
log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\"");
|
||||
return NULL;
|
||||
}
|
||||
puts("X");
|
||||
|
||||
router = malloc(sizeof(routerinfo_t));
|
||||
if (!router) {
|
||||
|
@ -477,7 +476,7 @@ routerinfo_t *router_get_entry_from_string(char **s) {
|
|||
goto router_read_failed;
|
||||
}
|
||||
|
||||
/* now advance *s so it's at the end of this router entry */
|
||||
/* 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;
|
||||
|
@ -494,10 +493,40 @@ routerinfo_t *router_get_entry_from_string(char **s) {
|
|||
goto router_read_failed;
|
||||
}
|
||||
|
||||
// test_write_pkey(router->pkey);
|
||||
|
||||
*s = next+1;
|
||||
while(**s != '\n') {
|
||||
*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)
|
||||
|
@ -509,7 +538,6 @@ routerinfo_t *router_get_entry_from_string(char **s) {
|
|||
|
||||
return router;
|
||||
|
||||
|
||||
router_read_failed:
|
||||
if(router->address)
|
||||
free(router->address);
|
||||
|
|
|
@ -506,8 +506,8 @@ void
|
|||
test_dir_format()
|
||||
{
|
||||
|
||||
char buf[2048], buf2[512];
|
||||
char *pk1_str, *pk2_str, *cp;
|
||||
char buf[2048], buf2[2048];
|
||||
char *pk1_str = NULL, *pk2_str = NULL, *cp;
|
||||
int pk1_str_len, pk2_str_len;
|
||||
routerinfo_t r1, r2;
|
||||
crypto_pk_env_t *pk1 = NULL, *pk2 = NULL;
|
||||
|
@ -528,6 +528,7 @@ test_dir_format()
|
|||
r1.ap_port = 9002;
|
||||
r1.dir_port = 9003;
|
||||
r1.pkey = pk1;
|
||||
r1.signing_pkey = NULL;
|
||||
r1.bandwidth = 1000;
|
||||
r1.exit_policy = NULL;
|
||||
r1.next = &r2;
|
||||
|
@ -548,6 +549,7 @@ test_dir_format()
|
|||
r2.ap_port = 0;
|
||||
r2.dir_port = 0;
|
||||
r2.pkey = pk2;
|
||||
r2.signing_pkey = pk1;
|
||||
r2.bandwidth = 3000;
|
||||
r2.exit_policy = &ex1;
|
||||
r2.next = NULL;
|
||||
|
@ -574,10 +576,13 @@ test_dir_format()
|
|||
test_eq(rp1->dir_port, r1.dir_port);
|
||||
test_eq(rp1->bandwidth, r1.bandwidth);
|
||||
test_assert(crypto_pk_cmp_keys(rp1->pkey, pk1) == 0);
|
||||
test_assert(rp1->signing_pkey == NULL);
|
||||
test_assert(rp1->exit_policy == NULL);
|
||||
|
||||
strcpy(buf2, "router tor.tor.tor 9005 0 0 0 3000\n");
|
||||
strcat(buf2, pk2_str);
|
||||
strcat(buf2, "signing-key\n");
|
||||
strcat(buf2, pk1_str);
|
||||
strcat(buf2, "accept *:80\nreject 18.*:24\n\n");
|
||||
test_assert(dump_router_to_string(buf, 2048, &r2)>0);
|
||||
test_streq(buf, buf2);
|
||||
|
@ -592,6 +597,7 @@ test_dir_format()
|
|||
test_eq(rp2->dir_port, r2.dir_port);
|
||||
test_eq(rp2->bandwidth, r2.bandwidth);
|
||||
test_assert(crypto_pk_cmp_keys(rp2->pkey, pk2) == 0);
|
||||
test_assert(crypto_pk_cmp_keys(rp2->signing_pkey, pk1) == 0);
|
||||
test_eq(rp2->exit_policy->policy_type, EXIT_POLICY_ACCEPT);
|
||||
test_streq(rp2->exit_policy->string, "accept *:80");
|
||||
test_streq(rp2->exit_policy->address, "*");
|
||||
|
@ -601,9 +607,17 @@ test_dir_format()
|
|||
test_streq(rp2->exit_policy->next->address, "18.*");
|
||||
test_streq(rp2->exit_policy->next->port, "24");
|
||||
test_assert(rp2->exit_policy->next->next == NULL);
|
||||
|
||||
/* Okay, now for the directories. */
|
||||
|
||||
|
||||
/* XXXX free everything*/
|
||||
|
||||
|
||||
if (pk1_str) free(pk1_str);
|
||||
if (pk2_str) free(pk2_str);
|
||||
if (pk1) crypto_free_pk_env(pk1);
|
||||
if (pk2) crypto_free_pk_env(pk2);
|
||||
if (rp1) routerlist_free(rp1);
|
||||
if (rp2) routerlist_free(rp2);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -617,7 +631,7 @@ main(int c, char**v) {
|
|||
log(LOG_ERR,NULL); /* make logging quieter */
|
||||
|
||||
setup_directory();
|
||||
#if 1
|
||||
#if 0
|
||||
puts("========================== Buffers =========================");
|
||||
test_buffers();
|
||||
puts("========================== Crypto ==========================");
|
||||
|
|
Loading…
Reference in New Issue