daemon: look up client-supplied hostname lazily
PATCH 1/2 daemon: look up client-supplied hostname lazily
Look up canonical hostname and IP address using getaddrinfo(3) or gethostbyname(3) only if --interpolated-path or --access-hook were specified.
Do that by introducing getter functions for canon_hostname and ip_address and using them for all read accesses. These wrappers call the new helper lookup_hostname(), which sets the variables only at its first call.
--- daemon.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-)
daemon.c +29 -8
@@ -61,6 +61,22 @@ static char *canon_hostname;static char *ip_address;static char *tcp_port; +static int hostname_lookup_done; + +static void lookup_hostname (void ); + +static const char *get_canon_hostname (void ) +{ +lookup_hostname (); +return canon_hostname; +} + +static const char *get_ip_address (void ) +{ +lookup_hostname (); +return ip_address; +} +static void logreport (int priority,const char *err,va_list params) {if (log_syslog) {
@@ -147,8 +163,8 @@ static const char *path_ok(const char *directory)struct strbuf_expand_dict_entry dict[6 ]; dict[0 ].placeholder ="H" ; dict[0 ].value = hostname; - dict[1 ].placeholder ="CH" ; dict[1 ].value = canon_hostname; - dict[2 ].placeholder ="IP" ; dict[2 ].value = ip_address; + dict[1 ].placeholder ="CH" ; dict[1 ].value =get_canon_hostname (); + dict[2 ].placeholder ="IP" ; dict[2 ].value =get_ip_address (); dict[3 ].placeholder ="P" ; dict[3 ].value = tcp_port; dict[4 ].placeholder ="D" ; dict[4 ].value = directory; dict[5 ].placeholder =NULL ; dict[5 ].value =NULL ;
@@ -254,8 +270,8 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons *arg++ = service->name; *arg++ = path; *arg++ =STRARG (hostname); - *arg++ =STRARG (canon_hostname); - *arg++ =STRARG (ip_address); + *arg++ =STRARG (get_canon_hostname ()); + *arg++ =STRARG (get_ip_address ()); *arg++ =STRARG (tcp_port); *arg =NULL ;#undef STRARG
@@ -509,6 +525,7 @@ static void parse_host_arg(char *extra_args, int buflen) }free (hostname); hostname =xstrdup_tolower (host); + hostname_lookup_done =0 ; }/* On to the next one */
@@ -517,11 +534,14 @@ static void parse_host_arg(char *extra_args, int buflen)if (extra_args < end && *extra_args)die ("Invalid request" ); } +} -/* -* Locate canonical hostname and its IP address. -*/ -if (hostname) { +/* +* Locate canonical hostname and its IP address. +*/ +static void lookup_hostname (void ) +{ +if (!hostname_lookup_done && hostname) {#ifndef NO_IPV6 struct addrinfo hints;struct addrinfo *ai;
@@ -569,6 +589,7 @@ static void parse_host_arg(char *extra_args, int buflen) ip_address = xstrdup(addrbuf); }#endif + hostname_lookup_done =1 ; } }
Signature · 1 line
2.3.0
PATCH 2/2 daemon: use callback to build interpolated path
Provide a callback function for strbuf_expand() instead of using the helper strbuf_expand_dict_cb(). While the resulting code is longer, it only looks up the canonical hostname and IP address if at least one of the placeholders %CH and %IP are used with --interpolated-path.
Use a struct for passing the directory to the callback function instead of passing it directly to avoid having to cast away its const qualifier.
--- daemon.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-)
daemon.c +45 -9
@@ -122,6 +122,46 @@ static void NORETURN daemon_die(const char *err, va_list params)exit (1 ); } +static void strbuf_addstr_or_null (struct strbuf *sb,const char *s) +{ +if (s) +strbuf_addstr (sb, s); +} + +struct expand_path_context { +const char *directory; +}; + +static size_t expand_path (struct strbuf *sb,const char *placeholder,void *ctx) +{ +struct expand_path_context *context = ctx; + +switch (placeholder[0 ]) { +case 'H' : +strbuf_addstr_or_null (sb, hostname); +return 1 ; +case 'C' : +if (placeholder[1 ] =='H' ) { +strbuf_addstr_or_null (sb,get_canon_hostname ()); +return 2 ; + } +break ; +case 'I' : +if (placeholder[1 ] =='P' ) { +strbuf_addstr_or_null (sb,get_ip_address ()); +return 2 ; + } +break ; +case 'P' : +strbuf_addstr_or_null (sb, tcp_port); +return 1 ; +case 'D' : +strbuf_addstr (sb, context->directory); +return 1 ; + } +return 0 ; +} +static const char *path_ok (const char *directory) {static char rpath[PATH_MAX ];
@@ -160,14 +200,10 @@ static const char *path_ok(const char *directory) }else if (interpolated_path && saw_extended_args) {struct strbuf expanded_path =STRBUF_INIT ; -struct strbuf_expand_dict_entry dict[6 ]; - - dict[0 ].placeholder ="H" ; dict[0 ].value = hostname; - dict[1 ].placeholder ="CH" ; dict[1 ].value =get_canon_hostname (); - dict[2 ].placeholder ="IP" ; dict[2 ].value =get_ip_address (); - dict[3 ].placeholder ="P" ; dict[3 ].value = tcp_port; - dict[4 ].placeholder ="D" ; dict[4 ].value = directory; - dict[5 ].placeholder =NULL ; dict[5 ].value =NULL ; +struct expand_path_context context; + + context.directory = directory; +if (*dir !='/' ) {/* Allow only absolute */ logerror ("'%s': Non-absolute path denied (interpolated-path active)" , dir);
@@ -175,7 +211,7 @@ static const char *path_ok(const char *directory) }strbuf_expand (&expanded_path, interpolated_path, - strbuf_expand_dict_cb, &dict); + expand_path, &context);strlcpy (interp_path, expanded_path.buf,PATH_MAX );strbuf_release (&expanded_path);loginfo ("Interpolated dir '%s'" , interp_path);
Signature · 1 line
2.3.0