2 * Copyright (c) 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/types.h>
19 #include <sys/queue.h>
22 #include <sys/socket.h>
25 #include <netinet/in.h>
37 #include "got_opentemp.h"
38 #include "got_reference.h"
40 #include "got_compat.h"
46 config_init(struct gotwebd
*env
)
48 struct privsep
*ps
= env
->gotwebd_ps
;
51 /* Global configuration. */
52 if (privsep_process
== PROC_GOTWEBD
)
53 env
->prefork_gotwebd
= GOTWEBD_NUMPROC
;
55 ps
->ps_what
[PROC_GOTWEBD
] = CONFIG_ALL
;
56 ps
->ps_what
[PROC_SOCKS
] = CONFIG_SOCKS
;
58 /* Other configuration. */
59 what
= ps
->ps_what
[privsep_process
];
60 if (what
& CONFIG_SOCKS
) {
62 TAILQ_INIT(&env
->servers
);
63 TAILQ_INIT(&env
->sockets
);
69 config_getcfg(struct gotwebd
*env
, struct imsg
*imsg
)
71 /* nothing to do but tell gotwebd configuration is done */
72 if (privsep_process
!= PROC_GOTWEBD
)
73 proc_compose(env
->gotwebd_ps
, PROC_GOTWEBD
,
74 IMSG_CFG_DONE
, NULL
, 0);
80 config_setserver(struct gotwebd
*env
, struct server
*srv
)
83 struct privsep
*ps
= env
->gotwebd_ps
;
85 memcpy(&ssrv
, srv
, sizeof(ssrv
));
86 if (proc_compose(ps
, PROC_SOCKS
, IMSG_CFG_SRV
, &ssrv
, sizeof(ssrv
))
88 fatal("proc_compose");
93 config_getserver(struct gotwebd
*env
, struct imsg
*imsg
)
96 uint8_t *p
= imsg
->data
;
98 IMSG_SIZE_CHECK(imsg
, &srv
);
100 srv
= calloc(1, sizeof(*srv
));
102 fatalx("%s: calloc", __func__
);
104 if (IMSG_DATA_SIZE(imsg
) != sizeof(*srv
)) {
105 log_debug("%s: imsg size error", __func__
);
110 memcpy(srv
, p
, sizeof(*srv
));
111 srv
->cached_repos
= calloc(GOTWEBD_REPO_CACHESIZE
,
112 sizeof(*srv
->cached_repos
));
113 if (srv
->cached_repos
== NULL
)
114 fatal("%s: calloc", __func__
);
115 srv
->ncached_repos
= 0;
117 /* log server info */
118 log_debug("%s: server=%s fcgi_socket=%s unix_socket=%s", __func__
,
119 srv
->name
, srv
->fcgi_socket
? "yes" : "no", srv
->unix_socket
?
122 TAILQ_INSERT_TAIL(&env
->servers
, srv
, entry
);
128 config_setsock(struct gotwebd
*env
, struct socket
*sock
)
130 struct privsep
*ps
= env
->gotwebd_ps
;
131 struct socket_conf s
;
138 /* open listening sockets */
139 if (sockets_privinit(env
, sock
) == -1)
142 for (id
= 0; id
< PROC_MAX
; id
++) {
143 what
= ps
->ps_what
[id
];
145 if ((what
& CONFIG_SOCKS
) == 0 || id
== privsep_process
)
148 memcpy(&s
, &sock
->conf
, sizeof(s
));
151 iov
[c
].iov_base
= &s
;
152 iov
[c
++].iov_len
= sizeof(s
);
154 if (id
== PROC_SOCKS
) {
155 /* XXX imsg code will close the fd after 1st call */
157 proc_range(ps
, id
, &n
, &m
);
158 for (n
= 0; n
< m
; n
++) {
161 else if ((fd
= dup(sock
->fd
)) == -1)
163 if (proc_composev_imsg(ps
, id
, n
, IMSG_CFG_SOCK
,
164 -1, fd
, iov
, c
) != 0) {
165 log_warn("%s: failed to compose "
166 "IMSG_CFG_SOCK imsg",
170 if (proc_flush_imsg(ps
, id
, n
) == -1) {
171 log_warn("%s: failed to flush "
172 "IMSG_CFG_SOCK imsg",
180 /* Close socket early to prevent fd exhaustion in gotwebd. */
181 if (sock
->fd
!= -1) {
190 config_getsock(struct gotwebd
*env
, struct imsg
*imsg
)
192 struct socket
*sock
= NULL
;
193 struct socket_conf sock_conf
;
194 uint8_t *p
= imsg
->data
;
197 IMSG_SIZE_CHECK(imsg
, &sock_conf
);
198 memcpy(&sock_conf
, p
, sizeof(sock_conf
));
200 if (IMSG_DATA_SIZE(imsg
) != sizeof(sock_conf
)) {
201 log_debug("%s: imsg size error", __func__
);
205 /* create a new socket */
206 if ((sock
= calloc(1, sizeof(*sock
))) == NULL
) {
212 memcpy(&sock
->conf
, &sock_conf
, sizeof(sock
->conf
));
215 TAILQ_INSERT_TAIL(&env
->sockets
, sock
, entry
);
217 for (i
= 0; i
< PRIV_FDS__MAX
; i
++)
218 sock
->priv_fd
[i
] = -1;
220 for (i
= 0; i
< GOTWEB_PACK_NUM_TEMPFILES
; i
++)
221 sock
->pack_fds
[i
] = -1;
223 /* log new socket info */
224 log_debug("%s: name=%s id=%d server=%s af_type=%s socket_path=%s",
225 __func__
, sock
->conf
.name
, sock
->conf
.id
, sock
->conf
.srv_name
,
226 sock
->conf
.af_type
== AF_UNIX
? "unix" :
227 (sock
->conf
.af_type
== AF_INET
? "inet" :
228 (sock
->conf
.af_type
== AF_INET6
? "inet6" : "unknown")),
229 strlen(sock
->conf
.unix_socket_name
) ?
230 sock
->conf
.unix_socket_name
: "none");
236 config_setfd(struct gotwebd
*env
, struct socket
*sock
)
238 struct privsep
*ps
= env
->gotwebd_ps
;
240 int fd
= -1, n
, m
, j
;
245 log_debug("%s: Allocating %d file descriptors",
246 __func__
, PRIV_FDS__MAX
+ GOTWEB_PACK_NUM_TEMPFILES
);
248 for (j
= 0; j
< PRIV_FDS__MAX
+ GOTWEB_PACK_NUM_TEMPFILES
; j
++) {
249 for (id
= 0; id
< PROC_MAX
; id
++) {
250 what
= ps
->ps_what
[id
];
252 if ((what
& CONFIG_SOCKS
) == 0 || id
== privsep_process
)
257 iov
[c
].iov_base
= &s
;
258 iov
[c
++].iov_len
= sizeof(s
);
260 if (id
== PROC_SOCKS
) {
262 * XXX imsg code will close the fd
266 proc_range(ps
, id
, &n
, &m
);
267 for (n
= 0; n
< m
; n
++) {
268 fd
= got_opentempfd();
271 if (proc_composev_imsg(ps
, id
, n
,
272 IMSG_CFG_FD
, -1, fd
, iov
, c
) != 0) {
273 log_warn("%s: failed to compose "
278 if (proc_flush_imsg(ps
, id
, n
) == -1) {
279 log_warn("%s: failed to flush "
288 /* Close fd early to prevent fd exhaustion in gotwebd. */
296 config_getfd(struct gotwebd
*env
, struct imsg
*imsg
)
299 uint8_t *p
= imsg
->data
;
300 int sock_id
, match
= 0, i
;
302 IMSG_SIZE_CHECK(imsg
, &sock_id
);
303 memcpy(&sock_id
, p
, sizeof(sock_id
));
305 TAILQ_FOREACH(sock
, &env
->sockets
, entry
) {
306 const int nfds
= (GOTWEB_PACK_NUM_TEMPFILES
+ PRIV_FDS__MAX
);
307 for (i
= 0; i
< nfds
; i
++) {
308 if (i
< PRIV_FDS__MAX
&& sock
->priv_fd
[i
] == -1) {
309 log_debug("%s: assigning socket %d priv_fd %d",
310 __func__
, sock_id
, imsg
->fd
);
311 sock
->priv_fd
[i
] = imsg
->fd
;
315 if (sock
->pack_fds
[i
- PRIV_FDS__MAX
] == -1) {
316 log_debug("%s: assigning socket %d pack_fd %d",
317 __func__
, sock_id
, imsg
->fd
);
318 sock
->pack_fds
[i
- PRIV_FDS__MAX
] = imsg
->fd
;