[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: Second patch for proposal 121



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Nick,

attached to this mail you find an improved patch.

I didn't quote and respond to your comments, because for half of them I
could only say: "Argh. How could I overlook that." And for the remaining
ones my answer would be: "Wow, I didn't imagine that Tor has a function
for *that*. If the Tor project should ever fail, let's go and sell it as
an API." ;)

Please let me know if there are more issues with this patch. Always
happy to learn! :)

Thanks!
- --Karsten
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFIoJ5k0M+WPffBEmURAiBlAJ4oxy4s8rVQat3UBHMU66ZmDcAvXgCgoMCk
okHNpoitYGeoKJzJdFurYZA=
=X00S
-----END PGP SIGNATURE-----
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/config.c
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/config.c	(revision 16498)
+++ /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),
@@ -1191,6 +1192,12 @@
     return -1;
   }
 
+  if (running_tor && rend_parse_service_authorization(options, 0) < 0) {
+    log_warn(LD_BUG, "Previously validated client authorization for "
+                     "hidden services could not be added!");
+    return -1;
+  }
+
   if (running_tor && directory_caches_v2_dir_info(options)) {
     len = strlen(options->DataDirectory)+32;
     fn = tor_malloc(len);
@@ -3402,6 +3409,11 @@
   if (rend_config_services(options, 1) < 0)
     REJECT("Failed to configure rendezvous options. See logs for details.");
 
+  /* Parse client-side authorization for hidden services. */
+  if (rend_parse_service_authorization(options, 1) < 0)
+    REJECT("Failed to configure client authorization for hidden services. "
+           "See logs for details.");
+
   if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0)
     return -1;
 
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/main.c
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/main.c	(revision 16498)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/main.c	(working copy)
@@ -1873,6 +1873,7 @@
   dirserv_free_all();
   rend_service_free_all();
   rend_cache_free_all();
+  rend_service_authorization_free_all();
   rep_hist_free_all();
   hs_usage_free_all();
   dns_free_all();
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/or.h
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/or.h	(revision 16498)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/or.h	(working copy)
@@ -612,6 +612,9 @@
 /** Length of 'y' portion of 'y.onion' URL. */
 #define REND_SERVICE_ID_LEN_BASE32 16
 
+/** Length of 'y.onion' including '.onion' URL. */
+#define REND_SERVICE_ADDRESS_LEN (16+1+5)
+
 /** Length of a binary-encoded rendezvous service ID. */
 #define REND_SERVICE_ID_LEN 10
 
@@ -2239,6 +2242,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. */
@@ -3806,6 +3811,26 @@
 int rend_client_send_introduction(origin_circuit_t *introcirc,
                                   origin_circuit_t *rendcirc);
 
+/** Client authorization type that a hidden service performs. */
+typedef enum rend_auth_type_t {
+  REND_NO_AUTH      = 0,
+  REND_BASIC_AUTH   = 1,
+  REND_STEALTH_AUTH = 2,
+} rend_auth_type_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_ADDRESS_LEN+1];
+  rend_auth_type_t auth_type;
+} rend_service_authorization_t;
+
+int rend_parse_service_authorization(or_options_t *options,
+                                     int validate_only);
+rend_service_authorization_t *rend_client_lookup_service_authorization(
+                                                const char *onion_address);
+void rend_service_authorization_free_all(void);
+
 /********************************* rendcommon.c ***************************/
 
 /** Hidden-service side configuration of client authorization. */
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/rendclient.c
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/rendclient.c	(revision 16498)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/rendclient.c	(working copy)
@@ -713,3 +713,136 @@
   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
+ * <b>onion_address</b>. Return NULL if no authorization is available for
+ * that address. */
+rend_service_authorization_t*
+rend_client_lookup_service_authorization(const 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)
+{
+  tor_free(auth);
+}
+
+/** Helper for strmap_free. */
+static void
+rend_service_authorization_strmap_item_free(void *service_auth)
+{
+  rend_service_authorization_free(service_auth);
+}
+
+/** Release all the storage held in auth_hid_servs.
+ */
+void
+rend_service_authorization_free_all(void)
+{
+  if (!auth_hid_servs) {
+    return;
+  }
+  strmap_free(auth_hid_servs, rend_service_authorization_strmap_item_free);
+  auth_hid_servs = NULL;
+}
+
+/** Parse <b>config_line</b> 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_service_authorization(or_options_t *options, int validate_only)
+{
+  config_line_t *line;
+  int res = -1;
+  strmap_t *parsed = strmap_new();
+  smartlist_t *sl = smartlist_create();
+
+  for (line = options->HidServAuth; line; line = line->next) {
+    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];
+    rend_service_authorization_t *auth = NULL;
+    int auth_type_val = 0;
+    SMARTLIST_FOREACH(sl, char *, c, tor_free(c););
+    smartlist_clear(sl);
+    smartlist_split_string(sl, line->value, " ",
+                           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'", line->value);
+      goto err;
+    }
+    auth = tor_malloc_zero(sizeof(rend_service_authorization_t));
+    /* Parse onion address. */
+    onion_address = smartlist_get(sl, 0);
+    if (strlen(onion_address) != REND_SERVICE_ADDRESS_LEN ||
+        strcmpend(onion_address, ".onion")) {
+      log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
+               onion_address);
+      goto err;
+    }
+    strlcpy(auth->onion_address, onion_address, REND_SERVICE_ID_LEN_BASE32+1);
+    if (!rend_valid_service_id(auth->onion_address)) {
+      log_warn(LD_CONFIG, "Onion address has wrong format: '%s'",
+               onion_address);
+      goto err;
+    }
+    /* Parse descriptor cookie. */
+    descriptor_cookie = smartlist_get(sl, 1);
+    if (strlen(descriptor_cookie) != REND_DESC_COOKIE_LEN_BASE64) {
+      log_warn(LD_CONFIG, "Authorization cookie has wrong length: '%s'",
+               descriptor_cookie);
+      goto err;
+    }
+    /* 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, sizeof(descriptor_cookie_tmp),
+                      descriptor_cookie_base64ext,
+                      strlen(descriptor_cookie_base64ext)) < 0) {
+      log_warn(LD_CONFIG, "Decoding authorization cookie failed: '%s'",
+               descriptor_cookie);
+      goto err;
+    }
+    auth_type_val = (descriptor_cookie_tmp[16] >> 4) + 1;
+    if (auth_type_val < 1 || auth_type_val > 2) {
+      log_warn(LD_CONFIG, "Authorization cookie has unknown authorization "
+                          "type encoded.");
+      goto err;
+    }
+    auth->auth_type = auth_type_val == 1 ? REND_BASIC_AUTH : REND_STEALTH_AUTH;
+    memcpy(auth->descriptor_cookie, descriptor_cookie_tmp,
+           REND_DESC_COOKIE_LEN);
+    if (strmap_get(parsed, auth->onion_address)) {
+      log_warn(LD_CONFIG, "Duplicate authorization for the same hidden "
+                          "service.");
+      goto err;
+    }
+    strmap_set(parsed, auth->onion_address, auth);
+  }
+  res = 0;
+  goto done;
+ err:
+  res = -1;
+ done:
+  SMARTLIST_FOREACH(sl, char *, c, tor_free(c););
+  smartlist_free(sl);
+  if (!validate_only && res == 0) {
+    rend_service_authorization_free_all();
+    auth_hid_servs = parsed;
+  } else {
+    strmap_free(parsed, rend_service_authorization_strmap_item_free);
+  }
+  return res;
+}
+
Index: /home/karsten/tor/tor-trunk-121-patches/src/or/rendservice.c
===================================================================
--- /home/karsten/tor/tor-trunk-121-patches/src/or/rendservice.c	(revision 16498)
+++ /home/karsten/tor/tor-trunk-121-patches/src/or/rendservice.c	(working copy)
@@ -40,13 +40,6 @@
  * rendezvous point before giving up? */
 #define MAX_REND_TIMEOUT 30
 
-/** DOCDOC */
-typedef enum rend_auth_type_t {
-  REND_NO_AUTH      = 0,
-  REND_BASIC_AUTH   = 1,
-  REND_STEALTH_AUTH = 2,
-} rend_auth_type_t;
-
 /** Represents a single hidden service running at this OP. */
 typedef struct rend_service_t {
   /* Fields specified in config file */

Attachment: patch-121-2a.txt.sig
Description: Binary data