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