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