]> jfr.im git - solanum.git/blame - ircd/sslproc.c
sslproc: prefix SPKI certfp types to distinguish them from CERT
[solanum.git] / ircd / sslproc.c
CommitLineData
f8451915
AC
1/*
2 * sslproc.c: An interface to ssld
3 * Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
4 * Copyright (C) 2007 ircd-ratbox development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
f8451915
AC
20 */
21
fe037171 22#include <rb_lib.h>
f8451915 23#include "stdinc.h"
3202e249
VY
24
25
f8451915
AC
26#include "s_conf.h"
27#include "logger.h"
28#include "listener.h"
29#include "sslproc.h"
30#include "s_serv.h"
31#include "ircd.h"
32#include "hash.h"
33#include "client.h"
34#include "send.h"
35#include "packet.h"
36
37#define ZIPSTATS_TIME 60
38
39static void collect_zipstats(void *unused);
3202e249 40static void ssl_read_ctl(rb_fde_t * F, void *data);
f8451915
AC
41static int ssld_count;
42
3202e249 43static char tmpbuf[READBUF_SIZE];
f8451915
AC
44static char nul = '\0';
45
46#define MAXPASSFD 4
47#define READSIZE 1024
48typedef struct _ssl_ctl_buf
49{
50 rb_dlink_node node;
51 char *buf;
52 size_t buflen;
53 rb_fde_t *F[MAXPASSFD];
54 int nfds;
55} ssl_ctl_buf_t;
56
57
58struct _ssl_ctl
59{
60 rb_dlink_node node;
61 int cli_count;
62 rb_fde_t *F;
63 rb_fde_t *P;
64 pid_t pid;
65 rb_dlink_list readq;
66 rb_dlink_list writeq;
eb1b303d 67 uint8_t shutdown;
0862e335 68 uint8_t dead;
e9ffc3c1 69 char version[256];
f8451915
AC
70};
71
93ad89b2 72static void ssld_update_config_one(ssl_ctl_t *ctl);
f7b0c4b3 73static void send_new_ssl_certs_one(ssl_ctl_t * ctl);
93ad89b2 74static void send_certfp_method(ssl_ctl_t *ctl);
f8451915
AC
75
76
77static rb_dlink_list ssl_daemons;
78
196740c4
AC
79static inline uint32_t
80buf_to_uint32(char *buf)
f8451915 81{
196740c4 82 uint32_t x;
0862e335 83 memcpy(&x, buf, sizeof(x));
f8451915
AC
84 return x;
85}
86
3202e249 87static inline void
196740c4 88uint32_to_buf(char *buf, uint32_t x)
f8451915 89{
0862e335 90 memcpy(buf, &x, sizeof(x));
f8451915
AC
91 return;
92}
93
f8451915 94static ssl_ctl_t *
3202e249 95allocate_ssl_daemon(rb_fde_t * F, rb_fde_t * P, int pid)
f8451915
AC
96{
97 ssl_ctl_t *ctl;
3202e249 98
f8451915
AC
99 if(F == NULL || pid < 0)
100 return NULL;
3202e249 101 ctl = rb_malloc(sizeof(ssl_ctl_t));
f8451915
AC
102 ctl->F = F;
103 ctl->P = P;
104 ctl->pid = pid;
105 ssld_count++;
106 rb_dlinkAdd(ctl, &ctl->node, &ssl_daemons);
107 return ctl;
108}
109
110static void
3202e249 111free_ssl_daemon(ssl_ctl_t * ctl)
f8451915
AC
112{
113 rb_dlink_node *ptr;
114 ssl_ctl_buf_t *ctl_buf;
115 int x;
116 if(ctl->cli_count)
117 return;
3202e249 118
f8451915
AC
119 RB_DLINK_FOREACH(ptr, ctl->readq.head)
120 {
121 ctl_buf = ptr->data;
122 for(x = 0; x < ctl_buf->nfds; x++)
3202e249 123 rb_close(ctl_buf->F[x]);
f8451915
AC
124
125 rb_free(ctl_buf->buf);
3202e249 126 rb_free(ctl_buf);
f8451915
AC
127 }
128
129 RB_DLINK_FOREACH(ptr, ctl->writeq.head)
130 {
131 ctl_buf = ptr->data;
132 for(x = 0; x < ctl_buf->nfds; x++)
133 rb_close(ctl_buf->F[x]);
134
135 rb_free(ctl_buf->buf);
136 rb_free(ctl_buf);
137 }
138 rb_close(ctl->F);
139 rb_close(ctl->P);
140 rb_dlinkDelete(&ctl->node, &ssl_daemons);
141 rb_free(ctl);
142}
143
144static char *ssld_path;
145
146static int ssld_spin_count = 0;
147static time_t last_spin;
148static int ssld_wait = 0;
149
150
eb1b303d
SA
151void
152restart_ssld(void)
153{
154 rb_dlink_node *ptr, *next;
155 ssl_ctl_t *ctl;
156
157 RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head)
158 {
159 ctl = ptr->data;
160 if(ctl->dead)
161 continue;
162 if(ctl->shutdown)
163 continue;
164 ctl->shutdown = 1;
165 ssld_count--;
166 if(!ctl->cli_count)
167 {
168 rb_kill(ctl->pid, SIGKILL);
169 free_ssl_daemon(ctl);
170 }
171 }
172
f7b0c4b3 173 start_ssldaemon(ServerInfo.ssld_count);
eb1b303d
SA
174}
175
f8451915
AC
176static void
177ssl_killall(void)
178{
179 rb_dlink_node *ptr, *next;
180 ssl_ctl_t *ctl;
181 RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head)
182 {
183 ctl = ptr->data;
184 if(ctl->dead)
185 continue;
186 ctl->dead = 1;
eb1b303d
SA
187 if(!ctl->shutdown)
188 ssld_count--;
3202e249 189 rb_kill(ctl->pid, SIGKILL);
eb1b303d
SA
190 if(!ctl->cli_count)
191 free_ssl_daemon(ctl);
f8451915
AC
192 }
193}
194
195static void
3202e249 196ssl_dead(ssl_ctl_t * ctl)
f8451915
AC
197{
198 if(ctl->dead)
199 return;
3202e249 200
f8451915 201 ctl->dead = 1;
3202e249 202 rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */
eb1b303d
SA
203
204 if(!ctl->shutdown)
205 {
206 ssld_count--;
207 ilog(L_MAIN, "ssld helper died - attempting to restart");
208 sendto_realops_snomask(SNO_GENERAL, L_ALL, "ssld helper died - attempting to restart");
f7b0c4b3 209 start_ssldaemon(1);
eb1b303d 210 }
f8451915
AC
211}
212
213static void
3202e249 214ssl_do_pipe(rb_fde_t * F, void *data)
f8451915
AC
215{
216 int retlen;
217 ssl_ctl_t *ctl = data;
218 retlen = rb_write(F, "0", 1);
219 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
220 {
221 ssl_dead(ctl);
222 return;
223 }
224 rb_setselect(F, RB_SELECT_READ, ssl_do_pipe, data);
225}
226
227static void
228restart_ssld_event(void *unused)
229{
230 ssld_spin_count = 0;
231 last_spin = 0;
232 ssld_wait = 0;
233 if(ServerInfo.ssld_count > get_ssld_count())
234 {
235 int start = ServerInfo.ssld_count - get_ssld_count();
236 ilog(L_MAIN, "Attempting to restart ssld processes");
536845c5 237 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Attempt to restart ssld processes");
f7b0c4b3 238 start_ssldaemon(start);
f8451915
AC
239 }
240}
241
242int
f7b0c4b3 243start_ssldaemon(int count)
f8451915
AC
244{
245 rb_fde_t *F1, *F2;
246 rb_fde_t *P1, *P2;
3202e249
VY
247#ifdef _WIN32
248 const char *suffix = ".exe";
249#else
250 const char *suffix = "";
251#endif
252
f8451915
AC
253 char fullpath[PATH_MAX + 1];
254 char fdarg[6];
255 const char *parv[2];
256 char buf[128];
3202e249 257 char s_pid[10];
f8451915
AC
258 pid_t pid;
259 int started = 0, i;
260
261 if(ssld_wait)
262 return 0;
263
264 if(ssld_spin_count > 20 && (rb_current_time() - last_spin < 5))
265 {
b9249347 266 ilog(L_MAIN, "ssld helper is spinning - will attempt to restart in 1 minute");
3202e249
VY
267 sendto_realops_snomask(SNO_GENERAL, L_ALL,
268 "ssld helper is spinning - will attempt to restart in 1 minute");
f8451915
AC
269 rb_event_add("restart_ssld_event", restart_ssld_event, NULL, 60);
270 ssld_wait = 1;
271 return 0;
272 }
273
274 ssld_spin_count++;
275 last_spin = rb_current_time();
3202e249 276
f8451915
AC
277 if(ssld_path == NULL)
278 {
4d8cfacd 279 snprintf(fullpath, sizeof(fullpath), "%s%cssld%s", ircd_paths[IRCD_PATH_LIBEXEC], RB_PATH_SEPARATOR, suffix);
3202e249 280
f8451915
AC
281 if(access(fullpath, X_OK) == -1)
282 {
4d8cfacd
AC
283 snprintf(fullpath, sizeof(fullpath), "%s%cbin%cssld%s",
284 ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix);
f8451915
AC
285 if(access(fullpath, X_OK) == -1)
286 {
3202e249 287 ilog(L_MAIN,
c74836dc 288 "Unable to execute ssld%s in %s or %s/bin",
4d8cfacd 289 suffix, ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
3202e249 290 return 0;
f8451915
AC
291 }
292 }
293 ssld_path = rb_strdup(fullpath);
294 }
b697c329 295 rb_strlcpy(buf, "-ircd ssld daemon", sizeof(buf));
f8451915
AC
296 parv[0] = buf;
297 parv[1] = NULL;
298
299 for(i = 0; i < count; i++)
300 {
301 ssl_ctl_t *ctl;
eda22d87
JT
302 if(rb_socketpair(AF_UNIX, SOCK_DGRAM, 0, &F1, &F2, "SSL/TLS handle passing socket") == -1)
303 {
304 ilog(L_MAIN, "Unable to create ssld - rb_socketpair failed: %s", strerror(errno));
305 return started;
306 }
55abcbb2 307
f8451915
AC
308 rb_set_buffers(F1, READBUF_SIZE);
309 rb_set_buffers(F2, READBUF_SIZE);
5203cba5 310 snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(F2));
3202e249 311 rb_setenv("CTL_FD", fdarg, 1);
cf09122b
JT
312 if(rb_pipe(&P1, &P2, "SSL/TLS pipe") == -1)
313 {
314 ilog(L_MAIN, "Unable to create ssld - rb_pipe failed: %s", strerror(errno));
315 return started;
316 }
5203cba5 317 snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(P1));
3202e249 318 rb_setenv("CTL_PIPE", fdarg, 1);
5203cba5 319 snprintf(s_pid, sizeof(s_pid), "%d", (int)getpid());
3202e249
VY
320 rb_setenv("CTL_PPID", s_pid, 1);
321#ifdef _WIN32
322 SetHandleInformation((HANDLE) rb_get_fd(F2), HANDLE_FLAG_INHERIT, 1);
323 SetHandleInformation((HANDLE) rb_get_fd(P1), HANDLE_FLAG_INHERIT, 1);
324#endif
325
326 pid = rb_spawn_process(ssld_path, (const char **) parv);
f8451915
AC
327 if(pid == -1)
328 {
329 ilog(L_MAIN, "Unable to create ssld: %s\n", strerror(errno));
330 rb_close(F1);
331 rb_close(F2);
332 rb_close(P1);
333 rb_close(P2);
334 return started;
335 }
336 started++;
337 rb_close(F2);
338 rb_close(P1);
339 ctl = allocate_ssl_daemon(F1, P2, pid);
bfc44622 340 if(ircd_ssl_ok)
93ad89b2 341 ssld_update_config_one(ctl);
f8451915
AC
342 ssl_read_ctl(ctl->F, ctl);
343 ssl_do_pipe(P2, ctl);
3202e249 344
f8451915 345 }
3202e249 346 return started;
f8451915
AC
347}
348
349static void
3202e249 350ssl_process_zipstats(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
f8451915
AC
351{
352 struct Client *server;
353 struct ZipStats *zips;
4f7a1fee 354 char *parv[7];
32fb5895 355 (void) rb_string_to_array(ctl_buf->buf, parv, 6);
f8451915
AC
356 server = find_server(NULL, parv[1]);
357 if(server == NULL || server->localClient == NULL || !IsCapable(server, CAP_ZIP))
358 return;
359 if(server->localClient->zipstats == NULL)
360 server->localClient->zipstats = rb_malloc(sizeof(struct ZipStats));
3202e249 361
f8451915
AC
362 zips = server->localClient->zipstats;
363
364 zips->in += strtoull(parv[2], NULL, 10);
365 zips->in_wire += strtoull(parv[3], NULL, 10);
366 zips->out += strtoull(parv[4], NULL, 10);
367 zips->out_wire += strtoull(parv[5], NULL, 10);
3202e249 368
f8451915 369 if(zips->in > 0)
3202e249 370 zips->in_ratio = ((double) (zips->in - zips->in_wire) / (double) zips->in) * 100.00;
f8451915
AC
371 else
372 zips->in_ratio = 0;
3202e249 373
f8451915 374 if(zips->out > 0)
3202e249 375 zips->out_ratio = ((double) (zips->out - zips->out_wire) / (double) zips->out) * 100.00;
f8451915
AC
376 else
377 zips->out_ratio = 0;
378}
379
4fbb7362
SA
380static void
381ssl_process_open_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
382{
383 struct Client *client_p;
384 uint32_t fd;
385
386 if(ctl_buf->buflen < 5)
387 return; /* bogus message..drop it.. XXX should warn here */
388
389 fd = buf_to_uint32(&ctl_buf->buf[1]);
390 client_p = find_cli_connid_hash(fd);
391 if(client_p == NULL || client_p->localClient == NULL)
392 return;
393
394 if(client_p->localClient->ssl_callback)
395 {
396 CNCB *hdl = client_p->localClient->ssl_callback;
397 void *data = client_p->localClient->ssl_data;
398
399 client_p->localClient->ssl_callback = NULL;
400 client_p->localClient->ssl_data = NULL;
401
402 hdl(client_p->localClient->F, RB_OK, data);
403 }
404}
405
f8451915 406static void
3202e249 407ssl_process_dead_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
f8451915
AC
408{
409 struct Client *client_p;
410 char reason[256];
196740c4 411 uint32_t fd;
f8451915
AC
412
413 if(ctl_buf->buflen < 6)
3202e249
VY
414 return; /* bogus message..drop it.. XXX should warn here */
415
196740c4 416 fd = buf_to_uint32(&ctl_buf->buf[1]);
f8451915 417 rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason));
b5b4a0e7 418 client_p = find_cli_connid_hash(fd);
4fbb7362 419 if(client_p == NULL || client_p->localClient == NULL)
f8451915 420 return;
4fbb7362
SA
421
422 if(IsAnyServer(client_p))
423 {
424 sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) && !IsServer(client_p) ? L_NETWIDE : L_ALL, "ssld error for %s: %s", client_p->name, reason);
425 ilog(L_SERVER, "ssld error for %s: %s", log_client_name(client_p, SHOW_IP), reason);
426 }
427
428 /* if there is still a pending callback, call it now */
429 if(client_p->localClient->ssl_callback)
430 {
431 CNCB *hdl = client_p->localClient->ssl_callback;
432 void *data = client_p->localClient->ssl_data;
433
434 client_p->localClient->ssl_callback = NULL;
435 client_p->localClient->ssl_data = NULL;
436
437 hdl(client_p->localClient->F, RB_ERROR_SSL, data);
438
439 /* the callback should have exited the client */
440 return;
441 }
442
42d609f6
JT
443 if(IsAnyServer(client_p) || IsRegistered(client_p))
444 {
445 /* read any last moment ERROR, QUIT or the like -- jilles */
446 if (!strcmp(reason, "Remote host closed the connection"))
447 read_packet(client_p->localClient->F, client_p);
448 if (IsAnyDead(client_p))
449 return;
450 }
f8451915
AC
451 exit_client(client_p, client_p, &me, reason);
452}
453
ebe33dbf
AC
454
455static void
456ssl_process_cipher_string(ssl_ctl_t *ctl, ssl_ctl_buf_t *ctl_buf)
457{
458 struct Client *client_p;
459 const char *cstring;
460 uint32_t fd;
461
462 if(ctl_buf->buflen < 6)
463 return; /* bogus message..drop it.. XXX should warn here */
464
465 fd = buf_to_uint32(&ctl_buf->buf[1]);
466 cstring = (const char *)&ctl_buf->buf[5];
467
468 if(EmptyString(cstring))
469 return;
470
b5b4a0e7 471 client_p = find_cli_connid_hash(fd);
ebe33dbf
AC
472 if(client_p != NULL && client_p->localClient != NULL)
473 {
474 rb_free(client_p->localClient->cipher_string);
475 client_p->localClient->cipher_string = rb_strdup(cstring);
476 }
477}
478
479
7247337a
JT
480static void
481ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
482{
483 struct Client *client_p;
196740c4 484 uint32_t fd;
dc986b54 485 uint32_t certfp_method;
196740c4 486 uint32_t len;
7247337a 487 uint8_t *certfp;
8eda114a 488 char *certfp_string;
dc986b54
SA
489 const char *method_string;
490 int method_len;
7247337a 491
dc986b54 492 if(ctl_buf->buflen > 13 + RB_SSL_CERTFP_LEN)
7247337a
JT
493 return; /* bogus message..drop it.. XXX should warn here */
494
196740c4 495 fd = buf_to_uint32(&ctl_buf->buf[1]);
dc986b54
SA
496 certfp_method = buf_to_uint32(&ctl_buf->buf[5]);
497 len = buf_to_uint32(&ctl_buf->buf[9]);
498 certfp = (uint8_t *)&ctl_buf->buf[13];
b5b4a0e7 499 client_p = find_cli_connid_hash(fd);
7247337a
JT
500 if(client_p == NULL)
501 return;
dc986b54
SA
502
503 switch (certfp_method) {
504 case RB_SSL_CERTFP_METH_CERT_SHA1:
505 case RB_SSL_CERTFP_METH_CERT_SHA256:
506 case RB_SSL_CERTFP_METH_CERT_SHA512:
507 method_string = "";
508 break;
509
510 /* These names are copied from RFC 7218 */
511 case RB_SSL_CERTFP_METH_SPKI_SHA256:
512 method_string = "SPKI:SHA2-256:";
513 break;
514 case RB_SSL_CERTFP_METH_SPKI_SHA512:
515 method_string = "SPKI:SHA2-512:";
516 break;
517 default:
518 return;
519 }
520 method_len = strlen(method_string);
521
8eda114a 522 rb_free(client_p->certfp);
dc986b54
SA
523 certfp_string = rb_malloc(method_len + len * 2 + 1);
524 strcpy(certfp_string, method_string);
66769bc1 525 for(uint32_t i = 0; i < len; i++)
dc986b54 526 snprintf(certfp_string + method_len + 2 * i, 3, "%02x",
7247337a 527 certfp[i]);
8eda114a 528 client_p->certfp = certfp_string;
7247337a
JT
529}
530
f8451915 531static void
3202e249 532ssl_process_cmd_recv(ssl_ctl_t * ctl)
f8451915
AC
533{
534 static const char *cannot_setup_ssl = "ssld cannot setup ssl, check your certificates and private key";
535 static const char *no_ssl_or_zlib = "ssld has neither SSL/TLS or zlib support killing all sslds";
3202e249 536 rb_dlink_node *ptr, *next;
f8451915 537 ssl_ctl_buf_t *ctl_buf;
66769bc1 538 unsigned long len;
e9ffc3c1 539
f8451915
AC
540 if(ctl->dead)
541 return;
e9ffc3c1 542
f8451915
AC
543 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head)
544 {
3202e249
VY
545 ctl_buf = ptr->data;
546 switch (*ctl_buf->buf)
f8451915 547 {
3202e249 548 case 'N':
bfc44622 549 ircd_ssl_ok = false; /* ssld says it can't do ssl/tls */
3202e249 550 break;
4fbb7362
SA
551 case 'O':
552 ssl_process_open_fd(ctl, ctl_buf);
553 break;
3202e249
VY
554 case 'D':
555 ssl_process_dead_fd(ctl, ctl_buf);
556 break;
ebe33dbf
AC
557 case 'C':
558 ssl_process_cipher_string(ctl, ctl_buf);
559 break;
7247337a
JT
560 case 'F':
561 ssl_process_certfp(ctl, ctl_buf);
562 break;
3202e249
VY
563 case 'S':
564 ssl_process_zipstats(ctl, ctl_buf);
565 break;
566 case 'I':
bfc44622 567 ircd_ssl_ok = false;
32ea9d3d 568 ilog(L_MAIN, "%s", cannot_setup_ssl);
481b443b 569 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", cannot_setup_ssl);
f1709d5a 570 break;
3202e249 571 case 'U':
43f06d8d 572 ircd_zlib_ok = 0;
bfc44622 573 ircd_ssl_ok = false;
32ea9d3d 574 ilog(L_MAIN, "%s", no_ssl_or_zlib);
481b443b 575 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", no_ssl_or_zlib);
3202e249 576 ssl_killall();
7cc67225 577 return;
e9ffc3c1
SA
578 case 'V':
579 len = ctl_buf->buflen - 1;
580 if (len > sizeof(ctl->version) - 1)
581 len = sizeof(ctl->version) - 1;
582 strncpy(ctl->version, &ctl_buf->buf[1], len);
3202e249 583 case 'z':
43f06d8d 584 ircd_zlib_ok = 0;
3202e249
VY
585 break;
586 default:
587 ilog(L_MAIN, "Received invalid command from ssld: %s", ctl_buf->buf);
588 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Received invalid command from ssld");
589 break;
f8451915
AC
590 }
591 rb_dlinkDelete(ptr, &ctl->readq);
592 rb_free(ctl_buf->buf);
593 rb_free(ctl_buf);
594 }
595
596}
597
598
599static void
3202e249 600ssl_read_ctl(rb_fde_t * F, void *data)
f8451915
AC
601{
602 ssl_ctl_buf_t *ctl_buf;
603 ssl_ctl_t *ctl = data;
604 int retlen;
605
606 if(ctl->dead)
607 return;
608 do
609 {
610 ctl_buf = rb_malloc(sizeof(ssl_ctl_buf_t));
611 ctl_buf->buf = rb_malloc(READSIZE);
612 retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, READSIZE, ctl_buf->F, 4);
613 ctl_buf->buflen = retlen;
3202e249
VY
614 if(retlen <= 0)
615 {
f8451915
AC
616 rb_free(ctl_buf->buf);
617 rb_free(ctl_buf);
618 }
619 else
620 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq);
3202e249
VY
621 }
622 while(retlen > 0);
623
f8451915
AC
624 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
625 {
626 ssl_dead(ctl);
627 return;
3202e249 628 }
f8451915
AC
629 ssl_process_cmd_recv(ctl);
630 rb_setselect(ctl->F, RB_SELECT_READ, ssl_read_ctl, ctl);
631}
632
633static ssl_ctl_t *
634which_ssld(void)
635{
636 ssl_ctl_t *ctl, *lowest = NULL;
637 rb_dlink_node *ptr;
3202e249 638
f8451915
AC
639 RB_DLINK_FOREACH(ptr, ssl_daemons.head)
640 {
641 ctl = ptr->data;
642 if(ctl->dead)
643 continue;
eb1b303d
SA
644 if(ctl->shutdown)
645 continue;
3202e249
VY
646 if(lowest == NULL)
647 {
f8451915
AC
648 lowest = ctl;
649 continue;
650 }
651 if(ctl->cli_count < lowest->cli_count)
652 lowest = ctl;
653 }
3202e249 654 return (lowest);
f8451915
AC
655}
656
657static void
3202e249 658ssl_write_ctl(rb_fde_t * F, void *data)
f8451915
AC
659{
660 ssl_ctl_t *ctl = data;
661 ssl_ctl_buf_t *ctl_buf;
662 rb_dlink_node *ptr, *next;
663 int retlen, x;
664
665 if(ctl->dead)
666 return;
667
668 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head)
669 {
670 ctl_buf = ptr->data;
671 /* in theory unix sock_dgram shouldn't ever short write this.. */
3202e249 672 retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf, ctl_buf->buflen, ctl->pid);
f8451915
AC
673 if(retlen > 0)
674 {
675 rb_dlinkDelete(ptr, &ctl->writeq);
676 for(x = 0; x < ctl_buf->nfds; x++)
677 rb_close(ctl_buf->F[x]);
678 rb_free(ctl_buf->buf);
679 rb_free(ctl_buf);
3202e249 680
f8451915
AC
681 }
682 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
683 {
684 ssl_dead(ctl);
685 return;
3202e249
VY
686 }
687 else
688 {
f8451915
AC
689 rb_setselect(ctl->F, RB_SELECT_WRITE, ssl_write_ctl, ctl);
690 }
691 }
692}
693
694static void
3202e249 695ssl_cmd_write_queue(ssl_ctl_t * ctl, rb_fde_t ** F, int count, const void *buf, size_t buflen)
f8451915
AC
696{
697 ssl_ctl_buf_t *ctl_buf;
3202e249 698 int x;
f8451915
AC
699
700 /* don't bother */
701 if(ctl->dead)
702 return;
3202e249 703
f8451915
AC
704 ctl_buf = rb_malloc(sizeof(ssl_ctl_buf_t));
705 ctl_buf->buf = rb_malloc(buflen);
706 memcpy(ctl_buf->buf, buf, buflen);
707 ctl_buf->buflen = buflen;
3202e249 708
f8451915
AC
709 for(x = 0; x < count && x < MAXPASSFD; x++)
710 {
3202e249 711 ctl_buf->F[x] = F[x];
f8451915
AC
712 }
713 ctl_buf->nfds = count;
714 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq);
715 ssl_write_ctl(ctl->F, ctl);
716}
717
718
719static void
f7b0c4b3 720send_new_ssl_certs_one(ssl_ctl_t * ctl)
f8451915
AC
721{
722 size_t len;
723
f7b0c4b3
SA
724 len = strlen(ServerInfo.ssl_cert) + strlen(ServerInfo.ssl_private_key) + 5;
725 if(ServerInfo.ssl_dh_params)
726 len += strlen(ServerInfo.ssl_dh_params);
727 if(ServerInfo.ssl_cipher_list)
728 len += strlen(ServerInfo.ssl_cipher_list);
f8451915
AC
729 if(len > sizeof(tmpbuf))
730 {
3202e249
VY
731 sendto_realops_snomask(SNO_GENERAL, L_ALL,
732 "Parameters for send_new_ssl_certs_one too long (%zu > %zu) to pass to ssld, not sending...",
733 len, sizeof(tmpbuf));
734 ilog(L_MAIN,
735 "Parameters for send_new_ssl_certs_one too long (%zu > %zu) to pass to ssld, not sending...",
736 len, sizeof(tmpbuf));
f8451915
AC
737 return;
738 }
f7b0c4b3
SA
739 len = snprintf(tmpbuf, sizeof(tmpbuf), "K%c%s%c%s%c%s%c%s%c", nul,
740 ServerInfo.ssl_cert, nul,
741 ServerInfo.ssl_private_key, nul,
742 ServerInfo.ssl_dh_params != NULL ? ServerInfo.ssl_dh_params : "", nul,
743 ServerInfo.ssl_cipher_list != NULL ? ServerInfo.ssl_cipher_list : "", nul);
f8451915
AC
744 ssl_cmd_write_queue(ctl, NULL, 0, tmpbuf, len);
745}
746
13d8f0ed 747static void
93ad89b2 748send_certfp_method(ssl_ctl_t *ctl)
13d8f0ed
AC
749{
750 char buf[5];
751
752 buf[0] = 'F';
93ad89b2 753 uint32_to_buf(&buf[1], ConfigFileEntry.certfp_method);
13d8f0ed
AC
754 ssl_cmd_write_queue(ctl, NULL, 0, buf, sizeof(buf));
755}
756
93ad89b2
SA
757static void
758ssld_update_config_one(ssl_ctl_t *ctl)
759{
760 send_certfp_method(ctl);
761 send_new_ssl_certs_one(ctl);
762}
763
f8451915 764void
f7b0c4b3 765ssld_update_config(void)
f8451915
AC
766{
767 rb_dlink_node *ptr;
f7b0c4b3 768
f8451915
AC
769 RB_DLINK_FOREACH(ptr, ssl_daemons.head)
770 {
771 ssl_ctl_t *ctl = ptr->data;
93ad89b2 772 ssld_update_config_one(ctl);
f8451915
AC
773 }
774}
775
3202e249 776ssl_ctl_t *
196740c4 777start_ssld_accept(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id)
f8451915
AC
778{
779 rb_fde_t *F[2];
780 ssl_ctl_t *ctl;
781 char buf[5];
782 F[0] = sslF;
783 F[1] = plainF;
784
785 buf[0] = 'A';
196740c4 786 uint32_to_buf(&buf[1], id);
f8451915 787 ctl = which_ssld();
5e270e7d
SA
788 if(!ctl)
789 return NULL;
f8451915
AC
790 ctl->cli_count++;
791 ssl_cmd_write_queue(ctl, F, 2, buf, sizeof(buf));
792 return ctl;
793}
794
795ssl_ctl_t *
196740c4 796start_ssld_connect(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id)
f8451915
AC
797{
798 rb_fde_t *F[2];
799 ssl_ctl_t *ctl;
800 char buf[5];
801 F[0] = sslF;
802 F[1] = plainF;
803
804 buf[0] = 'C';
196740c4 805 uint32_to_buf(&buf[1], id);
f8451915
AC
806
807 ctl = which_ssld();
5e270e7d
SA
808 if(!ctl)
809 return NULL;
f8451915
AC
810 ctl->cli_count++;
811 ssl_cmd_write_queue(ctl, F, 2, buf, sizeof(buf));
3202e249 812 return ctl;
f8451915
AC
813}
814
3202e249
VY
815void
816ssld_decrement_clicount(ssl_ctl_t * ctl)
f8451915
AC
817{
818 if(ctl == NULL)
819 return;
820
821 ctl->cli_count--;
eb1b303d
SA
822 if(ctl->shutdown && !ctl->cli_count)
823 {
824 ctl->dead = 1;
825 rb_kill(ctl->pid, SIGKILL);
826 }
f8451915
AC
827 if(ctl->dead && !ctl->cli_count)
828 {
829 free_ssl_daemon(ctl);
830 }
831}
832
55abcbb2 833/*
f8451915 834 * what we end up sending to the ssld process for ziplinks is the following
55abcbb2
KB
835 * Z[ourfd][level][RECVQ]
836 * Z = ziplinks command = buf[0]
f8451915
AC
837 * ourfd = Our end of the socketpair = buf[1..4]
838 * level = zip level buf[5]
839 * recvqlen = our recvq len = buf[6-7]
840 * recvq = any data we read prior to starting ziplinks
841 */
842void
843start_zlib_session(void *data)
844{
3202e249 845 struct Client *server = (struct Client *) data;
0862e335
VY
846 uint16_t recvqlen;
847 uint8_t level;
f8451915
AC
848 void *xbuf;
849
850 rb_fde_t *F[2];
851 rb_fde_t *xF1, *xF2;
852 char *buf;
853 void *recvq_start;
854
196740c4 855 size_t hdr = (sizeof(uint8_t) * 2) + sizeof(uint32_t);
f8451915
AC
856 size_t len;
857 int cpylen, left;
858
859 server->localClient->event = NULL;
860
861 recvqlen = rb_linebuf_len(&server->localClient->buf_recvq);
3202e249 862
f8451915
AC
863 len = recvqlen + hdr;
864
865 if(len > READBUF_SIZE)
866 {
3202e249
VY
867 sendto_realops_snomask(SNO_GENERAL, L_ALL,
868 "ssld - attempted to pass message of %zd len, max len %d, giving up",
869 len, READBUF_SIZE);
f8451915
AC
870 ilog(L_MAIN, "ssld - attempted to pass message of %zd len, max len %d, giving up", len, READBUF_SIZE);
871 exit_client(server, server, server, "ssld readbuf exceeded");
872 return;
873 }
874
3202e249 875 buf = rb_malloc(len);
f8451915
AC
876 level = ConfigFileEntry.compression_level;
877
196740c4 878 uint32_to_buf(&buf[1], rb_get_fd(server->localClient->F));
3202e249 879 buf[5] = (char) level;
f8451915 880
3202e249 881 recvq_start = &buf[6];
f8451915
AC
882 server->localClient->zipstats = rb_malloc(sizeof(struct ZipStats));
883
884 xbuf = recvq_start;
885 left = recvqlen;
886
887 do
888 {
889 cpylen = rb_linebuf_get(&server->localClient->buf_recvq, xbuf, left, LINEBUF_PARTIAL, LINEBUF_RAW);
890 left -= cpylen;
3202e249
VY
891 xbuf = (void *) (((uintptr_t) xbuf) + cpylen);
892 }
893 while(cpylen > 0);
f8451915
AC
894
895 /* Pass the socket to ssld. */
896 *buf = 'Z';
eda22d87
JT
897 if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF1, &xF2, "Initial zlib socketpairs") == -1)
898 {
899 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Error creating zlib socketpair - %s", strerror(errno));
900 ilog(L_MAIN, "Error creating zlib socketpairs - %s", strerror(errno));
901 exit_client(server, server, server, "Error creating zlib socketpair");
b9ff4868 902 rb_free(buf);
eda22d87
JT
903 return;
904 }
55abcbb2 905
3202e249 906 F[0] = server->localClient->F;
f8451915 907 F[1] = xF1;
f8451915
AC
908 server->localClient->F = xF2;
909 /* need to redo as what we did before isn't valid now */
de7cf7e0 910 uint32_to_buf(&buf[1], connid_get(server));
a4165b42
AS
911
912 server->localClient->z_ctl = which_ssld();
5e270e7d
SA
913 if(!server->localClient->z_ctl)
914 {
915 exit_client(server, server, server, "Error finding available ssld");
916 rb_free(buf);
917 return;
918 }
a4165b42
AS
919 server->localClient->z_ctl->cli_count++;
920 ssl_cmd_write_queue(server->localClient->z_ctl, F, 2, buf, len);
f8451915
AC
921 rb_free(buf);
922}
923
924static void
925collect_zipstats(void *unused)
926{
927 rb_dlink_node *ptr;
928 struct Client *target_p;
196740c4 929 char buf[sizeof(uint8_t) + sizeof(uint32_t) + HOSTLEN];
f8451915
AC
930 void *odata;
931 size_t len;
196740c4 932 uint32_t id;
f8451915
AC
933
934 buf[0] = 'S';
196740c4 935 odata = buf + sizeof(uint8_t) + sizeof(uint32_t);
f8451915
AC
936
937 RB_DLINK_FOREACH(ptr, serv_list.head)
938 {
939 target_p = ptr->data;
940 if(IsCapable(target_p, CAP_ZIP))
941 {
0862e335 942 len = sizeof(uint8_t) + sizeof(uint32_t);
f8451915
AC
943
944 id = rb_get_fd(target_p->localClient->F);
196740c4 945 uint32_to_buf(&buf[1], id);
3202e249
VY
946 rb_strlcpy(odata, target_p->name, (sizeof(buf) - len));
947 len += strlen(odata) + 1; /* Get the \0 as well */
a4165b42 948 ssl_cmd_write_queue(target_p->localClient->z_ctl, NULL, 0, buf, len);
f8451915
AC
949 }
950 }
951}
952
953static void
954cleanup_dead_ssl(void *unused)
955{
956 rb_dlink_node *ptr, *next;
957 ssl_ctl_t *ctl;
958 RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head)
959 {
960 ctl = ptr->data;
961 if(ctl->dead && !ctl->cli_count)
962 {
3202e249 963 free_ssl_daemon(ctl);
f8451915
AC
964 }
965 }
966}
967
968int
969get_ssld_count(void)
970{
971 return ssld_count;
972}
973
035d9143 974void
e9ffc3c1 975ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data)
035d9143
SA
976{
977 rb_dlink_node *ptr, *next;
978 ssl_ctl_t *ctl;
979 RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head)
980 {
981 ctl = ptr->data;
982 func(data, ctl->pid, ctl->cli_count,
983 ctl->dead ? SSLD_DEAD :
e9ffc3c1
SA
984 (ctl->shutdown ? SSLD_SHUTDOWN : SSLD_ACTIVE),
985 ctl->version);
035d9143
SA
986 }
987}
988
3202e249
VY
989void
990init_ssld(void)
f8451915
AC
991{
992 rb_event_addish("collect_zipstats", collect_zipstats, NULL, ZIPSTATS_TIME);
c42a66be 993 rb_event_addish("cleanup_dead_ssld", cleanup_dead_ssl, NULL, 60);
f8451915 994}