@@ -43,9 +43,6 @@ static const char *base_path;
43
43
static const char * interpolated_path ;
44
44
static int base_path_relaxed ;
45
45
46
- /* Flag indicating client sent extra args. */
47
- static int saw_extended_args ;
48
-
49
46
/* If defined, ~user notation is allowed and the string is inserted
50
47
* after ~user/. E.g. a request to git://host/~alice/frotz would
51
48
* go to /home/alice/pub_git/frotz with --user-path=pub_git.
@@ -56,25 +53,27 @@ static const char *user_path;
56
53
static unsigned int timeout ;
57
54
static unsigned int init_timeout ;
58
55
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
+ };
65
64
66
- static void lookup_hostname (void );
65
+ static void lookup_hostname (struct hostinfo * hi );
67
66
68
- static const char * get_canon_hostname (void )
67
+ static const char * get_canon_hostname (struct hostinfo * hi )
69
68
{
70
- lookup_hostname ();
71
- return canon_hostname .buf ;
69
+ lookup_hostname (hi );
70
+ return hi -> canon_hostname .buf ;
72
71
}
73
72
74
- static const char * get_ip_address (void )
73
+ static const char * get_ip_address (struct hostinfo * hi )
75
74
{
76
- lookup_hostname ();
77
- return ip_address .buf ;
75
+ lookup_hostname (hi );
76
+ return hi -> ip_address .buf ;
78
77
}
79
78
80
79
static 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)
124
123
125
124
struct expand_path_context {
126
125
const char * directory ;
126
+ struct hostinfo * hostinfo ;
127
127
};
128
128
129
129
static size_t expand_path (struct strbuf * sb , const char * placeholder , void * ctx )
130
130
{
131
131
struct expand_path_context * context = ctx ;
132
+ struct hostinfo * hi = context -> hostinfo ;
132
133
133
134
switch (placeholder [0 ]) {
134
135
case 'H' :
135
- strbuf_addbuf (sb , & hostname );
136
+ strbuf_addbuf (sb , & hi -> hostname );
136
137
return 1 ;
137
138
case 'C' :
138
139
if (placeholder [1 ] == 'H' ) {
139
- strbuf_addstr (sb , get_canon_hostname ());
140
+ strbuf_addstr (sb , get_canon_hostname (hi ));
140
141
return 2 ;
141
142
}
142
143
break ;
143
144
case 'I' :
144
145
if (placeholder [1 ] == 'P' ) {
145
- strbuf_addstr (sb , get_ip_address ());
146
+ strbuf_addstr (sb , get_ip_address (hi ));
146
147
return 2 ;
147
148
}
148
149
break ;
149
150
case 'P' :
150
- strbuf_addbuf (sb , & tcp_port );
151
+ strbuf_addbuf (sb , & hi -> tcp_port );
151
152
return 1 ;
152
153
case 'D' :
153
154
strbuf_addstr (sb , context -> directory );
@@ -156,7 +157,7 @@ static size_t expand_path(struct strbuf *sb, const char *placeholder, void *ctx)
156
157
return 0 ;
157
158
}
158
159
159
- static const char * path_ok (const char * directory )
160
+ static const char * path_ok (const char * directory , struct hostinfo * hi )
160
161
{
161
162
static char rpath [PATH_MAX ];
162
163
static char interp_path [PATH_MAX ];
@@ -192,11 +193,12 @@ static const char *path_ok(const char *directory)
192
193
dir = rpath ;
193
194
}
194
195
}
195
- else if (interpolated_path && saw_extended_args ) {
196
+ else if (interpolated_path && hi -> saw_extended_args ) {
196
197
struct strbuf expanded_path = STRBUF_INIT ;
197
198
struct expand_path_context context ;
198
199
199
200
context .directory = directory ;
201
+ context .hostinfo = hi ;
200
202
201
203
if (* dir != '/' ) {
202
204
/* Allow only absolute */
@@ -286,7 +288,8 @@ static int daemon_error(const char *dir, const char *msg)
286
288
287
289
static const char * access_hook ;
288
290
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 )
290
293
{
291
294
struct child_process child = CHILD_PROCESS_INIT ;
292
295
struct strbuf buf = STRBUF_INIT ;
@@ -298,10 +301,10 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
298
301
* arg ++ = access_hook ;
299
302
* arg ++ = service -> name ;
300
303
* 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 ;
305
308
* arg = NULL ;
306
309
307
310
child .use_shell = 1 ;
@@ -346,7 +349,8 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
346
349
return -1 ;
347
350
}
348
351
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 )
350
354
{
351
355
const char * path ;
352
356
int enabled = service -> enabled ;
@@ -360,7 +364,7 @@ static int run_service(const char *dir, struct daemon_service *service)
360
364
return daemon_error (dir , "service not enabled" );
361
365
}
362
366
363
- if (!(path = path_ok (dir )))
367
+ if (!(path = path_ok (dir , hi )))
364
368
return daemon_error (dir , "no such repository" );
365
369
366
370
/*
@@ -396,7 +400,7 @@ static int run_service(const char *dir, struct daemon_service *service)
396
400
* Optionally, a hook can choose to deny access to the
397
401
* repository depending on the phase of the moon.
398
402
*/
399
- if (access_hook && run_access_hook (service , dir , path ))
403
+ if (access_hook && run_access_hook (service , dir , path , hi ))
400
404
return -1 ;
401
405
402
406
/*
@@ -561,14 +565,14 @@ static void canonicalize_client(struct strbuf *out, const char *in)
561
565
/*
562
566
* Read the host as supplied by the client connection.
563
567
*/
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 )
565
569
{
566
570
char * val ;
567
571
int vallen ;
568
572
char * end = extra_args + buflen ;
569
573
570
574
if (extra_args < end && * extra_args ) {
571
- saw_extended_args = 1 ;
575
+ hi -> saw_extended_args = 1 ;
572
576
if (strncasecmp ("host=" , extra_args , 5 ) == 0 ) {
573
577
val = extra_args + 5 ;
574
578
vallen = strlen (val ) + 1 ;
@@ -577,13 +581,10 @@ static void parse_host_arg(char *extra_args, int buflen)
577
581
char * host ;
578
582
char * port ;
579
583
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 ;
587
588
}
588
589
589
590
/* On to the next one */
@@ -597,9 +598,9 @@ static void parse_host_arg(char *extra_args, int buflen)
597
598
/*
598
599
* Locate canonical hostname and its IP address.
599
600
*/
600
- static void lookup_hostname (void )
601
+ static void lookup_hostname (struct hostinfo * hi )
601
602
{
602
- if (!hostname_lookup_done && hostname .len ) {
603
+ if (!hi -> hostname_lookup_done && hi -> hostname .len ) {
603
604
#ifndef NO_IPV6
604
605
struct addrinfo hints ;
605
606
struct addrinfo * ai ;
@@ -609,21 +610,20 @@ static void lookup_hostname(void)
609
610
memset (& hints , 0 , sizeof (hints ));
610
611
hints .ai_flags = AI_CANONNAME ;
611
612
612
- gai = getaddrinfo (hostname .buf , NULL , & hints , & ai );
613
+ gai = getaddrinfo (hi -> hostname .buf , NULL , & hints , & ai );
613
614
if (!gai ) {
614
615
struct sockaddr_in * sin_addr = (void * )ai -> ai_addr ;
615
616
616
617
inet_ntop (AF_INET , & sin_addr -> sin_addr ,
617
618
addrbuf , sizeof (addrbuf ));
618
- strbuf_reset (& ip_address );
619
- strbuf_addstr (& ip_address , addrbuf );
619
+ strbuf_addstr (& hi -> ip_address , addrbuf );
620
620
621
- strbuf_reset (& canon_hostname );
622
621
if (ai -> ai_canonname )
623
- sanitize_client (& canon_hostname ,
622
+ sanitize_client (& hi -> canon_hostname ,
624
623
ai -> ai_canonname );
625
624
else
626
- strbuf_addbuf (& canon_hostname , & ip_address );
625
+ strbuf_addbuf (& hi -> canon_hostname ,
626
+ & hi -> ip_address );
627
627
628
628
freeaddrinfo (ai );
629
629
}
@@ -644,22 +644,39 @@ static void lookup_hostname(void)
644
644
inet_ntop (hent -> h_addrtype , & sa .sin_addr ,
645
645
addrbuf , sizeof (addrbuf ));
646
646
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 );
651
649
}
652
650
#endif
653
- hostname_lookup_done = 1 ;
651
+ hi -> hostname_lookup_done = 1 ;
654
652
}
655
653
}
656
654
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
+ }
657
671
658
672
static int execute (void )
659
673
{
660
674
char * line = packet_buffer ;
661
675
int pktlen , len , i ;
662
676
char * addr = getenv ("REMOTE_ADDR" ), * port = getenv ("REMOTE_PORT" );
677
+ struct hostinfo hi ;
678
+
679
+ hostinfo_init (& hi );
663
680
664
681
if (addr )
665
682
loginfo ("Connection from %s:%s" , addr , port );
@@ -678,13 +695,8 @@ static int execute(void)
678
695
pktlen -- ;
679
696
}
680
697
681
- strbuf_release (& hostname );
682
- strbuf_release (& canon_hostname );
683
- strbuf_release (& ip_address );
684
- strbuf_release (& tcp_port );
685
-
686
698
if (len != pktlen )
687
- parse_host_arg (line + len + 1 , pktlen - len - 1 );
699
+ parse_host_arg (& hi , line + len + 1 , pktlen - len - 1 );
688
700
689
701
for (i = 0 ; i < ARRAY_SIZE (daemon_service ); i ++ ) {
690
702
struct daemon_service * s = & (daemon_service [i ]);
@@ -697,10 +709,13 @@ static int execute(void)
697
709
* Note: The directory here is probably context sensitive,
698
710
* and might depend on the actual service being performed.
699
711
*/
700
- return run_service (arg , s );
712
+ int rc = run_service (arg , s , & hi );
713
+ hostinfo_clear (& hi );
714
+ return rc ;
701
715
}
702
716
}
703
717
718
+ hostinfo_clear (& hi );
704
719
logerror ("Protocol error: '%s'" , line );
705
720
return -1 ;
706
721
}
0 commit comments