1 char *Version =
2 "tircproxy v0.4.5, Copyleft 2000, Bjarni R. Einarsson <bre@netverjar.is>" ;
3
4 /*****************************************************************************\
5 *
6 * This is an IRC proxy server. It can be started from inetd to service
7 * IRC requests, or run as a stand-alone daemon. It can operate with
8 * or without the Linux kernel's transparent proxy feature (or the IPF
9 * filters for *BSD systems). DCC requests are transparently accepted,
10 * rewritten and proxied for the clients.
11 *
12 * Thanks go to the author of transproxy.c, this program is based on his
13 * code - and without it I would have written a much messier program or
14 * none at all. This code is distributed under the GPL.
15 *
16 * See the files README, CHANGELOG.txt and BUGS.txt for more info!
17 * Don't forget to edit tircproxy.h to suit your tastes!
18 *
19 * ************************************************************************* *
20 *
21 * Note to hackers, porters, etc.
22 *
23 * Please, please let me know if you find bugs in my code!
24 *
25 \*****************************************************************************/
26
27 /* The following is an example of a useful broadcast file.. the format for
28 * /etc/motd.irc is the same (raw IRC server output, that is).
29 *
30 * Keep things short, people have flood protection out there.. and others
31 * are "suppressing" the MOTD!
32
33 :admin@isp.net 999 * :This is a fake server message!
34 :bofh!admin@isp.net PRIVMSG #notice :The proxy server is about to be shut down!
35 :bofh!admin@isp.net PRIVMSG #notice :Be very afraid!!!
36
37 */
38
39 #include <config.h>
40
41 #include <unistd.h>
42 #include <sys/time.h>
43 #include <sys/socket.h>
44 #include <sys/wait.h>
45 #include <sys/stat.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <netdb.h>
49 #include <sys/types.h>
50 #include <syslog.h>
51 #include <signal.h>
52 #include <pwd.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <stdarg.h>
56 #include <string.h>
57 #include <ctype.h>
58 #include <fcntl.h>
59 #include <errno.h>
60
61 #include <tircproxy.h>
62
63 /* "Inheritance" of config options.
64 */
65 #ifdef PARANOID
66 # ifndef MIRC_DCC_KLUDGE
67 # define MIRC_DCC_KLUDGE 1
68 # endif
69 # ifndef NICK_LOG
70 # define NICK_LOG
71 # endif
72 #endif
73
74 #ifdef MIRC_DCC_KLUDGE
75 # warning MIRC DCC kludge active
76 #endif
77 #ifdef NICK_LOG
78 # warning Nickname logging active
79 #endif
80
81 #ifdef CDIR
82 # ifndef IP_TO_UID_PREFIX
83 # define IP_TO_UID_PREFIX CDIR CDIR_MAP "-"
84 # endif
85 #endif
86
87 /* Autoconf stuff
88 */
89
90 #ifdef HAVE_CRYPT_H
91 # include <crypt.h>
92 #endif
93
94 #if (HAVE_UDB_H && USE_UDB)
95 # warning Using UDB style IPC for identd etc.
96 # include <udb.h>
97 # undef CDIR
98 # define CDIR 1
99 # undef CDIR_IDENT
100 # define CDIR_IDENT 1
101 # undef IP_TO_UID_PREFIX
102 #else
103 # undef USE_UDB
104 #endif
105
106 #ifndef INADDR_NONE
107 # define INADDR_NONE -1
108 #endif
109
110 #if !HAVE_LIBWRAP
111 # undef TCP_WRAPPERS
112 # warning Configuration via /etc/hosts.* not available
113 #else
114 # warning Configuration via /etc/hosts.* available
115 #endif
116
117 #ifndef IPF
118 # define IPF 0
119 #endif
120 #undef TRANS
121
122 #if IPF
123 # if HAVE_NETINET_IP_NAT_H
124 # include <sys/ioctl.h>
125 # include <net/if.h>
126 # include <netinet/in_systm.h>
127 # include <netinet/tcp.h>
128 # if HAVE_NETINET_IP_FIL_COMPAT_H
129 # include <netinet/ip_fil_compat.h>
130 # else
131 # include <netinet/ip_compat.h>
132 # endif
133 # include <netinet/ip_fil.h>
134 # include <netinet/ip_nat.h>
135 # include <netinet/ip_state.h>
136 # include <netinet/ip_proxy.h>
137 # include <netinet/ip_nat.h>
138 # include <netinet/ipl.h>
139 # include <osreldate.h>
140 # define TRANS 1
141 # ifndef IPL_NAT
142 # define IPL_NAT IPNAT_NAME
143 # endif
144 # warning IPF transparent proxying available
145 # else
146 # undef IPF
147 # define IPF 0
148 # warning IPF support not available
149 # endif
150 #endif
151
152 #ifndef LINUX
153 # define LINUX 0
154 #endif
155
156 #if LINUX
157 # ifndef HAVE_LINUX
158 # undef LINUX
159 # define LINUX 0
160 # warning Linux support not available
161 # else
162 # warning Linux transparent proxying available (depends on kernel)
163 # define TRANS 1
164 # endif
165 #endif
166
167 #if QUIZ_MODE
168 # warning Quiz mode available
169 #else
170 # warning Quiz mode not available
171 #endif
172
173 /* Some useful definitions, which we might get from the system.
174 */
175 #ifndef MAXLOGNAME
176 # define MAXLOGNAME 64
177 #endif
178
179 #ifndef PATH_MAX
180 # define PATH_MAX 256
181 #endif
182
183 /* Do we want to use the TCP wrappers for access control?
184 */
185 #ifdef TCP_WRAPPERS
186 #include "tcpd.h"
187
188 int allow_severity = 0;
189 int deny_severity = 0;
190 int hosts_ctl(char *daemon,
191 char *client_name,
192 char *client_addr,
193 char *client_user);
194
195 #endif
196
197
198 /* Typedefs.
199 */
200 typedef unsigned long ipaddr_t;
201
202
203 /* Macros & definitions.
204 */
205 #define FD_MAX(a,b) ((a) > (b) ? (a) : (b))
206 #define MINUTE 60
207
208 #define DEBUG_FEATURES 1
209 #define DEBUG_BASIC 2
210 #define DEBUG_TRIVIA 8
211 #define DEBUG_NOFORK 9
212
213
214 /* Function prototypes.
215 */
216 static void usage (char *prog, char *opt);
217 static short get_port_num (char *portnum);
218 static ipaddr_t get_ip_addr (char *ipaddr);
219 static uid_t get_user_id (char *user);
220 static uid_t get_group_id (uid_t uid);
221 static int bind_to_port (ipaddr_t bind_ip, short bind_port,
222 int backlog, int dlev);
223 static int connect_to_server (struct sockaddr_in addr);
224 static void lookup_hostname (struct sockaddr_in *addr, char *hostname,
225 int hostlen, int needed);
226 static void server_main_loop (int sock);
227 static void trans_proxy (int sock, struct sockaddr_in *addr);
228 static int copy_loop (int sock, struct sockaddr_in *from_addr,
229 struct sockaddr_in *to_addr,
230 int is_server_connection);
231 static int copy_once (int rsock, char *rbuffer, int rbufsize,
232 char *rname,
233 int wsock, char *wlbuffer, int *wlbufpos,
234 char *wname,
235 int is_server_connection, int r_is_client,
236 int *read_len);
237 static int filtered_write (int to_sock, char *buff, int blen,
238 char *leftover, int *llen,
239 int isclient);
240 static int scan_line (char *line, int isclient);
241 static int dcc_mangle_filename (char *filename);
242 static int dcc_resume (int destport, int resume);
243 static char *proxy_dcc (int destaddr, int destport, int incoming);
244 static void get_user_name (struct sockaddr_in *addr);
245 static void change_uid (void);
246 #ifdef CDIR
247 static void tell_identd (struct sockaddr_in *, struct sockaddr_in *);
248 static void cleanup_identd (void);
249 #endif
250 static void broadcast (int sock, const char *filename);
251 static void alarm_signal (int sig);
252 static void hup_signal (int sig);
253 static void chld_signal (int sig);
254 static void debug_msg (int lev, int pri, const char *format, ...);
255 #ifdef QUIZ_MODE
256 static void quiz_delay_line (char *line, char **first, char ***bl);
257 static void quiz_dump_lines (int sock, char **first, char ***bl);
258 static void quiz_check_auth (char *pass);
259 static void quiz_msg (char *message);
260 static void quiz_greet (void);
261 #endif
262
263 /* Taken from the RFC 1459 ..
264 */
265 #define LENGTH_NICKNAME 9
266 #define LENGTH_SERVERDATA 512
267
268 /* These make useful global variables..
269 */
270 char user_nick[LENGTH_NICKNAME * 2];
271 char user_name[MAXLOGNAME];
272 char user_ident_file[PATH_MAX];
273 char server_tag[64], alarm_in[64];
274 ipaddr_t clients_ip = INADDR_NONE;
275 char clients_ip_s[64];
276 int motd_is_done = 0;
277
278 /* We need to remember some stuff to support DCC RESUME.
279 ** See: http://www.mirc.co.uk/help/dccresum.txt
280 */
281 #define MAX_DCC_SESSIONS 10
282 time_t dcc_session_time [MAX_DCC_SESSIONS];
283 int dcc_original_port [MAX_DCC_SESSIONS];
284 int dcc_proxied_port [MAX_DCC_SESSIONS];
285
286 /* Quid mode - require a password or an answer to some silly
287 ** question before sending the users' output to the server.
288 */
289 #ifdef QUIZ_MODE
290 # define QUIZ_OFF 0
291 # define QUIZ_ON 1
292 # define QUIZ_READY 2
293 # define QUIZ_FLUSH 3
294 # define QUIZ_S &from_cli_first, &from_cli_last
295 # define QUIZ_C &to_cli_first, &to_cli_last
296 char *from_cli_first = NULL;
297 char **from_cli_last = NULL;
298 char *to_cli_first = NULL;
299 char **to_cli_last = NULL;
300 char quizfile[PATH_MAX], quiz[512];
301 int use_unix_passwd = QUIZ_OFF;
302 int use_quiz_mode = QUIZ_OFF;
303 #endif
304
305 /* Configuration variables..
306 */
307 ipaddr_t bind_ip = INADDR_ANY;
308 ipaddr_t server_ip = INADDR_NONE;
309 ipaddr_t visible_ip_i = INADDR_ANY;
310 char visible_ip_i_s[64];
311 ipaddr_t visible_ip_o = INADDR_ANY;
312 char visible_ip_o_s[64];
313 int throttle_seconds = -1;
314 int allow_dcc_send = 1;
315 int allow_dcc_chat = 1;
316 int allow_dcc_unknown = 1;
317 short server_port = -1;
318 int broadcast_flag = 0;
319 int not_an_irc_proxy = 0;
320 int use_dcc_mangling = 1;
321 int use_syslog = 1;
322 int debug_level = 0;
323 int use_anonymity = 0;
324 int anon_notval = 0;
325 #ifdef PARANOID
326 int use_paranoid = 1;
327 #endif
328 #ifdef MIRC_DCC_KLUDGE
329 int use_mirc_dcc_kludge = 1;
330 #endif
331 #ifdef NICK_LOG
332 int use_nick_log = 1;
333 #endif
334 #ifdef TCP_WRAPPERS
335 int use_tcp_wrappers = 1;
336 #endif
337 #ifdef CDIR
338 int use_cdir = 1;
339 #endif
340 #ifdef USE_UDB
341 struct udb_connection conn;
342 #endif
343
344
345 /* Main!
346 */
main(int argc,char ** argv)347 int main(int argc, char **argv)
348 {
349 int arg;
350 int run_as_server = 0;
351 short bind_port = -1;
352 uid_t run_uid = 0;
353 gid_t run_gid = 0;
354 int sock;
355 struct sockaddr_in addr;
356 int len;
357
358 /* Parse the command line arguments.
359 */
360 while ((arg = getopt(argc, argv, "ab:d:h?i:o:pq:r:s:t:CDHIKLMNOQRSU")) != EOF)
361 {
362 switch (arg)
363 {
364
365 case 'a':
366 use_anonymity = 1;
367 break;
368 case 'b':
369 bind_ip = get_ip_addr(optarg);
370 break;
371 case 'd':
372 #ifdef TIRC_DEBUG
373 debug_level = atoi(optarg);
374 #else
375 usage(argv[0],"Feature DEBUG not available.");
376 #endif
377 break;
378 case 'h':
379 case '?':
380 usage(argv[0], NULL);
381 break;
382 case 'i':
383 visible_ip_i = get_ip_addr(optarg);
384 break;
385 case 'o':
386 visible_ip_o = get_ip_addr(optarg);
387 break;
388 case 'p':
389 #ifdef QUIZ_MODE
390 use_quiz_mode = use_unix_passwd = QUIZ_ON;
391 if (getuid()) fprintf(stderr,
392 "Warning: Not running as root, may not be able to check passwords!\n");
393 #else
394 usage(argv[0],"Feature QUIZ_MODE not active.");
395 #endif
396 break;
397 case 'q':
398 #ifdef QUIZ_MODE
399 use_quiz_mode = QUIZ_ON;
400 strncpy(quizfile, optarg, PATH_MAX);
401 quizfile[PATH_MAX-1] = '\0';
402 #else
403 usage(argv[0],"Feature QUIZ_MODE not active.");
404 #endif
405 break;
406 case 'r':
407 run_uid = get_user_id(optarg);
408 run_gid = get_group_id(run_uid);
409 break;
410 case 's':
411 run_as_server = 1;
412 bind_port = get_port_num(optarg);
413 break;
414
415 case 't':
416 throttle_seconds = atoi(optarg);
417 break;
418
419 case 'C':
420 allow_dcc_chat = 0;
421 break;
422
423 case 'D':
424 #ifdef NICK_LOG
425 use_nick_log = 0;
426 #else
427 usage(argv[0],"Feature NICK_LOG not active.");
428 #endif
429 break;
430 case 'H':
431 #ifdef TCP_WRAPPERS
432 use_tcp_wrappers = 0;
433 #else
434 usage(argv[0],"Feature TCP_WRAPPERS not active.");
435 #endif
436 break;
437 case 'I':
438 case 'O': /* backwards compatibility ... */
439 #ifdef CDIR
440 use_cdir = 0;
441 #else
442 usage(argv[0],"Neither CDIR nor USE_UDB compiled in, sorry.");
443 #endif
444 break;
445 case 'K':
446 #ifdef MIRC_DCC_KLUDGE
447 use_mirc_dcc_kludge = 0;
448 #else
449 usage(argv[0],"Feature MIRC_DCC_KLUDGE not active.");
450 #endif
451 break;
452 case 'L':
453 use_syslog = 0;
454 break;
455 case 'M':
456 use_dcc_mangling = 0;
457 break;
458
459 case 'N':
460 not_an_irc_proxy = 1;
461 break;
462 case 'R':
463 #ifdef PARANOID
464 use_paranoid = 0;
465 #else
466 usage(argv[0],"Feature PARANOID not active.");
467 #endif
468 break;
469 case 'S':
470 allow_dcc_send = 0;
471 break;
472 case 'U':
473 allow_dcc_unknown = 0;
474 break;
475 }
476 }
477
478 /* Set a few variables to 'default' values.
479 */
480 if ((bind_ip != INADDR_ANY) && (visible_ip_i == INADDR_ANY))
481 visible_ip_i = bind_ip;
482
483 *user_ident_file = *user_name = *user_nick = '\0';
484
485 /* Process the remaining command line arguments.
486 */
487 for (; optind < argc; ++optind)
488 {
489 if (server_ip == INADDR_NONE)
490 {
491 server_ip = get_ip_addr(argv[optind]);
492 }
493 else if (server_port == -1)
494 {
495 server_port = get_port_num(argv[optind]);
496 }
497 else
498 {
499 usage(argv[0], "Extra arguments were specified.");
500 }
501 }
502
503 if (server_ip == INADDR_NONE)
504 {
505 #ifndef TRANS
506 usage(argv[0], "No remote server specified!");
507 #else
508 if ((visible_ip_i == INADDR_ANY) &&
509 (allow_dcc_send | allow_dcc_chat | allow_dcc_unknown) &&
510 (!not_an_irc_proxy))
511 {
512 usage(argv[0], "No internal address specified, DCC would break!");
513 }
514
515 fprintf(stderr,
516 "No remote server specified, transparent operation assumed.\n");
517 #endif
518 }
519 else
520 {
521 if (server_port == -1)
522 {
523 server_port = 6667;
524 fprintf(stderr,"No remote port specified, defaulting to 6667\n");
525 }
526 }
527
528 /* Create a "server tag" for this proxy. This is used for preventing
529 ** loops, while allowing proxy-to-proxy operation.
530 */
531 {
532 char hostname[128];
533 gethostname(hostname, 127);
534
535 /* server_tag is 64 bytes - this is safe */
536 sprintf(server_tag, "X-tircproxy[%d/%.10s]\n",
537 getpid(), hostname );
538 }
539
540 #ifdef USE_UDB
541 /* Aquire handles to the UDB shared memory.
542 */
543 udb_init(UDB_ENV_BASE_KEY);
544 #endif
545
546 /* See if we should run as a server.
547 */
548 if (run_as_server)
549 {
550 /* Randomize the anonymouse userid.
551 */
552 if (use_anonymity)
553 {
554 srand(time((time_t) NULL));
555 anon_notval = rand();
556 }
557
558 /* Start by binding to the port, the child inherits this socket.
559 */
560 sock = bind_to_port(bind_ip, bind_port, SOMAXCONN, 0);
561 if (sock < 0)
562 {
563 usage(argv[0], "Failed to bind to port, is another tircproxy still running?");
564 }
565
566 /* Start a server process. When DEBUG is defined, and the
567 ** debug level is high, just run in the foreground.
568 */
569 #ifdef TIRC_DEBUG
570 switch ((debug_level >= DEBUG_NOFORK) ? 0 : fork())
571 #else
572 switch (fork())
573 #endif
574 {
575 case -1:
576 perror("fork()");
577 exit(1);
578
579 case 0:
580 /* Open syslog for logging errors.
581 */
582 if ((use_syslog) && (debug_level < DEBUG_NOFORK))
583 openlog((not_an_irc_proxy) ? "proxy" : "tircproxy",
584 LOG_PID, LOG_DAEMON);
585
586 /* Ignore some signals.
587 */
588 signal(SIGHUP, SIG_IGN);
589 #ifdef TIRC_DEBUG
590 if (debug_level < DEBUG_NOFORK)
591 #else
592 signal(SIGINT, SIG_IGN);
593 #endif
594 signal(SIGQUIT, SIG_IGN);
595 signal(SIGTSTP, SIG_IGN);
596 signal(SIGCONT, SIG_IGN);
597 signal(SIGPIPE, SIG_IGN);
598 signal(SIGALRM, alarm_signal);
599
600 if (run_gid)
601 {
602 /* Drop back to an untrusted user.
603 */
604 setgid(run_gid);
605 setuid(run_uid);
606
607 /* Start a new session and group.
608 */
609 setsid();
610 #ifdef HAVE_LINUX
611 setpgrp();
612 #endif
613 }
614
615 /* Handle the server main loop.
616 */
617 server_main_loop(sock);
618
619 /* Should never exit.
620 */
621 closelog();
622 exit(1);
623 }
624
625 /* Parent exits at this stage.
626 */
627 exit(0);
628 }
629
630 /* Open syslog for logging errors.
631 */
632 if ((use_syslog) && (debug_level < DEBUG_NOFORK))
633 openlog((not_an_irc_proxy) ? "proxy" : "tircproxy",
634 LOG_PID, LOG_DAEMON);
635
636 /* We are running from inetd so find the peer address.
637 */
638 len = sizeof(addr);
639 if (getpeername(STDIN_FILENO, (struct sockaddr *)&addr, &len) < 0)
640 {
641 debug_msg(0, LOG_ERR, "getpeername(): %.256s", strerror(errno));
642 closelog();
643
644 usage(argv[0], NULL);
645 }
646
647 /* Randomize (well, not really..) the anonymouse userid.
648 */
649 if (use_anonymity) anon_notval = (time((time_t) NULL) >> 17);
650
651 /* Make note of the client's IP address.
652 */
653 clients_ip = addr.sin_addr.s_addr;
654 lookup_hostname(&addr, clients_ip_s, sizeof(clients_ip_s), 0);
655
656 /* Set the keepalive socket option to on.
657 */
658 {
659 int on = 1;
660 setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
661 }
662
663 /* We are running from inetd so process stdin.
664 */
665 trans_proxy(STDIN_FILENO, &addr);
666 closelog();
667
668 return (0);
669 }
670
671
672 /* Print some basic help information.
673 */
usage(char * prog,char * opt)674 static void usage(char *prog, char *opt)
675 {
676 fprintf(stderr,"%s\n\n\
677 Usage: %s [switches..] [options..] [ircserver [ircport]]\n\
678 \n\
679 Options:\n",Version,prog);
680 #ifdef TIRC_DEBUG
681 fprintf(stderr,
682 " -d level Set debug level (0=nothing .. 8=everything, 9=foreground).\n");
683 #endif
684 fprintf(stderr,"\
685 -s port Run as a server bound to the specified port.\n\
686 -b ipaddr Bind to the specified ipaddr in server mode.\n\
687 -i ipaddr Internal IP, needed for incoming DCCs (when transparent).\n\
688 -o ipaddr Visible IP, used for connecting to the IRC server (and others).\n");
689 #ifdef QUIZ_MODE
690 fprintf(stderr,"\
691 -p Require a valid Unix password for access.\n\
692 -q file Read a list of 'quizzes' from the named file.\n");
693 #endif
694 fprintf(stderr,"\
695 -a Anonymous mode, hide as much info about the user as possible.\n\
696 -r user Run as the specified user in server mode.\n\
697 -t n Force a sleep(1) between connections under n seconds apart.\n\
698 Switches:\n\
699 -M Disable DCC SEND filename mangling/censorship.\n\
700 -C Disallow DCC CHAT.\n\
701 -S Disallow DCC file transmissions (SEND, TSEND, etc.).\n\
702 -U Disallow unknown DCC requests.\n\
703 -L Log to stderr instead of syslog.\n\
704 -N Not an IRC proxy, disable all neat-o IRC stuff\n");
705 #ifdef CDIR
706 fprintf(stderr,"\
707 -I Do not attempt to communicate with the identd.\n");
708 #endif
709 #ifdef PARANOID
710 fprintf(stderr,"\
711 -R Relaxed, allows proxy service to IPs we can't map to a UID.\n");
712 #endif
713 #ifdef NICK_LOG
714 fprintf(stderr,"\
715 -D Don't log clients' nicknames in syslog.\n");
716 #endif
717 #ifdef MIRC_DCC_KLUDGE
718 fprintf(stderr,"\
719 -K Disable the \"mIRC DCC kludge\" (read the documentation).\n");
720 #endif
721 #ifdef TCP_WRAPPERS
722 fprintf(stderr,"\
723 -H Ignore /etc/hosts.allow and /etc/hosts.deny.\n");
724 #endif
725 fprintf(stderr,"\n\
726 By default all features enabled at compile-time are active. In server mode\n\
727 the -s flag is mandatory.\n");
728
729 #ifdef TRANS
730 fprintf(stderr,"\n\
731 If no IRC server/port pair is specified the proxy assumes it is running in\n\
732 transparent mode. This requires support from the Linux kernel or a working\n\
733 ipf filter installation!\n");
734 #endif
735
736 if (opt)
737 {
738 fprintf(stderr,"\nERROR: %s\n", opt);
739 }
740
741 exit(1);
742 }
743
744
745 /* Return the port number, in network order, of the specified service.
746 */
get_port_num(char * portnum)747 static short get_port_num(char *portnum)
748 {
749 char *digits = portnum;
750 struct servent *serv;
751 short port;
752
753 for (port = 0; isdigit(*digits); ++digits)
754 {
755 port = (port * 10) + (*digits - '0');
756 }
757
758 if ((*digits != '\0') || (port <= 0))
759 {
760 if ((serv = getservbyname(portnum, "tcp")) != NULL)
761 {
762 port = ntohs(serv->s_port);
763 }
764 else
765 {
766 port = -1;
767 }
768 endservent();
769 }
770
771 #ifdef TIRC_DEBUG
772 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,
773 "Port lookup %s -> %hd\n", portnum, port);
774 #endif
775
776 return (port);
777 }
778
779
780 /* Return the IP address of the specified host.
781 */
get_ip_addr(char * ipaddr)782 static ipaddr_t get_ip_addr(char *ipaddr)
783 {
784 struct hostent *host;
785 ipaddr_t ip;
786
787 if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
788 (strcmp(ipaddr, "255.255.255.255") != 0))
789 {
790 if ((host = gethostbyname(ipaddr)) != NULL)
791 {
792 memcpy(&ip, host->h_addr, sizeof(ip));
793 }
794 endhostent();
795 }
796
797 #ifdef TIRC_DEBUG
798 debug_msg(DEBUG_BASIC, LOG_DEBUG,
799 "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
800 #endif
801
802 return (ip);
803 }
804
805
806 /* Find the userid of the specified user.
807 */
get_user_id(char * user)808 static uid_t get_user_id(char *user)
809 {
810 struct passwd *pw;
811 uid_t uid;
812
813 if ((pw = getpwnam(user)) != NULL)
814 {
815 uid = pw->pw_uid;
816 }
817 else if (*user == '#')
818 {
819 uid = (uid_t)atoi(&user[1]);
820 }
821 else
822 {
823 uid = -1;
824 }
825
826 #ifdef TIRC_DEBUG
827 debug_msg(DEBUG_BASIC, LOG_DEBUG,
828 "User lookup %s -> %d\n", user, uid);
829 #endif
830
831 endpwent();
832
833 return (uid);
834 }
835
836
837 /* Find the groupid of the specified user.
838 */
get_group_id(uid_t uid)839 static uid_t get_group_id(uid_t uid)
840 {
841 struct passwd *pw;
842 gid_t gid;
843
844 if ((pw = getpwuid(uid)) != NULL)
845 {
846 gid = pw->pw_gid;
847 }
848 else
849 {
850 gid = -1;
851 }
852
853 #ifdef TIRC_DEBUG
854 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,
855 "Group lookup %d -> %d\n", uid, gid);
856 #endif
857
858 endpwent();
859
860 return (gid);
861 }
862
863
864 /* Bind to the specified ip and port.
865 */
bind_to_port(ipaddr_t bind_ip,short bind_port,int backlog,int dlev)866 static int bind_to_port(ipaddr_t bind_ip, short bind_port, int backlog, int dlev)
867 {
868 struct sockaddr_in addr;
869 int sock;
870
871 /* Allocate a socket.
872 */
873 if ((sock = socket(AF_INET, SOCK_STREAM,
874 getprotobyname("tcp")->p_proto)) < 0)
875 {
876 debug_msg(dlev, LOG_WARNING, "socket(): %d - %.256s", errno, strerror(errno));
877 return(-1);
878 }
879
880 #ifdef TIRC_DEBUG
881 /* Set the SO_REUSEADDR option for debugging.
882 */
883 if (debug_level >= DEBUG_NOFORK) {
884 int on = 1;
885
886 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
887 }
888 #endif
889
890 /* Set the address to listen to.
891 */
892 memset(&addr, '\0', sizeof(addr));
893 addr.sin_family = AF_INET;
894 addr.sin_port = htons(bind_port);
895 addr.sin_addr.s_addr = bind_ip;
896
897 /* Bind our socket to the above address.
898 */
899 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
900 {
901 debug_msg(dlev, LOG_WARNING, "bind(): %d - %.256s", errno, strerror(errno));
902 return(-1);
903 }
904
905 /* Establish a large listen backlog.
906 */
907 if (listen(sock, backlog) < 0)
908 {
909 debug_msg(dlev, LOG_WARNING, "listen(): %d - %.256s", errno, strerror(errno));
910 return(-1);
911 }
912
913 return (sock);
914 }
915
916
917 /* Connect to the a server.
918 */
connect_to_server(struct sockaddr_in addr)919 static int connect_to_server(struct sockaddr_in addr)
920 {
921 struct sockaddr_in my_addr;
922 int sock;
923
924 /* Allocate a socket.
925 */
926 if ((sock = socket(AF_INET, SOCK_STREAM,
927 getprotobyname("tcp")->p_proto)) < 0)
928 {
929 debug_msg(0, LOG_WARNING, "socket(): .%256s", strerror(errno));
930 return (-1);
931 }
932
933 /* Set the address to connect to, and the address to connect from.
934 */
935 addr.sin_family = AF_INET;
936
937 memset(&my_addr, '\0', sizeof(my_addr));
938 my_addr.sin_family = AF_INET;
939 my_addr.sin_port = 0;
940 my_addr.sin_addr.s_addr = visible_ip_o;
941
942 /* Bind to the address we want to use.
943 */
944 if (bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
945 debug_msg(0, LOG_WARNING, "bind(): %d - %.256s",
946 errno, strerror(errno));
947
948 /* Connect our socket to the above address.
949 */
950 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
951 {
952 debug_msg(0, LOG_WARNING, "connect(): %.256s", strerror(errno));
953 return (-1);
954 }
955
956 /* Set the keepalive socket option to on.
957 */
958 {
959 int on = 1;
960 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
961 }
962
963 return (sock);
964 }
965
966
967 /* Translate a sockaddr_in structure into a usable ASCII hostname.
968 */
lookup_hostname(struct sockaddr_in * addr,char * hostname,int hostlen,int needed)969 static void lookup_hostname(struct sockaddr_in *addr, char *hostname,
970 int hostlen, int needed)
971 {
972 struct hostent *host;
973
974 if (needed)
975 {
976 /* Attempt a DNS lookup..
977 */
978 if ((host = gethostbyaddr((char *)&addr->sin_addr,
979 sizeof(addr->sin_addr),
980 AF_INET)) != NULL)
981 {
982 strncpy(hostname, host->h_name, hostlen);
983 hostname[hostlen - 1] = '\0';
984 return;
985 }
986 }
987
988 /* Get the hostname IP in dotted decimal in case the lookup fails.
989 */
990 strncpy(hostname, inet_ntoa(addr->sin_addr), hostlen);
991 hostname[hostlen - 1] = '\0';
992 }
993
994
995 /* This is the main loop when running as a server.
996 */
server_main_loop(int sock)997 static void server_main_loop(int sock)
998 {
999 int new_sock;
1000 struct sockaddr_in addr;
1001 int len;
1002 time_t last_time, this_time;
1003 int delay;
1004
1005 /* Call cleanup func on SIGCHLD.
1006 */
1007 signal(SIGCHLD, chld_signal);
1008
1009 last_time = (time_t) 0;
1010 delay = 0;
1011
1012 for (;;)
1013 {
1014 /* Accept an incoming connection.
1015 */
1016 len = sizeof(addr);
1017 while ((new_sock =
1018 accept(sock, (struct sockaddr *)&addr, &len)) < 0)
1019 {
1020 /* Connection resets are common enough to log them as debug only.
1021 */
1022 debug_msg(0, (errno == ECONNRESET ? LOG_DEBUG : LOG_ERR), "accept(): %.256s", strerror(errno));
1023 }
1024
1025 /* At most send the server one connection every
1026 ** throttle_seconds seconds.
1027 */
1028 this_time = time((time_t) NULL);
1029 if (this_time <= last_time+delay+throttle_seconds)
1030 delay++;
1031 else delay = 0;
1032 last_time = this_time;
1033
1034 /* Make note of the client's IP address.
1035 */
1036 clients_ip = addr.sin_addr.s_addr;
1037 lookup_hostname(&addr, clients_ip_s, sizeof(clients_ip_s), 0);
1038
1039 /* Create a new process to handle the connection.
1040 */
1041 switch (fork())
1042 {
1043 case -1:
1044 /* Under load conditions just ignore new connections.
1045 */
1046 break;
1047
1048 case 0:
1049 /* Start the proxy work in the new socket.
1050 */
1051 broadcast_flag = 0;
1052 if (delay) {
1053 debug_msg(0, LOG_DEBUG,"Delaying connection %d seconds..",delay);
1054 sleep(delay);
1055 }
1056 trans_proxy(new_sock, &addr);
1057 close(new_sock);
1058 closelog();
1059 exit(0);
1060 }
1061
1062 /* Close the socket as the child does the handling.
1063 */
1064 close(new_sock);
1065 }
1066 }
1067
1068
1069 /* Handle connections transparently or otherwise..
1070 */
trans_proxy(int sock,struct sockaddr_in * from_addr)1071 static void trans_proxy(int sock, struct sockaddr_in *from_addr)
1072 {
1073 struct sockaddr_in to_addr;
1074 int to_len;
1075 #if IPF
1076 #if __FreeBSD_version >=600024
1077 ipfobj_t obj;
1078 #endif
1079 struct sockaddr_in socketin, sloc;
1080 natlookup_t natlook;
1081 natlookup_t *natlookp = &natlook;
1082 int fd;
1083 #endif
1084
1085 /* Give this thing 10 minutes to get started (paranoia).
1086 */
1087 signal(SIGALRM, alarm_signal);
1088 alarm(10*MINUTE);
1089 strcpy(alarm_in, "trans_proxy");
1090
1091 /* Check who the client is.
1092 */
1093 get_user_name(from_addr);
1094
1095 #ifdef TCP_WRAPPERS
1096 if (use_tcp_wrappers)
1097 {
1098 char host_ip[64], host_name[64];
1099
1100 /* Lookup an ASCII representation of the host's IP address,
1101 ** and attempt to look up it's FQDN as well (DNS).
1102 */
1103 lookup_hostname(from_addr, host_ip, sizeof(host_ip), 0);
1104 lookup_hostname(from_addr, host_name, sizeof(host_name), 1);
1105
1106 /* Check if the calling host is allowed to use the proxy.
1107 */
1108 if (!hosts_ctl((not_an_irc_proxy) ? "proxy" : "tircproxy",
1109 host_name, host_ip, user_name))
1110 {
1111 debug_msg(0, LOG_INFO,
1112 "Denied access to: %.32s@%.128s [%.96s]",
1113 user_name, host_name, host_ip);
1114 return;
1115 }
1116 }
1117 #endif
1118
1119 /* Are we running in transparent mode?
1120 */
1121 if (server_ip == INADDR_NONE)
1122 {
1123 /* There are two completely different ways to do this, one
1124 ** based on linux transparent proxying the other based on
1125 ** ipf transparent proyxing, only one is used
1126 */
1127 #if LINUX
1128 /* The Linux method:
1129 **
1130 ** The first thing we do is get the IP address that the client was
1131 ** trying to connected to. Here lies part of the magic. Normally
1132 ** getsockname returns our address, but not with transparent proxying.
1133 */
1134 to_len = sizeof(to_addr);
1135 if (getsockname(sock, (struct sockaddr *)&to_addr, &to_len) < 0)
1136 {
1137 debug_msg(0, LOG_ERR, "getsockname(): %.256s", strerror(errno));
1138 return;
1139 }
1140 #else
1141 # if IPF
1142 /* This is the ipf method
1143 */
1144 to_len = sizeof(socketin);
1145 if (getpeername(sock, (struct sockaddr *)&socketin, &to_len) == -1)
1146 {
1147 perror("getpeername");
1148 exit(-1);
1149 }
1150
1151 to_len = sizeof(socketin);
1152 if (getsockname(sock, (struct sockaddr *)&sloc, &to_len) == -1)
1153 {
1154 perror("getsockname");
1155 exit(-1);
1156 }
1157
1158 #if __FreeBSD_version >=600024
1159 bzero(&obj, sizeof(obj));
1160 obj.ipfo_rev = IPFILTER_VERSION;
1161 obj.ipfo_size = sizeof(natlook);
1162 obj.ipfo_ptr = &natlook;
1163 obj.ipfo_type = IPFOBJ_NATLOOKUP;
1164 #endif
1165 bzero((char *)&natlook, sizeof(natlook));
1166 natlook.nl_outip = socketin.sin_addr;
1167 natlook.nl_inip = sloc.sin_addr;
1168 natlook.nl_flags = IPN_TCP;
1169 natlook.nl_outport = socketin.sin_port;
1170 natlook.nl_inport = sloc.sin_port;
1171
1172 fd = open(IPL_NAT, O_RDONLY);
1173 #if __FreeBSD_version >=600024
1174 if (ioctl(fd, SIOCGNATL, &obj) == -1)
1175 #else
1176 if (ioctl(fd, SIOCGNATL, &natlookp) == -1)
1177 #endif
1178 {
1179 perror("ioctl(SIOCGNATL)");
1180 exit(-1);
1181 }
1182 close(fd);
1183
1184 /* [ The following is WEIRD. Why the htons(ntohs()) ??
1185 ** And why the getip..(inet_ntoa()) ??? ]
1186 */
1187 memset(&to_addr, '\0', sizeof(to_addr));
1188 to_addr.sin_family = AF_INET;
1189 to_addr.sin_port = htons(ntohs(natlook.nl_realport));
1190 to_addr.sin_addr.s_addr = get_ip_addr(inet_ntoa(natlook.nl_realip));
1191 # endif /* IFP */
1192 #endif /* LINUX */
1193 }
1194 else
1195 {
1196 /* Ok, not transparent, we'll connect to the specified server.
1197 */
1198 memset(&to_addr, '\0', sizeof(to_addr));
1199 to_addr.sin_family = AF_INET;
1200 to_addr.sin_port = htons(server_port);
1201 to_addr.sin_addr.s_addr = server_ip;
1202 }
1203
1204 /* Drop root privs if we have them.
1205 */
1206 change_uid();
1207
1208 signal(SIGHUP, hup_signal);
1209
1210 debug_msg(0, LOG_DEBUG,
1211 "Copied %d bytes, exiting.",
1212 copy_loop(sock, from_addr, &to_addr, !not_an_irc_proxy));
1213
1214 #ifdef CDIR_IDENT
1215 if (use_cdir)
1216 cleanup_identd();
1217 #endif
1218 }
1219
1220
1221 /* Perform the proxy activity itself.
1222 */
copy_loop(int sock,struct sockaddr_in * from_addr,struct sockaddr_in * to_addr,int is_server_connection)1223 static int copy_loop(int sock, struct sockaddr_in *from_addr,
1224 struct sockaddr_in *to_addr,
1225 int is_server_connection)
1226 {
1227 int server,junk;
1228 struct sockaddr_in ourend, ourend_i;
1229 char blurb[64];
1230 char from_host[64];
1231 char to_host[64];
1232 static char headers[16384 + 1];
1233 static char ser_left[16384 + 1];
1234 static char cli_left[16384 + 1];
1235 int ser_ln = 0;
1236 int cli_ln = 0;
1237 int select_loop;
1238 int max_fd;
1239 fd_set read_fd;
1240 int read_len;
1241 int motd_sent = 0;
1242 int copied_bytes = 0;
1243
1244 /* Allow 3 minutes for things to get properly started.
1245 */
1246 signal(SIGALRM, alarm_signal);
1247 alarm(3*MINUTE);
1248 strcpy(alarm_in, "copy_loop: starting");
1249
1250 /* Lookup an ASCII representation of the host's IP address.
1251 */
1252 lookup_hostname(from_addr, from_host, sizeof(from_host), 0);
1253 lookup_hostname(to_addr, to_host, sizeof(to_host), 0);
1254
1255 /* Read the first couple of lines from the client, take a
1256 ** peek. Check if the server is looping.
1257 */
1258 if (is_server_connection)
1259 {
1260 #ifdef TIRC_DEBUG
1261 debug_msg(DEBUG_BASIC, LOG_DEBUG,
1262 "Checking if this is a loopy server..");
1263 #endif
1264 server = read_len = -1;
1265 copy_once(sock, headers, sizeof(headers), "client",
1266 server, ser_left, &ser_ln, "server",
1267 is_server_connection, 1,
1268 &read_len);
1269
1270 if (read_len <= 0) return 0;
1271
1272 strncpy(blurb,headers,63);
1273 if (strstr(blurb,server_tag) != NULL)
1274 {
1275 debug_msg(0, LOG_INFO, "Looping detected, terminating!");
1276 return 0;
1277 }
1278 }
1279
1280 /* Connect to the server (or die).
1281 */
1282 if ((server = connect_to_server(*to_addr)) < 0) return 0;
1283 junk = sizeof(ourend);
1284 strcpy(alarm_in, "copy_loop: getsockname 1");
1285 getsockname(server, (struct sockaddr *) &ourend, &junk);
1286
1287 #ifdef CDIR_IDENT
1288 /* Tell the ident server which user this connection really belongs to.
1289 **
1290 ** Note: This may be a race between us and the remote IRC server,
1291 ** depending on the implementation of the ident server.
1292 */
1293 if (use_cdir && is_server_connection) tell_identd(&ourend, to_addr);
1294 #endif
1295
1296 strcpy(alarm_in, "copy_loop: getsockname 2");
1297 getsockname(sock, (struct sockaddr *) &ourend_i, &junk);
1298
1299 /* Record what IP addresses we're using.
1300 */
1301 visible_ip_o = ourend.sin_addr.s_addr;
1302 lookup_hostname(&ourend, visible_ip_o_s, sizeof(visible_ip_o_s), 0);
1303
1304 if (visible_ip_i == INADDR_ANY)
1305 {
1306 visible_ip_i = ourend_i.sin_addr.s_addr;
1307 lookup_hostname(&ourend_i, visible_ip_i_s, sizeof(visible_ip_i_s), 0);
1308 }
1309
1310 /* Log the facts about the connection.
1311 */
1312 debug_msg(0, LOG_INFO, "%.64s -%.64s:%d-> %.64s:%d",
1313 from_host, user_name, ntohs(ourend.sin_port),
1314 to_host, ntohs(to_addr->sin_port));
1315
1316 /* Pass the data we read just now on to the server..
1317 */
1318 if (is_server_connection)
1319 {
1320 junk = strlen(server_tag);
1321 copy_once(sock, server_tag, 0, "tircproxy",
1322 server, ser_left, &ser_ln, "server",
1323 is_server_connection, 1, &junk);
1324 copy_once(sock, headers, sizeof(headers), "client",
1325 server, ser_left, &ser_ln, "server",
1326 is_server_connection, 1, &read_len);
1327 if (read_len <= 0) return 0;
1328 }
1329
1330 /* Continue by passing data back and forth between the
1331 ** client and the server (or remote end of DCC).
1332 */
1333 for (;;)
1334 {
1335 /* Construct a select read mask from both file descriptors.
1336 */
1337 FD_ZERO(&read_fd);
1338 FD_SET(sock, &read_fd);
1339 FD_SET(server, &read_fd);
1340 max_fd = FD_MAX(sock, server);
1341
1342 /* Allow 30 minutes for the loop to complete.
1343 */
1344 signal(SIGALRM, alarm_signal);
1345 alarm(30*MINUTE);
1346 strcpy(alarm_in, "copy_loop: waiting");
1347 #ifdef TIRC_DEBUG
1348 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,"copy_loop: waiting");
1349 #endif
1350 /* Wait for some data to be read.
1351 */
1352 select_loop = 1;
1353 while (select_loop)
1354 if (select(max_fd + 1, &read_fd, NULL, NULL, NULL) < 0)
1355 {
1356 if (errno != EINTR) {
1357 #ifdef TIRC_DEBUG
1358 debug_msg(DEBUG_BASIC, LOG_ERR,
1359 "select(): %.256s",
1360 strerror(errno));
1361 #endif
1362 close(server);
1363 return copied_bytes;
1364 }
1365 } else
1366 select_loop = 0;
1367
1368 /* We aren't waiting anymore..
1369 */
1370 strcpy(alarm_in, "copy_loop: copying");
1371 #ifdef TIRC_DEBUG
1372 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,"copy_loop: copying");
1373 #endif
1374
1375 if (is_server_connection)
1376 {
1377 /* Send the user a message, if requested by admin.
1378 */
1379 #ifdef BROADCAST_FILE
1380 if (broadcast_flag) broadcast(sock, BROADCAST_FILE);
1381 #endif
1382 #ifdef IRC_MOTD_FILE
1383 /* Send the user the MOTD.
1384 */
1385 if ((!motd_sent) &&
1386 (motd_is_done) &&
1387 (is_server_connection))
1388 {
1389 broadcast(sock, IRC_MOTD_FILE);
1390 motd_sent = 1;
1391 }
1392 #endif
1393 }
1394
1395 /* See if any data can be read from the client.
1396 */
1397 if (FD_ISSET(sock, &read_fd))
1398 {
1399 read_len = 0;
1400 copy_once(sock, headers, sizeof(headers), "client",
1401 server, ser_left, &ser_ln, "server",
1402 is_server_connection, 1,
1403 &read_len);
1404 if (read_len < 0) return copied_bytes;
1405 copied_bytes += read_len;
1406 }
1407
1408 /* See if any data can be read from the server.
1409 */
1410 if (FD_ISSET(server, &read_fd))
1411 {
1412 read_len = 0;
1413 copy_once(server, headers, sizeof(headers), "server",
1414 sock, cli_left, &cli_ln, "client",
1415 is_server_connection, 0,
1416 &read_len);
1417 if (read_len < 0) return copied_bytes;
1418 copied_bytes += read_len;
1419 }
1420
1421 #ifdef QUIZ_MODE
1422 /* Dump queued data meant for the client.
1423 */
1424 if (use_quiz_mode && motd_is_done)
1425 quiz_dump_lines(sock, QUIZ_C);
1426
1427 /* Dump queued data, stop quizzing if quiz mode is "flush".
1428 */
1429 if ((use_quiz_mode == QUIZ_FLUSH) && (copied_bytes > 128))
1430 {
1431 quiz_dump_lines(server, QUIZ_S);
1432 use_quiz_mode = QUIZ_OFF;
1433 }
1434 #endif
1435 }
1436 }
1437
1438
1439 /* This function handles a single copy cycle from one socket to another.
1440 ** If *read_len <= 0, then
1441 ** It reads at most rbufsize bytes from rsock, into rbuffer.
1442 ** If *read_len >= 0, then
1443 ** It writes the contents of rbuffer to wsock.
1444 **
1445 ** Writes are filtered if the is_server_connection is true.
1446 ** The function returns -1 or -2 on errors, or the number of read bytes on
1447 ** success.
1448 */
copy_once(int rsock,char * rbuffer,int rbufsize,char * rname,int wsock,char * wlbuffer,int * wlbufpos,char * wname,int is_server_connection,int r_is_client,int * read_len)1449 static int copy_once(int rsock, char *rbuffer, int rbufsize, char *rname,
1450 int wsock, char *wlbuffer, int *wlbufpos, char *wname,
1451 int is_server_connection, int r_is_client,
1452 int *read_len)
1453 {
1454 int rlen;
1455
1456 #ifdef TIRC_DEBUG
1457 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,
1458 "Entering copy_once (reading %s, writing %s)",
1459 rname, wname);
1460 #endif
1461
1462 rlen = *read_len;
1463 if (rlen <= 0) rlen = read(rsock, rbuffer, rbufsize - 1);
1464
1465 switch (rlen)
1466 {
1467 case -1:
1468 #ifdef TIRC_DEBUG
1469 debug_msg(DEBUG_BASIC,
1470 (errno == ECONNRESET ? LOG_DEBUG : LOG_WARNING),
1471 "read(%.32s) failed: %.256s", rname, strerror(errno));
1472 #endif
1473 if (errno != EINTR)
1474 {
1475 close(wsock);
1476 return -2;
1477 }
1478 return 0;
1479 case 0:
1480 #ifdef TIRC_DEBUG
1481 debug_msg(DEBUG_TRIVIA, LOG_DEBUG, "EOF!");
1482 #endif
1483 close(rsock);
1484 close(wsock);
1485 return -1;
1486 default:
1487 if (*read_len >= 0)
1488 {
1489 if (is_server_connection)
1490 {
1491 if (!filtered_write(wsock, rbuffer, rlen,
1492 wlbuffer, wlbufpos, r_is_client))
1493 {
1494 #ifdef TIRC_DEBUG
1495 debug_msg(DEBUG_BASIC, LOG_WARNING,
1496 "write(%.32s) failed: %.256s",
1497 wname, strerror(errno));
1498 #endif
1499 close(rsock);
1500 return 0;
1501 }
1502 }
1503 else
1504 {
1505 while (write(wsock, rbuffer, rlen) < 0)
1506 if (errno != EINTR)
1507 {
1508 #ifdef TIRC_DEBUG
1509 debug_msg(DEBUG_BASIC, LOG_WARNING,
1510 "write(%.32s) failed: %.256s",
1511 wname, strerror(errno));
1512 #endif
1513 close(rsock);
1514 return 0;
1515 }
1516 }
1517 break;
1518 }
1519 }
1520 #ifdef TIRC_DEBUG
1521 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,
1522 "Leaving copy_once (rlen = %d)", rlen);
1523 #endif
1524
1525 return (*read_len = rlen);
1526 }
1527
1528
1529 /* Line buffered write routine.. only dumps whole lines, and only
1530 ** after submitting them to the CTCP police.
1531 */
filtered_write(int to_sock,char * buff,int blen,char * leftover,int * llen,int isclient)1532 static int filtered_write(int to_sock, char *buff, int blen,
1533 char *leftover, int *llen,
1534 int isclient)
1535 {
1536 char *nl, *ol, *lp;
1537 int l,silent;
1538
1539 #ifdef TIRC_DEBUG
1540 debug_msg(DEBUG_TRIVIA, LOG_DEBUG, "Entering filtered_write");
1541 #endif
1542
1543 buff[blen] = '\0'; /* Null terminate buffer for strchr */
1544
1545 /* Break the input into lines, parse each one and send them one at
1546 ** a time to the client.
1547 */
1548 nl = ol = buff;
1549 lp = leftover + *llen;
1550 while ((nl = strchr(ol,'\n')) != NULL)
1551 {
1552 /* nl points to the first '\n' in the input.
1553 ** ol points to the beginning of the unscanned input.
1554 ** lp points to the end of the contents of 'leftover'
1555 ** which is the the fragment of a line we couldn't finish
1556 ** processing last time.
1557 */
1558
1559 nl++; /* Move nl past the '\n' */
1560 l = nl-ol; /* l = the length of this line */
1561 if (l > 1500) l = 1500; /* Arbitrary limits == bad! FIXME!! */
1562 memmove(lp, ol, l); /* Append new line to leftover */
1563 lp[l] = '\0'; /* Null terminate leftover */
1564
1565 /* Okay, now we have a complete line of data in the leftover
1566 ** buffer - scan it for interesting bits, and send it if it
1567 ** isn't deemed completely obscene. :)
1568 */
1569 if ((silent = scan_line(leftover, isclient)) > 0)
1570 {
1571 while (write(to_sock, leftover,
1572 strlen(leftover)) < 0)
1573 if (errno != EINTR)
1574 {
1575 #ifdef TIRC_DEBUG
1576 debug_msg(DEBUG_BASIC, LOG_WARNING,
1577 "write(%s) failed: %.256s",
1578 isclient ? "client" : "server",
1579 strerror(errno));
1580 #endif
1581 close(to_sock);
1582 return 0;
1583 }
1584 }
1585 #ifdef TIRC_DEBUG
1586 else if (silent >= 0)
1587 debug_msg(DEBUG_FEATURES, LOG_DEBUG,
1588 "Squelched: %.256s", leftover);
1589 #endif
1590
1591 /* Maintain loop integrity..
1592 */
1593 ol = nl;
1594 lp = leftover;
1595 }
1596 /* Loop has terminated - if anything is left in ol, then it isn't
1597 ** a complete line we can scan, it's only a fragment.
1598 **
1599 ** .. so we save it for next time, and return 1 for success.
1600 */
1601 *llen = blen + (buff - ol);
1602 memmove(leftover, ol, *llen);
1603
1604 return 1;
1605 }
1606
1607
1608 /* This function scans a single line of data for DCC constructs and other
1609 ** information we need to keep track of. The line is rewritten if necissary.
1610 ** Returns 1 if the line is "okay for writing", 0 if it is to be suppressed,
1611 ** -1 if it is to be suppressed silently.
1612 */
1613 #define CTRL_A ('A'&31)
scan_line(char * line,int isclient)1614 static int scan_line(char *line, int isclient)
1615 {
1616 char *done, *ctcp_begin, *ctcp_end, *p;
1617 char replace[LENGTH_SERVERDATA * 2];
1618
1619 /* Sanity check..
1620 */
1621 if (strlen(line) > LENGTH_SERVERDATA) {
1622 debug_msg(0, LOG_ERR, "Input to scan_line() of illegal length - input not scanned!");
1623 return(1);
1624 }
1625
1626 /* Scan all CTCPs (it IS legal to embed more than one in the same,
1627 ** line, but most clients don't handle this correctly).
1628 */
1629 done = line;
1630 while (((ctcp_begin = strchr(done, CTRL_A)) != NULL) &&
1631 ((ctcp_end = strchr(ctcp_begin + 1, CTRL_A)) != NULL))
1632 {
1633 char ctcp_type[32];
1634
1635 strncpy(ctcp_type, ctcp_begin + 1, sizeof(ctcp_type));
1636 ctcp_type[sizeof(ctcp_type) - 1] = '\0';
1637 if ((p = strchr(ctcp_type, ' ')) != NULL) *p = '\0';
1638
1639 /* It's a CTCP.. but is it DCC?
1640 */
1641 if (!strcasecmp(ctcp_type, "DCC"))
1642 {
1643 /* Okay, it's DCC.. rewrite it!
1644 */
1645 int squelch = 0;
1646 char type[32];
1647 char arg_1[256];
1648 char *rest;
1649 unsigned int arg_2, arg_3, scanned;
1650
1651 *replace = *ctcp_begin = *ctcp_end = '\0'; /* Chop! */
1652 ctcp_begin++;
1653
1654 if (sscanf(ctcp_begin, "%4s %31s %255s %u%u%n",
1655 ctcp_type, type,
1656 arg_1, &arg_2, &arg_3,
1657 &scanned) >= 5)
1658 {
1659 #ifdef TIRC_DEBUG
1660 debug_msg(DEBUG_FEATURES, LOG_DEBUG,
1661 "Caught: %.256s", ctcp_begin);
1662 #endif
1663 rest = ctcp_begin + scanned;
1664
1665 if (!strcasecmp(type, "CHAT"))
1666 {
1667 if (!allow_dcc_chat)
1668 #ifdef DISALLOW_DCC_CHAT
1669 sprintf(replace,
1670 DISALLOW_DCC_CHAT,
1671 type, arg_1);
1672 #else
1673 squelch = 1;
1674 #endif
1675 }
1676 else if (!strcasecmp(type, "SEND") ||
1677 !strcasecmp(type, "TSEND") ||
1678 !strcasecmp(type, "RESEND") ||
1679 !strcasecmp(type, "TRESEND"))
1680 {
1681 if (!allow_dcc_send)
1682 #ifdef DISALLOW_DCC_SEND
1683 sprintf(replace,
1684 DISALLOW_DCC_SEND,
1685 type, arg_1);
1686 #else
1687 squelch = 1;
1688 #endif
1689 else if (!dcc_mangle_filename(arg_1))
1690 #ifdef MANGLE_DCC_SEND
1691 sprintf(replace,
1692 MANGLE_DCC_SEND,
1693 type, arg_1);
1694 #else
1695 squelch = 1;
1696 #endif
1697 }
1698 else if (!strcasecmp(type, "RESUME"))
1699 {
1700 sprintf(replace,
1701 "%cDCC %s %s %d %d%s%c",
1702 CTRL_A,
1703 type, arg_1,
1704 dcc_resume(arg_2, 1),
1705 arg_3, rest, CTRL_A);
1706 }
1707 else if (!strcasecmp(type, "ACCEPT"))
1708 {
1709 sprintf(replace,
1710 "%cDCC %s %s %d %d%s%c",
1711 CTRL_A,
1712 type, arg_1,
1713 dcc_resume(arg_2, 0),
1714 arg_3, rest, CTRL_A);
1715 }
1716 /* Insert new DCC protocols here :-)
1717 */
1718 else if (!allow_dcc_unknown)
1719 #ifdef DISALLOW_DCC_SEND
1720 sprintf(replace,
1721 DISALLOW_DCC_FUNK,
1722 type, arg_1);
1723 #else
1724 squelch = 1;
1725 #endif
1726
1727 if (!*replace && !squelch)
1728 {
1729 /* No replacement has been set, so
1730 ** proxy this connection. :-)
1731 */
1732 sprintf(replace,
1733 "%c%s %s %s %s%s%c",
1734 CTRL_A, ctcp_type,
1735 type, arg_1,
1736 proxy_dcc(arg_2, arg_3, isclient),
1737 rest, CTRL_A);
1738 }
1739 }
1740
1741 /* Alternate (!= DCC) protocols go here.. */
1742
1743 /* Are we changing anything?
1744 */
1745 ctcp_begin--;
1746 if (*replace)
1747 {
1748 #ifdef TIRC_DEBUG
1749 debug_msg(DEBUG_FEATURES, LOG_DEBUG,
1750 "Sent: %.256s", replace);
1751 #endif
1752 done = ctcp_begin + strlen(replace); /* Mark */
1753 strcat(replace, ctcp_end + 1);
1754 strcpy(ctcp_begin, replace); /* Rewrite */
1755 }
1756 else
1757 {
1758 *ctcp_begin = *ctcp_end = CTRL_A; /* Unchop */
1759 done = ctcp_end + 1; /* Mark */
1760
1761 if (squelch)
1762 return(0);
1763 }
1764 } /* is DCC */
1765 else if ((use_anonymity) &&
1766 (isclient) &&
1767 ((!strcasecmp(ctcp_type, "VERSION")) ||
1768 (!strcasecmp(ctcp_type, "FINGER")) ||
1769 (!strcasecmp(ctcp_type, "USERINFO")) ||
1770 (!strcasecmp(ctcp_type, "CLIENTINFO"))) &&
1771 (!strncasecmp(line, "NOTICE", 6)))
1772 {
1773 strcpy(replace, CTCP_NOT_ALLOWED);
1774 done = ctcp_begin + strlen(replace) + 2; /* Mark */
1775 strcat(replace, ctcp_end);
1776 strcpy(ctcp_begin + 1, replace); /* Rewrite */
1777 }
1778 else if (isclient)
1779 {
1780 /* Squelch other outgoing CTCPs containing the
1781 ** client's IP address.
1782 */
1783 if (strstr(ctcp_begin, clients_ip_s) != NULL)
1784 return (0);
1785 done = ctcp_end + 1;
1786 }
1787 else
1788 done = ctcp_end + 1;
1789 }
1790
1791 /* Scan server input for the client's nickname.
1792 */
1793 if (!isclient)
1794 {
1795 char type[128];
1796 char arg[32];
1797 char nuh[512];
1798
1799 if (sscanf(line, ":%511s %127s %31s", nuh, type, arg) == 3)
1800 {
1801 if ((isdigit(*type) ||
1802 (!strcasecmp(type, "PRIVMSG"))) &&
1803 ((*arg != '&') && (*arg != '#') &&
1804 (*arg != '%') &&
1805 (*arg != '!') && (*arg != '*')))
1806 {
1807 #ifdef NICK_LOG
1808 if (use_nick_log &&
1809 strcasecmp(user_nick, arg))
1810 debug_msg(0, LOG_INFO, "Nick: %.256s", arg);
1811 #endif
1812 strncpy(user_nick, arg, sizeof(user_nick));
1813 user_nick[sizeof(user_nick) - 1] = '\0';
1814 }
1815 if ((!motd_is_done) &&
1816 ((!strcasecmp(type,"376")) ||
1817 (!strcasecmp(type,"421"))))
1818 motd_is_done = 1;
1819 }
1820 /* The server shouldn't start PINGing us until well
1821 ** after the end of the MOTD..
1822 */
1823 if ((!motd_is_done) && (!strncasecmp(line,"PING",4)))
1824 motd_is_done = 1;
1825 }
1826 else if (use_anonymity) /* Data is from client, anonymize */
1827 {
1828 if (!strncasecmp(line, "NOTICE", 6))
1829 {
1830 if (strstr(line, clients_ip_s) != NULL)
1831 return (0);
1832 }
1833 else if (!strncasecmp(line, "USER", 4))
1834 {
1835 int cip = ANON_USERID;
1836 sprintf(line,
1837 "USER t%x anon anon :%s\n",
1838 cip, ANON_IRCNAME);
1839 }
1840 }
1841 else if (!strncasecmp(line, "NOTICE", 6)) /* Fix mIRC junk */
1842 {
1843 char *p;
1844 while ((p = strstr(line, clients_ip_s)) != NULL)
1845 {
1846 *p = '\0';
1847 strcpy(replace, p+strlen(clients_ip_s));
1848 strcat(line, visible_ip_o_s);
1849 strcat(line, replace);
1850 }
1851 }
1852
1853 /* Other spying could be done here .. */
1854
1855 #ifdef QUIZ_MODE
1856 if (use_quiz_mode) {
1857 if ((isclient) && (use_quiz_mode <= QUIZ_FLUSH))
1858 {
1859 char cmd[32];
1860 char rest[512], out[512], *r;
1861 int what, retv, fuid;
1862
1863 what = 0;
1864 if (sscanf(line, "%31s %511s", cmd, rest) == 2)
1865 {
1866 if (!strcasecmp(cmd, "NICK")) what = 1;
1867 else if (!strcasecmp(cmd, "USER")) what = 2;
1868 else if (!strcasecmp(cmd, "PASS")) what = 3;
1869 else if (!strcasecmp(cmd, "PRIVMSG")) what = 4;
1870 else if (!strncasecmp(line, server_tag, 6))
1871 what = 2;
1872
1873 r = line+strlen(cmd)+1;
1874 if (*r == ':') r++;
1875 strncpy(rest, r, sizeof(rest)-1);
1876 rest[511] = '\0' ;
1877 if ((r = strchr(rest,'\n')) != NULL) *r = '\0';
1878 }
1879 else if (!strncasecmp(line, server_tag, 6)) what = 2;
1880
1881 r = rest;
1882 retv = -1;
1883 switch (what)
1884 {
1885 /* Users get fake nicks until after
1886 ** authentication (anti-nick-kill).
1887 */
1888 case 1: quiz_delay_line(line, QUIZ_S);
1889 fuid = getpid() * visible_ip_o;
1890 sprintf(user_nick, "}%x", fuid);
1891 sprintf(line, "NICK :%s\n", user_nick);
1892 sprintf(out, ":%.32s %.256s", r, line);
1893 quiz_delay_line(out, QUIZ_C);
1894 quiz_greet();
1895 retv = 1;
1896 break;
1897
1898 /* Allow the USER command.
1899 */
1900 case 2: retv = 1;
1901 strcat(line,"#PiNG#\n");
1902 break;
1903
1904 /* Check the users' responses.
1905 */
1906 case 4: if ((r = strchr(rest,' ')) != NULL)
1907 {
1908 *r++ = '\0';
1909 if (*r == ':') r++;
1910 }
1911 if (strcasecmp(rest, QUIZ_NICK))
1912 {
1913 quiz_delay_line(line, QUIZ_S);
1914 break;
1915 }
1916 case 3: quiz_check_auth(r);
1917 break;
1918 default: quiz_delay_line(line, QUIZ_S);
1919 break;
1920 }
1921
1922 return(retv);
1923 }
1924 }
1925 #endif
1926 return(1);
1927 }
1928
1929
1930 /* Mangle the given filename. Returns 1 if the filename
1931 ** is okay, 0 if not.
1932 */
dcc_mangle_filename(char * filename)1933 static int dcc_mangle_filename(char *filename)
1934 {
1935 struct dcc_mangle_struct *dmp;
1936
1937 /* Check the compiled-in rules first:
1938 */
1939 dmp = dcc_mangle;
1940 while (use_dcc_mangling &&
1941 (dmp->offered != NULL))
1942 {
1943 if (!strcasecmp(filename, dmp->offered))
1944 {
1945 if (dmp->replace != NULL)
1946 strcpy(filename, dmp->replace);
1947 else
1948 return(0);
1949 }
1950 dmp++;
1951 }
1952
1953 #ifdef TCP_WRAPPERS
1954 /* Check if the offered file is on the
1955 ** local blacklist.
1956 */
1957 if (use_tcp_wrappers)
1958 {
1959 if (!hosts_ctl("tircproxy_dcc_files",
1960 "", "", filename))
1961 return(0);
1962 }
1963 #endif
1964 return(1);
1965 }
1966
1967
1968 /* Looks up valid port numbers for proxying DCC RESUME requests.
1969 ** Set resume to 0 on "DCC RESUME", 1 on "DCC ACCEPT".
1970 */
dcc_resume(int destport,int resume)1971 static int dcc_resume(int destport, int resume)
1972 {
1973 int i;
1974
1975 for (i = 0; i < MAX_DCC_SESSIONS; i++)
1976 {
1977 if ((resume) && (dcc_proxied_port[i] == destport))
1978 {
1979 return(dcc_original_port[i]);
1980 }
1981 else if ((!resume) && (dcc_original_port[i] == destport))
1982 {
1983 return(dcc_proxied_port[i]);
1984 }
1985 }
1986 return (0);
1987 }
1988
1989
1990 /* This prepares to proxy a DCC session. Ut returns a pointer
1991 ** to a string containing the "<ip> <port>" reply to send to the
1992 ** client.
1993 */
proxy_dcc(int destaddr,int destport,int incoming)1994 static char *proxy_dcc(int destaddr, int destport, int incoming)
1995 {
1996 static char retvalue[128];
1997 int listen_sock;
1998 int sock;
1999 ipaddr_t vip;
2000 struct sockaddr_in addr;
2001 struct sockaddr_in to_addr;
2002 int len;
2003
2004 /* Mangle DCC offers below port 1024.
2005 */
2006 if (destport < 1024)
2007 {
2008 strcpy(retvalue,"junk junk");
2009 return retvalue;
2010 }
2011
2012 #ifdef MIRC_DCC_KLUDGE
2013 if (incoming && use_mirc_dcc_kludge) destaddr = ntohl(clients_ip);
2014 #endif
2015
2016 #ifdef TCP_WRAPPERS
2017 if (use_tcp_wrappers)
2018 {
2019 char host_ip[64], host_name[64];
2020 struct sockaddr_in addr;
2021 int okay = 1;
2022
2023 /* Lookup an ASCII representation of the host's IP address,
2024 ** and attempt to look up it's FQDN as well (DNS).
2025 */
2026 addr.sin_addr.s_addr = htonl(destaddr);
2027 lookup_hostname(&addr, host_ip, sizeof(host_ip), 0);
2028 lookup_hostname(&addr, host_name, sizeof(host_name), 1);
2029
2030 /* Check if the calling host is allowed to initiate DCC.
2031 */
2032 if (!hosts_ctl((incoming) ? "tircproxy_dcc_out" :
2033 "tircproxy_dcc_in",
2034 host_name, host_ip,
2035 (incoming) ? "" : user_name))
2036 {
2037 okay = 0;
2038 }
2039
2040 if (clients_ip != htonl(destaddr))
2041 {
2042 addr.sin_addr.s_addr = clients_ip;
2043 lookup_hostname(&addr, host_ip, sizeof(host_ip), 0);
2044 lookup_hostname(&addr, host_name, sizeof(host_name), 1);
2045
2046 /* Check if the client is allowed to use DCC.
2047 */
2048 if (!hosts_ctl("tircproxy_dcc_in",
2049 host_name, host_ip,
2050 user_name))
2051 {
2052 okay = 0;
2053 }
2054 }
2055
2056 if (!okay)
2057 {
2058 debug_msg(0, LOG_INFO,
2059 "Dropped illegal DCC from: %.128s (client %.32s@%.96s)",
2060 host_ip, user_name,
2061 inet_ntoa(addr.sin_addr));
2062 strcpy(retvalue,"junk junk");
2063 return(retvalue);
2064 }
2065 }
2066 #endif
2067
2068 /* Choose a DCC port at random, to make hijacking harder.
2069 ** (re: BUGTRAQ, 1998, December 22 & 23)
2070 */
2071 len = 10;
2072 while ((listen_sock = bind_to_port((incoming) ? visible_ip_o : visible_ip_i,
2073 ((rand() + getpid()) % PPOOL) + 1025,
2074 1, DEBUG_TRIVIA)) < 0)
2075 {
2076 if (--len < 1) {
2077 debug_msg(0, LOG_ERR, "Failed to bind to port, dropping DCC!");
2078
2079 strcpy(retvalue, "ack, pthpht!");
2080 return(retvalue);
2081 }
2082 }
2083
2084 /* call cleanup func on SIGCHLD
2085 */
2086 signal(SIGCHLD, chld_signal);
2087
2088 if (fork())
2089 {
2090 int i,n;
2091
2092 len = sizeof(to_addr);
2093 if (getsockname(listen_sock, (struct sockaddr *)&to_addr, &len) < 0)
2094 {
2095 debug_msg(0, LOG_ERR, "getsockname(): %.256s", strerror(errno));
2096 *retvalue = '\0';
2097 return(retvalue);
2098 }
2099 /* Close the socket as the child does the handling.
2100 */
2101 close(listen_sock);
2102
2103 vip = to_addr.sin_addr.s_addr;
2104
2105 /* Record the port info for this connection.
2106 */
2107 for (n = i = 0; i < MAX_DCC_SESSIONS; i++)
2108 if (dcc_session_time[i] < dcc_session_time[n]) n = i;
2109
2110 dcc_session_time[n] = time(NULL);
2111 dcc_original_port[n] = destport;
2112 dcc_proxied_port[n] = ntohs(to_addr.sin_port);
2113
2114 #ifdef HAVE_LINUX
2115 sprintf(retvalue,"%lu %u",
2116 (unsigned long int) ntohl(vip), ntohs(to_addr.sin_port));
2117 #else
2118 sprintf(retvalue,"%u %u",
2119 (unsigned int) ntohl(vip), ntohs(to_addr.sin_port));
2120 #endif
2121 return(retvalue);
2122 }
2123
2124 /* Give people five minutes to accept the call..
2125 */
2126 signal(SIGALRM, alarm_signal);
2127 alarm(5*MINUTE);
2128 strcpy(alarm_in,"proxy_dcc: accept");
2129
2130 /* No silly broadcasts shall mess up our DCC stuff!
2131 */
2132 signal(SIGHUP, SIG_IGN);
2133
2134 /* Accept an incoming connection.
2135 */
2136 len = sizeof(addr);
2137 if ((sock = accept(listen_sock, (struct sockaddr *)&addr, &len)) < 0)
2138 {
2139 /* Connection resets are common enough to log them as debug only.
2140 */
2141 debug_msg(0, (errno == ECONNRESET ? LOG_DEBUG : LOG_ERR), "accept(): %.256s", strerror(errno));
2142 exit (0);
2143 }
2144 close(listen_sock);
2145
2146 /* Ok, here we go!
2147 */
2148 memset(&to_addr, '\0', sizeof(to_addr));
2149 to_addr.sin_family = AF_INET;
2150 to_addr.sin_port = htons(destport);
2151 to_addr.sin_addr.s_addr = htonl(destaddr);
2152
2153 /* Make sure at least *one* end of the connection
2154 ** is the original client.
2155 */
2156 if ((to_addr.sin_addr.s_addr != clients_ip) &&
2157 (addr.sin_addr.s_addr != clients_ip))
2158 {
2159 debug_msg(0, LOG_WARNING, "Abuse: illegal DCC request %.128s <-> %.128s !",
2160 inet_ntoa(to_addr.sin_addr),
2161 inet_ntoa(addr.sin_addr));
2162 exit(0);
2163 }
2164
2165 debug_msg(0, LOG_DEBUG,
2166 "Copied %d bytes, exiting (DCC).",
2167 copy_loop(sock, &addr, &to_addr, 0));
2168
2169 #ifdef CDIR_IDENT
2170 if (use_cdir)
2171 cleanup_identd();
2172 #endif
2173 close(sock);
2174 closelog();
2175 exit(0);
2176 }
2177
2178
2179 /* Read username from disk or shared memory, if possible.
2180 */
get_user_name(struct sockaddr_in * addr)2181 static void get_user_name(struct sockaddr_in *addr)
2182 {
2183 int tries = 0;
2184 #ifdef USE_UDB
2185 struct udb_ip_user buf;
2186
2187 /* People neither using the CDIR stuff nor running as root probably
2188 * couldn't care less about ident problems.
2189 */
2190 if (!use_cdir && getuid()) tries = 10;
2191
2192 /* Be stubborn, to decrease the chance of race conditions.
2193 */
2194 while (!udb_ip_get(&(addr->sin_addr), &buf))
2195 {
2196 if (tries > 3)
2197 {
2198 debug_msg(0, LOG_WARNING,
2199 "Address not in UDB table, ident response will be wrong!");
2200 return;
2201 }
2202 else
2203 {
2204 tries++;
2205 sleep(1);
2206 }
2207 }
2208
2209 #ifdef TIRC_DEBUG
2210 debug_msg(DEBUG_TRIVIA, LOG_DEBUG, "Got username: %.256s", buf.username);
2211 #endif
2212
2213 strncpy(user_name, buf.username, MAXLOGNAME);
2214 user_name[MAXLOGNAME-1] = '\0';
2215 return;
2216
2217 #endif /* USE_UDB */
2218 #ifdef IP_TO_UID_PREFIX /* not USE_UDB */
2219 int fd;
2220 char ipfile[PATH_MAX];
2221 char *cp;
2222
2223 /* People neither using the CDIR stuff nor running as root probably
2224 * couldn't care less about ident problems.
2225 */
2226 #ifdef CDIR_IDENT
2227 if (!use_cdir && getuid()) tries = 10;
2228 #endif
2229
2230 /* FIXME: dangerous sprintfs */
2231 #ifdef CDIR
2232 if (use_cdir)
2233 # ifdef HAVE_SNPRINTF
2234 snprintf(ipfile, sizeof(ipfile),
2235 # else
2236 sprintf(ipfile,
2237 # endif
2238 "%s%s-%s", CDIR, CDIR_MAP,
2239 inet_ntoa(addr->sin_addr));
2240 else
2241 #endif
2242 # ifdef HAVE_SNPRINTF
2243 snprintf(ipfile, sizeof(ipfile),
2244 # else
2245 sprintf(ipfile,
2246 # endif
2247 "%s%s", IP_TO_UID_PREFIX,
2248 inet_ntoa(addr->sin_addr));
2249
2250 /* Repeat until we lose the ident race.. :-)
2251 */
2252 while ((fd = open(ipfile,O_RDONLY)) == -1)
2253 {
2254 if (tries > 5) {
2255 debug_msg(0, LOG_WARNING,
2256 "No %.256s file found, ident response will be wrong!",
2257 ipfile);
2258 return;
2259 }
2260 else
2261 {
2262 sleep(1);
2263 }
2264 tries++;
2265 }
2266
2267 user_name[0] = user_name[MAXLOGNAME-1] = '\0';
2268 read(fd, user_name, MAXLOGNAME-1);
2269 close(fd);
2270
2271 if ((cp = strchr(user_name,'\n'))) *cp = '\0';
2272 return;
2273
2274 #endif /* IP_TO_UID_PREFIX */
2275 }
2276
2277 /* Change uid & gid!
2278 */
change_uid(void)2279 static void change_uid(void)
2280 {
2281 #if (defined IP_TO_UID_PREFIX || defined USE_UDB)
2282 struct passwd *pw;
2283
2284 /* We aren't running as root, so there's nothing more we can do..
2285 */
2286 if (getuid()) return;
2287
2288 if ((pw = getpwnam(user_name)) == NULL)
2289 {
2290 debug_msg(0, LOG_WARNING,
2291 "Invalid user: %.32s, didn't changed UID/GID.",
2292 user_name);
2293 # ifdef PARANOID
2294 if (use_paranoid) exit(0);
2295 # endif
2296 return;
2297 }
2298
2299 /* Change ids..
2300 */
2301 setgid(pw->pw_gid);
2302 setuid(pw->pw_uid);
2303
2304 /* Start a new session and group.
2305 */
2306 setsid();
2307 # ifdef HAVE_LINUX
2308 setpgrp();
2309 # endif
2310 #endif /* IP_TO_UID_PREFIX */
2311 return;
2312 }
2313
2314
2315 /* Tell the ident server which user this connection really belongs to.
2316 */
2317 #ifdef CDIR
tell_identd(struct sockaddr_in * us,struct sockaddr_in * them)2318 static void tell_identd(struct sockaddr_in *us, struct sockaddr_in *them)
2319 {
2320 char fakeid[64], *u;
2321 # ifndef USE_UDB
2322 int fd;
2323 *user_ident_file = '\0';
2324
2325 sprintf(user_ident_file,
2326 "%s%s:%d-%s:%d", CDIR, CDIR_IDENT,
2327 ntohs(us->sin_port),
2328 inet_ntoa(them->sin_addr),
2329 ntohs(them->sin_port));
2330
2331 if ((fd = creat(user_ident_file, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1)
2332 {
2333 debug_msg(0, LOG_WARNING,
2334 "Unable to create %s, ident response will be wrong!",
2335 user_ident_file);
2336 *user_ident_file = '\0';
2337 return;
2338 }
2339 # endif
2340
2341 if ((use_anonymity) || (!*user_name))
2342 {
2343 int cip = ANON_USERID;
2344
2345 sprintf(fakeid, "t%x", cip);
2346 debug_msg(0, LOG_INFO, "Anonymized connection as %s", fakeid);
2347
2348 u = fakeid;
2349 }
2350 else
2351 u = user_name;
2352
2353 # ifdef USE_UDB
2354 memset(&conn, 0, sizeof(conn));
2355 conn.from.sin_family = us->sin_family;
2356 conn.from.sin_addr = us->sin_addr;
2357 conn.from.sin_port = us->sin_port;
2358 conn.to.sin_family = them->sin_family;
2359 conn.to.sin_addr = them->sin_addr;
2360 conn.to.sin_port = them->sin_port;
2361
2362 udb_conn_record(&conn, u, "", UDB_OVERWRITE_LRU, UDB_NOW);
2363
2364 # else
2365 if (write(fd, u, strlen(u)) < 0)
2366 debug_msg(0, LOG_WARNING,
2367 "Unable to write to %s, ident response will be wrong!",
2368 user_ident_file);
2369
2370 close(fd);
2371 # endif
2372 }
2373
2374 /* Cleanup ..
2375 */
cleanup_identd(void)2376 static void cleanup_identd(void)
2377 {
2378 # ifdef USE_UDB
2379 udb_conn_delete(&conn);
2380 # else
2381 if (*user_ident_file)
2382 unlink(user_ident_file);
2383 # endif
2384 }
2385 #endif /* CDIR */
2386
2387
2388 /* Broadcast a message from sysadmin to proxy user.. It's the
2389 ** sysadmin's problem to format the file so the client will understand
2390 ** the message!
2391 */
broadcast(int sock,const char * filename)2392 static void broadcast(int sock, const char *filename)
2393 {
2394 int fd,i;
2395 char buff[2048], *p, *np;
2396
2397 #ifdef HAVE_LINUX
2398 /* man signal:
2399 **
2400 ** Unlike BSD systems, signals under Linux are reset to their
2401 ** default values when raised.
2402 */
2403 signal(SIGHUP, hup_signal);
2404 #endif
2405 broadcast_flag = 0;
2406
2407 if ((fd = open(filename,O_RDONLY)) == -1) return;
2408 debug_msg(0, LOG_DEBUG, "Sending broadcast from: %.256s",filename);
2409
2410 while ((i = read(fd, buff, 2047)) > 0)
2411 {
2412 buff[2047] = '\0';
2413 np = p = buff;
2414
2415 while ((np = strstr(p, "$N$")) != NULL)
2416 {
2417 if (write(sock, p, np-p) < 0)
2418 debug_msg(0, LOG_WARNING, "Error writing to socket!");
2419 p = np+3;
2420 write(sock, user_nick, strlen(user_nick));
2421 }
2422 if (write(sock, p, (buff+i)-p) < 0)
2423 debug_msg(0, LOG_WARNING, "Error writing to socket!");
2424 }
2425 close(fd);
2426 }
2427
2428
2429 /* Catch alarm signals and exit.
2430 */
alarm_signal(int sig)2431 static void alarm_signal(int sig)
2432 {
2433 debug_msg(0, LOG_DEBUG, "Timeout in %.256s, exiting.", alarm_in);
2434 #ifdef CDIR_IDENT
2435 if (use_cdir)
2436 cleanup_identd();
2437 #endif
2438 exit(1);
2439 }
2440
2441
2442 /* Catch HUP signals and set broadcast flag.
2443 */
hup_signal(int sig)2444 static void hup_signal(int sig)
2445 {
2446 debug_msg(0, LOG_DEBUG, "HUP signal caught - broadcasting!");
2447 broadcast_flag = 1;
2448 }
2449
2450
2451 /* SIGCHLD handler (reap zombies)
2452 */
chld_signal(sig)2453 static void chld_signal (sig)
2454 {
2455 int status;
2456 while (waitpid(-1,&status,WNOHANG) > 0);
2457 #ifdef HAVE_LINUX
2458
2459 /* Reset the signal handler.
2460 */
2461 signal(SIGCHLD,chld_signal);
2462 #endif
2463 }
2464
2465 /* Debug message handler
2466 */
debug_msg(int lev,int pri,const char * format,...)2467 static void debug_msg(int lev, int pri, const char *format, ...) {
2468 va_list ap;
2469 char msg[512];
2470
2471 if (lev > debug_level) return;
2472
2473 va_start(ap,format);
2474 #if HAVE_VSNPRINTF
2475 vsnprintf(msg, 511, format, ap);
2476 #else
2477 # if HAVE_VPRINTF
2478 # warning Using vsprintf instead of vsnprintf!
2479 vsprintf(msg, format, ap);
2480 # else
2481 # error I need vsprintf or vsnprintf!
2482 # endif
2483 #endif
2484
2485 if ((use_syslog) && (debug_level < DEBUG_NOFORK))
2486 syslog(pri, "%s", msg);
2487 else fprintf(stderr,"[%d]\t%s\n", getpid(), msg);
2488
2489 va_end(ap);
2490 }
2491
2492 /* ************************************************************************* */
2493
2494 #ifdef QUIZ_MODE
2495
2496 # define QSTR(b) (b+sizeof(char *))
2497 # define QPTR(b) *((char **) b)
2498
2499 /* Save a line that was destined for output for later..
2500 */
2501 int quiz_delayed = 0;
quiz_delay_line(char * line,char ** first,char *** bl)2502 static void quiz_delay_line(char *line, char **first, char ***bl)
2503 {
2504 char *buf;
2505 int linelen;
2506
2507 quiz_delayed += linelen = strlen(line);
2508
2509 if (quiz_delayed > QUIZ_MEMORY_HOG) exit(1);
2510
2511 if (*bl == NULL) *bl = first;
2512
2513 **bl = buf = malloc(sizeof(char *)+linelen+1);
2514 strcpy(QSTR(buf), line);
2515
2516 QPTR(buf) = NULL;
2517 *bl = &QPTR(buf);
2518
2519 #ifdef TIRC_DEBUG
2520 debug_msg(DEBUG_TRIVIA, LOG_DEBUG, "Buffered: %.256s", line);
2521 #endif
2522 }
2523
2524 /* Print a line that was destined for output for later..
2525 */
quiz_dump_lines(int sock,char ** first,char *** bl)2526 static void quiz_dump_lines(int sock, char **first, char ***bl)
2527 {
2528 char *p;
2529
2530 if (*first == NULL) return;
2531
2532 do {
2533 while (write(sock, QSTR(*first),
2534 strlen(QSTR(*first))) < 0)
2535 if (errno != EINTR)
2536 {
2537 #ifdef TIRC_DEBUG
2538 debug_msg(DEBUG_BASIC, LOG_WARNING,
2539 "write(%s) failed in quiz_dump_lines: %.128s",
2540 strerror(errno));
2541 #endif
2542 return;
2543 }
2544 #ifdef TIRC_DEBUG
2545 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,
2546 "Flushed: %.256s", QSTR(*first));
2547 #endif
2548 p = QPTR(*first);
2549 free(*first);
2550 *first = p;
2551 } while (*first != NULL);
2552
2553 *bl = first;
2554 }
2555
2556 /* Check the username%password supplied by the user.
2557 */
2558 int quiz_passwd_checks = 0;
quiz_check_auth(char * pass)2559 static void quiz_check_auth(char *pass)
2560 {
2561 if (quiz_passwd_checks++ > 3) exit(1);
2562
2563 if (use_unix_passwd)
2564 {
2565 char *u, *p, *n, salt[4];
2566 struct passwd *pw;
2567
2568 if (((p = strchr(pass,'%')) != NULL) ||
2569 ((p = strchr(pass,' ')) != NULL))
2570 {
2571 u = pass;
2572 *p++ = '\0';
2573 }
2574 else if (*user_name)
2575 {
2576 u = user_name;
2577 p = pass;
2578 }
2579 else
2580 {
2581 quiz_msg(QUIZ_PASSWD_BAD);
2582 return;
2583 }
2584
2585 if ((n = strchr(p,'\n')) != NULL) *n = '\0';
2586
2587 if ((pw = getpwnam(u)) != NULL)
2588 {
2589 salt[0] = (pw->pw_passwd)[0];
2590 salt[1] = (pw->pw_passwd)[1];
2591 salt[2] = '\0';
2592 if (!strcmp(pw->pw_passwd, crypt(p,salt)))
2593 {
2594 quiz_msg(QUIZ_PASSWD_OK);
2595 use_quiz_mode = QUIZ_FLUSH;
2596 bzero(p,strlen(p));
2597 return;
2598 }
2599 }
2600
2601 #ifdef TIRC_DEBUG
2602 debug_msg(DEBUG_FEATURES, LOG_AUTH,
2603 "Incorrect password given for %s", u);
2604 #endif
2605 bzero(p,strlen(p));
2606 sleep(quiz_passwd_checks*2);
2607 quiz_msg(QUIZ_PASSWD_BAD);
2608 }
2609 else /* use_unix_passwd */
2610 {
2611 char *b, *p, buf[512], ok;
2612
2613 strcpy(buf,quiz);
2614 b = p = buf;
2615 ok = 0;
2616
2617 while ((p = strchr(p,':')) != NULL)
2618 {
2619 *p++ = '\0';
2620 if (!strcasecmp(pass,b)) ok = 1;
2621 b = p;
2622 }
2623 if (!strcasecmp(pass,b)) ok = 1;
2624
2625 if (ok)
2626 {
2627 quiz_msg(QUIZ_PASSWD_OK);
2628 use_quiz_mode = QUIZ_FLUSH;
2629 }
2630 else
2631 {
2632 #ifdef TIRC_DEBUG
2633 debug_msg(DEBUG_TRIVIA, LOG_DEBUG,
2634 "Incorrect quiz response: %s", pass);
2635 #endif
2636 quiz_msg(QUIZ_ANSWER_BAD);
2637 }
2638
2639 } /* else */
2640 }
2641
2642 /* Send the user a message..
2643 */
quiz_msg(char * message)2644 static void quiz_msg(char *message)
2645 {
2646 char out[512];
2647
2648 sprintf(out,":%.32s!irc@proxy PRIVMSG %.32s :%.256s\n",
2649 QUIZ_NICK, user_nick, message);
2650
2651 quiz_delay_line(out, QUIZ_C);
2652 }
2653
2654 /* Greet the user when he connects..
2655 */
quiz_greet(void)2656 static void quiz_greet(void)
2657 {
2658 FILE *fd;
2659 int i, r;
2660 char question[512], buff[512], *p;
2661
2662 if (use_unix_passwd)
2663 {
2664 quiz_msg(QUIZ_PASSWD_WAIT);
2665 return;
2666 }
2667
2668 /* Not using /etc/passwd, select a question from the quizfile */
2669
2670 srand(time((time_t) NULL));
2671
2672 if ((fd = fopen(quizfile,"r")) == NULL)
2673 {
2674 debug_msg(0, LOG_DEBUG,
2675 "Error (%.128s) reading quiz-file: %.128s",
2676 strerror(errno), quizfile);
2677 quiz_msg("Error opening quiz file. Notify the proxy administrator.");
2678 return;
2679 }
2680
2681 r = 0;
2682 while (fgets(buff, 512, fd) != NULL)
2683 if (*buff == '!')
2684 quiz_msg(buff+1);
2685 else
2686 if (*buff != '#')
2687 {
2688 i = rand();
2689 if ((i > r) || (!r))
2690 {
2691 r = i;
2692 strcpy(question,buff);
2693 }
2694 }
2695
2696 fclose(fd);
2697
2698 if ((p = strchr(question, ':')) != NULL)
2699 {
2700 *p++ = '\0';
2701 quiz_msg(question);
2702 strcpy(quiz,p);
2703 if ((p = strchr(quiz, '\n')) != NULL) *p = '\0';
2704 }
2705 else
2706 {
2707 debug_msg(0, LOG_DEBUG, "Invalid quiz: %.256s", question);
2708 quiz_msg("Invalid quiz in file. Notify the proxy administrator.");
2709 }
2710 }
2711 #endif
2712
2713
2714
2715