/* * ---------------------------------------------------------------- * Night Light IRC Proxy - Access Configuration Functions * ---------------------------------------------------------------- * Copyright (C) 1997-2007 Jonas Kvinge * All rights reserved. * * 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 2 of the License, 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Last modified by: * Jonas Kvinge (15.11.2006) * */ #define ACCESS_CONF_C #define NEED_SYS_TYPES_H 1 /* Extra types */ #define NEED_SYS_PARAM_H 1 /* Some systems need this */ #define NEED_LIMITS_H 0 /* Kernel limits */ #define NEED_STDARG_H 1 /* va_list, etc */ #define NEED_ERRNO_H 1 /* errno */ #define NEED_CTYPE_H 1 /* isdigit(), etc */ #define NEED_NETINET_IN_H 0 /* in_addr, sockaddr_in, etc */ #define NEED_ARPA_INET_H 0 /* inet_ntoa(), inet_aton(), etc */ #define NEED_STDIO_H 1 /* Standard C UNIX functions */ #define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */ #define NEED_TIME_H 1 /* time(), etc */ #define NEED_SYSCTL_H 0 /* sysctl(), etc */ #define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */ #define NEED_SYS_UIO_H 0 /* iovec, etc */ #define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */ #define NEED_SYS_IOCTL_H 0 /* ioctl(), etc */ #define NEED_SYS_FILIO_H 0 /* Solaris need this for ioctl(), etc */ #define NEED_UNISTD_H 1 /* Unix standard functions */ #define NEED_STRING_H 1 /* C string functions */ #define NEED_SIGNAL_H 0 /* Signal functions */ #define NEED_SYS_SOCKET_H 0 /* Socket functions */ #define NEED_NETDB_H 0 /* Network database functions */ #define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */ #define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */ #include "includes.h" #include "conf.h" #include "access_conf.h" /* VARIABLES - JONAS (31.07.2001) */ unsigned long int AccessConfs = 0; struct AccessConf_Struct *Allow_Head = NULL; struct AccessConf_Struct *Allow_Tail = NULL; struct AccessConf_Struct *Deny_Head = NULL; struct AccessConf_Struct *Deny_Tail = NULL; unsigned short int Access_CheckFirst = ACCESS_DENY; unsigned short int Access_Default = ACCESS_DENY; extern struct Conf_Struct ConfS; /* ACCESS_CONF_READ FUNCTION - JONAS (31.07.2001) */ signed long int access_conf_read(void) { char File[FILELEN+1] = ""; FILE *FilePT = NULL; unsigned short int Count = 0; unsigned short int Skip = 0; DEBUGPRINT(BITMASK_DEBUG_CONF, "Reading access configuration file."); if (ConfS.AccessConfFile[0] != '/') { strncat(File, ConfS.DataPath, FILELEN); if (ConfS.DataPath[strlen(ConfS.DataPath)] != '/') { strncat(File, "/", (FILELEN - strlen(File))); } } strncat(File, ConfS.AccessConfFile, (FILELEN - strlen(File))); FilePT = fopen(File, "r"); if (FilePT == NULL) { sysprint(BITMASK_ERROR, "Unable to open access configuration file %s: [%d] %s", File, errno, strerror(errno)); return(ERROR); } access_conf_destroy(); FOREVERLOOP { char Line[LINELEN+1] = ""; char *LinePT = NULL; char *TempPT = NULL; char *EntryPT = NULL; char *DataPT = NULL; memset(&Line, 0, LINELEN+1); TempPT = fgets(Line, LINELEN, FilePT); if (TempPT == NULL) { break; } ++Count; LinePT = Line; while ((TempPT = strchr(LinePT, '\r')) != NULL) { *TempPT = '\0'; } while ((TempPT = strchr(LinePT, '\n')) != NULL) { *TempPT = '\0'; } while ((TempPT = strchr(LinePT, '\t')) != NULL) { *TempPT = ' '; } while ((LinePT[0] == ' ') || (LinePT[0] == '\t')) { ++LinePT; } if ((LinePT[0] == '#') || (LinePT[0] == ';') || (LinePT[0] == '\0')) { continue; } EntryPT = LinePT; StrMovePastToken(LinePT, ' '); if (strcasecmp(EntryPT, "CONNECTION") == FALSE) { Skip = TRUE; continue; } if (EntryPT[0] == '}') { Skip = FALSE; continue; } if (Skip == TRUE) { continue; } if (LinePT == NULL) { sysprint(BITMASK_ERROR, "Access configuration error in file %s line %d: Expecting more data.", File, Count); continue; } DataPT = LinePT; StrMovePastToken(LinePT, ' '); if (strcasecmp(EntryPT, "ORDER") == FALSE) { char *OrderFPT = NULL; char *OrderLPT = NULL; OrderFPT = DataPT; OrderLPT = strchr(DataPT, ','); if (OrderLPT == NULL) { sysprint(BITMASK_ERROR, "Access configuration error in file %s line %d: Order incorrectly specified.", File, Count); continue; } OrderLPT[0] = '\0'; ++OrderLPT; while(OrderFPT[0] == ' ') { ++OrderFPT; } while(OrderLPT[0] == ' ') { ++OrderLPT; } while (((TempPT = strchr(OrderFPT, ' ')) != NULL) || ((TempPT = strchr(OrderFPT, '\t')) != NULL) || ((TempPT = strchr(OrderFPT, ';')) != NULL) || ((TempPT = strchr(OrderFPT, '#')) != NULL)) { if (TempPT == OrderFPT) { ++OrderFPT; } else { *TempPT = '\0'; } } while (((TempPT = strchr(OrderLPT, ' ')) != NULL) || ((TempPT = strchr(OrderLPT, '\t')) != NULL) || ((TempPT = strchr(OrderLPT, ';')) != NULL) || ((TempPT = strchr(OrderLPT, '#')) != NULL)) { if (TempPT == OrderLPT) { OrderLPT++; } else { *TempPT = '\0'; } } if ((strcasecmp(OrderFPT, "ALLOW") == FALSE) && (strcasecmp(OrderLPT, "DENY") == FALSE)) { Access_CheckFirst = ACCESS_ALLOW; DEBUGPRINT(BITMASK_DEBUG_CONF, "Access configuration: Rule order: Allow, Deny."); } if ((strcasecmp(OrderFPT, "DENY") == FALSE) && (strcasecmp(OrderLPT, "ALLOW") == FALSE)) { Access_CheckFirst = ACCESS_DENY; DEBUGPRINT(BITMASK_DEBUG_CONF, "Access configuration: Rule order: Deny, Allow."); } else { sysprint(BITMASK_ERROR, "Access configuration error, file %s line %d: Order incorrectly specified.", File, Count); continue; } continue; } else if (strcasecmp(EntryPT, "DEFAULT") == FALSE) { if (strcasecmp(DataPT, "ALLOW") == FALSE) { Access_Default = ACCESS_ALLOW; DEBUGPRINT(BITMASK_DEBUG_CONF, "Access configuration: Default rule: Allow."); } else if (strcasecmp(DataPT, "DENY") == FALSE) { Access_Default = ACCESS_DENY; DEBUGPRINT(BITMASK_DEBUG_CONF, "Access configuration: Default rule: Deny."); } else { sysprint(BITMASK_ERROR, "Access configuration error, file %s line %d: Default rule incorrectly specified.", File, Count); continue; } continue; } else if (strcasecmp(EntryPT, "ALLOW") == FALSE) { (void) access_conf_addallow(DataPT, (LinePT == NULL ? ACCESS_CONF_NOREASON : LinePT)); continue; } else if (strcasecmp(EntryPT, "DENY") == FALSE) { (void) access_conf_adddeny(DataPT, (LinePT == NULL ? ACCESS_CONF_NOREASON : LinePT)); continue; } else { #if 0 sysprint(BITMASK_ERROR, "Access configuration error, file %s line %d: Invalid entry \"%s\"", File, Count, EntryPT); #endif continue; } } (void) fclose(FilePT); return(AccessConfs); } /* ACCESS_CONF_ADDALLOW - JONAS (31.07.2001) */ struct AccessConf_Struct *access_conf_addallow(const char *const HostPT, const char *const ReasonPT) { struct AccessConf_Struct *AccessConf = NULL; struct AccessConf_Struct *AccessConf_NEW = NULL; assert(HostPT != NULL); assert(ReasonPT != NULL); DEBUGPRINT(BITMASK_DEBUG_CONF, "Access configuration: Allow rule: %s: %s", HostPT, ReasonPT); AccessConf_NEW = malloc(sizeof(struct AccessConf_Struct)); if (AccessConf_NEW == NULL) { aerrno = AEMALLOC; return(NULL); } memset(AccessConf_NEW, 0, sizeof(struct AccessConf_Struct)); AccessConf_NEW->Host = strdup(HostPT); AccessConf_NEW->Reason = strdup(ReasonPT); if ((AccessConf_NEW->Host == NULL) || (AccessConf_NEW->Reason == NULL)) { free(AccessConf_NEW->Host); free(AccessConf_NEW->Reason); free(AccessConf_NEW); aerrno = AEMALLOC; return(NULL); } if (Allow_Head == NULL) { Allow_Head = AccessConf_NEW; Allow_Tail = AccessConf_NEW; } else { AccessConf = Allow_Tail; AccessConf->Next = AccessConf_NEW; AccessConf_NEW->Prev = AccessConf; Allow_Tail = AccessConf_NEW; } AccessConf++; aerrno = AESUCCESS; return(AccessConf_NEW); } /* ACCESS_CONF_REMALLOW FUNCTION - JONAS (31.07.2001) */ void access_conf_remallow(struct AccessConf_Struct *AccessConf) { assert(AccessConf != NULL); if (AccessConf->Prev == NULL) { Allow_Head = AccessConf->Next; } else { AccessConf->Prev->Next = AccessConf->Next; } if (AccessConf->Next == NULL) { Allow_Tail = AccessConf->Prev; } else { AccessConf->Next->Prev = AccessConf->Prev; } free(AccessConf->Host); free(AccessConf->Reason); free(AccessConf); AccessConf--; } /* ACCESS_CONF_ADDDENY - JONAS (31.07.2001) */ struct AccessConf_Struct *access_conf_adddeny(const char *const HostPT, const char *const ReasonPT) { struct AccessConf_Struct *AccessConf = NULL; struct AccessConf_Struct *AccessConf_NEW = NULL; assert(HostPT != NULL); assert(ReasonPT != NULL); DEBUGPRINT(BITMASK_DEBUG_CONF, "Access configuration: Deny rule: %s: %s", HostPT, ReasonPT); AccessConf_NEW = malloc(sizeof(struct AccessConf_Struct)); if (AccessConf_NEW == NULL) { aerrno = AEMALLOC; return(NULL); } memset(AccessConf_NEW, 0, sizeof(struct AccessConf_Struct)); AccessConf_NEW->Host = strdup(HostPT); AccessConf_NEW->Reason = strdup(ReasonPT); if ((AccessConf_NEW->Host == NULL) || (AccessConf_NEW->Reason == NULL)) { free(AccessConf_NEW->Host); free(AccessConf_NEW->Reason); free(AccessConf_NEW); aerrno = AEMALLOC; return(NULL); } if (Deny_Head == NULL) { Deny_Head = AccessConf_NEW; Deny_Tail = AccessConf_NEW; } else { AccessConf = Deny_Tail; AccessConf->Next = AccessConf_NEW; AccessConf_NEW->Prev = AccessConf; Deny_Tail = AccessConf_NEW; } AccessConfs++; aerrno = AESUCCESS; return(AccessConf_NEW); } /* ACCESS_CONF_REMDENY FUNCTION - JONAS (31.07.2001) */ void access_conf_remdeny(struct AccessConf_Struct *AccessConf) { assert(AccessConf != NULL); if (AccessConf->Prev == NULL) { Deny_Head = AccessConf->Next; } else { AccessConf->Prev->Next = AccessConf->Next; } if (AccessConf->Next == NULL) { Deny_Tail = AccessConf->Prev; } else { AccessConf->Next->Prev = AccessConf->Prev; } free(AccessConf->Host); free(AccessConf->Reason); free(AccessConf); AccessConfs--; } /* ACCESS_CONF_DESTROY FUNCTION - JONAS (31.07.2001) */ void access_conf_destroy(void) { while (Allow_Head != NULL) { access_conf_remallow(Allow_Head); } while (Deny_Head != NULL) { access_conf_remdeny(Deny_Head); } }