From db948262489e4f4fa8cc2ce952cbca1e10c955f7 Mon Sep 17 00:00:00 2001 From: cvs Date: Wed, 17 Nov 2004 11:07:31 +0000 Subject: [PATCH] extended functionality/make more secure M.Z. --- conman.c | 320 +++++++++++++++++++++++++++++-------------------------- conman.h | 37 ++++--- 2 files changed, 194 insertions(+), 163 deletions(-) diff --git a/conman.c b/conman.c index 8066298f..afb22b83 100644 --- a/conman.c +++ b/conman.c @@ -29,6 +29,11 @@ appending outcode to text, Mark Koennecke, July 2004 + Made use of unused connections secure (connections are not + freed, but reused on new connections). + Introduced new type SCStore and functions SCSave, SCLoad. + Introduced SCPrintf to avoid many of these pBueffel. + Markus Zolliker, Sept 2004. Copyright: see copyright.h -----------------------------------------------------------------------------*/ @@ -41,6 +46,8 @@ #include #include #include +#include +#include #include "lld.h" #include "sics.h" #include "passwd.h" @@ -78,173 +85,143 @@ extern pServer pServ; /*------------- a number for generating automatic names --------------------*/ static int iName = 0; static int SCNormalWrite(SConnection *self, char *buffer, int iOut); - + static SConnection *freeConnections = NULL; + static long lastIdent = 0; /*===========================================================================*/ - SConnection *SCreateConnection(SicsInterp *pSics,mkChannel *pSock, int iUser) + static char *ConName(long ident) { + static char name[32]; + snprintf(name, sizeof(name), "CON%ld", ident); + return name; + } +/*--------------------------------------------------------------------------*/ + static void FreeConnection(SConnection *pCon) + { + memset(pCon,0,sizeof(SConnection)); + pCon->ident = 0; + pCon->next = freeConnections; + freeConnections = pCon; + } +/*--------------------------------------------------------------------------*/ + static SConnection *CreateConnection(SicsInterp *pSics) + { + int i; + SConnection *pRes = NULL; + char pBueffel[253]; + char pHost[132]; + + if (!freeConnections) + { /* no more free connection: get one by malloc */ + pRes = (SConnection *)malloc(sizeof(SConnection)); + if(!pRes) + { + /* This is a serious, very serious error! */ + SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); + return NULL; + } + memset(pRes,0,sizeof(SConnection)); + } + else + { /* reuse an old connection */ + pRes = freeConnections; + freeConnections = pRes->next; + } + + do + { /* loop until an unused ident is found */ + if (lastIdent == LONG_MAX) + { + /* This is a serious, very serious error! */ + SICSLogWrite("ERROR: Run out of connection identifiers!!",eInternal); + return NULL; + } + lastIdent++; + } while (FindCommand(pSics, ConName(lastIdent))); + pRes->ident = lastIdent; + + /* a descriptor */ + pRes->pDes = CreateDescriptor("Connection"); + if(!pRes->pDes) + { + /* This is a serious, very serious error! */ + SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); + FreeConnection(pRes); + return NULL; + } + + /* the callback registry */ + pRes->iList = LLDcreate(sizeof(Item)); + + /* the command stack */ + pRes->pStack = CreateCommandStack(); + if( (pRes->iList <0) || (!pRes->pStack)) + { + /* This is a serious, very serious error! */ + SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); + DeleteDescriptor(pRes->pDes); + FreeConnection(pRes); + return NULL; + } + + pRes->iOutput = eInError; /* gets everything except internal messages */ + pRes->iFiles = 0; /* default: no logfiles */ + pRes->inUse = 0; + pRes->iMacro = 0; + pRes->iTelnet = 0; + pRes->pSics = pSics; + pRes->eInterrupt = eContinue; + pRes->lMagic = CONMAGIC; + pRes->iLogin = 0; + pRes->conStart = time(NULL); + pRes->write = SCNormalWrite; + for(i = 0; i < 10; i++) + { + pRes->pFiles[i] = NULL; + } + + /* install command */ + AddCommand(pRes->pSics, ConName(pRes->ident), ConSicsAction, NULL,pRes); + return pRes; + + } +/*--------------------------------------------------------------------------*/ + SConnection *SCreateConnection(SicsInterp *pSics,mkChannel *pSock, int iUser) { - int i; SConnection *pRes = NULL; char pBueffel[253]; char pHost[132]; - pRes = (SConnection *)malloc(sizeof(SConnection)); - if(!pRes) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - return NULL; - } - memset(pRes,0,sizeof(SConnection)); + assert(pSock); - /* a descriptor */ - pRes->pDes = CreateDescriptor("Connection"); - if(!pRes->pDes) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - free(pRes); - return NULL; - } - - /* new name */ - sprintf(pBueffel,"CON%4.4d",iName); - iName++; - if(iName > 9999) - { - iName = 0; - } + pRes = CreateConnection(pSics); - /* the callback registry */ - pRes->iList = LLDcreate(sizeof(Item)); - - /* the command stack */ - pRes->pStack = CreateCommandStack(); - if( (pRes->iList <0) || (!pRes->pStack)) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - DeleteDescriptor(pRes->pDes); - free(pRes); - return NULL; - } SetCommandStackMaxSize(pRes->pStack,MAXSTACK); - pRes->pName = strdup(pBueffel); pRes->pSock = pSock; pRes->iUserRights = iUser; - pRes->iOutput = eInError; /* gets everything except internal messages */ - pRes->iFiles = 0; /* default: no logfiles */ - pRes->inUse = 0; - pRes->iMacro = 0; - pRes->iGrab = TokenGrabActive(); - pRes->iTelnet = 0; - pRes->pSics = pSics; - pRes->eInterrupt = eContinue; - pRes->lMagic = CONMAGIC; - pRes->iLogin = 0; - pRes->conStart = time(NULL); - pRes->write = SCNormalWrite; - for(i = 0; i < 10; i++) - { - pRes->pFiles[i] = NULL; - } - if(pRes->pSock) - { - NETInfo(pRes->pSock,pHost,131); - sprintf(pBueffel,"Accepted connection on socket %d from %s", - pRes->pSock->sockid, pHost); - SICSLogWrite(pBueffel,eInternal); - WriteToCommandLog("SYS >", pBueffel); - } - else - { - SICSLogWrite("Accepted dummy connection ",eInternal); - } - - /* install command */ - AddCommand(pRes->pSics, pRes->pName, ConSicsAction, NULL,pRes); + pRes->iGrab = TokenGrabActive(); + + NETInfo(pRes->pSock,pHost,131); + sprintf(pBueffel,"Accepted connection on socket %d from %s", + pRes->pSock->sockid, pHost); + SICSLogWrite(pBueffel,eInternal); + WriteToCommandLog("SYS >", pBueffel); + return pRes; } /*--------------------------------------------------------------------------*/ SConnection *SCCreateDummyConnection(SicsInterp *pSics) { - int i; SConnection *pRes = NULL; - char pBueffel[132]; - pRes = (SConnection *)malloc(sizeof(SConnection)); - if(!pRes) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - return NULL; - } - memset(pRes,0,sizeof(SConnection)); + pRes = CreateConnection(pSics); - /* a descriptor */ - pRes->pDes = CreateDescriptor("Connection"); - if(!pRes->pDes) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - free(pRes); - return NULL; - } - - /* new name */ - sprintf(pBueffel,"CON%4.4d",iName); - iName++; - if(iName > 9999) - { - iName = 0; - } - - /* the callback registry */ - pRes->iList = LLDcreate(sizeof(Item)); - - /* the command stack */ - pRes->pStack = CreateCommandStack(); - if( (pRes->iList <0) || (!pRes->pStack)) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - DeleteDescriptor(pRes->pDes); - free(pRes); - return NULL; - } - - pRes->pName = strdup(pBueffel); pRes->pSock = NULL; pRes->iUserRights = usInternal; - pRes->iOutput = eInError; /* gets everything except internal messages */ - pRes->iFiles = 0; /* default: no logfiles */ - pRes->inUse = 0; - pRes->iTelnet = 0; pRes->iGrab = 0; - pRes->iMacro = 0; - pRes->pSics = pSics; - pRes->lMagic = CONMAGIC; - pRes->eInterrupt = eContinue; - pRes->iLogin = 0; - pRes->conStart = time(NULL); - pRes->write = SCNormalWrite; - for(i = 0; i < 10; i++) - { - pRes->pFiles[i] = NULL; - } - if(pRes->pSock) - { - sprintf(pBueffel,"Accepted connection on socket %d",pRes->pSock->sockid); - SICSLogWrite(pBueffel,eInternal); - } - else - { - SICSLogWrite("Accepted dummy connection ",eInternal); - } - /* install command */ - AddCommand(pRes->pSics, pRes->pName, ConSicsAction, NULL,pRes); + SICSLogWrite("Accepted dummy connection ",eInternal); + return pRes; } /*--------------------------------------------------------------------------*/ @@ -434,11 +411,7 @@ extern pServer pServ; fclose(pVictim->pFiles[i]); } - if(pVictim->pName) - { - RemoveCommand(pVictim->pSics,pVictim->pName); - free(pVictim->pName); - } + RemoveCommand(pVictim->pSics,ConName(pVictim->ident)); if(pVictim->pDes) { @@ -468,9 +441,9 @@ extern pServer pServ; { DeleteCommandStack(pVictim->pStack); } - pVictim->lMagic=0; /* make a write to a freed conn. harmless */ + pVictim->lMagic=0; /* make a write to a freed connection harmless */ /* finally free pVictim*/ - free(pVictim); + FreeConnection(pVictim); } /*---------------------------------------------------------------------------*/ static int HasNL(char *buffer) @@ -563,6 +536,32 @@ extern pServer pServ; } return self->write(self,pBuffer,iOut); } +/*-------------------------------------------------------------------------*/ + int SCPrintf(SConnection *self, int iOut, char *fmt, ...) + { + va_list ap; + char buf[256]; + char *dyn; + int l; + int res; + + va_start(ap, fmt); + l = vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + if (l >= sizeof buf) { + /* we have probably a C99 conforming snprintf and need a larger buffer */ + dyn = malloc(l+1); + if (dyn != NULL) { + va_start(ap, fmt); + vsnprintf(dyn, l+1, fmt, ap); + va_end(ap); + res = SCWrite(self, dyn, iOut); + free(dyn); + return res; + } + } + return SCWrite(self, buf, iOut); + } /*-------------------------------------------------------------------------*/ writeFunc SCGetWriteFunc(SConnection *self) { @@ -597,7 +596,7 @@ static int doSockWrite(SConnection *self, char *buffer) iRet = NETWrite(self->pSock,buffer,strlen(buffer)); if(!HasNL(buffer)) { - iRet = NETWrite(self->pSock,"\n",sizeof("\n")); + iRet = NETWrite(self->pSock,"\n",strlen("\n")); } } if(!iRet) @@ -1396,7 +1395,7 @@ static void writeToLogFiles(SConnection *self, char *buffer) } else if(strcmp(argv[1],"myname") == 0) { - sprintf(pBueffel,"MyName = %s",pCon->pName); + sprintf(pBueffel,"MyName = %s",ConName(pCon->ident)); SCWrite(pCon,pBueffel,eValue); return 1; } @@ -1904,3 +1903,22 @@ int SCActive(SConnection *self) } return 0; } +/*--------------------------------------------------------------------------*/ +void SCSave(SCStore *con, SConnection *pCon) { + con->pCon = pCon; + if (pCon) { + con->ident = pCon->ident; + } +} +/*--------------------------------------------------------------------------*/ +SConnection *SCLoad(SCStore *con) { + SConnection *pCon; + + pCon = con->pCon; + if (pCon) { + if (con->ident != pCon->ident) { + con->pCon == NULL; /* connection has died */ + } + } + return pCon; +} diff --git a/conman.h b/conman.h index b8ef55b2..09b4a96f 100644 --- a/conman.h +++ b/conman.h @@ -30,9 +30,11 @@ typedef int (*writeFunc)(struct __SConnection *pCon, typedef struct __SConnection { /* object basics */ pObjectDescriptor pDes; - char *pName; + /* char *pName; now generated on the fly from ident */ long lMagic; - + long ident; + struct __SConnection *next; + /* I/O control */ mkChannel *pSock; FILE *pFiles[MAXLOGFILES]; @@ -62,15 +64,16 @@ typedef int (*writeFunc)(struct __SConnection *pCon, /* callback registry */ int iList; - /* Tasking Stuff */ - int iEnd; - /* for keeping track of the login - process on a non telnet connection. - Should only be used in SCTaskFunction - */ - int iLogin; - time_t conStart; - }SConnection; + /* Tasking Stuff */ + int iEnd; + /* for keeping track of the login + process on a non telnet connection. + Should only be used in SCTaskFunction + */ + int iLogin; + time_t conStart; + + } SConnection; #include "nserver.h" @@ -88,6 +91,7 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int SCDelLogFile(SConnection *pCon, int iFile); void SCSetOutputClass(SConnection *self, int iClass); int SCWrite(SConnection *self, char *pBuffer, int iOut); + int SCPrintf(SConnection *self, int iOut, char *fmt, ...); int SCRead(SConnection *self, char *pBuffer, int iBufLen); int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen); int SCSendOK(SConnection *self); @@ -140,7 +144,16 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int argc, char *argv[]); int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); - +/******************************** Store ************************************/ +typedef struct { + SConnection *pCon; + long ident; +} SCStore; +void SCSave(SCStore *con, SConnection *pCon); +/* save a connection for later use. */ + +SConnection *SCLoad(SCStore *con); +/* check con and return SConnection if still valid or NULL otherwise. */ #endif