|
@@ -24,6 +24,17 @@
|
|
|
|
|
|
#include "feature/nodelist/networkstatus_st.h"
|
|
|
|
|
|
+#define SUBPROCESS_PRIVATE
|
|
|
+#include "lib/process/env.h"
|
|
|
+#include "lib/process/subprocess.h"
|
|
|
+#include "lib/evloop/compat_libevent.h"
|
|
|
+
|
|
|
+#include <event2/event.h>
|
|
|
+
|
|
|
+#ifdef HAVE_UNISTD_H
|
|
|
+#include <unistd.h>
|
|
|
+#endif
|
|
|
+
|
|
|
static int cached_client_descriptor_has_expired(time_t now,
|
|
|
const hs_cache_client_descriptor_t *cached_desc);
|
|
|
|
|
@@ -117,6 +128,11 @@ cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
|
|
|
+ strlen(entry->encoded_desc));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+hs_cache_pirserver_insert_desc(hs_cache_dir_descriptor_t *desc);
|
|
|
+
|
|
|
|
|
|
* on success else a negative value is returned indicating that we have a
|
|
|
* newer version in our cache. On error, caller is responsible to free the
|
|
@@ -155,6 +171,9 @@ cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
|
|
|
* has been removed from the cache. */
|
|
|
store_v3_desc_as_dir(desc);
|
|
|
|
|
|
+
|
|
|
+ hs_cache_pirserver_insert_desc(desc);
|
|
|
+
|
|
|
|
|
|
* old HS protocol cache subsystem for which we are tied with. */
|
|
|
rend_cache_increment_allocation(cache_get_dir_entry_size(desc));
|
|
@@ -167,6 +186,8 @@ cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
|
|
|
* descriptor, lookup in our directory cache the entry. If found, 1 is
|
|
|
* returned and desc_out is populated with a newly allocated string being the
|
|
@@ -955,6 +976,195 @@ hs_cache_get_max_descriptor_size(void)
|
|
|
HS_DESC_MAX_LEN, 1, INT32_MAX);
|
|
|
}
|
|
|
|
|
|
+static process_handle_t *pirserver;
|
|
|
+static struct event *pirserver_read_ev;
|
|
|
+
|
|
|
+typedef enum {
|
|
|
+ PIRSERVER_READSTATE_HEADER,
|
|
|
+ PIRSERVER_READSTATE_BODY
|
|
|
+} PIRServerReadState;
|
|
|
+
|
|
|
+#define PIRSERVER_READHDR_SIZE 13
|
|
|
+
|
|
|
+static void
|
|
|
+hs_cache_pirserver_received(const unsigned char *hdrbuf,
|
|
|
+ const char *bodybuf, size_t bodylen)
|
|
|
+{
|
|
|
+
|
|
|
+ log_info(LD_DIRSERV,"PIRSERVER response header %p flag %d body len %ld body %s", *(void**)hdrbuf, hdrbuf[8], bodylen, escaped(bodybuf));
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+hs_cache_pirserver_recvcb(evutil_socket_t fd, short what,
|
|
|
+ ATTR_UNUSED void *arg) {
|
|
|
+ static PIRServerReadState readstate = PIRSERVER_READSTATE_HEADER;
|
|
|
+ static size_t readoff = 0;
|
|
|
+ static size_t readleft = PIRSERVER_READHDR_SIZE;
|
|
|
+ static unsigned char hdrbuf[PIRSERVER_READHDR_SIZE];
|
|
|
+ static char *bodybuf = NULL;
|
|
|
+
|
|
|
+ if (!(what & EV_READ)) {
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (readstate == PIRSERVER_READSTATE_HEADER) {
|
|
|
+ int res = read(fd, hdrbuf + readoff, readleft);
|
|
|
+ if (res <= 0) return;
|
|
|
+ readoff += res;
|
|
|
+ readleft -= res;
|
|
|
+ if (readleft == 0) {
|
|
|
+ readleft = ntohl(*(uint32_t*)(hdrbuf+PIRSERVER_READHDR_SIZE-4));
|
|
|
+ free(bodybuf);
|
|
|
+ bodybuf = NULL;
|
|
|
+ if (readleft > 0) {
|
|
|
+ bodybuf = malloc(readleft);
|
|
|
+ readoff = 0;
|
|
|
+ readstate = PIRSERVER_READSTATE_BODY;
|
|
|
+ } else {
|
|
|
+ hs_cache_pirserver_received(hdrbuf, NULL, 0);
|
|
|
+ readoff = 0;
|
|
|
+ readleft = PIRSERVER_READHDR_SIZE;
|
|
|
+ readstate = PIRSERVER_READSTATE_HEADER;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (readstate == PIRSERVER_READSTATE_BODY) {
|
|
|
+ int res = read(fd, bodybuf + readoff, readleft);
|
|
|
+ if (res <= 0) return;
|
|
|
+ readoff += res;
|
|
|
+ readleft -= res;
|
|
|
+ if (readleft == 0) {
|
|
|
+
|
|
|
+ hs_cache_pirserver_received(hdrbuf, bodybuf, readoff);
|
|
|
+
|
|
|
+
|
|
|
+ free(bodybuf);
|
|
|
+ bodybuf = NULL;
|
|
|
+ readoff = 0;
|
|
|
+ readleft = PIRSERVER_READHDR_SIZE;
|
|
|
+ readstate = PIRSERVER_READSTATE_HEADER;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ server if needed. */
|
|
|
+static void
|
|
|
+hs_cache_pir_poke(void)
|
|
|
+{
|
|
|
+ int res;
|
|
|
+ const char *pirserverpath = getenv("PIR_SERVER_PATH");
|
|
|
+ smartlist_t *env_vars = get_current_process_environment_variables();
|
|
|
+ const char *argv[2];
|
|
|
+ process_environment_t *env;
|
|
|
+
|
|
|
+ if (pirserver && pirserver->status == PROCESS_STATUS_RUNNING) {
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pirserver) {
|
|
|
+ if (pirserver_read_ev) {
|
|
|
+ event_free(pirserver_read_ev);
|
|
|
+ pirserver_read_ev = NULL;
|
|
|
+ }
|
|
|
+ tor_process_handle_destroy(pirserver, 1);
|
|
|
+ pirserver = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!pirserverpath) {
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ argv[0] = pirserverpath;
|
|
|
+ argv[1] = NULL;
|
|
|
+
|
|
|
+ env = process_environment_make(env_vars);
|
|
|
+
|
|
|
+ res = tor_spawn_background(pirserverpath, argv, env, &pirserver);
|
|
|
+
|
|
|
+ SMARTLIST_FOREACH(env_vars, void *, x, tor_free(x));
|
|
|
+ smartlist_free(env_vars);
|
|
|
+
|
|
|
+ if (res != PROCESS_STATUS_RUNNING) {
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ pirserver_read_ev = event_new(tor_libevent_get_base(),
|
|
|
+ pirserver->stdout_pipe, EV_READ|EV_PERSIST,
|
|
|
+ hs_cache_pirserver_recvcb, NULL);
|
|
|
+ event_add(pirserver_read_ev, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void
|
|
|
+hs_cache_pir_init(void)
|
|
|
+{
|
|
|
+ pirserver = NULL;
|
|
|
+ pirserver_read_ev = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+hs_cache_pirserver_send(const unsigned char *buf, size_t len)
|
|
|
+{
|
|
|
+ size_t written = 0;
|
|
|
+
|
|
|
+ hs_cache_pir_poke();
|
|
|
+ if (pirserver == NULL || pirserver->status != PROCESS_STATUS_RUNNING) {
|
|
|
+
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * pir server will never block, but we should actually put this into
|
|
|
+ * a write buffer. */
|
|
|
+ while (len) {
|
|
|
+ ssize_t res = write(pirserver->stdin_pipe, buf, len);
|
|
|
+ if (res < 0) return res;
|
|
|
+ if (res == 0) return written;
|
|
|
+ written += res;
|
|
|
+ buf += res;
|
|
|
+ len -= res;
|
|
|
+ }
|
|
|
+ return written;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+hs_cache_pirserver_insert_desc(hs_cache_dir_descriptor_t *desc)
|
|
|
+{
|
|
|
+ unsigned char hdr[13];
|
|
|
+ size_t encoded_desc_len;
|
|
|
+ size_t len;
|
|
|
+ int res;
|
|
|
+ int written = 0;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ memmove(hdr, "12345678\x01", 9);
|
|
|
+ encoded_desc_len = strlen(desc->encoded_desc);
|
|
|
+ len = DIGEST256_LEN + encoded_desc_len;
|
|
|
+ *(uint32_t*)(hdr+9) = htonl(len);
|
|
|
+
|
|
|
+ res = hs_cache_pirserver_send(hdr, 13);
|
|
|
+ if (res <= 0) return -1;
|
|
|
+ written += res;
|
|
|
+
|
|
|
+ res = hs_cache_pirserver_send(desc->key, DIGEST256_LEN);
|
|
|
+ if (res <= 0) return -1;
|
|
|
+ written += res;
|
|
|
+
|
|
|
+ res = hs_cache_pirserver_send(
|
|
|
+ (const unsigned char *)desc->encoded_desc,
|
|
|
+ encoded_desc_len);
|
|
|
+ if (res <= 0) return -1;
|
|
|
+ written += res;
|
|
|
+
|
|
|
+ return written;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
void
|
|
|
hs_cache_init(void)
|
|
@@ -968,6 +1178,8 @@ hs_cache_init(void)
|
|
|
|
|
|
tor_assert(!hs_cache_client_intro_state);
|
|
|
hs_cache_client_intro_state = digest256map_new();
|
|
|
+
|
|
|
+ hs_cache_pir_init();
|
|
|
}
|
|
|
|
|
|
|