/* Test encoding and decoding service authorization cookies */ static void test_hs_auth_cookies(void *arg) { #define TEST_COOKIE_RAW ((const uint8_t *) "abcdefghijklmnop") #define TEST_COOKIE_ENCODED "YWJjZGVmZ2hpamtsbW5vcA" #define TEST_COOKIE_ENCODED_STEALTH "YWJjZGVmZ2hpamtsbW5vcB" #define TEST_COOKIE_ENCODED_INVALID "YWJjZGVmZ2hpamtsbW5vcD" char *encoded_cookie; uint8_t raw_cookie[REND_DESC_COOKIE_LEN]; rend_auth_type_t auth_type; char *err_msg; int re; (void)arg; /* Test that encoding gives the expected result */ encoded_cookie = rend_auth_encode_cookie(TEST_COOKIE_RAW, REND_BASIC_AUTH); tt_str_op(encoded_cookie, OP_EQ, TEST_COOKIE_ENCODED); tor_free(encoded_cookie); encoded_cookie = rend_auth_encode_cookie(TEST_COOKIE_RAW, REND_STEALTH_AUTH); tt_str_op(encoded_cookie, OP_EQ, TEST_COOKIE_ENCODED_STEALTH); tor_free(encoded_cookie); /* Decoding should give the original value */ re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED, raw_cookie, &auth_type, &err_msg); tt_assert(!re); tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(raw_cookie, OP_EQ, TEST_COOKIE_RAW, REND_DESC_COOKIE_LEN); tt_int_op(auth_type, OP_EQ, REND_BASIC_AUTH); memset(raw_cookie, 0, sizeof(raw_cookie)); re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED_STEALTH, raw_cookie, &auth_type, &err_msg); tt_assert(!re); tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(raw_cookie, OP_EQ, TEST_COOKIE_RAW, REND_DESC_COOKIE_LEN); tt_int_op(auth_type, OP_EQ, REND_STEALTH_AUTH); memset(raw_cookie, 0, sizeof(raw_cookie)); /* Decoding with padding characters should also work */ re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED "==", raw_cookie, NULL, &err_msg); tt_assert(!re); tt_ptr_op(err_msg, OP_EQ, NULL); tt_mem_op(raw_cookie, OP_EQ, TEST_COOKIE_RAW, REND_DESC_COOKIE_LEN); /* Decoding with an unknown type should fail */ re = rend_auth_decode_cookie(TEST_COOKIE_ENCODED_INVALID, raw_cookie, &auth_type, &err_msg); tt_int_op(re, OP_LT, 0); tt_assert(err_msg); tor_free(err_msg); done: return; }
/** Parse the content of a client_key file in <b>ckstr</b> and add * rend_authorized_client_t's for each parsed client to * <b>parsed_clients</b>. Return the number of parsed clients as result * or -1 for failure. */ int rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr) { int result = -1; smartlist_t *tokens; directory_token_t *tok; const char *current_entry = NULL; memarea_t *area = NULL; char *err_msg = NULL; if (!ckstr || strlen(ckstr) == 0) return -1; tokens = smartlist_new(); /* Begin parsing with first entry, skipping comments or whitespace at the * beginning. */ area = memarea_new(); current_entry = eat_whitespace(ckstr); while (!strcmpstart(current_entry, "client-name ")) { rend_authorized_client_t *parsed_entry; /* Determine end of string. */ const char *eos = strstr(current_entry, "\nclient-name "); if (!eos) eos = current_entry + strlen(current_entry); else eos = eos + 1; /* Free tokens and clear token list. */ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); /* Tokenize string. */ if (tokenize_string(area, current_entry, eos, tokens, client_keys_token_table, 0)) { log_warn(LD_REND, "Error tokenizing client keys file."); goto err; } /* Advance to next entry, if available. */ current_entry = eos; /* Check minimum allowed length of token list. */ if (smartlist_len(tokens) < 2) { log_warn(LD_REND, "Impossibly short client key entry."); goto err; } /* Parse client name. */ tok = find_by_keyword(tokens, C_CLIENT_NAME); tor_assert(tok == smartlist_get(tokens, 0)); tor_assert(tok->n_args == 1); if (!rend_valid_client_name(tok->args[0])) { log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be " "between 1 and %d, and valid characters are " "[A-Za-z0-9+-_].)", tok->args[0], REND_CLIENTNAME_MAX_LEN); goto err; } /* Check if client name is duplicate. */ if (strmap_get(parsed_clients, tok->args[0])) { log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a " "duplicate client name: '%s'. Ignoring.", tok->args[0]); goto err; } parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t)); parsed_entry->client_name = tor_strdup(tok->args[0]); strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry); /* Parse client key. */ tok = find_opt_by_keyword(tokens, C_CLIENT_KEY); if (tok) { parsed_entry->client_key = tok->key; tok->key = NULL; /* Prevent free */ } /* Parse descriptor cookie. */ tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE); tor_assert(tok->n_args == 1); if (rend_auth_decode_cookie(tok->args[0], parsed_entry->descriptor_cookie, NULL, &err_msg) < 0) { tor_assert(err_msg); log_warn(LD_REND, "%s", err_msg); tor_free(err_msg); goto err; } } result = strmap_size(parsed_clients); goto done; err: result = -1; done: /* Free tokens and clear token list. */ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) memarea_drop_all(area); return result; }