X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fnetconfig.c;h=cce05ef4188c877f2c53a2db2401d4c925dbc179;hb=83b162e34bdb8474a872ae531b56c4cbb934a9a6;hp=3aac29463e616fc753e7b6d9b0df2dcce54980fc;hpb=4632e362fbc73c9abce30f0bcf4d0023144937a8;p=citadel.git diff --git a/citadel/netconfig.c b/citadel/netconfig.c index 3aac29463..cce05ef41 100644 --- a/citadel/netconfig.c +++ b/citadel/netconfig.c @@ -2,20 +2,22 @@ * This module handles shared rooms, inter-Citadel mail, and outbound * mailing list processing. * - * Copyright (c) 2000-2012 by the citadel.org team + * Copyright (c) 2000-2016 by the citadel.org team * - * This program is open source software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 3. + * This program is open source software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 3. * - * 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. + * 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. * */ #include "sysdep.h" #include +#include +#include #ifdef HAVE_SYSCALL_H # include @@ -25,15 +27,24 @@ # endif #endif #include +#include #include #include "include/ctdl_module.h" +#include "serv_extensions.h" +#include "config.h" + +void vFreeRoomNetworkStruct(void *vOneRoomNetCfg); +void FreeRoomNetworkStructContent(OneRoomNetCfg *OneRNCfg); + HashList *CfgTypeHash = NULL; -HashList *RoomConfigs = NULL; + /*-----------------------------------------------------------------------------* * Per room network configs * *-----------------------------------------------------------------------------*/ + + void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, int nSegments, CfgLineSerializer s, CfgLineDeAllocator d) { CfgLineType *pCfg; @@ -41,13 +52,15 @@ void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLinePar pCfg = (CfgLineType*) malloc(sizeof(CfgLineType)); pCfg->Parser = p; pCfg->Serializer = s; + pCfg->DeAllocator = d; pCfg->C = eCfg; pCfg->Str.Key = Name; pCfg->Str.len = len; pCfg->IsSingleLine = uniq; pCfg->nSegments = nSegments; - if (CfgTypeHash == NULL) + if (CfgTypeHash == NULL) { CfgTypeHash = NewHash(1, NULL); + } Put(CfgTypeHash, Name, len, pCfg, NULL); } @@ -82,34 +95,39 @@ const CfgLineType *GetCfgTypeByEnum(RoomNetCfg eCfg, HashPos *It) } return NULL; } -void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) + +void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCfg) { RoomNetCfgLine *nptr; int i; nptr = (RoomNetCfgLine *) malloc(sizeof(RoomNetCfgLine)); - nptr->next = OneRNCFG->NetConfigs[ThisOne->C]; + nptr->next = OneRNCfg->NetConfigs[ThisOne->C]; nptr->Value = malloc(sizeof(StrBuf*) * ThisOne->nSegments); + nptr->nValues = 0; memset(nptr->Value, 0, sizeof(StrBuf*) * ThisOne->nSegments); if (ThisOne->nSegments == 1) { nptr->Value[0] = NewStrBufPlain(LinePos, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); + nptr->nValues = 1; } else for (i = 0; i < ThisOne->nSegments; i++) { + nptr->nValues++; nptr->Value[i] = NewStrBufPlain(NULL, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); StrBufExtract_NextToken(nptr->Value[i], Line, &LinePos, '|'); } - OneRNCFG->NetConfigs[ThisOne->C] = nptr; + OneRNCfg->NetConfigs[ThisOne->C] = nptr; } -void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *OneRNCFG, RoomNetCfgLine *data) +void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *OneRNCfg, RoomNetCfgLine *data) { int i; StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0); + StrBufAppendBufPlain(OutputBuffer, HKEY("|"), 0); for (i = 0; i < ThisOne->nSegments; i++) { StrBufAppendBuf(OutputBuffer, data->Value[i], 0); @@ -123,7 +141,10 @@ void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data) { int i; - for (i = 0; i < ThisOne->nSegments; i++) + if (*data == NULL) + return; + + for (i = 0; i < (*data)->nValues; i++) { FreeStrBuf(&(*data)->Value[i]); } @@ -131,168 +152,208 @@ void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data) free(*data); *data = NULL; } + RoomNetCfgLine *DuplicateOneGenericCfgLine(const RoomNetCfgLine *data) { + int i; RoomNetCfgLine *NewData; NewData = (RoomNetCfgLine*)malloc(sizeof(RoomNetCfgLine)); - int i; + memset(NewData, 0, sizeof(RoomNetCfgLine)); NewData->Value = (StrBuf **)malloc(sizeof(StrBuf*) * data->nValues); + memset(NewData->Value, 0, sizeof(StrBuf*) * data->nValues); for (i = 0; i < data->nValues; i++) { NewData->Value[i] = NewStrBufDup(data->Value[i]); } + NewData->nValues = data->nValues; return NewData; } -int ReadRoomNetConfigFile(OneRoomNetCfg **pOneRNCFG, char *filename) + + +/* + * Create a config key for a room's netconfig entry + */ +void netcfg_keyname(char *keybuf, long roomnum) { - int fd; - const char *ErrStr = NULL; - const char *Pos; - const CfgLineType *pCfg; - StrBuf *Line; - StrBuf *InStr; - OneRoomNetCfg *OneRNCFG; - - fd = open(filename, O_NONBLOCK|O_RDONLY); - if (fd == -1) { - *pOneRNCFG = NULL; - return 0; + if (!keybuf) return; + sprintf(keybuf, "c_netconfig_%010ld", roomnum); +} + + + +/* + * Given a room number and a textual netconfig, convert to base64 and write to the configdb + */ +void write_netconfig_to_configdb(long roomnum, const char *raw_netconfig) +{ + char keyname[25]; + char *enc; + int enc_len; + int len; + + len = strlen(raw_netconfig); + netcfg_keyname(keyname, roomnum); + enc = malloc(len * 2); + + if (enc) { + enc_len = CtdlEncodeBase64(enc, raw_netconfig, len, 0); + if ((enc_len > 1) && (enc[enc_len-2] == 13)) enc[enc_len-2] = 0; + if ((enc_len > 0) && (enc[enc_len-1] == 10)) enc[enc_len-1] = 0; + enc[enc_len] = 0; + syslog(LOG_DEBUG, "Writing key '%s' (length=%d)", keyname, enc_len); + CtdlSetConfigStr(keyname, enc); + free(enc); } - OneRNCFG = malloc(sizeof(OneRoomNetCfg)); - memset(OneRNCFG, 0, sizeof(OneRoomNetCfg)); - *pOneRNCFG = OneRNCFG; - Line = NewStrBuf(); +} - while (StrBufTCP_read_line(Line, &fd, 0, &ErrStr) >= 0) { - if (StrLength(Line) == 0) - continue; - Pos = NULL; - InStr = NewStrBufPlain(NULL, StrLength(Line)); - StrBufExtract_NextToken(InStr, Line, &Pos, '|'); - pCfg = GetCfgTypeByStr(SKEY(InStr)); - if (pCfg != NULL) - { - pCfg->Parser(pCfg, Line, Pos, OneRNCFG); - } - else - { - if (OneRNCFG->misc == NULL) + +/* + * Given a room number, attempt to load the netconfig configdb entry for that room. + * If it returns NULL, there is no netconfig. + * Otherwise the caller owns the returned memory and is responsible for freeing it. + */ +char *LoadRoomNetConfigFile(long roomnum) +{ + char keyname[25]; + char *encoded_netconfig = NULL; + char *decoded_netconfig = NULL; + + netcfg_keyname(keyname, roomnum); + encoded_netconfig = CtdlGetConfigStr(keyname); + if (!encoded_netconfig) return NULL; + + decoded_netconfig = malloc(strlen(encoded_netconfig)); // yeah, way bigger than it needs to be, but safe + CtdlDecodeBase64(decoded_netconfig, encoded_netconfig, strlen(encoded_netconfig)); + return decoded_netconfig; +} + + +/* + * Deserialize a netconfig , allocate and return structured data + */ +OneRoomNetCfg *ParseRoomNetConfigFile(char *serialized_data) +{ + const char *Pos = NULL; + const CfgLineType *pCfg = NULL; + StrBuf *Line = NULL; + StrBuf *InStr = NULL; + StrBuf *Cfg = NULL; + OneRoomNetCfg *OneRNCfg = NULL; + int num_lines = 0; + int i = 0; + + OneRNCfg = malloc(sizeof(OneRoomNetCfg)); + memset(OneRNCfg, 0, sizeof(OneRoomNetCfg)); + + Line = NewStrBuf(); + InStr = NewStrBuf(); + Cfg = NewStrBufPlain(serialized_data, -1); + num_lines = num_tokens(ChrPtr(Cfg), '\n'); + + for (i=0; i 0) { + Pos = NULL; + StrBufExtract_NextToken(InStr, Line, &Pos, '|'); + + pCfg = GetCfgTypeByStr(SKEY(InStr)); + if (pCfg != NULL) { - OneRNCFG->misc = NewStrBufDup(Line); + pCfg->Parser(pCfg, Line, Pos, OneRNCfg); } else { - if(StrLength(OneRNCFG->misc) > 0) - StrBufAppendBufPlain(OneRNCFG->misc, HKEY("\n"), 0); - StrBufAppendBuf(OneRNCFG->misc, Line, 0); + if (OneRNCfg->misc == NULL) + { + OneRNCfg->misc = NewStrBufDup(Line); + } + else + { + if (StrLength(OneRNCfg->misc) > 0) { + StrBufAppendBufPlain(OneRNCfg->misc, HKEY("\n"), 0); + } + StrBufAppendBuf(OneRNCfg->misc, Line, 0); + } } } } - if (fd > 0) - close(fd); FreeStrBuf(&InStr); FreeStrBuf(&Line); - return 1; + FreeStrBuf(&Cfg); + return OneRNCfg; } -int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) + +void SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCfg, long roomnum) { RoomNetCfg eCfg; - StrBuf *Cfg; - char tempfilename[PATH_MAX]; - int TmpFD; - long len; - time_t unixtime; - struct timeval tv; - long reltid; /* if we don't have SYS_gettid, use "random" value */ - StrBuf *OutBuffer; - int rc; + StrBuf *Cfg = NULL; + StrBuf *OutBuffer = NULL; HashPos *CfgIt; - len = strlen(filename); - memcpy(tempfilename, filename, len + 1); - -#if defined(HAVE_SYONERNCFGALL_H) && defined (SYS_gettid) - reltid = syOneRNCFGall(SYS_gettid); -#endif - gettimeofday(&tv, NULL); - /* Promote to time_t; types differ on some OSes (like darwin) */ - unixtime = tv.tv_sec; - - sprintf(tempfilename + len, ".%ld-%ld", reltid, unixtime); - errno = 0; - TmpFD = open(tempfilename, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); Cfg = NewStrBuf(); - if ((TmpFD < 0) || (errno != 0)) { - syslog(LOG_CRIT, "ERROR: cannot open %s: %s\n", - filename, strerror(errno)); - unlink(tempfilename); - return 0; - } - else { - CfgIt = GetNewHashPos(CfgTypeHash, 1); - fchown(TmpFD, config.c_ctdluid, 0); - for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++) + OutBuffer = NewStrBuf(); + CfgIt = GetNewHashPos(CfgTypeHash, 1); + for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++) + { + const CfgLineType *pCfg; + pCfg = GetCfgTypeByEnum(eCfg, CfgIt); + if (pCfg) { - const CfgLineType *pCfg; - pCfg = GetCfgTypeByEnum(eCfg, CfgIt); if (pCfg->IsSingleLine) { - pCfg->Serializer(pCfg, OutBuffer, OneRNCFG, NULL); + pCfg->Serializer(pCfg, OutBuffer, OneRNCfg, NULL); } else { - RoomNetCfgLine *pName = OneRNCFG->NetConfigs[pCfg->C]; + RoomNetCfgLine *pName = OneRNCfg->NetConfigs[pCfg->C]; while (pName != NULL) { - pCfg->Serializer(pCfg, OutBuffer, OneRNCFG, pName); + pCfg->Serializer(pCfg, OutBuffer, OneRNCfg, pName); pName = pName->next; } - - } - } - DeleteHashPos(&CfgIt); + } + DeleteHashPos(&CfgIt); - if (OneRNCFG->misc != NULL) { - StrBufAppendBuf(OutBuffer, OneRNCFG->misc, 0); - } + if (OneRNCfg->misc != NULL) { + StrBufAppendBuf(OutBuffer, OneRNCfg->misc, 0); + } - rc = write(TmpFD, ChrPtr(OutBuffer), StrLength(OutBuffer)); - if ((rc >=0 ) && (rc == StrLength(Cfg))) - { - close(TmpFD); - rename(tempfilename, filename); - rc = 1; - } - else { - syslog(LOG_EMERG, - "unable to write %s; [%s]; not enough space on the disk?\n", - tempfilename, - strerror(errno)); - close(TmpFD); - unlink(tempfilename); - rc = 0; - } - FreeStrBuf(&OutBuffer); - + write_netconfig_to_configdb(roomnum, ChrPtr(OutBuffer)); + + FreeStrBuf(&OutBuffer); + FreeStrBuf(&Cfg); +} + + + +void AddRoomCfgLine(OneRoomNetCfg *OneRNCfg, struct ctdlroom *qrbuf, RoomNetCfg LineType, RoomNetCfgLine *Line) +{ + RoomNetCfgLine **pLine; + + if (OneRNCfg == NULL) + { + OneRNCfg = (OneRoomNetCfg*) malloc(sizeof(OneRoomNetCfg)); + memset(OneRNCfg, 0, sizeof(OneRoomNetCfg)); } - return rc; + pLine = &OneRNCfg->NetConfigs[LineType]; + + while(*pLine != NULL) pLine = &((*pLine)->next); + *pLine = Line; } -void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) +void FreeRoomNetworkStructContent(OneRoomNetCfg *OneRNCfg) { RoomNetCfg eCfg; HashPos *CfgIt; - OneRoomNetCfg *OneRNCFG; - OneRNCFG = (OneRoomNetCfg*)vOneRoomNetCfg; CfgIt = GetNewHashPos(CfgTypeHash, 1); for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++) { @@ -300,337 +361,110 @@ void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) RoomNetCfgLine *pNext, *pName; pCfg = GetCfgTypeByEnum(eCfg, CfgIt); - pName= OneRNCFG->NetConfigs[pCfg->C]; + pName= OneRNCfg->NetConfigs[eCfg]; while (pName != NULL) { pNext = pName->next; - pCfg->DeAllocator(pCfg, &pName); + if (pCfg != NULL) + { + pCfg->DeAllocator(pCfg, &pName); + } + else + { + DeleteGenericCfgLine(NULL, &pName); + } pName = pNext; } } DeleteHashPos(&CfgIt); - FreeStrBuf(&OneRNCFG->Sender); - FreeStrBuf(&OneRNCFG->RoomInfo); - FreeStrBuf(&OneRNCFG->misc); - free(OneRNCFG); -} -void FreeRoomNetworkStruct(OneRoomNetCfg **pOneRNCFG) -{ - vFreeRoomNetworkStruct(*pOneRNCFG); - *pOneRNCFG=NULL; + FreeStrBuf(&OneRNCfg->Sender); + FreeStrBuf(&OneRNCfg->RoomInfo); + FreeStrBuf(&OneRNCfg->misc); + memset(OneRNCfg, 0, sizeof(OneRoomNetCfg)); } -const OneRoomNetCfg* CtdlGetNetCfgForRoom(long QRNumber) + +void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) { - void *pv; - GetHash(RoomConfigs, LKEY(QRNumber), &pv); - return (OneRoomNetCfg*)pv; + OneRoomNetCfg *OneRNCfg; + OneRNCfg = (OneRoomNetCfg*)vOneRoomNetCfg; + FreeRoomNetworkStructContent(OneRNCfg); + free(OneRNCfg); } -void LoadAllNetConfigs(void) +void FreeRoomNetworkStruct(OneRoomNetCfg **pOneRNCfg) { - DIR *filedir = NULL; - struct dirent *d; - struct dirent *filedir_entry; - int d_type = 0; - int d_namelen; - long RoomNumber; - OneRoomNetCfg *OneRNCFG; - int IsNumOnly; - const char *pch; - char path[PATH_MAX]; - - RoomConfigs = NewHash(1, NULL); - filedir = opendir (ctdl_netcfg_dir); - if (filedir == NULL) { - return ; /// todo: panic! - } - - d = (struct dirent *)malloc(offsetof(struct dirent, d_name) + PATH_MAX + 1); - if (d == NULL) { - closedir(filedir); - return ; - } - - while ((readdir_r(filedir, d, &filedir_entry) == 0) && - (filedir_entry != NULL)) - { -#ifdef _DIRENT_HAVE_D_NAMLEN - d_namelen = filedir_entry->d_namelen; -#else - d_namelen = strlen(filedir_entry->d_name); -#endif - -#ifdef _DIRENT_HAVE_D_TYPE - d_type = filedir_entry->d_type; -#else - -#ifndef DT_UNKNOWN -#define DT_UNKNOWN 0 -#define DT_DIR 4 -#define DT_REG 8 -#define DT_LNK 10 - -#define IFTODT(mode) (((mode) & 0170000) >> 12) -#define DTTOIF(dirtype) ((dirtype) << 12) -#endif - d_type = DT_UNKNOWN; -#endif - if ((d_namelen > 1) && filedir_entry->d_name[d_namelen - 1] == '~') - continue; /* Ignore backup files... */ - - if ((d_namelen == 1) && - (filedir_entry->d_name[0] == '.')) - continue; - - if ((d_namelen == 2) && - (filedir_entry->d_name[0] == '.') && - (filedir_entry->d_name[1] == '.')) - continue; - - snprintf(path, PATH_MAX, "%s/%s", - ctdl_netcfg_dir, filedir_entry->d_name); - - if (d_type == DT_UNKNOWN) { - struct stat s; - if (lstat(path, &s) == 0) { - d_type = IFTODT(s.st_mode); - } - } + vFreeRoomNetworkStruct(*pOneRNCfg); + *pOneRNCfg=NULL; +} - switch (d_type) - { - case DT_DIR: - break; - case DT_LNK: /* TODO: check whether its a file or a directory */ - case DT_REG: - IsNumOnly = 1; - pch = filedir_entry->d_name; - while (*pch != '\0') - { - if (!isdigit(*pch)) - { - IsNumOnly = 0; - } - pch ++; - } - if (IsNumOnly) - { - RoomNumber = atol(filedir_entry->d_name); - ReadRoomNetConfigFile(&OneRNCFG, path); - if (OneRNCFG != NULL) - Put(RoomConfigs, LKEY(RoomNumber), OneRNCFG, vFreeRoomNetworkStruct); - - /* syslog(9, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */ - } - break; - default: - break; - } +/* + * Fetch the netconfig entry for a room, parse it, and return the data. + * Caller owns the returned memory and MUST free it using FreeRoomNetworkStruct() + */ +OneRoomNetCfg *CtdlGetNetCfgForRoom(long roomnum) +{ + OneRoomNetCfg *OneRNCfg = NULL; + char *serialized_config = NULL; + serialized_config = LoadRoomNetConfigFile(roomnum); + if (!serialized_config) return NULL; - } - free(d); - closedir(filedir); + OneRNCfg = ParseRoomNetConfigFile(serialized_config); + free(serialized_config); + return OneRNCfg; } /*-----------------------------------------------------------------------------* * Per room network configs : exchange with client * *-----------------------------------------------------------------------------*/ + void cmd_gnet(char *argbuf) { - char filename[PATH_MAX]; - char buf[SIZ]; - FILE *fp; - - - if (!IsEmptyStr(argbuf)) - { - if (CtdlAccessCheck(ac_aide)) return; - if (strcmp(argbuf, FILE_MAILALIAS)) - { - cprintf("%d No such file or directory\n", - ERROR + INTERNAL_ERROR); - return; - } - safestrncpy(filename, file_mail_aliases, sizeof(filename)); - cprintf("%d Settings for <%s>\n", - LISTING_FOLLOWS, - filename); - } - else - { - if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) { - /* users can edit the netconfigs for their own mailbox rooms */ - } - else if (CtdlAccessCheck(ac_room_aide)) return; - - assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); - cprintf("%d Network settings for room #%ld <%s>\n", - LISTING_FOLLOWS, - CC->room.QRnumber, CC->room.QRname); + if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) { + /* users can edit the netconfigs for their own mailbox rooms */ } + else if (CtdlAccessCheck(ac_room_aide)) return; + + cprintf("%d Network settings for room #%ld <%s>\n", LISTING_FOLLOWS, CC->room.QRnumber, CC->room.QRname); - fp = fopen(filename, "r"); - if (fp != NULL) { - while (fgets(buf, sizeof buf, fp) != NULL) { - buf[strlen(buf)-1] = 0; - cprintf("%s\n", buf); - } - fclose(fp); + char *c = LoadRoomNetConfigFile(CC->room.QRnumber); + if (c) { + cprintf("%s\n", c); + free(c); } - cprintf("000\n"); } -#define nForceAliases 5 -const ConstStr ForceAliases[nForceAliases] = { - {HKEY("bbs,")}, - {HKEY("root,")}, - {HKEY("Auto,")}, - {HKEY("postmaster,")}, - {HKEY("abuse,")} -}; - -void cmd_snet(char *argbuf) { - char tempfilename[PATH_MAX]; - char filename[PATH_MAX]; - int TmpFD; - StrBuf *Line; - struct stat StatBuf; - long len; + +void cmd_snet(char *argbuf) +{ + struct CitContext *CCC = CC; + StrBuf *Line = NULL; + StrBuf *TheConfig = NULL; int rc; - int IsMailAlias = 0; - int MailAliasesFound[nForceAliases]; unbuffer_output(); - - if (!IsEmptyStr(argbuf)) - { - if (CtdlAccessCheck(ac_aide)) return; - if (strcmp(argbuf, FILE_MAILALIAS)) - { - cprintf("%d No such file or directory\n", - ERROR + INTERNAL_ERROR); - return; - } - len = safestrncpy(filename, file_mail_aliases, sizeof(filename)); - memset(MailAliasesFound, 0, sizeof(MailAliasesFound)); - memcpy(tempfilename, filename, len + 1); - IsMailAlias = 1; - } - else - { - if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) { - /* users can edit the netconfigs for their own mailbox rooms */ - } - else if (CtdlAccessCheck(ac_room_aide)) return; - - len = assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); - memcpy(tempfilename, filename, len + 1); - } - memset(&StatBuf, 0, sizeof(struct stat)); - if ((stat(filename, &StatBuf) == -1) || (StatBuf.st_size == 0)) - StatBuf.st_size = 80; /* Not there or empty? guess 80 chars line. */ - - sprintf(tempfilename + len, ".%d", CC->cs_pid); - errno = 0; - TmpFD = open(tempfilename, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); - - if ((TmpFD > 0) && (errno == 0)) - { - char *tmp = malloc(StatBuf.st_size * 2); - memset(tmp, ' ', StatBuf.st_size * 2); - rc = write(TmpFD, tmp, StatBuf.st_size * 2); - free(tmp); - if ((rc <= 0) || (rc != StatBuf.st_size * 2)) - { - close(TmpFD); - cprintf("%d Unable to allocate the space required for %s: %s\n", - ERROR + INTERNAL_ERROR, - tempfilename, - strerror(errno)); - unlink(tempfilename); - return; - } - lseek(TmpFD, SEEK_SET, 0); - } - else { - cprintf("%d Unable to allocate the space required for %s: %s\n", - ERROR + INTERNAL_ERROR, - tempfilename, - strerror(errno)); - unlink(tempfilename); - return; - } Line = NewStrBuf(); + TheConfig = NewStrBuf(); + cprintf("%d send new netconfig now\n", SEND_LISTING); - cprintf("%d %s\n", SEND_LISTING, tempfilename); - - len = 0; - while (rc = CtdlClientGetLine(Line), - (rc >= 0)) + while (rc = CtdlClientGetLine(Line), (rc >= 0)) { if ((rc == 3) && (strcmp(ChrPtr(Line), "000") == 0)) break; - if (IsMailAlias) - { - int i; - - for (i = 0; i < nForceAliases; i++) - { - if ((!MailAliasesFound[i]) && - (strncmp(ForceAliases[i].Key, - ChrPtr(Line), - ForceAliases[i].len) == 0) - ) - { - MailAliasesFound[i] = 1; - break; - } - } - } - StrBufAppendBufPlain(Line, HKEY("\n"), 0); - write(TmpFD, ChrPtr(Line), StrLength(Line)); - len += StrLength(Line); + StrBufAppendBuf(TheConfig, Line, 0); + StrBufAppendBufPlain(TheConfig, HKEY("\n"), 0); } FreeStrBuf(&Line); - ftruncate(TmpFD, len); - close(TmpFD); - - if (IsMailAlias) - { - int i, state; - /* - * Sanity check whether all aliases required by the RFCs were set - * else bail out. - */ - state = 1; - for (i = 0; i < nForceAliases; i++) - { - if (!MailAliasesFound[i]) - state = 0; - } - if (state == 0) - { - cprintf("%d won't do this - you're missing an RFC required alias.\n", - ERROR + INTERNAL_ERROR); - unlink(tempfilename); - return; - } - } - /* Now copy the temp file to its permanent location. - * (We copy instead of link because they may be on different filesystems) - */ - begin_critical_section(S_NETCONFIGS); - rename(tempfilename, filename); - end_critical_section(S_NETCONFIGS); + write_netconfig_to_configdb(CCC->room.QRnumber, ChrPtr(TheConfig)); + FreeStrBuf(&TheConfig); } @@ -741,6 +575,7 @@ int is_recipient(OneRoomNetCfg *RNCfg, const char *Name) } nptr = nptr->next; } + i++; } return 0; } @@ -753,7 +588,6 @@ int CtdlNetconfigCheckRoomaccess( const char* RemoteIdentifier) { OneRoomNetCfg *RNCfg; - char filename[SIZ]; int found; if (RemoteIdentifier == NULL) @@ -762,18 +596,19 @@ int CtdlNetconfigCheckRoomaccess( return (ERROR + USERNAME_REQUIRED); } - assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); begin_critical_section(S_NETCONFIGS); - if (!ReadRoomNetConfigFile(&RNCfg, filename)) + RNCfg = CtdlGetNetCfgForRoom (CC->room.QRnumber); + if (RNCfg == NULL) { end_critical_section(S_NETCONFIGS); snprintf(errmsgbuf, n, "This mailing list only accepts posts from subscribers."); return (ERROR + NO_SUCH_USER); } - end_critical_section(S_NETCONFIGS); found = is_recipient (RNCfg, RemoteIdentifier); - vFreeRoomNetworkStruct(&RNCfg); + FreeRoomNetworkStruct(&RNCfg); + end_critical_section(S_NETCONFIGS); + if (found) { return (0); } @@ -824,12 +659,14 @@ void cmd_netp(char *cmdbuf) lens[0] = strlen(CCC->cs_addr); strs[1] = "SRV_UNKNOWN"; - lens[1] = sizeof("SRV_UNKNOWN" - 1); + lens[1] = sizeof("SRV_UNKNOWN") - 1; CtdlAideFPMessage( err_buf, "IGNet Networking.", - 2, strs, (long*) &lens); + 2, strs, (long*) &lens, + CCC->cs_pid, 0, + time(NULL)); DeleteHash(&working_ignetcfg); FreeStrBuf(&NodeStr); @@ -849,12 +686,15 @@ void cmd_netp(char *cmdbuf) lens[0] = strlen(CCC->cs_addr); strs[1] = "SRV_PW"; - lens[1] = sizeof("SRV_PW" - 1); + lens[1] = sizeof("SRV_PW") - 1; CtdlAideFPMessage( err_buf, "IGNet Networking.", - 2, strs, (long*) &lens); + 2, strs, + (long*) &lens, + CCC->cs_pid, 0, + time(NULL)); DeleteHash(&working_ignetcfg); FreeStrBuf(&NodeStr); @@ -870,7 +710,7 @@ void cmd_netp(char *cmdbuf) } nodelen = safestrncpy(CCC->net_node, node, sizeof CCC->net_node); CtdlNetworkTalkingTo(CCC->net_node, nodelen, NTT_ADD); - syslog(LOG_NOTICE, "Network node <%s> logged in from %s [%s]\n", + syslog(LOG_NOTICE, "Network node <%s> logged in from %s [%s]", CCC->net_node, CCC->cs_host, CCC->cs_addr ); cprintf("%d authenticated as network node '%s'\n", CIT_OK, CCC->net_node); @@ -1029,7 +869,7 @@ int CtdlIsValidNode(const StrBuf **nexthop, * First try the neighbor nodes */ if (GetCount(IgnetCfg) == 0) { - syslog(LOG_INFO, "IgnetCfg is empty!\n"); + syslog(LOG_INFO, "IgnetCfg is empty!"); if (nexthop != NULL) { *nexthop = NULL; } @@ -1061,11 +901,60 @@ int CtdlIsValidNode(const StrBuf **nexthop, /* * If we get to this point, the supplied node name is bogus. */ - syslog(LOG_ERR, "Invalid node name <%s>\n", ChrPtr(node)); + syslog(LOG_ERR, "Invalid node name <%s>", ChrPtr(node)); return(-1); } +/* + * Convert any legacy configuration files in the "netconfigs" directory + */ +void convert_legacy_netcfg_files(void) +{ + DIR *dh = NULL; + struct dirent *dit = NULL; + char filename[PATH_MAX]; + long roomnum; + FILE *fp; + long len; + char *v; + + dh = opendir(ctdl_netcfg_dir); + if (!dh) return; + + syslog(LOG_INFO, "Legacy netconfig files exist - converting them!"); + + while (dit = readdir(dh), dit != NULL) { // yes, we use the non-reentrant version; we're not in threaded mode yet + roomnum = atol(dit->d_name); + if (roomnum > 0) { + snprintf(filename, sizeof filename, "%s/%ld", ctdl_netcfg_dir, roomnum); + fp = fopen(filename, "r"); + if (fp) { + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + if (len > 0) { + v = malloc(len); + if (v) { + rewind(fp); + if (fread(v, len, 1, fp)) { + write_netconfig_to_configdb(roomnum, v); + unlink(filename); + } + free(v); + } + } + else { + unlink(filename); // zero length netconfig, just delete it + } + fclose(fp); + } + } + } + + closedir(dh); + rmdir(ctdl_netcfg_dir); +} + /* @@ -1075,7 +964,7 @@ CTDL_MODULE_INIT(netconfig) { if (!threading) { - LoadAllNetConfigs (); + convert_legacy_netcfg_files(); CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config"); CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config"); CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller");