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