Blame


1 8a35f56c 2022-07-16 thomas /*
2 8a35f56c 2022-07-16 thomas * Copyright (c) 2016-2019, 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 8a35f56c 2022-07-16 thomas * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
4 8a35f56c 2022-07-16 thomas * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
5 8a35f56c 2022-07-16 thomas * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
6 8a35f56c 2022-07-16 thomas * Copyright (c) 2001 Markus Friedl. All rights reserved.
7 8a35f56c 2022-07-16 thomas * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
8 8a35f56c 2022-07-16 thomas * Copyright (c) 2001 Theo de Raadt. All rights reserved.
9 8a35f56c 2022-07-16 thomas *
10 8a35f56c 2022-07-16 thomas * Permission to use, copy, modify, and distribute this software for any
11 8a35f56c 2022-07-16 thomas * purpose with or without fee is hereby granted, provided that the above
12 8a35f56c 2022-07-16 thomas * copyright notice and this permission notice appear in all copies.
13 8a35f56c 2022-07-16 thomas *
14 8a35f56c 2022-07-16 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 8a35f56c 2022-07-16 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 8a35f56c 2022-07-16 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 8a35f56c 2022-07-16 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 8a35f56c 2022-07-16 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 8a35f56c 2022-07-16 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 8a35f56c 2022-07-16 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 8a35f56c 2022-07-16 thomas */
22 8a35f56c 2022-07-16 thomas
23 8a35f56c 2022-07-16 thomas %{
24 4fccd2fe 2023-03-08 thomas #include "got_compat.h"
25 4fccd2fe 2023-03-08 thomas
26 8a35f56c 2022-07-16 thomas #include <sys/ioctl.h>
27 8a35f56c 2022-07-16 thomas #include <sys/types.h>
28 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
29 8a35f56c 2022-07-16 thomas #include <sys/socket.h>
30 8a35f56c 2022-07-16 thomas #include <sys/stat.h>
31 8a35f56c 2022-07-16 thomas
32 8a35f56c 2022-07-16 thomas #include <net/if.h>
33 8a35f56c 2022-07-16 thomas #include <netinet/in.h>
34 8a35f56c 2022-07-16 thomas
35 8a35f56c 2022-07-16 thomas #include <arpa/inet.h>
36 8a35f56c 2022-07-16 thomas
37 8a35f56c 2022-07-16 thomas #include <ctype.h>
38 8a35f56c 2022-07-16 thomas #include <err.h>
39 8a35f56c 2022-07-16 thomas #include <errno.h>
40 8a35f56c 2022-07-16 thomas #include <event.h>
41 8a35f56c 2022-07-16 thomas #include <ifaddrs.h>
42 8a35f56c 2022-07-16 thomas #include <limits.h>
43 8a35f56c 2022-07-16 thomas #include <netdb.h>
44 8a35f56c 2022-07-16 thomas #include <stdarg.h>
45 8a35f56c 2022-07-16 thomas #include <stdlib.h>
46 8a35f56c 2022-07-16 thomas #include <stdio.h>
47 8a35f56c 2022-07-16 thomas #include <string.h>
48 8a35f56c 2022-07-16 thomas #include <syslog.h>
49 8a35f56c 2022-07-16 thomas #include <unistd.h>
50 161663e7 2023-03-11 thomas
51 161663e7 2023-03-11 thomas #include "got_reference.h"
52 8a35f56c 2022-07-16 thomas
53 8a35f56c 2022-07-16 thomas #include "gotwebd.h"
54 8a35f56c 2022-07-16 thomas
55 8a35f56c 2022-07-16 thomas TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
56 8a35f56c 2022-07-16 thomas static struct file {
57 8a35f56c 2022-07-16 thomas TAILQ_ENTRY(file) entry;
58 8a35f56c 2022-07-16 thomas FILE *stream;
59 8a35f56c 2022-07-16 thomas char *name;
60 8a35f56c 2022-07-16 thomas int lineno;
61 8a35f56c 2022-07-16 thomas int errors;
62 8a35f56c 2022-07-16 thomas } *file;
63 8a35f56c 2022-07-16 thomas struct file *newfile(const char *, int);
64 8a35f56c 2022-07-16 thomas static void closefile(struct file *);
65 8a35f56c 2022-07-16 thomas int check_file_secrecy(int, const char *);
66 8a35f56c 2022-07-16 thomas int yyparse(void);
67 8a35f56c 2022-07-16 thomas int yylex(void);
68 8a35f56c 2022-07-16 thomas int yyerror(const char *, ...)
69 8a35f56c 2022-07-16 thomas __attribute__((__format__ (printf, 1, 2)))
70 8a35f56c 2022-07-16 thomas __attribute__((__nonnull__ (1)));
71 8a35f56c 2022-07-16 thomas int kw_cmp(const void *, const void *);
72 8a35f56c 2022-07-16 thomas int lookup(char *);
73 8a35f56c 2022-07-16 thomas int lgetc(int);
74 8a35f56c 2022-07-16 thomas int lungetc(int);
75 8a35f56c 2022-07-16 thomas int findeol(void);
76 8a35f56c 2022-07-16 thomas
77 8a35f56c 2022-07-16 thomas TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
78 8a35f56c 2022-07-16 thomas struct sym {
79 8a35f56c 2022-07-16 thomas TAILQ_ENTRY(sym) entry;
80 8a35f56c 2022-07-16 thomas int used;
81 8a35f56c 2022-07-16 thomas int persist;
82 8a35f56c 2022-07-16 thomas char *nam;
83 8a35f56c 2022-07-16 thomas char *val;
84 8a35f56c 2022-07-16 thomas };
85 8a35f56c 2022-07-16 thomas
86 8a35f56c 2022-07-16 thomas int symset(const char *, const char *, int);
87 8a35f56c 2022-07-16 thomas char *symget(const char *);
88 8a35f56c 2022-07-16 thomas
89 8a35f56c 2022-07-16 thomas static int errors;
90 8a35f56c 2022-07-16 thomas
91 8a35f56c 2022-07-16 thomas static struct gotwebd *gotwebd;
92 8a35f56c 2022-07-16 thomas static struct server *new_srv;
93 8a35f56c 2022-07-16 thomas static struct server *conf_new_server(const char *);
94 8a35f56c 2022-07-16 thomas int getservice(const char *);
95 8a35f56c 2022-07-16 thomas int n;
96 8a35f56c 2022-07-16 thomas
97 e760210d 2023-11-16 thomas int get_addrs(const char *, const char *, struct server *);
98 e4c7e0b0 2022-08-30 thomas int addr_dup_check(struct addresslist *, struct address *,
99 e4c7e0b0 2022-08-30 thomas const char *, const char *);
100 e4c7e0b0 2022-08-30 thomas int add_addr(struct server *, struct address *);
101 8a35f56c 2022-07-16 thomas
102 8a35f56c 2022-07-16 thomas typedef struct {
103 8a35f56c 2022-07-16 thomas union {
104 8a35f56c 2022-07-16 thomas long long number;
105 8a35f56c 2022-07-16 thomas char *string;
106 8a35f56c 2022-07-16 thomas } v;
107 8a35f56c 2022-07-16 thomas int lineno;
108 8a35f56c 2022-07-16 thomas } YYSTYPE;
109 8a35f56c 2022-07-16 thomas
110 8a35f56c 2022-07-16 thomas %}
111 8a35f56c 2022-07-16 thomas
112 c6c5c5fd 2023-12-30 thomas %token LISTEN WWW_PATH SITE_NAME SITE_OWNER SITE_LINK LOGO
113 8a35f56c 2022-07-16 thomas %token LOGO_URL SHOW_REPO_OWNER SHOW_REPO_AGE SHOW_REPO_DESCRIPTION
114 8a35f56c 2022-07-16 thomas %token MAX_REPOS_DISPLAY REPOS_PATH MAX_COMMITS_DISPLAY ON ERROR
115 3991b2a5 2022-10-31 thomas %token SHOW_SITE_OWNER SHOW_REPO_CLONEURL PORT PREFORK RESPECT_EXPORTOK
116 bea82c4f 2023-01-06 thomas %token UNIX_SOCKET UNIX_SOCKET_NAME SERVER CHROOT CUSTOM_CSS SOCKET
117 e85a14fa 2023-12-30 thomas %token SUMMARY_COMMITS_DISPLAY SUMMARY_TAGS_DISPLAY
118 8a35f56c 2022-07-16 thomas
119 8a35f56c 2022-07-16 thomas %token <v.string> STRING
120 8a35f56c 2022-07-16 thomas %token <v.number> NUMBER
121 8a35f56c 2022-07-16 thomas %type <v.number> boolean
122 61bbe977 2023-11-16 thomas %type <v.string> listen_addr
123 8a35f56c 2022-07-16 thomas
124 8a35f56c 2022-07-16 thomas %%
125 8a35f56c 2022-07-16 thomas
126 cfab1835 2022-10-04 thomas grammar : /* empty */
127 8a35f56c 2022-07-16 thomas | grammar '\n'
128 cfab1835 2022-10-04 thomas | grammar varset '\n'
129 8a35f56c 2022-07-16 thomas | grammar main '\n'
130 8a35f56c 2022-07-16 thomas | grammar server '\n'
131 cfab1835 2022-10-04 thomas | grammar error '\n' { file->errors++; }
132 cfab1835 2022-10-04 thomas ;
133 cfab1835 2022-10-04 thomas
134 cfab1835 2022-10-04 thomas varset : STRING '=' STRING {
135 cfab1835 2022-10-04 thomas char *s = $1;
136 cfab1835 2022-10-04 thomas while (*s++) {
137 cfab1835 2022-10-04 thomas if (isspace((unsigned char)*s)) {
138 cfab1835 2022-10-04 thomas yyerror("macro name cannot contain "
139 cfab1835 2022-10-04 thomas "whitespace");
140 cfab1835 2022-10-04 thomas free($1);
141 cfab1835 2022-10-04 thomas free($3);
142 cfab1835 2022-10-04 thomas YYERROR;
143 cfab1835 2022-10-04 thomas }
144 cfab1835 2022-10-04 thomas }
145 cfab1835 2022-10-04 thomas if (symset($1, $3, 0) == -1)
146 cfab1835 2022-10-04 thomas fatal("cannot store variable");
147 cfab1835 2022-10-04 thomas free($1);
148 cfab1835 2022-10-04 thomas free($3);
149 cfab1835 2022-10-04 thomas }
150 8a35f56c 2022-07-16 thomas ;
151 8a35f56c 2022-07-16 thomas
152 8a35f56c 2022-07-16 thomas boolean : STRING {
153 8a35f56c 2022-07-16 thomas if (strcasecmp($1, "1") == 0 ||
154 8a35f56c 2022-07-16 thomas strcasecmp($1, "on") == 0)
155 8a35f56c 2022-07-16 thomas $$ = 1;
156 8a35f56c 2022-07-16 thomas else if (strcasecmp($1, "0") == 0 ||
157 ee003af8 2023-06-15 thomas strcasecmp($1, "off") == 0)
158 8a35f56c 2022-07-16 thomas $$ = 0;
159 8a35f56c 2022-07-16 thomas else {
160 8a35f56c 2022-07-16 thomas yyerror("invalid boolean value '%s'", $1);
161 8a35f56c 2022-07-16 thomas free($1);
162 8a35f56c 2022-07-16 thomas YYERROR;
163 8a35f56c 2022-07-16 thomas }
164 8a35f56c 2022-07-16 thomas free($1);
165 8a35f56c 2022-07-16 thomas }
166 8a35f56c 2022-07-16 thomas | ON { $$ = 1; }
167 a0bd573d 2023-06-15 thomas | NUMBER {
168 a0bd573d 2023-06-15 thomas if ($1 != 0 && $1 != 1) {
169 a0bd573d 2023-06-15 thomas yyerror("invalid boolean value '%lld'", $1);
170 a0bd573d 2023-06-15 thomas YYERROR;
171 a0bd573d 2023-06-15 thomas }
172 a0bd573d 2023-06-15 thomas $$ = $1;
173 a0bd573d 2023-06-15 thomas }
174 61bbe977 2023-11-16 thomas ;
175 61bbe977 2023-11-16 thomas
176 61bbe977 2023-11-16 thomas listen_addr : '*' { $$ = NULL; }
177 61bbe977 2023-11-16 thomas | STRING
178 8a35f56c 2022-07-16 thomas ;
179 8a35f56c 2022-07-16 thomas
180 8a35f56c 2022-07-16 thomas main : PREFORK NUMBER {
181 a0bd573d 2023-06-15 thomas if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
182 a0bd573d 2023-06-15 thomas yyerror("prefork is %s: %lld",
183 a0bd573d 2023-06-15 thomas $2 <= 0 ? "too small" : "too large", $2);
184 a0bd573d 2023-06-15 thomas YYERROR;
185 a0bd573d 2023-06-15 thomas }
186 8a35f56c 2022-07-16 thomas gotwebd->prefork_gotwebd = $2;
187 8a35f56c 2022-07-16 thomas }
188 8a35f56c 2022-07-16 thomas | CHROOT STRING {
189 90757f0a 2023-06-15 thomas if (*$2 == '\0') {
190 90757f0a 2023-06-15 thomas yyerror("chroot path can't be an empty"
191 90757f0a 2023-06-15 thomas " string");
192 90757f0a 2023-06-15 thomas free($2);
193 90757f0a 2023-06-15 thomas YYERROR;
194 90757f0a 2023-06-15 thomas }
195 90757f0a 2023-06-15 thomas
196 8a35f56c 2022-07-16 thomas n = strlcpy(gotwebd->httpd_chroot, $2,
197 8a35f56c 2022-07-16 thomas sizeof(gotwebd->httpd_chroot));
198 8a35f56c 2022-07-16 thomas if (n >= sizeof(gotwebd->httpd_chroot)) {
199 8a35f56c 2022-07-16 thomas yyerror("%s: httpd_chroot truncated", __func__);
200 8a35f56c 2022-07-16 thomas free($2);
201 8a35f56c 2022-07-16 thomas YYERROR;
202 8a35f56c 2022-07-16 thomas }
203 8a35f56c 2022-07-16 thomas free($2);
204 8a35f56c 2022-07-16 thomas }
205 8a35f56c 2022-07-16 thomas | UNIX_SOCKET boolean {
206 8a35f56c 2022-07-16 thomas gotwebd->unix_socket = $2;
207 8a35f56c 2022-07-16 thomas }
208 8a35f56c 2022-07-16 thomas | UNIX_SOCKET_NAME STRING {
209 8a35f56c 2022-07-16 thomas n = snprintf(gotwebd->unix_socket_name,
210 8a35f56c 2022-07-16 thomas sizeof(gotwebd->unix_socket_name), "%s%s",
211 0b16f49b 2023-06-22 thomas gotwebd->httpd_chroot, $2);
212 717a78d4 2022-08-16 thomas if (n < 0 ||
213 717a78d4 2022-08-16 thomas (size_t)n >= sizeof(gotwebd->unix_socket_name)) {
214 8a35f56c 2022-07-16 thomas yyerror("%s: unix_socket_name truncated",
215 8a35f56c 2022-07-16 thomas __func__);
216 8a35f56c 2022-07-16 thomas free($2);
217 8a35f56c 2022-07-16 thomas YYERROR;
218 8a35f56c 2022-07-16 thomas }
219 8a35f56c 2022-07-16 thomas free($2);
220 8a35f56c 2022-07-16 thomas }
221 8a35f56c 2022-07-16 thomas ;
222 8a35f56c 2022-07-16 thomas
223 8a35f56c 2022-07-16 thomas server : SERVER STRING {
224 8a35f56c 2022-07-16 thomas struct server *srv;
225 8a35f56c 2022-07-16 thomas
226 90d63d47 2022-08-16 thomas TAILQ_FOREACH(srv, &gotwebd->servers, entry) {
227 8a35f56c 2022-07-16 thomas if (strcmp(srv->name, $2) == 0) {
228 8a35f56c 2022-07-16 thomas yyerror("server name exists '%s'", $2);
229 8a35f56c 2022-07-16 thomas free($2);
230 8a35f56c 2022-07-16 thomas YYERROR;
231 8a35f56c 2022-07-16 thomas }
232 8a35f56c 2022-07-16 thomas }
233 8a35f56c 2022-07-16 thomas
234 8a35f56c 2022-07-16 thomas new_srv = conf_new_server($2);
235 8a35f56c 2022-07-16 thomas log_debug("adding server %s", $2);
236 8a35f56c 2022-07-16 thomas free($2);
237 8a35f56c 2022-07-16 thomas }
238 8a35f56c 2022-07-16 thomas | SERVER STRING {
239 8a35f56c 2022-07-16 thomas struct server *srv;
240 8a35f56c 2022-07-16 thomas
241 90d63d47 2022-08-16 thomas TAILQ_FOREACH(srv, &gotwebd->servers, entry) {
242 8a35f56c 2022-07-16 thomas if (strcmp(srv->name, $2) == 0) {
243 8a35f56c 2022-07-16 thomas yyerror("server name exists '%s'", $2);
244 8a35f56c 2022-07-16 thomas free($2);
245 8a35f56c 2022-07-16 thomas YYERROR;
246 8a35f56c 2022-07-16 thomas }
247 8a35f56c 2022-07-16 thomas }
248 8a35f56c 2022-07-16 thomas
249 8a35f56c 2022-07-16 thomas new_srv = conf_new_server($2);
250 8a35f56c 2022-07-16 thomas log_debug("adding server %s", $2);
251 8a35f56c 2022-07-16 thomas free($2);
252 8a35f56c 2022-07-16 thomas } '{' optnl serveropts2 '}' {
253 8a35f56c 2022-07-16 thomas }
254 8a35f56c 2022-07-16 thomas ;
255 8a35f56c 2022-07-16 thomas
256 8a35f56c 2022-07-16 thomas serveropts1 : REPOS_PATH STRING {
257 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->repos_path, $2,
258 8a35f56c 2022-07-16 thomas sizeof(new_srv->repos_path));
259 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->repos_path)) {
260 8a35f56c 2022-07-16 thomas yyerror("%s: repos_path truncated", __func__);
261 8a35f56c 2022-07-16 thomas free($2);
262 8a35f56c 2022-07-16 thomas YYERROR;
263 8a35f56c 2022-07-16 thomas }
264 8a35f56c 2022-07-16 thomas free($2);
265 8a35f56c 2022-07-16 thomas }
266 8a35f56c 2022-07-16 thomas | SITE_NAME STRING {
267 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->site_name, $2,
268 8a35f56c 2022-07-16 thomas sizeof(new_srv->site_name));
269 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->site_name)) {
270 8a35f56c 2022-07-16 thomas yyerror("%s: site_name truncated", __func__);
271 8a35f56c 2022-07-16 thomas free($2);
272 8a35f56c 2022-07-16 thomas YYERROR;
273 8a35f56c 2022-07-16 thomas }
274 8a35f56c 2022-07-16 thomas free($2);
275 8a35f56c 2022-07-16 thomas }
276 8a35f56c 2022-07-16 thomas | SITE_OWNER STRING {
277 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->site_owner, $2,
278 8a35f56c 2022-07-16 thomas sizeof(new_srv->site_owner));
279 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->site_owner)) {
280 8a35f56c 2022-07-16 thomas yyerror("%s: site_owner truncated", __func__);
281 8a35f56c 2022-07-16 thomas free($2);
282 8a35f56c 2022-07-16 thomas YYERROR;
283 8a35f56c 2022-07-16 thomas }
284 8a35f56c 2022-07-16 thomas free($2);
285 8a35f56c 2022-07-16 thomas }
286 8a35f56c 2022-07-16 thomas | SITE_LINK STRING {
287 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->site_link, $2,
288 8a35f56c 2022-07-16 thomas sizeof(new_srv->site_link));
289 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->site_link)) {
290 8a35f56c 2022-07-16 thomas yyerror("%s: site_link truncated", __func__);
291 8a35f56c 2022-07-16 thomas free($2);
292 8a35f56c 2022-07-16 thomas YYERROR;
293 8a35f56c 2022-07-16 thomas }
294 8a35f56c 2022-07-16 thomas free($2);
295 8a35f56c 2022-07-16 thomas }
296 8a35f56c 2022-07-16 thomas | LOGO STRING {
297 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->logo, $2, sizeof(new_srv->logo));
298 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->logo)) {
299 8a35f56c 2022-07-16 thomas yyerror("%s: logo truncated", __func__);
300 8a35f56c 2022-07-16 thomas free($2);
301 8a35f56c 2022-07-16 thomas YYERROR;
302 8a35f56c 2022-07-16 thomas }
303 8a35f56c 2022-07-16 thomas free($2);
304 8a35f56c 2022-07-16 thomas }
305 8a35f56c 2022-07-16 thomas | LOGO_URL STRING {
306 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->logo_url, $2,
307 8a35f56c 2022-07-16 thomas sizeof(new_srv->logo_url));
308 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->logo_url)) {
309 8a35f56c 2022-07-16 thomas yyerror("%s: logo_url truncated", __func__);
310 8a35f56c 2022-07-16 thomas free($2);
311 8a35f56c 2022-07-16 thomas YYERROR;
312 8a35f56c 2022-07-16 thomas }
313 8a35f56c 2022-07-16 thomas free($2);
314 8a35f56c 2022-07-16 thomas }
315 8a35f56c 2022-07-16 thomas | CUSTOM_CSS STRING {
316 8a35f56c 2022-07-16 thomas n = strlcpy(new_srv->custom_css, $2,
317 8a35f56c 2022-07-16 thomas sizeof(new_srv->custom_css));
318 8a35f56c 2022-07-16 thomas if (n >= sizeof(new_srv->custom_css)) {
319 8a35f56c 2022-07-16 thomas yyerror("%s: custom_css truncated", __func__);
320 8a35f56c 2022-07-16 thomas free($2);
321 8a35f56c 2022-07-16 thomas YYERROR;
322 8a35f56c 2022-07-16 thomas }
323 8a35f56c 2022-07-16 thomas free($2);
324 8a35f56c 2022-07-16 thomas }
325 e760210d 2023-11-16 thomas | LISTEN ON listen_addr PORT STRING {
326 e760210d 2023-11-16 thomas if (get_addrs($3, $5, new_srv) == -1) {
327 e4c7e0b0 2022-08-30 thomas yyerror("could not get addrs");
328 77fb808d 2022-08-29 thomas YYERROR;
329 77fb808d 2022-08-29 thomas }
330 e760210d 2023-11-16 thomas free($3);
331 e760210d 2023-11-16 thomas free($5);
332 e4317279 2022-08-30 thomas new_srv->fcgi_socket = 1;
333 77fb808d 2022-08-29 thomas }
334 e760210d 2023-11-16 thomas | LISTEN ON listen_addr PORT NUMBER {
335 e760210d 2023-11-16 thomas char portno[32];
336 e760210d 2023-11-16 thomas int n;
337 e760210d 2023-11-16 thomas
338 e760210d 2023-11-16 thomas n = snprintf(portno, sizeof(portno), "%lld",
339 e760210d 2023-11-16 thomas (long long)$5);
340 e760210d 2023-11-16 thomas if (n < 0 || (size_t)n >= sizeof(portno))
341 e760210d 2023-11-16 thomas fatalx("port number too long: %lld",
342 e760210d 2023-11-16 thomas (long long)$5);
343 e760210d 2023-11-16 thomas
344 e760210d 2023-11-16 thomas if (get_addrs($3, portno, new_srv) == -1) {
345 e760210d 2023-11-16 thomas yyerror("could not get addrs");
346 e760210d 2023-11-16 thomas YYERROR;
347 e760210d 2023-11-16 thomas }
348 e760210d 2023-11-16 thomas free($3);
349 e760210d 2023-11-16 thomas new_srv->fcgi_socket = 1;
350 e760210d 2023-11-16 thomas }
351 bea82c4f 2023-01-06 thomas | LISTEN ON SOCKET STRING {
352 ee003af8 2023-06-15 thomas if (strcasecmp($4, "off") == 0) {
353 bea82c4f 2023-01-06 thomas new_srv->unix_socket = 0;
354 bea82c4f 2023-01-06 thomas free($4);
355 bea82c4f 2023-01-06 thomas YYACCEPT;
356 bea82c4f 2023-01-06 thomas }
357 bea82c4f 2023-01-06 thomas
358 bea82c4f 2023-01-06 thomas new_srv->unix_socket = 1;
359 bea82c4f 2023-01-06 thomas
360 bea82c4f 2023-01-06 thomas n = snprintf(new_srv->unix_socket_name,
361 bea82c4f 2023-01-06 thomas sizeof(new_srv->unix_socket_name), "%s%s",
362 0b16f49b 2023-06-22 thomas gotwebd->httpd_chroot, $4);
363 bea82c4f 2023-01-06 thomas if (n < 0 ||
364 bea82c4f 2023-01-06 thomas (size_t)n >= sizeof(new_srv->unix_socket_name)) {
365 bea82c4f 2023-01-06 thomas yyerror("%s: unix_socket_name truncated",
366 bea82c4f 2023-01-06 thomas __func__);
367 bea82c4f 2023-01-06 thomas free($4);
368 bea82c4f 2023-01-06 thomas YYERROR;
369 bea82c4f 2023-01-06 thomas }
370 bea82c4f 2023-01-06 thomas free($4);
371 bea82c4f 2023-01-06 thomas }
372 8a35f56c 2022-07-16 thomas | SHOW_SITE_OWNER boolean {
373 8a35f56c 2022-07-16 thomas new_srv->show_site_owner = $2;
374 8a35f56c 2022-07-16 thomas }
375 8a35f56c 2022-07-16 thomas | SHOW_REPO_OWNER boolean {
376 8a35f56c 2022-07-16 thomas new_srv->show_repo_owner = $2;
377 8a35f56c 2022-07-16 thomas }
378 8a35f56c 2022-07-16 thomas | SHOW_REPO_AGE boolean {
379 8a35f56c 2022-07-16 thomas new_srv->show_repo_age = $2;
380 8a35f56c 2022-07-16 thomas }
381 8a35f56c 2022-07-16 thomas | SHOW_REPO_DESCRIPTION boolean {
382 8a35f56c 2022-07-16 thomas new_srv->show_repo_description = $2;
383 8a35f56c 2022-07-16 thomas }
384 8a35f56c 2022-07-16 thomas | SHOW_REPO_CLONEURL boolean {
385 8a35f56c 2022-07-16 thomas new_srv->show_repo_cloneurl = $2;
386 8a35f56c 2022-07-16 thomas }
387 3991b2a5 2022-10-31 thomas | RESPECT_EXPORTOK boolean {
388 3991b2a5 2022-10-31 thomas new_srv->respect_exportok = $2;
389 3991b2a5 2022-10-31 thomas }
390 8a35f56c 2022-07-16 thomas | MAX_REPOS_DISPLAY NUMBER {
391 04833bad 2023-06-22 thomas if ($2 < 0) {
392 a0bd573d 2023-06-15 thomas yyerror("max_repos_display is too small: %lld",
393 a0bd573d 2023-06-15 thomas $2);
394 a0bd573d 2023-06-15 thomas YYERROR;
395 a0bd573d 2023-06-15 thomas }
396 a0bd573d 2023-06-15 thomas new_srv->max_repos_display = $2;
397 8a35f56c 2022-07-16 thomas }
398 8a35f56c 2022-07-16 thomas | MAX_COMMITS_DISPLAY NUMBER {
399 1fa505c4 2023-06-15 thomas if ($2 <= 1) {
400 1fa505c4 2023-06-15 thomas yyerror("max_commits_display is too small:"
401 1fa505c4 2023-06-15 thomas " %lld", $2);
402 1fa505c4 2023-06-15 thomas YYERROR;
403 1fa505c4 2023-06-15 thomas }
404 1fa505c4 2023-06-15 thomas new_srv->max_commits_display = $2;
405 e85a14fa 2023-12-30 thomas }
406 e85a14fa 2023-12-30 thomas | SUMMARY_COMMITS_DISPLAY NUMBER {
407 e85a14fa 2023-12-30 thomas if ($2 < 1) {
408 e85a14fa 2023-12-30 thomas yyerror("summary_commits_display is too small:"
409 e85a14fa 2023-12-30 thomas " %lld", $2);
410 e85a14fa 2023-12-30 thomas YYERROR;
411 e85a14fa 2023-12-30 thomas }
412 e85a14fa 2023-12-30 thomas new_srv->summary_commits_display = $2;
413 8a35f56c 2022-07-16 thomas }
414 e85a14fa 2023-12-30 thomas | SUMMARY_TAGS_DISPLAY NUMBER {
415 e85a14fa 2023-12-30 thomas if ($2 < 1) {
416 e85a14fa 2023-12-30 thomas yyerror("summary_tags_display is too small:"
417 e85a14fa 2023-12-30 thomas " %lld", $2);
418 e85a14fa 2023-12-30 thomas YYERROR;
419 e85a14fa 2023-12-30 thomas }
420 e85a14fa 2023-12-30 thomas new_srv->summary_tags_display = $2;
421 e85a14fa 2023-12-30 thomas }
422 8a35f56c 2022-07-16 thomas ;
423 8a35f56c 2022-07-16 thomas
424 8a35f56c 2022-07-16 thomas serveropts2 : serveropts2 serveropts1 nl
425 8a35f56c 2022-07-16 thomas | serveropts1 optnl
426 8a35f56c 2022-07-16 thomas ;
427 8a35f56c 2022-07-16 thomas
428 8a35f56c 2022-07-16 thomas nl : '\n' optnl
429 8a35f56c 2022-07-16 thomas ;
430 8a35f56c 2022-07-16 thomas
431 8a35f56c 2022-07-16 thomas optnl : '\n' optnl /* zero or more newlines */
432 8a35f56c 2022-07-16 thomas | /* empty */
433 8a35f56c 2022-07-16 thomas ;
434 8a35f56c 2022-07-16 thomas
435 8a35f56c 2022-07-16 thomas %%
436 8a35f56c 2022-07-16 thomas
437 8a35f56c 2022-07-16 thomas struct keywords {
438 8a35f56c 2022-07-16 thomas const char *k_name;
439 8a35f56c 2022-07-16 thomas int k_val;
440 8a35f56c 2022-07-16 thomas };
441 8a35f56c 2022-07-16 thomas
442 8a35f56c 2022-07-16 thomas int
443 8a35f56c 2022-07-16 thomas yyerror(const char *fmt, ...)
444 8a35f56c 2022-07-16 thomas {
445 8a35f56c 2022-07-16 thomas va_list ap;
446 8a35f56c 2022-07-16 thomas char *msg;
447 8a35f56c 2022-07-16 thomas
448 8a35f56c 2022-07-16 thomas file->errors++;
449 8a35f56c 2022-07-16 thomas va_start(ap, fmt);
450 8a35f56c 2022-07-16 thomas if (vasprintf(&msg, fmt, ap) == -1)
451 8a35f56c 2022-07-16 thomas fatalx("yyerror vasprintf");
452 8a35f56c 2022-07-16 thomas va_end(ap);
453 8a35f56c 2022-07-16 thomas logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
454 8a35f56c 2022-07-16 thomas free(msg);
455 8a35f56c 2022-07-16 thomas return (0);
456 8a35f56c 2022-07-16 thomas }
457 8a35f56c 2022-07-16 thomas
458 8a35f56c 2022-07-16 thomas int
459 8a35f56c 2022-07-16 thomas kw_cmp(const void *k, const void *e)
460 8a35f56c 2022-07-16 thomas {
461 8a35f56c 2022-07-16 thomas return (strcmp(k, ((const struct keywords *)e)->k_name));
462 8a35f56c 2022-07-16 thomas }
463 8a35f56c 2022-07-16 thomas
464 8a35f56c 2022-07-16 thomas int
465 8a35f56c 2022-07-16 thomas lookup(char *s)
466 8a35f56c 2022-07-16 thomas {
467 8a35f56c 2022-07-16 thomas /* This has to be sorted always. */
468 8a35f56c 2022-07-16 thomas static const struct keywords keywords[] = {
469 8a35f56c 2022-07-16 thomas { "chroot", CHROOT },
470 8a35f56c 2022-07-16 thomas { "custom_css", CUSTOM_CSS },
471 c24a47af 2022-08-11 thomas { "listen", LISTEN },
472 8a35f56c 2022-07-16 thomas { "logo", LOGO },
473 f0b4ad15 2023-01-02 thomas { "logo_url", LOGO_URL },
474 8a35f56c 2022-07-16 thomas { "max_commits_display", MAX_COMMITS_DISPLAY },
475 8a35f56c 2022-07-16 thomas { "max_repos_display", MAX_REPOS_DISPLAY },
476 c24a47af 2022-08-11 thomas { "on", ON },
477 8a35f56c 2022-07-16 thomas { "port", PORT },
478 8a35f56c 2022-07-16 thomas { "prefork", PREFORK },
479 8a35f56c 2022-07-16 thomas { "repos_path", REPOS_PATH },
480 3991b2a5 2022-10-31 thomas { "respect_exportok", RESPECT_EXPORTOK },
481 8a35f56c 2022-07-16 thomas { "server", SERVER },
482 8a35f56c 2022-07-16 thomas { "show_repo_age", SHOW_REPO_AGE },
483 8a35f56c 2022-07-16 thomas { "show_repo_cloneurl", SHOW_REPO_CLONEURL },
484 8a35f56c 2022-07-16 thomas { "show_repo_description", SHOW_REPO_DESCRIPTION },
485 8a35f56c 2022-07-16 thomas { "show_repo_owner", SHOW_REPO_OWNER },
486 8a35f56c 2022-07-16 thomas { "show_site_owner", SHOW_SITE_OWNER },
487 8a35f56c 2022-07-16 thomas { "site_link", SITE_LINK },
488 8a35f56c 2022-07-16 thomas { "site_name", SITE_NAME },
489 8a35f56c 2022-07-16 thomas { "site_owner", SITE_OWNER },
490 bea82c4f 2023-01-06 thomas { "socket", SOCKET },
491 e85a14fa 2023-12-30 thomas { "summary_commits_display", SUMMARY_COMMITS_DISPLAY },
492 e85a14fa 2023-12-30 thomas { "summary_tags_display", SUMMARY_TAGS_DISPLAY },
493 8a35f56c 2022-07-16 thomas { "unix_socket", UNIX_SOCKET },
494 8a35f56c 2022-07-16 thomas { "unix_socket_name", UNIX_SOCKET_NAME },
495 8a35f56c 2022-07-16 thomas };
496 8a35f56c 2022-07-16 thomas const struct keywords *p;
497 8a35f56c 2022-07-16 thomas
498 8a35f56c 2022-07-16 thomas p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
499 8a35f56c 2022-07-16 thomas sizeof(keywords[0]), kw_cmp);
500 8a35f56c 2022-07-16 thomas
501 8a35f56c 2022-07-16 thomas if (p)
502 8a35f56c 2022-07-16 thomas return (p->k_val);
503 8a35f56c 2022-07-16 thomas else
504 8a35f56c 2022-07-16 thomas return (STRING);
505 8a35f56c 2022-07-16 thomas }
506 8a35f56c 2022-07-16 thomas
507 8a35f56c 2022-07-16 thomas #define MAXPUSHBACK 128
508 8a35f56c 2022-07-16 thomas
509 8a35f56c 2022-07-16 thomas unsigned char *parsebuf;
510 8a35f56c 2022-07-16 thomas int parseindex;
511 8a35f56c 2022-07-16 thomas unsigned char pushback_buffer[MAXPUSHBACK];
512 8a35f56c 2022-07-16 thomas int pushback_index = 0;
513 8a35f56c 2022-07-16 thomas
514 8a35f56c 2022-07-16 thomas int
515 8a35f56c 2022-07-16 thomas lgetc(int quotec)
516 8a35f56c 2022-07-16 thomas {
517 8a35f56c 2022-07-16 thomas int c, next;
518 8a35f56c 2022-07-16 thomas
519 8a35f56c 2022-07-16 thomas if (parsebuf) {
520 8a35f56c 2022-07-16 thomas /* Read character from the parsebuffer instead of input. */
521 8a35f56c 2022-07-16 thomas if (parseindex >= 0) {
522 8a35f56c 2022-07-16 thomas c = parsebuf[parseindex++];
523 8a35f56c 2022-07-16 thomas if (c != '\0')
524 8a35f56c 2022-07-16 thomas return (c);
525 8a35f56c 2022-07-16 thomas parsebuf = NULL;
526 8a35f56c 2022-07-16 thomas } else
527 8a35f56c 2022-07-16 thomas parseindex++;
528 8a35f56c 2022-07-16 thomas }
529 8a35f56c 2022-07-16 thomas
530 8a35f56c 2022-07-16 thomas if (pushback_index)
531 8a35f56c 2022-07-16 thomas return (pushback_buffer[--pushback_index]);
532 8a35f56c 2022-07-16 thomas
533 8a35f56c 2022-07-16 thomas if (quotec) {
534 8a35f56c 2022-07-16 thomas c = getc(file->stream);
535 8a35f56c 2022-07-16 thomas if (c == EOF)
536 8a35f56c 2022-07-16 thomas yyerror("reached end of file while parsing "
537 8a35f56c 2022-07-16 thomas "quoted string");
538 8a35f56c 2022-07-16 thomas return (c);
539 8a35f56c 2022-07-16 thomas }
540 8a35f56c 2022-07-16 thomas
541 8a35f56c 2022-07-16 thomas c = getc(file->stream);
542 8a35f56c 2022-07-16 thomas while (c == '\\') {
543 8a35f56c 2022-07-16 thomas next = getc(file->stream);
544 8a35f56c 2022-07-16 thomas if (next != '\n') {
545 8a35f56c 2022-07-16 thomas c = next;
546 8a35f56c 2022-07-16 thomas break;
547 8a35f56c 2022-07-16 thomas }
548 8a35f56c 2022-07-16 thomas yylval.lineno = file->lineno;
549 8a35f56c 2022-07-16 thomas file->lineno++;
550 8a35f56c 2022-07-16 thomas c = getc(file->stream);
551 8a35f56c 2022-07-16 thomas }
552 8a35f56c 2022-07-16 thomas
553 8a35f56c 2022-07-16 thomas return (c);
554 8a35f56c 2022-07-16 thomas }
555 8a35f56c 2022-07-16 thomas
556 8a35f56c 2022-07-16 thomas int
557 8a35f56c 2022-07-16 thomas lungetc(int c)
558 8a35f56c 2022-07-16 thomas {
559 8a35f56c 2022-07-16 thomas if (c == EOF)
560 8a35f56c 2022-07-16 thomas return (EOF);
561 8a35f56c 2022-07-16 thomas if (parsebuf) {
562 8a35f56c 2022-07-16 thomas parseindex--;
563 8a35f56c 2022-07-16 thomas if (parseindex >= 0)
564 8a35f56c 2022-07-16 thomas return (c);
565 8a35f56c 2022-07-16 thomas }
566 8a35f56c 2022-07-16 thomas if (pushback_index < MAXPUSHBACK-1)
567 8a35f56c 2022-07-16 thomas return (pushback_buffer[pushback_index++] = c);
568 8a35f56c 2022-07-16 thomas else
569 8a35f56c 2022-07-16 thomas return (EOF);
570 8a35f56c 2022-07-16 thomas }
571 8a35f56c 2022-07-16 thomas
572 8a35f56c 2022-07-16 thomas int
573 8a35f56c 2022-07-16 thomas findeol(void)
574 8a35f56c 2022-07-16 thomas {
575 8a35f56c 2022-07-16 thomas int c;
576 8a35f56c 2022-07-16 thomas
577 8a35f56c 2022-07-16 thomas parsebuf = NULL;
578 8a35f56c 2022-07-16 thomas
579 8a35f56c 2022-07-16 thomas /* Skip to either EOF or the first real EOL. */
580 8a35f56c 2022-07-16 thomas while (1) {
581 8a35f56c 2022-07-16 thomas if (pushback_index)
582 8a35f56c 2022-07-16 thomas c = pushback_buffer[--pushback_index];
583 8a35f56c 2022-07-16 thomas else
584 8a35f56c 2022-07-16 thomas c = lgetc(0);
585 8a35f56c 2022-07-16 thomas if (c == '\n') {
586 8a35f56c 2022-07-16 thomas file->lineno++;
587 8a35f56c 2022-07-16 thomas break;
588 8a35f56c 2022-07-16 thomas }
589 8a35f56c 2022-07-16 thomas if (c == EOF)
590 8a35f56c 2022-07-16 thomas break;
591 8a35f56c 2022-07-16 thomas }
592 8a35f56c 2022-07-16 thomas return (ERROR);
593 8a35f56c 2022-07-16 thomas }
594 8a35f56c 2022-07-16 thomas
595 8a35f56c 2022-07-16 thomas int
596 8a35f56c 2022-07-16 thomas yylex(void)
597 8a35f56c 2022-07-16 thomas {
598 8a35f56c 2022-07-16 thomas unsigned char buf[8096];
599 8a35f56c 2022-07-16 thomas unsigned char *p, *val;
600 8a35f56c 2022-07-16 thomas int quotec, next, c;
601 8a35f56c 2022-07-16 thomas int token;
602 8a35f56c 2022-07-16 thomas
603 8a35f56c 2022-07-16 thomas top:
604 8a35f56c 2022-07-16 thomas p = buf;
605 8a35f56c 2022-07-16 thomas c = lgetc(0);
606 8a35f56c 2022-07-16 thomas while (c == ' ' || c == '\t')
607 8a35f56c 2022-07-16 thomas c = lgetc(0); /* nothing */
608 8a35f56c 2022-07-16 thomas
609 8a35f56c 2022-07-16 thomas yylval.lineno = file->lineno;
610 8a35f56c 2022-07-16 thomas if (c == '#') {
611 8a35f56c 2022-07-16 thomas c = lgetc(0);
612 8a35f56c 2022-07-16 thomas while (c != '\n' && c != EOF)
613 8a35f56c 2022-07-16 thomas c = lgetc(0); /* nothing */
614 8a35f56c 2022-07-16 thomas }
615 8a35f56c 2022-07-16 thomas if (c == '$' && parsebuf == NULL) {
616 8a35f56c 2022-07-16 thomas while (1) {
617 8a35f56c 2022-07-16 thomas c = lgetc(0);
618 8a35f56c 2022-07-16 thomas if (c == EOF)
619 8a35f56c 2022-07-16 thomas return (0);
620 8a35f56c 2022-07-16 thomas
621 8a35f56c 2022-07-16 thomas if (p + 1 >= buf + sizeof(buf) - 1) {
622 8a35f56c 2022-07-16 thomas yyerror("string too long");
623 8a35f56c 2022-07-16 thomas return (findeol());
624 8a35f56c 2022-07-16 thomas }
625 8a35f56c 2022-07-16 thomas if (isalnum(c) || c == '_') {
626 8a35f56c 2022-07-16 thomas *p++ = c;
627 8a35f56c 2022-07-16 thomas continue;
628 8a35f56c 2022-07-16 thomas }
629 8a35f56c 2022-07-16 thomas *p = '\0';
630 8a35f56c 2022-07-16 thomas lungetc(c);
631 8a35f56c 2022-07-16 thomas break;
632 8a35f56c 2022-07-16 thomas }
633 8a35f56c 2022-07-16 thomas val = symget(buf);
634 8a35f56c 2022-07-16 thomas if (val == NULL) {
635 8a35f56c 2022-07-16 thomas yyerror("macro '%s' not defined", buf);
636 8a35f56c 2022-07-16 thomas return (findeol());
637 8a35f56c 2022-07-16 thomas }
638 8a35f56c 2022-07-16 thomas parsebuf = val;
639 8a35f56c 2022-07-16 thomas parseindex = 0;
640 8a35f56c 2022-07-16 thomas goto top;
641 8a35f56c 2022-07-16 thomas }
642 8a35f56c 2022-07-16 thomas
643 8a35f56c 2022-07-16 thomas switch (c) {
644 8a35f56c 2022-07-16 thomas case '\'':
645 8a35f56c 2022-07-16 thomas case '"':
646 8a35f56c 2022-07-16 thomas quotec = c;
647 8a35f56c 2022-07-16 thomas while (1) {
648 8a35f56c 2022-07-16 thomas c = lgetc(quotec);
649 8a35f56c 2022-07-16 thomas if (c == EOF)
650 8a35f56c 2022-07-16 thomas return (0);
651 8a35f56c 2022-07-16 thomas if (c == '\n') {
652 8a35f56c 2022-07-16 thomas file->lineno++;
653 8a35f56c 2022-07-16 thomas continue;
654 8a35f56c 2022-07-16 thomas } else if (c == '\\') {
655 8a35f56c 2022-07-16 thomas next = lgetc(quotec);
656 8a35f56c 2022-07-16 thomas if (next == EOF)
657 8a35f56c 2022-07-16 thomas return (0);
658 8a35f56c 2022-07-16 thomas if (next == quotec || c == ' ' || c == '\t')
659 8a35f56c 2022-07-16 thomas c = next;
660 8a35f56c 2022-07-16 thomas else if (next == '\n') {
661 8a35f56c 2022-07-16 thomas file->lineno++;
662 8a35f56c 2022-07-16 thomas continue;
663 8a35f56c 2022-07-16 thomas } else
664 8a35f56c 2022-07-16 thomas lungetc(next);
665 8a35f56c 2022-07-16 thomas } else if (c == quotec) {
666 8a35f56c 2022-07-16 thomas *p = '\0';
667 8a35f56c 2022-07-16 thomas break;
668 8a35f56c 2022-07-16 thomas } else if (c == '\0') {
669 8a35f56c 2022-07-16 thomas yyerror("syntax error");
670 8a35f56c 2022-07-16 thomas return (findeol());
671 8a35f56c 2022-07-16 thomas }
672 8a35f56c 2022-07-16 thomas if (p + 1 >= buf + sizeof(buf) - 1) {
673 8a35f56c 2022-07-16 thomas yyerror("string too long");
674 8a35f56c 2022-07-16 thomas return (findeol());
675 8a35f56c 2022-07-16 thomas }
676 8a35f56c 2022-07-16 thomas *p++ = c;
677 8a35f56c 2022-07-16 thomas }
678 8a35f56c 2022-07-16 thomas yylval.v.string = strdup(buf);
679 8a35f56c 2022-07-16 thomas if (yylval.v.string == NULL)
680 8a35f56c 2022-07-16 thomas err(1, "yylex: strdup");
681 8a35f56c 2022-07-16 thomas return (STRING);
682 8a35f56c 2022-07-16 thomas }
683 8a35f56c 2022-07-16 thomas
684 8a35f56c 2022-07-16 thomas #define allowed_to_end_number(x) \
685 8a35f56c 2022-07-16 thomas (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
686 8a35f56c 2022-07-16 thomas
687 8a35f56c 2022-07-16 thomas if (c == '-' || isdigit(c)) {
688 8a35f56c 2022-07-16 thomas do {
689 8a35f56c 2022-07-16 thomas *p++ = c;
690 8a35f56c 2022-07-16 thomas if ((unsigned)(p-buf) >= sizeof(buf)) {
691 8a35f56c 2022-07-16 thomas yyerror("string too long");
692 8a35f56c 2022-07-16 thomas return (findeol());
693 8a35f56c 2022-07-16 thomas }
694 8a35f56c 2022-07-16 thomas c = lgetc(0);
695 8a35f56c 2022-07-16 thomas } while (c != EOF && isdigit(c));
696 8a35f56c 2022-07-16 thomas lungetc(c);
697 8a35f56c 2022-07-16 thomas if (p == buf + 1 && buf[0] == '-')
698 8a35f56c 2022-07-16 thomas goto nodigits;
699 8a35f56c 2022-07-16 thomas if (c == EOF || allowed_to_end_number(c)) {
700 8a35f56c 2022-07-16 thomas const char *errstr = NULL;
701 8a35f56c 2022-07-16 thomas
702 8a35f56c 2022-07-16 thomas *p = '\0';
703 8a35f56c 2022-07-16 thomas yylval.v.number = strtonum(buf, LLONG_MIN,
704 8a35f56c 2022-07-16 thomas LLONG_MAX, &errstr);
705 8a35f56c 2022-07-16 thomas if (errstr) {
706 8a35f56c 2022-07-16 thomas yyerror("\"%s\" invalid number: %s",
707 8a35f56c 2022-07-16 thomas buf, errstr);
708 8a35f56c 2022-07-16 thomas return (findeol());
709 8a35f56c 2022-07-16 thomas }
710 8a35f56c 2022-07-16 thomas return (NUMBER);
711 8a35f56c 2022-07-16 thomas } else {
712 8a35f56c 2022-07-16 thomas nodigits:
713 8a35f56c 2022-07-16 thomas while (p > buf + 1)
714 8a35f56c 2022-07-16 thomas lungetc(*--p);
715 8a35f56c 2022-07-16 thomas c = *--p;
716 8a35f56c 2022-07-16 thomas if (c == '-')
717 8a35f56c 2022-07-16 thomas return (c);
718 8a35f56c 2022-07-16 thomas }
719 8a35f56c 2022-07-16 thomas }
720 8a35f56c 2022-07-16 thomas
721 8a35f56c 2022-07-16 thomas #define allowed_in_string(x) \
722 8a35f56c 2022-07-16 thomas (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
723 8a35f56c 2022-07-16 thomas x != '{' && x != '}' && \
724 8a35f56c 2022-07-16 thomas x != '!' && x != '=' && x != '#' && \
725 8a35f56c 2022-07-16 thomas x != ','))
726 8a35f56c 2022-07-16 thomas
727 8a35f56c 2022-07-16 thomas if (isalnum(c) || c == ':' || c == '_') {
728 8a35f56c 2022-07-16 thomas do {
729 8a35f56c 2022-07-16 thomas *p++ = c;
730 8a35f56c 2022-07-16 thomas if ((unsigned)(p-buf) >= sizeof(buf)) {
731 8a35f56c 2022-07-16 thomas yyerror("string too long");
732 8a35f56c 2022-07-16 thomas return (findeol());
733 8a35f56c 2022-07-16 thomas }
734 8a35f56c 2022-07-16 thomas c = lgetc(0);
735 8a35f56c 2022-07-16 thomas } while (c != EOF && (allowed_in_string(c)));
736 8a35f56c 2022-07-16 thomas lungetc(c);
737 8a35f56c 2022-07-16 thomas *p = '\0';
738 8a35f56c 2022-07-16 thomas token = lookup(buf);
739 8a35f56c 2022-07-16 thomas if (token == STRING) {
740 8a35f56c 2022-07-16 thomas yylval.v.string = strdup(buf);
741 8a35f56c 2022-07-16 thomas if (yylval.v.string == NULL)
742 8a35f56c 2022-07-16 thomas err(1, "yylex: strdup");
743 8a35f56c 2022-07-16 thomas }
744 8a35f56c 2022-07-16 thomas return (token);
745 8a35f56c 2022-07-16 thomas }
746 8a35f56c 2022-07-16 thomas if (c == '\n') {
747 8a35f56c 2022-07-16 thomas yylval.lineno = file->lineno;
748 8a35f56c 2022-07-16 thomas file->lineno++;
749 8a35f56c 2022-07-16 thomas }
750 8a35f56c 2022-07-16 thomas if (c == EOF)
751 8a35f56c 2022-07-16 thomas return (0);
752 8a35f56c 2022-07-16 thomas return (c);
753 8a35f56c 2022-07-16 thomas }
754 8a35f56c 2022-07-16 thomas
755 8a35f56c 2022-07-16 thomas int
756 8a35f56c 2022-07-16 thomas check_file_secrecy(int fd, const char *fname)
757 8a35f56c 2022-07-16 thomas {
758 8a35f56c 2022-07-16 thomas struct stat st;
759 8a35f56c 2022-07-16 thomas
760 8a35f56c 2022-07-16 thomas if (fstat(fd, &st)) {
761 8a35f56c 2022-07-16 thomas log_warn("cannot stat %s", fname);
762 8a35f56c 2022-07-16 thomas return (-1);
763 8a35f56c 2022-07-16 thomas }
764 8a35f56c 2022-07-16 thomas if (st.st_uid != 0 && st.st_uid != getuid()) {
765 8a35f56c 2022-07-16 thomas log_warnx("%s: owner not root or current user", fname);
766 8a35f56c 2022-07-16 thomas return (-1);
767 8a35f56c 2022-07-16 thomas }
768 8a35f56c 2022-07-16 thomas if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
769 8a35f56c 2022-07-16 thomas log_warnx("%s: group writable or world read/writable", fname);
770 8a35f56c 2022-07-16 thomas return (-1);
771 8a35f56c 2022-07-16 thomas }
772 8a35f56c 2022-07-16 thomas return (0);
773 8a35f56c 2022-07-16 thomas }
774 8a35f56c 2022-07-16 thomas
775 8a35f56c 2022-07-16 thomas struct file *
776 8a35f56c 2022-07-16 thomas newfile(const char *name, int secret)
777 8a35f56c 2022-07-16 thomas {
778 8a35f56c 2022-07-16 thomas struct file *nfile;
779 8a35f56c 2022-07-16 thomas
780 8a35f56c 2022-07-16 thomas nfile = calloc(1, sizeof(struct file));
781 8a35f56c 2022-07-16 thomas if (nfile == NULL) {
782 8a35f56c 2022-07-16 thomas log_warn("calloc");
783 8a35f56c 2022-07-16 thomas return (NULL);
784 8a35f56c 2022-07-16 thomas }
785 8a35f56c 2022-07-16 thomas nfile->name = strdup(name);
786 8a35f56c 2022-07-16 thomas if (nfile->name == NULL) {
787 8a35f56c 2022-07-16 thomas log_warn("strdup");
788 8a35f56c 2022-07-16 thomas free(nfile);
789 8a35f56c 2022-07-16 thomas return (NULL);
790 8a35f56c 2022-07-16 thomas }
791 8a35f56c 2022-07-16 thomas nfile->stream = fopen(nfile->name, "r");
792 8a35f56c 2022-07-16 thomas if (nfile->stream == NULL) {
793 8a35f56c 2022-07-16 thomas /* no warning, we don't require a conf file */
794 8a35f56c 2022-07-16 thomas free(nfile->name);
795 8a35f56c 2022-07-16 thomas free(nfile);
796 8a35f56c 2022-07-16 thomas return (NULL);
797 8a35f56c 2022-07-16 thomas } else if (secret &&
798 8a35f56c 2022-07-16 thomas check_file_secrecy(fileno(nfile->stream), nfile->name)) {
799 8a35f56c 2022-07-16 thomas fclose(nfile->stream);
800 8a35f56c 2022-07-16 thomas free(nfile->name);
801 8a35f56c 2022-07-16 thomas free(nfile);
802 8a35f56c 2022-07-16 thomas return (NULL);
803 8a35f56c 2022-07-16 thomas }
804 8a35f56c 2022-07-16 thomas nfile->lineno = 1;
805 8a35f56c 2022-07-16 thomas return (nfile);
806 8a35f56c 2022-07-16 thomas }
807 8a35f56c 2022-07-16 thomas
808 8a35f56c 2022-07-16 thomas static void
809 8a35f56c 2022-07-16 thomas closefile(struct file *xfile)
810 8a35f56c 2022-07-16 thomas {
811 8a35f56c 2022-07-16 thomas fclose(xfile->stream);
812 8a35f56c 2022-07-16 thomas free(xfile->name);
813 8a35f56c 2022-07-16 thomas free(xfile);
814 8a35f56c 2022-07-16 thomas }
815 8a35f56c 2022-07-16 thomas
816 9f849004 2022-08-06 thomas static void
817 9f849004 2022-08-06 thomas add_default_server(void)
818 9f849004 2022-08-06 thomas {
819 9f849004 2022-08-06 thomas new_srv = conf_new_server(D_SITENAME);
820 9f849004 2022-08-06 thomas log_debug("%s: adding default server %s", __func__, D_SITENAME);
821 9f849004 2022-08-06 thomas }
822 9f849004 2022-08-06 thomas
823 8a35f56c 2022-07-16 thomas int
824 8a35f56c 2022-07-16 thomas parse_config(const char *filename, struct gotwebd *env)
825 8a35f56c 2022-07-16 thomas {
826 8a35f56c 2022-07-16 thomas struct sym *sym, *next;
827 8a35f56c 2022-07-16 thomas
828 8a35f56c 2022-07-16 thomas if (config_init(env) == -1)
829 8a35f56c 2022-07-16 thomas fatalx("failed to initialize configuration");
830 8a35f56c 2022-07-16 thomas
831 8a35f56c 2022-07-16 thomas gotwebd = env;
832 9f849004 2022-08-06 thomas
833 9f849004 2022-08-06 thomas file = newfile(filename, 0);
834 9f849004 2022-08-06 thomas if (file == NULL) {
835 9f849004 2022-08-06 thomas add_default_server();
836 9f849004 2022-08-06 thomas sockets_parse_sockets(env);
837 9f849004 2022-08-06 thomas /* just return, as we don't require a conf file */
838 9f849004 2022-08-06 thomas return (0);
839 9f849004 2022-08-06 thomas }
840 8a35f56c 2022-07-16 thomas
841 8a35f56c 2022-07-16 thomas yyparse();
842 8a35f56c 2022-07-16 thomas errors = file->errors;
843 8a35f56c 2022-07-16 thomas closefile(file);
844 8a35f56c 2022-07-16 thomas
845 8a35f56c 2022-07-16 thomas /* Free macros and check which have not been used. */
846 8a35f56c 2022-07-16 thomas TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
847 8a35f56c 2022-07-16 thomas if ((gotwebd->gotwebd_verbose > 1) && !sym->used)
848 8a35f56c 2022-07-16 thomas fprintf(stderr, "warning: macro '%s' not used\n",
849 8a35f56c 2022-07-16 thomas sym->nam);
850 8a35f56c 2022-07-16 thomas if (!sym->persist) {
851 8a35f56c 2022-07-16 thomas free(sym->nam);
852 8a35f56c 2022-07-16 thomas free(sym->val);
853 8a35f56c 2022-07-16 thomas TAILQ_REMOVE(&symhead, sym, entry);
854 8a35f56c 2022-07-16 thomas free(sym);
855 8a35f56c 2022-07-16 thomas }
856 8a35f56c 2022-07-16 thomas }
857 8a35f56c 2022-07-16 thomas
858 8a35f56c 2022-07-16 thomas if (errors)
859 8a35f56c 2022-07-16 thomas return (-1);
860 8a35f56c 2022-07-16 thomas
861 8a35f56c 2022-07-16 thomas /* just add default server if no config specified */
862 9f849004 2022-08-06 thomas if (gotwebd->server_cnt == 0)
863 9f849004 2022-08-06 thomas add_default_server();
864 8a35f56c 2022-07-16 thomas
865 8a35f56c 2022-07-16 thomas /* setup our listening sockets */
866 8a35f56c 2022-07-16 thomas sockets_parse_sockets(env);
867 8a35f56c 2022-07-16 thomas
868 8a35f56c 2022-07-16 thomas return (0);
869 8a35f56c 2022-07-16 thomas }
870 8a35f56c 2022-07-16 thomas
871 8a35f56c 2022-07-16 thomas struct server *
872 8a35f56c 2022-07-16 thomas conf_new_server(const char *name)
873 8a35f56c 2022-07-16 thomas {
874 8a35f56c 2022-07-16 thomas struct server *srv = NULL;
875 8a35f56c 2022-07-16 thomas
876 8a35f56c 2022-07-16 thomas srv = calloc(1, sizeof(*srv));
877 8a35f56c 2022-07-16 thomas if (srv == NULL)
878 8a35f56c 2022-07-16 thomas fatalx("%s: calloc", __func__);
879 8a35f56c 2022-07-16 thomas
880 8a35f56c 2022-07-16 thomas n = strlcpy(srv->name, name, sizeof(srv->name));
881 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->name))
882 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
883 8a35f56c 2022-07-16 thomas n = snprintf(srv->unix_socket_name,
884 8a35f56c 2022-07-16 thomas sizeof(srv->unix_socket_name), "%s%s", D_HTTPD_CHROOT,
885 8a35f56c 2022-07-16 thomas D_UNIX_SOCKET);
886 717a78d4 2022-08-16 thomas if (n < 0 || (size_t)n >= sizeof(srv->unix_socket_name))
887 8a35f56c 2022-07-16 thomas fatalx("%s: snprintf", __func__);
888 8a35f56c 2022-07-16 thomas n = strlcpy(srv->repos_path, D_GOTPATH,
889 8a35f56c 2022-07-16 thomas sizeof(srv->repos_path));
890 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->repos_path))
891 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
892 8a35f56c 2022-07-16 thomas n = strlcpy(srv->site_name, D_SITENAME,
893 8a35f56c 2022-07-16 thomas sizeof(srv->site_name));
894 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->site_name))
895 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
896 8a35f56c 2022-07-16 thomas n = strlcpy(srv->site_owner, D_SITEOWNER,
897 8a35f56c 2022-07-16 thomas sizeof(srv->site_owner));
898 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->site_owner))
899 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
900 8a35f56c 2022-07-16 thomas n = strlcpy(srv->site_link, D_SITELINK,
901 8a35f56c 2022-07-16 thomas sizeof(srv->site_link));
902 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->site_link))
903 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
904 8a35f56c 2022-07-16 thomas n = strlcpy(srv->logo, D_GOTLOGO,
905 8a35f56c 2022-07-16 thomas sizeof(srv->logo));
906 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->logo))
907 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
908 8a35f56c 2022-07-16 thomas n = strlcpy(srv->logo_url, D_GOTURL, sizeof(srv->logo_url));
909 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->logo_url))
910 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
911 8a35f56c 2022-07-16 thomas n = strlcpy(srv->custom_css, D_GOTWEBCSS, sizeof(srv->custom_css));
912 8a35f56c 2022-07-16 thomas if (n >= sizeof(srv->custom_css))
913 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
914 8a35f56c 2022-07-16 thomas
915 8a35f56c 2022-07-16 thomas srv->show_site_owner = D_SHOWSOWNER;
916 8a35f56c 2022-07-16 thomas srv->show_repo_owner = D_SHOWROWNER;
917 8a35f56c 2022-07-16 thomas srv->show_repo_age = D_SHOWAGE;
918 8a35f56c 2022-07-16 thomas srv->show_repo_description = D_SHOWDESC;
919 8a35f56c 2022-07-16 thomas srv->show_repo_cloneurl = D_SHOWURL;
920 3991b2a5 2022-10-31 thomas srv->respect_exportok = D_RESPECTEXPORTOK;
921 8a35f56c 2022-07-16 thomas
922 8a35f56c 2022-07-16 thomas srv->max_repos_display = D_MAXREPODISP;
923 8a35f56c 2022-07-16 thomas srv->max_commits_display = D_MAXCOMMITDISP;
924 e85a14fa 2023-12-30 thomas srv->summary_commits_display = D_MAXSLCOMMDISP;
925 e85a14fa 2023-12-30 thomas srv->summary_tags_display = D_MAXSLTAGDISP;
926 8a35f56c 2022-07-16 thomas
927 8a35f56c 2022-07-16 thomas srv->unix_socket = 1;
928 e4317279 2022-08-30 thomas srv->fcgi_socket = 0;
929 8a35f56c 2022-07-16 thomas
930 62f85214 2022-08-16 thomas TAILQ_INIT(&srv->al);
931 90d63d47 2022-08-16 thomas TAILQ_INSERT_TAIL(&gotwebd->servers, srv, entry);
932 8a35f56c 2022-07-16 thomas gotwebd->server_cnt++;
933 8a35f56c 2022-07-16 thomas
934 8a35f56c 2022-07-16 thomas return srv;
935 8a35f56c 2022-07-16 thomas };
936 8a35f56c 2022-07-16 thomas
937 8a35f56c 2022-07-16 thomas int
938 8a35f56c 2022-07-16 thomas symset(const char *nam, const char *val, int persist)
939 8a35f56c 2022-07-16 thomas {
940 8a35f56c 2022-07-16 thomas struct sym *sym;
941 8a35f56c 2022-07-16 thomas
942 8a35f56c 2022-07-16 thomas TAILQ_FOREACH(sym, &symhead, entry) {
943 8a35f56c 2022-07-16 thomas if (strcmp(nam, sym->nam) == 0)
944 8a35f56c 2022-07-16 thomas break;
945 8a35f56c 2022-07-16 thomas }
946 8a35f56c 2022-07-16 thomas
947 8a35f56c 2022-07-16 thomas if (sym != NULL) {
948 8a35f56c 2022-07-16 thomas if (sym->persist == 1)
949 8a35f56c 2022-07-16 thomas return (0);
950 8a35f56c 2022-07-16 thomas else {
951 8a35f56c 2022-07-16 thomas free(sym->nam);
952 8a35f56c 2022-07-16 thomas free(sym->val);
953 8a35f56c 2022-07-16 thomas TAILQ_REMOVE(&symhead, sym, entry);
954 8a35f56c 2022-07-16 thomas free(sym);
955 8a35f56c 2022-07-16 thomas }
956 8a35f56c 2022-07-16 thomas }
957 8a35f56c 2022-07-16 thomas sym = calloc(1, sizeof(*sym));
958 8a35f56c 2022-07-16 thomas if (sym == NULL)
959 8a35f56c 2022-07-16 thomas return (-1);
960 8a35f56c 2022-07-16 thomas
961 8a35f56c 2022-07-16 thomas sym->nam = strdup(nam);
962 8a35f56c 2022-07-16 thomas if (sym->nam == NULL) {
963 8a35f56c 2022-07-16 thomas free(sym);
964 8a35f56c 2022-07-16 thomas return (-1);
965 8a35f56c 2022-07-16 thomas }
966 8a35f56c 2022-07-16 thomas sym->val = strdup(val);
967 8a35f56c 2022-07-16 thomas if (sym->val == NULL) {
968 8a35f56c 2022-07-16 thomas free(sym->nam);
969 8a35f56c 2022-07-16 thomas free(sym);
970 8a35f56c 2022-07-16 thomas return (-1);
971 8a35f56c 2022-07-16 thomas }
972 8a35f56c 2022-07-16 thomas sym->used = 0;
973 8a35f56c 2022-07-16 thomas sym->persist = persist;
974 8a35f56c 2022-07-16 thomas TAILQ_INSERT_TAIL(&symhead, sym, entry);
975 8a35f56c 2022-07-16 thomas return (0);
976 8a35f56c 2022-07-16 thomas }
977 8a35f56c 2022-07-16 thomas
978 8a35f56c 2022-07-16 thomas int
979 8a35f56c 2022-07-16 thomas cmdline_symset(char *s)
980 8a35f56c 2022-07-16 thomas {
981 8a35f56c 2022-07-16 thomas char *sym, *val;
982 8a35f56c 2022-07-16 thomas int ret;
983 8a35f56c 2022-07-16 thomas
984 8a35f56c 2022-07-16 thomas val = strrchr(s, '=');
985 8a35f56c 2022-07-16 thomas if (val == NULL)
986 8a35f56c 2022-07-16 thomas return (-1);
987 8a35f56c 2022-07-16 thomas
988 43be1edb 2022-09-05 thomas sym = strndup(s, val - s);
989 8a35f56c 2022-07-16 thomas if (sym == NULL)
990 43be1edb 2022-09-05 thomas fatal("%s: strndup", __func__);
991 8a35f56c 2022-07-16 thomas
992 8a35f56c 2022-07-16 thomas ret = symset(sym, val + 1, 1);
993 8a35f56c 2022-07-16 thomas free(sym);
994 8a35f56c 2022-07-16 thomas
995 8a35f56c 2022-07-16 thomas return (ret);
996 8a35f56c 2022-07-16 thomas }
997 8a35f56c 2022-07-16 thomas
998 8a35f56c 2022-07-16 thomas char *
999 8a35f56c 2022-07-16 thomas symget(const char *nam)
1000 8a35f56c 2022-07-16 thomas {
1001 8a35f56c 2022-07-16 thomas struct sym *sym;
1002 8a35f56c 2022-07-16 thomas
1003 8a35f56c 2022-07-16 thomas TAILQ_FOREACH(sym, &symhead, entry) {
1004 8a35f56c 2022-07-16 thomas if (strcmp(nam, sym->nam) == 0) {
1005 8a35f56c 2022-07-16 thomas sym->used = 1;
1006 8a35f56c 2022-07-16 thomas return (sym->val);
1007 8a35f56c 2022-07-16 thomas }
1008 8a35f56c 2022-07-16 thomas }
1009 8a35f56c 2022-07-16 thomas return (NULL);
1010 8a35f56c 2022-07-16 thomas }
1011 8a35f56c 2022-07-16 thomas
1012 8a35f56c 2022-07-16 thomas int
1013 e760210d 2023-11-16 thomas get_addrs(const char *hostname, const char *servname, struct server *new_srv)
1014 8a35f56c 2022-07-16 thomas {
1015 8a35f56c 2022-07-16 thomas struct addrinfo hints, *res0, *res;
1016 e760210d 2023-11-16 thomas int error;
1017 2edd250d 2023-11-16 thomas struct sockaddr_in *sin;
1018 2edd250d 2023-11-16 thomas struct sockaddr_in6 *sin6;
1019 8a35f56c 2022-07-16 thomas struct address *h;
1020 8a35f56c 2022-07-16 thomas
1021 8a35f56c 2022-07-16 thomas memset(&hints, 0, sizeof(hints));
1022 fb0cb708 2023-06-01 thomas hints.ai_family = AF_UNSPEC;
1023 e760210d 2023-11-16 thomas hints.ai_socktype = SOCK_STREAM;
1024 61bbe977 2023-11-16 thomas hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
1025 e760210d 2023-11-16 thomas error = getaddrinfo(hostname, servname, &hints, &res0);
1026 8a35f56c 2022-07-16 thomas if (error) {
1027 e760210d 2023-11-16 thomas log_warnx("%s: could not parse \"%s:%s\": %s", __func__,
1028 e760210d 2023-11-16 thomas hostname, servname, gai_strerror(error));
1029 8a35f56c 2022-07-16 thomas return (-1);
1030 8a35f56c 2022-07-16 thomas }
1031 8a35f56c 2022-07-16 thomas
1032 61bbe977 2023-11-16 thomas for (res = res0; res; res = res->ai_next) {
1033 8a35f56c 2022-07-16 thomas if ((h = calloc(1, sizeof(*h))) == NULL)
1034 8a35f56c 2022-07-16 thomas fatal(__func__);
1035 8a35f56c 2022-07-16 thomas
1036 e760210d 2023-11-16 thomas if (hostname == NULL) {
1037 61bbe977 2023-11-16 thomas strlcpy(h->ifname, "*", sizeof(h->ifname));
1038 61bbe977 2023-11-16 thomas } else {
1039 e760210d 2023-11-16 thomas if (strlcpy(h->ifname, hostname, sizeof(h->ifname)) >=
1040 8a35f56c 2022-07-16 thomas sizeof(h->ifname)) {
1041 ac485591 2023-11-16 thomas log_warnx("%s: address truncated: %s",
1042 ac485591 2023-11-16 thomas __func__, hostname);
1043 8a35f56c 2022-07-16 thomas freeaddrinfo(res0);
1044 8a35f56c 2022-07-16 thomas free(h);
1045 8a35f56c 2022-07-16 thomas return (-1);
1046 8a35f56c 2022-07-16 thomas }
1047 8a35f56c 2022-07-16 thomas }
1048 2edd250d 2023-11-16 thomas
1049 7d1d4b6f 2023-11-16 thomas h->ai_family = res->ai_family;
1050 7d1d4b6f 2023-11-16 thomas h->ai_socktype = res->ai_socktype;
1051 7d1d4b6f 2023-11-16 thomas h->ai_protocol = res->ai_protocol;
1052 2edd250d 2023-11-16 thomas memcpy(&h->ss, res->ai_addr, res->ai_addrlen);
1053 2edd250d 2023-11-16 thomas h->slen = res->ai_addrlen;
1054 8a35f56c 2022-07-16 thomas
1055 e760210d 2023-11-16 thomas switch (res->ai_family) {
1056 e760210d 2023-11-16 thomas case AF_INET:
1057 2edd250d 2023-11-16 thomas sin = (struct sockaddr_in *)res->ai_addr;
1058 2edd250d 2023-11-16 thomas h->port = ntohs(sin->sin_port);
1059 e760210d 2023-11-16 thomas break;
1060 e760210d 2023-11-16 thomas case AF_INET6:
1061 2edd250d 2023-11-16 thomas sin6 = (struct sockaddr_in6 *)res->ai_addr;
1062 2edd250d 2023-11-16 thomas h->port = ntohs(sin6->sin6_port);
1063 e760210d 2023-11-16 thomas break;
1064 e760210d 2023-11-16 thomas default:
1065 e760210d 2023-11-16 thomas fatalx("unknown address family %d", res->ai_family);
1066 8a35f56c 2022-07-16 thomas }
1067 8a35f56c 2022-07-16 thomas
1068 e4c7e0b0 2022-08-30 thomas if (add_addr(new_srv, h))
1069 e4c7e0b0 2022-08-30 thomas return -1;
1070 8a35f56c 2022-07-16 thomas }
1071 8a35f56c 2022-07-16 thomas freeaddrinfo(res0);
1072 8a35f56c 2022-07-16 thomas return (0);
1073 e4c7e0b0 2022-08-30 thomas }
1074 e4c7e0b0 2022-08-30 thomas
1075 e4c7e0b0 2022-08-30 thomas int
1076 e4c7e0b0 2022-08-30 thomas addr_dup_check(struct addresslist *al, struct address *h, const char *new_srv,
1077 e4c7e0b0 2022-08-30 thomas const char *other_srv)
1078 e4c7e0b0 2022-08-30 thomas {
1079 e4c7e0b0 2022-08-30 thomas struct address *a;
1080 e4c7e0b0 2022-08-30 thomas void *ia;
1081 e4c7e0b0 2022-08-30 thomas char buf[INET6_ADDRSTRLEN];
1082 e4c7e0b0 2022-08-30 thomas const char *addrstr;
1083 e4c7e0b0 2022-08-30 thomas
1084 e4c7e0b0 2022-08-30 thomas TAILQ_FOREACH(a, al, entry) {
1085 7d1d4b6f 2023-11-16 thomas if (a->ai_family != h->ai_family ||
1086 7d1d4b6f 2023-11-16 thomas a->ai_socktype != h->ai_socktype ||
1087 7d1d4b6f 2023-11-16 thomas a->ai_protocol != h->ai_protocol ||
1088 7d1d4b6f 2023-11-16 thomas a->slen != h->slen ||
1089 2edd250d 2023-11-16 thomas memcmp(&a->ss, &h->ss, a->slen) != 0)
1090 e4c7e0b0 2022-08-30 thomas continue;
1091 e4c7e0b0 2022-08-30 thomas
1092 e4c7e0b0 2022-08-30 thomas switch (h->ss.ss_family) {
1093 e4c7e0b0 2022-08-30 thomas case AF_INET:
1094 e4c7e0b0 2022-08-30 thomas ia = &((struct sockaddr_in *)(&h->ss))->sin_addr;
1095 e4c7e0b0 2022-08-30 thomas break;
1096 e4c7e0b0 2022-08-30 thomas case AF_INET6:
1097 e4c7e0b0 2022-08-30 thomas ia = &((struct sockaddr_in6 *)(&h->ss))->sin6_addr;
1098 e4c7e0b0 2022-08-30 thomas break;
1099 e4c7e0b0 2022-08-30 thomas default:
1100 e4c7e0b0 2022-08-30 thomas yyerror("unknown address family: %d", h->ss.ss_family);
1101 e4c7e0b0 2022-08-30 thomas return -1;
1102 e4c7e0b0 2022-08-30 thomas }
1103 e4c7e0b0 2022-08-30 thomas addrstr = inet_ntop(h->ss.ss_family, ia, buf, sizeof(buf));
1104 e4c7e0b0 2022-08-30 thomas if (addrstr) {
1105 e4c7e0b0 2022-08-30 thomas if (other_srv) {
1106 e4c7e0b0 2022-08-30 thomas yyerror("server %s: duplicate fcgi listen "
1107 e4c7e0b0 2022-08-30 thomas "address %s:%d, already used by server %s",
1108 e4c7e0b0 2022-08-30 thomas new_srv, addrstr, h->port, other_srv);
1109 e4c7e0b0 2022-08-30 thomas } else {
1110 e4c7e0b0 2022-08-30 thomas log_warnx("server: %s: duplicate fcgi listen "
1111 e4c7e0b0 2022-08-30 thomas "address %s:%d", new_srv, addrstr, h->port);
1112 e4c7e0b0 2022-08-30 thomas }
1113 e4c7e0b0 2022-08-30 thomas } else {
1114 e4c7e0b0 2022-08-30 thomas if (other_srv) {
1115 e4c7e0b0 2022-08-30 thomas yyerror("server: %s: duplicate fcgi listen "
1116 e4c7e0b0 2022-08-30 thomas "address, already used by server %s",
1117 e4c7e0b0 2022-08-30 thomas new_srv, other_srv);
1118 e4c7e0b0 2022-08-30 thomas } else {
1119 e4c7e0b0 2022-08-30 thomas log_warnx("server %s: duplicate fcgi listen "
1120 e4c7e0b0 2022-08-30 thomas "address", new_srv);
1121 e4c7e0b0 2022-08-30 thomas }
1122 e4c7e0b0 2022-08-30 thomas }
1123 e4c7e0b0 2022-08-30 thomas
1124 e4c7e0b0 2022-08-30 thomas return -1;
1125 e4c7e0b0 2022-08-30 thomas }
1126 e4c7e0b0 2022-08-30 thomas
1127 e4c7e0b0 2022-08-30 thomas return 0;
1128 8a35f56c 2022-07-16 thomas }
1129 e4c7e0b0 2022-08-30 thomas
1130 e4c7e0b0 2022-08-30 thomas int
1131 e4c7e0b0 2022-08-30 thomas add_addr(struct server *new_srv, struct address *h)
1132 e4c7e0b0 2022-08-30 thomas {
1133 e4c7e0b0 2022-08-30 thomas struct server *srv;
1134 e4c7e0b0 2022-08-30 thomas
1135 e4c7e0b0 2022-08-30 thomas /* Address cannot be shared between different servers. */
1136 e4c7e0b0 2022-08-30 thomas TAILQ_FOREACH(srv, &gotwebd->servers, entry) {
1137 e4c7e0b0 2022-08-30 thomas if (srv == new_srv)
1138 e4c7e0b0 2022-08-30 thomas continue;
1139 e4c7e0b0 2022-08-30 thomas if (addr_dup_check(&srv->al, h, new_srv->name, srv->name))
1140 e4c7e0b0 2022-08-30 thomas return -1;
1141 e4c7e0b0 2022-08-30 thomas }
1142 e4c7e0b0 2022-08-30 thomas
1143 e4c7e0b0 2022-08-30 thomas /* Tolerate duplicate address lines within the scope of a server. */
1144 e4c7e0b0 2022-08-30 thomas if (addr_dup_check(&new_srv->al, h, NULL, NULL) == 0)
1145 e4c7e0b0 2022-08-30 thomas TAILQ_INSERT_TAIL(&new_srv->al, h, entry);
1146 e4c7e0b0 2022-08-30 thomas else
1147 e4c7e0b0 2022-08-30 thomas free(h);
1148 e4c7e0b0 2022-08-30 thomas
1149 e4c7e0b0 2022-08-30 thomas return 0;
1150 e4c7e0b0 2022-08-30 thomas }