@@ -43,9 +43,6 @@ static const char *base_path;
4343static const char * interpolated_path ;
4444static int base_path_relaxed ;
4545
46- /* Flag indicating client sent extra args. */
47- static int saw_extended_args ;
48-
4946/* If defined, ~user notation is allowed and the string is inserted
5047 * after ~user/. E.g. a request to git://host/~alice/frotz would
5148 * go to /home/alice/pub_git/frotz with --user-path=pub_git.
@@ -56,25 +53,27 @@ static const char *user_path;
5653static unsigned int timeout ;
5754static unsigned int init_timeout ;
5855
59- static struct strbuf hostname = STRBUF_INIT ;
60- static struct strbuf canon_hostname = STRBUF_INIT ;
61- static struct strbuf ip_address = STRBUF_INIT ;
62- static struct strbuf tcp_port = STRBUF_INIT ;
63-
64- static int hostname_lookup_done ;
56+ struct hostinfo {
57+ struct strbuf hostname ;
58+ struct strbuf canon_hostname ;
59+ struct strbuf ip_address ;
60+ struct strbuf tcp_port ;
61+ unsigned int hostname_lookup_done :1 ;
62+ unsigned int saw_extended_args :1 ;
63+ };
6564
66- static void lookup_hostname (void );
65+ static void lookup_hostname (struct hostinfo * hi );
6766
68- static const char * get_canon_hostname (void )
67+ static const char * get_canon_hostname (struct hostinfo * hi )
6968{
70- lookup_hostname ();
71- return canon_hostname .buf ;
69+ lookup_hostname (hi );
70+ return hi -> canon_hostname .buf ;
7271}
7372
74- static const char * get_ip_address (void )
73+ static const char * get_ip_address (struct hostinfo * hi )
7574{
76- lookup_hostname ();
77- return ip_address .buf ;
75+ lookup_hostname (hi );
76+ return hi -> ip_address .buf ;
7877}
7978
8079static void logreport (int priority , const char * err , va_list params )
@@ -124,30 +123,32 @@ static void NORETURN daemon_die(const char *err, va_list params)
124123
125124struct expand_path_context {
126125 const char * directory ;
126+ struct hostinfo * hostinfo ;
127127};
128128
129129static size_t expand_path (struct strbuf * sb , const char * placeholder , void * ctx )
130130{
131131 struct expand_path_context * context = ctx ;
132+ struct hostinfo * hi = context -> hostinfo ;
132133
133134 switch (placeholder [0 ]) {
134135 case 'H' :
135- strbuf_addbuf (sb , & hostname );
136+ strbuf_addbuf (sb , & hi -> hostname );
136137 return 1 ;
137138 case 'C' :
138139 if (placeholder [1 ] == 'H' ) {
139- strbuf_addstr (sb , get_canon_hostname ());
140+ strbuf_addstr (sb , get_canon_hostname (hi ));
140141 return 2 ;
141142 }
142143 break ;
143144 case 'I' :
144145 if (placeholder [1 ] == 'P' ) {
145- strbuf_addstr (sb , get_ip_address ());
146+ strbuf_addstr (sb , get_ip_address (hi ));
146147 return 2 ;
147148 }
148149 break ;
149150 case 'P' :
150- strbuf_addbuf (sb , & tcp_port );
151+ strbuf_addbuf (sb , & hi -> tcp_port );
151152 return 1 ;
152153 case 'D' :
153154 strbuf_addstr (sb , context -> directory );
@@ -156,7 +157,7 @@ static size_t expand_path(struct strbuf *sb, const char *placeholder, void *ctx)
156157 return 0 ;
157158}
158159
159- static const char * path_ok (const char * directory )
160+ static const char * path_ok (const char * directory , struct hostinfo * hi )
160161{
161162 static char rpath [PATH_MAX ];
162163 static char interp_path [PATH_MAX ];
@@ -192,11 +193,12 @@ static const char *path_ok(const char *directory)
192193 dir = rpath ;
193194 }
194195 }
195- else if (interpolated_path && saw_extended_args ) {
196+ else if (interpolated_path && hi -> saw_extended_args ) {
196197 struct strbuf expanded_path = STRBUF_INIT ;
197198 struct expand_path_context context ;
198199
199200 context .directory = directory ;
201+ context .hostinfo = hi ;
200202
201203 if (* dir != '/' ) {
202204 /* Allow only absolute */
@@ -286,7 +288,8 @@ static int daemon_error(const char *dir, const char *msg)
286288
287289static const char * access_hook ;
288290
289- static int run_access_hook (struct daemon_service * service , const char * dir , const char * path )
291+ static int run_access_hook (struct daemon_service * service , const char * dir ,
292+ const char * path , struct hostinfo * hi )
290293{
291294 struct child_process child = CHILD_PROCESS_INIT ;
292295 struct strbuf buf = STRBUF_INIT ;
@@ -298,10 +301,10 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
298301 * arg ++ = access_hook ;
299302 * arg ++ = service -> name ;
300303 * arg ++ = path ;
301- * arg ++ = hostname .buf ;
302- * arg ++ = get_canon_hostname ();
303- * arg ++ = get_ip_address ();
304- * arg ++ = tcp_port .buf ;
304+ * arg ++ = hi -> hostname .buf ;
305+ * arg ++ = get_canon_hostname (hi );
306+ * arg ++ = get_ip_address (hi );
307+ * arg ++ = hi -> tcp_port .buf ;
305308 * arg = NULL ;
306309
307310 child .use_shell = 1 ;
@@ -346,7 +349,8 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
346349 return -1 ;
347350}
348351
349- static int run_service (const char * dir , struct daemon_service * service )
352+ static int run_service (const char * dir , struct daemon_service * service ,
353+ struct hostinfo * hi )
350354{
351355 const char * path ;
352356 int enabled = service -> enabled ;
@@ -360,7 +364,7 @@ static int run_service(const char *dir, struct daemon_service *service)
360364 return daemon_error (dir , "service not enabled" );
361365 }
362366
363- if (!(path = path_ok (dir )))
367+ if (!(path = path_ok (dir , hi )))
364368 return daemon_error (dir , "no such repository" );
365369
366370 /*
@@ -396,7 +400,7 @@ static int run_service(const char *dir, struct daemon_service *service)
396400 * Optionally, a hook can choose to deny access to the
397401 * repository depending on the phase of the moon.
398402 */
399- if (access_hook && run_access_hook (service , dir , path ))
403+ if (access_hook && run_access_hook (service , dir , path , hi ))
400404 return -1 ;
401405
402406 /*
@@ -561,14 +565,14 @@ static void canonicalize_client(struct strbuf *out, const char *in)
561565/*
562566 * Read the host as supplied by the client connection.
563567 */
564- static void parse_host_arg (char * extra_args , int buflen )
568+ static void parse_host_arg (struct hostinfo * hi , char * extra_args , int buflen )
565569{
566570 char * val ;
567571 int vallen ;
568572 char * end = extra_args + buflen ;
569573
570574 if (extra_args < end && * extra_args ) {
571- saw_extended_args = 1 ;
575+ hi -> saw_extended_args = 1 ;
572576 if (strncasecmp ("host=" , extra_args , 5 ) == 0 ) {
573577 val = extra_args + 5 ;
574578 vallen = strlen (val ) + 1 ;
@@ -577,13 +581,10 @@ static void parse_host_arg(char *extra_args, int buflen)
577581 char * host ;
578582 char * port ;
579583 parse_host_and_port (val , & host , & port );
580- if (port ) {
581- strbuf_reset (& tcp_port );
582- sanitize_client (& tcp_port , port );
583- }
584- strbuf_reset (& hostname );
585- canonicalize_client (& hostname , host );
586- hostname_lookup_done = 0 ;
584+ if (port )
585+ sanitize_client (& hi -> tcp_port , port );
586+ canonicalize_client (& hi -> hostname , host );
587+ hi -> hostname_lookup_done = 0 ;
587588 }
588589
589590 /* On to the next one */
@@ -597,9 +598,9 @@ static void parse_host_arg(char *extra_args, int buflen)
597598/*
598599 * Locate canonical hostname and its IP address.
599600 */
600- static void lookup_hostname (void )
601+ static void lookup_hostname (struct hostinfo * hi )
601602{
602- if (!hostname_lookup_done && hostname .len ) {
603+ if (!hi -> hostname_lookup_done && hi -> hostname .len ) {
603604#ifndef NO_IPV6
604605 struct addrinfo hints ;
605606 struct addrinfo * ai ;
@@ -609,21 +610,20 @@ static void lookup_hostname(void)
609610 memset (& hints , 0 , sizeof (hints ));
610611 hints .ai_flags = AI_CANONNAME ;
611612
612- gai = getaddrinfo (hostname .buf , NULL , & hints , & ai );
613+ gai = getaddrinfo (hi -> hostname .buf , NULL , & hints , & ai );
613614 if (!gai ) {
614615 struct sockaddr_in * sin_addr = (void * )ai -> ai_addr ;
615616
616617 inet_ntop (AF_INET , & sin_addr -> sin_addr ,
617618 addrbuf , sizeof (addrbuf ));
618- strbuf_reset (& ip_address );
619- strbuf_addstr (& ip_address , addrbuf );
619+ strbuf_addstr (& hi -> ip_address , addrbuf );
620620
621- strbuf_reset (& canon_hostname );
622621 if (ai -> ai_canonname )
623- sanitize_client (& canon_hostname ,
622+ sanitize_client (& hi -> canon_hostname ,
624623 ai -> ai_canonname );
625624 else
626- strbuf_addbuf (& canon_hostname , & ip_address );
625+ strbuf_addbuf (& hi -> canon_hostname ,
626+ & hi -> ip_address );
627627
628628 freeaddrinfo (ai );
629629 }
@@ -644,22 +644,39 @@ static void lookup_hostname(void)
644644 inet_ntop (hent -> h_addrtype , & sa .sin_addr ,
645645 addrbuf , sizeof (addrbuf ));
646646
647- strbuf_reset (& canon_hostname );
648- sanitize_client (& canon_hostname , hent -> h_name );
649- strbuf_reset (& ip_address );
650- strbuf_addstr (& ip_address , addrbuf );
647+ sanitize_client (& hi -> canon_hostname , hent -> h_name );
648+ strbuf_addstr (& hi -> ip_address , addrbuf );
651649 }
652650#endif
653- hostname_lookup_done = 1 ;
651+ hi -> hostname_lookup_done = 1 ;
654652 }
655653}
656654
655+ static void hostinfo_init (struct hostinfo * hi )
656+ {
657+ memset (hi , 0 , sizeof (* hi ));
658+ strbuf_init (& hi -> hostname , 0 );
659+ strbuf_init (& hi -> canon_hostname , 0 );
660+ strbuf_init (& hi -> ip_address , 0 );
661+ strbuf_init (& hi -> tcp_port , 0 );
662+ }
663+
664+ static void hostinfo_clear (struct hostinfo * hi )
665+ {
666+ strbuf_release (& hi -> hostname );
667+ strbuf_release (& hi -> canon_hostname );
668+ strbuf_release (& hi -> ip_address );
669+ strbuf_release (& hi -> tcp_port );
670+ }
657671
658672static int execute (void )
659673{
660674 char * line = packet_buffer ;
661675 int pktlen , len , i ;
662676 char * addr = getenv ("REMOTE_ADDR" ), * port = getenv ("REMOTE_PORT" );
677+ struct hostinfo hi ;
678+
679+ hostinfo_init (& hi );
663680
664681 if (addr )
665682 loginfo ("Connection from %s:%s" , addr , port );
@@ -678,13 +695,8 @@ static int execute(void)
678695 pktlen -- ;
679696 }
680697
681- strbuf_release (& hostname );
682- strbuf_release (& canon_hostname );
683- strbuf_release (& ip_address );
684- strbuf_release (& tcp_port );
685-
686698 if (len != pktlen )
687- parse_host_arg (line + len + 1 , pktlen - len - 1 );
699+ parse_host_arg (& hi , line + len + 1 , pktlen - len - 1 );
688700
689701 for (i = 0 ; i < ARRAY_SIZE (daemon_service ); i ++ ) {
690702 struct daemon_service * s = & (daemon_service [i ]);
@@ -697,10 +709,13 @@ static int execute(void)
697709 * Note: The directory here is probably context sensitive,
698710 * and might depend on the actual service being performed.
699711 */
700- return run_service (arg , s );
712+ int rc = run_service (arg , s , & hi );
713+ hostinfo_clear (& hi );
714+ return rc ;
701715 }
702716 }
703717
718+ hostinfo_clear (& hi );
704719 logerror ("Protocol error: '%s'" , line );
705720 return -1 ;
706721}
0 commit comments