1 /* Open DC Hub - A Linux/Unix version of the Direct Connect hub.
2 * Copyright (C) 2002,2003 Jonatan Nilsson
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <netdb.h>
29 #if HAVE_MALLOC_H
30 # include <malloc.h>
31 #endif
32 #include <string.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #if HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
39 #if HAVE_FCNTL_H
40 # include <fcntl.h>
41 #endif
42 #include <signal.h>
43 #include <sys/un.h>
44 #include <errno.h>
45 #ifdef HAVE_CRYPT_H
46 # include <crypt.h>
47 #endif
48 #if TIME_WITH_SYS_TIME
49 # include <sys/time.h>
50 # include <time.h>
51 #else
52 # if HAVE_SYS_TIME_H
53 # include <sys/time.h>
54 # else
55 # include <time.h>
56 # endif
57 #endif
58 #ifdef HAVE_SYSLOG_H
59 # include <syslog.h>
60 #endif
61 #ifdef SWITCH_USER
62 # include <sys/capability.h>
63 # include <sys/prctl.h>
64 # include <pwd.h>
65 # include <grp.h>
66 #endif
67 #include <sys/shm.h>
68 #include <sys/sem.h>
69 #include <sys/ipc.h>
70
71 #include "main.h"
72 #include "network.h"
73 #include "commands.h"
74 #include "utils.h"
75 #include "fileio.h"
76 #include "userlist.h"
77 #ifdef HAVE_PERL
78 # include "perl_utils.h"
79 #endif
80
81 #ifndef SIGCHLD
82 # define SIGCHLD SIGCLD
83 #endif
84
85 /* Set default variables, used if config does not exist or is bad */
set_default_vars(void)86 int set_default_vars(void)
87 {
88 users_per_fork = 1000;
89 min_share = 0;
90 min_upload_slots = 0;
91 max_users = 1000;
92 hublist_upload = 1;
93 registered_only = 0;
94 ban_overrides_allow = 0;
95 check_key = 0;
96 reverse_dns = 0;
97 redirect_host[0] = '\0';
98 admin_port = 0xD1C0; /* Easy to remember :) */
99 admin_localhost = 0;
100 searchcheck_exclude_internal = 1;
101 searchcheck_exclude_all = 0;
102 kick_bantime = 5;
103 searchspam_time = 5;
104 max_email_len = 50;
105 max_desc_len = 100;
106 crypt_enable = 1;
107 printf("Enter port number to listen for connections. \nPorts below 1024 is only for root: ");
108 scanf("%u", &listening_port);
109 if(listening_port == 0)
110 {
111 printf("Bad port number\n");
112 exit(EXIT_FAILURE);
113 }
114 printf("Listening Port set to %u\n\n", listening_port);
115 sprintf(public_hub_host, "vandel405.dynip.com");
116 min_version[0] = '\0';
117 sprintf(hub_name, "Open DC Hub");
118 sprintf(hub_description, "A Unix/Linux Direct Connect Hub");
119 if((hub_full_mess = realloc(hub_full_mess, sizeof(char) * 50)) == NULL)
120 {
121 logprintf(1, "Error - In set_default_vars()/realloc(): ");
122 logerror(1, errno);
123 quit = 1;
124 return 0;
125 }
126 sprintf(hub_full_mess, "Sorry, this hub is full at the moment");
127 sprintf(default_pass, "");
128 printf("Please, supply an admin pass for hub: ");
129 scanf("%50s", admin_pass);
130 printf("Your admin pass is set to %s\n\n", admin_pass);
131 printf("Please, supply a password for hub linking: ");
132 scanf("%50s", link_pass);
133 printf("Your Hub linking pass is set to %s\n\n", link_pass);
134 return 1;
135 }
136
137 /* When all users have left a forked process, that process should be terminated */
kill_forked_process(void)138 void kill_forked_process(void)
139 {
140 int erret;
141
142 set_listening_pid(0);
143
144 remove_all(0xFFFF, 1, 1);
145
146 if(listening_socket != -1)
147 {
148 while(((erret = close(listening_socket)) != 0) && (errno == EINTR))
149 logprintf(1, "Error - In kill_forked_process()/close(): Interrupted system call. Trying again.\n");
150
151 if(erret != 0)
152 {
153 logprintf(1, "Error - In kill_forked_process()/close(): ");
154 logerror(1, errno);
155 }
156 }
157
158 if(admin_listening_socket != -1)
159 {
160 while(((erret = close(admin_listening_socket)) != 0) && (errno == EINTR))
161 logprintf(1, "Error - In kill_forked_process()/close(): Interrupted system call. Trying again.\n");
162
163 if(erret != 0)
164 {
165 logprintf(1, "Error - In kill_forked_process()/close(): ");
166 logerror(1, errno);
167 }
168 }
169
170 exit(EXIT_SUCCESS);
171 }
172
173
174 /* Accept connection from newly created forked process */
new_forked_process(void)175 void new_forked_process(void)
176 {
177 struct user_t *user;
178 struct sockaddr_un remote_addr;
179 int len, flags;
180
181 memset(&remote_addr, 0, sizeof(struct sockaddr_un));
182 /* Allocate space for the new user */
183 if((user = malloc(sizeof(struct user_t))) == NULL)
184 {
185 logprintf(1, "Error - In new_forked_process()/malloc(): ");
186 logerror(1, errno);
187 quit = 1;
188 return;
189 }
190
191 /* Get a new socket for the connected user */
192 len = sizeof(struct sockaddr_un);
193 while(((user->sock = accept(listening_unx_socket,
194 (struct sockaddr *)&remote_addr, &len)) < 0)
195 && (errno == EINTR))
196 logprintf(1, "Error - In new_forked_process()/accept(): Interrupted system call. Trying again.\n");
197
198 if(user->sock < 0)
199 {
200 logprintf(1, "Error - In new_forked_process()/accept(): ");
201 logerror(1, errno);
202 free(user);
203 return;
204 }
205
206 if((flags = fcntl(user->sock, F_GETFL, 0)) < 0)
207 {
208 logprintf(1, "Error - In new_forked_process()/in fcntl(): ");
209 logerror(1, errno);
210 close(user->sock);
211 free(user);
212 return;
213 }
214
215 /* Non blocking mode */
216 if(fcntl(user->sock, F_SETFL, flags | O_NONBLOCK) < 0)
217 {
218 logprintf(1, "Error - In new_forked_process()/in fcntl(): ");
219 logerror(1, errno);
220 close(user->sock);
221 free(user);
222 return;
223 }
224
225
226 user->type = FORKED;
227 user->rem = 0;
228 user->buf = NULL;
229 user->outbuf = NULL;
230 sprintf(user->hostname, "forked_process");
231 memset(user->nick, 0, MAX_NICK_LEN+1);
232
233 /* Add the user at the first place in the list. */
234 add_non_human_to_list(user);
235
236 logprintf(5, "Got new unix connection on sock %d\n", user->sock);
237 }
238
239
240 /* Create a new process */
fork_process(void)241 void fork_process(void)
242 {
243 int sock;
244 int len;
245 int erret;
246 struct sockaddr_un remote_addr;
247 struct user_t *user;
248 int flags;
249
250 memset(&remote_addr, 0, sizeof(struct sockaddr_un));
251 if((pid = fork()) == -1)
252 {
253 logprintf(1, "Fork failed, exiting process\n");
254 logerror(1, errno);
255 quit = 1;
256 return;
257 }
258
259 /* If we are the parent */
260 if(pid > 0)
261 {
262 /* All users are removed from the parent */
263 remove_all(UNKEYED | NON_LOGGED | REGULAR | REGISTERED | OP
264 | OP_ADMIN, 1, 1);
265 logprintf(5, "Forked new process, childs pid is %d and parents pid is %d\n", pid, getpid());
266 /* And set current pid of process */
267 pid = getpid();
268 }
269
270 /* And if we are the child */
271 else
272 {
273 /* Close the listening sockets */
274 while(((erret = close(listening_unx_socket)) != 0) && (errno == EINTR))
275 logprintf(1, "Error - In fork_process()/close(): Interrupted system call. Trying again.\n");
276
277 if(erret != 0)
278 {
279 logprintf(1, "Error - In fork_process()/close(): ");
280 logerror(1, errno);
281 }
282
283 while(((erret = close(listening_udp_socket)) != 0) && (errno == EINTR))
284 logprintf(1, "Error - In fork_process()/close(): Interrupted system call. Trying again.\n");
285
286 if(erret != 0)
287 {
288 logprintf(1, "Error - In fork_process()/close(): ");
289 logerror(1, errno);
290 }
291
292 /* Set the alarm */
293 alarm(ALARM_TIME);
294
295 /* And remove all connections to forked process. We only want
296 * connections between parent and child, not between children. Also
297 * remove connections to other hubs, we let the parent take care of
298 * those.*/
299 remove_all(SCRIPT | LINKED | FORKED, 0, 0);
300
301 /* If some other process already has opened the socket, we'll exit. */
302 if(set_listening_pid((int)getpid()) <= 0)
303 exit(EXIT_SUCCESS);
304
305 /* Open the human listening sockets. */
306 if((listening_socket = get_listening_socket(listening_port, 0)) == -1)
307 {
308 logprintf(1, "Error - In fork_process(): Couldn't open listening socket\n");
309 quit = 1;
310 }
311
312 if((admin_listening_socket = get_listening_socket(admin_port, admin_localhost)) == -1)
313 {
314 logprintf(1, "Admin listening socket disabled\n");
315 }
316
317 /* And connect to parent process */
318 if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
319 {
320 logprintf(1, "Error - In fork_process()/socket(): ");
321 logerror(1, errno);
322 quit = 1;
323 return;
324 }
325
326 remote_addr.sun_family = AF_UNIX;
327 strcpy(remote_addr.sun_path, un_sock_path);
328 len = strlen(remote_addr.sun_path) + sizeof(remote_addr.sun_family) + 1;
329 if(connect(sock, (struct sockaddr *)&remote_addr, len) == -1)
330 {
331 logprintf(1, "Error - In fork_process()/connect(): ");
332 logerror(1, errno);
333 quit = 1;
334 return;
335 }
336
337 if((user = malloc(sizeof(struct user_t))) == NULL)
338 {
339 logprintf(1, "Error - In fork_process()/malloc(): ");
340 logerror(1, errno);
341 quit = 1;
342 return;
343 }
344
345 user->sock = sock;
346 user->type = FORKED;
347 user->rem = 0;
348 user->buf = NULL;
349 user->outbuf = NULL;
350 memset(user->nick, 0, MAX_NICK_LEN+1);
351 sprintf(user->hostname, "parent_process");
352
353 if((flags = fcntl(user->sock, F_GETFL, 0)) < 0)
354 {
355 logprintf(1, "Error - In fork_process()/in fcntl(): ");
356 logerror(1, errno);
357 close(user->sock);
358 free(user);
359 return;
360 }
361
362 /* Non blocking mode */
363 if(fcntl(user->sock, F_SETFL, flags | O_NONBLOCK) < 0)
364 {
365 logprintf(1, "Error - In fork_process()/in fcntl(): ");
366 logerror(1, errno);
367 close(user->sock);
368 free(user);
369 return;
370 }
371
372
373 /* Add the user at the first place in the list */
374 add_non_human_to_list(user);
375 }
376 }
377
378 /* This function is used to move the listening socket to a process that has
379 * room for more users. If no process have room, a new is forked. */
switch_listening_process(char * buf,struct user_t * user)380 void switch_listening_process(char *buf, struct user_t *user)
381 {
382 int nbr_of_users;
383 int forknbr = 0;
384 struct user_t *non_human;
385 int nbr_of_forked = 0;
386
387 if(pid > 0)
388 nbr_of_forked = count_users(FORKED);
389
390 non_human = non_human_user_list;
391
392 /* If a process has closed the listening sockets. */
393 if((pid > 0) && (strncmp(buf, "$ClosedListen", 13) == 0))
394 {
395 if(nbr_of_forked == 1)
396 {
397 do_fork = 1;
398 return;
399 }
400 current_forked = 1;
401 while((non_human != NULL)
402 && (non_human->type != FORKED))
403 non_human = non_human->next;
404 send_to_user("$OpenListen|", non_human);
405 current_forked++;
406 }
407 else if(strncmp(buf, "$OpenListen", 11) == 0)
408 {
409 /* Check if we want to accept new clients in this process. */
410 nbr_of_users = count_users(UNKEYED | NON_LOGGED | REGULAR
411 | REGISTERED | OP | OP_ADMIN | ADMIN
412 | NON_LOGGED_ADM);
413
414 if((nbr_of_users < users_per_fork)
415 && (nbr_of_users < (max_sockets-5)))
416 {
417 if(listening_socket == -1)
418 {
419 if(set_listening_pid((int)getpid()) > 0)
420 {
421 /* Open the listening sockets. */
422 if((listening_socket = get_listening_socket(listening_port, 0)) == -1)
423 logprintf(1, "Error - In switch_listening_process(): Couldn't open listening socket\n");
424
425 admin_listening_socket = get_listening_socket(admin_port, admin_localhost);
426 }
427 }
428 }
429 else
430 send_to_user("$RejListen|", user);
431 }
432
433 /* If a process that couldn't take the listening sockets. */
434 else if((pid > 0) && (strncmp(buf, "$RejListen", 10) == 0))
435 {
436 if(current_forked > nbr_of_forked)
437 do_fork = 1;
438 else
439 {
440 while(non_human != NULL)
441 {
442 if(non_human->type == FORKED)
443 {
444 forknbr++;
445 if(forknbr == current_forked)
446 {
447 send_to_user("$OpenListen|", non_human);
448 current_forked++;
449 return;
450 }
451 }
452 non_human = non_human->next;
453 }
454 /* If we get here, which we usually shouldn't, we didn't find a
455 * process to host the listening sockets, so we will have to
456 * fork. */
457 do_fork = 1;
458 }
459 }
460 }
461
462
463 /* Create a process for uploading to public hub list */
do_upload_to_hublist(void)464 void do_upload_to_hublist(void)
465 {
466 int nbrusers;
467 int erret;
468
469 nbrusers = count_all_users();
470
471 if((pid = fork()) == -1)
472 {
473 logprintf(1, "Error - Couldn't fork new process in do_upload_to_hublist()\n");
474 logerror(1, errno);
475 return;
476 }
477 if(pid > 0)
478 pid = getpid();
479 else
480 {
481 pid = -2;
482 remove_all(0xFFFF, 0, 0);
483
484 while(((erret = close(listening_unx_socket)) != 0) && (errno == EINTR))
485 logprintf(1, "Error - In do_upload_to_hublist()/close(): Interrupted system call. Trying again.\n");
486
487 if(erret != 0)
488 {
489 logprintf(1, "Error - In do_upload_to_hublist()/close(): ");
490 logerror(1, errno);
491 }
492
493 while(((erret = close(listening_udp_socket)) != 0) && (errno == EINTR))
494 logprintf(1, "Error - In do_upload_to_hublist()/close(): Interrupted system call. Trying again.\n");
495
496 if(erret != 0)
497 {
498 logprintf(1, "Error - In do_upload_to_hublist()/close(): ");
499 logerror(1, errno);
500 }
501
502 upload_to_hublist(nbrusers);
503 }
504 upload = 0;
505 }
506
507
508 /* Removes all users of specified type. */
remove_all(int type,int send_quit,int remove_from_list)509 void remove_all(int type, int send_quit, int remove_from_list)
510 {
511 struct sock_t *human_user;
512 struct user_t *non_human;
513 struct sock_t *next_human;
514 struct user_t *next_non_human;
515
516 human_user = human_sock_list;
517 non_human = non_human_user_list;
518
519 /* First non-humans. */
520 while(non_human != NULL)
521 {
522 next_non_human = non_human->next;
523
524 if((non_human->type & type) != 0)
525 remove_user(non_human, send_quit, remove_from_list);
526
527 non_human = next_non_human;
528 }
529 while(human_user != NULL)
530 {
531 next_human = human_user->next;
532
533 if((human_user->user->type & type) != 0)
534 remove_user(human_user->user, send_quit, remove_from_list);
535
536 human_user = next_human;
537 }
538 }
539
term_signal(int z)540 void term_signal(int z)
541 {
542 quit = 1;
543 }
544
545 /* This will execute every ALARM_TIME seconds, it checks timeouts and uploads
546 * to public hublist */
alarm_signal(int z)547 void alarm_signal(int z)
548 {
549 struct user_t *non_human;
550 struct sock_t *human_user;
551
552 if((debug != 0) && (pid > 0))
553 logprintf(2, "Got alarm signal\n");
554
555 /* Send the hub_timer sub to the scripts. */
556 #ifdef HAVE_PERL
557 if(pid > 0)
558 command_to_scripts("$Script hub_timer|");
559 #endif
560
561 /* Check timeouts */
562 non_human = non_human_user_list;
563 while(non_human != NULL)
564 {
565 if((non_human->timeout == 0) && (non_human->type == LINKED))
566 {
567 logprintf(2, "Linked hub at %s, port %d is offline\n", non_human->hostname, non_human->key);
568 non_human->rem = REMOVE_USER;
569 }
570 non_human = non_human->next;
571 }
572
573 human_user = human_sock_list;
574 while(human_user != NULL)
575 {
576 if((human_user->user->type &
577 (UNKEYED | NON_LOGGED | NON_LOGGED_ADM)) != 0)
578 {
579 logprintf(2, "Timeout for non logged in user at %s, removing user\n", human_user->user->hostname);
580 human_user->user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
581 }
582 human_user = human_user->next;
583 }
584
585 /* And reset all timeout values */
586 non_human = non_human_user_list;
587 while(non_human != NULL)
588 {
589 if(non_human->type == LINKED)
590 non_human->timeout = 0;
591 non_human = non_human->next;
592 }
593
594 /* And make clear for upload to public hub list */
595 if(pid > 0)
596 {
597 if(hublist_upload != 0)
598 upload = 1;
599 do_write = 1;
600 do_send_linked_hubs = 1;
601 do_purge_user_list = 1;
602 }
603 else
604 {
605 upload = 0;
606 do_write = 0;
607 do_purge_user_list = 0;
608 }
609
610 remove_expired();
611
612 alarm(ALARM_TIME);
613 }
614
init_sig(void)615 void init_sig(void)
616 {
617 struct sigaction sv;
618
619 memset(&sv, 0, sizeof(struct sigaction));
620 sv.sa_flags = 0;
621 sigemptyset(&sv.sa_mask);
622 #ifdef SA_NOCLDWAIT
623 sv.sa_flags |= SA_NOCLDWAIT;
624 #endif
625 #ifdef SA_NOCLDSTOP
626 sv.sa_flags |= SA_NOCLDSTOP;
627 #endif
628
629 sv.sa_handler = SIG_IGN;
630 /* Don't want broken pipes to kill the hub. */
631 sigaction(SIGPIPE, &sv, NULL);
632
633 /* ...or any defunct child processes. */
634 sigaction(SIGCHLD, &sv, NULL);
635
636 sv.sa_handler = term_signal;
637
638 /* Also, shut down properly. */
639 sigaction(SIGTERM, &sv, NULL);
640 sigaction(SIGINT, &sv, NULL);
641
642 sv.sa_handler = alarm_signal;
643
644 /* And set handler for the alarm call. */
645 sigaction(SIGALRM, &sv, NULL);
646 }
647
648 /* Send info about one user to another. If all is 1, send to all */
send_user_info(struct user_t * from_user,char * to_user_nick,int all)649 void send_user_info(struct user_t *from_user, char *to_user_nick, int all)
650 {
651 char *send_buf;
652 struct user_t *to_user;
653 int to_nick_len;
654
655 (all != 0) ? (to_nick_len = 5) : (to_nick_len = strlen(to_user_nick)+1);
656
657 if((send_buf = malloc(sizeof(char) * (9 + to_nick_len
658 + strlen(from_user->nick) + 1
659 + ((from_user->desc == NULL) ? 0 : strlen(from_user->desc)) + 4 + 10
660 + ((from_user->email == NULL) ? 0 : strlen(from_user->email)) + 20 + 1))) == NULL)
661 {
662 logprintf(1, "Error - In send_user_info()/malloc(): ");
663 logerror(1, errno);
664 quit = 1;
665 return;
666 }
667
668 if(all != 0)
669 sprintf(send_buf, "$MyINFO $ALL ");
670 else
671 sprintf(send_buf, "$MyINFO $%s ", to_user_nick);
672
673 sprintfa(send_buf, "%s", from_user->nick);
674 sprintfa(send_buf, " ");
675 if(from_user->desc != NULL)
676 sprintfa(send_buf, "%s", from_user->desc);
677 sprintfa(send_buf, "$ $");
678 switch(from_user->con_type)
679 {
680 case 1:
681 sprintfa(send_buf, "28.8Kbps");
682 break;
683 case 2:
684 sprintfa(send_buf, "33.6Kbps");
685 break;
686 case 3:
687 sprintfa(send_buf, "56Kbps");
688 break;
689 case 4:
690 sprintfa(send_buf, "Satellite");
691 break;
692 case 5:
693 sprintfa(send_buf, "ISDN");
694 break;
695 case 6:
696 sprintfa(send_buf, "DSL");
697 break;
698 case 7:
699 sprintfa(send_buf, "Cable");
700 break;
701 case 8:
702 sprintfa(send_buf, "LAN(T1)");
703 break;
704 case 9:
705 sprintfa(send_buf, "LAN(T3)");
706 break;
707 // @Ciuly: added some other connection types
708 case 10:
709 sprintfa(send_buf, "Wireless");
710 break;
711 case 11:
712 sprintfa(send_buf, "Modem");
713 break;
714 case 12:
715 sprintfa(send_buf, "Netlimiter");
716 break;
717 // end @Ciuly
718 // Start fix for 1027168 by Ciuly
719 default:
720 sprintfa(send_buf, "Unknown");
721 break;
722 // End fix for 1027168
723 }
724 sprintfa(send_buf, "%c", from_user->flag);
725 sprintfa(send_buf, "$");
726 if(from_user->email != NULL)
727 sprintfa(send_buf, "%s", from_user->email);
728 sprintfa(send_buf, "$%lld", from_user->share);
729 sprintfa(send_buf, "$|");
730
731 /* The $Script user represents all scripts, so send the string to all
732 * running scripts. */
733 if((pid > 0) && (strncmp(to_user_nick, "$Script", 7) == 0))
734 send_to_non_humans(send_buf, SCRIPT, NULL);
735 else if((to_user = get_human_user(to_user_nick)) != NULL)
736 send_to_user(send_buf, to_user);
737 else
738 send_to_non_humans(send_buf, FORKED, NULL);
739 free(send_buf);
740 }
741
742 /* Sends different hub messages to user */
hub_mess(struct user_t * user,int mess_type)743 void hub_mess(struct user_t *user, int mess_type)
744 {
745 char *send_string;
746
747 send_string = NULL;
748 switch(mess_type)
749 {
750 /* If a user just connected */
751 case INIT_MESS:
752 if((send_string = malloc(sizeof(char) * 110)) == NULL)
753 {
754 logprintf(1, "Error - In hub_mess()/malloc(): ");
755 logerror(1, errno);
756 quit = 1;
757 return;
758 }
759
760 sprintf(send_string, "$HubName %s|", hub_name);
761 sprintfa(send_string, "<Hub-Security> This hub is running version %s of Open DC Hub.|", VERSION);
762 break;
763
764 /* If the hub is full, tell user */
765 case HUB_FULL_MESS:
766 if((send_string = malloc(sizeof(char)
767 * (15 + strlen(hub_full_mess) + 3))) == NULL)
768 {
769 logprintf(1, "Error - In hub_mess()/malloc(): ");
770 logerror(1, errno);
771 quit = 1;
772 return;
773 }
774 sprintf(send_string, "<Hub-Security> %s|",
775 hub_full_mess);
776 break;
777
778 case BAN_MESS:
779 if((send_string = malloc(sizeof(char) * 50)) == NULL)
780 {
781 logprintf(1, "Error - In hub_mess()/malloc(): ");
782 logerror(1, errno);
783 quit = 1;
784 return;
785 }
786
787 sprintf(send_string, "<Hub-Security> Your IP or Hostname is banned|");
788 break;
789
790 case GET_PASS_MESS:
791 if((send_string = malloc(sizeof(char) * 100)) == NULL)
792 {
793 logprintf(1, "Error - In hub_mess()/malloc(): ");
794 logerror(1, errno);
795 quit = 1;
796 return;
797 }
798
799 sprintf(send_string, "<Hub-Security> Your nickname is registered, please supply a password.|$GetPass|");
800 break;
801
802 case GET_PASS_MESS2:
803 if((send_string = malloc(sizeof(char) * 100)) == NULL)
804 {
805 logprintf(1, "Error - In hub_mess()/malloc(): ");
806 logerror(1, errno);
807 quit = 1;
808 return;
809 }
810
811 sprintf(send_string, "<Hub-Security> Password required to enter hub.|$GetPass|");
812 break;
813
814 case LOGGED_IN_MESS:
815 /* Construct the reply string */
816 if((send_string = malloc(sizeof(char) * (60 + strlen(user->nick)))) == NULL)
817 {
818 logprintf(1, "Error - In hub_mess()/malloc(): ");
819 logerror(1, errno);
820 quit = 1;
821 return;
822 }
823 sprintf(send_string, "<Hub-Security> Logged in.|$Hello %s|", user->nick);
824 break;
825
826 case OP_LOGGED_IN_MESS:
827 if((send_string = malloc(sizeof(char) * (15 + strlen(user->nick)))) == NULL)
828 {
829 logprintf(1, "Error - In hub_mess()/malloc(): ");
830 logerror(1, errno);
831 quit = 1;
832 return;
833 }
834 sprintf(send_string, "$LogedIn %s|", user->nick);
835 break;
836
837 case BAD_PASS_MESS:
838 /* Construct the reply string */
839 if((send_string = malloc(sizeof(char) * 60)) == NULL)
840 {
841 logprintf(1, "Error - In hub_mess()/malloc(): ");
842 logerror(1, errno);
843 quit = 1;
844 return;
845 }
846 sprintf(send_string, "$BadPass|<Hub-Security> That password was incorrect.|");
847 break;
848
849 case HELLO_MESS:
850 /* Construct the reply string */
851 if((send_string = malloc(sizeof(char) * (strlen(user->nick) + 12))) == NULL)
852 {
853 logprintf(1, "Error - In hub_mess()/malloc(): ");
854 logerror(1, errno);
855 quit = 1;
856 return;
857 }
858 sprintf(send_string, "$Hello %s|", user->nick);
859 break;
860
861 case INIT_ADMIN_MESS:
862 /* Construct the reply string */
863 if((send_string = malloc(sizeof(char) * 200)) == NULL)
864 {
865 logprintf(1, "Error - In hub_mess()/malloc(): ");
866 logerror(1, errno);
867 quit = 1;
868 return;
869 }
870 sprintf(send_string, "\r\nOpen DC Hub, version %s, administrators port.\r\nAll commands begin with \'$\' and end with \'|\'.\r\nPlease supply administrators passord.\r\n", VERSION);
871 break;
872 }
873
874 /* Send the constructed string */
875 if(send_string != NULL)
876 send_to_user(send_string, user);
877 free(send_string);
878 }
879
880 /* This function handles every command in the received packet one by one */
881 /* Returns 0 if user should be removed */
handle_command(char * buf,struct user_t * user)882 int handle_command(char *buf, struct user_t *user)
883 {
884 int ret;
885 char *temp;
886 char tempstr[MAX_HOST_LEN+1];
887
888 temp = NULL;
889 while(buf != NULL)
890 {
891 /* Check if it's a '$' or a '<' first in the command string */
892 if((strchr(buf, '$') != NULL) && (strchr(buf, '<') == NULL))
893 temp = strchr(buf, '$');
894 else if((strchr(buf, '$') == NULL) && (strchr(buf, '<') != NULL))
895 temp = strchr(buf, '<');
896 else if((strchr(buf, '$') == NULL) && (strchr(buf, '<') == NULL))
897 {
898 /* This is what happends every time a command doesn't fit in one
899 * single package. */
900 return 1;
901 }
902
903 else
904 (strchr(buf, '$') < strchr(buf, '<'))
905 ? (temp = strchr(buf, '$')) /* The '$' is first */
906 : (temp = strchr(buf, '<')); /* The '<' is first */
907
908 buf = temp;
909 temp = NULL;
910 /* First check if it's a whole command */
911 if(strchr(buf, '|') != NULL)
912 {
913 /* Copy command to temporary buf so we don't get more sent to the
914 * function than neccessary */
915 if((temp = malloc(sizeof(char) * (cut_string(buf, '|') + 3))) == NULL)
916 {
917 logprintf(1, "Error - In handle_command()/malloc(): ");
918 logerror(1, errno);
919 quit = 1;
920 return -1;
921 }
922 strncpy(temp, buf, cut_string(buf, '|') + 1);
923 if(cut_string(buf, '|') > 0)
924 temp[cut_string(buf, '|')+1] = '\0';
925
926 /* The Key command */
927 if(strncmp(temp, "$Key ", 5) == 0)
928 {
929 if(user->type == UNKEYED)
930 {
931 if(validate_key(buf, user) == 0)
932 {
933 logprintf(1, "User at %s provided bad $Key, removing user\n", user->hostname);
934 free(temp);
935 return 0;
936 }
937 }
938 }
939
940 /* The ValidateNick command */
941 else if(strncmp(temp, "$ValidateNick ", 14) == 0)
942 {
943 /* Only for non logged in users. If client wants to change
944 * nick, it first has to disconnect. */
945 /* Also allowed for scripts to register their nick in the
946 * nicklist. */
947 if((user->type == NON_LOGGED)
948 || ((user->type == SCRIPT) && (pid > 0)))
949 {
950 if(validate_nick(temp, user) == 0)
951 {
952 free(temp);
953 return 0;
954 }
955 }
956 }
957
958 /* The Version command */
959 else if(strncmp(temp, "$Version ", 9) == 0)
960 {
961 if(user->type != ADMIN)
962 {
963 if(version(temp, user) == 0)
964 {
965 free(temp);
966 return 0;
967 }
968 }
969 }
970
971 /* The GetNickList command */
972 else if(strncasecmp(temp, "$GetNickList", 12) == 0)
973 {
974 send_nick_list(user);
975 }
976
977 /* The MyINFO command */
978 else if(strncmp(temp, "$MyINFO $", 9) == 0)
979 {
980 if(user->type != ADMIN)
981 {
982 if(my_info(temp, user) == 0)
983 {
984 free(temp);
985 return 0;
986 }
987 }
988 }
989
990 /* The GetINFO command */
991 else if(strncasecmp(temp, "$GetINFO ", 9) == 0)
992 {
993 /* Only for logged in users */
994 if((user->type & (UNKEYED | NON_LOGGED | LINKED)) == 0)
995 get_info(temp, user);
996 }
997
998 /* The To: From: command */
999 else if(strncmp(temp, "$To: ", 5) == 0)
1000 {
1001 /* Only for logged in users */
1002 if((user->type & (UNKEYED | NON_LOGGED | SCRIPT | LINKED)) == 0)
1003 to_from(temp, user);
1004 }
1005
1006 /* The ConnectToMe command */
1007 else if(strncmp(temp, "$ConnectToMe ", 13) == 0)
1008 {
1009 if((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN
1010 | FORKED)) != 0)
1011 connect_to_me(temp, user);
1012 }
1013
1014 /* The RevConnectToMe command */
1015 else if(strncmp(temp, "$RevConnectToMe ", 16) == 0)
1016 {
1017 if((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN
1018 | FORKED)) != 0)
1019 rev_connect_to_me(temp, user);
1020 }
1021
1022 /* The Search command */
1023 else if(strncmp(temp, "$Search ", 8) == 0)
1024 {
1025 if((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN
1026 | FORKED | SCRIPT)) != 0)
1027 search(temp, user);
1028 }
1029
1030 /* The SR command */
1031 else if(strncmp(temp, "$SR ", 4) == 0)
1032 {
1033 if((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN
1034 | FORKED)) != 0)
1035 sr(temp, user);
1036 }
1037
1038 /* The MyPass command */
1039 else if(strncmp(temp, "$MyPass ", 8) == 0)
1040 {
1041 if(user->type == NON_LOGGED)
1042 {
1043 if(my_pass(temp + 8, user) == 0)
1044 {
1045 free(temp);
1046 return 0;
1047 }
1048 }
1049 }
1050
1051 /* The kick command */
1052 else if(strncasecmp(temp, "$Kick ", 6) == 0)
1053 {
1054 if((user->type & (OP | OP_ADMIN | ADMIN | FORKED | SCRIPT)) != 0)
1055 {
1056 kick(temp, user, 1);
1057 }
1058 else
1059 logprintf(2, "%s tried to kick without having priviledges\n", user->nick);
1060 }
1061
1062 /* The OpForceMove command */
1063 else if(strncmp(temp, "$OpForceMove ", 13) == 0)
1064 {
1065 if((user->type & (OP | OP_ADMIN | ADMIN | FORKED)) != 0)
1066 {
1067 op_force_move(temp, user);
1068 }
1069 else
1070 logprintf(2, "%s tried to redirect without having priviledges\n", user->nick);
1071 }
1072
1073 /* The chat command, starts with <nick> */
1074 else if(*temp == '<')
1075 {
1076 if((user->type & (SCRIPT | UNKEYED | LINKED | NON_LOGGED)) == 0)
1077 chat(temp, user);
1078 }
1079
1080 /* Commands that should be forwarded from forked processes */
1081 else if((strncmp(temp, "$Hello ", 7) == 0)
1082 || (strncmp(temp, "$Quit ", 6) == 0)
1083 || (strncmp(temp, "$OpList ", 8) == 0))
1084 {
1085 if(user->type == FORKED)
1086 {
1087 if(strncmp(temp, "$OpList ", 8) == 0)
1088 /* The oplist ends with two '|' */
1089 strcat(temp, "|");
1090 send_to_non_humans(temp, FORKED, user);
1091 send_to_humans(temp, REGULAR | REGISTERED | OP
1092 | OP_ADMIN, user);
1093 }
1094 }
1095
1096 /* Internal commands for mangement through telnet port and
1097 * communication between processes */
1098 else if((strncmp(temp, "$ClosedListen", 13) == 0)
1099 && (user->type == FORKED) && (pid > 0))
1100 {
1101 switch_listening_process(temp, user);
1102 }
1103
1104 else if((strncmp(temp, "$OpenListen", 11) == 0)
1105 && (user->type == FORKED) && (pid == 0))
1106 {
1107 switch_listening_process(temp, user);
1108 }
1109
1110 else if((strncmp(temp, "$RejListen", 10) == 0)
1111 && (user->type == FORKED) && (pid > 0))
1112 {
1113 switch_listening_process(temp, user);
1114 }
1115
1116 else if((strncmp(temp, "$DiscUser", 9) == 0)
1117 && (user->type == FORKED))
1118 {
1119 disc_user(temp, user);
1120 }
1121
1122 else if((strncasecmp(temp, "$ForceMove ", 11) == 0)
1123 && (user->type == FORKED))
1124 {
1125 redirect_all(temp + 11, user);
1126 }
1127
1128 else if((strncasecmp(temp, "$QuitProgram", 12) == 0)
1129 && ((user->type == FORKED) || (user->type == ADMIN)
1130 || (user->type == SCRIPT)))
1131 {
1132 if(user->type == ADMIN)
1133 uprintf(user, "\r\nShutting down hub...\r\n");
1134 quit = 1;
1135 }
1136
1137 else if(strncasecmp(temp, "$Exit", 5) == 0)
1138 {
1139 if(user->type == ADMIN)
1140 {
1141 logprintf(1, "Got exit from admin at %s, hanging up\n", user->hostname);
1142 free(temp);
1143 return 0;
1144 }
1145 }
1146
1147 else if((strncasecmp(temp, "$RedirectAll ", 13) == 0) && (user->type == ADMIN))
1148 {
1149 uprintf(user, "\r\nRedirecting all users...\r\n");
1150 logprintf(1, "Admin at %s redirected all users\n", user->hostname);
1151 redirect_all(temp+13, user);
1152 }
1153
1154 else if((strncasecmp(temp, "$AdminPass", 10) == 0) && (user->type == NON_LOGGED_ADM))
1155 {
1156 if(check_admin_pass(temp, user) == 0)
1157 {
1158 logprintf(2, "User from %s provided bad Admin Pass\n", user->hostname);
1159 free(temp);
1160 return 0;
1161 }
1162 }
1163
1164 else if(strncasecmp(temp, "$Set ", 5) == 0)
1165 {
1166 if((user->type & (FORKED | SCRIPT | ADMIN)) != 0)
1167 set_var(temp, user);
1168 }
1169
1170 else if(strncasecmp(temp, "$Ban ", 5) == 0)
1171 {
1172 if((user->type & (ADMIN | SCRIPT)) != 0)
1173 {
1174 ret = ballow(temp+5, BAN, user);
1175 if(user->type == ADMIN)
1176 {
1177 if(ret == -1)
1178 {
1179 send_to_user("\r\nCouldn't add entry to ban list\r\n", user);
1180 logprintf(4, "Error - Failed adding entry to ban list\n");
1181 }
1182 else if(ret == 0)
1183 {
1184 send_to_user("\r\nEntry is already on the list\r\n", user);
1185 }
1186 else
1187 {
1188 send_to_user("\r\nAdded entry to ban list\r\n", user);
1189 sscanf(temp+5, "%120[^|]", tempstr);
1190 logprintf(3, "Admin at %s added %s to banlist\n", user->hostname, tempstr);
1191 }
1192 }
1193 }
1194 }
1195 else if(strncasecmp(temp, "$Allow ", 7) == 0)
1196 {
1197 if((user->type & (ADMIN | SCRIPT)) != 0)
1198 {
1199 ret = ballow(temp+7, ALLOW, user);
1200 if(user->type == ADMIN)
1201 {
1202 if(ret == -1)
1203 {
1204 send_to_user("\r\nCouldn't add entry to allow list\r\n", user);
1205 logprintf(4, "Error - Failed adding entry to allow list\n");
1206 }
1207 else if(ret == 0)
1208 {
1209 send_to_user("\r\nEntry is already on the list\r\n", user);
1210 }
1211 else
1212 {
1213 send_to_user("\r\nAdded entry to allow list\r\n", user);
1214 sscanf(temp+7, "%120[^|]", tempstr);
1215 logprintf(3, "Admin at %s added %s to allow list\n", user->hostname, tempstr);
1216 }
1217 }
1218 }
1219 }
1220 else if(strncasecmp(temp, "$Unban ", 7) == 0)
1221 {
1222 if((user->type & (ADMIN | SCRIPT)) != 0)
1223 {
1224 ret = unballow(temp+7, BAN);
1225 if(user->type == ADMIN)
1226 {
1227 if(ret == -1)
1228 {
1229 send_to_user("\r\nCouldn't remove entry from ban list\r\n", user);
1230 logprintf(1, "Error - Failed removing entry from ban list\n");
1231 }
1232 else if(ret == 0)
1233 {
1234 send_to_user("\r\nEntry wasn't found in list\r\n", user);
1235 }
1236 else
1237 {
1238 send_to_user("\r\nRemoved entry from ban list\r\n", user);
1239 sscanf(temp+7, "%120[^|]", tempstr);
1240 logprintf(3, "Admin at %s removed %s from ban list\n", user->hostname, tempstr);
1241 }
1242 }
1243 }
1244 }
1245 else if(strncasecmp(temp, "$Unallow ", 9) == 0)
1246 {
1247 if((user->type & (ADMIN | SCRIPT)) != 0)
1248 {
1249 ret = unballow(temp+9, ALLOW);
1250 if(user->type == ADMIN)
1251 {
1252 if(ret == -1)
1253 {
1254 send_to_user("\r\nCouldn't remove entry from allow list\r\n", user);
1255 logprintf(1, "Error - Failed removing entry from allow list\n");
1256 }
1257 else if(ret == 0)
1258 {
1259 send_to_user("\r\nEntry wasn't found in list\r\n", user);
1260 }
1261 else
1262 {
1263 send_to_user("\r\nRemoved entry from allow list\r\n", user);
1264 sscanf(temp+9, "%120[^|]", tempstr);
1265 logprintf(3, "Admin at %s removed %s from allow list\n", user->hostname, tempstr);
1266 }
1267 }
1268 }
1269 }
1270 else if(strncasecmp(temp, "$GetBanList", 11) == 0)
1271 {
1272 if(user->type == ADMIN)
1273 {
1274 uprintf(user, "\r\n");
1275 send_user_list(BAN, user);
1276 uprintf(user, "\r\n");
1277 }
1278 }
1279 else if(strncasecmp(temp, "$GetAllowList", 13) == 0)
1280 {
1281 if(user->type == ADMIN)
1282 {
1283 uprintf(user, "\r\n");
1284 send_user_list(ALLOW, user);
1285 uprintf(user, "\r\n");
1286 }
1287 }
1288 else if(strncasecmp(temp, "$GetRegList", 11) == 0)
1289 {
1290 if(user->type == ADMIN)
1291 {
1292 uprintf(user, "\r\n");
1293 send_user_list(REG, user);
1294 uprintf(user, "\r\n");
1295 }
1296 }
1297 else if(strncasecmp(temp, "$GetConfig", 10) == 0)
1298 {
1299 if(user->type == ADMIN)
1300 {
1301 uprintf(user, "\r\n");
1302 send_user_list(CONFIG, user);
1303 uprintf(user, "\r\n");
1304 }
1305 }
1306 else if(strncasecmp(temp, "$GetMotd", 8) == 0)
1307 {
1308 if(user->type == ADMIN)
1309 {
1310 uprintf(user, "\r\n");
1311 send_motd(user);
1312 send_to_user("\r\n", user);
1313 }
1314 }
1315 else if(strncasecmp(temp, "$GetLinkList", 12) == 0)
1316 {
1317 if(user->type == ADMIN)
1318 {
1319 uprintf(user, "\r\n");
1320 send_user_list(LINK, user);
1321 uprintf(user, "\r\n");
1322 }
1323 }
1324 else if(strncasecmp(temp, "$AddRegUser ", 12) == 0)
1325 {
1326 if((user->type & (ADMIN | SCRIPT)) != 0)
1327 {
1328 ret = add_reg_user(temp, user);
1329 if(user->type == ADMIN)
1330 {
1331 if(ret == -1)
1332 send_to_user("\r\nCouldn't add user to reg list\r\n", user);
1333 else if(ret == 2)
1334 send_to_user("\r\nBad format for $AddRegUser. Correct format is:\r\n$AddRegUser <nickname> <password> <opstatus>|\r\n", user);
1335 else if(ret == 3)
1336 send_to_user("\r\nThat nickname is already registered\r\n", user);
1337 else
1338 {
1339 send_to_user("\r\nAdded user to reglist\r\n", user);
1340 logprintf(3, "Admin at %s added entry to reglist\n", user->hostname);
1341 }
1342 }
1343 }
1344 }
1345 else if(strncasecmp(temp, "$RemoveRegUser ", 15) == 0)
1346 {
1347 if((user->type & (ADMIN | SCRIPT)) != 0)
1348 {
1349 ret = remove_reg_user(temp+15, user);
1350 if(user->type == ADMIN)
1351 {
1352 if(ret == 0)
1353 send_to_user("\r\nUser wasn't found in reg list\r\n", user);
1354 else if(ret == -1)
1355 send_to_user("\r\nCouldn't remove user from reg list\r\n", user);
1356 else
1357 {
1358 send_to_user("\r\nRemoved user from reglist\r\n", user);
1359 logprintf(3, "Admin at %s removed entry from reglist\n", user->hostname);
1360 }
1361 }
1362 }
1363 }
1364 else if(strncasecmp(temp, "$AddLinkedHub ", 14) == 0)
1365 {
1366 if((user->type & (ADMIN | SCRIPT)) != 0)
1367 {
1368 ret = add_linked_hub(temp);
1369 if(user->type == ADMIN)
1370 {
1371 if(ret == -1)
1372 send_to_user("\r\nCouldn't add hub to link list\r\n", user);
1373 else if(ret == 2)
1374 send_to_user("\r\nBad format for $AddLinkedHub. Correct format is:\r\n$AddLinkedHub <ip> <port>|\r\n", user);
1375 else if(ret == 3)
1376 send_to_user("\r\nThat hub is already in the linklist\r\n", user);
1377 else
1378 {
1379 send_to_user("\r\nAdded hub to linklist\r\n", user);
1380 logprintf(3, "Admin at %s added entry to linklist\n", user->hostname);
1381 }
1382 }
1383 }
1384 }
1385 else if(strncasecmp(temp, "$RemoveLinkedHub ", 17) == 0)
1386 {
1387 if((user->type & (ADMIN | SCRIPT)) != 0)
1388 {
1389 ret = remove_linked_hub(temp+17);
1390 if(user->type == ADMIN)
1391 {
1392 if(ret == 0)
1393 send_to_user("\r\nHub wasn't found in link list\r\n", user);
1394 else if(ret == -1)
1395 send_to_user("\r\nCouldn't remove hub from link list\r\n", user);
1396 else if(ret == 2)
1397 send_to_user("\r\nBad format for $RemoveLinkedHub. Correct format is:\r\n$RemoveLinkedHub <ip> <port>|\r\n", user);
1398 else
1399 {
1400 send_to_user("\r\nRemoved hub from linklist\r\n", user);
1401 logprintf(3, "Admin at %s removed entry from linklist\n", user->hostname);
1402 }
1403 }
1404 }
1405 }
1406 else if(strncmp(temp, "$MultiSearch ", 13) == 0)
1407 {
1408 if((user->type & (FORKED | REGULAR | REGISTERED | OP | OP_ADMIN)) != 0)
1409 multi_search(temp, user);
1410 }
1411 else if(strncmp(temp, "$MultiConnectToMe ", 18) == 0)
1412 {
1413 if((user->type & (FORKED | REGULAR | REGISTERED | OP | OP_ADMIN)) != 0)
1414 multi_connect_to_me(temp, user);
1415 }
1416 else if(strncasecmp(temp, "$GetHost ", 9) == 0)
1417 {
1418 if(user->type == ADMIN)
1419 get_host(temp, user, HOST);
1420 }
1421 else if(strncasecmp(temp, "$GetIP ", 7) == 0)
1422 {
1423 if(user->type == ADMIN)
1424 get_host(temp, user, IP);
1425 }
1426 else if(strncasecmp(temp, "$Commands", 9) == 0)
1427 {
1428 if(user->type == ADMIN)
1429 send_commands(user);
1430 }
1431 else if(strncasecmp(temp, "$MassMessage ", 13) == 0)
1432 {
1433 if(user->type == ADMIN)
1434 {
1435 uprintf(user, "\r\nSent Mass Message\r\n");
1436 send_mass_message(temp + 13, user);
1437 }
1438 }
1439 else if(strncasecmp(temp, "$AddPerm ", 9) == 0)
1440 {
1441 if((user->type & (ADMIN | FORKED | SCRIPT)) != 0)
1442 {
1443 ret = add_perm(temp, user);
1444 if(user->type == ADMIN)
1445 {
1446 if(ret == -1)
1447 uprintf(user, "\r\nCouldn't add permission to user\r\n");
1448 else if(ret == 2)
1449 uprintf(user, "\r\nBad format for $AaddPerm. Correct format is:\r\n$AddPerm <nick> <permission>|\r\nand permission is one of: BAN_ALLOW, USER_INFO, MASSMESSAGE, USER_ADMIN\r\n");
1450 else if(ret == 3)
1451 uprintf(user, "\r\nUser already has that permission.\r\n");
1452 else if(ret == 4)
1453 uprintf(user, "\r\nUser is not an operator.\r\n");
1454 else
1455 {
1456 uprintf(user, "\r\nAdded permission to user.\r\n");
1457 logprintf(3, "Administrator at %s added permission to user\n", user->hostname);
1458 }
1459 }
1460 }
1461 }
1462 else if(strncasecmp(temp, "$RemovePerm ", 12) == 0)
1463 {
1464 if((user->type & (ADMIN | FORKED | SCRIPT)) != 0)
1465 {
1466 ret = remove_perm(temp, user);
1467 if(user->type == ADMIN)
1468 {
1469 if(ret == -1)
1470 uprintf(user, "\r\nCouldn't remove permission from user.\r\n");
1471 else if(ret == 2)
1472 uprintf(user, "\r\nBad format for $RemovePerm. Correct format is:\r\n$RemovePerm <nick> <permission>|\r\nand permission is one of: BAN_ALLOW, USER_INFO, MASSMESSAGE, USER_ADMIN\r\n");
1473 else if(ret == 3)
1474 uprintf(user, "\r\nUser does not have that permission.\r\n");
1475 else if(ret == 4)
1476 uprintf(user, "\r\nUser is not an operator.\r\n");
1477 else
1478 {
1479 uprintf(user, "\r\nRemoved permission from user.\r\n");
1480 logprintf(3, "Administrator at %s removed permission from user\n", user->hostname);
1481 }
1482 }
1483 }
1484 }
1485 else if(strncasecmp(temp, "$ShowPerms ", 11) == 0)
1486 {
1487 if(user->type == ADMIN)
1488 {
1489 if((ret = show_perms(user, temp)) == 2)
1490 uprintf(user, "\r\nBad format for $ShowPerms. Correct format is:\r\n$ShowPerms <nick>|");
1491 else if(ret == 3)
1492 uprintf(user, "\r\nUser is not an operator.\r\n");
1493 }
1494 }
1495 else if(strncasecmp(temp, "$ShowPerms ", 11) == 0)
1496 {
1497 if(user->type == ADMIN)
1498 {
1499 if((ret = show_perms(user, temp)) == 2)
1500 uprintf(user, "\r\nBad format for $ShowPerms. Correct format is:\r\n$ShowPerms <nick>|");
1501 else if(ret == 3)
1502 uprintf(user, "\r\nUser is not an operator.\r\n");
1503 }
1504 }
1505 else if(strncasecmp(temp, "$NickBan ", 9) == 0)
1506 {
1507 if((user->type & (ADMIN | SCRIPT)) != 0)
1508 {
1509 ret = ballow(temp+9, NICKBAN, user);
1510 if(user->type == ADMIN)
1511 {
1512 if(ret == -1)
1513 {
1514 uprintf(user, "\r\nCouldn't add entry to nickban list\r\n");
1515 logprintf(4, "Error - Failed adding entry to nickban list\n");
1516 }
1517 else if(ret == 2)
1518 uprintf(user, "\r\nEntry is already on the list\r\n");
1519 else
1520 {
1521 uprintf(user, "\r\nAdded entry to nickban list\r\n");
1522 sscanf(temp+9, "%120[^|]", tempstr);
1523 logprintf(3, "Administrator at %s added %s to nickban list\n", user->hostname, tempstr);
1524 }
1525 }
1526 }
1527 }
1528 else if(strncasecmp(temp, "$GetNickBanList", 15) == 0)
1529 {
1530 if(user->type == ADMIN)
1531 {
1532 uprintf(user, "\r\nNickban list:\r\n");
1533 send_user_list(NICKBAN, user);
1534 uprintf(user, "\r\n");
1535 }
1536 }
1537 else if(strncasecmp(temp, "$UnNickBan ", 11) == 0)
1538 {
1539 if((user->type & (ADMIN | SCRIPT)) != 0)
1540 {
1541 ret = unballow(temp+11, NICKBAN);
1542 if(user->type == ADMIN)
1543 {
1544 if(ret == -1)
1545 {
1546 uprintf(user, "\r\nCouldn't remove entry from nickban list\r\n");
1547 logprintf(4, "Error - Failed adding entry to nickban list\n");
1548 }
1549 else if(ret == 2)
1550 uprintf(user, "\r\nEntry wasn't found in list\r\n");
1551 else
1552 {
1553 uprintf(user, "\r\nRemoved entry from nickban list\r\n");
1554 sscanf(temp+9, "%120[^|]", tempstr);
1555 logprintf(3, "Administrator at %s removed %s from nickban list\n", user->hostname, tempstr);
1556 }
1557 }
1558 }
1559 }
1560 /* Commands from script processes */
1561 #ifdef HAVE_PERL
1562 else if(strncasecmp(temp, "$NewScript", 10) == 0)
1563 {
1564 if(user->type == FORKED)
1565 {
1566 user->type = SCRIPT;
1567 sprintf(user->hostname, "script_process");
1568 sprintf(user->nick, "script process");
1569 }
1570 }
1571 else if(strncmp(temp, "$Script ", 8) == 0)
1572 {
1573 if(pid > 0)
1574 {
1575 if(user->type == FORKED)
1576 non_format_to_scripts(temp);
1577 }
1578 else
1579 {
1580 if(user->type == SCRIPT)
1581 sub_to_script(temp + 8);
1582 }
1583 }
1584 else if(strncasecmp(temp, "$ReloadScripts", 14) == 0)
1585 {
1586 if((user->type & (ADMIN | FORKED)) != 0)
1587 {
1588 if(user->type == ADMIN)
1589 uprintf(user, "\r\nReloading scripts...\r\n");
1590 if(pid > 0)
1591 script_reload = 1;
1592
1593 else
1594 send_to_non_humans(temp, FORKED, user);
1595 }
1596 }
1597 else if(strncasecmp(temp, "$ScriptToUser ", 14) == 0)
1598 {
1599 if((user->type & (SCRIPT | FORKED)) != 0)
1600 script_to_user(temp, user);
1601 }
1602 else if(strncasecmp(temp, "$DataToAll ", 11) == 0)
1603 {
1604 if(user->type == SCRIPT)
1605 {
1606 send_to_non_humans(temp, FORKED, user);
1607 send_to_humans(temp + 11, REGULAR | REGISTERED | OP | OP_ADMIN, user);
1608 }
1609 else if(user->type == FORKED)
1610 send_to_humans(temp + 11, REGULAR | REGISTERED | OP | OP_ADMIN, user);
1611 }
1612 #endif
1613 }
1614
1615 /* Send to scripts */
1616 #ifdef HAVE_PERL
1617 if(((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN)) != 0)
1618 && (temp != NULL) && (strlen(temp) > 2)
1619 && (strncasecmp(temp, "$ReloadScripts", 14) != 0))
1620 {
1621 command_to_scripts("$Script data_arrival %c%c%s%c%c",
1622 '\005', '\005', user->nick, '\005', '\005');
1623 non_format_to_scripts(temp);
1624 }
1625 #endif
1626
1627 if((buf = strchr(buf, '|')) != NULL)
1628 buf++;
1629
1630 if(temp != NULL)
1631 free(temp);
1632 }
1633 return 1;
1634 }
1635
1636 /* Add a user who connected */
new_human_user(int sock)1637 int new_human_user(int sock)
1638 {
1639 struct user_t *user;
1640 struct sockaddr_in client;
1641 int namelen;
1642 int yes = 1;
1643 int i = 0;
1644 int banret, allowret;
1645 int socknum;
1646 int erret;
1647 int flags;
1648
1649 memset(&client, 0, sizeof(struct sockaddr_in));
1650
1651 /* Get a socket for the connected user. */
1652 namelen = sizeof(client);
1653 while(((socknum = accept(sock, (struct sockaddr *)&client,
1654 &namelen)) == -1) && ((errno == EAGAIN) || (errno == EINTR)))
1655 {
1656 i++;
1657 usleep(500);
1658 /* Giving up after half a second */
1659 if(i == 1000)
1660 return -1;
1661 }
1662
1663 /* Allocate space for the new user */
1664 if((user = malloc(sizeof(struct user_t))) == NULL)
1665 {
1666 logprintf(1, "Error - In new_human_user()/malloc(): ");
1667 logerror(1, errno);
1668 quit = 1;
1669 return -1;
1670 }
1671
1672 /* Set the sock of the user. */
1673 user->sock = socknum;
1674
1675 /* Reset the last search time */
1676 user->last_search = 0;
1677
1678 /* Avoid dead peers */
1679 if(setsockopt(user->sock, SOL_SOCKET, SO_KEEPALIVE, &yes,
1680 sizeof(int)) == -1)
1681 {
1682 logprintf(1, "Error - In new_human_user()/set_sock_opt(): ");
1683 logerror(1, errno);
1684 close(user->sock);
1685 free(user);
1686 return -1;
1687 }
1688
1689 if((flags = fcntl(user->sock, F_GETFL, 0)) < 0)
1690 {
1691 logprintf(1, "Error - In new_human_user()/in fcntl(): ");
1692 logerror(1, errno);
1693 close(user->sock);
1694 free(user);
1695 return -1;
1696 }
1697
1698 /* Non blocking mode */
1699 if(fcntl(user->sock, F_SETFL, flags | O_NONBLOCK) < 0)
1700 {
1701 logprintf(1, "Error - In new_human_user()/in fcntl(): ");
1702 logerror(1, errno);
1703 close(user->sock);
1704 free(user);
1705 return -1;
1706 }
1707
1708 /* Set users ip */
1709 user->ip = client.sin_addr.s_addr;
1710
1711 /* Set users hostname if reverse_dns is set. */
1712 if(reverse_dns != 0)
1713 strcpy(user->hostname, hostname_from_ip(user->ip));
1714 else
1715 strcpy(user->hostname, inet_ntoa(client.sin_addr));
1716
1717 /* Send to scripts */
1718 #ifdef HAVE_PERL
1719 command_to_scripts("$Script attempted_connection %c%c%s|", '\005', '\005', user->hostname);
1720 #endif
1721
1722 /* Set user vars to 0/NULL */
1723 user->type = NON_LOGGED;
1724 memset(user->nick, 0, MAX_NICK_LEN+1);
1725 memset(user->version, 0, MAX_VERSION_LEN+1);
1726 user->email = NULL;
1727 user->desc = NULL;
1728 user->con_type = 0;
1729 user->flag = 0;
1730 user->share = 0;
1731 user->timeout = 0;
1732 user->buf = NULL;
1733 user->outbuf = NULL;
1734 user->rem = 0;
1735 user->last_search = (time_t)0;
1736
1737 sprintf(user->nick, "Non_logged_in_user");
1738
1739 /* Check if hub is full */
1740 if(sock == listening_socket)
1741 {
1742 if((count_all_users()) >= max_users)
1743 {
1744 hub_mess(user, HUB_FULL_MESS);
1745 if(!((redirect_host == NULL) || ((int)redirect_host[0] <= 0x20)))
1746 {
1747 uprintf(user, "$ForceMove %s|", redirect_host);
1748 }
1749
1750 while(((erret = close(user->sock)) != 0) && (errno == EINTR))
1751 logprintf(1, "Error - In new_human_user()/close(): Interrupted system call. Trying again.\n");
1752
1753 if(erret != 0)
1754 {
1755 logprintf(1, "Error - In new_human_user()/close(): ");
1756 logerror(1, errno);
1757 }
1758
1759 free(user);
1760 return 1;
1761 }
1762 }
1763
1764 /* Check if user is banned */
1765 if(sock != admin_listening_socket)
1766 {
1767 banret = check_if_banned(user, BAN);
1768 allowret = check_if_allowed(user);
1769
1770 if(ban_overrides_allow == 0)
1771 {
1772 if((allowret != 1) && (banret == 1))
1773 {
1774 hub_mess(user, BAN_MESS);
1775 logprintf(4, "User %s from %s (%s) denied\n", user->nick, user->hostname, inet_ntoa(client.sin_addr));
1776 while(((erret = close(user->sock)) != 0) && (errno == EINTR))
1777 logprintf(1, "Error - In new_human_user()/close(): Interrupted system call. Trying again.\n");
1778
1779 if(erret != 0)
1780 {
1781 logprintf(1, "Error - In new_human_user()/close(): ");
1782 logerror(1, errno);
1783 }
1784
1785 free(user);
1786 return 1;
1787 }
1788 }
1789
1790 else
1791 {
1792 if((allowret != 1) || (banret == 1))
1793 {
1794 hub_mess(user, BAN_MESS);
1795 logprintf(4, "User %s from %s (%s) denied\n", user->nick, user->hostname, inet_ntoa(client.sin_addr));
1796 while(((erret = close(user->sock)) != 0) && (errno == EINTR))
1797 logprintf(1, "Error - In new_human_user()/close(): Interrupted system call. Trying again.\n");
1798
1799 if(erret != 0)
1800 {
1801 logprintf(1, "Error - In new_human_user()/close(): ");
1802 logerror(1, errno);
1803 }
1804
1805 free(user);
1806 return 1;
1807 }
1808 }
1809
1810 if((banret == -1) || (allowret == -1))
1811 {
1812 while(((erret = close(user->sock)) != 0) && (errno == EINTR))
1813 logprintf(1, "Error - In new_human_user()/close(): Interrupted system call. Trying again.\n");
1814
1815 if(erret != 0)
1816 {
1817 logprintf(1, "Error - In new_human_user()/close(): ");
1818 logerror(1, errno);
1819 }
1820 free(user);
1821 return -1;
1822 }
1823 }
1824
1825 /* Add sock struct of the user. */
1826 add_socket(user);
1827
1828 if(sock == listening_socket)
1829 logprintf(4, "New connection on socket %d from user at %s\n", user->sock, user->hostname);
1830 else if(sock == admin_listening_socket)
1831 logprintf(4, "New admin connection on socket %d from user at %s\n", user->sock, user->hostname);
1832
1833 /* If it's a regular user. */
1834 if(sock == listening_socket)
1835 {
1836 if(check_key != 0)
1837 user->type = UNKEYED;
1838 send_lock(user);
1839 hub_mess(user, INIT_MESS);
1840 }
1841 else if(sock == admin_listening_socket)
1842 {
1843 user->type = NON_LOGGED_ADM;
1844 hub_mess(user, INIT_ADMIN_MESS);
1845 }
1846
1847 if((count_users(UNKEYED | NON_LOGGED | REGULAR | REGISTERED | OP | OP_ADMIN
1848 | ADMIN | NON_LOGGED_ADM) >= users_per_fork)
1849 || (max_sockets <= count_users(0xFFFF)+10))
1850 {
1851 set_listening_pid(0);
1852 while(((erret = close(listening_socket)) != 0) && (errno == EINTR))
1853 logprintf(1, "Error - In new_human_user()/close(): Interrupted system call. Trying again.\n");
1854
1855 if(erret != 0)
1856 {
1857 logprintf(1, "Error - In new_human_user()/close(): ");
1858 logerror(1, errno);
1859 }
1860
1861 while(((erret = close(admin_listening_socket)) != 0) && (errno == EINTR))
1862 logprintf(1, "Error - In new_human_user()/close(): Interrupted system call. Trying again.\n");
1863
1864 if(erret != 0)
1865 {
1866 logprintf(1, "Error - In new_human_user()/close(): ");
1867 logerror(1, errno);
1868 }
1869
1870 listening_socket = -1;
1871 admin_listening_socket = -1;
1872 send_to_user("$ClosedListen|", non_human_user_list);
1873 }
1874
1875 return 0;
1876 }
1877
1878 /* Add a non-human user to the linked list. */
add_non_human_to_list(struct user_t * user)1879 void add_non_human_to_list(struct user_t *user)
1880 {
1881 /* Add the user at the first place in the list */
1882 user->next = non_human_user_list;
1883 non_human_user_list = user;
1884 }
1885
1886 /* Remove a non-human user. */
remove_non_human(struct user_t * our_user)1887 void remove_non_human(struct user_t *our_user)
1888 {
1889 int erret;
1890 struct user_t *user, *last_user;
1891
1892 user = non_human_user_list;
1893 last_user = NULL;
1894
1895 while(user != NULL)
1896 {
1897 if(user == our_user)
1898 {
1899 if(our_user->type != LINKED)
1900 {
1901 while(((erret = close(user->sock)) != 0) && (errno == EINTR))
1902 logprintf(1, "Error - In remove_non_human()/close(): Interrupted system call. Trying again.\n");
1903
1904 if(erret != 0)
1905 {
1906 logprintf(1, "Error - In remove_non_human()/close(): ");
1907 logerror(1, errno);
1908 }
1909 }
1910
1911 if(last_user == NULL)
1912 non_human_user_list = user->next;
1913 else
1914 last_user->next = user->next;
1915 if(our_user->type != LINKED)
1916 {
1917 if(our_user->buf != NULL)
1918 free(our_user->buf);
1919 if(our_user->outbuf != NULL)
1920 free(our_user->outbuf);
1921 }
1922
1923 free(our_user);
1924
1925 return;
1926 }
1927 last_user = user;
1928 user = user->next;
1929 }
1930 }
1931
1932 /* Add a human user to the hashtable. */
add_human_to_hash(struct user_t * user)1933 void add_human_to_hash(struct user_t *user)
1934 {
1935 int hashv;
1936
1937 hashv = get_hash(user->nick);
1938
1939 /* Adds the user first in the linked list of the specified hash value. */
1940 user->next = human_hash_table[hashv];
1941 human_hash_table[hashv] = user;
1942 }
1943
1944 /* Returns a human user from a certain nick. */
get_human_user(char * nick)1945 struct user_t* get_human_user(char *nick)
1946 {
1947 struct user_t *user;
1948
1949 user = human_hash_table[get_hash(nick)];
1950
1951 while((user != NULL)
1952 && !((strncasecmp(user->nick, nick, strlen(nick)) == 0)
1953 && (strlen(nick) == strlen(user->nick))))
1954 user = user->next;
1955
1956 return user;
1957 }
1958
1959 /* Removes a human user from hashtable. */
remove_human_from_hash(char * nick)1960 void remove_human_from_hash(char *nick)
1961 {
1962 struct user_t *user, *last_user;
1963 int hashv;
1964
1965 hashv = get_hash(nick);
1966 user = human_hash_table[hashv];
1967 last_user = NULL;
1968
1969 while(user != NULL)
1970 {
1971 if((strncmp(user->nick, nick, strlen(nick)) == 0)
1972 && (strlen(nick) == strlen(user->nick)))
1973 {
1974 if(last_user == NULL)
1975 human_hash_table[hashv] = user->next;
1976 else
1977 last_user->next = user->next;
1978
1979 return;
1980 }
1981 last_user = user;
1982 user = user->next;
1983 }
1984 }
1985
1986 /* Removes a human user. */
remove_human_user(struct user_t * user)1987 void remove_human_user(struct user_t *user)
1988 {
1989 int erret;
1990
1991 /* Remove the user from the hashtable. */
1992 if((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN | ADMIN)) != 0)
1993 remove_human_from_hash(user->nick);
1994
1995
1996 /* When a logged in user in a non script process leaves, the user should
1997 * be removed from the list and the users share should be subtracted from
1998 * the total share. */
1999 if((user->nick != NULL)
2000 && ((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN)) != 0)
2001 && (pid == 0))
2002 {
2003 if(user->share > 0)
2004 add_total_share(-user->share);
2005 }
2006
2007 while(((erret = close(user->sock)) != 0) && (errno == EINTR))
2008 logprintf(1, "Error - In remove_human_user()/close(): Interrupted system call. Trying again.\n");
2009
2010 if(erret != 0)
2011 {
2012 logprintf(1, "Error - In remove_human_user()/close(): ");
2013 logerror(1, errno);
2014 }
2015
2016 if(user->buf != NULL)
2017 {
2018 free(user->buf);
2019 user->buf = NULL;
2020 }
2021 if(user->outbuf != NULL)
2022 {
2023 free(user->outbuf);
2024 user->outbuf = NULL;
2025 }
2026 if(user->email != NULL)
2027 {
2028 free(user->email);
2029 user->email = NULL;
2030 }
2031 if(user->desc != NULL)
2032 {
2033 free(user->desc);
2034 user->desc = NULL;
2035 }
2036
2037 /* Remove the socket struct of the user. */
2038 remove_socket(user);
2039
2040
2041 #ifdef HAVE_PERL
2042 if((user->type & (REGULAR | REGISTERED | OP | OP_ADMIN)) != 0)
2043 {
2044 command_to_scripts("$Script user_disconnected %c%c", '\005', '\005');
2045 non_format_to_scripts(user->nick);
2046 command_to_scripts("|");
2047 }
2048 #endif
2049
2050 /* And free the user. */
2051 free(user);
2052
2053 if((count_users(UNKEYED | NON_LOGGED | REGULAR | REGISTERED | OP
2054 | OP_ADMIN | ADMIN) == 0) && (pid == 0)
2055 && (listening_socket == -1))
2056 kill_forked_process();
2057 }
2058
2059 /* Removes a user. Sends the $quit string if send_quit is non-zero and removes
2060 * the user from the userlist if remove_from_list is non-zero. */
remove_user(struct user_t * our_user,int send_quit,int remove_from_list)2061 void remove_user(struct user_t *our_user, int send_quit, int remove_from_list)
2062 {
2063 char quit_string[MAX_NICK_LEN+10];
2064
2065 if(send_quit != 0)
2066 {
2067 if((our_user->type & (REGULAR | REGISTERED | OP | OP_ADMIN)) != 0)
2068 {
2069 sprintf(quit_string, "$Quit %s|", our_user->nick);
2070 send_to_non_humans(quit_string, FORKED, NULL);
2071 send_to_humans(quit_string, REGULAR | REGISTERED | OP | OP_ADMIN,
2072 our_user);
2073 }
2074 else if((our_user->type == SCRIPT)
2075 && (strncmp(our_user->nick, "script process", 14) != 0))
2076 {
2077 sprintf(quit_string, "$Quit %s|", our_user->nick);
2078 send_to_non_humans(quit_string, FORKED, NULL);
2079 send_to_humans(quit_string, REGULAR | REGISTERED | OP | OP_ADMIN,
2080 our_user);
2081 }
2082 }
2083
2084 if((remove_from_list != 0)
2085 && (our_user->type & (REGULAR | REGISTERED | OP | OP_ADMIN | SCRIPT))
2086 != 0)
2087 remove_user_from_list(our_user->nick);
2088
2089 if((our_user->type & (UNKEYED | NON_LOGGED | REGULAR | REGISTERED | OP
2090 | OP_ADMIN | ADMIN | NON_LOGGED_ADM)) != 0)
2091 remove_human_user(our_user);
2092 else
2093 remove_non_human(our_user);
2094 }
2095
2096 /* Removes all users who have the rem variable set to non-zero */
clear_user_list(void)2097 void clear_user_list(void)
2098 {
2099 struct user_t *non_human;
2100 struct user_t *next_non_human;
2101 struct sock_t *human_user;
2102 struct sock_t *next_human_user;
2103
2104 non_human = non_human_user_list;
2105 human_user = human_sock_list;
2106
2107 while(non_human != NULL)
2108 {
2109 next_non_human = non_human->next;
2110 if(non_human->rem != 0)
2111 remove_user(non_human, non_human->rem & SEND_QUIT,
2112 non_human->rem & REMOVE_FROM_LIST);
2113
2114 non_human = next_non_human;
2115 }
2116
2117 while(human_user != NULL)
2118 {
2119 next_human_user = human_user->next;
2120 if(human_user->user->rem != 0)
2121 remove_user(human_user->user, human_user->user->rem & SEND_QUIT,
2122 human_user->user->rem & REMOVE_FROM_LIST);
2123
2124 human_user = next_human_user;
2125 }
2126 }
2127
2128 /********************************************************/
2129 /* Get action from a connected socket */
2130 /* Returns -1 on error, */
2131 /* 0 on connection closed, */
2132 /* 1 on received message */
socket_action(struct user_t * user)2133 int socket_action(struct user_t *user)
2134 {
2135 int buf_len;
2136 char *command_buf;
2137 char buf[MAX_MESS_SIZE + 1];
2138 int i = 0;
2139
2140 command_buf = NULL;
2141
2142 /* Error or connection closed? */
2143 while(((buf_len = recv(user->sock, buf, MAX_MESS_SIZE, 0)) == -1)
2144 && ((errno == EAGAIN) || (errno == EINTR)))
2145 {
2146 i++;
2147 usleep(500);
2148 /* Giving up after half a second */
2149 if(i == 1000)
2150 break;
2151 }
2152
2153 if(buf_len <= 0)
2154 {
2155 /* Connection closed */
2156 if(buf_len == 0)
2157 {
2158 /* If it was a human user. */
2159 if((user->type & (SCRIPT | LINKED | FORKED)) == 0)
2160 {
2161 if((int)user->nick[0] > 0x20)
2162 logprintf(1, "%s from %s at socket %d hung up\n", user->nick, user->hostname, user->sock);
2163 else
2164 logprintf(1, "User at socket %d from %s hung up\n", user->sock, user->hostname);
2165 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2166 }
2167 else
2168 {
2169 /* If the parent process disconnected, exit this process. */
2170 if(pid <= 0)
2171 {
2172 if(count_users(SCRIPT | FORKED) == 1)
2173 kill_forked_process();
2174 }
2175
2176 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2177
2178 /* If it was a forked process, check if we have a listening
2179 * process. I we don't, we fork. */
2180 if((user->type == FORKED) && (get_listening_pid() == 0)
2181 && (pid > 0))
2182 do_fork = 1;
2183 }
2184 return 0;
2185 }
2186 else if(errno == ECONNRESET)
2187 {
2188 if((user->type & (SCRIPT | LINKED | FORKED)) == 0)
2189 {
2190 if((int)user->nick[0] > 0x20)
2191 logprintf(1, "%s from %s at socket %d hung up (Connection reset by peer)\n", user->nick, user->hostname, user->sock);
2192 else
2193 logprintf(1, "User at socket %d from %s hung up (Connection reset by peer)\n", user->sock, user->hostname);
2194 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2195 }
2196 else
2197 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2198 return 0;
2199 }
2200 else if(errno == ETIMEDOUT)
2201 {
2202 if((user->type & (SCRIPT | LINKED | FORKED)) == 0)
2203 {
2204 if((int)user->nick[0] > 0x20)
2205 logprintf(1, "%s from %s at socket %d hung up (Connection timed out)\n", user->nick, user->hostname, user->sock);
2206 else
2207 logprintf(1, "User at socket %d from %s hung up (Connection timed out)\n", user->sock, user->hostname);
2208 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2209 }
2210 else
2211 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2212 return 0;
2213 }
2214 else if(errno == EHOSTUNREACH)
2215 {
2216 if((user->type & (SCRIPT | LINKED | FORKED)) == 0)
2217 {
2218 if((int)user->nick[0] > 0x20)
2219 logprintf(1, "%s from %s at socket %d hung up (No route to host)\n", user->nick, user->hostname, user->sock);
2220 else
2221 logprintf(1, "User at socket %d from %s hung up (No route to host)\n", user->sock, user->hostname);
2222 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2223 }
2224 else
2225 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2226 return 0;
2227 }
2228 else
2229 {
2230 logprintf(4, "Error - In get_socket_action()/socket_action()/recv() when receiving from %s: ", user->hostname);
2231 logerror(4, errno);
2232 return -1;
2233 }
2234 }
2235 else
2236 {
2237 /* Set the char after the last received one in buf to null in case the memory
2238 * position was set to something else than null before */
2239 buf[buf_len] = '\0';
2240
2241 /* If the inbuf is empty */
2242 if(user->buf == NULL)
2243 {
2244 if((command_buf = malloc(sizeof(char) * (buf_len + 1))) == NULL)
2245 {
2246 logprintf(1, "Error - In socket_action()/malloc(): ");
2247 logerror(1, errno);
2248 quit = 1;
2249 return -1;
2250 }
2251 strcpy(command_buf, buf);
2252 if(strchr(command_buf, '|') != NULL)
2253 {
2254 if(handle_command(command_buf, user) == 0)
2255 {
2256 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2257 free(command_buf);
2258 return 0;
2259 }
2260 }
2261
2262 /* If the string doesn't contain the '|' at all */
2263 if(strchr(buf, '|') == NULL)
2264 {
2265 if((user->buf = malloc(sizeof(char) * (buf_len + 1))) == NULL)
2266 {
2267 logprintf(1, "Error - In socket_action()/malloc(): ");
2268 logerror(1, errno);
2269 quit = 1;
2270 free(command_buf);
2271 return -1;
2272 }
2273 strcpy(user->buf, buf);
2274 }
2275 else
2276 /* If the string continues after the last '|' */
2277 {
2278 if((user->buf = malloc(sizeof(char) * strlen(strrchr(buf, '|')))) == NULL)
2279 {
2280 logprintf(1, "Error - In socket_action()/malloc(): ");
2281 logerror(1, errno);
2282 quit = 1;
2283 free(command_buf);
2284 return -1;
2285 }
2286 strcpy(user->buf, strrchr(buf, '|') + 1);
2287 }
2288 }
2289 else
2290 /* We have something in the inbuf */
2291 {
2292 if((command_buf = malloc(sizeof(char) * (buf_len + strlen(user->buf) + 1))) == NULL)
2293 {
2294 logprintf(1, "Error - In socket_action()/malloc(): ");
2295 logerror(1, errno);
2296 quit = 1;
2297 return -1;
2298 }
2299 strcpy(command_buf, user->buf);
2300 strcat(command_buf, buf);
2301 if(strchr(command_buf, '|') != NULL)
2302 {
2303 if(handle_command(command_buf, user) == 0)
2304 {
2305 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2306 free(command_buf);
2307 return 0;
2308 }
2309 }
2310
2311 /* If the string doesn't contain a '|' */
2312 if(strchr(buf, '|') == NULL)
2313 {
2314 if((user->buf = realloc(user->buf, sizeof(char)
2315 * (buf_len + strlen(user->buf) + 1))) == NULL)
2316 {
2317 logprintf(1, "Error - In socket_action()/realloc(): ");
2318 logerror(1, errno);
2319 quit = 1;
2320 free(command_buf);
2321 return -1;
2322 }
2323 strcat(user->buf, buf);
2324
2325 /* The buf shouldn't be able to grow too much. If it gets
2326 * really big, it's probably due to some kind of attack */
2327 if(strlen(user->buf) >= MAX_BUF_SIZE)
2328 {
2329 if(user->rem == 0)
2330 logprintf(1, "User from %s had too big buf, kicking user\n", user->hostname);
2331 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2332 }
2333 }
2334
2335 /* If the string continues after the last '|' */
2336 else if(strlen(strrchr(buf, '|')) > 1)
2337 {
2338 if((user->buf = realloc(user->buf, sizeof(char)
2339 * strlen(strrchr(buf, '|')))) == NULL)
2340 {
2341 logprintf(1, "Error - In socket_action()/realloc(): ");
2342 logerror(1, errno);
2343 quit = 1;
2344 free(command_buf);
2345 return -1;
2346 }
2347 strcpy(user->buf, strrchr(buf, '|') + 1);
2348
2349 /* The buf shouldn't be able to grow too much. If it gets
2350 * really big, it's probably due to some kind of attack. */
2351 if(strlen(user->buf) >= MAX_BUF_SIZE)
2352 {
2353 if(user->rem == 0)
2354 logprintf(1, "User from %s had to big buf, kicking user\n", user->hostname);
2355 user->rem = REMOVE_USER | SEND_QUIT | REMOVE_FROM_LIST;
2356 }
2357 }
2358
2359
2360 /* The string ends with the '|' */
2361 else
2362 {
2363 free(user->buf);
2364 user->buf = NULL;
2365 }
2366 }
2367
2368 logprintf(5, "PID: %d Received command from %s, type 0x%X: %s\n",
2369 (int)getpid(), user->hostname, user->type, command_buf);
2370
2371 if(command_buf != NULL)
2372 free(command_buf);
2373
2374 return 1;
2375 }
2376 }
2377
2378 /* Handles udp packages. */
udp_action(void)2379 int udp_action(void)
2380 {
2381 int mess_len;
2382 int sin_len;
2383 char message[4096];
2384 struct sockaddr_in sin;
2385 struct user_t *user_list;
2386 struct hostent *ex_user;
2387 int i=0;
2388
2389 memset(&sin, 0, sizeof(struct sockaddr_in));
2390 sin_len = sizeof(struct sockaddr);
2391
2392 while(((mess_len = recvfrom(listening_udp_socket, message, sizeof(message), 0,
2393 (struct sockaddr *)&sin, &sin_len)) == -1)
2394 && ((errno == EAGAIN) || (errno == EINTR)))
2395 {
2396 i++;
2397 usleep(500);
2398 /* Giving up after half a second */
2399 if(i == 1000)
2400 break;
2401 }
2402
2403 if(mess_len <= 0)
2404 {
2405 logprintf(4, "Error - In udp_action()/recvfrom(): ");
2406 logerror(4, errno);
2407 return -1;
2408 }
2409
2410 message[mess_len] = '\0';
2411
2412 /* Check if user is in the list */
2413 user_list = non_human_user_list;
2414 while(user_list != NULL)
2415 {
2416 if(user_list->type == LINKED)
2417 {
2418 ex_user = gethostbyname(user_list->hostname);
2419 if((((struct in_addr *)ex_user->h_addr_list[0])->s_addr == sin.sin_addr.s_addr) && (user_list->key == ntohs(sin.sin_port)))
2420 {
2421 if(strncmp(message, "$Search ", 8) == 0)
2422 search(message, user_list);
2423 else if(strncmp(message, "$ConnectToMe ", 13) == 0)
2424 connect_to_me(message, user_list);
2425 }
2426 }
2427 user_list = user_list->next;
2428 }
2429
2430 if((strncmp(message, "$Up ", 4) == 0) || (strncmp(message, "$UpToo ", 7) == 0))
2431 up_cmd(message, ntohs(sin.sin_port));
2432
2433 logprintf(5, "Received udp packet from %s, port %d:\n%s\n",
2434 inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), message);
2435
2436 /* Send event to scripts */
2437 #ifdef HAVE_PERL
2438 command_to_scripts("$Script multi_hub_data_chunk_in %c%c", '\005', '\005');
2439 non_format_to_scripts(message);
2440 #endif
2441
2442 return 1;
2443 }
2444
2445
2446 /* Takes password and encrypts it. http://www.gnu.org/manual/glibc-2.2.5/html_node/crypt.html */
encrypt_pass(char * password)2447 void encrypt_pass(char* password)
2448 {
2449 unsigned long seed[2];
2450 char salt[] = "$1$........";
2451
2452 const char *const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2453
2454 int i;
2455
2456 seed[0] = time(NULL); /* Maybe using /dev/urandom. */
2457 seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
2458
2459 /* Turn it into printable characters from `seedchars'. */
2460 for (i = 0; i < 8; i++)
2461 salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
2462 if(crypt_enable != 0)
2463 strcpy(password, crypt(password, salt));
2464 }
2465
2466
2467
2468 /**********************************************************/
2469 /* Main function */
main(int argc,char * argv[])2470 int main(int argc, char *argv[])
2471 {
2472 int ret;
2473 int erret;
2474 int x;
2475 #ifdef SWITCH_USER
2476 struct passwd *userinfo;
2477 struct group *groupinfo;
2478 int got_user = 0;
2479 int got_group = 0;
2480 cap_t cap;
2481 int cap_failed = 0;
2482 cap_value_t caps[1];
2483 caps[0] = CAP_NET_BIND_SERVICE;
2484 #endif
2485
2486 max_sockets = getdtablesize();
2487
2488 #ifndef HAVE_POLL
2489 # ifdef FD_SETSIZE
2490 if(max_sockets > FD_SETSIZE)
2491 max_sockets = FD_SETSIZE;
2492 # endif
2493 #endif
2494
2495 /* Init some variables */
2496 listening_socket = -1;
2497 admin_listening_socket = -1;
2498 debug = 0;
2499 do_send_linked_hubs = 0;
2500 do_purge_user_list = 0;
2501 do_fork = 0;
2502 upload = 0;
2503 quit = 0;
2504 script_reload = 0;
2505 verbosity = 4;
2506 redir_on_min_share = 1;
2507 hub_full_mess = NULL;
2508 non_human_user_list = NULL;
2509 human_sock_list = NULL;
2510 memset(logfile, 0, MAX_FDP_LEN+1);
2511 syslog_enable = 0;
2512 syslog_switch = 0;
2513 searchcheck_exclude_internal = 0;
2514 searchcheck_exclude_all = 0;
2515 kick_bantime = 0;
2516 searchspam_time = 0;
2517 working_dir[0] = '\0';
2518 max_email_len = 50;
2519 max_desc_len = 100;
2520 crypt_enable = 1;
2521 current_forked = 1;
2522
2523 /* Parse arguments to program */
2524 for (x = 0; x < argc; x++)
2525 {
2526 /* Debug mode */
2527 if ((strcmp(argv[x], "-d")) == 0)
2528 debug = 1;
2529 #ifdef SWITCH_USER
2530 else if ((strcmp(argv[x], "-u")) == 0)
2531 {
2532 x++;
2533 userinfo = getpwnam(argv[x]);
2534 if(userinfo == NULL)
2535 {
2536 printf("Couldn't locate user: %s\n", argv[x]);
2537 perror("getpwnam");
2538 exit(EXIT_FAILURE);
2539 }
2540 dchub_user = userinfo->pw_uid;
2541 got_user = 1;
2542 if(got_group == 0)
2543 dchub_group = userinfo->pw_gid;
2544 }
2545 else if ((strcmp(argv[x], "-g")) == 0)
2546 {
2547 x++;
2548 groupinfo = getgrnam(argv[x]);
2549 if(groupinfo == NULL)
2550 {
2551 printf("Couldn't locate group: %s\n", argv[x]);
2552 perror("getgrnam");
2553 exit(EXIT_FAILURE);
2554 }
2555 dchub_group = groupinfo->gr_gid;
2556 got_group = 1;
2557 }
2558 #endif
2559 /* Print help and exit*/
2560 else if ((strcmp(argv[x], "-h")) == 0)
2561 {
2562 printf("\nOpen DC Hub, version %s\n", VERSION);
2563 printf(" -d : Debug mode. Also prevents Open DC Hub from making itself a\n background daemon.\n");
2564 printf(" -h : Print this help and exit.\n");
2565 printf(" --version : Print version.\n");
2566 printf(" -l <logfile> : Set logfile.\n");
2567 printf(" -s : Use syslog instead of a logfile.\n");
2568 printf(" -w <path> : Set the path to the working directory.\n");
2569 #ifdef SWITCH_USER
2570 printf(" -u <user> : User to switch to run as.\n");
2571 printf(" -g <group> : Group to switch to run as.\n");
2572 #endif
2573 exit(EXIT_SUCCESS);
2574 }
2575 /* Set logfile */
2576 else if ((strcmp(argv[x], "-l")) == 0)
2577 {
2578 x++;
2579 /* Check if argv[x] is usable as logfile. */
2580 if((ret = open(argv[x], O_RDWR | O_CREAT, 0600)) >= 0)
2581 {
2582 /* Set logfile. */
2583 strncpy(logfile,argv[x],MAX_FDP_LEN);
2584 printf("Using logfile: %s\n", logfile);
2585 close(ret);
2586 }
2587 else
2588 {
2589 printf("Couldn't open logfile: %s\n", argv[x]);
2590 perror("open");
2591 exit(EXIT_FAILURE);
2592 }
2593 }
2594 else if ((strcmp(argv[x], "-s")) == 0)
2595 {
2596 syslog_switch = 1;
2597 openlog(SYSLOG_IDENT, LOG_ODELAY, LOG_USER);
2598 }
2599 else if ((strcmp(argv[x], "-w")) == 0)
2600 {
2601 x++;
2602 strncpy(working_dir, argv[x], MAX_FDP_LEN);
2603 if((ret = access(working_dir, F_OK)) < 0)
2604 {
2605 printf("Directory does not exist: %s\n", argv[x]);
2606 perror("access");
2607 exit(EXIT_FAILURE);
2608 }
2609 }
2610 else if ((strcmp(argv[x], "--version"))== 0)
2611 {
2612 printf("Open DC Hub %s\n", VERSION);
2613 exit(EXIT_SUCCESS);
2614 }
2615 }
2616 #ifdef SWITCH_USER
2617 if (got_user)
2618 {
2619 if ((geteuid() == 0) && ((cap = cap_init()) != NULL))
2620 {
2621 if (prctl(PR_SET_KEEPCAPS, 1))
2622 cap_failed = 1;
2623 else if (setgroups(0, NULL) == -1)
2624 cap_failed = 1;
2625 else if ((setegid(dchub_group) == -1)
2626 || (seteuid(dchub_user) == -1))
2627 cap_failed = 1;
2628 else if (cap_set_flag(cap, CAP_EFFECTIVE, 1, caps, CAP_SET) == -1)
2629 cap_failed = 1;
2630 else if (cap_set_flag(cap, CAP_PERMITTED, 1, caps, CAP_SET) == -1)
2631 cap_failed = 1;
2632 else if (cap_set_flag(cap, CAP_INHERITABLE, 1, caps, CAP_SET) == -1)
2633 cap_failed = 1;
2634 else if (cap_set_proc(cap) == -1)
2635 cap_failed = 1;
2636 else if ((setresgid(dchub_group, dchub_group, dchub_group) == -1) ||
2637 (setresuid(dchub_user, dchub_user, dchub_user) == -1))
2638 cap_failed = 1;
2639 else if (setuid(0) == 0)
2640 cap_failed = 1;
2641 cap_free(cap);
2642 }
2643 else
2644 cap_failed = 1;
2645
2646 if(cap_failed != 0)
2647 {
2648 perror("Error in switching user\n");
2649 exit(EXIT_FAILURE);
2650 }
2651 }
2652 else
2653 {
2654 dchub_user = getuid();
2655 dchub_group = getgid();
2656 }
2657 #endif
2658
2659
2660 /* This is only a list of addresses to users, not users, so it won't be that
2661 * space consuming although this will use more memory than a linked list.
2662 * It's simply faster operation on behalf of more memory usage. */
2663 if((human_hash_table = calloc(max_sockets + 1, sizeof(struct user_t *))) == NULL)
2664 {
2665 printf("Couldn't initiate human_hash_table.\n");
2666 perror("calloc");
2667 exit(EXIT_FAILURE);
2668 }
2669
2670 if(init_dirs() == 0)
2671 return 1;
2672
2673 logprintf(1, "***Started Open DC Hub version %s***\n", VERSION);
2674 hub_start_time = time(NULL);
2675 if(read_config() == -1)
2676 {
2677 if(set_default_vars() == 0)
2678 {
2679 logprintf(1, "Failed setting config variables! Exiting\n");
2680 exit(EXIT_FAILURE);
2681 }
2682 if(write_config_file() == -1)
2683 {
2684 logprintf(1, "Failed writing config file! Exiting\n");
2685 exit(EXIT_FAILURE);
2686 }
2687 logprintf(1, "Created config file\n");
2688 }
2689 #ifdef HAVE_SYSLOG_H
2690 if((syslog_enable != 0) && (syslog_switch == 0))
2691 {
2692 logprintf(1, "***Switching to syslog***\n");
2693 openlog(SYSLOG_IDENT, LOG_ODELAY, LOG_USER);
2694 }
2695 #endif
2696 if((ret = write_motd("Welcome to the hub. Enjoy your stay.", 0)) == -1)
2697 {
2698 logprintf(1, "Failed creating motd file! Exiting\n");
2699 exit(EXIT_FAILURE);
2700 }
2701 else if(ret == 1)
2702 logprintf(1, "Created motd file\n");
2703
2704 create_banlist();
2705 create_nickbanlist();
2706 create_allowlist();
2707 create_reglist();
2708 create_linklist();
2709 create_op_permlist();
2710 if((int)hub_hostname[0] <= 0x20)
2711 if(set_hub_hostname() == -1)
2712 return 1;
2713
2714 /* Test if we can open the listening socket. */
2715 if((listening_socket = get_listening_socket(listening_port, 0)) == -1)
2716 {
2717 printf("Bind failed.\nRemember, to use a listening port below 1024, you need to be root.\nAlso, make sure that you don't have another instance of the program\nalready running.\n");
2718 close(listening_unx_socket);
2719 close(listening_udp_socket);
2720 return 1;
2721 }
2722
2723 while(((erret = close(listening_socket)) != 0) && (errno == EINTR))
2724 logprintf(1, "Error - main()/close(): Interrupted system call. Trying again.\n");
2725
2726 if(erret != 0)
2727 {
2728 logprintf(1, "Error - main/close(): ");
2729 perror("close");
2730 return 1;
2731 }
2732
2733 listening_socket = -1;
2734
2735 if((listening_unx_socket = get_listening_unx_socket()) == -1)
2736 return 1;
2737
2738 if((listening_udp_socket = get_listening_udp_socket(listening_port)) == -1)
2739 {
2740 printf("Bind failed.\nRemember, to use a listening port below 1024, you need to be root.\nAlso, make sure that you don't have another instance of the program\nalready running.\n");
2741 close(listening_unx_socket);
2742 return 1;
2743 }
2744
2745 /* Tell user that hub is running */
2746 printf("Hub is up and running. Listening for user connections on port %u\n", listening_port);
2747 if(admin_port != 0) {
2748 printf("and listening for admin connections on ");
2749 if(admin_localhost == 1) {
2750 printf("localhost port %u\n", admin_port);
2751 } else {
2752 printf("port %u\n", admin_port);
2753 }
2754 }
2755
2756 /* With -d, for debug, we will run in console so skip this part. */
2757 if(debug == 0)
2758 {
2759 /* Make program a daemon */
2760 pid = fork();
2761 if(pid < 0)
2762 {
2763 perror("fork");
2764 exit(EXIT_FAILURE);
2765 }
2766 if(pid > 0)
2767 exit(EXIT_SUCCESS);
2768 if(setsid() < 0)
2769 {
2770 perror("setsid");
2771 exit(EXIT_FAILURE);
2772 }
2773
2774 if(close(STDIN_FILENO) != 0)
2775 {
2776 logprintf(1, "Error - When closing STDIN_FILENO, exiting\n");
2777 exit(EXIT_FAILURE);
2778 }
2779 if(close(STDOUT_FILENO) != 0)
2780 {
2781 logprintf(1, "Error - When closing STDOUT_FILENO, exiting\n");
2782 exit(EXIT_FAILURE);
2783 }
2784 if(close(STDERR_FILENO) != 0)
2785 {
2786 logprintf(1, "Error - When closing STDERR_FILENO, exiting\n");
2787 exit(EXIT_FAILURE);
2788 }
2789 }
2790
2791 /* Set pid */
2792 pid = getpid();
2793
2794 /* Initialize the semaphores. */
2795 if(init_sem(&total_share_sem) == -1)
2796 {
2797 logprintf(1, "Couldn't initialize the total share semaphore.\n");
2798 exit(EXIT_FAILURE);
2799 }
2800
2801 if(init_sem(&user_list_sem) == -1)
2802 {
2803 logprintf(1, "Couldn't initialize the user list semaphore.\n");
2804 exit(EXIT_FAILURE);
2805 }
2806
2807 if(init_share_shm() == -1)
2808 {
2809 logprintf(1, "Couldn't initialize the total share shared memory segment.\n");
2810 semctl(total_share_sem, 0, IPC_RMID, NULL);
2811 semctl(user_list_sem, 0, IPC_RMID, NULL);
2812 }
2813
2814 if(init_user_list() == -1)
2815 {
2816 logprintf(1, "Couldn't initialize the user list.\n");
2817 semctl(total_share_sem, 0, IPC_RMID, NULL);
2818 semctl(user_list_sem, 0, IPC_RMID, NULL);
2819 }
2820
2821 init_sig();
2822
2823 /* Send initial alarm */
2824 if((kill(pid, SIGALRM)) < 0)
2825 {
2826 return 1;
2827 }
2828
2829 /* Init perl scripts */
2830 #ifdef HAVE_PERL
2831 if(perl_init() == 0)
2832 logprintf(1, "Error - Perl initialization failed.\n");
2833 else if(pid <= 0)
2834 sub_to_script("started_serving|");
2835
2836 #endif
2837
2838 /* Fork process which holds the listening sockets. */
2839 if(pid > 0)
2840 fork_process();
2841
2842 while(quit == 0)
2843 {
2844 if(pid > 0)
2845 {
2846 if((upload != 0) && (hublist_upload != 0))
2847 do_upload_to_hublist();
2848 if(do_write != 0)
2849 {
2850 write_config_file();
2851 do_write = 0;
2852 }
2853 if(do_send_linked_hubs != 0)
2854 {
2855 send_linked_hubs();
2856 do_send_linked_hubs = 0;
2857 }
2858 if(do_purge_user_list != 0)
2859 {
2860 purge_user_list();
2861 do_purge_user_list = 0;
2862 }
2863 #ifdef HAVE_PERL
2864 if(script_reload != 0)
2865 {
2866 perl_init();
2867 script_reload = 0;
2868 }
2869 #endif
2870 }
2871 get_socket_action();
2872 clear_user_list();
2873 if((do_fork == 1) && (pid > 0))
2874 {
2875 fork_process();
2876 do_fork = 0;
2877 }
2878 }
2879 quit_program();
2880 remove_all(0xFFFF, 0, 0);
2881 return 0;
2882 }
2883