From 6e37086f85aa3e421ebc6f4d64de1cd82bcdeaa6 Mon Sep 17 00:00:00 2001 From: Neel Chauhan Date: Thu, 6 Aug 2020 22:32:30 -0700 Subject: [PATCH] v3 control: Persist ONION_CLIENT_AUTH_ADD client name --- changes/ticket40089 | 4 +++ src/feature/control/control_hs.c | 11 ++++++++ src/feature/hs/hs_client.c | 2 ++ src/feature/hs/hs_client.h | 3 ++ src/test/test_hs_control.c | 47 ++++++++++++++++++++++++++++++-- 5 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 changes/ticket40089 diff --git a/changes/ticket40089 b/changes/ticket40089 new file mode 100644 index 0000000000..121e8e9820 --- /dev/null +++ b/changes/ticket40089 @@ -0,0 +1,4 @@ + o Minor features (control port): + - If a ClientName was specified in ONION_CLIENT_AUTH_ADD for an + onion service, display it when we use ONION_CLIENT_AUTH_VIEW + on it. Closes ticket 40089. Patch by Neel Chauhan. diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c index c8de03b318..54b767cd0d 100644 --- a/src/feature/control/control_hs.c +++ b/src/feature/control/control_hs.c @@ -134,6 +134,13 @@ handle_control_onion_client_auth_add(control_connection_t *conn, } } SMARTLIST_FOREACH_END(flag); } + if (!strcasecmp(line->key, "ClientName")) { + if (strlen(line->value) > REND_CLIENTNAME_MAX_LEN) { + control_printf_endreply(conn, 512, "ClientName longer than %d chars", + REND_CLIENTNAME_MAX_LEN); + } + creds->client_name = tor_strdup(line->value); + } } hs_client_register_auth_status_t register_status; @@ -255,6 +262,10 @@ encode_client_auth_cred_for_control_port( } } + if (cred->client_name) { + smartlist_add_asprintf(control_line, " ClientName=%s", cred->client_name); + } + /* Join all the components into a single string */ msg_str = smartlist_join_strings(control_line, "", 0, NULL); diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index d9c5d8ca1d..fc1fd76efc 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -2168,6 +2168,8 @@ client_service_authorization_free_(hs_client_service_authorization_t *auth) return; } + tor_free(auth->client_name); + memwipe(auth, 0, sizeof(*auth)); tor_free(auth); } diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index a11caa309f..88dede8126 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -71,6 +71,9 @@ typedef struct hs_client_service_authorization_t { /** An onion address that is used to connect to the onion service. */ char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]; + /** An client name used to connect to the onion service. */ + char *client_name; + /* Optional flags for this client. */ int flags; } hs_client_service_authorization_t; diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c index 1f574179e9..80bbf547dc 100644 --- a/src/test/test_hs_control.c +++ b/src/test/test_hs_control.c @@ -212,7 +212,8 @@ test_hs_control_good_onion_client_auth_add(void *arg) MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock); int retval; - ed25519_public_key_t service_identity_pk_2fv, service_identity_pk_jt4; + ed25519_public_key_t service_identity_pk_2fv, service_identity_pk_jt4, + service_identity_pk_jam; control_connection_t conn; char *args = NULL; char *cp1 = NULL; @@ -238,6 +239,12 @@ test_hs_control_good_onion_client_auth_add(void *arg) &service_identity_pk_jt4, NULL, NULL); tt_int_op(retval, OP_EQ, 0); + + retval = hs_parse_address( + "jamie3vkiwibfiwucd6vxijskbhpjdyajmzeor4mc4i7yopvpo4p7cyd", + &service_identity_pk_jam, + NULL, NULL); + tt_int_op(retval, OP_EQ, 0); } digest256map_t *client_auths = get_hs_client_auths_map(); @@ -264,6 +271,20 @@ test_hs_control_good_onion_client_auth_add(void *arg) retval = handle_control_command(&conn, (uint32_t) strlen(args), args); tt_int_op(retval, OP_EQ, 0); + /* Check contents */ + cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz); + tt_str_op(cp1, OP_EQ, "250 OK\r\n"); + tor_free(cp1); + tor_free(args); + + /* Register second service (even with an unrecognized argument) */ + args = tor_strdup("jamie3vkiwibfiwucd6vxijskbhpjdyajmzeor4mc4i7yopvpo4p7cyd " + "x25519:FCV0c0ELDKKDpSFgVIB8Yow8Evj5iD+GoiTtK878NkQ= " + "ClientName=MeganNicole "); + + retval = handle_control_command(&conn, (uint32_t) strlen(args), args); + tt_int_op(retval, OP_EQ, 0); + /* Check contents */ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz); tt_str_op(cp1, OP_EQ, "250 OK\r\n"); @@ -271,7 +292,7 @@ test_hs_control_good_onion_client_auth_add(void *arg) client_auths = get_hs_client_auths_map(); tt_assert(client_auths); - tt_uint_op(digest256map_size(client_auths), OP_EQ, 2); + tt_uint_op(digest256map_size(client_auths), OP_EQ, 3); hs_client_service_authorization_t *client_2fv = digest256map_get(client_auths, service_identity_pk_2fv.pubkey); @@ -283,6 +304,11 @@ test_hs_control_good_onion_client_auth_add(void *arg) tt_assert(client_jt4); tt_int_op(client_jt4->flags, OP_EQ, 0); + hs_client_service_authorization_t *client_jam = + digest256map_get(client_auths, service_identity_pk_jam.pubkey); + tt_assert(client_jam); + tt_int_op(client_jam->flags, OP_EQ, 0); + /* Now let's VIEW the auth credentials */ tor_free(conn.current_cmd); conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_VIEW"); @@ -294,6 +320,9 @@ test_hs_control_good_onion_client_auth_add(void *arg) #define VIEW_CORRECT_REPLY_NO_ADDR "250-ONION_CLIENT_AUTH_VIEW\r\n" \ "250-CLIENT 2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd " \ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ=\r\n" \ + "250-CLIENT jamie3vkiwibfiwucd6vxijskbhpjdyajmzeor4mc4i7yopvpo4p7cyd " \ + "x25519:FCV0c0ELDKKDpSFgVIB8Yow8Evj5iD+GoiTtK878NkQ= " \ + "ClientName=MeganNicole\r\n" \ "250-CLIENT jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd " \ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=\r\n" \ "250 OK\r\n" @@ -364,7 +393,19 @@ test_hs_control_good_onion_client_auth_add(void *arg) /* Now also remove the other one */ tor_free(args); - args =tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd"); + args = + tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd"); + + retval = handle_control_command(&conn, (uint32_t) strlen(args), args); + tt_int_op(retval, OP_EQ, 0); + cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz); + tt_str_op(cp1, OP_EQ, "250 OK\r\n"); + tor_free(cp1); + + /* Now also remove the other one */ + tor_free(args); + args = + tor_strdup("jamie3vkiwibfiwucd6vxijskbhpjdyajmzeor4mc4i7yopvpo4p7cyd"); retval = handle_control_command(&conn, (uint32_t) strlen(args), args); tt_int_op(retval, OP_EQ, 0);