[or-cvs] Refactor buffers; implement descriptors.
Nick Mathewson
nickm at seul.org
Thu Sep 25 05:17:14 UTC 2003
Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv24061/src/or
Modified Files:
buffers.c circuit.c config.c connection.c connection_edge.c
connection_or.c cpuworker.c directory.c dns.c main.c onion.c
or.h routers.c test.c
Log Message:
Refactor buffers; implement descriptors.
'buf_t' is now an opaque type defined in buffers.c .
Router descriptors now include all keys; routers generate keys as
needed on startup (in a newly defined "data directory"), and generate
their own descriptors. Descriptors are now self-signed.
Implementation is not complete: descriptors are never published; and
upon receiving a descriptor, the directory doesn't do anything with
it.
At least "routers.or" and orkeygen are now obsolete, BTW.
Index: buffers.c
===================================================================
RCS file: /home/or/cvsroot/src/or/buffers.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- buffers.c 24 Sep 2003 21:24:52 -0000 1.36
+++ buffers.c 25 Sep 2003 05:17:10 -0000 1.37
@@ -8,50 +8,103 @@
extern or_options_t options; /* command-line and config-file options */
-/* Create a new buf of size MAX_BUF_SIZE. Write a pointer to it
- * into *buf, write MAX_BUF_SIZE into *buflen, and initialize
- * *buf_datalen to 0. Return 0.
+struct buf_t {
+ char *buf;
+ size_t len;
+ size_t datalen;
+};
+
+#define BUF_OK(b) ((b) && (b)->buf && (b)->datalen <= (b)->len)
+
+/* Find the first instance of str on buf. If none exists, return -1.
+ * Otherwise, return index of the first character in buf _after_ the
+ * first instance of str.
*/
-int buf_new(char **buf, int *buflen, int *buf_datalen) {
+static int find_str_in_str(const char *str, int str_len,
+ const char *buf, int buf_len)
+{
+ const char *location;
+ const char *last_possible = buf + buf_len - str_len;
- assert(buf && buflen && buf_datalen);
+ assert(str && str_len > 0 && buf);
- *buf = (char *)tor_malloc(MAX_BUF_SIZE);
-// memset(*buf,0,MAX_BUF_SIZE);
- *buflen = MAX_BUF_SIZE;
- *buf_datalen = 0;
+ if(buf_len < str_len)
+ return -1;
- return 0;
+ for(location = buf; location <= last_possible; location++)
+ if((*location == *str) && !memcmp(location+1, str+1, str_len-1))
+ return location-buf+str_len;
+
+ return -1;
}
-void buf_free(char *buf) {
+/* Create and return a new buf of size 'size'
+ */
+buf_t *buf_new_with_capacity(size_t size) {
+ buf_t *buf;
+ buf = (buf_t*)tor_malloc(sizeof(buf_t));
+ buf->buf = (char *)tor_malloc(size);
+ buf->len = size;
+ buf->datalen = 0;
+// memset(buf->buf,0,size);
+
+ assert(BUF_OK(buf));
+ return buf;
+}
+
+buf_t *buf_new()
+{
+ return buf_new_with_capacity(MAX_BUF_SIZE);
+}
+
+
+size_t buf_datalen(const buf_t *buf)
+{
+ return buf->datalen;
+}
+
+size_t buf_capacity(const buf_t *buf)
+{
+ return buf->len;
+}
+
+const char *_buf_peek_raw_buffer(const buf_t *buf)
+{
+ return buf->buf;
+}
+
+void buf_free(buf_t *buf) {
+ assert(buf && buf->buf);
+ free(buf->buf);
free(buf);
}
-/* read from socket s, writing onto buf+buf_datalen.
+
+
+/* read from socket s, writing onto end of buf.
* read at most 'at_most' bytes, and in any case don't read more than will fit based on buflen.
* If read() returns 0, set *reached_eof to 1 and return 0. If you want to tear
* down the connection return -1, else return the number of bytes read.
*/
-int read_to_buf(int s, int at_most, char **buf, int *buflen, int *buf_datalen, int *reached_eof) {
+int read_to_buf(int s, int at_most, buf_t *buf, int *reached_eof) {
int read_result;
#ifdef MS_WINDOWS
int e;
#endif
- assert(buf && *buf && buflen && buf_datalen && reached_eof && (s>=0));
+ assert(BUF_OK(buf) && reached_eof && (s>=0));
/* this is the point where you would grow the buffer, if you want to */
- if(at_most > *buflen - *buf_datalen)
- at_most = *buflen - *buf_datalen; /* take the min of the two */
+ if(at_most > buf->len - buf->datalen)
+ at_most = buf->len - buf->datalen; /* take the min of the two */
if(at_most == 0)
return 0; /* we shouldn't read anything */
// log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most);
- read_result = read(s, *buf+*buf_datalen, at_most);
+ read_result = read(s, buf->buf+buf->datalen, at_most);
if (read_result < 0) {
if(!ERRNO_EAGAIN(errno)) { /* it's a real error */
return -1;
@@ -68,31 +121,33 @@
*reached_eof = 1;
return 0;
} else { /* we read some bytes */
- *buf_datalen += read_result;
- log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf.",read_result, *buf_datalen);
+ buf->datalen += read_result;
+ log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf.",read_result,
+ (int)buf->datalen);
return read_result;
}
}
-int read_to_buf_tls(tor_tls *tls, int at_most, char **buf, int *buflen, int *buf_datalen) {
+int read_to_buf_tls(tor_tls *tls, int at_most, buf_t *buf) {
int r;
- assert(tls && *buf && buflen && buf_datalen);
+ assert(tls && BUF_OK(buf));
- if (at_most > *buflen - *buf_datalen)
- at_most = *buflen - *buf_datalen;
+ if (at_most > buf->len - buf->datalen)
+ at_most = buf->len - buf->datalen;
if (at_most == 0)
return 0;
- r = tor_tls_read(tls, *buf+*buf_datalen, at_most);
+ r = tor_tls_read(tls, buf->buf+buf->datalen, at_most);
if (r<0)
return r;
- *buf_datalen += r;
- log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf.",r, *buf_datalen);
+ buf->datalen += r;
+ log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf.",r, (int)buf->datalen);
return r;
}
-int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datalen) {
+int flush_buf(int s, buf_t *buf, int *buf_flushlen)
+{
/* push from buf onto s
* then memmove to front of buf
@@ -103,14 +158,12 @@
int e;
#endif
- assert(buf && *buf && buflen && buf_flushlen && buf_datalen && (s>=0) && (*buf_flushlen <= *buf_datalen));
+ assert(BUF_OK(buf) && buf_flushlen && (s>=0) && (*buf_flushlen <= buf->datalen));
if(*buf_flushlen == 0) /* nothing to flush */
return 0;
- /* this is the point where you would grow the buffer, if you want to */
-
- write_result = write(s, *buf, *buf_flushlen);
+ write_result = write(s, buf->buf, *buf_flushlen);
if (write_result < 0) {
if(!ERRNO_EAGAIN(errno)) { /* it's a real error */
return -1;
@@ -124,72 +177,70 @@
log_fn(LOG_DEBUG,"write() would block, returning.");
return 0;
} else {
- *buf_datalen -= write_result;
+ buf->datalen -= write_result;
*buf_flushlen -= write_result;
- memmove(*buf, *buf+write_result, *buf_datalen);
+ memmove(buf->buf, buf->buf+write_result, buf->datalen);
log_fn(LOG_DEBUG,"%d: flushed %d bytes, %d ready to flush, %d remain.",
- s,write_result,*buf_flushlen,*buf_datalen);
+ s,write_result,*buf_flushlen,(int)buf->datalen);
return *buf_flushlen;
/* XXX USE_TLS should change to return write_result like any sane function would */
}
}
-int flush_buf_tls(tor_tls *tls, char **buf, int *buflen, int *buf_flushlen, int *buf_datalen)
+int flush_buf_tls(tor_tls *tls, buf_t *buf, int *buf_flushlen)
{
int r;
- assert(tls && *buf && buflen && buf_datalen);
+ assert(tls && BUF_OK(buf) && buf_flushlen);
/* we want to let tls write even if flushlen is zero, because it might
* have a partial record pending */
- r = tor_tls_write(tls, *buf, *buf_flushlen);
+ r = tor_tls_write(tls, buf->buf, *buf_flushlen);
if (r < 0) {
return r;
}
- *buf_datalen -= r;
+ buf->datalen -= r;
*buf_flushlen -= r;
- memmove(*buf, *buf+r, *buf_datalen);
+ memmove(buf->buf, buf->buf+r, buf->datalen);
log_fn(LOG_DEBUG,"flushed %d bytes, %d ready to flush, %d remain.",
- r,*buf_flushlen,*buf_datalen);
+ r,*buf_flushlen,(int)buf->datalen);
return r;
}
-int write_to_buf(char *string, int string_len,
- char **buf, int *buflen, int *buf_datalen) {
+int write_to_buf(char *string, int string_len, buf_t *buf) {
/* append string to buf (growing as needed, return -1 if "too big")
* return total number of bytes on the buf
*/
- assert(string && buf && *buf && buflen && buf_datalen);
+ assert(string && BUF_OK(buf));
/* this is the point where you would grow the buffer, if you want to */
- if (string_len + *buf_datalen > *buflen) { /* we're out of luck */
+ if (string_len + buf->datalen > buf->len) { /* we're out of luck */
log_fn(LOG_DEBUG, "buflen too small. Time to implement growing dynamic bufs.");
return -1;
}
- memcpy(*buf+*buf_datalen, string, string_len);
- *buf_datalen += string_len;
- log_fn(LOG_DEBUG,"added %d bytes to buf (now %d total).",string_len, *buf_datalen);
- return *buf_datalen;
+ memcpy(buf->buf+buf->datalen, string, string_len);
+ buf->datalen += string_len;
+ log_fn(LOG_DEBUG,"added %d bytes to buf (now %d total).",string_len, (int)buf->datalen);
+ return buf->datalen;
}
-int fetch_from_buf(char *string, int string_len,
- char **buf, int *buflen, int *buf_datalen) {
+int fetch_from_buf(char *string, int string_len, buf_t *buf) {
/* There must be string_len bytes in buf; write them onto string,
* then memmove buf back (that is, remove them from buf).
*
* Return the number of bytes still on the buffer. */
- assert(string && buf && *buf && buflen && buf_datalen);
- assert(string_len <= *buf_datalen); /* make sure we don't ask for too much */
+ assert(string && BUF_OK(buf));
+ assert(string_len <= buf->datalen); /* make sure we don't ask for too much */
- memcpy(string,*buf,string_len);
- *buf_datalen -= string_len;
- memmove(*buf, *buf+string_len, *buf_datalen);
- return *buf_datalen;
+ memcpy(string,buf->buf,string_len);
+ buf->datalen -= string_len;
+ memmove(buf->buf, buf->buf+string_len, buf->datalen);
+ return buf->datalen;
}
/* There is a (possibly incomplete) http statement on *buf, of the
@@ -204,24 +255,24 @@
*
* Else, change nothing and return 0.
*/
-int fetch_from_buf_http(char *buf, int *buf_datalen,
+int fetch_from_buf_http(buf_t *buf,
char *headers_out, int max_headerlen,
char *body_out, int max_bodylen) {
char *headers, *body;
int i;
int headerlen, bodylen, contentlen;
- assert(buf && buf_datalen);
+ assert(BUF_OK(buf));
- headers = buf;
- i = find_on_inbuf("\r\n\r\n", 4, buf, *buf_datalen);
+ headers = buf->buf;
+ i = find_on_inbuf("\r\n\r\n", 4, buf);
if(i < 0) {
log_fn(LOG_DEBUG,"headers not all here yet.");
return 0;
}
- body = buf+i;
+ body = buf->buf+i;
headerlen = body-headers; /* includes the CRLFCRLF */
- bodylen = *buf_datalen - headerlen;
+ bodylen = buf->datalen - headerlen;
log_fn(LOG_DEBUG,"headerlen %d, bodylen %d.",headerlen,bodylen);
if(headers_out && max_headerlen <= headerlen) {
@@ -234,9 +285,11 @@
}
#define CONTENT_LENGTH "\r\nContent-Length: "
- i = find_on_inbuf(CONTENT_LENGTH, strlen(CONTENT_LENGTH), headers, headerlen);
+ i = find_str_in_str(CONTENT_LENGTH, sizeof(CONTENT_LENGTH),
+ headers, headerlen);
if(i > 0) {
contentlen = atoi(headers+i);
+ /* XXX What if content-length is malformed? */
if(bodylen < contentlen) {
log_fn(LOG_DEBUG,"body not all here yet.");
return 0; /* not all there yet */
@@ -246,15 +299,15 @@
}
/* all happy. copy into the appropriate places, and return 1 */
if(headers_out) {
- memcpy(headers_out,buf,headerlen);
+ memcpy(headers_out,buf->buf,headerlen);
headers_out[headerlen] = 0; /* null terminate it */
}
if(body_out) {
- memcpy(body_out,buf+headerlen,bodylen);
+ memcpy(body_out,buf->buf+headerlen,bodylen);
body_out[bodylen] = 0; /* null terminate it */
}
- *buf_datalen -= (headerlen+bodylen);
- memmove(buf, buf+headerlen+bodylen, *buf_datalen);
+ buf->datalen -= (headerlen+bodylen);
+ memmove(buf, buf->buf+headerlen+bodylen, buf->datalen);
return 1;
}
@@ -269,7 +322,7 @@
* If it's invalid or too big, return -1.
* Else it's not all there yet, change nothing and return 0.
*/
-int fetch_from_buf_socks(char *buf, int *buf_datalen,
+int fetch_from_buf_socks(buf_t *buf,
char *addr_out, int max_addrlen,
uint16_t *port_out) {
socks4_t socks4_info;
@@ -278,14 +331,14 @@
enum {socks4, socks4a } socks_prot = socks4a;
char *next, *startaddr;
- if(*buf_datalen < sizeof(socks4_t)) /* basic info available? */
+ if(buf->datalen < sizeof(socks4_t)) /* basic info available? */
return 0; /* not yet */
/* an inlined socks4_unpack() */
- socks4_info.version = *buf;
- socks4_info.command = *(buf+1);
- socks4_info.destport = ntohs(*(uint16_t*)(buf+2));
- socks4_info.destip = ntohl(*(uint32_t*)(buf+4));
+ socks4_info.version = (unsigned char) *(buf->buf);
+ socks4_info.command = (unsigned char) *(buf->buf+1);
+ socks4_info.destport = ntohs(*(uint16_t*)(buf->buf+2));
+ socks4_info.destip = ntohl(*(uint32_t*)(buf->buf+4));
if(socks4_info.version != 4) {
log_fn(LOG_NOTICE,"Unrecognized version %d.",socks4_info.version);
@@ -321,7 +374,7 @@
socks_prot = socks4;
}
- next = memchr(buf+SOCKS4_NETWORK_LEN, 0, *buf_datalen);
+ next = memchr(buf->buf+SOCKS4_NETWORK_LEN, 0, buf->datalen);
if(!next) {
log_fn(LOG_DEBUG,"Username not here yet.");
return 0;
@@ -329,7 +382,7 @@
startaddr = next+1;
if(socks_prot == socks4a) {
- next = memchr(startaddr, 0, buf+*buf_datalen-startaddr);
+ next = memchr(startaddr, 0, buf->buf+buf->datalen-startaddr);
if(!next) {
log_fn(LOG_DEBUG,"Destaddr not here yet.");
return 0;
@@ -342,32 +395,19 @@
log_fn(LOG_DEBUG,"Everything is here. Success.");
*port_out = port;
strcpy(addr_out, socks_prot == socks4 ? tmpbuf : startaddr);
- *buf_datalen -= (next-buf+1); /* next points to the final \0 on inbuf */
- memmove(buf, next+1, *buf_datalen);
+ buf->datalen -= (next-buf->buf+1); /* next points to the final \0 on inbuf */
+ memmove(buf->buf, next+1, buf->datalen);
// log_fn(LOG_DEBUG,"buf_datalen is now %d:'%s'",*buf_datalen,buf);
return 1;
}
-int find_on_inbuf(char *string, int string_len,
- char *buf, int buf_datalen) {
+int find_on_inbuf(char *string, int string_len, buf_t *buf) {
/* find first instance of needle 'string' on haystack 'buf'. return how
* many bytes from the beginning of buf to the end of string.
* If it's not there, return -1.
*/
- char *location;
- char *last_possible = buf + buf_datalen - string_len;
-
- assert(string && string_len > 0 && buf);
-
- if(buf_datalen < string_len)
- return -1;
-
- for(location = buf; location <= last_possible; location++)
- if((*location == *string) && !memcmp(location+1, string+1, string_len-1))
- return location-buf+string_len;
-
- return -1;
+ return find_str_in_str(string, string_len, buf->buf, buf->datalen);
}
/*
Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- circuit.c 24 Sep 2003 21:24:52 -0000 1.67
+++ circuit.c 25 Sep 2003 05:17:10 -0000 1.68
@@ -751,7 +751,7 @@
cell.aci = circ->n_aci;
cell.length = DH_ONIONSKIN_LEN;
- if(onion_skin_create(circ->n_conn->pkey, &(circ->cpath->handshake_state), cell.payload) < 0) {
+ if(onion_skin_create(circ->n_conn->onion_pkey, &(circ->cpath->handshake_state), cell.payload) < 0) {
log_fn(LOG_INFO,"onion_skin_create (first hop) failed.");
return -1;
}
@@ -791,7 +791,7 @@
cell.length = RELAY_HEADER_SIZE + 6 + DH_ONIONSKIN_LEN;
*(uint32_t*)(cell.payload+RELAY_HEADER_SIZE) = htonl(hop->addr);
*(uint16_t*)(cell.payload+RELAY_HEADER_SIZE+4) = htons(hop->port);
- if(onion_skin_create(router->pkey, &(hop->handshake_state), cell.payload+RELAY_HEADER_SIZE+6) < 0) {
+ if(onion_skin_create(router->onion_pkey, &(hop->handshake_state), cell.payload+RELAY_HEADER_SIZE+6) < 0) {
log_fn(LOG_INFO,"onion_skin_create failed.");
return -1;
}
Index: config.c
===================================================================
RCS file: /home/or/cvsroot/src/or/config.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- config.c 24 Sep 2003 21:24:52 -0000 1.43
+++ config.c 25 Sep 2003 05:17:10 -0000 1.44
@@ -189,10 +189,8 @@
/* string options */
config_compare(list, "LogLevel", CONFIG_TYPE_STRING, &options->LogLevel) ||
- config_compare(list, "PrivateKeyFile", CONFIG_TYPE_STRING, &options->PrivateKeyFile) ||
- config_compare(list, "SigningPrivateKeyFile", CONFIG_TYPE_STRING, &options->SigningPrivateKeyFile) ||
+ config_compare(list, "DataDirectory", CONFIG_TYPE_STRING, &options->DataDirectory) ||
config_compare(list, "RouterFile", CONFIG_TYPE_STRING, &options->RouterFile) ||
- config_compare(list, "CertFile", CONFIG_TYPE_STRING, &options->CertFile) ||
config_compare(list, "Nickname", CONFIG_TYPE_STRING, &options->Nickname) ||
/* int options */
@@ -238,6 +236,7 @@
memset(options,0,sizeof(or_options_t));
options->LogLevel = "debug";
options->loglevel = LOG_DEBUG;
+ options->DataDirectory = NULL;
options->CoinWeight = 0.8;
options->MaxConn = 900;
options->DirFetchPeriod = 600;
@@ -246,7 +245,6 @@
options->NewCircuitPeriod = 60; /* once a minute */
options->TotalBandwidth = 800000; /* at most 800kB/s total sustained incoming */
options->NumCpus = 1;
- options->CertFile = "default.cert";
/* learn config file name, get config lines, assign them */
i = 1;
@@ -316,18 +314,13 @@
result = -1;
}
- if(options->OnionRouter && options->PrivateKeyFile == NULL) {
- log(LOG_ERR,"PrivateKeyFile option required for OnionRouter, but not found.");
+ if(options->OnionRouter && options->DataDirectory == NULL) {
+ log(LOG_ERR,"DataDirectory option required for OnionRouter, but not found.");
result = -1;
}
if(options->OnionRouter && options->Nickname == NULL) {
log_fn(LOG_ERR,"Nickname required for OnionRouter, but not found.");
- result = -1;
- }
-
- if(options->DirPort > 0 && options->SigningPrivateKeyFile == NULL) {
- log(LOG_ERR,"SigningPrivateKeyFile option required for DirServer, but not found.");
result = -1;
}
Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- connection.c 24 Sep 2003 21:24:52 -0000 1.101
+++ connection.c 25 Sep 2003 05:17:10 -0000 1.102
@@ -80,8 +80,8 @@
memset(conn,0,sizeof(connection_t)); /* zero it out to start */
conn->type = type;
- if(buf_new(&conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen) < 0 ||
- buf_new(&conn->outbuf, &conn->outbuflen, &conn->outbuf_datalen) < 0)
+ if(!(conn->inbuf = buf_new()) ||
+ !(conn->outbuf = buf_new()))
return NULL;
conn->receiver_bucket = 50000; /* should be enough to do the handshake */
@@ -108,8 +108,12 @@
tor_tls_free(conn->tls);
}
- if (conn->pkey)
- crypto_free_pk_env(conn->pkey);
+ if (conn->onion_pkey)
+ crypto_free_pk_env(conn->onion_pkey);
+ if (conn->link_pkey)
+ crypto_free_pk_env(conn->link_pkey);
+ if (conn->identity_pkey)
+ crypto_free_pk_env(conn->identity_pkey);
if(conn->s > 0) {
log_fn(LOG_INFO,"closing fd %d.",conn->s);
@@ -287,14 +291,14 @@
log_fn(LOG_INFO,"Other side has a cert but it's bad. Closing.");
return -1;
}
- router = router_get_by_pk(pk);
+ router = router_get_by_link_pk(pk);
if (!router) {
log_fn(LOG_INFO,"Unrecognized public key from peer. Closing.");
crypto_free_pk_env(pk);
return -1;
}
- if(conn->pkey) { /* I initiated this connection. */
- if(crypto_pk_cmp_keys(conn->pkey, pk)) {
+ if(conn->link_pkey) { /* I initiated this connection. */
+ if(crypto_pk_cmp_keys(conn->link_pkey, pk)) {
log_fn(LOG_INFO,"We connected to '%s' but he gave us a different key. Closing.", router->nickname);
crypto_free_pk_env(pk);
return -1;
@@ -306,7 +310,7 @@
log_fn(LOG_INFO,"That router is already connected. Dropping.");
return -1;
}
- conn->pkey = pk;
+ conn->link_pkey = pk;
conn->bandwidth = router->bandwidth;
conn->addr = router->addr, conn->port = router->or_port;
if(conn->address)
@@ -326,13 +330,13 @@
log_fn(LOG_INFO,"Other side has a cert but it's bad. Closing.");
return -1;
}
- router = router_get_by_pk(pk);
+ router = router_get_by_link_pk(pk);
if (!router) {
log_fn(LOG_INFO,"Unrecognized public key from peer. Closing.");
crypto_free_pk_env(pk);
return -1;
}
- if(crypto_pk_cmp_keys(conn->pkey, pk)) {
+ if(crypto_pk_cmp_keys(conn->link_pkey, pk)) {
log_fn(LOG_INFO,"We connected to '%s' but he gave us a different key. Closing.", router->nickname);
crypto_free_pk_env(pk);
return -1;
@@ -494,8 +498,7 @@
return connection_tls_continue_handshake(conn);
/* else open, or closing */
- result = read_to_buf_tls(conn->tls, at_most, &conn->inbuf,
- &conn->inbuflen, &conn->inbuf_datalen);
+ result = read_to_buf_tls(conn->tls, at_most, conn->inbuf);
switch(result) {
case TOR_TLS_ERROR:
@@ -510,8 +513,9 @@
return 0;
}
} else {
- result = read_to_buf(conn->s, at_most, &conn->inbuf, &conn->inbuflen,
- &conn->inbuf_datalen, &conn->inbuf_reached_eof);
+ result = read_to_buf(conn->s, at_most, conn->inbuf,
+ &conn->inbuf_reached_eof);
+
// log(LOG_DEBUG,"connection_read_to_buf(): read_to_buf returned %d.",read_result);
if(result < 0)
@@ -534,11 +538,11 @@
}
int connection_fetch_from_buf(char *string, int len, connection_t *conn) {
- return fetch_from_buf(string, len, &conn->inbuf, &conn->inbuflen, &conn->inbuf_datalen);
+ return fetch_from_buf(string, len, conn->inbuf);
}
int connection_find_on_inbuf(char *string, int len, connection_t *conn) {
- return find_on_inbuf(string, len, conn->inbuf, conn->inbuf_datalen);
+ return find_on_inbuf(string, len, conn->inbuf);
}
int connection_wants_to_flush(connection_t *conn) {
@@ -550,8 +554,7 @@
}
int connection_flush_buf(connection_t *conn) {
- return flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
- &conn->outbuf_flushlen, &conn->outbuf_datalen);
+ return flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen);
}
/* return -1 if you want to break the conn, else return 0 */
@@ -573,8 +576,7 @@
}
/* else open, or closing */
- switch(flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen,
- &conn->outbuf_flushlen, &conn->outbuf_datalen)) {
+ switch(flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen)) {
case TOR_TLS_ERROR:
case TOR_TLS_CLOSE:
log_fn(LOG_DEBUG,"tls error. breaking.");
@@ -601,8 +603,7 @@
*/
}
} else {
- if(flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
- &conn->outbuf_flushlen, &conn->outbuf_datalen) < 0)
+ if(flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen) < 0)
return -1;
/* conns in CONNECTING state will fall through... */
}
@@ -631,7 +632,7 @@
conn->outbuf_flushlen += len;
}
- return write_to_buf(string, len, &conn->outbuf, &conn->outbuflen, &conn->outbuf_datalen);
+ return write_to_buf(string, len, conn->outbuf);
}
int connection_receiver_bucket_should_increase(connection_t *conn) {
@@ -741,29 +742,25 @@
/* buffers */
assert(conn->inbuf);
- assert(conn->inbuflen >= conn->inbuf_datalen);
- assert(conn->inbuflen >= 0);
- assert(conn->inbuf_datalen >= 0);
assert(conn->outbuf);
- assert(conn->outbuflen >= conn->outbuf_datalen);
- assert(conn->outbuflen >= 0);
- assert(conn->outbuf_datalen >= 0);
assert(!now || conn->timestamp_lastread <= now);
assert(!now || conn->timestamp_lastwritten <= now);
assert(conn->timestamp_created <= conn->timestamp_lastread);
assert(conn->timestamp_created <= conn->timestamp_lastwritten);
+ /* XXX Fix this; no longer so.*/
+#if 0
if(conn->type != CONN_TYPE_OR && conn->type != CONN_TYPE_DIR)
assert(!conn->pkey);
/* pkey is set if we're a dir client, or if we're an OR in state OPEN
* connected to another OR.
*/
+#endif
if (conn->type != CONN_TYPE_OR) {
assert(conn->bandwidth == -1);
assert(conn->receiver_bucket == -1);
- /* Addr, port, address XXX */
assert(!conn->tls);
} else {
assert(conn->bandwidth);
Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- connection_edge.c 21 Sep 2003 06:15:43 -0000 1.24
+++ connection_edge.c 25 Sep 2003 05:17:10 -0000 1.25
@@ -336,7 +336,7 @@
return 0;
}
- amount_to_process = conn->inbuf_datalen;
+ amount_to_process = buf_datalen(conn->inbuf);
if(!amount_to_process)
return 0;
@@ -352,7 +352,8 @@
connection_fetch_from_buf(cell.payload+RELAY_HEADER_SIZE, cell.length, conn);
- log_fn(LOG_DEBUG,"(%d) Packaging %d bytes (%d waiting).",conn->s,cell.length, conn->inbuf_datalen);
+ log_fn(LOG_DEBUG,"(%d) Packaging %d bytes (%d waiting).",conn->s,cell.length,
+ (int)buf_datalen(conn->inbuf));
cell.command = CELL_RELAY;
SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_DATA);
@@ -440,7 +441,7 @@
log_fn(LOG_DEBUG,"entered.");
- switch(fetch_from_buf_socks(conn->inbuf,&conn->inbuf_datalen,
+ switch(fetch_from_buf_socks(conn->inbuf,
destaddr, sizeof(destaddr), &destport)) {
case -1:
log_fn(LOG_DEBUG,"Fetching socks handshake failed. Closing.");
Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- connection_or.c 24 Sep 2003 21:24:52 -0000 1.52
+++ connection_or.c 25 Sep 2003 05:17:10 -0000 1.53
@@ -99,7 +99,8 @@
conn->addr = router->addr;
conn->port = router->or_port;
conn->bandwidth = router->bandwidth;
- conn->pkey = crypto_pk_dup_key(router->pkey);
+ conn->onion_pkey = crypto_pk_dup_key(router->onion_pkey);
+ conn->link_pkey = crypto_pk_dup_key(router->link_pkey);
conn->address = strdup(router->address);
if(connection_add(conn) < 0) { /* no space, forget it */
@@ -148,9 +149,9 @@
int connection_process_cell_from_inbuf(connection_t *conn) {
char buf[CELL_NETWORK_SIZE];
cell_t cell;
-
- log_fn(LOG_DEBUG,"%d: starting, inbuf_datalen %d.",conn->s,conn->inbuf_datalen);
- if(conn->inbuf_datalen < CELL_NETWORK_SIZE) /* entire response available? */
+
+ log_fn(LOG_DEBUG,"%d: starting, inbuf_datalen %d.",conn->s,buf_datalen(conn->inbuf));
+ if(buf_datalen(conn->inbuf) < CELL_NETWORK_SIZE) /* entire response available? */
return 0; /* not yet */
connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn);
Index: cpuworker.c
===================================================================
RCS file: /home/or/cvsroot/src/or/cpuworker.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cpuworker.c 16 Sep 2003 01:58:46 -0000 1.5
+++ cpuworker.c 25 Sep 2003 05:17:11 -0000 1.6
@@ -73,9 +73,9 @@
}
if(conn->state == CPUWORKER_STATE_BUSY_ONION) {
- if(conn->inbuf_datalen < LEN_ONION_RESPONSE) /* entire answer available? */
+ if(buf_datalen(conn->inbuf) < LEN_ONION_RESPONSE) /* entire answer available? */
return 0; /* not yet */
- assert(conn->inbuf_datalen == LEN_ONION_RESPONSE);
+ assert(buf_datalen(conn->inbuf) == LEN_ONION_RESPONSE);
connection_fetch_from_buf(buf,LEN_ONION_RESPONSE,conn);
@@ -147,7 +147,7 @@
}
if(question_type == CPUWORKER_TASK_ONION) {
- if(onion_skin_server_handshake(question, get_privatekey(),
+ if(onion_skin_server_handshake(question, get_onion_key(),
reply_to_proxy, keys, 32) < 0) {
/* failure */
log_fn(LOG_ERR,"onion_skin_server_handshake failed.");
Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/src/or/directory.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- directory.c 22 Sep 2003 06:22:00 -0000 1.30
+++ directory.c 25 Sep 2003 05:17:11 -0000 1.31
@@ -53,11 +53,11 @@
conn->address = strdup(router->address);
conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */
conn->bandwidth = -1;
- if (router->signing_pkey)
- conn->pkey = crypto_pk_dup_key(router->signing_pkey);
+ if (router->identity_pkey)
+ conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
else {
log_fn(LOG_ERR, "No signing key known for dirserver %s; signature won't be checked", conn->address);
- conn->pkey = NULL;
+ conn->identity_pkey = NULL;
}
if(connection_add(conn) < 0) { /* no space, forget it */
@@ -124,7 +124,7 @@
static void directory_rebuild(void) {
if(directory_dirty) {
if (dump_signed_directory_to_string(the_directory, MAX_DIR_SIZE,
- get_signing_privatekey())) {
+ get_identity_key())) {
log(LOG_ERR, "Error writing directory");
return;
}
@@ -144,7 +144,7 @@
switch(conn->state) {
case DIR_CONN_STATE_CLIENT_READING_FETCH:
/* kill it, but first process the_directory and learn about new routers. */
- switch(fetch_from_buf_http(conn->inbuf,&conn->inbuf_datalen,
+ switch(fetch_from_buf_http(conn->inbuf,
NULL, 0, the_directory, MAX_DIR_SIZE)) {
case -1: /* overflow */
log_fn(LOG_DEBUG,"'fetch' response too large. Failing.");
@@ -161,11 +161,11 @@
log_fn(LOG_DEBUG,"Empty directory. Ignoring.");
return -1;
}
- if(router_get_dir_from_string(the_directory, conn->pkey) < 0) {
+ if(router_get_dir_from_string(the_directory, conn->identity_pkey) < 0){
log_fn(LOG_DEBUG,"...but parsing failed. Ignoring.");
} else {
log_fn(LOG_DEBUG,"and got an %s directory; updated routers.",
- conn->pkey ? "authenticated" : "unauthenticated");
+ conn->identity_pkey ? "authenticated" : "unauthenticated");
}
if(options.OnionRouter) { /* connect to them all */
router_retry_connections();
@@ -196,7 +196,7 @@
assert(conn && conn->type == CONN_TYPE_DIR);
- switch(fetch_from_buf_http(conn->inbuf,&conn->inbuf_datalen,
+ switch(fetch_from_buf_http(conn->inbuf,
headers, sizeof(headers), body, sizeof(body))) {
case -1: /* overflow */
log_fn(LOG_DEBUG,"input too large. Failing.");
Index: dns.c
===================================================================
RCS file: /home/or/cvsroot/src/or/dns.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- dns.c 16 Sep 2003 01:58:46 -0000 1.25
+++ dns.c 25 Sep 2003 05:17:11 -0000 1.26
@@ -309,9 +309,9 @@
}
assert(conn->state == DNSWORKER_STATE_BUSY);
- if(conn->inbuf_datalen < 4) /* entire answer available? */
+ if(buf_datalen(conn->inbuf) < 4) /* entire answer available? */
return 0; /* not yet */
- assert(conn->inbuf_datalen == 4);
+ assert(buf_datalen(conn->inbuf) == 4);
connection_fetch_from_buf((char*)&answer,sizeof(answer),conn);
Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -d -r1.100 -r1.101
--- main.c 24 Sep 2003 21:24:52 -0000 1.100
+++ main.c 25 Sep 2003 05:17:11 -0000 1.101
@@ -7,6 +7,7 @@
/********* START PROTOTYPES **********/
static void dumpstats(void); /* dump stats to stdout */
+static int init_descriptor(void);
/********* START VARIABLES **********/
@@ -29,30 +30,42 @@
static int please_reap_children=0; /* whether we should waitpid for exited children*/
#endif /* signal stuff */
-/* private key */
-static crypto_pk_env_t *privatekey=NULL;
-static crypto_pk_env_t *signing_privatekey=NULL;
+/* private keys */
+static crypto_pk_env_t *onionkey=NULL;
+static crypto_pk_env_t *linkkey=NULL;
+static crypto_pk_env_t *identitykey=NULL;
routerinfo_t *my_routerinfo=NULL;
/********* END VARIABLES ************/
-void set_privatekey(crypto_pk_env_t *k) {
- privatekey = k;
+void set_onion_key(crypto_pk_env_t *k) {
+ onionkey = k;
}
-crypto_pk_env_t *get_privatekey(void) {
- assert(privatekey);
- return privatekey;
+crypto_pk_env_t *get_onion_key(void) {
+ assert(onionkey);
+ return onionkey;
}
-void set_signing_privatekey(crypto_pk_env_t *k) {
- signing_privatekey = k;
+void set_link_key(crypto_pk_env_t *k)
+{
+ linkkey = k;
}
-crypto_pk_env_t *get_signing_privatekey(void) {
- assert(signing_privatekey);
- return signing_privatekey;
+crypto_pk_env_t *get_link_key(void)
+{
+ assert(linkkey);
+ return linkkey;
+}
+
+void set_identity_key(crypto_pk_env_t *k) {
+ identitykey = k;
+}
+
+crypto_pk_env_t *get_identity_key(void) {
+ assert(identitykey);
+ return identitykey;
}
/****************************************************************************
@@ -69,7 +82,7 @@
log(LOG_INFO,"connection_add(): failing because nfds is too high.");
return -1;
}
-
+
conn->poll_index = nfds;
connection_set_poll_socket(conn);
connection_array[nfds] = conn;
@@ -146,7 +159,7 @@
assert(conn);
if(connection_state_is_open(conn) &&
!conn->marked_for_close &&
- !crypto_pk_cmp_keys(conn->pkey, router->pkey)) {
+ !crypto_pk_cmp_keys(conn->onion_pkey, router->onion_pkey)) {
log(LOG_INFO,"connection_twin_get_by_addr_port(): Found twin (%s).",conn->address);
return conn;
}
@@ -308,13 +321,11 @@
if(conn->s >= 0) { /* might be an incomplete edge connection */
/* FIXME there's got to be a better way to check for this -- and make other checks? */
if(connection_speaks_cells(conn) && conn->state != OR_CONN_STATE_CONNECTING)
- flush_buf_tls(conn->tls, &conn->outbuf, &conn->outbuflen,
- &conn->outbuf_flushlen, &conn->outbuf_datalen);
+ flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen);
else
- flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
- &conn->outbuf_flushlen, &conn->outbuf_datalen);
+ flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen);
if(connection_wants_to_flush(conn)) /* not done flushing */
- log_fn(LOG_WARNING,"Conn (socket %d) still wants to flush. Losing %d bytes!",conn->s, conn->inbuf_datalen);
+ log_fn(LOG_WARNING,"Conn (socket %d) still wants to flush. Losing %d bytes!",conn->s, (int)buf_datalen(conn->inbuf));
}
connection_remove(conn);
connection_free(conn);
@@ -420,68 +431,218 @@
return (1000 - (now.tv_usec / 1000)); /* how many milliseconds til the next second? */
}
-static int do_main_loop(void) {
- int i;
- int timeout;
- int poll_result;
- crypto_pk_env_t *prkey;
+#define FN_ERROR -1
+#define FN_NOENT 0
+#define FN_FILE 1
+#define FN_DIR 2
+static int fn_exists(const char *fname)
+{
+ struct stat st;
+ if (stat(fname, &st)) {
+ if (errno == ENOENT) {
+ return FN_NOENT;
+ }
+ return FN_ERROR;
+ }
+ if (st.st_mode & S_IFDIR)
+ return FN_DIR;
+ else
+ return FN_FILE;
+}
- /* load the routers file */
- if(router_get_list_from_file(options.RouterFile) < 0) {
- log(LOG_ERR,"Error loading router list.");
- return -1;
+static crypto_pk_env_t *init_key_from_file(const char *fname)
+{
+ crypto_pk_env_t *prkey = NULL;
+ int fd = -1;
+ FILE *file = NULL;
+
+ if (!(prkey = crypto_new_pk_env(CRYPTO_PK_RSA))) {
+ log(LOG_ERR, "Error creating crypto environment.");
+ goto error;
}
- /* load the private key, if we're supposed to have one */
- if(options.OnionRouter) {
- prkey = crypto_new_pk_env(CRYPTO_PK_RSA);
- if (!prkey) {
- log(LOG_ERR,"Error creating a crypto environment.");
- return -1;
+ switch(fn_exists(fname)) {
+ case FN_DIR:
+ case FN_ERROR:
+ log(LOG_ERR, "Can't read key from %s", fname);
+ goto error;
+ case FN_NOENT:
+ log(LOG_INFO, "No key found in %s; generating fresh key.", fname);
+ if (crypto_pk_generate_key(prkey)) {
+ log(LOG_ERR, "Error generating key: %s", crypto_perror());
+ goto error;
}
- if (crypto_pk_read_private_key_from_filename(prkey, options.PrivateKeyFile)) {
- log(LOG_ERR,"Error loading private key.");
- return -1;
+ if (crypto_pk_check_key(prkey) <= 0) {
+ log(LOG_ERR, "Generated key seems invalid");
+ goto error;
}
- set_privatekey(prkey);
- cpu_init(); /* launch cpuworkers. Need to do this *after* we've read the private key. */
- }
-
- /* load the directory private key, if we're supposed to have one */
- if(options.DirPort) {
- prkey = crypto_new_pk_env(CRYPTO_PK_RSA);
- if (!prkey) {
- log(LOG_ERR,"Error creating a crypto environment.");
- return -1;
+ log(LOG_INFO, "Generated key seems valid");
+ fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0400);
+ if (fd == -1) {
+ log(LOG_ERR, "Can't open %s for writing", fname);
+ goto error;
}
- if (crypto_pk_read_private_key_from_filename(prkey, options.SigningPrivateKeyFile)) {
- log(LOG_ERR,"Error loading private key.");
- return -1;
+ file = fdopen(fd, "w");
+ if (!file) {
+ log(LOG_ERR, "Can't fdopen %s for writing", fname);
+ goto error;
}
- set_signing_privatekey(prkey);
+ if (crypto_pk_write_private_key_to_file(prkey, file) < 0) {
+ log(LOG_ERR, "Can't write private key to %s", fname);
+ goto error;
+ }
+ fclose(file);
+ /* XXX fingerprint */
+ return prkey;
+ case FN_FILE:
+ if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
+ log(LOG_ERR, "Error loading private key.");
+ goto error;
+ }
+ return prkey;
+ default:
+ assert(0);
}
- if(options.OnionRouter) {
- struct stat statbuf;
- if(stat(options.CertFile, &statbuf) < 0) {
- log_fn(LOG_INFO,"CertFile %s is missing. Generating.", options.CertFile);
- if(tor_tls_write_certificate(options.CertFile,
- get_privatekey(),
- options.Nickname) < 0) {
- log_fn(LOG_ERR,"Couldn't write CertFile %s. Dying.", options.CertFile);
- return -1;
- }
- }
+ error:
+ if (prkey)
+ crypto_free_pk_env(prkey);
+ if (fd >= 0 && !file)
+ close(fd);
+ if (file)
+ fclose(file);
+ return NULL;
+}
- if(tor_tls_context_new(options.CertFile, get_privatekey(), 1) < 0) {
- log_fn(LOG_ERR,"Error creating tls context.");
+static int init_keys(void)
+{
+ char keydir[512];
+ char fingerprint[FINGERPRINT_LEN+1];
+ char *cp;
+ crypto_pk_env_t *prkey;
+ FILE *file;
+
+ /* OP's don't need keys. Just initialize the TLS context.*/
+ if (!options.OnionRouter && !options.DirPort) {
+ if (tor_tls_context_new(NULL, 0, NULL)<0) {
+ log_fn(LOG_ERR, "Error creating TLS context for OP.");
return -1;
}
- } else { /* just a proxy, the context is easy */
- if(tor_tls_context_new(NULL, NULL, 0) < 0) {
- log_fn(LOG_ERR,"Error creating tls context.");
+ return 0;
+ }
+ assert(options.DataDirectory);
+ if (strlen(options.DataDirectory) > (512-128)) {
+ log_fn(LOG_ERR, "DataDirectory is too long.");
+ return -1;
+ }
+ strcpy(keydir, options.DataDirectory);
+ switch (fn_exists(keydir)) {
+ case FN_NOENT:
+ log_fn(LOG_ERR, "DataDirectory does not exist");
+ return -1;
+ case FN_ERROR:
+ log_fn(LOG_ERR, "DataDirectory can't be read");
+ return -1;
+ case FN_FILE:
+ log_fn(LOG_ERR, "DataDirectory is not a directory.");
+ return -1;
+ }
+ strcat(keydir, "/keys");
+ switch (fn_exists(keydir)) {
+ case FN_NOENT:
+ if (mkdir(keydir, 0700)) {
+ log_fn(LOG_ERR, "Error making key directory.");
return -1;
}
+ break;
+ case FN_ERROR:
+ log_fn(LOG_ERR, "Error reading key directory.");
+ return -1;
+ case FN_FILE:
+ log_fn(LOG_ERR, "Key directory is not a directory.");
+ return -1;
+ case FN_DIR:
+ chmod(keydir, 0700);
+ break;
+ }
+ cp = keydir + strlen(keydir); /* End of string. */
+ assert(!*cp);
+
+ /* 1. Read identity key. Make it if none is found. */
+ strcat(keydir, "/identity.key");
+ prkey = init_key_from_file(keydir);
+ if (!prkey) return -1;
+ set_identity_key(prkey);
+ /* 2. Read onion key. Make it if none is found. */
+ *cp = '\0';
+ strcat(keydir, "/onion.key");
+ prkey = init_key_from_file(keydir);
+ if (!prkey) return -1;
+ set_onion_key(prkey);
+
+ /* 3. Initialize link key and TLS context. */
+ *cp = '\0';
+ strcat(keydir, "/link.key");
+ prkey = init_key_from_file(keydir);
+ if (!prkey) return -1;
+ set_link_key(prkey);
+ if (tor_tls_context_new(prkey, 1, options.Nickname) < 0) {
+ log_fn(LOG_ERR, "Error initializing TLS context");
+ return -1;
+ }
+ /* 4. Dump router descriptor to 'router.desc' */
+ /* Must be called after keys are initialized. */
+ if (init_descriptor()<0) {
+ log_fn(LOG_ERR, "Error initializing descriptor.");
+ return -1;
+ }
+ strcpy(keydir, options.DataDirectory);
+ strcat(keydir, "/router.desc");
+ file = fopen(keydir, "w");
+ if (!file) {
+ log_fn(LOG_ERR, "Error opening %s for writing", keydir);
+ return -1;
+ }
+ fputs(router_get_my_descriptor(), file);
+ fclose(file);
+ /* 5. Dump fingerprint to 'fingerprint' */
+ strcpy(keydir, options.DataDirectory);
+ strcat(keydir, "/fingerprint");
+ file = fopen(keydir, "w");
+ if (!file) {
+ log_fn(LOG_ERR, "Error opening %s for writing", keydir);
+ return -1;
+ }
+ if (crypto_pk_get_fingerprint(get_identity_key(), fingerprint)<0) {
+ log_fn(LOG_ERR, "Error computing fingerprint");
+ return -1;
+ }
+ fprintf(file, "%s %s\n", options.Nickname, fingerprint);
+ fclose(file);
+
+ return 0;
+}
+
+static int do_main_loop(void) {
+ int i;
+ int timeout;
+ int poll_result;
+
+ /* load the routers file */
+ if(router_get_list_from_file(options.RouterFile) < 0) {
+ log_fn(LOG_ERR,"Error loading router list.");
+ return -1;
+ }
+
+ /* load the private keys, if we're supposed to have them, and set up the
+ * TLS context. */
+ if (init_keys() < 0) {
+ log_fn(LOG_ERR,"Error initializing keys; exiting");
+ return -1;
+ }
+
+ if(options.OnionRouter) {
+ cpu_init(); /* launch cpuworkers. Need to do this *after* we've read the private key. */
}
/* start up the necessary connections based on which ports are
@@ -590,9 +751,10 @@
conn->state, conn_state_to_string[conn->type][conn->state], now.tv_sec - conn->timestamp_created);
if(!connection_is_listener(conn)) {
printf("Conn %d is to '%s:%d'.\n",i,conn->address, conn->port);
- printf("Conn %d: %d bytes waiting on inbuf (last read %ld secs ago)\n",i,conn->inbuf_datalen,
- now.tv_sec - conn->timestamp_lastread);
- printf("Conn %d: %d bytes waiting on outbuf (last written %ld secs ago)\n",i,conn->outbuf_datalen,
+ printf("Conn %d: %d bytes waiting on inbuf (last read %ld secs ago)\n",i,
+ (int)buf_datalen(conn->inbuf),
+ now.tv_sec - conn->timestamp_lastread);
+ printf("Conn %d: %d bytes waiting on outbuf (last written %ld secs ago)\n",i,(int)buf_datalen(conn->outbuf),
now.tv_sec - conn->timestamp_lastwritten);
}
circuit_dump_by_conn(conn); /* dump info about all the circuits using this conn */
@@ -601,42 +763,50 @@
}
-int dump_router_to_string(char *s, int maxlen, routerinfo_t *router) {
- char *pkey;
- char *signing_pkey, *signing_pkey_tag;
- int pkeylen, signing_pkeylen;
+int dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
+ crypto_pk_env_t *ident_key) {
+ char *onion_pkey;
+ char *link_pkey;
+ char *identity_pkey;
+ char digest[20];
+ char signature[128];
+ int onion_pkeylen, link_pkeylen, identity_pkeylen;
int written;
int result=0;
struct exit_policy_t *tmpe;
- if(crypto_pk_write_public_key_to_string(router->pkey,&pkey,&pkeylen)<0) {
- log(LOG_ERR,"dump_router_to_string(): write pkey to string failed!");
- return 0;
+ if(crypto_pk_write_public_key_to_string(router->onion_pkey,
+ &onion_pkey,&onion_pkeylen)<0) {
+ log_fn(LOG_ERR,"write onion_pkey to string failed!");
+ return -1;
}
- 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";
+ if(crypto_pk_write_public_key_to_string(router->identity_pkey,
+ &identity_pkey,&identity_pkeylen)<0) {
+ log_fn(LOG_ERR,"write identity_pkey to string failed!");
+ return -1;
+ }
+
+ if(crypto_pk_write_public_key_to_string(router->link_pkey,
+ &link_pkey,&link_pkeylen)<0) {
+ log_fn(LOG_ERR,"write link_pkey to string failed!");
+ return -1;
}
- result = snprintf(s, maxlen, "router %s %d %d %d %d\n%s%s%s",
+ result = snprintf(s, maxlen,
+ "router %s %d %d %d %d\nonion-key\n%s"
+ "link-key\n%s"
+ "signing-key\n%s",
router->address,
router->or_port,
router->ap_port,
router->dir_port,
router->bandwidth,
- pkey,
- signing_pkey_tag, signing_pkey);
+ onion_pkey, link_pkey, identity_pkey);
- free(pkey);
- if (*signing_pkey)
- free(signing_pkey);
+ free(onion_pkey);
+ free(link_pkey);
+ free(identity_pkey);
if(result < 0 || result > maxlen) {
/* apparently different glibcs do different things on snprintf error.. so check both */
@@ -654,19 +824,34 @@
}
written += result;
}
+ if (written > maxlen-256) /* Not enough room for signature. */
+ return -1;
- if(written > maxlen-2) {
- return -1; /* not enough space for \n\0 */
- }
- /* XXX count fenceposts here. They're probably wrong. In general,
- * we need a better way to handle overruns in building the directory
- * string, and a better way to handle directory string size in general. */
+ strcat(s+written, "router-signature\n");
+ written += strlen(s+written);
+ s[written] = '\0';
+ if (router_get_router_hash(s, digest) < 0)
+ return -1;
+ if (crypto_pk_private_sign(ident_key, digest, 20, signature) < 0) {
+ log_fn(LOG_ERR, "Error signing digest");
+ return -1;
+ }
+ strcat(s+written, "-----BEGIN SIGNATURE-----\n");
+ written += strlen(s+written);
+ if (base64_encode(s+written, maxlen-written, signature, 128) < 0) {
+ log_fn(LOG_ERR, "Couldn't base64-encode signature");
+ }
+ written += strlen(s+written);
+ strcat(s+written, "-----END SIGNATURE-----\n");
+ written += strlen(s+written);
+
+ if (written > maxlen-2)
+ return -1;
/* include a last '\n' */
s[written] = '\n';
s[written+1] = 0;
return written+1;
-
}
static int
@@ -738,7 +923,10 @@
cp = s+i;
for (i = 0; i < dir->n_routers; ++i) {
router = dir->routers[i];
- written = dump_router_to_string(cp, eos-cp, router);
+ /* XXX This is wrong; we shouldn't sign routers, but rather propagate
+ * XXX the original router blocks, unaltered.
+ */
+ written = dump_router_to_string(cp, eos-cp, router, private_key);
if(written < 0) {
log(LOG_ERR,"dump_signed_directory_to_string(): tried to exceed string length.");
@@ -789,8 +977,35 @@
return 0;
}
-char *router_get_my_descriptor(void) {
- return "this is bob's descriptor";
+static char descriptor[8192];
+/* XXX should this replace my_routerinfo? */
+static routerinfo_t *desc_routerinfo;
+const char *router_get_my_descriptor(void) {
+ return descriptor;
+}
+
+static int init_descriptor(void) {
+ routerinfo_t *ri;
+ ri = tor_malloc(sizeof(routerinfo_t));
+ ri->address = strdup("XXXXXXX"); /*XXX*/
+ ri->nickname = strdup(options.Nickname);
+ /* No need to set addr. ???? */
+ ri->or_port = options.ORPort;
+ ri->ap_port = options.APPort;
+ ri->dir_port = options.DirPort;
+ ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
+ ri->link_pkey = crypto_pk_dup_key(get_link_key());
+ ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
+ ri->bandwidth = options.TotalBandwidth;
+ ri->exit_policy = NULL; /* XXX implement this. */
+ if (desc_routerinfo)
+ routerinfo_free(desc_routerinfo);
+ desc_routerinfo = ri;
+ if (dump_router_to_string(descriptor, 8192, ri, get_identity_key())<0) {
+ log_fn(LOG_ERR, "Couldn't dump router to string.");
+ return -1;
+ }
+ return 0;
}
void daemonize(void) {
@@ -840,7 +1055,7 @@
crypto_seed_rng();
retval = do_main_loop();
crypto_global_cleanup();
-
+
return retval;
}
Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- onion.c 16 Sep 2003 20:57:08 -0000 1.65
+++ onion.c 25 Sep 2003 05:17:11 -0000 1.66
@@ -231,7 +231,7 @@
choice = choice % rarray_len;
log(LOG_DEBUG,"new_route(): Contemplating router %u.",choice);
if(choice == oldchoice ||
- (oldchoice < rarray_len && !crypto_pk_cmp_keys(rarray[choice]->pkey, rarray[oldchoice]->pkey)) ||
+ (oldchoice < rarray_len && !crypto_pk_cmp_keys(rarray[choice]->onion_pkey, rarray[oldchoice]->onion_pkey)) ||
(options.OnionRouter && !connection_twin_get_by_addr_port(rarray[choice]->addr, rarray[choice]->or_port))) {
/* Same router as last choice, or router twin,
* or no routers with that key are connected to us.
@@ -263,7 +263,7 @@
}
}
for(j=0;j<i;j++) {
- if(!crypto_pk_cmp_keys(rarray[i]->pkey, rarray[j]->pkey)) {
+ if(!crypto_pk_cmp_keys(rarray[i]->onion_pkey, rarray[j]->onion_pkey)) {
/* these guys are twins. so we've already counted him. */
log(LOG_DEBUG,"Nope, %d is a twin of %d.",i,j);
goto next_i_loop;
@@ -311,8 +311,8 @@
log(LOG_DEBUG,"onion_generate_cpath(): %u : %s:%u, %u/%u",routelen-i,
inet_ntoa(netaddr),
(rarray[route[i]])->or_port,
- (int) (rarray[route[i]])->pkey,
- crypto_pk_keysize((rarray[route[i]])->pkey));
+ (int) (rarray[route[i]])->onion_pkey,
+ crypto_pk_keysize((rarray[route[i]])->onion_pkey));
}
/* create the cpath layer by layer, starting at the last hop */
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.136
retrieving revision 1.137
diff -u -d -r1.136 -r1.137
--- or.h 24 Sep 2003 21:24:52 -0000 1.136
+++ or.h 25 Sep 2003 05:17:11 -0000 1.137
@@ -245,6 +245,8 @@
#define ZERO_STREAM "\0\0\0\0\0\0\0\0"
+typedef struct buf_t buf_t;
+
struct connection_t {
uint8_t type;
@@ -261,16 +263,12 @@
* iteration of the main loop?
*/
- char *inbuf;
- int inbuflen; /* how many bytes are alloc'ed for inbuf? */
- int inbuf_datalen; /* how many bytes of data are on inbuf? */
+ buf_t *inbuf;
int inbuf_reached_eof; /* did read() return 0 on this conn? */
long timestamp_lastread; /* when was the last time poll() said we could read? */
- char *outbuf;
- int outbuflen; /* how many bytes are allocated for the outbuf? */
+ buf_t *outbuf;
int outbuf_flushlen; /* how much data should we try to flush from the outbuf? */
- int outbuf_datalen; /* how much data is there total on the outbuf? */
long timestamp_lastwritten; /* when was the last time poll() said we could write? */
long timestamp_created; /* when was this connection_t created? */
@@ -287,7 +285,9 @@
char *address; /* FQDN (or IP) of the guy on the other end.
* strdup into this, because free_connection frees it
*/
- crypto_pk_env_t *pkey; /* public RSA key for the other side */
+ crypto_pk_env_t *onion_pkey; /* public RSA key for the other side's onions */
+ crypto_pk_env_t *link_pkey; /* public RSA key for the other side's TLS */
+ crypto_pk_env_t *identity_pkey; /* public RSA key for the other side's signing */
/* Used only by OR connections: */
tor_tls *tls;
@@ -331,8 +331,9 @@
uint16_t ap_port;
uint16_t dir_port;
- crypto_pk_env_t *pkey; /* public RSA key */
- crypto_pk_env_t *signing_pkey; /* May be null */
+ crypto_pk_env_t *onion_pkey; /* public RSA key for onions */
+ crypto_pk_env_t *link_pkey; /* public RSA key for TLS */
+ crypto_pk_env_t *identity_pkey; /* public RSA key for signing */
/* link info */
uint32_t bandwidth;
@@ -405,10 +406,8 @@
typedef struct {
char *LogLevel;
+ char *DataDirectory;
char *RouterFile;
- char *SigningPrivateKeyFile;
- char *PrivateKeyFile;
- char *CertFile;
char *Nickname;
double CoinWeight;
int Daemon;
@@ -435,24 +434,29 @@
/********************************* buffers.c ***************************/
-int buf_new(char **buf, int *buflen, int *buf_datalen);
-void buf_free(char *buf);
+buf_t *buf_new();
+buf_t *buf_new_with_capacity(size_t size);
+void buf_free(buf_t *buf);
-int read_to_buf(int s, int at_most, char **buf, int *buflen, int *buf_datalen, int *reached_eof);
-int read_to_buf_tls(tor_tls *tls, int at_most, char **buf, int *buflen, int *buf_datalen);
+size_t buf_datalen(const buf_t *buf);
+size_t buf_capacity(const buf_t *buf);
+const char *_buf_peek_raw_buffer(const buf_t *buf);
-int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datalen);
-int flush_buf_tls(tor_tls *tls, char **buf, int *buflen, int *buf_flushlen, int *buf_datalen);
+int read_to_buf(int s, int at_most, buf_t *buf, int *reached_eof);
+int read_to_buf_tls(tor_tls *tls, int at_most, buf_t *buf);
-int write_to_buf(char *string, int string_len, char **buf, int *buflen, int *buf_datalen);
-int fetch_from_buf(char *string, int string_len, char **buf, int *buflen, int *buf_datalen);
-int fetch_from_buf_http(char *buf, int *buf_datalen,
+int flush_buf(int s, buf_t *buf, int *buf_flushlen);
+int flush_buf_tls(tor_tls *tls, buf_t *buf, int *buf_flushlen);
+
+int write_to_buf(char *string, int string_len, buf_t *buf);
+int fetch_from_buf(char *string, int string_len, buf_t *buf);
+int fetch_from_buf_http(buf_t *buf,
char *headers_out, int max_headerlen,
char *body_out, int max_bodylen);
-int fetch_from_buf_socks(char *buf, int *buf_datalen,
+int fetch_from_buf_socks(buf_t *buf,
char *addr_out, int max_addrlen,
uint16_t *port_out);
-int find_on_inbuf(char *string, int string_len, char *buf, int buf_datalen);
+int find_on_inbuf(char *string, int string_len, buf_t *buf);
/********************************* circuit.c ***************************/
@@ -589,10 +593,10 @@
/********************************* main.c ***************************/
-void set_privatekey(crypto_pk_env_t *k);
-crypto_pk_env_t *get_privatekey(void);
-void set_signing_privatekey(crypto_pk_env_t *k);
-crypto_pk_env_t *get_signing_privatekey(void);
+void set_onion_key(crypto_pk_env_t *k);
+crypto_pk_env_t *get_onion_key(void);
+void set_identity_key(crypto_pk_env_t *k);
+crypto_pk_env_t *get_identity_key(void);
int connection_add(connection_t *conn);
int connection_remove(connection_t *conn);
void connection_set_poll_socket(connection_t *conn);
@@ -617,7 +621,7 @@
int dump_signed_directory_to_string_impl(char *s, int maxlen,
directory_t *dir,
crypto_pk_env_t *private_key);
-char *router_get_my_descriptor(void);
+const char *router_get_my_descriptor(void);
int main(int argc, char *argv[]);
@@ -655,16 +659,20 @@
void router_retry_connections(void);
routerinfo_t *router_pick_directory_server(void);
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
-routerinfo_t *router_get_by_pk(crypto_pk_env_t *pk);
+routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk);
+#if 0
+routerinfo_t *router_get_by_identity_pk(crypto_pk_env_t *pk);
+#endif
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_get_router_hash(char *s, char *digest);
/* Reads a list of known routers, unsigned. */
int router_get_list_from_string(char *s);
/* Exported for debugging */
-int router_get_list_from_string_impl(char *s, directory_t **dest);
+int router_get_list_from_string_impl(char **s, directory_t **dest);
/* Reads a signed directory. */
int router_get_dir_from_string(char *s, crypto_pk_env_t *pkey);
/* Exported or debugging */
Index: routers.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routers.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- routers.c 18 Sep 2003 08:11:31 -0000 1.49
+++ routers.c 25 Sep 2003 05:17:11 -0000 1.50
@@ -28,10 +28,6 @@
static char *eat_whitespace_no_nl(char *s);
static char *find_whitespace(char *s);
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);
static int
@@ -119,7 +115,7 @@
return NULL;
}
-routerinfo_t *router_get_by_pk(crypto_pk_env_t *pk)
+routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk)
{
int i;
routerinfo_t *router;
@@ -128,14 +124,32 @@
for(i=0;i<directory->n_routers;i++) {
router = directory->routers[i];
- /* XXX Should this really be a separate link key? */
- if (0 == crypto_pk_cmp_keys(router->pkey, pk))
+ if (0 == crypto_pk_cmp_keys(router->link_pkey, pk))
return router;
}
return NULL;
}
+
+#if 0
+routerinfo_t *router_get_by_identity_pk(crypto_pk_env_t *pk)
+{
+ int i;
+ routerinfo_t *router;
+
+ assert(directory);
+
+ for(i=0;i<directory->n_routers;i++) {
+ router = directory->routers[i];
+ /* XXX Should this really be a separate link key? */
+ if (0 == crypto_pk_cmp_keys(router->identity_pkey, pk))
+ return router;
+ }
+ return NULL;
+}
+#endif
+
void router_get_directory(directory_t **pdirectory) {
*pdirectory = directory;
@@ -174,10 +188,12 @@
if (router->address)
free(router->address);
- if (router->pkey)
- crypto_free_pk_env(router->pkey);
- if (router->signing_pkey)
- crypto_free_pk_env(router->signing_pkey);
+ if (router->onion_pkey)
+ crypto_free_pk_env(router->onion_pkey);
+ if (router->link_pkey)
+ crypto_free_pk_env(router->link_pkey);
+ if (router->identity_pkey)
+ crypto_free_pk_env(router->identity_pkey);
e = router->exit_policy;
while (e) {
etmp = e->next;
@@ -195,7 +211,8 @@
int i;
for (i = 0; i < directory->n_routers; ++i)
routerinfo_free(directory->routers[i]);
- free(directory->routers);
+ if (directory->routers)
+ free(directory->routers);
if(directory->software_versions)
free(directory->software_versions);
free(directory);
@@ -282,6 +299,9 @@
K_ROUTER,
K_SIGNED_DIRECTORY,
K_SIGNING_KEY,
+ K_ONION_KEY,
+ K_LINK_KEY,
+ K_ROUTER_SIGNATURE,
_SIGNATURE,
_PUBLIC_KEY,
_ERR,
@@ -298,6 +318,9 @@
{ "recommended-software", K_RECOMMENDED_SOFTWARE },
{ "signed-directory", K_SIGNED_DIRECTORY },
{ "signing-key", K_SIGNING_KEY },
+ { "onion-key", K_ONION_KEY },
+ { "link-key", K_LINK_KEY },
+ { "router-signature", K_ROUTER_SIGNATURE },
{ NULL, -1 }
};
@@ -450,6 +473,9 @@
case K_ROUTER: printf("Router"); break;
case K_SIGNED_DIRECTORY: printf("Signed-Directory"); break;
case K_SIGNING_KEY: printf("Signing-Key"); break;
+ case K_ONION_KEY: printf("Onion-key"); break;
+ case K_LINK_KEY: printf("Link-key"); break;
+ case K_ROUTER_SIGNATURE: printf("Router-signature"); break;
default:
printf("?????? %d\n", tok->tp); return;
}
@@ -459,7 +485,6 @@
printf("\n");
return;
}
-
static int
router_get_next_token(char **s, directory_token_t *tok) {
int i;
@@ -508,7 +533,7 @@
int router_get_list_from_string(char *s)
{
- if (router_get_list_from_string_impl(s, &directory)) {
+ if (router_get_list_from_string_impl(&s, &directory)) {
log(LOG_ERR, "Error parsing router file");
return -1;
}
@@ -519,43 +544,46 @@
return 0;
}
-int router_get_list_from_string_impl(char *s, directory_t **dest) {
- directory_token_t tok;
- if (router_get_next_token(&s, &tok)) {
- log(LOG_ERR, "Error reading routers: %s", tok.val.error);
- return -1;
- }
- return router_get_list_from_string_tok(&s, dest, &tok);
-}
-
-static int router_get_dir_hash(char *s, char *digest)
+static int router_get_hash_impl(char *s, char *digest, const char *start_str,
+ const char *end_str)
{
char *start, *end;
- start = strstr(s, "signed-directory");
+ start = strstr(s, start_str);
if (!start) {
- log(LOG_ERR,"router_get_dir_hash(): couldn't find \"signed-directory\"");
+ log_fn(LOG_ERR,"couldn't find \"%s\"",start_str);
return -1;
}
- end = strstr(start, "directory-signature");
+ end = strstr(start+strlen(start_str), end_str);
if (!end) {
- log(LOG_ERR,"router_get_dir_hash(): couldn't find \"directory-signature\"");
+ log_fn(LOG_ERR,"couldn't find \"%s\"",end_str);
return -1;
}
end = strchr(end, '\n');
if (!end) {
- log(LOG_ERR,"router_get_dir_hash(): couldn't find EOL");
+ log_fn(LOG_ERR,"couldn't find EOL");
return -1;
}
++end;
if (crypto_SHA_digest(start, end-start, digest)) {
- log(LOG_ERR,"router_get_dir_hash(): couldn't compute digest");
+ log_fn(LOG_ERR,"couldn't compute digest");
return -1;
}
return 0;
}
+static int router_get_dir_hash(char *s, char *digest)
+{
+ return router_get_hash_impl(s,digest,
+ "signed-directory","directory-signature");
+}
+int router_get_router_hash(char *s, char *digest)
+{
+ return router_get_hash_impl(s,digest,
+ "router ","router-signature");
+}
+
/* return 0 if myversion is in start. Else return -1. */
int compare_recommended_versions(char *myversion, char *start) {
int len_myversion = strlen(myversion);
@@ -621,12 +649,11 @@
log(LOG_ERR, "Error reading directory: expected %s", name); \
return -1; \
} } while(0)
-
+
if (router_get_dir_hash(s, digest)) {
log(LOG_ERR, "Unable to compute digest of directory");
- return -1;
+ goto err;
}
-
NEXT_TOK();
TOK_IS(K_SIGNED_DIRECTORY, "signed-directory");
@@ -634,17 +661,17 @@
TOK_IS(K_RECOMMENDED_SOFTWARE, "recommended-software");
if (tok.val.cmd.n_args != 1) {
log(LOG_ERR, "Invalid recommded-software line");
- return -1;
+ goto err;
}
versions = strdup(tok.val.cmd.args[0]);
- NEXT_TOK();
- if (router_get_list_from_string_tok(&s, &new_dir, &tok)) {
+ if (router_get_list_from_string_impl(&s, &new_dir)) {
log(LOG_ERR, "Error reading routers from directory");
- return -1;
+ goto err;
}
new_dir->software_versions = versions;
-
+
+ NEXT_TOK();
TOK_IS(K_DIRECTORY_SIGNATURE, "directory-signature");
NEXT_TOK();
TOK_IS(_SIGNATURE, "signature");
@@ -653,12 +680,12 @@
!= 20) {
log(LOG_ERR, "Error reading directory: invalid signature.");
free(tok.val.signature);
- return -1;
+ goto err;
}
if (memcmp(digest, signed_digest, 20)) {
log(LOG_ERR, "Error reading directory: signature does not match.");
free(tok.val.signature);
- return -1;
+ goto err;
}
}
free(tok.val.signature);
@@ -671,12 +698,16 @@
*dest = new_dir;
return 0;
+
+ err:
+ if (new_dir)
+ directory_free(new_dir);
+ return -1;
#undef NEXT_TOK
#undef TOK_IS
}
-static int router_get_list_from_string_tok(char **s, directory_t **dest,
- directory_token_t *tok)
+int router_get_list_from_string_impl(char **s, directory_t **dest)
{
routerinfo_t *router;
routerinfo_t **rarray;
@@ -686,8 +717,11 @@
rarray = (routerinfo_t **)tor_malloc((sizeof(routerinfo_t *))*MAX_ROUTERS_IN_DIR);
- while (tok->tp == K_ROUTER) {
- router = router_get_entry_from_string_tok(s, tok);
+ while (1) {
+ *s = eat_whitespace(*s);
+ if (strncmp(*s, "router ", 7)!=0)
+ break;
+ router = router_get_entry_from_string(s);
if (!router) {
log(LOG_ERR, "Error reading router");
return -1;
@@ -755,34 +789,32 @@
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) {
- router_release_token(&tok);
- 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.
*/
-static routerinfo_t *router_get_entry_from_string_tok(char**s, directory_token_t *tok) {
+routerinfo_t *router_get_entry_from_string(char**s) {
routerinfo_t *router = NULL;
+#if 0
+ char signed_digest[128];
+#endif
+ char digest[128];
+ directory_token_t _tok;
+ directory_token_t *tok = &_tok;
-#define NEXT_TOKEN() \
- do { if (router_get_next_token(s, tok)) { \
- log(LOG_ERR, "Error reading directory: %s", tok->val.error); \
- goto err; \
+#define NEXT_TOKEN() \
+ do { if (router_get_next_token(s, tok)) { \
+ log(LOG_ERR, "Error reading directory: %s", tok->val.error); \
+ goto err; \
} } while(0)
#define ARGS tok->val.cmd.args
+ if (router_get_router_hash(*s, digest) < 0)
+ return NULL;
+
+ NEXT_TOKEN();
+
if (tok->tp != K_ROUTER) {
router_release_token(tok);
log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\"");
@@ -793,7 +825,7 @@
memset(router,0,sizeof(routerinfo_t)); /* zero it out first */
/* C doesn't guarantee that NULL is represented by 0 bytes. You'll
thank me for this someday. */
- router->pkey = router->signing_pkey = NULL;
+ router->onion_pkey = router->identity_pkey = router->link_pkey = NULL;
if (tok->val.cmd.n_args != 5) {
log(LOG_ERR,"router_get_entry_from_string(): Wrong # of arguments to \"router\"");
@@ -828,38 +860,77 @@
router->or_port, router->ap_port, router->dir_port, router->bandwidth);
NEXT_TOKEN();
+ if (tok->tp != K_ONION_KEY) {
+ log_fn(LOG_ERR, "Missing onion-key"); goto err;
+ }
+ 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;
+ log_fn(LOG_ERR, "Missing onion key"); goto err;
+ } /* XXX Check key length */
+ router->onion_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();
- }
+ if (tok->tp != K_LINK_KEY) {
+ log_fn(LOG_ERR, "Missing link-key"); goto err;
+ }
+ NEXT_TOKEN();
+ if (tok->tp != _PUBLIC_KEY) {
+ log_fn(LOG_ERR, "Missing link key"); goto err;
+ } /* XXX Check key length */
+ router->link_pkey = tok->val.public_key;
+ NEXT_TOKEN();
+ if (tok->tp != K_SIGNING_KEY) {
+ log_fn(LOG_ERR, "Missing signing-key"); goto err;
+ }
+ NEXT_TOKEN();
+ if (tok->tp != _PUBLIC_KEY) {
+ log_fn(LOG_ERR, "Missing signing key"); goto err;
+ }
+ router->identity_pkey = tok->val.public_key;
+
+ NEXT_TOKEN();
while (tok->tp == K_ACCEPT || tok->tp == K_REJECT) {
router_add_exit_policy(router, tok);
NEXT_TOKEN();
}
+ if (tok->tp != K_ROUTER_SIGNATURE) {
+ log_fn(LOG_ERR,"Missing router signature");
+ goto err;
+ }
+ NEXT_TOKEN();
+ if (tok->tp != _SIGNATURE) {
+ log_fn(LOG_ERR,"Missing router signature");
+ goto err;
+ }
+ assert (router->identity_pkey);
+#if 0
+ /* XXX This should get re-enabled, once directory servers properly
+ * XXX relay signed router blocks. */
+ if (crypto_pk_public_checksig(router->identity_pkey, tok->val.signature,
+ 128, signed_digest) != 20) {
+ log_fn(LOG_ERR, "Invalid signature");
+ goto err;
+ }
+ if (memcmp(digest, signed_digest, 20)) {
+ log_fn(LOG_ERR, "Mismatched signature");
+ goto err;
+ }
+#endif
+
return router;
err:
router_release_token(tok);
if(router->address)
free(router->address);
- if(router->pkey)
- crypto_free_pk_env(router->pkey);
- if(router->signing_pkey)
- crypto_free_pk_env(router->signing_pkey);
+ if(router->link_pkey)
+ crypto_free_pk_env(router->link_pkey);
+ if(router->onion_pkey)
+ crypto_free_pk_env(router->onion_pkey);
+ if(router->identity_pkey)
+ crypto_free_pk_env(router->identity_pkey);
router_free_exit_policy(router);
free(router);
return NULL;
Index: test.c
===================================================================
RCS file: /home/or/cvsroot/src/or/test.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- test.c 10 Sep 2003 00:47:24 -0000 1.37
+++ test.c 25 Sep 2003 05:17:11 -0000 1.38
@@ -49,19 +49,19 @@
char str[256];
char str2[256];
- char *buf;
- int buflen, buf_datalen;
+ buf_t *buf;
+ buf_t *buf2;
int s, i, j, eof;
/****
* buf_new
****/
- if (buf_new(&buf, &buflen, &buf_datalen))
+ if (!(buf = buf_new()))
test_fail();
- test_eq(buflen, MAX_BUF_SIZE);
- test_eq(buf_datalen, 0);
+ test_eq(buf_capacity(buf), MAX_BUF_SIZE);
+ test_eq(buf_datalen(buf), 0);
/****
* read_to_buf
@@ -75,52 +75,52 @@
s = open("/tmp/tor_test/data", O_RDONLY, 0);
eof = 0;
- i = read_to_buf(s, 10, &buf, &buflen, &buf_datalen, &eof);
- test_eq(buflen, MAX_BUF_SIZE);
- test_eq(buf_datalen, 10);
+ i = read_to_buf(s, 10, buf, &eof);
+ test_eq(buf_capacity(buf), MAX_BUF_SIZE);
+ test_eq(buf_datalen(buf), 10);
test_eq(eof, 0);
test_eq(i, 10);
- test_memeq(str, buf, 10);
+ test_memeq(str, (char*)_buf_peek_raw_buffer(buf), 10);
/* Test reading 0 bytes. */
- i = read_to_buf(s, 0, &buf, &buflen, &buf_datalen, &eof);
- test_eq(buflen, MAX_BUF_SIZE);
- test_eq(buf_datalen, 10);
+ i = read_to_buf(s, 0, buf, &eof);
+ test_eq(buf_capacity(buf), MAX_BUF_SIZE);
+ test_eq(buf_datalen(buf), 10);
test_eq(eof, 0);
test_eq(i, 0);
/* Now test when buffer is filled exactly. */
- buflen = 16;
- i = read_to_buf(s, 6, &buf, &buflen, &buf_datalen, &eof);
- test_eq(buflen, 16);
- test_eq(buf_datalen, 16);
+ buf2 = buf_new_with_capacity(6);
+ i = read_to_buf(s, 6, buf2, &eof);
+ test_eq(buf_capacity(buf2), 6);
+ test_eq(buf_datalen(buf2), 6);
test_eq(eof, 0);
test_eq(i, 6);
- test_memeq(str, buf, 16);
+ test_memeq(str+10, (char*)_buf_peek_raw_buffer(buf2), 6);
+ buf_free(buf2);
/* Now test when buffer is filled with more data to read. */
- buflen = 32;
- i = read_to_buf(s, 128, &buf, &buflen, &buf_datalen, &eof);
- test_eq(buflen, 32);
- test_eq(buf_datalen, 32);
+ buf2 = buf_new_with_capacity(32);
+ i = read_to_buf(s, 128, buf2, &eof);
+ test_eq(buf_capacity(buf2), 32);
+ test_eq(buf_datalen(buf2), 32);
test_eq(eof, 0);
- test_eq(i, 16);
- test_memeq(str, buf, 32);
+ test_eq(i, 32);
+ buf_free(buf2);
/* Now read to eof. */
- buflen = MAX_BUF_SIZE;
- test_assert(buflen > 256);
- i = read_to_buf(s, 1024, &buf, &buflen, &buf_datalen, &eof);
- test_eq(i, (256-32));
- test_eq(buflen, MAX_BUF_SIZE);
- test_eq(buf_datalen, 256);
- test_memeq(str, buf, 256);
+ test_assert(buf_capacity(buf) > 256);
+ i = read_to_buf(s, 1024, buf, &eof);
+ test_eq(i, (256-32-10-6));
+ test_eq(buf_capacity(buf), MAX_BUF_SIZE);
+ test_eq(buf_datalen(buf), 256-6-32);
+ test_memeq(str, (char*)_buf_peek_raw_buffer(buf), 10); /* XXX Check rest. */
test_eq(eof, 0);
- i = read_to_buf(s, 1024, &buf, &buflen, &buf_datalen, &eof);
+ i = read_to_buf(s, 1024, buf, &eof);
test_eq(i, 0);
- test_eq(buflen, MAX_BUF_SIZE);
- test_eq(buf_datalen, 256);
+ test_eq(buf_capacity(buf), MAX_BUF_SIZE);
+ test_eq(buf_datalen(buf), 256-6-32);
test_eq(eof, 1);
close(s);
@@ -128,50 +128,59 @@
/****
* find_on_inbuf
****/
+ buf_free(buf);
+ buf = buf_new();
+ s = open("/tmp/tor_test/data", O_RDONLY, 0);
+ eof = 0;
+ i = read_to_buf(s, 1024, buf, &eof);
+ test_eq(256, i);
+ close(s);
- test_eq(((int)'d') + 1, find_on_inbuf("abcd", 4, buf, buf_datalen));
- test_eq(-1, find_on_inbuf("xyzzy", 5, buf, buf_datalen));
+ test_eq(((int)'d') + 1, find_on_inbuf("abcd", 4, buf));
+ test_eq(-1, find_on_inbuf("xyzzy", 5, buf));
/* Make sure we don't look off the end of the buffef */
- buf[256] = 'A';
- buf[257] = 'X';
- test_eq(-1, find_on_inbuf("\xff" "A", 2, buf, buf_datalen));
- test_eq(-1, find_on_inbuf("AX", 2, buf, buf_datalen));
+ ((char*)_buf_peek_raw_buffer(buf))[256] = 'A';
+ ((char*)_buf_peek_raw_buffer(buf))[257] = 'X';
+ test_eq(-1, find_on_inbuf("\xff" "A", 2, buf));
+ test_eq(-1, find_on_inbuf("AX", 2, buf));
/* Make sure we use the string length */
- test_eq(((int)'d')+1, find_on_inbuf("abcdX", 4, buf, buf_datalen));
+ test_eq(((int)'d')+1, find_on_inbuf("abcdX", 4, buf));
/****
* fetch_from_buf
****/
memset(str2, 255, 256);
- test_eq(246, fetch_from_buf(str2, 10, &buf, &buflen, &buf_datalen));
+ test_eq(246, fetch_from_buf(str2, 10, buf));
test_memeq(str2, str, 10);
- test_memeq(str+10,buf,246);
- test_eq(buf_datalen,246);
+ test_memeq(str+10,(char*)_buf_peek_raw_buffer(buf),246);
+ test_eq(buf_datalen(buf),246);
- test_eq(0, fetch_from_buf(str2, 246, &buf, &buflen, &buf_datalen));
+ test_eq(0, fetch_from_buf(str2, 246, buf));
test_memeq(str2, str+10, 246);
- test_eq(buflen,MAX_BUF_SIZE);
- test_eq(buf_datalen,0);
+ test_eq(buf_capacity(buf),MAX_BUF_SIZE);
+ test_eq(buf_datalen(buf),0);
/****
* write_to_buf
****/
- memset(buf, (int)'-', 256);
- i = write_to_buf("Hello world", 11, &buf, &buflen, &buf_datalen);
+ memset((char *)_buf_peek_raw_buffer(buf), (int)'-', 256);
+ i = write_to_buf("Hello world", 11, buf);
test_eq(i, 11);
- test_eq(buf_datalen, 11);
- test_memeq(buf, "Hello world", 11);
- i = write_to_buf("XYZZY", 5, &buf, &buflen, &buf_datalen);
+ test_eq(buf_datalen(buf), 11);
+ test_memeq((char*)_buf_peek_raw_buffer(buf), "Hello world", 11);
+ i = write_to_buf("XYZZY", 5, buf);
test_eq(i, 16);
- test_eq(buf_datalen, 16);
- test_memeq(buf, "Hello worldXYZZY", 16);
+ test_eq(buf_datalen(buf), 16);
+ test_memeq((char*)_buf_peek_raw_buffer(buf), "Hello worldXYZZY", 16);
/* Test when buffer is overfull. */
+#if 0
buflen = 18;
test_eq(-1, write_to_buf("This string will not fit.", 25,
&buf, &buflen, &buf_datalen));
test_eq(buf_datalen, 16);
test_memeq(buf, "Hello worldXYZZY--", 18);
buflen = MAX_BUF_SIZE;
+#endif
/****
* flush_buf
@@ -482,7 +491,8 @@
}
/* from main.c */
-int dump_router_to_string(char *s, int maxlen, routerinfo_t *router);
+int dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
+ crypto_pk_env_t *ident_key);
void dump_directory_to_string(char *s, int maxlen);
/* from routers.c */
@@ -491,28 +501,30 @@
void
test_dir_format()
{
-
- char buf[2048], buf2[2048];
- char *pk1_str = NULL, *pk2_str = NULL, *cp;
- int pk1_str_len, pk2_str_len;
+ char buf[8192], buf2[8192];
+ char *pk1_str = NULL, *pk2_str = NULL, *pk3_str = NULL, *cp;
+ int pk1_str_len, pk2_str_len, pk3_str_len;
routerinfo_t r1, r2;
- crypto_pk_env_t *pk1 = NULL, *pk2 = NULL;
- routerinfo_t *rp1, *rp2;
+ crypto_pk_env_t *pk1 = NULL, *pk2 = NULL, *pk3 = NULL;
+ routerinfo_t *rp1 = NULL, *rp2 = NULL;
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)) );
+ test_assert( (pk3 = crypto_new_pk_env(CRYPTO_PK_RSA)) );
test_assert(! crypto_pk_generate_key(pk1));
test_assert(! crypto_pk_generate_key(pk2));
+ test_assert(! crypto_pk_generate_key(pk3));
r1.address = "testaddr1.foo.bar";
r1.addr = 0xc0a80001u; /* 192.168.0.1 */
r1.or_port = 9000;
r1.ap_port = 9002;
r1.dir_port = 9003;
- r1.pkey = pk1;
- r1.signing_pkey = NULL;
+ r1.onion_pkey = pk1;
+ r1.identity_pkey = pk2;
+ r1.link_pkey = pk3;
r1.bandwidth = 1000;
r1.exit_policy = NULL;
@@ -530,8 +542,9 @@
r2.or_port = 9005;
r2.ap_port = 0;
r2.dir_port = 0;
- r2.pkey = pk2;
- r2.signing_pkey = pk1;
+ r2.onion_pkey = pk2;
+ r2.identity_pkey = pk1;
+ r2.link_pkey = pk2;
r2.bandwidth = 3000;
r2.exit_policy = &ex1;
@@ -539,14 +552,23 @@
&pk1_str_len));
test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str,
&pk2_str_len));
- strcpy(buf2, "router testaddr1.foo.bar 9000 9002 9003 1000\n");
+ test_assert(!crypto_pk_write_public_key_to_string(pk3 , &pk3_str,
+ &pk3_str_len));
+
+ strcpy(buf2, "router testaddr1.foo.bar 9000 9002 9003 1000\nonion-key\n");
strcat(buf2, pk1_str);
- strcat(buf2, "\n");
+ strcat(buf2, "link-key\n");
+ strcat(buf2, pk3_str);
+ strcat(buf2, "signing-key\n");
+ strcat(buf2, pk2_str);
+ strcat(buf2, "router-signature\n");
memset(buf, 0, 2048);
- test_assert(dump_router_to_string(buf, 2048, &r1)>0);
+ test_assert(dump_router_to_string(buf, 2048, &r1, pk1)>0);
+ buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same 2ce*/
test_streq(buf, buf2);
-
+
+ test_assert(dump_router_to_string(buf, 2048, &r1, pk1)>0);
cp = buf;
rp1 = router_get_entry_from_string(&cp);
test_assert(rp1);
@@ -555,16 +577,18 @@
test_eq(rp1->ap_port, r1.ap_port);
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(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0);
+ test_assert(crypto_pk_cmp_keys(rp1->link_pkey, pk3) == 0);
+ test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0);
test_assert(rp1->exit_policy == NULL);
+#if 0
strcpy(buf2, "router tor.tor.tor 9005 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_assert(dump_router_to_string(buf, 2048, &r2, pk2)>0);
test_streq(buf, buf2);
cp = buf;
@@ -575,8 +599,8 @@
test_eq(rp2->ap_port, r2.ap_port);
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_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0);
+ test_assert(crypto_pk_cmp_keys(rp2->identity_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, "*");
@@ -586,6 +610,7 @@
test_streq(rp2->exit_policy->next->address, "18.*");
test_streq(rp2->exit_policy->next->port, "24");
test_assert(rp2->exit_policy->next->next == NULL);
+#endif
/* Okay, now for the directories. */
dir1 = (directory_t*) tor_malloc(sizeof(directory_t));
@@ -593,7 +618,7 @@
dir1->routers = (routerinfo_t**) tor_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));
+ test_assert(! dump_signed_directory_to_string_impl(buf, 4096, dir1, pk1));
/* puts(buf); */
test_assert(! router_get_dir_from_string_impl(buf, &dir2, pk1));
More information about the tor-commits
mailing list