Index: /home/karsten/tor/tor-trunk-121-patches/src/or/config.c
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/config.c (revision 16480)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/config.c (working copy)
@@ -227,6 +227,7 @@
VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
+ V(HidServAuth, LINELIST, NULL),
V(HSAuthoritativeDir, BOOL, "0"),
V(HSAuthorityRecordStats, BOOL, "0"),
V(HttpProxy, STRING, NULL),
@@ -3154,6 +3155,16 @@
options->MinUptimeHidServDirectoryV2 = 0;
}
+ /* Parse client-side authorization for hidden services. */
+ if (options->HidServAuth) {
+ for (cl = options->HidServAuth; cl; cl = cl->next) {
+ if (rend_parse_client_auth(cl->value) < 0) {
+ log_warn(LD_CONFIG, "HidServAuth contains illegal value: '%s'; "
+ "ignoring.", cl->value);
+ }
+ }
+ }
+
if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds."
" Clipping.", MIN_REND_POST_PERIOD);
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/or.h
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/or.h (revision 16480)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/or.h (working copy)
@@ -2239,6 +2239,8 @@
* other ORs are running. */
config_line_t *RendConfigLines; /**< List of configuration lines
* for rendezvous services. */
+ config_line_t *HidServAuth; /**< List of configuration lines for client-side
+ * authorizations for hidden services */
char *ContactInfo; /**< Contact info to be published in the directory. */
char *HttpProxy; /**< hostname[:port] to use as http proxy, if any. */
@@ -3805,6 +3807,7 @@
int rend_client_send_introduction(origin_circuit_t *introcirc,
origin_circuit_t *rendcirc);
+int rend_parse_client_auth(char *config_line);
/********************************* rendcommon.c ***************************/
@@ -3815,6 +3818,13 @@
crypto_pk_env_t *client_key;
} rend_authorized_client_t;
+/** Client-side configuration of authorization for a hidden service. */
+typedef struct rend_service_authorization_t {
+ char descriptor_cookie[REND_DESC_COOKIE_LEN];
+ char onion_address[REND_SERVICE_ID_LEN_BASE32+1+5+1];
+ int auth_type;
+} rend_service_authorization_t;
+
/** ASCII-encoded v2 hidden service descriptor. */
typedef struct rend_encoded_v2_service_descriptor_t {
char desc_id[DIGEST_LEN]; /**< Descriptor ID. */
@@ -3890,6 +3900,7 @@
void rend_get_descriptor_id_bytes(char *descriptor_id_out,
const char *service_id,
const char *secret_id_part);
+rend_service_authorization_t *lookup_client_auth(char *onion_address);
/********************************* rendservice.c ***************************/
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/rendclient.c (revision 16480)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/rendclient.c (working copy)
@@ -713,3 +713,104 @@
return extend_info_dup(intro->extend_info);
}
+/** Client-side authorizations for hidden services; map of onion address to
+ * rend_service_authorization_t*. */
+static strmap_t *auth_hid_servs = NULL;
+
+/** Look up the client-side authorization for the hidden service with
+ * onion_address. Return NULL if no authorization is available for
+ * that address. */
+rend_service_authorization_t*
+lookup_client_auth(char *onion_address)
+{
+ tor_assert(onion_address);
+ if (!auth_hid_servs) return NULL;
+ return strmap_get(auth_hid_servs, onion_address);
+}
+
+/** Helper: Free storage held by rend_service_authorization_t. */
+static void
+rend_service_authorization_free(rend_service_authorization_t *auth)
+{
+ if (!auth) return;
+ tor_free(auth);
+}
+
+/** Parse config_line as a client-side authorization for a hidden
+ * service and add it to the local map of hidden service authorizations.
+ * Return 0 for success and -1 for failure. */
+int
+rend_parse_client_auth(char *config_line)
+{
+ char *onion_address, *descriptor_cookie;
+ char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
+ char descriptor_cookie_base64ext[REND_DESC_COOKIE_LEN_BASE64+2+1];
+ smartlist_t *sl = smartlist_create();
+ rend_service_authorization_t *auth = NULL;
+ int res = -1, auth_type = 0;
+ tor_assert(config_line);
+ smartlist_split_string(sl, config_line, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
+ if (smartlist_len(sl) < 2) {
+ log_warn(LD_CONFIG, "Configuration line does not consist of "
+ "\"onion-address authorization-cookie [service-name]\": '%s'",
+ config_line);
+ goto free;
+ }
+ auth = tor_malloc_zero(sizeof(rend_service_authorization_t));
+ /* Parse onion address. */
+ onion_address = smartlist_get(sl, 0);
+ if (strlen(onion_address) != 16+1+5 ||
+ strstr(onion_address, ".onion") != onion_address + 16) {
+ log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
+ onion_address);
+ goto free;
+ }
+ strlcpy(auth->onion_address, onion_address, 16+1);
+ if (!rend_valid_service_id(auth->onion_address)) {
+ log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
+ onion_address);
+ goto free;
+ }
+ /* Parse descriptor cookie. */
+ descriptor_cookie = smartlist_get(sl, 1);
+ if (strlen(descriptor_cookie) != 22) {
+ log_warn(LD_CONFIG, "Authorization cookie has wrong length: '%s'",
+ descriptor_cookie);
+ goto free;
+ }
+ /* Add trailing zero bytes (AA) to make base64-decoding happy. */
+ tor_snprintf(descriptor_cookie_base64ext,
+ REND_DESC_COOKIE_LEN_BASE64+2+1,
+ "%sAA", descriptor_cookie);
+ if (base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
+ descriptor_cookie_base64ext,
+ strlen(descriptor_cookie_base64ext)) < 0) {
+ log_warn(LD_CONFIG, "Decoding authorization cookie failed: '%s'",
+ descriptor_cookie);
+ goto free;
+ }
+ auth_type = (descriptor_cookie_tmp[16] >> 4) + 1;
+ if (auth_type < 1 || auth_type > 2) {
+ log_warn(LD_CONFIG, "Authorization cookie has unknown authorization type "
+ "encoded.");
+ goto free;
+ }
+ auth->auth_type = auth_type;
+ memcpy(auth->descriptor_cookie, descriptor_cookie_tmp,
+ REND_DESC_COOKIE_LEN);
+ /* Add parsed client authorization to local map. */
+ if (!auth_hid_servs)
+ auth_hid_servs = strmap_new();
+ strmap_set(auth_hid_servs, auth->onion_address, auth);
+ auth = NULL;
+ res = 0;
+ free:
+ if (sl)
+ SMARTLIST_FOREACH(sl, char *, c, tor_free(c););
+ smartlist_free(sl);
+ if (auth)
+ rend_service_authorization_free(auth);
+ return res;
+}
+