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; +} +