Merge branch 'conclean' into rhel7

Conflicts:
	SCinter.c
	telnet.c
This commit is contained in:
2017-04-03 11:44:35 +02:00
23 changed files with 306 additions and 930 deletions

505
nread.c
View File

@@ -194,439 +194,6 @@ int NetReadRemove(pNetRead self, mkChannel * pSock)
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int NetReadAccept(pNetRead self, mkChannel * pSock)
{
mkChannel *pNew = NULL;
char pBuffer[1064];
int iRet;
SConnection *pRes = NULL;
char *pUser = NULL, *pPasswd = NULL;
time_t target;
if (!VerifyChannel(pSock)) {
return 0;
}
/* check for new connection */
pNew = NETAccept(pSock, 0);
if (pNew) {
/* create connection object */
/* TODO
pRes = SCreateConnection(self->pMain->pSics,pNew,3);
*/
if (!pRes) {
Log(ERROR,"sys","%s","Failure to allocate new Connection");
NETClosePort(pNew);
free(pNew);
return 0;
} else {
/* register the connection and create a task for it here */
NetReadRegister(self, pNew, command, pRes);
TaskRegisterN(self->pMain->pTasker, "NetReadAccept",
SCTaskFunction,
SCSignalFunction, SCDeleteConnection, pRes, TASK_PRIO_LOW);
SCSendOK(pRes);
return 1;
}
} else {
return 0;
}
}
/*--------------------------------------------------------------------------*/
#define COLLECT 0
#define SKIPTERM 1
/*------------------------------------------------------------------------*/
static int NetReadRead(pNetRead self, pNetItem pItem)
{
char *pPtr, *pEnd, *pBufEnd;
char pBuffer[1024], pMuell[20];
char pBueffel[80];
int i, iInt, iRet, iStat, state;
/* read first */
memset(pBuffer, 0, 1024);
iRet = NETRead(pItem->pCon->pSock, pBuffer, 1022, 0);
if (iRet < 0) { /* EOF */
pItem->pCon->iEnd = 1;
NetReadRemove(self, pItem->pCon->pSock);
return 0;
} else if (iRet == 0) { /* should not happen */
return 1;
}
/* iRet is now the number of bytes read. Now we check for command
interrupts */
pPtr = strstr(pBuffer, "INT1712");
if (pPtr) {
sscanf(pPtr, "%s %d", pMuell, &iInt);
if (SCMatchRights(pItem->pCon, usUser)) {
TaskSignal(self->pMain->pTasker, SICSINT, &iInt);
Log(ERROR,"com","sock%03.3d:INTERRUPT", pItem->pCon->pSock->sockid);
if (iInt == eEndServer) {
TaskStop(self->pMain->pTasker);
}
} else {
SCWrite(pItem->pCon,
"ERROR: insufficient privilege to invoke Interrupt", eError);
}
return 0;
}
/* split into command lines
and put into fifo
*/
pBufEnd = pBuffer + iRet;
pPtr = pBuffer;
pEnd = pBuffer;
state = COLLECT;
while (pEnd < pBufEnd) {
switch (state) {
case COLLECT:
if ((*pEnd != '\r') && (*pEnd != '\n')) {
pEnd++;
} else {
/* there is a string between pPtr and pEnd */
*pEnd = '\0';
/* do we have something in hold ? */
if (strlen(pItem->pHold) > 0) {
strlcat(pItem->pHold, pPtr, 511);
/* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == PROTSICS &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError);
}
pItem->pHold[0] = '\0';
} else {
/* no, normal command */
/* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == PROTSICS &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pPtr);
if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError);
}
}
pPtr = pEnd + 1;
pEnd = pPtr;
state = SKIPTERM;
}
break;
case SKIPTERM:
if ((*pEnd != '\r') && (*pEnd != '\n')) {
state = COLLECT;
pPtr = pEnd;
} else {
pEnd++;
pPtr = pEnd;
}
break;
}
}
/* when we are here we may still have an incomplete command pending */
if (pEnd != pPtr && strlen(pPtr) > 0) {
strlcpy(pItem->pHold, pPtr, 511);
}
return 1;
}
/*-------------------------- telnet protocoll code -------------------------*/
static int TelnetAccept(pNetRead self, mkChannel * pSock)
{
mkChannel *pNew = NULL;
char pBuffer[1064];
int iRet;
SConnection *pRes = NULL;
pTelTask pTel = NULL;
if (!VerifyChannel(pSock)) {
return 0;
}
/* check for new connection */
pNew = NETAccept(pSock, 0);
if (pNew) {
/* create connection object */
/* TODO
pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy);
*/
if (!pRes) {
Log(ERROR,"sys","%s","Failure to allocate new Connection");
NETClosePort(pNew);
free(pNew);
return 0;
} else {
/* Create a task object for the telnet connection */
pTel = CreateTelnet(pRes);
if (!pTel) {
Log(ERROR,"sys","%s","Failure to allocate new Telnet Task Object");
SCDeleteConnection(pRes);
return 0;
}
/* register connection and task */
pRes->iTelnet = 1;
NetReadRegister(self, pNew, tcommand, pRes);
TaskRegisterN(self->pMain->pTasker," TelnetAccept",
TelnetTask, TelnetSignal, DeleteTelnet, pTel, TASK_PRIO_LOW);
return 1;
}
} else {
return 0;
}
}
/*------------------------------------------------------------------------
Telnet is fully described in RFC-854. This implementation is very simple.
It just supports the NVT and no options. Implementation is via a state
machine with the state tStatus in the pItem structure. This is necessary
as single characters may be sent by telnet clients.
-------------------------------------------------------------------------*/
/* Telnet codes */
#define SE 240
#define NOP 241
#define DM 242 /* data mark */
#define BRK 243
#define IP 244
#define AO 245
#define AYT 246
#define EC 247
#define EL 248
#define GA 249
#define SB 250
#define WILL 251
#define WONT 252
#define DO 253
#define DONT 254
#define IAC 255
#define EOR 239
/*-----------------------------------------------------------------------*/
static int TelnetReply(pNetItem pItem, char code, char cChar)
{
char pReply[3];
pReply[0] = IAC;
pReply[1] = code;
pReply[2] = cChar;
NETWrite(pItem->pCon->pSock, pReply, 3);
return 1;
}
/*------------------------------------------------------------------------*/
static int TelnetRead(pNetRead self, pNetItem pItem)
{
char pBuffer[1024], pMuell[20], pError[256];
int i, iStat, iInt, iRet;
int cChar;
char *pPtr = NULL;
SConnection *pOwner = NULL;
/* read first */
memset(pBuffer, 0, 1023);
iRet = NETRead(pItem->pCon->pSock, pBuffer, 1022, 0);
if (iRet < 0) { /* EOF */
pItem->pCon->iEnd = 1;
NetReadRemove(self, pItem->pCon->pSock);
return 0;
} else if (iRet == 0) { /* should not happen */
return 1;
}
/* iRet is now the number of bytes read. Now we check for command
interrupts */
pPtr = strstr(pBuffer, "INT1712");
if (pPtr) {
sscanf(pPtr, "%s %d", pMuell, &iInt);
if (SCMatchRights(pItem->pCon, usUser)) {
/* owners may kill own tasks, otherwise manager
privilege is required.
*/
pOwner = GetExeOwner(pServ->pExecutor);
if (pOwner) {
if (pOwner != pItem->pCon) {
if (!SCMatchRights(pItem->pCon, usMugger)) {
SCWrite(pItem->pCon,
"ERROR: Insufficient privilege to stop other people's experiments",
eError);
return 1;
}
}
}
TaskSignal(self->pMain->pTasker, SICSINT, &iInt);
Log(ERROR,"com","%s:interrupt: %d", ConID(pItem->pCon),iInt);
if (iInt == eEndServer) {
TaskStop(self->pMain->pTasker);
}
} else {
SCWrite(pItem->pCon,
"ERROR: insufficient privilege to invoke Interrupt", eError);
}
return 1;
}
/* do telnet analysis of the data buffer */
for (i = 0; i < iRet; i++) {
cChar = (int) pBuffer[i];
#ifdef TELNETDEBUG
if ((cChar > 48) && (cChar < 128)) {
printf("char: %c\n", cChar);
} else {
printf("Control: %d\n", cChar);
}
#endif
/* Telnet status switching */
switch (pItem->tStatus) {
case tData:
switch (cChar) {
case IAC:
pItem->tStatus = tIAC;
break;
case '\r':
case '\n':
/* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == PROTSICS &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
/* printf("%s\n",pItem->pHold); */
if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError);
}
memset(pItem->pHold, 0, 511);
pItem->iEOD = 0;
pItem->tStatus = tCR;
break;
case (char) 8: /* backspace */
pItem->iEOD--;
if (pItem->iEOD < 0) {
pItem->iEOD = 0;
}
break;
case (char) 0: /* ignore 0 character sent as end of text */
break;
default:
pItem->pHold[pItem->iEOD] = cChar;
pItem->iEOD++;
break;
} /* end of tData case */
break;
case tCR: /* ignore the second character after a newline.
Telnet gives you two characters for newline
*/
pItem->tStatus = tData;
break;
case tIAC:
switch (cChar) {
case IAC:
pItem->tStatus = tData;
break;
case WILL:
pItem->tStatus = tWill;
break;
case WONT:
pItem->tStatus = tWont;
break;
case DONT:
pItem->tStatus = tDont;
break;
case DO:
pItem->tStatus = tDo;
break;
case EOR:
pItem->tStatus = tData;
break;
case SB:
pItem->tStatus = tSB;
break;
case EC:
pItem->iEOD--;
if (pItem->iEOD < 0) {
pItem->iEOD = 0;
}
pItem->tStatus = tData;
break;
case EL:
memset(pItem->pHold, 0, 511);
pItem->iEOD = 0;
pItem->tStatus = tData;
break;
case IP:
SCSetInterrupt(pItem->pCon, eAbortBatch);
pItem->tStatus = tData;
break;
default:
pItem->tStatus = tData;
break;
} /* end of tIAC */
break;
case tWill: /* we do not do options! */
TelnetReply(pItem, DONT, cChar);
pItem->tStatus = tData;
break;
case tWont: /* we do not do options! A Wont is sent by the client
if it cannot do a option we requested it to have. As
we do not try to force options, this should not happen
*/
pItem->tStatus = tData;
break;
case tDo: /* we do not do options! */
TelnetReply(pItem, WONT, cChar);
pItem->tStatus = tData;
break;
case tDont: /* we do not do options! A Dont is sent by the client
if it cannot do a option we requested it to have. As
we do not try to force options, this should not happen
*/
pItem->tStatus = tData;
break;
case tSB: /* as we do not have options, we cannot have suboption
negotaitions. Something is seriously wrong when
we are here. It is a protocoll error. However, we
ignore it silently. tSB marks the start of the
subnegotiation. The current character must be the
option code we are dealing with.
*/
pItem->tStatus = tSE;
break;
case tSE:
/* now we are in the suboption parameter. Normally data
should be copied to a suboption string buffer here
until SE.
*/
switch (cChar) {
case IAC:
break;
case SE:
pItem->tStatus = tData;
/* suboption interpretation would go here */
break;
default:
/* copy data to suboption buffer */
break;
}
break;
default:
/* There is something wrong here! */
snprintf(pError,sizeof(pError)-1, "ERROR: bad telnet code %d", cChar);
Log(ERROR,"sys","%s",pError);
pItem->tStatus = tData;
break;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int NetReadUDP(pNetRead self, pNetItem pItem)
{
@@ -708,13 +275,6 @@ int NetReaderTask(void *pData)
GetCharArray(self->conList));
}
/*
* This costs a surprising amount of CPU-time, in a test 10%!
* This is why it has been commented away
snprintf(num, sizeof num, "%d", conCount);
IFSetOption(pSICSOptions, "ConnectionCount", num);
IFSetOption(pSICSOptions, "ConMask", GetCharArray(self->conList));
*/
/* the select itself */
tmo.tv_usec = self->iReadTimeout;
@@ -731,29 +291,6 @@ int NetReaderTask(void *pData)
LLDnodeDataTo(self->iList, &NItem);
if (FD_ISSET(NItem.pSock->sockid, &lMask)) { /* data */
switch (NItem.eType) {
/* lists have been changed after accept, return */
case naccept:
NetReadAccept(self, NItem.pSock);
return 1;
break;
case taccept:
TelnetAccept(self, NItem.pSock);
return 1;
break;
case command:
iStatus = NetReadRead(self, &NItem);
if (iStatus == 0) { /* there was an eof */
/* do not continue, list is messy */
return 1;
}
break;
case tcommand:
iStatus = TelnetRead(self, &NItem);
if (iStatus == 0) { /* there was an eof */
/* do not continue, list is messy */
return 1;
}
break;
case udp:
NetReadUDP(self, &NItem);
break;
@@ -1048,6 +585,10 @@ static int testAndInvokeInterrupt(pCommandCBData self, int handle)
}
return 0;
}
/*----------------------------------------------------------------------------------*/
#define COLLECT 0
#define SKIPTERM 1
/*----------------------------------------------------------------------------------*/
static int CommandDataCB(int handle, void *userData)
@@ -1067,10 +608,10 @@ static int CommandDataCB(int handle, void *userData)
if (pPtr[i] == '\r' || pPtr[i] == '\n') {
self->state = SKIPTERM;
if (!testAndInvokeInterrupt(self, handle)) {
if (self->pCon->iProtocolID == PROTSICS && CostaLocked(self->pCon->pStack))
if (SCGetProtocolID(self->pCon) == PROTSICS && SCCostaLocked(self->pCon))
status = 0;
else
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
status = SCCostaTop(self->pCon, GetCharArray(self->command));
if (!status) {
SCWrite(self->pCon, "ERROR: Busy", eError);
}
@@ -1114,7 +655,7 @@ static int CommandAcceptCB(int handle, void *userData)
}
usData->pCon = pCon;
usData->state = COLLECT;
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
snprintf(buffer,sizeof(buffer),"con%ld", SCGetIdent(pCon));
TaskRegisterN(pServ->pTasker,
buffer,
SCTaskFunction,
@@ -1123,6 +664,30 @@ static int CommandAcceptCB(int handle, void *userData)
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------------
Telnet is fully described in RFC-854. This implementation is very simple.
It just supports the NVT and no options. Implementation is via a state
machine with the state tStatus in the pItem structure. This is necessary
as single characters may be sent by telnet clients.
-------------------------------------------------------------------------*/
/* Telnet codes */
#define SE 240
#define NOP 241
#define DM 242 /* data mark */
#define BRK 243
#define IP 244
#define AO 245
#define AYT 246
#define EC 247
#define EL 248
#define GA 249
#define SB 250
#define WILL 251
#define WONT 252
#define DO 253
#define DONT 254
#define IAC 255
#define EOR 239
/*-----------------------------------------------------------------------*/
static int ANETTelnetReply(int sockHandle, char code, char cChar)
@@ -1171,10 +736,10 @@ static int ANETTelnetProcess(int handle, void *usData)
case '\r':
case '\n':
if (!testAndInvokeInterrupt(self, handle)) {
if (self->pCon->iProtocolID == PROTSICS && CostaLocked(self->pCon->pStack))
if (SCGetProtocolID(self->pCon) == PROTSICS && SCCostaLocked(self->pCon))
status = 0;
else
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
status = SCCostaTop(self->pCon, GetCharArray(self->command));
if (!status) {
SCWrite(self->pCon, "ERROR: Busy", eError);
}
@@ -1329,8 +894,8 @@ static int TelnetAcceptCB(int handle, void *userData)
return 0;
}
/* register connection and task */
pCon->iTelnet = 1;
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
SCSetTelnet(pCon,1);
snprintf(buffer,sizeof(buffer),"con%ld", SCGetIdent(pCon));
TaskRegisterN(pServ->pTasker,
buffer,
TelnetTask, TelnetSignal, DeleteTelnet, pTel, TASK_PRIO_LOW);