]> jfr.im git - solanum.git/blame - ssld/ssld.c
Add 3 more of the delegates to CREDITS
[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{
521#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
522 struct rlimit limit;
523
524 if(!getrlimit(RLIMIT_NOFILE, &limit))
525 {
526 return limit.rlim_cur;
527 }
528#endif /* RLIMIT_FD_MAX */
529 return MAXCONNECTIONS;
530}
531
408a29c6
AC
532static void
533ssl_send_cipher(conn_t *conn)
534{
408a29c6 535 size_t len;
74ff144d 536 uint8_t buf[512];
408a29c6
AC
537 char cstring[256];
538 const char *p;
539 if(!IsSSL(conn))
540 return;
541
542 p = rb_ssl_get_cipher(conn->mod_fd);
543
544 if(p == NULL)
545 return;
546
547 rb_strlcpy(cstring, p, sizeof(cstring));
548
549 buf[0] = 'C';
550 uint32_to_buf(&buf[1], conn->id);
74ff144d 551 strcpy((char *) &buf[5], cstring);
408a29c6
AC
552 len = (strlen(cstring) + 1) + 5;
553 mod_cmd_write_queue(conn->ctl, buf, len);
408a29c6
AC
554}
555
556static void
557ssl_send_certfp(conn_t *conn)
558{
dc986b54 559 uint8_t buf[13 + RB_SSL_CERTFP_LEN];
408a29c6 560
dc986b54 561 int len = rb_get_ssl_certfp(conn->mod_fd, &buf[13], certfp_method);
408a29c6
AC
562 if (!len)
563 return;
564
565 lrb_assert(len <= RB_SSL_CERTFP_LEN);
566 buf[0] = 'F';
567 uint32_to_buf(&buf[1], conn->id);
dc986b54
SA
568 uint32_to_buf(&buf[5], certfp_method);
569 uint32_to_buf(&buf[9], len);
570 mod_cmd_write_queue(conn->ctl, buf, 13 + len);
408a29c6
AC
571}
572
4fbb7362
SA
573static void
574ssl_send_open(conn_t *conn)
575{
576 uint8_t buf[5];
577
578 buf[0] = 'O';
579 uint32_to_buf(&buf[1], conn->id);
580 mod_cmd_write_queue(conn->ctl, buf, 5);
581}
582
8d99443b 583static void
3202e249 584ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
8d99443b
VY
585{
586 conn_t *conn = data;
7247337a 587
8d99443b
VY
588 if(status == RB_OK)
589 {
408a29c6
AC
590 ssl_send_cipher(conn);
591 ssl_send_certfp(conn);
4fbb7362 592 ssl_send_open(conn);
fbbc6aeb
SA
593 conn_mod_read_cb(conn->mod_fd, conn);
594 conn_plain_read_cb(conn->plain_fd, conn);
8d99443b
VY
595 return;
596 }
a444bb78 597 /* ircd doesn't care about the reason for this */
8d99443b
VY
598 close_conn(conn, NO_WAIT, 0);
599 return;
600}
601
602static void
3202e249 603ssl_process_connect_cb(rb_fde_t *F, int status, void *data)
8d99443b
VY
604{
605 conn_t *conn = data;
a7675ed2 606
8d99443b
VY
607 if(status == RB_OK)
608 {
408a29c6
AC
609 ssl_send_cipher(conn);
610 ssl_send_certfp(conn);
4fbb7362 611 ssl_send_open(conn);
fbbc6aeb
SA
612 conn_mod_read_cb(conn->mod_fd, conn);
613 conn_plain_read_cb(conn->plain_fd, conn);
8d99443b 614 }
a444bb78
JT
615 else if(status == RB_ERR_TIMEOUT)
616 close_conn(conn, WAIT_PLAIN, "SSL handshake timed out");
617 else if(status == RB_ERROR_SSL)
618 close_conn(conn, WAIT_PLAIN, "%s", rb_get_ssl_strerror(conn->mod_fd));
619 else
620 close_conn(conn, WAIT_PLAIN, "SSL handshake failed");
8d99443b
VY
621}
622
623
c03677e9
JT
624static void
625cleanup_bad_message(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
626{
627 int i;
628
629 /* XXX should log this somehow */
630 for (i = 0; i < ctlb->nfds; i++)
631 rb_close(ctlb->F[i]);
632}
633
8d99443b
VY
634static void
635ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
636{
637 conn_t *conn;
408a29c6 638 uint32_t id;
8d99443b
VY
639
640 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
641
408a29c6
AC
642 id = buf_to_uint32(&ctlb->buf[1]);
643 conn_add_id_hash(conn, id);
8d99443b
VY
644 SetSSL(conn);
645
646 if(rb_get_type(conn->mod_fd) & RB_FD_UNKNOWN)
8d99443b 647 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
a5ddb7df
AC
648
649 if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
8d99443b
VY
650 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
651
652 rb_ssl_start_accepted(ctlb->F[0], ssl_process_accept_cb, conn, 10);
653}
654
e6bbb410
EM
655static void
656ssl_change_certfp_method(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
657{
408a29c6 658 certfp_method = buf_to_uint32(&ctlb->buf[1]);
e6bbb410
EM
659}
660
8d99443b
VY
661static void
662ssl_process_connect(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
663{
664 conn_t *conn;
408a29c6 665 uint32_t id;
8d99443b
VY
666 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
667
408a29c6
AC
668 id = buf_to_uint32(&ctlb->buf[1]);
669 conn_add_id_hash(conn, id);
8d99443b
VY
670 SetSSL(conn);
671
672 if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
673 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
674
a5ddb7df 675 if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
8d99443b
VY
676 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
677
678
679 rb_ssl_start_connected(ctlb->F[0], ssl_process_connect_cb, conn, 10);
680}
681
682static void
683process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
684{
685 char outstat[512];
686 conn_t *conn;
85e9bf41 687 uint8_t *odata;
408a29c6 688 uint32_t id;
8d99443b 689
408a29c6 690 id = buf_to_uint32(&ctlb->buf[1]);
3202e249 691
8d99443b
VY
692 odata = &ctlb->buf[5];
693 conn = conn_find_by_id(id);
694
695 if(conn == NULL)
696 return;
697
5203cba5 698 snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
26b83fa0
SA
699 (unsigned long long)conn->plain_out,
700 (unsigned long long)conn->mod_in,
701 (unsigned long long)conn->plain_in,
702 (unsigned long long)conn->mod_out);
8d99443b
VY
703 conn->plain_out = 0;
704 conn->plain_in = 0;
705 conn->mod_in = 0;
706 conn->mod_out = 0;
707 mod_cmd_write_queue(ctl, outstat, strlen(outstat) + 1); /* +1 is so we send the \0 as well */
708}
709
8d99443b
VY
710static void
711ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
712{
713 char *buf;
c1725bda 714 char *cert, *key, *dhparam, *cipher_list;
8d99443b 715
85e9bf41 716 buf = (char *) &ctl_buf->buf[2];
8d99443b
VY
717 cert = buf;
718 buf += strlen(cert) + 1;
719 key = buf;
720 buf += strlen(key) + 1;
721 dhparam = buf;
c1725bda
AC
722 buf += strlen(dhparam) + 1;
723 cipher_list = buf;
f5960b83
AJ
724 if(strlen(key) == 0)
725 key = cert;
f831e926
AJ
726 if(strlen(dhparam) == 0)
727 dhparam = NULL;
c1725bda
AC
728 if(strlen(cipher_list) == 0)
729 cipher_list = NULL;
8d99443b 730
c1725bda 731 if(!rb_setup_ssl_server(cert, key, dhparam, cipher_list))
8d99443b
VY
732 {
733 const char *invalid = "I";
734 mod_cmd_write_queue(ctl, invalid, strlen(invalid));
735 return;
3202e249 736 }
8d99443b
VY
737}
738
739static void
3202e249 740send_nossl_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
8d99443b
VY
741{
742 static const char *nossl_cmd = "N";
743 conn_t *conn;
408a29c6 744 uint32_t id;
8d99443b
VY
745
746 if(ctlb != NULL)
3202e249 747 {
8d99443b 748 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
408a29c6
AC
749 id = buf_to_uint32(&ctlb->buf[1]);
750 conn_add_id_hash(conn, id);
8d99443b 751 close_conn(conn, WAIT_PLAIN, "libratbox reports no SSL/TLS support");
3202e249
VY
752 }
753 mod_cmd_write_queue(ctl, nossl_cmd, strlen(nossl_cmd));
8d99443b
VY
754}
755
756static void
3202e249 757send_i_am_useless(mod_ctl_t * ctl)
8d99443b
VY
758{
759 static const char *useless = "U";
760 mod_cmd_write_queue(ctl, useless, strlen(useless));
761}
762
e9ffc3c1
SA
763static void
764send_version(mod_ctl_t * ctl)
765{
766 char version[256] = { 'V', 0 };
767 strncpy(&version[1], rb_lib_version(), sizeof(version) - 2);
768 mod_cmd_write_queue(ctl, version, strlen(version));
769}
770
8d99443b 771static void
3202e249 772send_nozlib_support(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
8d99443b
VY
773{
774 static const char *nozlib_cmd = "z";
775 conn_t *conn;
408a29c6 776 uint32_t id;
8d99443b
VY
777 if(ctlb != NULL)
778 {
779 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
408a29c6
AC
780 id = buf_to_uint32(&ctlb->buf[1]);
781 conn_add_id_hash(conn, id);
8d99443b 782 close_conn(conn, WAIT_PLAIN, "libratbox reports no zlib support");
3202e249 783 }
8d99443b
VY
784 mod_cmd_write_queue(ctl, nozlib_cmd, strlen(nozlib_cmd));
785}
786
787static void
788mod_process_cmd_recv(mod_ctl_t * ctl)
789{
790 rb_dlink_node *ptr, *next;
791 mod_ctl_buf_t *ctl_buf;
792
793 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head)
794 {
795 ctl_buf = ptr->data;
796
797 switch (*ctl_buf->buf)
798 {
799 case 'A':
800 {
c03677e9
JT
801 if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5)
802 {
803 cleanup_bad_message(ctl, ctl_buf);
804 break;
805 }
806
d35870ee 807 if(!ssld_ssl_ok)
8d99443b
VY
808 {
809 send_nossl_support(ctl, ctl_buf);
810 break;
811 }
812 ssl_process_accept(ctl, ctl_buf);
813 break;
814 }
815 case 'C':
816 {
9e98a842 817 if (ctl_buf->buflen != 5)
c03677e9
JT
818 {
819 cleanup_bad_message(ctl, ctl_buf);
820 break;
821 }
822
d35870ee 823 if(!ssld_ssl_ok)
8d99443b
VY
824 {
825 send_nossl_support(ctl, ctl_buf);
826 break;
827 }
828 ssl_process_connect(ctl, ctl_buf);
829 break;
830 }
e6bbb410
EM
831 case 'F':
832 {
5a9fa2e2 833 if (ctl_buf->buflen != 5)
e6bbb410
EM
834 {
835 cleanup_bad_message(ctl, ctl_buf);
836 break;
837 }
838 ssl_change_certfp_method(ctl, ctl_buf);
839 break;
840 }
8d99443b
VY
841 case 'K':
842 {
d35870ee 843 if(!ssld_ssl_ok)
8d99443b
VY
844 {
845 send_nossl_support(ctl, ctl_buf);
846 break;
847 }
848 ssl_new_keys(ctl, ctl_buf);
849 break;
850 }
8d99443b
VY
851 case 'S':
852 {
853 process_stats(ctl, ctl_buf);
854 break;
855 }
07c2bb75 856
8d99443b 857 case 'Z':
21192997 858 send_nozlib_support(ctl, ctl_buf);
8d99443b 859 break;
3202e249 860
8d99443b
VY
861 default:
862 break;
863 /* Log unknown commands */
864 }
865 rb_dlinkDelete(ptr, &ctl->readq);
866 rb_free(ctl_buf->buf);
867 rb_free(ctl_buf);
868 }
869
870}
871
872
873
874static void
3202e249 875mod_read_ctl(rb_fde_t *F, void *data)
8d99443b
VY
876{
877 mod_ctl_buf_t *ctl_buf;
878 mod_ctl_t *ctl = data;
879 int retlen;
c03677e9 880 int i;
8d99443b
VY
881
882 do
883 {
884 ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
885 ctl_buf->buf = rb_malloc(READBUF_SIZE);
886 ctl_buf->buflen = READBUF_SIZE;
887 retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, ctl_buf->buflen, ctl_buf->F,
888 MAXPASSFD);
889 if(retlen <= 0)
890 {
891 rb_free(ctl_buf->buf);
892 rb_free(ctl_buf);
893 }
894 else
895 {
896 ctl_buf->buflen = retlen;
897 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq);
c03677e9
JT
898 for (i = 0; i < MAXPASSFD && ctl_buf->F[i] != NULL; i++)
899 ;
900 ctl_buf->nfds = i;
8d99443b
VY
901 }
902 }
3202e249 903 while(retlen > 0);
8d99443b
VY
904
905 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
906 exit(0);
907
908 mod_process_cmd_recv(ctl);
909 rb_setselect(ctl->F, RB_SELECT_READ, mod_read_ctl, ctl);
910}
911
912static void
3202e249 913mod_write_ctl(rb_fde_t *F, void *data)
8d99443b
VY
914{
915 mod_ctl_t *ctl = data;
916 mod_ctl_buf_t *ctl_buf;
917 rb_dlink_node *ptr, *next;
918 int retlen, x;
919
920 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head)
921 {
922 ctl_buf = ptr->data;
923 retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf,
3202e249 924 ctl_buf->buflen, ppid);
8d99443b
VY
925 if(retlen > 0)
926 {
927 rb_dlinkDelete(ptr, &ctl->writeq);
3202e249 928 for(x = 0; x < ctl_buf->nfds; x++)
8d99443b
VY
929 rb_close(ctl_buf->F[x]);
930 rb_free(ctl_buf->buf);
931 rb_free(ctl_buf);
932
933 }
934 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
3202e249
VY
935 exit(0);
936
8d99443b 937 }
464b7606
JT
938 if(rb_dlink_list_length(&ctl->writeq) > 0)
939 rb_setselect(ctl->F, RB_SELECT_WRITE, mod_write_ctl, ctl);
8d99443b
VY
940}
941
942
943static void
3202e249 944read_pipe_ctl(rb_fde_t *F, void *data)
8d99443b 945{
6cd1aca7 946 char inbuf[READBUF_SIZE];
8d99443b 947 int retlen;
3202e249 948 while((retlen = rb_read(F, inbuf, sizeof(inbuf))) > 0)
8d99443b
VY
949 {
950 ;; /* we don't do anything with the pipe really, just care if the other process dies.. */
951 }
952 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
953 exit(0);
954 rb_setselect(F, RB_SELECT_READ, read_pipe_ctl, NULL);
955
956}
957
958int
959main(int argc, char **argv)
960{
3202e249 961 const char *s_ctlfd, *s_pipe, *s_pid;
8f0c3422 962 int ctlfd, pipefd, maxfd, x;
8d99443b 963 maxfd = maxconn();
3202e249 964
8d99443b
VY
965 s_ctlfd = getenv("CTL_FD");
966 s_pipe = getenv("CTL_PIPE");
3202e249 967 s_pid = getenv("CTL_PPID");
8d99443b 968
3202e249 969 if(s_ctlfd == NULL || s_pipe == NULL || s_pid == NULL)
8d99443b 970 {
3202e249 971 fprintf(stderr,
a6f63a82 972 "This is the solanum ssld for internal ircd use.\n");
3202e249 973 fprintf(stderr,
4dbb75ee 974 "You aren't supposed to run me directly. Exiting.\n");
8d99443b
VY
975 exit(1);
976 }
977
978 ctlfd = atoi(s_ctlfd);
979 pipefd = atoi(s_pipe);
3202e249 980 ppid = atoi(s_pid);
209c57fb 981
4f8866f6 982 for(x = 3; x < maxfd; x++)
8d99443b 983 {
4f8866f6 984 if(x != ctlfd && x != pipefd)
8d99443b
VY
985 close(x);
986 }
4f8866f6 987
8d99443b 988 x = open("/dev/null", O_RDWR);
464b7606 989
8d99443b
VY
990 if(x >= 0)
991 {
992 if(ctlfd != 0 && pipefd != 0)
993 dup2(x, 0);
994 if(ctlfd != 1 && pipefd != 1)
995 dup2(x, 1);
996 if(ctlfd != 2 && pipefd != 2)
997 dup2(x, 2);
998 if(x > 2)
999 close(x);
1000 }
209c57fb 1001
8d99443b
VY
1002 setup_signals();
1003 rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
1004 rb_init_rawbuffers(1024);
19d1853f 1005 rb_init_prng(NULL, RB_PRNG_DEFAULT);
d35870ee 1006 ssld_ssl_ok = rb_supports_ssl();
8d99443b
VY
1007 mod_ctl = rb_malloc(sizeof(mod_ctl_t));
1008 mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
1009 mod_ctl->F_pipe = rb_open(pipefd, RB_FD_PIPE, "ircd pipe");
1010 rb_set_nb(mod_ctl->F);
1011 rb_set_nb(mod_ctl->F_pipe);
1012 rb_event_addish("clean_dead_conns", clean_dead_conns, NULL, 10);
4b6a4d47 1013 rb_event_add("check_handshake_flood", check_handshake_flood, NULL, 10);
8d99443b
VY
1014 read_pipe_ctl(mod_ctl->F_pipe, NULL);
1015 mod_read_ctl(mod_ctl->F, mod_ctl);
e9ffc3c1 1016 send_version(mod_ctl);
d35870ee 1017 if(!zlib_ok && !ssld_ssl_ok)
8d99443b
VY
1018 {
1019 /* this is really useless... */
1020 send_i_am_useless(mod_ctl);
1021 /* sleep until the ircd kills us */
1187d611 1022 rb_sleep(1 << 30, 0);
8d99443b
VY
1023 exit(1);
1024 }
1025
1026 if(!zlib_ok)
1027 send_nozlib_support(mod_ctl, NULL);
d35870ee 1028 if(!ssld_ssl_ok)
8d99443b
VY
1029 send_nossl_support(mod_ctl, NULL);
1030 rb_lib_loop(0);
1031 return 0;
1032}
1033
1034
8d99443b
VY
1035static void
1036dummy_handler(int sig)
1037{
1038 return;
1039}
1040
1041static void
1042setup_signals()
1043{
1044 struct sigaction act;
1045
1046 act.sa_flags = 0;
1047 act.sa_handler = SIG_IGN;
1048 sigemptyset(&act.sa_mask);
1049 sigaddset(&act.sa_mask, SIGPIPE);
1050 sigaddset(&act.sa_mask, SIGALRM);
1051#ifdef SIGTRAP
1052 sigaddset(&act.sa_mask, SIGTRAP);
1053#endif
1054
1055#ifdef SIGWINCH
1056 sigaddset(&act.sa_mask, SIGWINCH);
1057 sigaction(SIGWINCH, &act, 0);
1058#endif
1059 sigaction(SIGPIPE, &act, 0);
1060#ifdef SIGTRAP
1061 sigaction(SIGTRAP, &act, 0);
1062#endif
1063
1064 act.sa_handler = dummy_handler;
1065 sigaction(SIGALRM, &act, 0);
1066}