{"thread":{"id":"38568","subject":"[PATCH 1/2] daemon: look up client-supplied hostname lazily","startedAt":"2015-02-15T18:31:41Z","lastAt":"2015-02-15T18:33:52Z","messageCount":2,"participants":["René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"256104","messageId":"54E0E60D.6000305@web.de","threadId":"38568","inReplyTo":null,"subject":"[PATCH 1/2] daemon: look up client-supplied hostname lazily","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2015-02-15T18:31:41Z","receivedAt":"2015-02-15T18:31:41Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Look up canonical hostname and IP address using getaddrinfo(3) or\ngethostbyname(3) only if --interpolated-path or --access-hook were\nspecified.\n\nDo that by introducing getter functions for canon_hostname and\nip_address and using them for all read accesses.  These wrappers call\nthe new helper lookup_hostname(), which sets the variables only at its\nfirst call.\n\nSigned-off-by: Rene Scharfe <l.s.r@web.de>\n---\n daemon.c | 37 +++++++++++++++++++++++++++++--------\n 1 file changed, 29 insertions(+), 8 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 54a03bd..ef41943 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -61,6 +61,22 @@ static char *canon_hostname;\n static char *ip_address;\n static char *tcp_port;\n \n+static int hostname_lookup_done;\n+\n+static void lookup_hostname(void);\n+\n+static const char *get_canon_hostname(void)\n+{\n+\tlookup_hostname();\n+\treturn canon_hostname;\n+}\n+\n+static const char *get_ip_address(void)\n+{\n+\tlookup_hostname();\n+\treturn ip_address;\n+}\n+\n static void logreport(int priority, const char *err, va_list params)\n {\n \tif (log_syslog) {\n@@ -147,8 +163,8 @@ static const char *path_ok(const char *directory)\n \t\tstruct strbuf_expand_dict_entry dict[6];\n \n \t\tdict[0].placeholder = \"H\"; dict[0].value = hostname;\n-\t\tdict[1].placeholder = \"CH\"; dict[1].value = canon_hostname;\n-\t\tdict[2].placeholder = \"IP\"; dict[2].value = ip_address;\n+\t\tdict[1].placeholder = \"CH\"; dict[1].value = get_canon_hostname();\n+\t\tdict[2].placeholder = \"IP\"; dict[2].value = get_ip_address();\n \t\tdict[3].placeholder = \"P\"; dict[3].value = tcp_port;\n \t\tdict[4].placeholder = \"D\"; dict[4].value = directory;\n \t\tdict[5].placeholder = NULL; dict[5].value = NULL;\n@@ -254,8 +270,8 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons\n \t*arg++ = service->name;\n \t*arg++ = path;\n \t*arg++ = STRARG(hostname);\n-\t*arg++ = STRARG(canon_hostname);\n-\t*arg++ = STRARG(ip_address);\n+\t*arg++ = STRARG(get_canon_hostname());\n+\t*arg++ = STRARG(get_ip_address());\n \t*arg++ = STRARG(tcp_port);\n \t*arg = NULL;\n #undef STRARG\n@@ -509,6 +525,7 @@ static void parse_host_arg(char *extra_args, int buflen)\n \t\t\t\t}\n \t\t\t\tfree(hostname);\n \t\t\t\thostname = xstrdup_tolower(host);\n+\t\t\t\thostname_lookup_done = 0;\n \t\t\t}\n \n \t\t\t/* On to the next one */\n@@ -517,11 +534,14 @@ static void parse_host_arg(char *extra_args, int buflen)\n \t\tif (extra_args < end && *extra_args)\n \t\t\tdie(\"Invalid request\");\n \t}\n+}\n \n-\t/*\n-\t * Locate canonical hostname and its IP address.\n-\t */\n-\tif (hostname) {\n+/*\n+ * Locate canonical hostname and its IP address.\n+ */\n+static void lookup_hostname(void)\n+{\n+\tif (!hostname_lookup_done && hostname) {\n #ifndef NO_IPV6\n \t\tstruct addrinfo hints;\n \t\tstruct addrinfo *ai;\n@@ -569,6 +589,7 @@ static void parse_host_arg(char *extra_args, int buflen)\n \t\t\tip_address = xstrdup(addrbuf);\n \t\t}\n #endif\n+\t\thostname_lookup_done = 1;\n \t}\n }\n \n-- \n2.3.0\n"},{"id":"256105","messageId":"54E0E690.8000607@web.de","threadId":"38568","inReplyTo":"54E0E60D.6000305@web.de","subject":"[PATCH 2/2] daemon: use callback to build interpolated path","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2015-02-15T18:33:52Z","receivedAt":"2015-02-15T18:33:52Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Provide a callback function for strbuf_expand() instead of using the\nhelper strbuf_expand_dict_cb().  While the resulting code is longer, it\nonly looks up the canonical hostname and IP address if at least one of\nthe placeholders %CH and %IP are used with --interpolated-path.\n\nUse a struct for passing the directory to the callback function instead\nof passing it directly to avoid having to cast away its const qualifier.\n\nSigned-off-by: Rene Scharfe <l.s.r@web.de>\n---\n daemon.c | 54 +++++++++++++++++++++++++++++++++++++++++++++---------\n 1 file changed, 45 insertions(+), 9 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex ef41943..09fa652 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -122,6 +122,46 @@ static void NORETURN daemon_die(const char *err, va_list params)\n \texit(1);\n }\n \n+static void strbuf_addstr_or_null(struct strbuf *sb, const char *s)\n+{\n+\tif (s)\n+\t\tstrbuf_addstr(sb, s);\n+}\n+\n+struct expand_path_context {\n+\tconst char *directory;\n+};\n+\n+static size_t expand_path(struct strbuf *sb, const char *placeholder, void *ctx)\n+{\n+\tstruct expand_path_context *context = ctx;\n+\n+\tswitch (placeholder[0]) {\n+\tcase 'H':\n+\t\tstrbuf_addstr_or_null(sb, hostname);\n+\t\treturn 1;\n+\tcase 'C':\n+\t\tif (placeholder[1] == 'H') {\n+\t\t\tstrbuf_addstr_or_null(sb, get_canon_hostname());\n+\t\t\treturn 2;\n+\t\t}\n+\t\tbreak;\n+\tcase 'I':\n+\t\tif (placeholder[1] == 'P') {\n+\t\t\tstrbuf_addstr_or_null(sb, get_ip_address());\n+\t\t\treturn 2;\n+\t\t}\n+\t\tbreak;\n+\tcase 'P':\n+\t\tstrbuf_addstr_or_null(sb, tcp_port);\n+\t\treturn 1;\n+\tcase 'D':\n+\t\tstrbuf_addstr(sb, context->directory);\n+\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n static const char *path_ok(const char *directory)\n {\n \tstatic char rpath[PATH_MAX];\n@@ -160,14 +200,10 @@ static const char *path_ok(const char *directory)\n \t}\n \telse if (interpolated_path && saw_extended_args) {\n \t\tstruct strbuf expanded_path = STRBUF_INIT;\n-\t\tstruct strbuf_expand_dict_entry dict[6];\n-\n-\t\tdict[0].placeholder = \"H\"; dict[0].value = hostname;\n-\t\tdict[1].placeholder = \"CH\"; dict[1].value = get_canon_hostname();\n-\t\tdict[2].placeholder = \"IP\"; dict[2].value = get_ip_address();\n-\t\tdict[3].placeholder = \"P\"; dict[3].value = tcp_port;\n-\t\tdict[4].placeholder = \"D\"; dict[4].value = directory;\n-\t\tdict[5].placeholder = NULL; dict[5].value = NULL;\n+\t\tstruct expand_path_context context;\n+\n+\t\tcontext.directory = directory;\n+\n \t\tif (*dir != '/') {\n \t\t\t/* Allow only absolute */\n \t\t\tlogerror(\"'%s': Non-absolute path denied (interpolated-path active)\", dir);\n@@ -175,7 +211,7 @@ static const char *path_ok(const char *directory)\n \t\t}\n \n \t\tstrbuf_expand(&expanded_path, interpolated_path,\n-\t\t\t\tstrbuf_expand_dict_cb, &dict);\n+\t\t\t      expand_path, &context);\n \t\tstrlcpy(interp_path, expanded_path.buf, PATH_MAX);\n \t\tstrbuf_release(&expanded_path);\n \t\tloginfo(\"Interpolated dir '%s'\", interp_path);\n-- \n2.3.0\n"}]}