/*-------------------------------------------------------------------------- S I C S T E L N E T Implementation of the telnet task things for SICS. The actual telnet protocoll handling lives in nread.c. coyright: see copyright.h Mark Koennecke, January 1998 ----------------------------------------------------------------------------*/ #include #include "sics.h" #include "passwd.h" #include "telnet.h" #include "commandlog.h" #include "fortify.h" #define LOGINWAIT 300 /* 300 == 5 minutes to wait for valid username password */ /*-------------------------------------------------------------------------*/ typedef struct __TelTask { SConnection *pCon; int iLogin; char pLoginWord[132]; time_t tStart; } TelTask; /*--------------------------------------------------------------------------*/ pTelTask CreateTelnet(SConnection *pCon) { pTelTask pRes = NULL; char *pPtr = NULL; time_t shit; assert(pCon); /* check for the login word */ pPtr = IFindOption(pSICSOptions,"TelWord"); if(!pPtr) { return NULL; } pRes = (pTelTask)malloc(sizeof(TelTask)); if(!pRes) { return NULL; } /* initialise */ memset(pRes,0,sizeof(TelTask)); pRes->pCon = pCon; pRes->iLogin = 0; pRes->tStart = time(&shit); strcpy(pRes->pLoginWord,pPtr); return pRes; } /*--------------------------------------------------------------------------*/ void DeleteTelnet(void *pData) { pTelTask pKill = NULL; assert(pData); pKill = (pTelTask)pData; if(pKill->pCon) { SCDeleteConnection(pKill->pCon); } free(pKill); } /*-------------------------------------------------------------------------*/ static void SendWelcome(SConnection *pCon) { SCWrite(pCon,"--------- Welcome to SICS ------------",eError); SCWrite(pCon,"You are now connected to a SICS Instrument Control Server",eError); SCWrite(pCon,"\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",eError); SCWrite(pCon,"WARNING: Proceed with utmost care!",eError); SCWrite(pCon,"YOU MAY BE MOVING HARDWARE IN THE EXPERIMENT HALL",eError); SCWrite(pCon,"YOU MAY CAUSE GRIEVIOUS BODILY HARM TO SOMEBODY",eError); SCWrite(pCon,"YOU MAY DAMAGE VALUABLE AND SOMETIMES IRREPLACABLE HARDWARE", eError); SCWrite(pCon,"Continuing here seriously compromises hacker's ethics",eError); SCWrite(pCon,"You will NOT find valuable data here!",eError); SCWrite(pCon,"The SICS server does NOT allow you to spawn to the system",eError); SCWrite(pCon,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",eError); } /*-------------------------------------------------------------------------*/ static void SendGA(SConnection *pCon) { char pReply[2]; pReply[0] = (char)255; pReply[1] = (char)249; NETWrite(pCon->pSock,pReply,2); } /*--------------------------------------------------------------------------*/ int TelnetTaskOld(void *pData) { pTelTask self = NULL; char *pPtr = NULL; char *pLogin = NULL; char *pUser = NULL, *pPasswd = NULL; char pBuffer[512], pHost[131]; int iRet; time_t shit; self = (pTelTask)pData; assert(self); if(self->pCon->iEnd) { if(SCActive(self->pCon)) { return 1; } else { return 0; } } /* pop and execute */ iRet = CostaPop(self->pCon->pStack,&pPtr); if(iRet) { if(pPtr) { if(self->iLogin) /* handle normal command */ { /* check for logoff */ if(strstr(pPtr,"logoff") != NULL) { NetReadRemove(pServ->pReader,self->pCon->pSock); free(pPtr); self->pCon->iEnd = 1; return 0; } /* invoke command */ CostaLock(self->pCon->pStack); SCInvoke(self->pCon,pServ->pSics,pPtr); CostaUnlock(self->pCon->pStack); SendGA(self->pCon); free(pPtr); } else /* handle login messages */ { pLogin = strstr(pPtr,self->pLoginWord); if(!pLogin) { SCWrite(self->pCon, "------------------- Get Lost -------------------", eError); if(time(&shit) > self->tStart + LOGINWAIT) { SCWrite(self->pCon, "I cannot stand your login attempts anymore!", eError); NetReadRemove(pServ->pReader,self->pCon->pSock); self->pCon->iEnd = 1; free(pPtr); return 0; } free(pPtr); return 1; } else /* check username / password */ { pLogin += strlen(self->pLoginWord); pUser = strtok(pLogin," \t"); pPasswd = strtok(NULL," \t\r\n"); iRet = IsValidUser(pUser,pPasswd); if(iRet < 0) { sprintf(pBuffer,"SYSTEM ATTACK by %s / %s",pUser, pPasswd); SICSLogWrite(pBuffer,eInternal); SCWrite(self->pCon, "I do not know you, I do not let you in",eError); SendGA(self->pCon); free(pPtr); return 1; } else { NETInfo(self->pCon->pSock,pHost,131); sprintf(pBuffer,"Accepted connection on socket %d from %s", self->pCon->pSock->sockid, pHost); SICSLogWrite(pBuffer,eInternal); WriteToCommandLog("SYS >", pBuffer); SendWelcome(self->pCon); SCSetRights(self->pCon,iRet); self->iLogin = 1; SendGA(self->pCon); free(pPtr); return 1; } } } } } /* check for no commands but timeout on telnet */ if( !self->iLogin && (time(&shit) > self->tStart + LOGINWAIT) ) { self->pCon->iEnd = 1; NetReadRemove(pServ->pReader,self->pCon->pSock); return 0; } /* check for end */ if(self->pCon->iEnd) { if(SCActive(self->pCon)) { return 1; } else { return 0; } } return 1; } /*--------------------------------------------------------------------------*/ int TelnetTask(void *pData) { pTelTask self = NULL; char *pPtr = NULL; char *pLogin = NULL; char *pUser = NULL, *pPasswd = NULL; char pBuffer[512], pHost[131]; int iRet; time_t shit; self = (pTelTask)pData; assert(self); if(self->pCon->iEnd) { if(SCActive(self->pCon)) { return 1; } else { return 0; } } /* pop and execute */ iRet = CostaPop(self->pCon->pStack,&pPtr); if(iRet) { if(pPtr) { if(self->iLogin) /* handle normal command */ { /* check for logoff */ if(strstr(pPtr,"logoff") != NULL) { ANETclose(self->pCon->sockHandle); free(pPtr); self->pCon->iEnd = 1; return 0; } /* invoke command */ CostaLock(self->pCon->pStack); SCInvoke(self->pCon,pServ->pSics,pPtr); CostaUnlock(self->pCon->pStack); SendGA(self->pCon); free(pPtr); } else /* handle login messages */ { pLogin = strstr(pPtr,self->pLoginWord); if(!pLogin) { SCWrite(self->pCon, "------------------- Get Lost -------------------", eError); if(time(&shit) > self->tStart + LOGINWAIT) { SCWrite(self->pCon, "I cannot stand your login attempts anymore!", eError); ANETclose(self->pCon->sockHandle); self->pCon->iEnd = 1; free(pPtr); return 0; } free(pPtr); return 1; } else /* check username / password */ { pLogin += strlen(self->pLoginWord); pUser = strtok(pLogin," \t"); pPasswd = strtok(NULL," \t\r\n"); iRet = IsValidUser(pUser,pPasswd); if(iRet < 0) { sprintf(pBuffer,"SYSTEM ATTACK by %s / %s",pUser, pPasswd); SICSLogWrite(pBuffer,eInternal); SCWrite(self->pCon, "I do not know you, I do not let you in",eError); SendGA(self->pCon); free(pPtr); return 1; } else { sprintf(pBuffer,"Accepted telnet connection on handle %d", self->pCon->sockHandle); SICSLogWrite(pBuffer,eInternal); WriteToCommandLog("SYS >", pBuffer); SendWelcome(self->pCon); SCSetRights(self->pCon,iRet); self->iLogin = 1; SendGA(self->pCon); free(pPtr); return 1; } } } } } /* check for no commands but timeout on telnet */ if( !self->iLogin && (time(&shit) > self->tStart + LOGINWAIT) ) { self->pCon->iEnd = 1; ANETclose(self->pCon->sockHandle); return 0; } /* check for end */ if(self->pCon->iEnd) { if(SCActive(self->pCon)) { return 1; } else { return 0; } } return 1; } /*---------------------------------------------------------------------------*/ void TelnetSignal(void *pData, int iSignal, void *pSigData) { pTelTask self = NULL; int *iInt; char *pPtr; self = (pTelTask)pData; assert(self); if(iSignal == SICSINT) { iInt = (int *)pSigData; SCSetInterrupt(self->pCon,*iInt); if(*iInt == eEndServer) { self->pCon->iEnd = 1; } } else if(iSignal == SICSBROADCAST) { pPtr = (char *)pSigData; if(pPtr) { SCWrite(self->pCon,pPtr,eWarning); } } else if(iSignal == TOKENRELEASE) { self->pCon->iGrab = 0; } else if(iSignal == TOKENGRAB) { self->pCon->iGrab = 1; } } /*-------------------------------------------------------------------------*/ static mkChannel *pTelnet = NULL; void InstallTelnet(void) { char *pPtr = NULL; int i, iPort; /* No double telnet ports ! */ assert(!pTelnet); /* if the option is not there or invalid, telnet is disabled */ pPtr = IFindOption(pSICSOptions,"TelnetPort"); if(!pPtr) { return; } i = sscanf(pPtr,"%d",&iPort); /* if(i > 0) { pTelnet = NETOpenPort(iPort); } if(pTelnet) { NetReadRegister(pServ->pReader,pTelnet, taccept, NULL); } */ /* when we have a port have the NetReader listen and handle it */ NetReadInstallANETPort(pServ->pReader,taccept, iPort); } /*---------------------------------------------------------------------------*/ void KillTelnet(void) { if(pTelnet) { NETClosePort(pTelnet); /* NetReadRemove(pServ->pReader,pTelnet); */ free(pTelnet); pTelnet = NULL; } } /*------------------------------------------------------------------------ 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