NetworkConfig: move to RoomNetworkConfig; move NTT-List into its own file.
authorWilfried Goesgens <dothebart@citadel.org>
Tue, 1 Jan 2013 15:28:43 +0000 (16:28 +0100)
committerWilfried Goesgens <dothebart@citadel.org>
Tue, 1 Jan 2013 15:28:43 +0000 (16:28 +0100)
13 files changed:
citadel/Makefile.in
citadel/include/ctdl_module.h
citadel/modules/network/netconfig.h
citadel/modules/network/netspool.h
citadel/modules/network/serv_netconfig.c
citadel/modules/network/serv_netmail.c
citadel/modules/network/serv_netspool.c
citadel/modules/network/serv_network.c
citadel/modules/network/serv_network.h
citadel/modules/network/serv_networkclient.c
citadel/msgbase.c
citadel/netconfig.c
citadel/nttlist.c [new file with mode: 0644]

index c2ecdb7ee58541899d2c6379aef1d0e92855e758..d6210e08c3629a0c72d620506ec3e454bc22d04a 100644 (file)
@@ -83,7 +83,7 @@ SOURCES=utils/aidepost.c utils/citmail.c \
        locate_host.c md5.c auth.c msgbase.c parsedate.c \
        room_ops.c euidindex.c server_main.c ldap.c \
        support.c sysdep.c user_ops.c journaling.c threads.c \
-       context.c event_client.c netconfig.c
+       context.c event_client.c netconfig.c nttlist.c
 
 
 include Make_sources
@@ -138,7 +138,7 @@ SERV_OBJS = server_main.o utillib/citadel_dirs.o event_client.o \
        internet_addressing.o journaling.o \
        parsedate.o genstamp.o ecrash.o threads.o context.o \
        clientsocket.o modules_init.o modules_upgrade.o $(SERV_MODULES) \
-       svn_revision.o ldap.o netconfig.o
+       svn_revision.o ldap.o netconfig.o nttlist.o
 
 citserver$(EXEEXT): $(SERV_OBJS)
        $(CC) $(SERV_OBJS) $(LDFLAGS) $(SERVER_LDFLAGS) $(LIBS) $(SERVER_LIBS) $(RESOLV) -o citserver$(EXEEXT)
index eddcbeffcc92df2cfe961eb23cb9001200a8518b..7dad38745dd8c472f82c9658775a8b2b466db805 100644 (file)
@@ -416,7 +416,50 @@ void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomN
 void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data);
 
 
+typedef struct _nodeconf {
+       int DeleteMe;
+       StrBuf *NodeName;
+       StrBuf *Secret;
+       StrBuf *Host;
+       StrBuf *Port;
+}CtdlNodeConf;
 
+HashList* CtdlLoadIgNetCfg(void);
+
+
+int CtdlNetconfigCheckRoomaccess(char *errmsgbuf, 
+                                size_t n,
+                                const char* RemoteIdentifier);
+
+
+typedef struct __NetMap {
+       StrBuf *NodeName;
+       time_t lastcontact;
+       StrBuf *NextHop;
+}CtdlNetMap;
+
+HashList* CtdlReadNetworkMap(void);
+StrBuf *CtdlSerializeNetworkMap(HashList *Map);
+void NetworkLearnTopology(char *node, char *path, HashList *the_netmap, int *netmap_changed);
+int CtdlIsValidNode(const StrBuf **nexthop,
+                   const StrBuf **secret,
+                   StrBuf *node,
+                   HashList *IgnetCfg,
+                   HashList *the_netmap);
+
+
+
+
+int CtdlNetworkTalkingTo(const char *nodename, long len, int operation);
+
+/*
+ * Operations that can be performed by network_talking_to()
+ */
+enum {
+        NTT_ADD,
+        NTT_REMOVE,
+        NTT_CHECK
+};
 
 /*
  * Expose API calls from user_ops.c
index 6168f0402487eda1fc21d11be02b8b575b591463..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,54 +0,0 @@
-/*
- * This module handles shared rooms, inter-Citadel mail, and outbound
- * mailing list processing.
- *
- * Copyright (c) 2000-2012 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 as published by
- *  the Free Software Foundation; either version 3 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * ** NOTE **   A word on the S_NETCONFIGS semaphore:
- * This is a fairly high-level type of critical section.  It ensures that no
- * two threads work on the netconfigs files at the same time.  Since we do
- * so many things inside these, here are the rules:
- *  1. begin_critical_section(S_NETCONFIGS) *before* begin_ any others.
- *  2. Do *not* perform any I/O with the client during these sections.
- *
- */
-
-typedef struct _nodeconf {
-       int DeleteMe;
-       StrBuf *NodeName;
-       StrBuf *Secret;
-       StrBuf *Host;
-       StrBuf *Port;
-}NodeConf;
-
-typedef struct __NetMap {
-       StrBuf *NodeName;
-       time_t lastcontact;
-       StrBuf *NextHop;
-}NetMap;
-
-HashList* load_ignetcfg(void);
-
-HashList* read_network_map(void);
-StrBuf *SerializeNetworkMap(HashList *Map);
-void network_learn_topology(char *node, char *path, HashList *the_netmap, int *netmap_changed);
-
-int is_valid_node(const StrBuf **nexthop,
-                 const StrBuf **secret,
-                 StrBuf *node,
-                 HashList *IgnetCfg,
-                 HashList *the_netmap);
index 34e13acae9ddebcf1654c99143ce1600dd5a72fa..7d751727791a3376f07402f2619fbda7cd0b0b8d 100644 (file)
  *
  */
 
-typedef struct maplist maplist;
+typedef struct MapList MapList;
 
-struct maplist {
-       struct maplist *next;
+struct MapList {
+       MapList *next;
        StrBuf *remote_nodename;
        StrBuf *remote_roomname;
 };
@@ -56,4 +56,3 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
 void free_spoolcontrol_struct(SpoolControl **scc);
 int writenfree_spoolcontrol_file(SpoolControl **scc, char *filename);
 int read_spoolcontrol_file(SpoolControl **scc, char *filename);
-int is_recipient(OneRoomNetCfg *RNCfg, const char *Name);
index 34ef2529bb94e3b69e84e1f93dab344aca9f34a5..94aeb62d3e73e224e9fabb1b0f0f355911f39420 100644 (file)
 
 
 
-void DeleteNodeConf(void *vNode)
-{
-       NodeConf *Node = (NodeConf*) vNode;
-       FreeStrBuf(&Node->NodeName);
-       FreeStrBuf(&Node->Secret);
-       FreeStrBuf(&Node->Host);
-       FreeStrBuf(&Node->Port);
-       free(Node);
-}
-
-NodeConf *NewNode(StrBuf *SerializedNode)
-{
-       const char *Pos = NULL;
-       NodeConf *Node;
-
-       /* we need at least 4 pipes and some other text so its invalid. */
-       if (StrLength(SerializedNode) < 8)
-               return NULL;
-       Node = (NodeConf *) malloc(sizeof(NodeConf));
-
-       Node->DeleteMe = 0;
-
-       Node->NodeName=NewStrBuf();
-       StrBufExtract_NextToken(Node->NodeName, SerializedNode, &Pos, '|');
-
-       Node->Secret=NewStrBuf();
-       StrBufExtract_NextToken(Node->Secret, SerializedNode, &Pos, '|');
-
-       Node->Host=NewStrBuf();
-       StrBufExtract_NextToken(Node->Host, SerializedNode, &Pos, '|');
-
-       Node->Port=NewStrBuf();
-       StrBufExtract_NextToken(Node->Port, SerializedNode, &Pos, '|');
-       return Node;
-}
-
-
-/*
- * Load or refresh the Citadel network (IGnet) configuration for this node.
- */
-HashList* load_ignetcfg(void)
-{
-       const char *LinePos;
-       char       *Cfg;
-       StrBuf     *Buf;
-       StrBuf     *LineBuf;
-       HashList   *Hash;
-       NodeConf   *Node;
-
-       Cfg =  CtdlGetSysConfig(IGNETCFG);
-       if ((Cfg == NULL) || IsEmptyStr(Cfg)) {
-               if (Cfg != NULL)
-                       free(Cfg);
-               return NULL;
-       }
-
-       Hash = NewHash(1, NULL);
-       Buf = NewStrBufPlain(Cfg, -1);
-       free(Cfg);
-       LineBuf = NewStrBufPlain(NULL, StrLength(Buf));
-       LinePos = NULL;
-       do
-       {
-               StrBufSipLine(LineBuf, Buf, &LinePos);
-               if (StrLength(LineBuf) != 0) {
-                       Node = NewNode(LineBuf);
-                       if (Node != NULL) {
-                               Put(Hash, SKEY(Node->NodeName), Node, DeleteNodeConf);
-                       }
-               }
-       } while (LinePos != StrBufNOTNULL);
-       FreeStrBuf(&Buf);
-       FreeStrBuf(&LineBuf);
-       return Hash;
-}
-
-void DeleteNetMap(void *vNetMap)
-{
-       NetMap *TheNetMap = (NetMap*) vNetMap;
-       FreeStrBuf(&TheNetMap->NodeName);
-       FreeStrBuf(&TheNetMap->NextHop);
-       free(TheNetMap);
-}
-
-NetMap *NewNetMap(StrBuf *SerializedNetMap)
-{
-       const char *Pos = NULL;
-       NetMap *NM;
-
-       /* we need at least 3 pipes and some other text so its invalid. */
-       if (StrLength(SerializedNetMap) < 6)
-               return NULL;
-       NM = (NetMap *) malloc(sizeof(NetMap));
-
-       NM->NodeName=NewStrBuf();
-       StrBufExtract_NextToken(NM->NodeName, SerializedNetMap, &Pos, '|');
-
-       NM->lastcontact = StrBufExtractNext_long(SerializedNetMap, &Pos, '|');
-
-       NM->NextHop=NewStrBuf();
-       StrBufExtract_NextToken(NM->NextHop, SerializedNetMap, &Pos, '|');
-
-       return NM;
-}
-
-HashList* read_network_map(void)
-{
-       const char *LinePos;
-       char       *Cfg;
-       StrBuf     *Buf;
-       StrBuf     *LineBuf;
-       HashList   *Hash;
-       NetMap     *TheNetMap;
-
-       Cfg =  CtdlGetSysConfig(IGNETMAP);
-       if ((Cfg == NULL) || IsEmptyStr(Cfg)) {
-               if (Cfg != NULL)
-                       free(Cfg);
-               return NULL;
-       }
-
-       Hash = NewHash(1, NULL);
-       Buf = NewStrBufPlain(Cfg, -1);
-       free(Cfg);
-       LineBuf = NewStrBufPlain(NULL, StrLength(Buf));
-       LinePos = NULL;
-       while (StrBufSipLine(Buf, LineBuf, &LinePos))
-       {
-               TheNetMap = NewNetMap(LineBuf);
-               if (TheNetMap != NULL) { /* TODO: is the NodeName Uniq? */
-                       Put(Hash, SKEY(TheNetMap->NodeName), TheNetMap, DeleteNetMap);
-               }
-       }
-       FreeStrBuf(&Buf);
-       FreeStrBuf(&LineBuf);
-       return Hash;
-}
-
-StrBuf *SerializeNetworkMap(HashList *Map)
-{
-       void *vMap;
-       const char *key;
-       long len;
-       StrBuf *Ret = NewStrBuf();
-       HashPos *Pos = GetNewHashPos(Map, 0);
-
-       while (GetNextHashPos(Map, Pos, &len, &key, &vMap))
-       {
-               NetMap *pMap = (NetMap*) vMap;
-               StrBufAppendBuf(Ret, pMap->NodeName, 0);
-               StrBufAppendBufPlain(Ret, HKEY("|"), 0);
-
-               StrBufAppendPrintf(Ret, "%ld", pMap->lastcontact, 0);
-               StrBufAppendBufPlain(Ret, HKEY("|"), 0);
-
-               StrBufAppendBuf(Ret, pMap->NextHop, 0);
-               StrBufAppendBufPlain(Ret, HKEY("\n"), 0);
-       }
-       DeleteHashPos(&Pos);
-       return Ret;
-}
-
-
-/*
- * Learn topology from path fields
- */
-void network_learn_topology(char *node, char *path, HashList *the_netmap, int *netmap_changed)
-{
-       NetMap *pNM = NULL;
-       void *vptr;
-       char nexthop[256];
-       NetMap *nmptr;
-
-       if (GetHash(the_netmap, node, strlen(node), &vptr) && 
-           (vptr != NULL))/* TODO: is the NodeName Uniq? */
-       {
-               pNM = (NetMap*)vptr;
-               extract_token(nexthop, path, 0, '!', sizeof nexthop);
-               if (!strcmp(nexthop, ChrPtr(pNM->NextHop))) {
-                       pNM->lastcontact = time(NULL);
-                       (*netmap_changed) ++;
-                       return;
-               }
-       }
-
-       /* If we got here then it's not in the map, so add it. */
-       nmptr = (NetMap *) malloc(sizeof (NetMap));
-       nmptr->NodeName = NewStrBufPlain(node, -1);
-       nmptr->lastcontact = time(NULL);
-       nmptr->NextHop = NewStrBuf ();
-       StrBufExtract_tokenFromStr(nmptr->NextHop, path, strlen(path), 0, '!');
-       /* TODO: is the NodeName Uniq? */
-       Put(the_netmap, SKEY(nmptr->NodeName), nmptr, DeleteNetMap);
-       (*netmap_changed) ++;
-}
-
-
-/*
- * Check the network map and determine whether the supplied node name is
- * valid.  If it is not a neighbor node, supply the name of a neighbor node
- * which is the next hop.  If it *is* a neighbor node, we also fill in the
- * shared secret.
- */
-int is_valid_node(const StrBuf **nexthop,
-                 const StrBuf **secret,
-                 StrBuf *node,
-                 HashList *IgnetCfg,
-                 HashList *the_netmap)
-{
-       void *vNetMap;
-       void *vNodeConf;
-       NodeConf *TheNode;
-       NetMap *TheNetMap;
-
-       if (StrLength(node) == 0) {
-               return(-1);
-       }
-
-       /*
-        * First try the neighbor nodes
-        */
-       if (GetCount(IgnetCfg) == 0) {
-               syslog(LOG_INFO, "IgnetCfg is empty!\n");
-               if (nexthop != NULL) {
-                       *nexthop = NULL;
-               }
-               return(-1);
-       }
-
-       /* try to find a neigbour with the name 'node' */
-       if (GetHash(IgnetCfg, SKEY(node), &vNodeConf) && 
-           (vNodeConf != NULL))
-       {
-               TheNode = (NodeConf*)vNodeConf;
-               if (secret != NULL)
-                       *secret = TheNode->Secret;
-               return 0;               /* yup, it's a direct neighbor */
-       }
-
-       /*
-        * If we get to this point we have to see if we know the next hop
-        *//* TODO: is the NodeName Uniq? */
-       if ((GetCount(the_netmap) > 0) &&
-           (GetHash(the_netmap, SKEY(node), &vNetMap)))
-       {
-               TheNetMap = (NetMap*)vNetMap;
-               if (nexthop != NULL)
-                       *nexthop = TheNetMap->NextHop;
-               return(0);
-       }
-
-       /*
-        * If we get to this point, the supplied node name is bogus.
-        */
-       syslog(LOG_ERR, "Invalid node name <%s>\n", ChrPtr(node));
-       return(-1);
-}
-
-
-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);
-       }
-
-       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);
-       }
-
-       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;
-       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();
-
-       cprintf("%d %s\n", SEND_LISTING, tempfilename);
-
-       len = 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);
-       }
-       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);
-}
-
-/*
- * cmd_netp() - authenticate to the server as another Citadel node polling
- *           for network traffic
- */
-void cmd_netp(char *cmdbuf)
-{
-       struct CitContext *CCC = CC;
-       HashList *working_ignetcfg;
-       char *node;
-       StrBuf *NodeStr;
-       long nodelen;
-       int v;
-       long lens[2];
-       const char *strs[2];
-
-       const StrBuf *secret = NULL;
-       const StrBuf *nexthop = NULL;
-       char err_buf[SIZ] = "";
-
-       /* Authenticate */
-       node = CCC->curr_user;
-       nodelen = extract_token(CCC->curr_user, cmdbuf, 0, '|', sizeof CCC->curr_user);
-       NodeStr = NewStrBufPlain(node, nodelen);
-       /* load the IGnet Configuration to check node validity */
-       working_ignetcfg = load_ignetcfg();
-       v = is_valid_node(&nexthop, &secret, NodeStr, working_ignetcfg, NULL);
-       if (v != 0) {
-               snprintf(err_buf, sizeof err_buf,
-                       "An unknown Citadel server called \"%s\" attempted to connect from %s [%s].\n",
-                       node, CCC->cs_host, CCC->cs_addr
-               );
-               syslog(LOG_WARNING, "%s", err_buf);
-               cprintf("%d authentication failed\n", ERROR + PASSWORD_REQUIRED);
-
-               strs[0] = CCC->cs_addr;
-               lens[0] = strlen(CCC->cs_addr);
-               
-               strs[1] = "SRV_UNKNOWN";
-               lens[1] = sizeof("SRV_UNKNOWN" - 1);
-
-               CtdlAideFPMessage(
-                       err_buf,
-                       "IGNet Networking.",
-                       2, strs, (long*) &lens);
-
-               DeleteHash(&working_ignetcfg);
-               FreeStrBuf(&NodeStr);
-               return;
-       }
-
-       extract_token(CCC->user.password, cmdbuf, 1, '|', sizeof CCC->user.password);
-       if (strcasecmp(CCC->user.password, ChrPtr(secret))) {
-               snprintf(err_buf, sizeof err_buf,
-                       "A Citadel server at %s [%s] failed to authenticate as network node \"%s\".\n",
-                       CCC->cs_host, CCC->cs_addr, node
-               );
-               syslog(LOG_WARNING, "%s", err_buf);
-               cprintf("%d authentication failed\n", ERROR + PASSWORD_REQUIRED);
-
-               strs[0] = CCC->cs_addr;
-               lens[0] = strlen(CCC->cs_addr);
-               
-               strs[1] = "SRV_PW";
-               lens[1] = sizeof("SRV_PW" - 1);
-
-               CtdlAideFPMessage(
-                       err_buf,
-                       "IGNet Networking.",
-                       2, strs, (long*) &lens);
-
-               DeleteHash(&working_ignetcfg);
-               FreeStrBuf(&NodeStr);
-               return;
-       }
-
-       if (network_talking_to(node, nodelen, NTT_CHECK)) {
-               syslog(LOG_WARNING, "Duplicate session for network node <%s>", node);
-               cprintf("%d Already talking to %s right now\n", ERROR + RESOURCE_BUSY, node);
-               DeleteHash(&working_ignetcfg);
-               FreeStrBuf(&NodeStr);
-               return;
-       }
-       nodelen = safestrncpy(CCC->net_node, node, sizeof CCC->net_node);
-       network_talking_to(CCC->net_node, nodelen, NTT_ADD);
-       syslog(LOG_NOTICE, "Network node <%s> logged in from %s [%s]\n",
-               CCC->net_node, CCC->cs_host, CCC->cs_addr
-       );
-       cprintf("%d authenticated as network node '%s'\n", CIT_OK, CCC->net_node);
-       DeleteHash(&working_ignetcfg);
-       FreeStrBuf(&NodeStr);
-}
-
-int netconfig_check_roomaccess(
-       char *errmsgbuf, 
-       size_t n,
-       const char* RemoteIdentifier)
-{
-       SpoolControl *sc;
-       char filename[SIZ];
-       int found;
-
-       if (RemoteIdentifier == NULL)
-       {
-               snprintf(errmsgbuf, n, "Need sender to permit access.");
-               return (ERROR + USERNAME_REQUIRED);
-       }
-
-       assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir);
-       begin_critical_section(S_NETCONFIGS);
-       if (!read_spoolcontrol_file(&sc, filename))
-       {
-               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 (sc->RNCfg, RemoteIdentifier);
-       free_spoolcontrol_struct(&sc);
-       if (found) {
-               return (0);
-       }
-       else {
-               snprintf(errmsgbuf, n,
-                        "This mailing list only accepts posts from subscribers.");
-               return (ERROR + NO_SUCH_USER);
-       }
-}
-/*
- * Module entry point
- */
-CTDL_MODULE_INIT(netconfig)
-{
-       if (!threading)
-       {
-               CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
-               CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");
-               CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller");
-       }
-       return "netconfig";
-}
index 2078c32cc1b1672292dea87556dbd449e5c9097d..b440105be14f0dd533971879ef328a57949683ba 100644 (file)
@@ -264,7 +264,7 @@ void network_spool_msg(long msgnum,
        char *newpath = NULL;
        struct CtdlMessage *msg = NULL;
        RoomNetCfgLine *nptr;
-       maplist *mptr;
+       MapList *mptr;
        struct ser_ret sermsg;
        FILE *fp;
        char filename[PATH_MAX];
@@ -466,11 +466,11 @@ void network_spool_msg(long msgnum,
                                }
 
                                Buf = NewStrBufPlain(msg->cm_fields['N'], -1);
-                               if (is_valid_node(NULL,
-                                                 NULL,
-                                                 Buf,
-                                                 sc->working_ignetcfg,
-                                                 sc->the_netmap) == 0)
+                               if (CtdlIsValidNode(NULL,
+                                                   NULL,
+                                                   Buf,
+                                                   sc->working_ignetcfg,
+                                                   sc->the_netmap) == 0)
                                {
                                        ok_to_participate = 1;
                                }
@@ -552,18 +552,18 @@ void network_spool_msg(long msgnum,
 
                /* Now send it to every node */
                if (sc->RNCfg->NetConfigs[ignet_push_share] != NULL)
-               for (mptr = (maplist*)sc->RNCfg->NetConfigs[ignet_push_share]; mptr != NULL;
+               for (mptr = (MapList*)sc->RNCfg->NetConfigs[ignet_push_share]; mptr != NULL;
                    mptr = mptr->next) {
 
                        send = 1;
                        NewStrBufDupAppendFlush(&Buf, mptr->remote_nodename, NULL, 1);
 
                        /* Check for valid node name */
-                       if (is_valid_node(NULL,
-                                         NULL,
-                                         Buf,
-                                         sc->working_ignetcfg,
-                                         sc->the_netmap) != 0)
+                       if (CtdlIsValidNode(NULL,
+                                           NULL,
+                                           Buf,
+                                           sc->working_ignetcfg,
+                                           sc->the_netmap) != 0)
                        {
                                QN_syslog(LOG_ERR,
                                          "Invalid node <%s>\n",
index d66161bcc9429fe19f6f9d7c2b63cedc35c16a0e..040930b3e7b0124fc01caa85098ed2da2d019f5c 100644 (file)
@@ -157,37 +157,6 @@ void SerializeIgnetPushShare(const CfgLineType *ThisOne, StrBuf *OutputBuffer, O
        StrBufAppendBufPlain(OutputBuffer, HKEY("\n"), 0);
 }
 
-int is_recipient(OneRoomNetCfg *RNCfg, const char *Name)
-{
-       const RoomNetCfg RecipientCfgs[] = {
-               listrecp,
-               digestrecp,
-               participate,
-               maxRoomNetCfg
-       };
-       int i;
-       RoomNetCfgLine *nptr;
-       size_t len;
-       
-       len = strlen(Name);
-       i = 0;
-       while (RecipientCfgs[i] != maxRoomNetCfg)
-       {
-               nptr = RNCfg->NetConfigs[RecipientCfgs[i]];
-               
-               while (nptr != NULL)
-               {
-                       if ((StrLength(nptr->Value) == len) && 
-                           (!strcmp(Name, ChrPtr(nptr->Value))))
-                       {
-                               return 1;
-                       }
-                       nptr = nptr->next;
-               }
-       }
-       return 0;
-}
-
 
 /*
  * Batch up and send all outbound traffic from the current room
@@ -313,11 +282,11 @@ void network_process_buffer(char *buffer, long size, HashList *working_ignetcfg,
 
                        /* route the message */
                        Buf = NewStrBufPlain(msg->cm_fields['D'], -1);
-                       if (is_valid_node(&nexthop, 
-                                         NULL, 
-                                         Buf, 
-                                         working_ignetcfg, 
-                                         the_netmap) == 0) 
+                       if (CtdlIsValidNode(&nexthop, 
+                                           NULL, 
+                                           Buf, 
+                                           working_ignetcfg, 
+                                           the_netmap) == 0) 
                        {
                                /* prepend our node to the path */
                                if (msg->cm_fields['P'] != NULL) {
@@ -389,10 +358,10 @@ void network_process_buffer(char *buffer, long size, HashList *working_ignetcfg,
 
        /* Learn network topology from the path */
        if ((msg->cm_fields['N'] != NULL) && (msg->cm_fields['P'] != NULL)) {
-               network_learn_topology(msg->cm_fields['N'], 
-                                      msg->cm_fields['P'], 
-                                      the_netmap, 
-                                      netmap_changed);
+               NetworkLearnTopology(msg->cm_fields['N'], 
+                                    msg->cm_fields['P'], 
+                                    the_netmap, 
+                                    netmap_changed);
        }
 
        /* Is the sending node giving us a very persuasive suggestion about
@@ -673,7 +642,7 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
                         ChrPtr(NextHop));
 
                QN_syslog(LOG_DEBUG, "Consolidate %s to %s\n", filename, ChrPtr(NextHop));
-               if (network_talking_to(SKEY(NextHop), NTT_CHECK)) {
+               if (CtdlNetworkTalkingTo(SKEY(NextHop), NTT_CHECK)) {
                        nFailed++;
                        QN_syslog(LOG_DEBUG,
                                  "Currently online with %s - skipping for now\n",
@@ -685,7 +654,7 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
                        size_t fsize;
                        int infd, outfd;
                        const char *err = NULL;
-                       network_talking_to(SKEY(NextHop), NTT_ADD);
+                       CtdlNetworkTalkingTo(SKEY(NextHop), NTT_ADD);
 
                        infd = open(filename, O_RDONLY);
                        if (infd == -1) {
@@ -694,7 +663,7 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
                                          "failed to open %s for reading due to %s; skipping.\n",
                                          filename, strerror(errno)
                                        );
-                               network_talking_to(SKEY(NextHop), NTT_REMOVE);
+                               CtdlNetworkTalkingTo(SKEY(NextHop), NTT_REMOVE);
                                continue;                               
                        }
                        
@@ -714,7 +683,7 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
                                          spooloutfilename, strerror(errno)
                                        );
                                close(infd);
-                               network_talking_to(SKEY(NextHop), NTT_REMOVE);
+                               CtdlNetworkTalkingTo(SKEY(NextHop), NTT_REMOVE);
                                continue;
                        }
 
@@ -748,7 +717,7 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
                        FDIOBufferDelete(&FDIO);
                        close(infd);
                        close(outfd);
-                       network_talking_to(SKEY(NextHop), NTT_REMOVE);
+                       CtdlNetworkTalkingTo(SKEY(NextHop), NTT_REMOVE);
                }
        }
        closedir(dp);
@@ -814,11 +783,11 @@ void network_consolidate_spoolout(HashList *working_ignetcfg, HashList *the_netm
                        filedir_entry->d_name
                );
 
-               i = is_valid_node(&nexthop,
-                                 NULL,
-                                 NextHop,
-                                 working_ignetcfg,
-                                 the_netmap);
+               i = CtdlIsValidNode(&nexthop,
+                                   NULL,
+                                   NextHop,
+                                   working_ignetcfg,
+                                   the_netmap);
        
                if ( (i != 0) || (StrLength(nexthop) > 0) ) {
                        unlink(filename);
index 094aedf73585e6675eb7a72504c3b00f4d0a8813..ff579cb5f2305d844fcc8cf2403d0a8f9e95cad4 100644 (file)
@@ -254,7 +254,7 @@ int network_sync_to(char *target_node, long len)
        }
 
        sc.working_ignetcfg = load_ignetcfg();
-       sc.the_netmap = read_network_map();
+       sc.the_netmap = CtdlReadNetworkMap();
 
        /* Send ALL messages */
        num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL,
@@ -554,13 +554,13 @@ void network_do_queue(void)
                        return;
        }
        /* Load the IGnet Configuration into memory */
-       working_ignetcfg = load_ignetcfg();
+       working_ignetcfg = CtdlLoadIgNetCfg();
 
        /*
         * Load the network map and filter list into memory.
         */
        if (!server_shutting_down)
-               the_netmap = read_network_map();
+               the_netmap = CtdlReadNetworkMap();
        if (!server_shutting_down)
                load_network_filter_list();
 
@@ -612,7 +612,7 @@ void network_do_queue(void)
 
        /* Save the network map back to disk */
        if (netmap_changed) {
-               StrBuf *MapStr = SerializeNetworkMap(the_netmap);
+               StrBuf *MapStr = CtdlSerializeNetworkMap(the_netmap);
                CtdlPutSysConfig(IGNETMAP, SmashStrBuf(&MapStr));
        }
 
@@ -644,60 +644,6 @@ int network_room_handler (struct ctdlroom *room)
        return 0;
 }
 
-int NTTDebugEnabled = 0;
-
-/*
- * network_talking_to()  --  concurrency checker
- */
-static HashList *nttlist = NULL;
-int network_talking_to(const char *nodename, long len, int operation) {
-
-       int retval = 0;
-       HashPos *Pos = NULL;
-       void *vdata;
-
-       begin_critical_section(S_NTTLIST);
-
-       switch(operation) {
-
-               case NTT_ADD:
-                       if (nttlist == NULL) 
-                               nttlist = NewHash(1, NULL);
-                       Put(nttlist, nodename, len, NewStrBufPlain(nodename, len), HFreeStrBuf);
-                       if (NTTDebugEnabled) syslog(LOG_DEBUG, "nttlist: added <%s>\n", nodename);
-                       break;
-               case NTT_REMOVE:
-                       if ((nttlist == NULL) ||
-                           (GetCount(nttlist) == 0))
-                               break;
-                       Pos = GetNewHashPos(nttlist, 1);
-                       if (GetHashPosFromKey (nttlist, nodename, len, Pos))
-                               DeleteEntryFromHash(nttlist, Pos);
-                       DeleteHashPos(&Pos);
-                       if (NTTDebugEnabled) syslog(LOG_DEBUG, "nttlist: removed <%s>\n", nodename);
-
-                       break;
-
-               case NTT_CHECK:
-                       if ((nttlist == NULL) ||
-                           (GetCount(nttlist) == 0))
-                               break;
-                       if (GetHash(nttlist, nodename, len, &vdata))
-                               retval ++;
-                       if (NTTDebugEnabled) syslog(LOG_DEBUG, "nttlist: have [%d] <%s>\n", retval, nodename);
-                       break;
-       }
-
-       end_critical_section(S_NTTLIST);
-       return(retval);
-}
-
-void cleanup_nttlist(void)
-{
-        begin_critical_section(S_NTTLIST);
-       DeleteHash(&nttlist);
-        end_critical_section(S_NTTLIST);
-}
 
 
 
@@ -709,7 +655,7 @@ void network_logout_hook(void)
         * If we were talking to a network node, we're not anymore...
         */
        if (!IsEmptyStr(CCC->net_node)) {
-               network_talking_to(CCC->net_node, strlen(CCC->net_node), NTT_REMOVE);
+               CtdlNetworkTalkingTo(CCC->net_node, strlen(CCC->net_node), NTT_REMOVE);
                CCC->net_node[0] = '\0';
        }
 }
@@ -718,7 +664,7 @@ void network_cleanup_function(void)
        struct CitContext *CCC = CC;
 
        if (!IsEmptyStr(CCC->net_node)) {
-               network_talking_to(CCC->net_node, strlen(CCC->net_node), NTT_REMOVE);
+               CtdlNetworkTalkingTo(CCC->net_node, strlen(CCC->net_node), NTT_REMOVE);
                CCC->net_node[0] = '\0';
        }
 }
@@ -727,10 +673,7 @@ void network_cleanup_function(void)
 /*
  * Module entry point
  */
-void SetNTTDebugEnabled(const int n)
-{
-       NTTDebugEnabled = n;
-}
+
 void SetNetQDebugEnabled(const int n)
 {
        NetQDebugEnabled = n;
@@ -741,9 +684,7 @@ CTDL_MODULE_INIT(network)
        if (!threading)
        {
                CtdlFillSystemContext(&networker_spool_CC, "CitNetSpool");
-               CtdlRegisterDebugFlagHook(HKEY("networktalkingto"), SetNTTDebugEnabled, &NTTDebugEnabled);
                CtdlRegisterDebugFlagHook(HKEY("networkqueue"), SetNetQDebugEnabled, &NetQDebugEnabled);
-               CtdlRegisterCleanupHook(cleanup_nttlist);
                CtdlRegisterSessionHook(network_cleanup_function, EVT_STOP, PRIO_STOP + 30);
                 CtdlRegisterSessionHook(network_logout_hook, EVT_LOGOUT, PRIO_LOGOUT + 10);
                CtdlRegisterProtoHook(cmd_nsyn, "NSYN", "Synchronize room to node");
index 1cc61f46068a80d0b8f291b7d92a1c0ed01544b6..7de793905f76699979d801c97b1f105940af756e 100644 (file)
@@ -42,13 +42,3 @@ void network_queue_room(struct ctdlroom *, void *);
 void network_bounce(struct CtdlMessage *msg, char *reason);
 int network_usetable(struct CtdlMessage *msg);
 
-int network_talking_to(const char *nodename, long len, int operation);
-
-/*
- * Operations that can be performed by network_talking_to()
- */
-enum {
-        NTT_ADD,
-        NTT_REMOVE,
-        NTT_CHECK
-};
index 92ae1f78bec986f286ea3c3e14bf1fdd57f5bc19..c3cd1e700bb31a3934e29958231469da6aba743b 100644 (file)
@@ -71,7 +71,6 @@
 #include "citadel_dirs.h"
 #include "threads.h"
 #include "context.h"
-#include "netconfig.h"
 #include "ctdl_module.h"
 
 struct CitContext networker_client_CC;
@@ -220,7 +219,7 @@ eNextState FinalizeNetworker(AsyncIO *IO)
 {
        AsyncNetworker *NW = (AsyncNetworker *)IO->Data;
 
-       network_talking_to(SKEY(NW->node), NTT_REMOVE);
+       CtdlNetworkTalkingTo(SKEY(NW->node), NTT_REMOVE);
 
        DeleteNetworker(IO->Data);
        return eAbort;
@@ -957,7 +956,7 @@ static int NetworkerCount = 0;
 void RunNetworker(AsyncNetworker *NW)
 {
        NW->n = NetworkerCount++;
-       network_talking_to(SKEY(NW->node), NTT_ADD);
+       CtdlNetworkTalkingTo(SKEY(NW->node), NTT_ADD);
        syslog(LOG_DEBUG, "NW[%s][%ld]: polling\n", ChrPtr(NW->node), NW->n);
        ParseURL(&NW->IO.ConnectMe, NW->Url, 504);
 
@@ -1021,7 +1020,7 @@ void network_poll_other_citadel_nodes(int full_poll, HashList *ignetcfg)
                /* Use the string tokenizer to grab one line at a time */
                if(server_shutting_down)
                        return;/* TODO free stuff*/
-               NodeConf *pNode = (NodeConf*) vCfg;
+               CtdlNodeConf *pNode = (CtdlNodeConf*) vCfg;
                poll = 0;
                NW = (AsyncNetworker*)malloc(sizeof(AsyncNetworker));
                memset(NW, 0, sizeof(AsyncNetworker));
@@ -1057,7 +1056,7 @@ void network_poll_other_citadel_nodes(int full_poll, HashList *ignetcfg)
                                     ChrPtr(NW->secret),
                                     ChrPtr(NW->host),
                                     ChrPtr(NW->port));
-                       if (!network_talking_to(SKEY(NW->node), NTT_CHECK))
+                       if (!CtdlNetworkTalkingTo(SKEY(NW->node), NTT_CHECK))
                        {
                                RunNetworker(NW);
                                continue;
@@ -1087,7 +1086,7 @@ void network_do_clientqueue(void)
                );
        }
 
-       working_ignetcfg = load_ignetcfg();
+       working_ignetcfg = CtdlLoadIgNetCfg();
        /*
         * Poll other Citadel nodes.  Maybe.  If "full_processing" is set
         * then we poll everyone.  Otherwise we only poll nodes we have stuff
index dc407afdc369ff88aad6d06684dd39da9cb03b53..6320144f4c58203a947ed5c6c4ee24ef8538bba6 100644 (file)
@@ -4011,11 +4011,6 @@ struct CtdlMessage *CtdlMakeMessage(
        return(msg);
 }
 
-extern int netconfig_check_roomaccess(
-       char *errmsgbuf, 
-       size_t n,
-       const char* RemoteIdentifier); /* TODO: find a smarter way */
-
 /*
  * Check to see whether we have permission to post a message in the current
  * room.  Returns a *CITADEL ERROR CODE* and puts a message in errmsgbuf, or
@@ -4050,7 +4045,7 @@ int CtdlDoIHavePermissionToPostInThisRoom(
                }
                if ((PostPublic!=POST_LMTP) &&(CC->room.QRflags2 & QR2_SMTP_PUBLIC) == 0) {
 
-                       return netconfig_check_roomaccess(errmsgbuf, n, RemoteIdentifier);
+                       return CtdlNetconfigCheckRoomaccess(errmsgbuf, n, RemoteIdentifier);
                }
                return (0);
 
index 3c20541c0f7fd51714b0a750e96ae78506ddd030..6137bd3d48d99202e0d3ca0f779ea2f80d7e21e3 100644 (file)
@@ -30,8 +30,9 @@
 #include "include/ctdl_module.h"
 HashList *CfgTypeHash = NULL;
 
-
-
+/*-----------------------------------------------------------------------------*
+ *                       Per room network configs                              *
+ *-----------------------------------------------------------------------------*/
 void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLineParser p, int uniq, CfgLineSerializer s, CfgLineDeAllocator d)
 {
        CfgLineType *pCfg;
@@ -276,3 +277,646 @@ void free_spoolcontrol_struct(OneRoomNetCfg **pOneRNCFG)
        *pOneRNCFG=NULL;
 }
 
+
+/*-----------------------------------------------------------------------------*
+ *              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);
+       }
+
+       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);
+       }
+
+       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;
+       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();
+
+       cprintf("%d %s\n", SEND_LISTING, tempfilename);
+
+       len = 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);
+       }
+       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);
+}
+
+
+/*-----------------------------------------------------------------------------*
+ *                       Per node network configs                              *
+ *-----------------------------------------------------------------------------*/
+void DeleteCtdlNodeConf(void *vNode)
+{
+       CtdlNodeConf *Node = (CtdlNodeConf*) vNode;
+       FreeStrBuf(&Node->NodeName);
+       FreeStrBuf(&Node->Secret);
+       FreeStrBuf(&Node->Host);
+       FreeStrBuf(&Node->Port);
+       free(Node);
+}
+
+CtdlNodeConf *NewNode(StrBuf *SerializedNode)
+{
+       const char *Pos = NULL;
+       CtdlNodeConf *Node;
+
+       /* we need at least 4 pipes and some other text so its invalid. */
+       if (StrLength(SerializedNode) < 8)
+               return NULL;
+       Node = (CtdlNodeConf *) malloc(sizeof(CtdlNodeConf));
+
+       Node->DeleteMe = 0;
+
+       Node->NodeName=NewStrBuf();
+       StrBufExtract_NextToken(Node->NodeName, SerializedNode, &Pos, '|');
+
+       Node->Secret=NewStrBuf();
+       StrBufExtract_NextToken(Node->Secret, SerializedNode, &Pos, '|');
+
+       Node->Host=NewStrBuf();
+       StrBufExtract_NextToken(Node->Host, SerializedNode, &Pos, '|');
+
+       Node->Port=NewStrBuf();
+       StrBufExtract_NextToken(Node->Port, SerializedNode, &Pos, '|');
+       return Node;
+}
+
+
+/*
+ * Load or refresh the Citadel network (IGnet) configuration for this node.
+ */
+HashList* CtdlLoadIgNetCfg(void)
+{
+       const char *LinePos;
+       char       *Cfg;
+       StrBuf     *Buf;
+       StrBuf     *LineBuf;
+       HashList   *Hash;
+       CtdlNodeConf   *Node;
+
+       Cfg =  CtdlGetSysConfig(IGNETCFG);
+       if ((Cfg == NULL) || IsEmptyStr(Cfg)) {
+               if (Cfg != NULL)
+                       free(Cfg);
+               return NULL;
+       }
+
+       Hash = NewHash(1, NULL);
+       Buf = NewStrBufPlain(Cfg, -1);
+       free(Cfg);
+       LineBuf = NewStrBufPlain(NULL, StrLength(Buf));
+       LinePos = NULL;
+       do
+       {
+               StrBufSipLine(LineBuf, Buf, &LinePos);
+               if (StrLength(LineBuf) != 0) {
+                       Node = NewNode(LineBuf);
+                       if (Node != NULL) {
+                               Put(Hash, SKEY(Node->NodeName), Node, DeleteCtdlNodeConf);
+                       }
+               }
+       } while (LinePos != StrBufNOTNULL);
+       FreeStrBuf(&Buf);
+       FreeStrBuf(&LineBuf);
+       return Hash;
+}
+
+
+int is_recipient(OneRoomNetCfg *RNCfg, const char *Name)
+{
+       const RoomNetCfg RecipientCfgs[] = {
+               listrecp,
+               digestrecp,
+               participate,
+               maxRoomNetCfg
+       };
+       int i;
+       RoomNetCfgLine *nptr;
+       size_t len;
+       
+       len = strlen(Name);
+       i = 0;
+       while (RecipientCfgs[i] != maxRoomNetCfg)
+       {
+               nptr = RNCfg->NetConfigs[RecipientCfgs[i]];
+               
+               while (nptr != NULL)
+               {
+                       if ((StrLength(nptr->Value) == len) && 
+                           (!strcmp(Name, ChrPtr(nptr->Value))))
+                       {
+                               return 1;
+                       }
+                       nptr = nptr->next;
+               }
+       }
+       return 0;
+}
+
+
+
+int CtdlNetconfigCheckRoomaccess(
+       char *errmsgbuf, 
+       size_t n,
+       const char* RemoteIdentifier)
+{
+       OneRoomNetCfg *RNCfg;
+       char filename[SIZ];
+       int found;
+
+       if (RemoteIdentifier == NULL)
+       {
+               snprintf(errmsgbuf, n, "Need sender to permit access.");
+               return (ERROR + USERNAME_REQUIRED);
+       }
+
+       assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir);
+       begin_critical_section(S_NETCONFIGS);
+       if (!read_spoolcontrol_file(&RNCfg, filename))
+       {
+               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);
+       free_spoolcontrol_struct(&RNCfg);
+       if (found) {
+               return (0);
+       }
+       else {
+               snprintf(errmsgbuf, n,
+                        "This mailing list only accepts posts from subscribers.");
+               return (ERROR + NO_SUCH_USER);
+       }
+}
+
+
+
+/*
+ * cmd_netp() - authenticate to the server as another Citadel node polling
+ *           for network traffic
+ */
+void cmd_netp(char *cmdbuf)
+{
+       struct CitContext *CCC = CC;
+       HashList *working_ignetcfg;
+       char *node;
+       StrBuf *NodeStr;
+       long nodelen;
+       int v;
+       long lens[2];
+       const char *strs[2];
+
+       const StrBuf *secret = NULL;
+       const StrBuf *nexthop = NULL;
+       char err_buf[SIZ] = "";
+
+       /* Authenticate */
+       node = CCC->curr_user;
+       nodelen = extract_token(CCC->curr_user, cmdbuf, 0, '|', sizeof CCC->curr_user);
+       NodeStr = NewStrBufPlain(node, nodelen);
+       /* load the IGnet Configuration to check node validity */
+       working_ignetcfg = CtdlLoadIgNetCfg();
+       v = CtdlIsValidNode(&nexthop, &secret, NodeStr, working_ignetcfg, NULL);
+       if (v != 0) {
+               snprintf(err_buf, sizeof err_buf,
+                       "An unknown Citadel server called \"%s\" attempted to connect from %s [%s].\n",
+                       node, CCC->cs_host, CCC->cs_addr
+               );
+               syslog(LOG_WARNING, "%s", err_buf);
+               cprintf("%d authentication failed\n", ERROR + PASSWORD_REQUIRED);
+
+               strs[0] = CCC->cs_addr;
+               lens[0] = strlen(CCC->cs_addr);
+               
+               strs[1] = "SRV_UNKNOWN";
+               lens[1] = sizeof("SRV_UNKNOWN" - 1);
+
+               CtdlAideFPMessage(
+                       err_buf,
+                       "IGNet Networking.",
+                       2, strs, (long*) &lens);
+
+               DeleteHash(&working_ignetcfg);
+               FreeStrBuf(&NodeStr);
+               return;
+       }
+
+       extract_token(CCC->user.password, cmdbuf, 1, '|', sizeof CCC->user.password);
+       if (strcasecmp(CCC->user.password, ChrPtr(secret))) {
+               snprintf(err_buf, sizeof err_buf,
+                       "A Citadel server at %s [%s] failed to authenticate as network node \"%s\".\n",
+                       CCC->cs_host, CCC->cs_addr, node
+               );
+               syslog(LOG_WARNING, "%s", err_buf);
+               cprintf("%d authentication failed\n", ERROR + PASSWORD_REQUIRED);
+
+               strs[0] = CCC->cs_addr;
+               lens[0] = strlen(CCC->cs_addr);
+               
+               strs[1] = "SRV_PW";
+               lens[1] = sizeof("SRV_PW" - 1);
+
+               CtdlAideFPMessage(
+                       err_buf,
+                       "IGNet Networking.",
+                       2, strs, (long*) &lens);
+
+               DeleteHash(&working_ignetcfg);
+               FreeStrBuf(&NodeStr);
+               return;
+       }
+
+       if (CtdlNetworkTalkingTo(node, nodelen, NTT_CHECK)) {
+               syslog(LOG_WARNING, "Duplicate session for network node <%s>", node);
+               cprintf("%d Already talking to %s right now\n", ERROR + RESOURCE_BUSY, node);
+               DeleteHash(&working_ignetcfg);
+               FreeStrBuf(&NodeStr);
+               return;
+       }
+       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",
+               CCC->net_node, CCC->cs_host, CCC->cs_addr
+       );
+       cprintf("%d authenticated as network node '%s'\n", CIT_OK, CCC->net_node);
+       DeleteHash(&working_ignetcfg);
+       FreeStrBuf(&NodeStr);
+}
+
+
+/*-----------------------------------------------------------------------------*
+ *                 Network maps: evaluate other nodes                          *
+ *-----------------------------------------------------------------------------*/
+
+void DeleteNetMap(void *vNetMap)
+{
+       CtdlNetMap *TheNetMap = (CtdlNetMap*) vNetMap;
+       FreeStrBuf(&TheNetMap->NodeName);
+       FreeStrBuf(&TheNetMap->NextHop);
+       free(TheNetMap);
+}
+
+CtdlNetMap *NewNetMap(StrBuf *SerializedNetMap)
+{
+       const char *Pos = NULL;
+       CtdlNetMap *NM;
+
+       /* we need at least 3 pipes and some other text so its invalid. */
+       if (StrLength(SerializedNetMap) < 6)
+               return NULL;
+       NM = (CtdlNetMap *) malloc(sizeof(CtdlNetMap));
+
+       NM->NodeName=NewStrBuf();
+       StrBufExtract_NextToken(NM->NodeName, SerializedNetMap, &Pos, '|');
+
+       NM->lastcontact = StrBufExtractNext_long(SerializedNetMap, &Pos, '|');
+
+       NM->NextHop=NewStrBuf();
+       StrBufExtract_NextToken(NM->NextHop, SerializedNetMap, &Pos, '|');
+
+       return NM;
+}
+
+HashList* CtdlReadNetworkMap(void)
+{
+       const char *LinePos;
+       char       *Cfg;
+       StrBuf     *Buf;
+       StrBuf     *LineBuf;
+       HashList   *Hash;
+       CtdlNetMap     *TheNetMap;
+
+       Cfg =  CtdlGetSysConfig(IGNETMAP);
+       if ((Cfg == NULL) || IsEmptyStr(Cfg)) {
+               if (Cfg != NULL)
+                       free(Cfg);
+               return NULL;
+       }
+
+       Hash = NewHash(1, NULL);
+       Buf = NewStrBufPlain(Cfg, -1);
+       free(Cfg);
+       LineBuf = NewStrBufPlain(NULL, StrLength(Buf));
+       LinePos = NULL;
+       while (StrBufSipLine(Buf, LineBuf, &LinePos))
+       {
+               TheNetMap = NewNetMap(LineBuf);
+               if (TheNetMap != NULL) { /* TODO: is the NodeName Uniq? */
+                       Put(Hash, SKEY(TheNetMap->NodeName), TheNetMap, DeleteNetMap);
+               }
+       }
+       FreeStrBuf(&Buf);
+       FreeStrBuf(&LineBuf);
+       return Hash;
+}
+
+StrBuf *CtdlSerializeNetworkMap(HashList *Map)
+{
+       void *vMap;
+       const char *key;
+       long len;
+       StrBuf *Ret = NewStrBuf();
+       HashPos *Pos = GetNewHashPos(Map, 0);
+
+       while (GetNextHashPos(Map, Pos, &len, &key, &vMap))
+       {
+               CtdlNetMap *pMap = (CtdlNetMap*) vMap;
+               StrBufAppendBuf(Ret, pMap->NodeName, 0);
+               StrBufAppendBufPlain(Ret, HKEY("|"), 0);
+
+               StrBufAppendPrintf(Ret, "%ld", pMap->lastcontact, 0);
+               StrBufAppendBufPlain(Ret, HKEY("|"), 0);
+
+               StrBufAppendBuf(Ret, pMap->NextHop, 0);
+               StrBufAppendBufPlain(Ret, HKEY("\n"), 0);
+       }
+       DeleteHashPos(&Pos);
+       return Ret;
+}
+
+
+/*
+ * Learn topology from path fields
+ */
+void NetworkLearnTopology(char *node, char *path, HashList *the_netmap, int *netmap_changed)
+{
+       CtdlNetMap *pNM = NULL;
+       void *vptr;
+       char nexthop[256];
+       CtdlNetMap *nmptr;
+
+       if (GetHash(the_netmap, node, strlen(node), &vptr) && 
+           (vptr != NULL))/* TODO: is the NodeName Uniq? */
+       {
+               pNM = (CtdlNetMap*)vptr;
+               extract_token(nexthop, path, 0, '!', sizeof nexthop);
+               if (!strcmp(nexthop, ChrPtr(pNM->NextHop))) {
+                       pNM->lastcontact = time(NULL);
+                       (*netmap_changed) ++;
+                       return;
+               }
+       }
+
+       /* If we got here then it's not in the map, so add it. */
+       nmptr = (CtdlNetMap *) malloc(sizeof (CtdlNetMap));
+       nmptr->NodeName = NewStrBufPlain(node, -1);
+       nmptr->lastcontact = time(NULL);
+       nmptr->NextHop = NewStrBuf ();
+       StrBufExtract_tokenFromStr(nmptr->NextHop, path, strlen(path), 0, '!');
+       /* TODO: is the NodeName Uniq? */
+       Put(the_netmap, SKEY(nmptr->NodeName), nmptr, DeleteNetMap);
+       (*netmap_changed) ++;
+}
+
+
+/*
+ * Check the network map and determine whether the supplied node name is
+ * valid.  If it is not a neighbor node, supply the name of a neighbor node
+ * which is the next hop.  If it *is* a neighbor node, we also fill in the
+ * shared secret.
+ */
+int CtdlIsValidNode(const StrBuf **nexthop,
+                   const StrBuf **secret,
+                   StrBuf *node,
+                   HashList *IgnetCfg,
+                   HashList *the_netmap)
+{
+       void *vNetMap;
+       void *vNodeConf;
+       CtdlNodeConf *TheNode;
+       CtdlNetMap *TheNetMap;
+
+       if (StrLength(node) == 0) {
+               return(-1);
+       }
+
+       /*
+        * First try the neighbor nodes
+        */
+       if (GetCount(IgnetCfg) == 0) {
+               syslog(LOG_INFO, "IgnetCfg is empty!\n");
+               if (nexthop != NULL) {
+                       *nexthop = NULL;
+               }
+               return(-1);
+       }
+
+       /* try to find a neigbour with the name 'node' */
+       if (GetHash(IgnetCfg, SKEY(node), &vNodeConf) && 
+           (vNodeConf != NULL))
+       {
+               TheNode = (CtdlNodeConf*)vNodeConf;
+               if (secret != NULL)
+                       *secret = TheNode->Secret;
+               return 0;               /* yup, it's a direct neighbor */
+       }
+
+       /*
+        * If we get to this point we have to see if we know the next hop
+        *//* TODO: is the NodeName Uniq? */
+       if ((GetCount(the_netmap) > 0) &&
+           (GetHash(the_netmap, SKEY(node), &vNetMap)))
+       {
+               TheNetMap = (CtdlNetMap*)vNetMap;
+               if (nexthop != NULL)
+                       *nexthop = TheNetMap->NextHop;
+               return(0);
+       }
+
+       /*
+        * If we get to this point, the supplied node name is bogus.
+        */
+       syslog(LOG_ERR, "Invalid node name <%s>\n", ChrPtr(node));
+       return(-1);
+}
+
+
+/*
+ * Module entry point
+ */
+CTDL_MODULE_INIT(netconfig)
+{
+       if (!threading)
+       {
+
+               CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
+               CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");
+               CtdlRegisterProtoHook(cmd_netp, "NETP", "Identify as network poller");
+       }
+       return "netconfig";
+}
diff --git a/citadel/nttlist.c b/citadel/nttlist.c
new file mode 100644 (file)
index 0000000..5831d4a
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * This module handles shared rooms, inter-Citadel mail, and outbound
+ * mailing list processing.
+ *
+ * Copyright (c) 2000-2012 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 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 <stdio.h>
+#include <libcitadel.h>
+#include "ctdl_module.h"
+#include "serv_extensions.h"
+
+/*-----------------------------------------------------------------------------*
+ *                 Network maps: evaluate other nodes                          *
+ *-----------------------------------------------------------------------------*/
+int NTTDebugEnabled = 0;
+
+/*
+ * network_talking_to()  --  concurrency checker
+ */
+static HashList *nttlist = NULL;
+int CtdlNetworkTalkingTo(const char *nodename, long len, int operation)
+{
+
+       int retval = 0;
+       HashPos *Pos = NULL;
+       void *vdata;
+
+       begin_critical_section(S_NTTLIST);
+
+       switch(operation) {
+
+               case NTT_ADD:
+                       if (nttlist == NULL) 
+                               nttlist = NewHash(1, NULL);
+                       Put(nttlist, nodename, len, NewStrBufPlain(nodename, len), HFreeStrBuf);
+                       if (NTTDebugEnabled) syslog(LOG_DEBUG, "nttlist: added <%s>\n", nodename);
+                       break;
+               case NTT_REMOVE:
+                       if ((nttlist == NULL) ||
+                           (GetCount(nttlist) == 0))
+                               break;
+                       Pos = GetNewHashPos(nttlist, 1);
+                       if (GetHashPosFromKey (nttlist, nodename, len, Pos))
+                               DeleteEntryFromHash(nttlist, Pos);
+                       DeleteHashPos(&Pos);
+                       if (NTTDebugEnabled) syslog(LOG_DEBUG, "nttlist: removed <%s>\n", nodename);
+
+                       break;
+
+               case NTT_CHECK:
+                       if ((nttlist == NULL) ||
+                           (GetCount(nttlist) == 0))
+                               break;
+                       if (GetHash(nttlist, nodename, len, &vdata))
+                               retval ++;
+                       if (NTTDebugEnabled) syslog(LOG_DEBUG, "nttlist: have [%d] <%s>\n", retval, nodename);
+                       break;
+       }
+
+       end_critical_section(S_NTTLIST);
+       return(retval);
+}
+
+void cleanup_nttlist(void)
+{
+        begin_critical_section(S_NTTLIST);
+       DeleteHash(&nttlist);
+        end_critical_section(S_NTTLIST);
+}
+
+
+
+/*
+ * Module entry point
+ */
+void SetNTTDebugEnabled(const int n)
+{
+       NTTDebugEnabled = n;
+}
+
+
+
+/*
+ * Module entry point
+ */
+CTDL_MODULE_INIT(nttlist)
+{
+       if (!threading)
+       {
+               CtdlRegisterDebugFlagHook(HKEY("networktalkingto"), SetNTTDebugEnabled, &NTTDebugEnabled);
+
+               CtdlRegisterCleanupHook(cleanup_nttlist);
+       }
+       return "nttlist";
+}