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