diff --git a/ChangeLog b/ChangeLog
index ec4ab45ca4..f17da10b1c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -56,6 +56,8 @@ Changes in version 0.2.0.20-?? - 2008-02-??
- We were comparing the raw BridgePassword entry with a base64'ed
version of it, when handling a "/tor/networkstatus-bridges"
directory request. Now compare correctly. Noticed by Veracode.
+ - When starting as an authority, do not overwrite all certificates
+ cached from author authorities. Bugfix on 0.2.0.x. Fixes bug 606.
o Code simplifications and refactoring:
- Remove the tor_strpartition function: its logic was confused,
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 44f5ebac32..e025a5b2bc 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -13,7 +13,7 @@ const char buffers_c_id[] =
* fairly opaque string holders that can read to or flush from:
* memory, file descriptors, or TLS connections.
**/
-
+#define BUFFERS_PRIVATE
#include "or.h"
//#define PARANOIA
@@ -1075,7 +1075,7 @@ buf_matches_at_pos(const buf_pos_t *pos, const char *s, size_t n)
/** Return the first position in buf at which the n-character
* string s occurs, or -1 if it does not occur. */
-static int
+/*private*/ int
buf_find_string_offset(const buf_t *buf, const char *s, size_t n)
{
buf_pos_t pos;
diff --git a/src/or/directory.c b/src/or/directory.c
index 6f494ec3cf..2a05c390dc 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -1533,7 +1533,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
log_info(LD_DIR,"Received authority certificates (size %d) from server "
"'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
- if (trusted_dirs_load_certs_from_string(body, 0)<0) {
+ if (trusted_dirs_load_certs_from_string(body, 0, 1)<0) {
log_warn(LD_DIR, "Unable to parse fetched certificates");
connection_dir_download_cert_failed(conn, status_code);
} else {
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 1455418a88..50f8569292 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -1543,7 +1543,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
/* Hey, it's a new cert! */
trusted_dirs_load_certs_from_string(
vote->cert->cache_info.signed_descriptor_body,
- 0 /* from_store */);
+ 0 /* from_store */, 1 /*flush*/);
if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest,
vote->cert->signing_key_digest)) {
log_warn(LD_BUG, "We added a cert, but still couldn't find it.");
diff --git a/src/or/or.h b/src/or/or.h
index 50d98e82ab..33ae67a4e8 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2471,6 +2471,10 @@ int peek_buf_has_control0_command(buf_t *buf);
void assert_buf_ok(buf_t *buf);
+#ifdef BUFFERS_PRIVATE
+int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
+#endif
+
/********************************* circuitbuild.c **********************/
char *circuit_list_path(origin_circuit_t *circ, int verbose);
@@ -3846,7 +3850,8 @@ typedef struct trusted_dir_server_t {
int get_n_authorities(authority_type_t type);
int trusted_dirs_reload_certs(void);
-int trusted_dirs_load_certs_from_string(const char *contents, int from_store);
+int trusted_dirs_load_certs_from_string(const char *contents, int from_store,
+ int flush);
void trusted_dirs_flush_certs_to_disk(void);
authority_cert_t *authority_cert_get_newest_by_id(const char *id_digest);
authority_cert_t *authority_cert_get_by_sk_digest(const char *sk_digest);
diff --git a/src/or/router.c b/src/or/router.c
index 026709c677..88179fdcd9 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -587,7 +587,7 @@ init_keys(void)
if (cert) { /* add my own cert to the list of known certs */
log_info(LD_DIR, "adding my own v3 cert");
if (trusted_dirs_load_certs_from_string(
- cert->cache_info.signed_descriptor_body, 0)<0) {
+ cert->cache_info.signed_descriptor_body, 0, 0)<0) {
log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing.");
return -1;
}
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 2418c7ee8e..d6a4316f24 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -127,7 +127,7 @@ trusted_dirs_reload_certs(void)
tor_free(filename);
if (!contents)
return 0;
- r = trusted_dirs_load_certs_from_string(contents, 1);
+ r = trusted_dirs_load_certs_from_string(contents, 1, 1);
tor_free(contents);
return r;
}
@@ -155,7 +155,8 @@ already_have_cert(authority_cert_t *cert)
* to flush any changed certificates to disk. Return 0 on success, -1 on
* failure. */
int
-trusted_dirs_load_certs_from_string(const char *contents, int from_store)
+trusted_dirs_load_certs_from_string(const char *contents, int from_store,
+ int flush)
{
trusted_dir_server_t *ds;
const char *s, *eos;
@@ -215,7 +216,8 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store)
trusted_dir_servers_certs_changed = 1;
}
- trusted_dirs_flush_certs_to_disk();
+ if (flush)
+ trusted_dirs_flush_certs_to_disk();
networkstatus_note_certs_arrived();
return 0;