K_DIR_KEY_PUBLISHED,
K_DIR_KEY_EXPIRES,
K_DIR_KEY_CERTIFICATION,
+ K_DIR_ADDRESS,
K_VOTE_STATUS,
K_VALID_AFTER,
END_OF_TABLE
};
-/** List of tokens allowable in the footer of v1/v2 directory/networkstatus
- * footers. */
#define CERTIFICATE_MEMBERS \
T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
GE(1), NO_OBJ ), \
T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
- NO_ARGS, NEED_OBJ),
+ NO_ARGS, NEED_OBJ), \
+ T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
static token_rule_t dir_key_certificate_table[] = {
CERTIFICATE_MEMBERS
END_OF_TABLE
};
+/** List of tokens allowable in the footer of v1/v2 directory/networkstatus
+ * footers. */
static token_rule_t networkstatus_vote_footer_token_table[] = {
T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
END_OF_TABLE
goto err;
}
+ tok = find_first_by_keyword(tokens, K_DIR_ADDRESS);
+ if (tok) {
+ tor_assert(tok->n_args);
+ if (parse_addr_port(LOG_WARN, tok->args[0], NULL, &cert->addr,
+ &cert->dir_port)<0) {
+ log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
+ goto err;
+ }
+ }
+
tok = find_first_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
tor_assert(tok);
if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
char *identity_key_file = NULL;
char *signing_key_file = NULL;
char *certificate_file = NULL;
+int reuse_signing_key = 0;
int verbose = 0;
int make_new_id = 0;
int months_lifetime = DEFAULT_LIFETIME;
+char *address = NULL;
EVP_PKEY *identity_key = NULL;
EVP_PKEY *signing_key = NULL;
fprintf(stderr, "Syntax:\n"
"tor-gencert [-h|--help] [-v] [--create-identity-key] "
"[-i identity_key_file]\n"
- " [-s signing_key_file] [-c certificate_file]\n");
+ " [-s signing_key_file] [-c certificate_file] "
+ "[--reuse-signing-key]\n");
}
/* XXXX copied from crypto.c */
fprintf(stderr, "Lifetime (in months) was out of range.");
return 1;
}
+ } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--reuse")) {
+ reuse_signing_key = 1;
} else if (!strcmp(argv[i], "-v")) {
verbose = 1;
+ } else if (!strcmp(argv[i], "-a")) {
+ uint32_t addr;
+ uint16_t port;
+ char b[INET_NTOA_BUF_LEN];
+ struct in_addr in;
+ if (i+1>=argc) {
+ fprintf(stderr, "No argument to -a\n");
+ return 1;
+ }
+ if (parse_addr_port(LOG_ERR, argv[++i], NULL, &addr, &port)<0)
+ return 1;
+ in.s_addr = htonl(addr);
+ tor_inet_ntoa(&in, b, sizeof(b));
+ address = tor_malloc(INET_NTOA_BUF_LEN+32);
+ tor_snprintf(address, INET_NTOA_BUF_LEN+32, "%s:%d", b, (int)port);
} else if (!strcmp(argv[i], "--create-identity-key")) {
make_new_id = 1;
} else {
return 0;
}
+/** DOCDOC */
+static int
+load_signing_key(void)
+{
+ FILE *f;
+ if (!(f = fopen(signing_key_file, "r"))) {
+ log_err(LD_GENERAL, "Couldn't open %s for reading: %s",
+ signing_key_file, strerror(errno));
+ return 1;
+ }
+ if (!(signing_key = PEM_read_PrivateKey(f, NULL, NULL, NULL))) {
+ log_err(LD_GENERAL, "Couldn't read siging key from %s", signing_key_file);
+ return 1;
+ }
+ fclose(f);
+ return 0;
+}
+
/** DOCDOC */
static int
generate_signing_key(void)
format_iso_time(expires, mktime(&tm));
tor_snprintf(buf, sizeof(buf),
- "dir-key-certificate-version 3\n"
- "fingerprint %s\n"
+ "dir-key-certificate-version 3"
+ "%s%s"
+ "\nfingerprint %s\n"
"dir-key-published %s\n"
"dir-key-expires %s\n"
"dir-identity-key\n%s"
"dir-signing-key\n%s"
"dir-key-certification\n",
+ address?"\ndir-address ":"", address?address:"",
fingerprint, published, expires, ident, signing);
signed_len = strlen(buf);
SHA1((const unsigned char*)buf,signed_len,(unsigned char*)digest);
goto done;
if (load_identity_key())
goto done;
- if (generate_signing_key())
- goto done;
+ if (reuse_signing_key) {
+ if (load_signing_key())
+ goto done;
+ } else {
+ if (generate_signing_key())
+ goto done;
+ }
if (generate_certificate())
goto done;
EVP_PKEY_free(identity_key);
if (signing_key)
EVP_PKEY_free(signing_key);
+ tor_free(address);
crypto_global_cleanup();
return r;