extended functionality/make more secure M.Z.
This commit is contained in:
320
conman.c
320
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 <zlib.h>
|
||||
#include <tcl.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#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;
|
||||
}
|
||||
|
37
conman.h
37
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
|
||||
|
Reference in New Issue
Block a user