1 /*
2  * Copyright (c) 2013-2021 Joris Vink <joris@coders.se>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <sys/param.h>
18 #include <sys/types.h>
19 #include <sys/shm.h>
20 #include <sys/wait.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 #include <sys/socket.h>
24 
25 #include <openssl/rand.h>
26 
27 #include <fcntl.h>
28 #include <grp.h>
29 #include <pwd.h>
30 #include <signal.h>
31 
32 #include "kore.h"
33 
34 #if defined(KORE_USE_ACME)
35 #include "acme.h"
36 #endif
37 
38 #if !defined(KORE_NO_HTTP)
39 #include "http.h"
40 #endif
41 
42 #if defined(KORE_USE_PGSQL)
43 #include "pgsql.h"
44 #endif
45 
46 #if defined(KORE_USE_TASKS)
47 #include "tasks.h"
48 #endif
49 
50 #if defined(KORE_USE_PYTHON)
51 #include "python_api.h"
52 #endif
53 
54 #if defined(KORE_USE_CURL)
55 #include "curl.h"
56 #endif
57 
58 #if defined(__linux__)
59 #include "seccomp.h"
60 #endif
61 
62 #if !defined(WAIT_ANY)
63 #define WAIT_ANY		(-1)
64 #endif
65 
66 #define WORKER_SOLO_COUNT	3
67 
68 #define WORKER(id)						\
69 	(struct kore_worker *)((u_int8_t *)kore_workers +	\
70 	    (sizeof(struct kore_worker) * id))
71 
72 struct wlock {
73 	volatile int		lock;
74 	pid_t			current;
75 };
76 
77 static int	worker_trylock(void);
78 static void	worker_unlock(void);
79 static void	worker_reaper(pid_t, int);
80 
81 static inline int	worker_acceptlock_obtain(void);
82 static inline void	worker_acceptlock_release(void);
83 static void		worker_accept_avail(struct kore_msg *, const void *);
84 
85 static void	worker_entropy_recv(struct kore_msg *, const void *);
86 static void	worker_keymgr_response(struct kore_msg *, const void *);
87 
88 static int				accept_avail;
89 static struct kore_worker		*kore_workers;
90 static int				worker_no_lock;
91 static int				shm_accept_key;
92 static struct wlock			*accept_lock;
93 
94 struct kore_worker		*worker = NULL;
95 u_int8_t			worker_set_affinity = 1;
96 u_int32_t			worker_accept_threshold = 16;
97 u_int32_t			worker_rlimit_nofiles = 768;
98 u_int32_t			worker_max_connections = 512;
99 u_int32_t			worker_active_connections = 0;
100 int				worker_policy = KORE_WORKER_POLICY_RESTART;
101 
102 void
kore_worker_init(void)103 kore_worker_init(void)
104 {
105 	size_t			len;
106 	struct kore_worker	*kw;
107 	u_int16_t		idx, id, cpu;
108 
109 	worker_no_lock = 0;
110 
111 	if (worker_count == 0)
112 		worker_count = cpu_count;
113 
114 	/* Account for the keymgr/acme even if we don't end up starting it. */
115 	worker_count += 2;
116 
117 	len = sizeof(*accept_lock) +
118 	    (sizeof(struct kore_worker) * worker_count);
119 
120 	shm_accept_key = shmget(IPC_PRIVATE, len, IPC_CREAT | IPC_EXCL | 0700);
121 	if (shm_accept_key == -1)
122 		fatal("kore_worker_init(): shmget() %s", errno_s);
123 	if ((accept_lock = shmat(shm_accept_key, NULL, 0)) == (void *)-1)
124 		fatal("kore_worker_init(): shmat() %s", errno_s);
125 
126 	accept_lock->lock = 0;
127 	accept_lock->current = 0;
128 
129 	kore_workers = (struct kore_worker *)((u_int8_t *)accept_lock +
130 	    sizeof(*accept_lock));
131 	memset(kore_workers, 0, sizeof(struct kore_worker) * worker_count);
132 
133 	kore_debug("kore_worker_init(): system has %d cpu's", cpu_count);
134 	kore_debug("kore_worker_init(): starting %d workers", worker_count);
135 
136 	if (worker_count > cpu_count) {
137 		kore_debug("kore_worker_init(): more workers than cpu's");
138 	}
139 
140 	/* Setup log buffers. */
141 	for (idx = KORE_WORKER_BASE; idx < worker_count; idx++) {
142 		kw = WORKER(idx);
143 		kw->lb.offset = 0;
144 	}
145 
146 	/* Now start all the workers. */
147 	id = 1;
148 	cpu = 1;
149 	for (idx = KORE_WORKER_BASE; idx < worker_count; idx++) {
150 		if (cpu >= cpu_count)
151 			cpu = 0;
152 		kore_worker_spawn(idx, id++, cpu++);
153 	}
154 
155 	if (keymgr_active) {
156 #if defined(KORE_USE_ACME)
157 		/* The ACME process is only started if we need it. */
158 		if (acme_provider) {
159 			kore_worker_spawn(KORE_WORKER_ACME_IDX,
160 			    KORE_WORKER_ACME, 0);
161 		}
162 #endif
163 
164 		/* Now we can start the keymgr. */
165 		kore_worker_spawn(KORE_WORKER_KEYMGR_IDX,
166 		    KORE_WORKER_KEYMGR, 0);
167 	}
168 }
169 
170 void
kore_worker_spawn(u_int16_t idx,u_int16_t id,u_int16_t cpu)171 kore_worker_spawn(u_int16_t idx, u_int16_t id, u_int16_t cpu)
172 {
173 	struct kore_worker	*kw;
174 
175 	kw = WORKER(idx);
176 	kw->id = id;
177 	kw->cpu = cpu;
178 	kw->has_lock = 0;
179 	kw->active_hdlr = NULL;
180 	kw->running = 1;
181 
182 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, kw->pipe) == -1)
183 		fatal("socketpair(): %s", errno_s);
184 
185 	if (!kore_connection_nonblock(kw->pipe[0], 0) ||
186 	    !kore_connection_nonblock(kw->pipe[1], 0))
187 		fatal("could not set pipe fds to nonblocking: %s", errno_s);
188 
189 	kw->pid = fork();
190 	if (kw->pid == -1)
191 		fatal("could not spawn worker child: %s", errno_s);
192 
193 	if (kw->pid == 0) {
194 		kw->pid = getpid();
195 		kore_worker_entry(kw);
196 		/* NOTREACHED */
197 	}
198 }
199 
200 struct kore_worker *
kore_worker_data(u_int8_t id)201 kore_worker_data(u_int8_t id)
202 {
203 	if (id >= worker_count)
204 		fatal("id %u too large for worker count", id);
205 
206 	return (WORKER(id));
207 }
208 
209 void
kore_worker_shutdown(void)210 kore_worker_shutdown(void)
211 {
212 	struct kore_worker	*kw;
213 	pid_t			pid;
214 	int			status;
215 	u_int16_t		idx, done;
216 
217 	if (!kore_quiet) {
218 		kore_log(LOG_NOTICE,
219 		    "waiting for workers to drain and shutdown");
220 	}
221 
222 	for (;;) {
223 		for (idx = 0; idx < worker_count; idx++) {
224 			kw = WORKER(idx);
225 			if (kw->running == 0)
226 				continue;
227 
228 			if (kw->pid != 0) {
229 				pid = waitpid(kw->pid, &status, 0);
230 				if (pid == -1)
231 					continue;
232 
233 #if defined(__linux__)
234 				kore_seccomp_trace(kw->pid, status);
235 #endif
236 
237 				kw->pid = 0;
238 				kw->running = 0;
239 
240 				if (!kore_quiet) {
241 					kore_log(LOG_NOTICE, "worker %s exited",
242 					    kore_worker_name(kw->id));
243 				}
244 			}
245 		}
246 
247 		done = 0;
248 		for (idx = 0; idx < worker_count; idx++) {
249 			kw = WORKER(idx);
250 			if (kw->running == 0) {
251 				done++;
252 				continue;
253 			}
254 		}
255 
256 		if (done == worker_count)
257 			break;
258 	}
259 
260 	if (shmctl(shm_accept_key, IPC_RMID, NULL) == -1) {
261 		kore_log(LOG_NOTICE,
262 		    "failed to deleted shm segment: %s", errno_s);
263 	}
264 }
265 
266 void
kore_worker_dispatch_signal(int sig)267 kore_worker_dispatch_signal(int sig)
268 {
269 	u_int16_t		idx;
270 	struct kore_worker	*kw;
271 
272 	for (idx = 0; idx < worker_count; idx++) {
273 		kw = WORKER(idx);
274 
275 		if (kw->pid == -1 || kw->pid == 0)
276 			continue;
277 
278 		if (kill(kw->pid, sig) == -1) {
279 			kore_debug("kill(%d, %d): %s", kw->pid, sig, errno_s);
280 		}
281 	}
282 }
283 
284 void
kore_worker_privdrop(const char * runas,const char * root)285 kore_worker_privdrop(const char *runas, const char *root)
286 {
287 	rlim_t			fd;
288 	struct rlimit		rl;
289 	struct passwd		*pw = NULL;
290 
291 	if (root == NULL)
292 		fatalx("no root directory for kore_worker_privdrop");
293 
294 	/* Must happen before chroot. */
295 	if (skip_runas == 0) {
296 		if (runas == NULL)
297 			fatalx("no runas user given and -r not specified");
298 		pw = getpwnam(runas);
299 		if (pw == NULL) {
300 			fatalx("cannot getpwnam(\"%s\") for user: %s",
301 			    runas, errno_s);
302 		}
303 	}
304 
305 	if (skip_chroot == 0) {
306 		if (chroot(root) == -1) {
307 			fatalx("cannot chroot(\"%s\"): %s",
308 			    root, errno_s);
309 		}
310 
311 		if (chdir("/") == -1)
312 			fatalx("cannot chdir(\"/\"): %s", errno_s);
313 	} else {
314 		if (chdir(root) == -1)
315 			fatalx("cannot chdir(\"%s\"): %s", root, errno_s);
316 	}
317 
318 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
319 		kore_log(LOG_WARNING, "getrlimit(RLIMIT_NOFILE): %s", errno_s);
320 	} else {
321 		for (fd = 0; fd < rl.rlim_cur; fd++) {
322 			if (fcntl(fd, F_GETFD, NULL) != -1) {
323 				worker_rlimit_nofiles++;
324 			}
325 		}
326 	}
327 
328 	rl.rlim_cur = worker_rlimit_nofiles;
329 	rl.rlim_max = worker_rlimit_nofiles;
330 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
331 		kore_log(LOG_ERR, "setrlimit(RLIMIT_NOFILE, %u): %s",
332 		    worker_rlimit_nofiles, errno_s);
333 	}
334 
335 	if (skip_runas == 0) {
336 		if (setgroups(1, &pw->pw_gid) ||
337 #if defined(__MACH__) || defined(NetBSD)
338 		    setgid(pw->pw_gid) || setegid(pw->pw_gid) ||
339 		    setuid(pw->pw_uid) || seteuid(pw->pw_uid))
340 #else
341 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
342 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
343 #endif
344 			fatalx("cannot drop privileges");
345 	}
346 
347 	kore_platform_sandbox();
348 }
349 
350 void
kore_worker_entry(struct kore_worker * kw)351 kore_worker_entry(struct kore_worker *kw)
352 {
353 	struct kore_runtime_call	*rcall;
354 	u_int64_t			last_seed;
355 	int				quit, had_lock;
356 	u_int64_t			netwait, now, next_timeo;
357 
358 	worker = kw;
359 
360 #if defined(__linux__)
361 	kore_seccomp_traceme();
362 #endif
363 
364 	kore_platform_proctitle(kore_worker_name(kw->id));
365 
366 	if (worker_set_affinity == 1)
367 		kore_platform_worker_setcpu(kw);
368 
369 	kore_pid = kw->pid;
370 
371 	kore_signal_setup();
372 
373 	if (kw->id == KORE_WORKER_KEYMGR) {
374 		kore_keymgr_run();
375 		exit(0);
376 	}
377 
378 #if defined(KORE_USE_ACME)
379 	if (kw->id == KORE_WORKER_ACME) {
380 		kore_acme_run();
381 		exit(0);
382 	}
383 #endif
384 
385 	net_init();
386 	kore_connection_init();
387 	kore_platform_event_init();
388 	kore_msg_worker_init();
389 
390 #if defined(KORE_USE_TASKS)
391 	kore_task_init();
392 #endif
393 
394 	kore_worker_privdrop(kore_runas_user, kore_root_path);
395 
396 #if !defined(KORE_NO_HTTP)
397 	http_init();
398 	kore_filemap_resolve_paths();
399 	kore_accesslog_worker_init();
400 #endif
401 	kore_timer_init();
402 	kore_fileref_init();
403 	kore_domain_keymgr_init();
404 
405 	quit = 0;
406 	had_lock = 0;
407 	next_timeo = 0;
408 	accept_avail = 1;
409 	worker_active_connections = 0;
410 
411 	last_seed = 0;
412 
413 	if (keymgr_active) {
414 		kore_msg_register(KORE_MSG_CRL, worker_keymgr_response);
415 		kore_msg_register(KORE_MSG_ENTROPY_RESP, worker_entropy_recv);
416 		kore_msg_register(KORE_MSG_CERTIFICATE, worker_keymgr_response);
417 
418 		if (worker->restarted) {
419 			kore_msg_send(KORE_WORKER_KEYMGR,
420 			    KORE_MSG_CERTIFICATE_REQ, NULL, 0);
421 		}
422 #if defined(KORE_USE_ACME)
423 		kore_msg_register(KORE_ACME_CHALLENGE_SET_CERT,
424 		    worker_keymgr_response);
425 		kore_msg_register(KORE_ACME_CHALLENGE_CLEAR_CERT,
426 		    worker_keymgr_response);
427 #endif
428 	}
429 
430 	kore_msg_register(KORE_MSG_ACCEPT_AVAILABLE, worker_accept_avail);
431 
432 	if (nlisteners == 0)
433 		worker_no_lock = 1;
434 
435 	if (!kore_quiet) {
436 		kore_log(LOG_NOTICE,
437 		    "worker %d started (cpu#%d, pid#%d)",
438 		    kw->id, kw->cpu, kw->pid);
439 	}
440 
441 	rcall = kore_runtime_getcall("kore_worker_configure");
442 	if (rcall != NULL) {
443 		kore_runtime_execute(rcall);
444 		kore_free(rcall);
445 	}
446 
447 	kore_module_onload();
448 	worker->restarted = 0;
449 
450 	for (;;) {
451 		now = kore_time_ms();
452 
453 		if (keymgr_active && (now - last_seed) > KORE_RESEED_TIME) {
454 			kore_msg_send(KORE_WORKER_KEYMGR,
455 			    KORE_MSG_ENTROPY_REQ, NULL, 0);
456 			last_seed = now;
457 		}
458 
459 		if (!worker->has_lock && accept_avail) {
460 			if (worker_acceptlock_obtain()) {
461 				accept_avail = 0;
462 				if (had_lock == 0) {
463 					kore_platform_enable_accept();
464 					had_lock = 1;
465 				}
466 			}
467 		}
468 
469 		netwait = kore_timer_next_run(now);
470 
471 		if (netwait == KORE_WAIT_INFINITE) {
472 			if (sig_recv != 0)
473 				netwait = 10;
474 #if !defined(KORE_NO_HTTP)
475 			if (http_request_count > 0)
476 				netwait = 100;
477 #endif
478 		}
479 
480 #if defined(KORE_USE_PYTHON)
481 		if (kore_python_coro_pending())
482 			netwait = 0;
483 #endif
484 
485 		kore_platform_event_wait(netwait);
486 		now = kore_time_ms();
487 
488 		if (worker->has_lock)
489 			worker_acceptlock_release();
490 
491 		if (!worker->has_lock) {
492 			if (had_lock == 1) {
493 				had_lock = 0;
494 				kore_platform_disable_accept();
495 			}
496 		}
497 
498 		if (sig_recv != 0) {
499 			switch (sig_recv) {
500 			case SIGHUP:
501 				kore_module_reload(1);
502 				break;
503 			case SIGQUIT:
504 			case SIGINT:
505 			case SIGTERM:
506 				quit = 1;
507 				break;
508 			case SIGCHLD:
509 #if defined(KORE_USE_PYTHON)
510 				kore_python_proc_reap();
511 #endif
512 				break;
513 			default:
514 				break;
515 			}
516 
517 			sig_recv = 0;
518 		}
519 
520 		if (quit)
521 			break;
522 
523 		kore_timer_run(now);
524 #if defined(KORE_USE_CURL)
525 		kore_curl_run_scheduled();
526 		kore_curl_do_timeout();
527 #endif
528 #if !defined(KORE_NO_HTTP)
529 		http_process();
530 #endif
531 #if defined(KORE_USE_PYTHON)
532 		kore_python_coro_run();
533 #endif
534 		if (next_timeo <= now) {
535 			kore_connection_check_timeout(now);
536 			next_timeo = now + 500;
537 		}
538 
539 		kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
540 	}
541 
542 	rcall = kore_runtime_getcall("kore_worker_teardown");
543 	if (rcall != NULL) {
544 		kore_runtime_execute(rcall);
545 		kore_free(rcall);
546 	}
547 
548 	kore_msg_send(KORE_MSG_PARENT, KORE_MSG_SHUTDOWN, NULL, 0);
549 	kore_server_cleanup();
550 
551 	kore_platform_event_cleanup();
552 	kore_connection_cleanup();
553 	kore_domain_cleanup();
554 	kore_module_cleanup();
555 #if !defined(KORE_NO_HTTP)
556 	http_cleanup();
557 #endif
558 	net_cleanup();
559 
560 #if defined(KORE_USE_PYTHON)
561 	kore_python_cleanup();
562 #endif
563 
564 #if defined(KORE_USE_PGSQL)
565 	kore_pgsql_sys_cleanup();
566 #endif
567 
568 	kore_debug("worker %d shutting down", kw->id);
569 
570 	kore_mem_cleanup();
571 	exit(0);
572 }
573 
574 void
kore_worker_reap(void)575 kore_worker_reap(void)
576 {
577 	pid_t			pid;
578 	int			status;
579 
580 	for (;;) {
581 		pid = waitpid(WAIT_ANY, &status, WNOHANG);
582 
583 		if (pid == -1) {
584 			if (errno == ECHILD)
585 				return;
586 			if (errno == EINTR)
587 				continue;
588 			kore_log(LOG_ERR,
589 			    "failed to wait for children: %s", errno_s);
590 			return;
591 		}
592 
593 		if (pid == 0)
594 			return;
595 
596 		worker_reaper(pid, status);
597 	}
598 }
599 
600 void
kore_worker_make_busy(void)601 kore_worker_make_busy(void)
602 {
603 	if (worker_count == WORKER_SOLO_COUNT || worker_no_lock == 1)
604 		return;
605 
606 	if (worker->has_lock) {
607 		worker_unlock();
608 		worker->has_lock = 0;
609 		kore_msg_send(KORE_MSG_WORKER_ALL,
610 		    KORE_MSG_ACCEPT_AVAILABLE, NULL, 0);
611 	}
612 }
613 
614 int
kore_worker_keymgr_response_verify(struct kore_msg * msg,const void * data,struct kore_domain ** out)615 kore_worker_keymgr_response_verify(struct kore_msg *msg, const void *data,
616     struct kore_domain **out)
617 {
618 	struct kore_server		*srv;
619 	struct kore_domain		*dom;
620 	const struct kore_x509_msg	*req;
621 
622 	if (msg->length < sizeof(*req)) {
623 		kore_log(LOG_WARNING,
624 		    "short keymgr message (%zu)", msg->length);
625 		return (KORE_RESULT_ERROR);
626 	}
627 
628 	req = (const struct kore_x509_msg *)data;
629 	if (msg->length != (sizeof(*req) + req->data_len)) {
630 		kore_log(LOG_WARNING,
631 		    "invalid keymgr payload (%zu)", msg->length);
632 		return (KORE_RESULT_ERROR);
633 	}
634 
635 	if (req->domain[KORE_DOMAINNAME_LEN] != '\0') {
636 		kore_log(LOG_WARNING, "domain not NUL-terminated");
637 		return (KORE_RESULT_ERROR);
638 
639 	}
640 
641 	if (out == NULL)
642 		return (KORE_RESULT_OK);
643 
644 	dom = NULL;
645 
646 	LIST_FOREACH(srv, &kore_servers, list) {
647 		dom = NULL;
648 
649 		if (srv->tls == 0)
650 			continue;
651 
652 		TAILQ_FOREACH(dom, &srv->domains, list) {
653 			if (!strcmp(dom->domain, req->domain))
654 				break;
655 		}
656 
657 		if (dom != NULL)
658 			break;
659 	}
660 
661 	if (dom == NULL) {
662 		kore_log(LOG_WARNING,
663 		    "got keymgr response for domain that does not exist");
664 		return (KORE_RESULT_ERROR);
665 	}
666 
667 	*out = dom;
668 
669 	return (KORE_RESULT_OK);
670 }
671 
672 static void
worker_reaper(pid_t pid,int status)673 worker_reaper(pid_t pid, int status)
674 {
675 	u_int16_t		idx;
676 	struct kore_worker	*kw;
677 	const char		*func;
678 
679 #if defined(__linux__)
680 	if (kore_seccomp_trace(pid, status))
681 		return;
682 #endif
683 
684 	for (idx = 0; idx < worker_count; idx++) {
685 		kw = WORKER(idx);
686 		if (kw->pid != pid)
687 			continue;
688 
689 		if (!kore_quiet) {
690 			kore_log(LOG_NOTICE,
691 			    "worker %s (%d) exited with status %d",
692 			    kore_worker_name(kw->id), pid, status);
693 		}
694 
695 		kw->running = 0;
696 
697 		if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
698 			kw->pid = 0;
699 			break;
700 		}
701 
702 		func = "none";
703 #if !defined(KORE_NO_HTTP)
704 		if (kw->active_hdlr != NULL)
705 			func = kw->active_hdlr->func;
706 #endif
707 		kore_log(LOG_NOTICE,
708 		    "worker %d (pid: %d) (hdlr: %s) gone",
709 		    kw->id, kw->pid, func);
710 
711 #if defined(__linux__)
712 		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSYS) {
713 			kore_log(LOG_NOTICE,
714 			    "worker %d died from sandbox violation", kw->id);
715 		}
716 #endif
717 
718 		if (kw->id == KORE_WORKER_KEYMGR ||
719 		    kw->id == KORE_WORKER_ACME) {
720 			kore_log(LOG_CRIT,
721 			    "keymgr or acme process gone, stopping");
722 			kw->pid = 0;
723 			if (raise(SIGTERM) != 0) {
724 				kore_log(LOG_WARNING,
725 				    "failed to raise SIGTERM signal");
726 			}
727 			break;
728 		}
729 
730 		if (kw->pid == accept_lock->current &&
731 		    worker_no_lock == 0)
732 			worker_unlock();
733 
734 #if !defined(KORE_NO_HTTP)
735 		if (kw->active_hdlr != NULL) {
736 			kw->active_hdlr->errors++;
737 			kore_log(LOG_NOTICE,
738 			    "hdlr %s has caused %d error(s)",
739 			    kw->active_hdlr->func,
740 			    kw->active_hdlr->errors);
741 		}
742 #endif
743 
744 		if (worker_policy == KORE_WORKER_POLICY_TERMINATE) {
745 			kw->pid = 0;
746 			kore_log(LOG_NOTICE,
747 			    "worker policy is 'terminate', stopping");
748 			if (raise(SIGTERM) != 0) {
749 				kore_log(LOG_WARNING,
750 				    "failed to raise SIGTERM signal");
751 			}
752 			break;
753 		}
754 
755 		kore_log(LOG_NOTICE, "restarting worker %d", kw->id);
756 		kw->restarted = 1;
757 		kore_msg_parent_remove(kw);
758 		kore_worker_spawn(idx, kw->id, kw->cpu);
759 		kore_msg_parent_add(kw);
760 
761 		break;
762 	}
763 }
764 
765 static inline void
worker_acceptlock_release(void)766 worker_acceptlock_release(void)
767 {
768 	if (worker_count == WORKER_SOLO_COUNT || worker_no_lock == 1)
769 		return;
770 
771 	if (worker->has_lock != 1)
772 		return;
773 
774 	if (worker_active_connections < worker_max_connections) {
775 #if !defined(KORE_NO_HTTP)
776 		if (http_request_count < http_request_limit)
777 			return;
778 #else
779 		return;
780 #endif
781 	}
782 
783 #if defined(WORKER_DEBUG)
784 	kore_log(LOG_DEBUG, "worker busy, releasing lock");
785 #endif
786 
787 	worker_unlock();
788 	worker->has_lock = 0;
789 
790 	kore_msg_send(KORE_MSG_WORKER_ALL, KORE_MSG_ACCEPT_AVAILABLE, NULL, 0);
791 }
792 
793 static inline int
worker_acceptlock_obtain(void)794 worker_acceptlock_obtain(void)
795 {
796 	int		r;
797 
798 	if (worker->has_lock == 1)
799 		return (1);
800 
801 	if (worker_count == WORKER_SOLO_COUNT || worker_no_lock == 1) {
802 		worker->has_lock = 1;
803 		return (1);
804 	}
805 
806 	if (worker_active_connections >= worker_max_connections)
807 		return (0);
808 
809 #if !defined(KORE_NO_HTTP)
810 	if (http_request_count >= http_request_limit)
811 		return (0);
812 #endif
813 
814 	r = 0;
815 	if (worker_trylock()) {
816 		r = 1;
817 		worker->has_lock = 1;
818 #if defined(WORKER_DEBUG)
819 		kore_log(LOG_DEBUG, "got lock");
820 #endif
821 	}
822 
823 	return (r);
824 }
825 
826 static int
worker_trylock(void)827 worker_trylock(void)
828 {
829 	if (!__sync_bool_compare_and_swap(&(accept_lock->lock), 0, 1))
830 		return (0);
831 
832 	accept_lock->current = worker->pid;
833 
834 	return (1);
835 }
836 
837 static void
worker_unlock(void)838 worker_unlock(void)
839 {
840 	accept_lock->current = 0;
841 	if (!__sync_bool_compare_and_swap(&(accept_lock->lock), 1, 0))
842 		kore_log(LOG_NOTICE, "worker_unlock(): wasn't locked");
843 }
844 
845 static void
worker_accept_avail(struct kore_msg * msg,const void * data)846 worker_accept_avail(struct kore_msg *msg, const void *data)
847 {
848 	accept_avail = 1;
849 }
850 
851 static void
worker_entropy_recv(struct kore_msg * msg,const void * data)852 worker_entropy_recv(struct kore_msg *msg, const void *data)
853 {
854 	if (msg->length != 1024) {
855 		kore_log(LOG_WARNING,
856 		    "invalid entropy response (got:%zu - wanted:1024)",
857 		    msg->length);
858 	}
859 
860 	RAND_poll();
861 	RAND_seed(data, msg->length);
862 }
863 
864 static void
worker_keymgr_response(struct kore_msg * msg,const void * data)865 worker_keymgr_response(struct kore_msg *msg, const void *data)
866 {
867 	struct kore_domain		*dom;
868 	const struct kore_x509_msg	*req;
869 
870 	if (!kore_worker_keymgr_response_verify(msg, data, &dom))
871 		return;
872 
873 	req = (const struct kore_x509_msg *)data;
874 
875 	switch (msg->id) {
876 	case KORE_MSG_CERTIFICATE:
877 		kore_domain_tlsinit(dom, KORE_PEM_CERT_CHAIN,
878 		    req->data, req->data_len);
879 		break;
880 	case KORE_MSG_CRL:
881 		kore_domain_crl_add(dom, req->data, req->data_len);
882 		break;
883 #if defined(KORE_USE_ACME)
884 	case KORE_ACME_CHALLENGE_SET_CERT:
885 		if (dom->ssl_ctx == NULL) {
886 			kore_domain_tlsinit(dom, KORE_DER_CERT_DATA,
887 			    req->data, req->data_len);
888 		}
889 
890 		kore_free(dom->acme_cert);
891 		dom->acme_cert_len = req->data_len;
892 		dom->acme_cert = kore_calloc(1, req->data_len);
893 		memcpy(dom->acme_cert, req->data, req->data_len);
894 
895 		kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge active",
896 		    dom->domain);
897 		dom->acme_challenge = 1;
898 		break;
899 	case KORE_ACME_CHALLENGE_CLEAR_CERT:
900 		dom->acme_cert_len = 0;
901 		dom->acme_challenge = 0;
902 		kore_free(dom->acme_cert);
903 		kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge disabled",
904 		    dom->domain);
905 		break;
906 #endif
907 	default:
908 		kore_log(LOG_WARNING, "unknown keymgr request %u", msg->id);
909 		break;
910 	}
911 }
912