aboutsummaryrefslogtreecommitdiff
path: root/iauth/a_conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'iauth/a_conf.c')
-rw-r--r--iauth/a_conf.c548
1 files changed, 548 insertions, 0 deletions
diff --git a/iauth/a_conf.c b/iauth/a_conf.c
new file mode 100644
index 0000000..602ab53
--- /dev/null
+++ b/iauth/a_conf.c
@@ -0,0 +1,548 @@
+/************************************************************************
+ * IRC - Internet Relay Chat, iauth/a_conf.c
+ * Copyright (C) 1998 Christophe Kalt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef lint
+static char rcsid[] = "@(#)$Id: a_conf.c,v 1.21 1999/07/11 22:11:33 kalt Exp $";
+#endif
+
+#include "os.h"
+#include "a_defines.h"
+#define A_CONF_C
+#include "a_externs.h"
+#undef A_CONF_C
+
+static aModule *Mlist[16];
+
+#define DEFAULT_TIMEOUT 30
+
+u_int debuglevel = 0;
+
+AnInstance *instances = NULL;
+
+static void
+conf_err(nb, msg, chk)
+u_int nb;
+char *msg, *chk;
+{
+ if (chk)
+ printf("line %d: %s\n", nb, msg);
+ else
+ sendto_log(ALOG_IRCD|ALOG_DCONF, LOG_ERR,
+ "Configuration error line %d: %s", nb, msg);
+}
+
+/*
+ * Match address by #IP bitmask (10.11.12.128/27)
+ */
+static int
+match_ipmask(mask, ipaddr)
+aTarget *mask;
+char *ipaddr;
+{
+#ifdef INET6
+ return 1;
+#else
+ int i1, i2, i3, i4;
+ u_long iptested;
+
+ if (sscanf(ipaddr, "%d.%d.%d.%d", &i1, &i2, &i3, &i4) != 4)
+ return -1;
+ iptested = htonl(i1 * 0x1000000 + i2 * 0x10000 + i3 * 0x100 + i4);
+ return ((iptested & mask->lmask) == mask->baseip) ? 0 : 1;
+#endif
+}
+
+/* conf_read: read the configuration file, instanciate modules */
+char *
+conf_read(cfile)
+char *cfile;
+{
+ AnInstance *ident = NULL; /* make sure this module is used */
+ u_char needh = 0; /* do we need hostname information for any host? */
+ u_char o_req = 0, o_dto = 0, o_wup = 0;
+ static char o_all[5];
+ u_int timeout = DEFAULT_TIMEOUT, totto = 0;
+ u_int lnnb = 0, i;
+ u_char icount = 0, Mcnt = 0;
+ char buffer[160], *ch;
+ AnInstance **last = &instances, *itmp;
+ FILE *cfh;
+
+ Mlist[Mcnt++] = &Module_rfc931;
+ Mlist[Mcnt++] = &Module_socks;
+ Mlist[Mcnt++] = &Module_pipe;
+ Mlist[Mcnt++] = &Module_lhex;
+ Mlist[Mcnt] = NULL;
+
+ cfh = fopen((cfile) ? cfile : IAUTHCONF_PATH, "r");
+ if (cfh)
+ {
+ while (fgets(buffer, 160, cfh))
+ {
+ if (ch = index(buffer, '\n'))
+ lnnb += 1;
+ else
+ {
+ conf_err(lnnb, "line too long, ignoring.",
+ cfile);
+ /* now skip what's left */
+ while (fgets(buffer, 160, cfh))
+ if (index(buffer, '\n'))
+ break;
+ continue;
+ }
+ if (buffer[0] == '#' || buffer[0] == '\n')
+ continue;
+ *ch = '\0';
+ if (ch = index(buffer, '#'))
+ *ch = '\0';
+ if (!strncmp("required", buffer, 8))
+ {
+ o_req = 1;
+ continue;
+ }
+ if (!strncmp("notimeout", buffer, 9))
+ {
+ o_dto = 1;
+ continue;
+ }
+ if (!strncmp("extinfo", buffer, 7))
+ {
+ o_wup = 1;
+ continue;
+ }
+ if (!strncmp("timeout = ", buffer, 10))
+ {
+ if (sscanf(buffer, "timeout = %u",
+ &timeout) != 1)
+ conf_err(lnnb, "Invalid setting.",
+ cfile);
+ continue;
+ }
+ /* debugmode setting */
+ if (!strncmp("debuglvl = 0x", buffer, 13))
+ {
+ if (sscanf(buffer, "debuglvl = %x",
+ &debuglevel) != 1)
+ conf_err(lnnb, "Invalid setting.",
+ cfile);
+ else if (!cfile)
+ sendto_log(ALOG_DCONF, LOG_DEBUG,
+ "debuglevel = %X",
+ debuglevel);
+ continue;
+ }
+#if defined(USE_DSM)
+ if (!strncmp("shared ", buffer, 7))
+ {
+ char lfname[80];
+ void *mod_handle;
+ aModule *(*load_func)();
+
+ ch = index(buffer+7, ' ');
+ if (ch == NULL)
+ {
+ conf_err(lnnb, "Syntax error.", cfile);
+ continue;
+ }
+ *ch++ = '\0';
+ mod_handle = dlopen(ch, RTLD_NOW);
+ if (mod_handle == NULL)
+ {
+ conf_err(lnnb, dlerror(), cfile);
+ continue;
+ }
+# if defined(DLSYM_NEEDS_UNDERSCORE)
+ sprintf(lfname, "_%s_load", buffer+7);
+# else
+ sprintf(lfname, "%s_load", buffer+7);
+# endif
+ load_func = (aModule *(*)())dlsym(mod_handle,
+ lfname);
+ if (load_func == NULL)
+ {
+ conf_err(lnnb,"Invalid shared object.",
+ cfile);
+ dlclose(mod_handle);
+ continue;
+ }
+ Mlist[Mcnt] = load_func();
+ if (Mlist[Mcnt])
+ {
+ Mcnt += 1;
+ Mlist[Mcnt] = NULL;
+ }
+ else
+ {
+ conf_err(lnnb, "Failed.", cfile);
+ dlclose(mod_handle);
+ }
+ continue;
+ }
+#endif
+ if (buffer[0] == '\t')
+ {
+ conf_err(lnnb, "Ignoring unexpected property.",
+ cfile);
+ continue;
+ }
+ /* at this point, it has to be the following */
+ if (strncasecmp("module ", buffer, 7))
+ {
+ conf_err(lnnb,
+ "Unexpected line: not a module.",
+ cfile);
+ continue;
+ }
+ for (i = 0; Mlist[i] != NULL; i++)
+ if (!strcasecmp(buffer+7, Mlist[i]->name))
+ break;
+ if (Mlist[i] == NULL)
+ {
+ conf_err(lnnb, "Unknown module name.", cfile);
+ continue;
+ }
+ if (Mlist[i] == &Module_rfc931 && ident)
+ {
+ conf_err(lnnb,
+ "This module can only be loaded once.",
+ cfile);
+ continue;
+ }
+ *last = (AnInstance *) malloc(sizeof(AnInstance));
+ (*last)->nexti = NULL;
+ (*last)->in = icount++;
+ (*last)->mod = Mlist[i];
+ (*last)->opt = NULL;
+ (*last)->popt = NULL;
+ (*last)->data = NULL;
+ (*last)->hostname = NULL;
+ (*last)->address = NULL;
+ (*last)->timeout = timeout;
+ if (Mlist[i] == &Module_rfc931)
+ ident = *last;
+
+ while (fgets(buffer, 160, cfh))
+ {
+ aTarget **ttmp;
+ u_long baseip = 0, lmask = 0;
+
+ if (ch = index(buffer, '\n'))
+ lnnb += 1;
+ else
+ {
+ conf_err(lnnb,
+ "line too long, ignoring.",
+ cfile);
+ /* now skip what's left */
+ while (fgets(buffer, 160, cfh))
+ if (index(buffer,'\n'))
+ break;
+ continue;
+ }
+ if (buffer[0] == '#')
+ continue;
+ if (buffer[0] == '\n')
+ break;
+ if (buffer[0] != '\t')
+ {
+ conf_err(lnnb, "Invalid syntax.",
+ cfile);
+ continue;
+ }
+ *ch = '\0';
+ if (!strncasecmp(buffer+1, "option = ", 9))
+ {
+ if ((*last)->opt)
+ conf_err(lnnb,
+ "Duplicate option keyword: ignored.",
+ cfile);
+ else
+ (*last)->opt =
+ mystrdup(buffer + 10);
+ continue;
+ }
+ if (!strncasecmp(buffer+1, "host = ", 7))
+ {
+ needh = 1;
+ ttmp = &((*last)->hostname);
+ ch = buffer + 8;
+ }
+ else if (!strncasecmp(buffer+1, "ip = ", 5))
+ {
+ ttmp = &((*last)->address);
+ ch = buffer + 6;
+ if (strchr(ch, '/'))
+ {
+ int i1, i2, i3, i4, m;
+
+ if (sscanf(ch,"%d.%d.%d.%d/%d",
+ &i1, &i2, &i3, &i4,
+ &m) != 5 ||
+ m < 1 || m > 31)
+ {
+ conf_err(lnnb,
+ "Bad mask.",
+ cfile);
+ continue;
+ }
+ lmask = htonl((u_long)0xffffffffL << (32 - m));
+ baseip = htonl(i1 * 0x1000000 +
+ i2 * 0x10000 +
+ i3 * 0x100 +
+ i4);
+ }
+ else
+ {
+ lmask = 0;
+ baseip = 0;
+ }
+ }
+ else if (!strncmp(buffer+1, "timeout = ", 10))
+ {
+ u_int local_timeout;
+ if (sscanf(buffer+1, "timeout = %u",
+ &local_timeout) != 1)
+ conf_err(lnnb,
+ "Invalid setting.",
+ cfile);
+ (*last)->timeout = local_timeout;
+ continue;
+ }
+ else
+ {
+ conf_err(lnnb, "Invalid keyword.",
+ cfile);
+ continue;
+ }
+ if (Mlist[i] == &Module_rfc931)
+ continue;
+ while (*ttmp)
+ ttmp = &((*ttmp)->nextt);
+ *ttmp = (aTarget *) malloc(sizeof(aTarget));
+ if (*ch == '!')
+ {
+ (*ttmp)->yes = -1;
+ ch++;
+ }
+ else
+ (*ttmp)->yes = 0;
+ (*ttmp)->value = mystrdup(ch);
+ if ((*ttmp)->baseip)
+ {
+ (*ttmp)->lmask = lmask;
+ (*ttmp)->baseip = baseip;
+ }
+ (*ttmp)->nextt = NULL;
+ }
+
+ last = &((*last)->nexti);
+ }
+ }
+ else if (cfile)
+ {
+ perror("fopen");
+ exit(0);
+ }
+ if (ident == NULL)
+ {
+ ident = *last = (AnInstance *) malloc(sizeof(AnInstance));
+ (*last)->nexti = NULL;
+ (*last)->opt = NULL;
+ (*last)->mod = &Module_rfc931;
+ (*last)->hostname = NULL;
+ (*last)->address = NULL;
+ (*last)->timeout = DEFAULT_TIMEOUT;
+ }
+ ident->timeout = MAX(DEFAULT_TIMEOUT, ident->timeout);
+
+ itmp = instances;
+ while (itmp)
+ {
+ totto += itmp->timeout;
+ itmp = itmp->nexti;
+ }
+ if (totto > ACCEPTTIMEOUT)
+ {
+ if (cfile)
+ printf("Warning: sum of timeouts exceeds ACCEPTTIMEOUT!\n");
+ else
+ sendto_log(ALOG_IRCD|ALOG_DCONF, LOG_ERR,
+ "Warning: sum of timeouts exceeds ACCEPTTIMEOUT!");
+ if (o_dto)
+ if (cfile)
+ printf("Error: \"notimeout\" is set!\n");
+ else
+ sendto_log(ALOG_IRCD|ALOG_DCONF, LOG_ERR,
+ "Error: \"notimeout\" is set!");
+ }
+
+ itmp = instances;
+ if (cfile)
+ {
+ aTarget *ttmp;
+ char *err;
+
+ printf("\nModule(s) loaded:\n");
+ while (itmp)
+ {
+ printf("\t%s\t%s\n", itmp->mod->name,
+ (itmp->opt) ? itmp->opt : "");
+ if (ttmp = itmp->hostname)
+ {
+ printf("\t\tHost = %s%s",
+ (ttmp->yes == 0) ? "" : "!",
+ ttmp->value);
+ while (ttmp = ttmp->nextt)
+ printf(",%s%s",
+ (ttmp->yes == 0) ? "" : "!",
+ ttmp->value);
+ printf("\n");
+ }
+ if (ttmp = itmp->address)
+ {
+ printf("\t\tIP = %s",
+ (ttmp->yes == 0) ? "" : "!",
+ ttmp->value);
+ while (ttmp = ttmp->nextt)
+ printf(",%s%s",
+ (ttmp->yes == 0) ? "" : "!",
+ ttmp->value);
+ printf("\n");
+ }
+ if (itmp->timeout != DEFAULT_TIMEOUT)
+ printf("\t\ttimeout: %u seconds\n",
+ itmp->timeout);
+ if (itmp->mod->init)
+ {
+ err = itmp->mod->init(itmp);
+ printf("\t\tInitialization: %s\n",
+ (err) ? err : "Successful");
+ }
+ itmp = itmp->nexti;
+ }
+ }
+ else
+ while (itmp)
+ {
+ if (itmp->mod->init)
+ itmp->mod->init(itmp);
+ itmp = itmp->nexti;
+ }
+
+ ch = o_all;
+ if (o_req) *ch++ = 'R';
+ if (o_dto) *ch++ = 'T';
+ if (o_wup) *ch++ = 'A';
+ if (needh) *ch++ = 'W';
+ *ch++ = '\0';
+ return o_all;
+}
+
+/* conf_match: check if an instance is to be applied to a connection
+ Returns -1: no match, and never will
+ 0: got a match, doIt[tm]
+ 1: no match, but might be later so ask again */
+int
+conf_match(cl, inst)
+u_int cl;
+AnInstance *inst;
+{
+ aTarget *ttmp;
+
+ /* general case, always matches */
+ if (inst->address == NULL && inst->hostname == NULL)
+ return 0;
+ /* feature case, "host = *" to force to wait for DNS info */
+ if ((cldata[cl].state & A_NOH) && inst->hostname &&
+ !strcmp(inst->hostname->value, "*"))
+ return 0;
+ /* check matches on IP addresses */
+ if (ttmp = inst->address)
+ while (ttmp)
+ {
+ if (ttmp->baseip)
+ {
+ if (match_ipmask(ttmp, cldata[cl].itsip) == 0)
+ return ttmp->yes;
+ }
+ else
+ if (match(ttmp->value, cldata[cl].itsip) == 0)
+ return ttmp->yes;
+ ttmp = ttmp->nextt;
+ }
+ /* check matches on hostnames */
+ if (ttmp = inst->hostname)
+ {
+ if (cldata[cl].state & A_GOTH)
+ {
+ while (ttmp)
+ {
+ if (match(ttmp->value, cldata[cl].host) == 0)
+ return ttmp->yes;
+ ttmp = ttmp->nextt;
+ }
+ /* no match, will never match */
+ return -1;
+ }
+ else if (cldata[cl].state & A_NOH)
+ return -1;
+ else
+ /* may be later, once we have DNS information */
+ return 1;
+ }
+ /* fall through, no match, will never match */
+ return -1;
+}
+
+/* conf_ircd: send the configuration to the ircd daemon */
+void
+conf_ircd()
+{
+ AnInstance *itmp = instances;
+ aTarget *ttmp;
+
+ sendto_ircd("a");
+ while (itmp)
+ {
+ if (itmp->address == NULL && itmp->hostname == NULL)
+ sendto_ircd("A * %s %s", itmp->mod->name,
+ (itmp->popt) ? itmp->popt : "");
+ else
+ {
+ ttmp = itmp->address;
+ while (ttmp)
+ {
+ sendto_ircd("A %s %s %s", ttmp->value,
+ itmp->mod->name,
+ (itmp->popt) ? itmp->popt : "");
+ ttmp = ttmp->nextt;
+ }
+ ttmp = itmp->hostname;
+ while (ttmp)
+ {
+ sendto_ircd("A %s %s %s", ttmp->value,
+ itmp->mod->name,
+ (itmp->popt) ? itmp->popt : "");
+ ttmp = ttmp->nextt;
+ }
+ }
+ itmp = itmp->nexti;
+ }
+}