1 /*
2  * ----------------------------------------------------------------
3  * ircproxy - Connection Configuration Functions
4  * ----------------------------------------------------------------
5  * Copyright (C) 1997-2009 Jonas Kvinge
6  *
7  * This file is part of ircproxy.
8  *
9  * ircproxy is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * ircproxy is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with ircproxy.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * Additional permission under GNU GPL version 3 section 7
23  *
24  * If you modify ircproxy, or any covered work, by linking or
25  * combining it with openssl (or a modified version of that library),
26  * containing parts covered by the terms of the OpenSSL License and the
27  * SSLeay License, the licensors of ircproxy grant you additional
28  * permission to convey the resulting work.
29  *
30  * $Id: conn_conf.c 54 2009-03-18 18:23:29Z jonasio $
31  *
32  */
33 
34 #define CONN_CONF_C
35 
36 #define NEED_SYS_TYPES_H 1		/* Extra types */
37 #define NEED_SYS_PARAM_H 1		/* Some systems need this */
38 #define NEED_LIMITS_H 0			/* Kernel limits */
39 #define NEED_STDARG_H 1			/* va_list, etc */
40 #define NEED_ERRNO_H 1			/* errno */
41 #define NEED_CTYPE_H 1			/* isdigit(), etc */
42 #define NEED_NETINET_IN_H 1		/* in_addr, sockaddr_in, etc */
43 #define NEED_ARPA_INET_H 0		/* inet_ntoa(), inet_aton(), etc */
44 #define NEED_STDIO_H 1			/* Standard C UNIX functions */
45 #define NEED_STDLIB_H 1			/* malloc(), exit(), atoi(), etc */
46 #define NEED_TIME_H 1			/* time(), etc */
47 #define NEED_SYSCTL_H 0			/* sysctl(), etc */
48 #define NEED_SYS_STAT_H 0		/* chmod(), mkdir(), etc */
49 #define NEED_SYS_UIO_H 0		/* iovec, etc */
50 #define NEED_FCNTL_H 1			/* open(), creat(), fcntl(), etc */
51 #define NEED_SYS_IOCTL_H 0		/* ioctl(), etc */
52 #define NEED_SYS_FILIO_H 0		/* Solaris need this for ioctl(), etc */
53 #define NEED_UNISTD_H 1			/* Unix standard functions */
54 #define NEED_STRING_H 1			/* C string functions */
55 #define NEED_SIGNAL_H 0			/* Signal functions */
56 #define NEED_SYS_SOCKET_H 0		/* Socket functions */
57 #define NEED_NETDB_H 0			/* Network database functions */
58 #define NEED_ARPA_NAMESER_H 0		/* Nameserver definitions */
59 #define NEED_GETUSERPW_HEADERS 0 	/* Functions to retrive system passwords */
60 #define NEED_ARES 0			/* Functions needed for ares */
61 #define NEED_SSL 1			/* Needed for SSL support */
62 
63 #include "includes.h"
64 #include "irc.h"
65 
66 #include "conf.h"
67 
68 #include "conn_conf.h"
69 #include "conn.h"
70 
71 /* VARIABLES - JONAS (31.07.2001) */
72 
73 unsigned long int ConnConfs = 0;
74 
75 struct ConnConf_Struct *ConnConf_Head = NULL;
76 struct ConnConf_Struct *ConnConf_Tail = NULL;
77 
78 extern struct Conf_Struct ConfS;
79 extern unsigned short int Root;
80 
81 /* CONN_CONF_READ FUNCTION - JONAS (31.07.2001) */
82 
conn_conf_read(void)83 signed long int conn_conf_read(void) {
84 
85   char File[FILELEN+1] = "";
86   FILE *FilePT = NULL;
87 
88   char *TempPT = NULL;
89 
90   char Line[LINELEN+1] = "";
91   char *LinePT = NULL;
92 
93   unsigned short int Count = 0;
94 
95   char *EntryPT = NULL;
96 
97   struct ConnConf_Struct *ConnConf = NULL;
98   struct ConnConfServer_Struct *ConnConfServer = NULL;
99 
100   struct Conn_Struct *ConnS = NULL;
101 
102   unsigned short int NextLineIsAServer = 0;
103   unsigned short int UnsignedShortInt = 0;
104 
105   DEBUGPRINT(BITMASK_DEBUG_CONF, "Reading connection configuration file.");
106 
107   if (ConfS.ConnConfFile[0] != '/') {
108     strncat(File, ConfS.DataPath, FILELEN);
109     if (ConfS.DataPath[strlen(ConfS.DataPath)] != '/') { strncat(File, "/", (FILELEN - strlen(File))); }
110   }
111   strncat(File, ConfS.ConnConfFile, (FILELEN - strlen(File)));
112 
113   FilePT = fopen(File, "r");
114   if (FilePT == NULL) {
115     sysprint(BITMASK_ERROR, "Unable to open connection configuration file %s: [%d] %s", File, errno, strerror(errno));
116     return(ERROR);
117   }
118 
119   conn_conf_destroy();
120 
121   FOREVERLOOP {
122 
123     memset(&Line, 0, LINELEN+1);
124     TempPT = fgets(Line, LINELEN, FilePT);
125     if (TempPT == NULL) { break; }
126     ++Count;
127     LinePT = Line;
128 
129     while ((TempPT = strchr(LinePT, '\r')) != NULL) { *TempPT = '\0'; }
130     while ((TempPT = strchr(LinePT, '\n')) != NULL) { *TempPT = '\0'; }
131     while ((TempPT = strchr(LinePT, '\t')) != NULL) { *TempPT = ' '; }
132 
133     while ((LinePT[0] == ' ') || (LinePT[0] == '\t')) { ++LinePT; }
134     if ((LinePT[0] == '#') || (LinePT[0] == ';') || (LinePT[0] == '\0')) { continue; }
135 
136     EntryPT = LinePT;
137     StrMovePastToken(LinePT, ' ');
138 
139     if (NextLineIsAServer == TRUE) {
140 
141       char *HostPT = CONN_CONF_SERVERHOST_DEFAULT;
142       char *PortPT = CONN_CONF_SERVERPORT_DEFAULT;
143       char *PassPT = CONN_CONF_SERVERPASS_DEFAULT;
144 
145       if (EntryPT[0] == '}') { /* End of server list */
146         NextLineIsAServer = FALSE;
147         continue;
148       }
149 
150       HostPT = EntryPT;
151       StrMovePastToken(EntryPT, ':');
152 
153       if (EntryPT != NULL) {
154         PortPT = EntryPT;
155         StrMovePastToken(EntryPT, ':');
156       }
157 
158       if (LinePT != NULL) {
159         PassPT = LinePT;
160         StrMovePastToken(EntryPT, ':');
161       }
162 
163       if (ConnConf != NULL) conn_conf_addserver(ConnConf, HostPT, strtoul(PortPT, NULL, 0), PassPT);
164       continue;
165     }
166 
167     if (strcasecmp(EntryPT, "CONNECTION") == FALSE) {
168 
169       char *NamePT = NULL;
170 
171       if (LinePT == NULL) {
172         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Expecting connection name for \"CONNECTION\" definition.", File, Count);
173         continue;
174       }
175       NamePT = LinePT;
176       StrMovePastToken(LinePT, ' ');
177       ConnConf = conn_conf_add(NamePT);
178       assert(ConnConf != NULL);
179       continue;
180     }
181     if (EntryPT[0] == '}') { ConnConf = NULL; continue; } /* End of connection */
182 
183     if (ConnConf == NULL) {
184       sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Entry \"%s\" is invalid before a \"CONNECTION <Name> {\" definition.", File, Count, EntryPT);
185       continue;
186     }
187 
188     if (strcasecmp(EntryPT, "NICK") == FALSE) {
189       if (LinePT == NULL) {
190         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in NICK definition.", File, Count);
191         continue;
192       }
193       ConnConf->Nick = strrealloc(ConnConf->Nick, LinePT);
194       continue;
195     }
196     else if (strcasecmp(EntryPT, "AWAYNICK") == FALSE) {
197       if (LinePT == NULL) {
198         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in AWAYNICK definition.", File, Count);
199         continue;
200       }
201       ConnConf->AwayNick = strrealloc(ConnConf->AwayNick, LinePT);
202       continue;
203     }
204     else if (strcasecmp(EntryPT, "USER") == FALSE) {
205       if (LinePT == NULL) {
206         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in USER definition.", File, Count);
207         continue;
208       }
209       ConnConf->User = strrealloc(ConnConf->User, LinePT);
210       continue;
211     }
212     else if (strcasecmp(EntryPT, "HOST") == FALSE) {
213       if (LinePT == NULL) {
214         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in HOST definition.", File, Count);
215         continue;
216       }
217       ConnConf->Host = strrealloc(ConnConf->Host, LinePT);
218       continue;
219     }
220     else if (strcasecmp(EntryPT, "SERVERS") == FALSE) {
221       if (LinePT == NULL) {
222         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing \"{\" in SERVERS definition.", File, Count);
223         continue;
224       }
225       if (LinePT[0] == '{') { NextLineIsAServer = TRUE; continue; }
226       sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Invalid SERVERS definition.", File, Count);
227       continue;
228     }
229     else if ((strcasecmp(EntryPT, "MODE") == FALSE) || (strcasecmp(EntryPT, "USERMODE") == FALSE)) {
230       if (LinePT == NULL) {
231         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in USERMODE definition.", File, Count);
232         continue;
233       }
234       ConnConf->Mode = strrealloc(ConnConf->Mode, LinePT);
235       continue;
236     }
237     else if ((strcasecmp(EntryPT, "INFO") == FALSE) || (strcasecmp(EntryPT, "USERINFO") == FALSE)) {
238       if (LinePT == NULL) {
239         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in USERINFO definition.", File, Count);
240         continue;
241       }
242       ConnConf->Info = strrealloc(ConnConf->Info, LinePT);
243       continue;
244     }
245     else if ((strcasecmp(EntryPT, "CHANS") == FALSE) || (strcasecmp(EntryPT, "CHANNELS") == FALSE)) {
246       if (LinePT == NULL) {
247         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in CHANNELS definition.", File, Count);
248         continue;
249       }
250       ConnConf->Chans = strrealloc(ConnConf->Chans, LinePT);
251       continue;
252     }
253     else if (strcasecmp(EntryPT, "IPV6") == FALSE) {
254       if (LinePT == NULL) {
255         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for IPV6 definition.", File, Count);
256         continue;
257       }
258       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_IPV6; }
259       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_IPV6; }
260       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: IPV6 definition must be yes/no or 1/0.", File, Count); }
261       continue;
262     }
263     else if (strcasecmp(EntryPT, "SSL") == FALSE) {
264       if (LinePT == NULL) {
265         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for SSL definition.", File, Count);
266         continue;
267       }
268       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_SSL; }
269       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_SSL; }
270       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: SSL definition must be yes/no or 1/0.", File, Count); }
271       continue;
272     }
273     else if (strcasecmp(EntryPT, "AUTOCONNECT") == FALSE) {
274       if (LinePT == NULL) {
275         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for AUTOCONNECT definition.", File, Count);
276         continue;
277       }
278       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_AUTOCONNECT; }
279       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_AUTOCONNECT; }
280       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: AUTOCONNECT definition must be yes/no or 1/0.", File, Count); }
281       continue;
282     }
283     else if (strcasecmp(EntryPT, "LOGGING") == FALSE) {
284       if (LinePT == NULL) {
285         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for LOGGING definition.", File, Count);
286         continue;
287       }
288       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_LOGGING; }
289       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_LOGGING; }
290       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: LOGGING definition must be yes/no or 1/0.", File, Count); }
291       continue;
292     }
293     else if (strcasecmp(EntryPT, "AUTOAWAY") == FALSE) {
294       if (LinePT == NULL) {
295         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for AUTOAWAY definition.", File, Count);
296         continue;
297       }
298       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_AUTOAWAY; }
299       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_AUTOAWAY; }
300       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: AUTOAWAY definition must be yes/no or 1/0.", File, Count); }
301       continue;
302     }
303     else if (strcasecmp(EntryPT, "PUBLICAWAY") == FALSE) {
304       if (LinePT == NULL) {
305         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for PUBLICAWAY definition.", File, Count);
306         continue;
307       }
308       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_PUBLICAWAY; }
309       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_PUBLICAWAY; }
310       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: PUBLICAWAY definition must be yes/no or 1/0.", File, Count); }
311       continue;
312     }
313     else if (strcasecmp(EntryPT, "REGAINNICK") == FALSE) {
314       if (LinePT == NULL) {
315         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for REGAINNICK definition.", File, Count);
316         continue;
317       }
318       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_REGAINNICK; }
319       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_REGAINNICK; }
320       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: REGAINNICK definition must be yes/no or 1/0.", File, Count); }
321       continue;
322     }
323     else if ((strcasecmp(EntryPT, "MAXCLIENTS") == FALSE) || (strcasecmp(EntryPT, "MAXUSERS") == FALSE)) {
324       if (LinePT == NULL) {
325         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing numeric for MAXUSERS definition.", File, Count);
326         continue;
327       }
328       UnsignedShortInt = atoi(LinePT);
329       ConnConf->MaxClients = UnsignedShortInt;
330       continue;
331     }
332     else if (strcasecmp(EntryPT, "MAXSENDLINES") == FALSE) {
333       char *SendMaxLinesPT = NULL;
334       char *SendLineTimePT = NULL;
335       if (LinePT == NULL) {
336         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: The MAXSENDLINES definition must be followed by an \"Lines:Time\" entry.", File, Count);
337         continue;
338       }
339       SendMaxLinesPT = LinePT;
340       StrMovePastToken(LinePT, ':');
341       if (LinePT == NULL) {
342         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: The MAXSENDLINES definition must be followed by an \"Lines:Time\" entry.", File, Count);
343         continue;
344       }
345       SendLineTimePT = LinePT;
346       ConnConf->SendMaxLines = atoi(SendMaxLinesPT);
347       ConnConf->SendLineTime = atoi(SendLineTimePT);
348       continue;
349     }
350     else if (strcasecmp(EntryPT, "MAXSENDBUFFER") == FALSE) {
351       char *SendMaxBufferPT = NULL;
352       char *SendBufferTimePT = NULL;
353       if (LinePT == NULL) {
354         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: The MAXSENDBUFFER definition must be followed by an \"Buffer:Time\" entry.", File, Count);
355         continue;
356       }
357       SendMaxBufferPT = LinePT;
358       StrMovePastToken(LinePT, ':');
359       if (LinePT == NULL) {
360         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: The MAXSENDBUFFER definition must be followed by an \"Buffer:Time\" entry.", File, Count);
361         continue;
362       }
363       SendBufferTimePT = LinePT;
364       ConnConf->SendMaxBuffer = atoi(SendMaxBufferPT);
365       ConnConf->SendBufferTime = atoi(SendBufferTimePT);
366       continue;
367     }
368     else if (strcasecmp(EntryPT, "AWAYMSG") == FALSE) {
369       if (LinePT == NULL) {
370         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in AWAYMSG definition.", File, Count);
371         continue;
372       }
373       ConnConf->AwayMsg = strrealloc(ConnConf->AwayMsg, LinePT);
374       continue;
375     }
376     else if ((strcasecmp(EntryPT, "PUBLICDETACHMSG") == FALSE) || (strcasecmp(EntryPT, "PUBLICAWAYMSG") == FALSE)) {
377       if (LinePT == NULL) {
378         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in PUBLICDETACHMSG definition.", File, Count);
379         continue;
380       }
381       ConnConf->PublicDetachMsg = strrealloc(ConnConf->PublicDetachMsg, LinePT);
382       continue;
383     }
384     else if ((strcasecmp(EntryPT, "PUBLICATTACHMSG") == FALSE) || (strcasecmp(EntryPT, "PUBLICBACKMSG") == FALSE)) {
385       if (LinePT == NULL) {
386         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in PUBLICATTACHMSG definition.", File, Count);
387         continue;
388       }
389       ConnConf->PublicAttachMsg = strrealloc(ConnConf->PublicAttachMsg, LinePT);
390       continue;
391     }
392     else if (strcasecmp(EntryPT, "CHANCYCLE") == FALSE) {
393       if (LinePT == NULL) {
394         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for CHANCYCLE definition.", File, Count);
395         continue;
396       }
397       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_CHANCYCLE; }
398       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_CHANCYCLE; }
399       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: CHANCYCLE definition must be yes/no or 1/0.", File, Count); }
400       continue;
401     }
402     else if (strcasecmp(EntryPT, "NICKSERVNUH") == FALSE) {
403       if (LinePT == NULL) {
404         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in NICKSERVNUH definition.", File, Count);
405         continue;
406       }
407       ConnConf->NickServNUH = strrealloc(ConnConf->NickServNUH, LinePT);
408       continue;
409     }
410     else if (strcasecmp(EntryPT, "NICKSERVPASS") == FALSE) {
411       if (LinePT == NULL) {
412         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in NICKSERVPASS definition.", File, Count);
413         continue;
414       }
415       ConnConf->NickServPass = strrealloc(ConnConf->NickServPass, LinePT);
416       continue;
417     }
418     else if (strcasecmp(EntryPT, "NICKSERVTEXT") == FALSE) {
419       if (LinePT == NULL) {
420         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in NICKSERVTEXT definition.", File, Count);
421         continue;
422       }
423       ConnConf->NickServText = strrealloc(ConnConf->NickServText, LinePT);
424       continue;
425     }
426     else if (strcasecmp(EntryPT, "AUTOATTACH") == FALSE) {
427       if (LinePT == NULL) {
428         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for AUTOATTACH definition.", File, Count);
429         continue;
430       }
431       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_AUTOATTACH; }
432       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_AUTOATTACH; }
433       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: AUTOATTACH definition must be yes/no or 1/0.", File, Count); }
434       continue;
435     }
436 
437     else if (strcasecmp(EntryPT, "RAWLOG") == FALSE) {
438       if (LinePT == NULL) {
439         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing 0 or 1 for RAWLOG definition.", File, Count);
440         continue;
441       }
442       if ((strcasecmp(LinePT, "y") == FALSE) || (strcasecmp(LinePT, "yes") == FALSE) || (strcasecmp(LinePT, "1") == FALSE)) { ConnConf->ConfFlags |= CONN_CONF_BITMASK_RAWLOG; }
443       else if ((strcasecmp(LinePT, "n") == FALSE) || (strcasecmp(LinePT, "no") == FALSE) || (strcasecmp(LinePT, "0") == FALSE)) { ConnConf->ConfFlags &= ~CONN_CONF_BITMASK_RAWLOG; }
444       else { sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: RAWLOG definition must be yes/no or 1/0.", File, Count); }
445       continue;
446     }
447 
448 
449 
450     else if (strcasecmp(EntryPT, "CHANLOG") == FALSE) {
451       if (LinePT == NULL) {
452         sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Missing data in CHANLOG definition.", File, Count);
453         continue;
454       }
455       for (; *LinePT != '\0' ; LinePT++) {
456         switch(*LinePT) {
457           case IRC_EVENT_PRIVMSG:
458             ConnConf->ChanLogFlags |= IRC_BITMASK_PRIVMSG;
459             break;
460           case IRC_EVENT_ACTION:
461             ConnConf->ChanLogFlags |= IRC_BITMASK_ACTION;
462             break;
463           case IRC_EVENT_CTCP:
464             ConnConf->ChanLogFlags |= IRC_BITMASK_CTCP;
465             break;
466           case IRC_EVENT_NOTICE:
467             ConnConf->ChanLogFlags |= IRC_BITMASK_NOTICE;
468             break;
469           case IRC_EVENT_NICK:
470             ConnConf->ChanLogFlags |= IRC_BITMASK_NICK;
471             break;
472           case IRC_EVENT_QUIT:
473             ConnConf->ChanLogFlags |= IRC_BITMASK_QUIT;
474             break;
475           case IRC_EVENT_MODE:
476             ConnConf->ChanLogFlags |= IRC_BITMASK_MODE;
477             break;
478           case IRC_EVENT_JOIN:
479             ConnConf->ChanLogFlags |= IRC_BITMASK_JOIN;
480             break;
481           case IRC_EVENT_PART:
482             ConnConf->ChanLogFlags |= IRC_BITMASK_PART;
483             break;
484           case IRC_EVENT_KICK:
485             ConnConf->ChanLogFlags |= IRC_BITMASK_KICK;
486             break;
487           case IRC_EVENT_TOPIC:
488             ConnConf->ChanLogFlags |= IRC_BITMASK_TOPIC;
489             break;
490           case '*':
491             ConnConf->ChanLogFlags |= IRC_BITMASK_PRIVMSG;
492             ConnConf->ChanLogFlags |= IRC_BITMASK_ACTION;
493             ConnConf->ChanLogFlags |= IRC_BITMASK_CTCP;
494             ConnConf->ChanLogFlags |= IRC_BITMASK_NOTICE;
495             ConnConf->ChanLogFlags |= IRC_BITMASK_NICK;
496             ConnConf->ChanLogFlags |= IRC_BITMASK_QUIT;
497             ConnConf->ChanLogFlags |= IRC_BITMASK_MODE;
498             ConnConf->ChanLogFlags |= IRC_BITMASK_JOIN;
499             ConnConf->ChanLogFlags |= IRC_BITMASK_PART;
500             ConnConf->ChanLogFlags |= IRC_BITMASK_KICK;
501             ConnConf->ChanLogFlags |= IRC_BITMASK_TOPIC;
502             break;
503           default:
504             break;
505         }
506       }
507       continue;
508     }
509 
510 
511 #if 0
512     sysprint(BITMASK_ERROR, "Connection configuration error, file %s line %d: Unknown entry \"%s\" for CONNECTION definition.", File, Count, EntryPT);
513 #endif
514 
515   }
516   fclose(FilePT);
517 
518   for (ConnConf = ConnConf_Head ; ConnConf != NULL ; ConnConf = ConnConf->Next) {
519     DEBUGPRINT(BITMASK_DEBUG_CONF, "Adding connection: Name: %s - Nick: %s - Away Nick: %s - User: %s - Host: %s - Mode: %s - Info: %s - Chans: %s - Max Users: %d - Send Max Lines: %d - Send Line Time: %d - Send Max Buffer: %d - Send Buffer Time: %d.", ConnConf->Name, ConnConf->Nick, ConnConf->AwayNick, ConnConf->User, ConnConf->Host, ConnConf->Mode, ConnConf->Info, ConnConf->Chans, ConnConf->MaxClients, ConnConf->SendMaxLines, ConnConf->SendLineTime, ConnConf->SendMaxBuffer, ConnConf->SendBufferTime);
520     if ((ConfS.UnixPasswd == TRUE) && (Root == TRUE)) {
521       sysgetuidfromuser(ConnConf->User);
522       if (aerrno != AESUCCESS) {
523         sysprint(BITMASK_ERROR, "Connection configuration error, connection %s: Owner of connection user \"%s\" does not exist in %s.", ConnConf->Name, ConnConf->User, PASSWD_FILE);
524       }
525     }
526     ConnS = conn_add(ConnConf);
527     assert(ConnS != NULL);
528     for (ConnConfServer = ConnConf->Server_Head ; ConnConfServer != NULL ; ConnConfServer = ConnConfServer->Next) {
529       DEBUGPRINT(BITMASK_DEBUG_CONF, "Adding connection %s server: Host: %s - Port: %ld -.", ConnConf->Name, ConnConfServer->Host, ConnConfServer->Port);
530       conn_addserver(ConnS, ConnConfServer->Host, ConnConfServer->Port, ConnConfServer->Pass);
531     }
532   }
533 
534   return(ConnConfs);
535 
536 }
537 
538 /* CONN_CONF_ADD - JONAS (31.07.2001) */
539 
conn_conf_add(const char * const NamePT)540 struct ConnConf_Struct *conn_conf_add(const char *const NamePT) {
541 
542   struct ConnConf_Struct *ConnConf = NULL;
543   struct ConnConf_Struct *ConnConf_NEW = NULL;
544 
545   assert(NamePT != NULL);
546 
547   ConnConf = conn_conf_get(NamePT);
548   if (ConnConf != NULL) {
549     aerrno = AEEXISTS;
550     return(ConnConf);
551   }
552 
553   ConnConf_NEW = malloc(sizeof(struct ConnConf_Struct));
554   if (ConnConf_NEW == NULL) {
555     aerrno = AEMALLOC;
556     return(NULL);
557   }
558 
559   memset(ConnConf_NEW, 0, sizeof(struct ConnConf_Struct));
560 
561   ConnConf_NEW->Name = strdup(NamePT);
562   ConnConf_NEW->Nick = strdup(CONN_CONF_NICK_DEFAULT);
563   ConnConf_NEW->AwayNick = strdup(CONN_CONF_AWAYNICK_DEFAULT);
564   ConnConf_NEW->User = strdup(CONN_CONF_USER_DEFAULT);
565   ConnConf_NEW->Host = strdup(CONN_CONF_HOST_DEFAULT);
566   ConnConf_NEW->Mode = strdup(CONN_CONF_USERMODE_DEFAULT);
567   ConnConf_NEW->Info = strdup(CONN_CONF_USERINFO_DEFAULT);
568   ConnConf_NEW->Chans = strdup(CONN_CONF_CHANS_DEFAULT);
569   ConnConf_NEW->AwayMsg = strdup(CONN_CONF_AWAYMSG_DEFAULT);
570   ConnConf_NEW->PublicDetachMsg = strdup(CONN_CONF_PUBLICAWAYMSG_DEFAULT);
571   ConnConf_NEW->PublicAttachMsg = strdup(CONN_CONF_PUBLICBACKMSG_DEFAULT);
572   ConnConf_NEW->NickServNUH = strdup(CONN_CONF_NICKSERVNUH_DEFAULT);
573   ConnConf_NEW->NickServPass = strdup(CONN_CONF_NICKSERVPASS_DEFAULT);
574   ConnConf_NEW->NickServText = strdup(CONN_CONF_NICKSERVTEXT_DEFAULT);
575 
576   if (
577      (ConnConf_NEW->Name == NULL) ||
578      (ConnConf_NEW->Nick == NULL) ||
579      (ConnConf_NEW->AwayNick == NULL) ||
580      (ConnConf_NEW->User == NULL) ||
581      (ConnConf_NEW->Host == NULL) ||
582      (ConnConf_NEW->Mode == NULL) ||
583      (ConnConf_NEW->Info == NULL) ||
584      (ConnConf_NEW->Chans == NULL) ||
585      (ConnConf_NEW->AwayMsg == NULL) ||
586      (ConnConf_NEW->PublicDetachMsg == NULL) ||
587      (ConnConf_NEW->PublicAttachMsg == NULL) ||
588      (ConnConf_NEW->NickServNUH == NULL) ||
589      (ConnConf_NEW->NickServPass == NULL) ||
590      (ConnConf_NEW->NickServText == NULL)
591     ) {
592     free(ConnConf_NEW->Name);
593     free(ConnConf_NEW->Nick);
594     free(ConnConf_NEW->AwayNick);
595     free(ConnConf_NEW->User);
596     free(ConnConf_NEW->Host);
597     free(ConnConf_NEW->Mode);
598     free(ConnConf_NEW->Info);
599     free(ConnConf_NEW->Chans);
600     free(ConnConf_NEW->AwayMsg);
601     free(ConnConf_NEW->PublicDetachMsg);
602     free(ConnConf_NEW->PublicAttachMsg);
603     free(ConnConf_NEW->NickServNUH);
604     free(ConnConf_NEW->NickServPass);
605     free(ConnConf_NEW->NickServText);
606     free(ConnConf_NEW);
607     aerrno = AEMALLOC;
608     return(NULL);
609   }
610 
611   ConnConf_NEW->MaxClients = CONN_CONF_MAXCLIENTS_DEFAULT;
612   ConnConf_NEW->SendMaxLines = CONN_CONF_SENDMAXLINES_DEFAULT;
613   ConnConf_NEW->SendLineTime = CONN_CONF_SENDLINETIME_DEFAULT;
614   ConnConf_NEW->SendMaxBuffer = CONN_CONF_SENDMAXBUFFER_DEFAULT;
615   ConnConf_NEW->SendBufferTime = CONN_CONF_SENDBUFFERTIME_DEFAULT;
616 
617   if (ConnConf_Head == NULL) {
618     ConnConf_Head = ConnConf_NEW;
619     ConnConf_Tail = ConnConf_NEW;
620   }
621   else {
622     ConnConf = ConnConf_Tail;
623     ConnConf->Next = ConnConf_NEW;
624     ConnConf_NEW->Prev = ConnConf;
625     ConnConf_Tail = ConnConf_NEW;
626   }
627 
628   ConnConfs++;
629 
630   aerrno = AESUCCESS;
631   return(ConnConf_NEW);
632 
633 }
634 
635 /* CONN_CONF_REM FUNCTION - JONAS (31.07.2001) */
636 
conn_conf_rem(struct ConnConf_Struct * ConnConf)637 void conn_conf_rem(struct ConnConf_Struct *ConnConf) {
638 
639   assert(ConnConf != NULL);
640 
641   if (ConnConf->Prev == NULL) { ConnConf_Head = ConnConf->Next; }
642   else { ConnConf->Prev->Next = ConnConf->Next; }
643 
644   if (ConnConf->Next == NULL) { ConnConf_Tail = ConnConf->Prev; }
645   else { ConnConf->Next->Prev = ConnConf->Prev; }
646 
647   conn_conf_remservers(ConnConf);
648 
649   free(ConnConf->Name);
650   free(ConnConf->Nick);
651   free(ConnConf->AwayNick);
652   free(ConnConf->User);
653   free(ConnConf->Host);
654   free(ConnConf->Mode);
655   free(ConnConf->Info);
656   free(ConnConf->Chans);
657   free(ConnConf->AwayMsg);
658   free(ConnConf->PublicDetachMsg);
659   free(ConnConf->PublicAttachMsg);
660   free(ConnConf->NickServNUH);
661   free(ConnConf->NickServPass);
662   free(ConnConf->NickServText);
663   free(ConnConf);
664 
665   ConnConfs--;
666 
667 }
668 
669 /* CONN_CONF_GET FUNCTION - JONAS (31.07.2001) */
670 
conn_conf_get(const char * const NamePT)671 struct ConnConf_Struct *conn_conf_get(const char *const NamePT) {
672 
673   struct ConnConf_Struct *ConnConf = NULL;
674 
675   assert(NamePT != NULL);
676 
677   for (ConnConf = ConnConf_Head ; ConnConf != NULL ; ConnConf = ConnConf->Next) {
678     if (strcasecmp(ConnConf->Name, NamePT) == FALSE) {
679       aerrno = AESUCCESS;
680       return(ConnConf);
681     }
682   }
683   aerrno = AENOMATCH;
684   return(NULL);
685 
686 }
687 
688 /* CONN_CONF_DESTROY FUNCTION - JONAS (31.07.2001) */
689 
conn_conf_destroy(void)690 void conn_conf_destroy(void) {
691 
692   while (ConnConf_Head != NULL) { conn_conf_rem(ConnConf_Head); }
693 
694 }
695 
696 /* CONN_CONF_ADDSERVER - JONAS (31.07.2001) */
697 
conn_conf_addserver(struct ConnConf_Struct * ConnConf,const char * const HostPT,const unsigned long int Port,const char * const PassPT)698 struct ConnConfServer_Struct *conn_conf_addserver(struct ConnConf_Struct *ConnConf, const char *const HostPT, const unsigned long int Port, const char *const PassPT) {
699 
700   struct ConnConfServer_Struct *ConnConfServer = NULL;
701   struct ConnConfServer_Struct *ConnConfServer_NEW = NULL;
702 
703   assert(ConnConf != NULL);
704   assert(HostPT != NULL);
705   assert(PassPT != NULL);
706 
707   ConnConfServer = conn_conf_getserver(ConnConf, HostPT);
708   if (ConnConfServer != NULL) {
709     aerrno = AEEXISTS;
710     return(ConnConfServer);
711   }
712 
713   ConnConfServer_NEW = malloc(sizeof(struct ConnConfServer_Struct));
714   if (ConnConfServer_NEW == NULL) {
715     aerrno = AEMALLOC;
716     return(NULL);
717   }
718 
719   memset(ConnConfServer_NEW, 0, sizeof(struct ConnConfServer_Struct));
720 
721   ConnConfServer_NEW->Host = strdup(HostPT);
722   ConnConfServer_NEW->Pass = strdup(PassPT);
723   ConnConfServer_NEW->Port = Port;
724 
725   if ((ConnConfServer_NEW->Host == NULL) || (ConnConfServer_NEW->Pass == NULL)) {
726     free(ConnConfServer_NEW->Host);
727     free(ConnConfServer_NEW->Pass);
728     free(ConnConfServer_NEW);
729     aerrno = AEMALLOC;
730     return(NULL);
731   }
732 
733   if (ConnConf->Server_Head == NULL) {
734     ConnConf->Server_Head = ConnConfServer_NEW;
735     ConnConf->Server_Tail = ConnConfServer_NEW;
736   }
737   else {
738     ConnConfServer = ConnConf->Server_Tail;
739     ConnConfServer->Next = ConnConfServer_NEW;
740     ConnConfServer_NEW->Prev = ConnConfServer;
741     ConnConf->Server_Tail = ConnConfServer_NEW;
742   }
743 
744   ConnConf->Servers++;
745 
746   aerrno = AESUCCESS;
747   return(ConnConfServer_NEW);
748 
749 }
750 
751 /* CONN_CONF_REMSERVER FUNCTION - JONAS (31.07.2001) */
752 
conn_conf_remserver(struct ConnConf_Struct * ConnConf,struct ConnConfServer_Struct * ConnConfServer)753 void conn_conf_remserver(struct ConnConf_Struct *ConnConf, struct ConnConfServer_Struct *ConnConfServer) {
754 
755   assert(ConnConf != NULL);
756   assert(ConnConfServer != NULL);
757 
758   if (ConnConfServer->Prev == NULL) { ConnConf->Server_Head = ConnConfServer->Next; }
759   else { ConnConfServer->Prev->Next = ConnConfServer->Next; }
760 
761   if (ConnConfServer->Next == NULL) { ConnConf->Server_Tail = ConnConfServer->Prev; }
762   else { ConnConfServer->Next->Prev = ConnConfServer->Prev; }
763 
764   free(ConnConfServer->Pass);
765   free(ConnConfServer->Host);
766   free(ConnConfServer);
767   ConnConf->Servers--;
768 
769 }
770 
771 /* CONN_CONF_GET FUNCTION - JONAS (31.07.2001) */
772 
conn_conf_getserver(struct ConnConf_Struct * ConnConf,const char * const HostPT)773 struct ConnConfServer_Struct *conn_conf_getserver(struct ConnConf_Struct *ConnConf, const char *const HostPT) {
774 
775   struct ConnConfServer_Struct *ConnConfServer = NULL;
776 
777   assert(ConnConf != NULL);
778   assert(HostPT != NULL);
779 
780   for (ConnConfServer = ConnConf->Server_Head ; ConnConfServer != NULL ; ConnConfServer = ConnConfServer->Next) {
781     if (strcasecmp(ConnConfServer->Host, HostPT) == FALSE) {
782       aerrno = AESUCCESS;
783       return(ConnConfServer);
784     }
785   }
786   aerrno = AENOMATCH;
787   return(NULL);
788 
789 }
790 
791 /* CONN_CONF_REMSERVERS FUNCTION - JONAS (31.07.2001) */
792 
conn_conf_remservers(struct ConnConf_Struct * ConnConf)793 void conn_conf_remservers(struct ConnConf_Struct *ConnConf) {
794 
795   while (ConnConf->Server_Head != NULL) { conn_conf_remserver(ConnConf, ConnConf->Server_Head); }
796 
797 }
798