@@ -61,6 +61,22 @@ static char *canon_hostname;
6161static char * ip_address ;
6262static char * tcp_port ;
6363
64+ static int hostname_lookup_done ;
65+
66+ static void lookup_hostname (void );
67+
68+ static const char * get_canon_hostname (void )
69+ {
70+ lookup_hostname ();
71+ return canon_hostname ;
72+ }
73+
74+ static const char * get_ip_address (void )
75+ {
76+ lookup_hostname ();
77+ return ip_address ;
78+ }
79+
6480static void logreport (int priority , const char * err , va_list params )
6581{
6682 if (log_syslog ) {
@@ -106,6 +122,46 @@ static void NORETURN daemon_die(const char *err, va_list params)
106122 exit (1 );
107123}
108124
125+ static void strbuf_addstr_or_null (struct strbuf * sb , const char * s )
126+ {
127+ if (s )
128+ strbuf_addstr (sb , s );
129+ }
130+
131+ struct expand_path_context {
132+ const char * directory ;
133+ };
134+
135+ static size_t expand_path (struct strbuf * sb , const char * placeholder , void * ctx )
136+ {
137+ struct expand_path_context * context = ctx ;
138+
139+ switch (placeholder [0 ]) {
140+ case 'H' :
141+ strbuf_addstr_or_null (sb , hostname );
142+ return 1 ;
143+ case 'C' :
144+ if (placeholder [1 ] == 'H' ) {
145+ strbuf_addstr_or_null (sb , get_canon_hostname ());
146+ return 2 ;
147+ }
148+ break ;
149+ case 'I' :
150+ if (placeholder [1 ] == 'P' ) {
151+ strbuf_addstr_or_null (sb , get_ip_address ());
152+ return 2 ;
153+ }
154+ break ;
155+ case 'P' :
156+ strbuf_addstr_or_null (sb , tcp_port );
157+ return 1 ;
158+ case 'D' :
159+ strbuf_addstr (sb , context -> directory );
160+ return 1 ;
161+ }
162+ return 0 ;
163+ }
164+
109165static const char * path_ok (const char * directory )
110166{
111167 static char rpath [PATH_MAX ];
@@ -144,22 +200,18 @@ static const char *path_ok(const char *directory)
144200 }
145201 else if (interpolated_path && saw_extended_args ) {
146202 struct strbuf expanded_path = STRBUF_INIT ;
147- struct strbuf_expand_dict_entry dict [6 ];
148-
149- dict [0 ].placeholder = "H" ; dict [0 ].value = hostname ;
150- dict [1 ].placeholder = "CH" ; dict [1 ].value = canon_hostname ;
151- dict [2 ].placeholder = "IP" ; dict [2 ].value = ip_address ;
152- dict [3 ].placeholder = "P" ; dict [3 ].value = tcp_port ;
153- dict [4 ].placeholder = "D" ; dict [4 ].value = directory ;
154- dict [5 ].placeholder = NULL ; dict [5 ].value = NULL ;
203+ struct expand_path_context context ;
204+
205+ context .directory = directory ;
206+
155207 if (* dir != '/' ) {
156208 /* Allow only absolute */
157209 logerror ("'%s': Non-absolute path denied (interpolated-path active)" , dir );
158210 return NULL ;
159211 }
160212
161213 strbuf_expand (& expanded_path , interpolated_path ,
162- strbuf_expand_dict_cb , & dict );
214+ expand_path , & context );
163215 strlcpy (interp_path , expanded_path .buf , PATH_MAX );
164216 strbuf_release (& expanded_path );
165217 loginfo ("Interpolated dir '%s'" , interp_path );
@@ -254,8 +306,8 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
254306 * arg ++ = service -> name ;
255307 * arg ++ = path ;
256308 * arg ++ = STRARG (hostname );
257- * arg ++ = STRARG (canon_hostname );
258- * arg ++ = STRARG (ip_address );
309+ * arg ++ = STRARG (get_canon_hostname () );
310+ * arg ++ = STRARG (get_ip_address () );
259311 * arg ++ = STRARG (tcp_port );
260312 * arg = NULL ;
261313#undef STRARG
@@ -548,6 +600,7 @@ static void parse_host_arg(char *extra_args, int buflen)
548600 }
549601 free (hostname );
550602 hostname = canonicalize_client (host );
603+ hostname_lookup_done = 0 ;
551604 }
552605
553606 /* On to the next one */
@@ -556,11 +609,14 @@ static void parse_host_arg(char *extra_args, int buflen)
556609 if (extra_args < end && * extra_args )
557610 die ("Invalid request" );
558611 }
612+ }
559613
560- /*
561- * Locate canonical hostname and its IP address.
562- */
563- if (hostname ) {
614+ /*
615+ * Locate canonical hostname and its IP address.
616+ */
617+ static void lookup_hostname (void )
618+ {
619+ if (!hostname_lookup_done && hostname ) {
564620#ifndef NO_IPV6
565621 struct addrinfo hints ;
566622 struct addrinfo * ai ;
@@ -609,6 +665,7 @@ static void parse_host_arg(char *extra_args, int buflen)
609665 ip_address = xstrdup (addrbuf );
610666 }
611667#endif
668+ hostname_lookup_done = 1 ;
612669 }
613670}
614671
0 commit comments