]> jfr.im git - solanum.git/blame - ssld/ssld.c
SET SPANNUM: Fix incorrect > 0 check to be >= 0
[solanum.git] / ssld / ssld.c
CommitLineData
8d99443b
VY
1/*
2 * ssld.c: The ircd-ratbox ssl/zlib helper daemon thingy
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
8d99443b
VY
20 */
21
22
23#include "stdinc.h"
24
8d99443b
VY
25#define MAXPASSFD 4
26#ifndef READBUF_SIZE
27#define READBUF_SIZE 16384
28#endif
29
30static void setup_signals(void);
3202e249 31static pid_t ppid;
8d99443b 32
408a29c6
AC
33static inline uint32_t
34buf_to_uint32(uint8_t *buf)
8d99443b 35{
408a29c6 36 uint32_t x;
4b6a4d47 37 memcpy(&x, buf, sizeof(x));
8d99443b
VY
38 return x;
39}
40
3202e249 41static inline void
408a29c6 42uint32_to_buf(uint8_t *buf, uint32_t x)
8d99443b 43{
4b6a4d47 44 memcpy(buf, &x, sizeof(x));
8d99443b
VY
45 return;
46}
47
8d99443b
VY
48typedef struct _mod_ctl_buf
49{
50 rb_dlink_node node;
85e9bf41 51 uint8_t *buf;
8d99443b
VY
52 size_t buflen;
53 rb_fde_t *F[MAXPASSFD];
54 int nfds;
55} mod_ctl_buf_t;
56
57typedef struct _mod_ctl
58{
59 rb_dlink_node node;
60 int cli_count;
61 rb_fde_t *F;
62 rb_fde_t *F_pipe;
63 rb_dlink_list readq;
64 rb_dlink_list writeq;
65} mod_ctl_t;
66
67static mod_ctl_t *mod_ctl;
68
8d99443b
VY
69typedef struct _conn
70{
71 rb_dlink_node node;
72 mod_ctl_t *ctl;
73 rawbuf_head_t *modbuf_out;
74 rawbuf_head_t *plainbuf_out;
75
408a29c6 76 uint32_t id;
8d99443b
VY
77
78 rb_fde_t *mod_fd;
79 rb_fde_t *plain_fd;
94356462
AC
80 uint64_t mod_out;
81 uint64_t mod_in;
82 uint64_t plain_in;
83 uint64_t plain_out;
7edb4f16 84 uint8_t flags;
8d99443b
VY
85 void *stream;
86} conn_t;
87
88#define FLAG_SSL 0x01
89#define FLAG_ZIP 0x02
90#define FLAG_CORK 0x04
91#define FLAG_DEAD 0x08
3202e249
VY
92#define FLAG_SSL_W_WANTS_R 0x10 /* output needs to wait until input possible */
93#define FLAG_SSL_R_WANTS_W 0x20 /* input needs to wait until output possible */
07c2bb75 94#define FLAG_ZIPSSL 0x40
8d99443b
VY
95
96#define IsSSL(x) ((x)->flags & FLAG_SSL)
97#define IsZip(x) ((x)->flags & FLAG_ZIP)
98#define IsCork(x) ((x)->flags & FLAG_CORK)
99#define IsDead(x) ((x)->flags & FLAG_DEAD)
73d6283c
VY
100#define IsSSLWWantsR(x) ((x)->flags & FLAG_SSL_W_WANTS_R)
101#define IsSSLRWantsW(x) ((x)->flags & FLAG_SSL_R_WANTS_W)
07c2bb75 102#define IsZipSSL(x) ((x)->flags & FLAG_ZIPSSL)
8d99443b
VY
103
104#define SetSSL(x) ((x)->flags |= FLAG_SSL)
105#define SetZip(x) ((x)->flags |= FLAG_ZIP)
106#define SetCork(x) ((x)->flags |= FLAG_CORK)
107#define SetDead(x) ((x)->flags |= FLAG_DEAD)
73d6283c
VY
108#define SetSSLWWantsR(x) ((x)->flags |= FLAG_SSL_W_WANTS_R)
109#define SetSSLRWantsW(x) ((x)->flags |= FLAG_SSL_R_WANTS_W)
8d99443b 110
8d99443b 111#define ClearCork(x) ((x)->flags &= ~FLAG_CORK)
73d6283c
VY
112#define ClearSSLWWantsR(x) ((x)->flags &= ~FLAG_SSL_W_WANTS_R)
113#define ClearSSLRWantsW(x) ((x)->flags &= ~FLAG_SSL_R_WANTS_W)
8d99443b
VY
114
115#define NO_WAIT 0x0
116#define WAIT_PLAIN 0x1
117
4b6a4d47
VY
118#define HASH_WALK_SAFE(i, max, ptr, next, table) for(i = 0; i < max; i++) { RB_DLINK_FOREACH_SAFE(ptr, next, table[i].head)
119#define HASH_WALK_END }
8d99443b
VY
120#define CONN_HASH_SIZE 2000
121#define connid_hash(x) (&connid_hash_table[(x % CONN_HASH_SIZE)])
122
4b6a4d47
VY
123
124
8d99443b
VY
125static rb_dlink_list connid_hash_table[CONN_HASH_SIZE];
126static rb_dlink_list dead_list;
127
3202e249 128static void conn_mod_read_cb(rb_fde_t *fd, void *data);
8d99443b
VY
129static void conn_mod_write_sendq(rb_fde_t *, void *data);
130static void conn_plain_write_sendq(rb_fde_t *, void *data);
131static void mod_write_ctl(rb_fde_t *, void *data);
3202e249 132static void conn_plain_read_cb(rb_fde_t *fd, void *data);
e99f6122 133static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data);
3202e249 134static void mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len);
8d99443b 135static const char *remote_closed = "Remote host closed the connection";
d35870ee 136static bool ssld_ssl_ok;
cf430c1a 137static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
503727d1 138static bool zlib_ok = false;
4b6a4d47 139
8d99443b
VY
140
141static conn_t *
408a29c6 142conn_find_by_id(uint32_t id)
8d99443b
VY
143{
144 rb_dlink_node *ptr;
145 conn_t *conn;
146
147 RB_DLINK_FOREACH(ptr, (connid_hash(id))->head)
148 {
149 conn = ptr->data;
150 if(conn->id == id && !IsDead(conn))
151 return conn;
152 }
153 return NULL;
154}
155
156static void
408a29c6 157conn_add_id_hash(conn_t * conn, uint32_t id)
8d99443b
VY
158{
159 conn->id = id;
160 rb_dlinkAdd(conn, &conn->node, connid_hash(id));
161}
162
163static void
164free_conn(conn_t * conn)
165{
166 rb_free_rawbuffer(conn->modbuf_out);
167 rb_free_rawbuffer(conn->plainbuf_out);
8d99443b
VY
168 rb_free(conn);
169}
170
171static void
172clean_dead_conns(void *unused)
173{
174 conn_t *conn;
175 rb_dlink_node *ptr, *next;
176 RB_DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
177 {
178 conn = ptr->data;
179 free_conn(conn);
180 }
181 dead_list.tail = dead_list.head = NULL;
182}
183
184
185static void
186close_conn(conn_t * conn, int wait_plain, const char *fmt, ...)
187{
188 va_list ap;
3202e249 189 char reason[128]; /* must always be under 250 bytes */
85e9bf41 190 uint8_t buf[256];
8d99443b
VY
191 int len;
192 if(IsDead(conn))
193 return;
3202e249 194
8d99443b
VY
195 rb_rawbuf_flush(conn->modbuf_out, conn->mod_fd);
196 rb_rawbuf_flush(conn->plainbuf_out, conn->plain_fd);
197 rb_close(conn->mod_fd);
198 SetDead(conn);
199
408a29c6 200 if(!IsZipSSL(conn))
e99f6122
JT
201 rb_dlinkDelete(&conn->node, connid_hash(conn->id));
202
8d99443b
VY
203 if(!wait_plain || fmt == NULL)
204 {
205 rb_close(conn->plain_fd);
8d99443b
VY
206 rb_dlinkAdd(conn, &conn->node, &dead_list);
207 return;
208 }
e99f6122
JT
209 rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_shutdown_cb, conn);
210 rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL);
8d99443b 211 va_start(ap, fmt);
5203cba5 212 vsnprintf(reason, sizeof(reason), fmt, ap);
8d99443b
VY
213 va_end(ap);
214
215 buf[0] = 'D';
408a29c6 216 uint32_to_buf(&buf[1], conn->id);
85e9bf41 217 rb_strlcpy((char *) &buf[5], reason, sizeof(buf) - 5);
8d99443b
VY
218 len = (strlen(reason) + 1) + 5;
219 mod_cmd_write_queue(conn->ctl, buf, len);
220}
221
222static conn_t *
3202e249 223make_conn(mod_ctl_t * ctl, rb_fde_t *mod_fd, rb_fde_t *plain_fd)
8d99443b
VY
224{
225 conn_t *conn = rb_malloc(sizeof(conn_t));
226 conn->ctl = ctl;
227 conn->modbuf_out = rb_new_rawbuffer();
228 conn->plainbuf_out = rb_new_rawbuffer();
229 conn->mod_fd = mod_fd;
230 conn->plain_fd = plain_fd;
231 conn->id = -1;
232 conn->stream = NULL;
233 rb_set_nb(mod_fd);
234 rb_set_nb(plain_fd);
235 return conn;
236}
237
4b6a4d47
VY
238static void
239check_handshake_flood(void *unused)
240{
241 conn_t *conn;
242 rb_dlink_node *ptr, *next;
243 unsigned int count;
244 int i;
245 HASH_WALK_SAFE(i, CONN_HASH_SIZE, ptr, next, connid_hash_table)
246 {
247 conn = ptr->data;
248 if(!IsSSL(conn))
249 continue;
3202e249 250
4b6a4d47
VY
251 count = rb_ssl_handshake_count(conn->mod_fd);
252 /* nothing needs to do this more than twice in ten seconds i don't think */
253 if(count > 2)
254 close_conn(conn, WAIT_PLAIN, "Handshake flooding");
255 else
256 rb_ssl_clear_handshake_count(conn->mod_fd);
3202e249
VY
257 }
258HASH_WALK_END}
4b6a4d47 259
8d99443b 260static void
3202e249 261conn_mod_write_sendq(rb_fde_t *fd, void *data)
8d99443b
VY
262{
263 conn_t *conn = data;
264 const char *err;
265 int retlen;
266 if(IsDead(conn))
267 return;
268
73d6283c
VY
269 if(IsSSLWWantsR(conn))
270 {
271 ClearSSLWWantsR(conn);
272 conn_mod_read_cb(conn->mod_fd, conn);
273 if(IsDead(conn))
274 return;
275 }
276
3202e249 277 while((retlen = rb_rawbuf_flush(conn->modbuf_out, fd)) > 0)
8d99443b
VY
278 conn->mod_out += retlen;
279
280 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
281 {
282 if(retlen == 0)
283 close_conn(conn, WAIT_PLAIN, "%s", remote_closed);
284 if(IsSSL(conn) && retlen == RB_RW_SSL_ERROR)
285 err = rb_get_ssl_strerror(conn->mod_fd);
286 else
287 err = strerror(errno);
288 close_conn(conn, WAIT_PLAIN, "Write error: %s", err);
289 return;
290 }
291 if(rb_rawbuf_length(conn->modbuf_out) > 0)
292 {
73d6283c
VY
293 if(retlen != RB_RW_SSL_NEED_READ)
294 rb_setselect(conn->mod_fd, RB_SELECT_WRITE, conn_mod_write_sendq, conn);
295 else
296 {
297 rb_setselect(conn->mod_fd, RB_SELECT_READ, conn_mod_write_sendq, conn);
298 rb_setselect(conn->mod_fd, RB_SELECT_WRITE, NULL, NULL);
299 SetSSLWWantsR(conn);
300 }
8d99443b
VY
301 }
302 else
303 rb_setselect(conn->mod_fd, RB_SELECT_WRITE, NULL, NULL);
304
305 if(IsCork(conn) && rb_rawbuf_length(conn->modbuf_out) == 0)
306 {
307 ClearCork(conn);
308 conn_plain_read_cb(conn->plain_fd, conn);
309 }
310
311}
312
313static void
314conn_mod_write(conn_t * conn, void *data, size_t len)
315{
316 if(IsDead(conn)) /* no point in queueing to a dead man */
317 return;
318 rb_rawbuf_append(conn->modbuf_out, data, len);
319}
320
321static void
322conn_plain_write(conn_t * conn, void *data, size_t len)
323{
324 if(IsDead(conn)) /* again no point in queueing to dead men */
325 return;
326 rb_rawbuf_append(conn->plainbuf_out, data, len);
327}
328
329static void
330mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len)
331{
332 mod_ctl_buf_t *ctl_buf;
333 ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
334 ctl_buf->buf = rb_malloc(len);
335 ctl_buf->buflen = len;
336 memcpy(ctl_buf->buf, data, len);
337 ctl_buf->nfds = 0;
338 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq);
339 mod_write_ctl(ctl->F, ctl);
340}
341
25a89965 342static bool
8d99443b
VY
343plain_check_cork(conn_t * conn)
344{
345 if(rb_rawbuf_length(conn->modbuf_out) >= 4096)
346 {
55abcbb2 347 /* if we have over 4k pending outbound, don't read until
8d99443b
VY
348 * we've cleared the queue */
349 SetCork(conn);
350 rb_setselect(conn->plain_fd, RB_SELECT_READ, NULL, NULL);
351 /* try to write */
352 conn_mod_write_sendq(conn->mod_fd, conn);
25a89965 353 return true;
8d99443b 354 }
25a89965 355 return false;
8d99443b
VY
356}
357
358
359static void
3202e249 360conn_plain_read_cb(rb_fde_t *fd, void *data)
8d99443b 361{
6cd1aca7 362 char inbuf[READBUF_SIZE];
8d99443b
VY
363 conn_t *conn = data;
364 int length = 0;
365 if(conn == NULL)
366 return;
367
368 if(IsDead(conn))
369 return;
370
371 if(plain_check_cork(conn))
372 return;
373
3202e249 374 while(1)
8d99443b
VY
375 {
376 if(IsDead(conn))
377 return;
378
379 length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf));
380
381 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
382 {
383 close_conn(conn, NO_WAIT, NULL);
384 return;
385 }
386
387 if(length < 0)
388 {
389 rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_cb, conn);
390 conn_mod_write_sendq(conn->mod_fd, conn);
391 return;
392 }
393 conn->plain_in += length;
394
81531536 395 conn_mod_write(conn, inbuf, length);
8d99443b
VY
396 if(IsDead(conn))
397 return;
398 if(plain_check_cork(conn))
399 return;
400 }
401}
402
e99f6122
JT
403static void
404conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data)
405{
6cd1aca7 406 char inbuf[READBUF_SIZE];
e99f6122
JT
407 conn_t *conn = data;
408 int length = 0;
409
410 if(conn == NULL)
411 return;
412
413 while(1)
414 {
415 length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf));
416
417 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
418 {
419 rb_close(conn->plain_fd);
420 rb_dlinkAdd(conn, &conn->node, &dead_list);
421 return;
422 }
423
424 if(length < 0)
425 {
426 rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_shutdown_cb, conn);
427 return;
428 }
429 }
430}
431
8d99443b 432static void
3202e249 433conn_mod_read_cb(rb_fde_t *fd, void *data)
8d99443b 434{
6cd1aca7 435 char inbuf[READBUF_SIZE];
8d99443b 436 conn_t *conn = data;
8d99443b
VY
437 int length;
438 if(conn == NULL)
439 return;
440 if(IsDead(conn))
441 return;
442
73d6283c
VY
443 if(IsSSLRWantsW(conn))
444 {
445 ClearSSLRWantsW(conn);
446 conn_mod_write_sendq(conn->mod_fd, conn);
447 if(IsDead(conn))
448 return;
449 }
450
3202e249 451 while(1)
8d99443b
VY
452 {
453 if(IsDead(conn))
454 return;
455
456 length = rb_read(conn->mod_fd, inbuf, sizeof(inbuf));
457
458 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
459 {
3202e249
VY
460 if(length == 0)
461 {
8d99443b
VY
462 close_conn(conn, WAIT_PLAIN, "%s", remote_closed);
463 return;
464 }
465
f660af21 466 const char *err;
8d99443b
VY
467 if(IsSSL(conn) && length == RB_RW_SSL_ERROR)
468 err = rb_get_ssl_strerror(conn->mod_fd);
469 else
470 err = strerror(errno);
471 close_conn(conn, WAIT_PLAIN, "Read error: %s", err);
472 return;
473 }
474 if(length < 0)
475 {
73d6283c
VY
476 if(length != RB_RW_SSL_NEED_WRITE)
477 rb_setselect(conn->mod_fd, RB_SELECT_READ, conn_mod_read_cb, conn);
478 else
479 {
480 rb_setselect(conn->mod_fd, RB_SELECT_READ, NULL, NULL);
481 rb_setselect(conn->mod_fd, RB_SELECT_WRITE, conn_mod_read_cb, conn);
482 SetSSLRWantsW(conn);
483 }
8d99443b
VY
484 conn_plain_write_sendq(conn->plain_fd, conn);
485 return;
3202e249 486 }
8d99443b 487 conn->mod_in += length;
81531536 488 conn_plain_write(conn, inbuf, length);
8d99443b
VY
489 }
490}
491
492static void
3202e249 493conn_plain_write_sendq(rb_fde_t *fd, void *data)
8d99443b
VY
494{
495 conn_t *conn = data;
496 int retlen;
497
498 if(IsDead(conn))
499 return;
500
3202e249 501 while((retlen = rb_rawbuf_flush(conn->plainbuf_out, fd)) > 0)
8d99443b
VY
502 {
503 conn->plain_out += retlen;
504 }
505 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
506 {
507 close_conn(data, NO_WAIT, NULL);
508 return;
509 }
3202e249 510
8d99443b
VY
511
512 if(rb_rawbuf_length(conn->plainbuf_out) > 0)
513 rb_setselect(conn->plain_fd, RB_SELECT_WRITE, conn_plain_write_sendq, conn);
514 else
515 rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL);
516}
517
518static int
519maxconn(void)
520{
8d99443b
VY
521 struct rlimit limit;
522
523 if(!getrlimit(RLIMIT_NOFILE, &limit))
524 {
525 return limit.rlim_cur;
526 }
8d99443b
VY
527 return MAXCONNECTIONS;
528}
529
408a29c6
AC
530static void
531ssl_send_cipher(conn_t *conn)
532{
408a29c6 533 size_t len;
74ff144d 534 uint8_t buf[512];
408a29c6
AC
535 char cstring[256];
536 const char *p;
537 if(!IsSSL(conn))
538 return;
539
540 p = rb_ssl_get_cipher(conn->mod_fd);
541
542 if(p == NULL)
543 return;
544
545 rb_strlcpy(cstring, p, sizeof(cstring));
546
547 buf[0] = 'C';
548 uint32_to_buf(&buf[1], conn->id);
74ff144d 549 strcpy((char *) &buf[5], cstring);
408a29c6
AC
550 len = (strlen(cstring) + 1) + 5;
551 mod_cmd_write_queue(conn->ctl, buf, len);
408a29c6
AC
552}
553
554static void
555ssl_send_certfp(conn_t *conn)
556{
dc986b54 557 uint8_t buf[13 + RB_SSL_CERTFP_LEN];
408a29c6 558
dc986b54 559 int len = rb_get_ssl_certfp(conn->mod_fd, &buf[13], certfp_method);
408a29c6
AC
560 if (!len)
561 return;
562
563 lrb_assert(len <= RB_SSL_CERTFP_LEN);
564 buf[0] = 'F';
565 uint32_to_buf(&buf[1], conn->id);
dc986b54
SA
566 uint32_to_buf(&buf[5], certfp_method);
567 uint32_to_buf(&buf[9], len);
568 mod_cmd_write_queue(conn->ctl, buf, 13 + len);
408a29c6
AC
569}
570
4fbb7362
SA
571static void
572ssl_send_open(conn_t *conn)
573{
574 uint8_t buf[5];
575
576 buf[0] = 'O';
577 uint32_to_buf(&buf[1], conn->id);
578 mod_cmd_write_queue(conn->ctl, buf, 5);
579}
580
8d99443b 581static void
3202e249 582ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
8d99443b
VY
583{
584 conn_t *conn = data;
7247337a 585
8d99443b
VY
586 if(status == RB_OK)
587 {
408a29c6
AC
588 ssl_send_cipher(conn);
589 ssl_send_certfp(conn);
4fbb7362 590 ssl_send_open(conn);
fbbc6aeb
SA
591 conn_mod_read_cb(conn->mod_fd, conn);
592 conn_plain_read_cb(conn->plain_fd, conn);
8d99443b
VY
593 return;
594 }
a444bb78 595 /* ircd doesn't care about the reason for this */
8d99443b
VY
596 close_conn(conn, NO_WAIT, 0);
597 return;
598}
599
600static void
3202e249 601ssl_process_connect_cb(rb_fde_t *F, int status, void *data)
8d99443b
VY
602{
603 conn_t *conn = data;
a7675ed2 604
8d99443b
VY
605 if(status == RB_OK)
606 {
408a29c6
AC
607 ssl_send_cipher(conn);
608 ssl_send_certfp(conn);
4fbb7362 609 ssl_send_open(conn);
fbbc6aeb
SA
610 conn_mod_read_cb(conn->mod_fd, conn);
611 conn_plain_read_cb(conn->plain_fd, conn);
8d99443b 612 }
a444bb78
JT
613 else if(status == RB_ERR_TIMEOUT)
614 close_conn(conn, WAIT_PLAIN, "SSL handshake timed out");
615 else if(status == RB_ERROR_SSL)
616 close_conn(conn, WAIT_PLAIN, "%s", rb_get_ssl_strerror(conn->mod_fd));
617 else
618 close_conn(conn, WAIT_PLAIN, "SSL handshake failed");
8d99443b
VY
619}
620
621
c03677e9
JT
622static void
623cleanup_bad_message(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
624{
625 int i;
626
627 /* XXX should log this somehow */
628 for (i = 0; i < ctlb->nfds; i++)
629 rb_close(ctlb->F[i]);
630}
631
8d99443b
VY
632static void
633ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
634{
635 conn_t *conn;
408a29c6 636 uint32_t id;
8d99443b
VY
637
638 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
639
408a29c6
AC
640 id = buf_to_uint32(&ctlb->buf[1]);
641 conn_add_id_hash(conn, id);
8d99443b
VY
642 SetSSL(conn);
643
644 if(rb_get_type(conn->mod_fd) & RB_FD_UNKNOWN)
8d99443b 645 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
a5ddb7df
AC
646
647 if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
8d99443b
VY
648 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
649
650 rb_ssl_start_accepted(ctlb->F[0], ssl_process_accept_cb, conn, 10);
651}
652
e6bbb410
EM
653static void
654ssl_change_certfp_method(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
655{
408a29c6 656 certfp_method = buf_to_uint32(&ctlb->buf[1]);
e6bbb410
EM
657}
658
8d99443b
VY
659static void
660ssl_process_connect(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
661{
662 conn_t *conn;
408a29c6 663 uint32_t id;
8d99443b
VY
664 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
665
408a29c6
AC
666 id = buf_to_uint32(&ctlb->buf[1]);
667 conn_add_id_hash(conn, id);
8d99443b
VY
668 SetSSL(conn);
669
670 if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
671 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
672
a5ddb7df 673 if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
8d99443b
VY
674 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
675
676
677 rb_ssl_start_connected(ctlb->F[0], ssl_process_connect_cb, conn, 10);
678}
679
680static void
681process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
682{
683 char outstat[512];
684 conn_t *conn;
85e9bf41 685 uint8_t *odata;
408a29c6 686 uint32_t id;
8d99443b 687
408a29c6 688 id = buf_to_uint32(&ctlb->buf[1]);
3202e249 689
8d99443b
VY
690 odata = &ctlb->buf[5];
691 conn = conn_find_by_id(id);
692
693 if(conn == NULL)
694 return;
695
5203cba5 696 snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
26b83fa0
SA
697 (unsigned long long)conn->plain_out,
698 (unsigned long long)conn->mod_in,
699 (unsigned long long)conn->plain_in,
700 (unsigned long long)conn->mod_out);
8d99443b
VY
701 conn->plain_out = 0;
702 conn->plain_in = 0;
703 conn->mod_in = 0;
704 conn->mod_out = 0;
705 mod_cmd_write_queue(ctl, outstat, strlen(outstat) + 1); /* +1 is so we send the \0 as well */
706}
707
8d99443b
VY
708static void
709ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
710{
711 char *buf;
c1725bda 712 char *cert, *key, *dhparam, *cipher_list;
8d99443b 713
85e9bf41 714 buf = (char *) &ctl_buf->buf[2];
8d99443b
VY
715 cert = buf;
716 buf += strlen(cert) + 1;
717 key = buf;
718 buf += strlen(key) + 1;
719 dhparam = buf;
c1725bda
AC
720 buf += strlen(dhparam) + 1;
721 cipher_list = buf;
f5960b83
AJ
722 if(strlen(key) == 0)
723 key = cert;
f831e926
AJ
724 if(strlen(dhparam) == 0)
725 dhparam = NULL;
c1725bda
AC
726 if(strlen(cipher_list) == 0)
727 cipher_list = NULL;
8d99443b 728
c1725bda 729 if(!rb_setup_ssl_server(cert, key, dhparam, cipher_list))
8d99443b
VY
730 {
731 const char *invalid = "I";
732 mod_cmd_write_queue(ctl, invalid, strlen(invalid));
733 return;
3202e249 734 }
8d99443b
VY
735}
736
737static void
3202e249 738send_nossl_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
8d99443b
VY
739{
740 static const char *nossl_cmd = "N";
741 conn_t *conn;
408a29c6 742 uint32_t id;
8d99443b
VY
743
744 if(ctlb != NULL)
3202e249 745 {
8d99443b 746 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
408a29c6
AC
747 id = buf_to_uint32(&ctlb->buf[1]);
748 conn_add_id_hash(conn, id);
8d99443b 749 close_conn(conn, WAIT_PLAIN, "libratbox reports no SSL/TLS support");
3202e249
VY
750 }
751 mod_cmd_write_queue(ctl, nossl_cmd, strlen(nossl_cmd));
8d99443b
VY
752}
753
754static void
3202e249 755send_i_am_useless(mod_ctl_t * ctl)
8d99443b
VY
756{
757 static const char *useless = "U";
758 mod_cmd_write_queue(ctl, useless, strlen(useless));
759}
760
e9ffc3c1
SA
761static void
762send_version(mod_ctl_t * ctl)
763{
764 char version[256] = { 'V', 0 };
765 strncpy(&version[1], rb_lib_version(), sizeof(version) - 2);
766 mod_cmd_write_queue(ctl, version, strlen(version));
767}
768
8d99443b 769static void
3202e249 770send_nozlib_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
8d99443b
VY
771{
772 static const char *nozlib_cmd = "z";
773 conn_t *conn;
408a29c6 774 uint32_t id;
8d99443b
VY
775 if(ctlb != NULL)
776 {
777 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
408a29c6
AC
778 id = buf_to_uint32(&ctlb->buf[1]);
779 conn_add_id_hash(conn, id);
8d99443b 780 close_conn(conn, WAIT_PLAIN, "libratbox reports no zlib support");
3202e249 781 }
8d99443b
VY
782 mod_cmd_write_queue(ctl, nozlib_cmd, strlen(nozlib_cmd));
783}
784
785static void
786mod_process_cmd_recv(mod_ctl_t * ctl)
787{
788 rb_dlink_node *ptr, *next;
789 mod_ctl_buf_t *ctl_buf;
790
791 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head)
792 {
793 ctl_buf = ptr->data;
794
795 switch (*ctl_buf->buf)
796 {
797 case 'A':
798 {
c03677e9
JT
799 if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5)
800 {
801 cleanup_bad_message(ctl, ctl_buf);
802 break;
803 }
804
d35870ee 805 if(!ssld_ssl_ok)
8d99443b
VY
806 {
807 send_nossl_support(ctl, ctl_buf);
808 break;
809 }
810 ssl_process_accept(ctl, ctl_buf);
811 break;
812 }
813 case 'C':
814 {
9e98a842 815 if (ctl_buf->buflen != 5)
c03677e9
JT
816 {
817 cleanup_bad_message(ctl, ctl_buf);
818 break;
819 }
820
d35870ee 821 if(!ssld_ssl_ok)
8d99443b
VY
822 {
823 send_nossl_support(ctl, ctl_buf);
824 break;
825 }
826 ssl_process_connect(ctl, ctl_buf);
827 break;
828 }
e6bbb410
EM
829 case 'F':
830 {
5a9fa2e2 831 if (ctl_buf->buflen != 5)
e6bbb410
EM
832 {
833 cleanup_bad_message(ctl, ctl_buf);
834 break;
835 }
836 ssl_change_certfp_method(ctl, ctl_buf);
837 break;
838 }
8d99443b
VY
839 case 'K':
840 {
d35870ee 841 if(!ssld_ssl_ok)
8d99443b
VY
842 {
843 send_nossl_support(ctl, ctl_buf);
844 break;
845 }
846 ssl_new_keys(ctl, ctl_buf);
847 break;
848 }
8d99443b
VY
849 case 'S':
850 {
851 process_stats(ctl, ctl_buf);
852 break;
853 }
07c2bb75 854
8d99443b 855 case 'Z':
21192997 856 send_nozlib_support(ctl, ctl_buf);
8d99443b 857 break;
3202e249 858
8d99443b
VY
859 default:
860 break;
861 /* Log unknown commands */
862 }
863 rb_dlinkDelete(ptr, &ctl->readq);
864 rb_free(ctl_buf->buf);
865 rb_free(ctl_buf);
866 }
867
868}
869
870
871
872static void
3202e249 873mod_read_ctl(rb_fde_t *F, void *data)
8d99443b
VY
874{
875 mod_ctl_buf_t *ctl_buf;
876 mod_ctl_t *ctl = data;
877 int retlen;
c03677e9 878 int i;
8d99443b
VY
879
880 do
881 {
882 ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
883 ctl_buf->buf = rb_malloc(READBUF_SIZE);
884 ctl_buf->buflen = READBUF_SIZE;
885 retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, ctl_buf->buflen, ctl_buf->F,
886 MAXPASSFD);
887 if(retlen <= 0)
888 {
889 rb_free(ctl_buf->buf);
890 rb_free(ctl_buf);
891 }
892 else
893 {
894 ctl_buf->buflen = retlen;
895 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq);
c03677e9
JT
896 for (i = 0; i < MAXPASSFD && ctl_buf->F[i] != NULL; i++)
897 ;
898 ctl_buf->nfds = i;
8d99443b
VY
899 }
900 }
3202e249 901 while(retlen > 0);
8d99443b
VY
902
903 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
904 exit(0);
905
906 mod_process_cmd_recv(ctl);
907 rb_setselect(ctl->F, RB_SELECT_READ, mod_read_ctl, ctl);
908}
909
910static void
3202e249 911mod_write_ctl(rb_fde_t *F, void *data)
8d99443b
VY
912{
913 mod_ctl_t *ctl = data;
914 mod_ctl_buf_t *ctl_buf;
915 rb_dlink_node *ptr, *next;
916 int retlen, x;
917
918 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head)
919 {
920 ctl_buf = ptr->data;
921 retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf,
3202e249 922 ctl_buf->buflen, ppid);
8d99443b
VY
923 if(retlen > 0)
924 {
925 rb_dlinkDelete(ptr, &ctl->writeq);
3202e249 926 for(x = 0; x < ctl_buf->nfds; x++)
8d99443b
VY
927 rb_close(ctl_buf->F[x]);
928 rb_free(ctl_buf->buf);
929 rb_free(ctl_buf);
930
931 }
932 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
3202e249
VY
933 exit(0);
934
8d99443b 935 }
464b7606
JT
936 if(rb_dlink_list_length(&ctl->writeq) > 0)
937 rb_setselect(ctl->F, RB_SELECT_WRITE, mod_write_ctl, ctl);
8d99443b
VY
938}
939
940
941static void
3202e249 942read_pipe_ctl(rb_fde_t *F, void *data)
8d99443b 943{
6cd1aca7 944 char inbuf[READBUF_SIZE];
8d99443b 945 int retlen;
3202e249 946 while((retlen = rb_read(F, inbuf, sizeof(inbuf))) > 0)
8d99443b
VY
947 {
948 ;; /* we don't do anything with the pipe really, just care if the other process dies.. */
949 }
950 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
951 exit(0);
952 rb_setselect(F, RB_SELECT_READ, read_pipe_ctl, NULL);
953
954}
955
956int
957main(int argc, char **argv)
958{
3202e249 959 const char *s_ctlfd, *s_pipe, *s_pid;
8f0c3422 960 int ctlfd, pipefd, maxfd, x;
8d99443b 961 maxfd = maxconn();
3202e249 962
8d99443b
VY
963 s_ctlfd = getenv("CTL_FD");
964 s_pipe = getenv("CTL_PIPE");
3202e249 965 s_pid = getenv("CTL_PPID");
8d99443b 966
3202e249 967 if(s_ctlfd == NULL || s_pipe == NULL || s_pid == NULL)
8d99443b 968 {
3202e249 969 fprintf(stderr,
a6f63a82 970 "This is the solanum ssld for internal ircd use.\n");
3202e249 971 fprintf(stderr,
4dbb75ee 972 "You aren't supposed to run me directly. Exiting.\n");
8d99443b
VY
973 exit(1);
974 }
975
976 ctlfd = atoi(s_ctlfd);
977 pipefd = atoi(s_pipe);
3202e249 978 ppid = atoi(s_pid);
209c57fb 979
4f8866f6 980 for(x = 3; x < maxfd; x++)
8d99443b 981 {
4f8866f6 982 if(x != ctlfd && x != pipefd)
8d99443b
VY
983 close(x);
984 }
4f8866f6 985
8d99443b 986 x = open("/dev/null", O_RDWR);
464b7606 987
8d99443b
VY
988 if(x >= 0)
989 {
990 if(ctlfd != 0 && pipefd != 0)
991 dup2(x, 0);
992 if(ctlfd != 1 && pipefd != 1)
993 dup2(x, 1);
994 if(ctlfd != 2 && pipefd != 2)
995 dup2(x, 2);
996 if(x > 2)
997 close(x);
998 }
209c57fb 999
8d99443b
VY
1000 setup_signals();
1001 rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
1002 rb_init_rawbuffers(1024);
19d1853f 1003 rb_init_prng(NULL, RB_PRNG_DEFAULT);
d35870ee 1004 ssld_ssl_ok = rb_supports_ssl();
8d99443b
VY
1005 mod_ctl = rb_malloc(sizeof(mod_ctl_t));
1006 mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
1007 mod_ctl->F_pipe = rb_open(pipefd, RB_FD_PIPE, "ircd pipe");
1008 rb_set_nb(mod_ctl->F);
1009 rb_set_nb(mod_ctl->F_pipe);
1010 rb_event_addish("clean_dead_conns", clean_dead_conns, NULL, 10);
4b6a4d47 1011 rb_event_add("check_handshake_flood", check_handshake_flood, NULL, 10);
8d99443b
VY
1012 read_pipe_ctl(mod_ctl->F_pipe, NULL);
1013 mod_read_ctl(mod_ctl->F, mod_ctl);
e9ffc3c1 1014 send_version(mod_ctl);
d35870ee 1015 if(!zlib_ok && !ssld_ssl_ok)
8d99443b
VY
1016 {
1017 /* this is really useless... */
1018 send_i_am_useless(mod_ctl);
1019 /* sleep until the ircd kills us */
1187d611 1020 rb_sleep(1 << 30, 0);
8d99443b
VY
1021 exit(1);
1022 }
1023
1024 if(!zlib_ok)
1025 send_nozlib_support(mod_ctl, NULL);
d35870ee 1026 if(!ssld_ssl_ok)
8d99443b
VY
1027 send_nossl_support(mod_ctl, NULL);
1028 rb_lib_loop(0);
1029 return 0;
1030}
1031
1032
8d99443b
VY
1033static void
1034dummy_handler(int sig)
1035{
1036 return;
1037}
1038
1039static void
1040setup_signals()
1041{
1042 struct sigaction act;
1043
1044 act.sa_flags = 0;
1045 act.sa_handler = SIG_IGN;
1046 sigemptyset(&act.sa_mask);
1047 sigaddset(&act.sa_mask, SIGPIPE);
1048 sigaddset(&act.sa_mask, SIGALRM);
1049#ifdef SIGTRAP
1050 sigaddset(&act.sa_mask, SIGTRAP);
1051#endif
1052
1053#ifdef SIGWINCH
1054 sigaddset(&act.sa_mask, SIGWINCH);
1055 sigaction(SIGWINCH, &act, 0);
1056#endif
1057 sigaction(SIGPIPE, &act, 0);
1058#ifdef SIGTRAP
1059 sigaction(SIGTRAP, &act, 0);
1060#endif
1061
1062 act.sa_handler = dummy_handler;
1063 sigaction(SIGALRM, &act, 0);
1064}