Skip to content

Commit 01cec54

Browse files
rscharfegitster
authored andcommitted
daemon: deglobalize hostname information
Move the variables related to the client-supplied hostname into its own struct, let execute() own an instance of that instead of storing the information in global variables and pass the struct to any function that needs to access it as a parameter. The lifetime of the variables is easier to see this way. Allocated memory is released within execute(). The strbufs don't have to be reset anymore because they are written to only once at most: parse_host_arg() is only called once by execute() and lookup_hostname() guards against being called twice using hostname_lookup_done. Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7a646ce commit 01cec54

File tree

1 file changed

+74
-59
lines changed

1 file changed

+74
-59
lines changed

daemon.c

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ static const char *base_path;
4343
static const char *interpolated_path;
4444
static 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;
5653
static unsigned int timeout;
5754
static 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

8079
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)
124123

125124
struct expand_path_context {
126125
const char *directory;
126+
struct hostinfo *hostinfo;
127127
};
128128

129129
static 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

287289
static 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

658672
static 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

Comments
 (0)