/*-------------------------------------------------------------------------- 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 "fortify.h" #include "asynnet.h" #include "conman.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); strlcpy(pRes->pLoginWord, pPtr,131); 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; ANETwrite(SCGetSockHandle(pCon), pReply, 2); } /*--------------------------------------------------------------------------*/ 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 (SCGetEnd(self->pCon)) { if (SCActive(self->pCon)) { return 1; } else { Log(INFO,"sys","Handle %d disconnected", self->pCon->sockHandle); return 0; } } /* pop and execute */ iRet = SCCostaTop(self->pCon,pPtr); if (iRet) { if (pPtr) { if (self->iLogin) { /* handle normal command */ /* check for logoff */ if (strstr(pPtr, "logoff") != NULL) { SCClose(self->pCon); free(pPtr); return 0; } /* invoke command */ SCCostaLock(self->pCon); SCInvoke(self->pCon, pServ->pSics, pPtr); SCCostaUnLock(self->pCon); 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); SCClose(self->pCon); 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) { snprintf(pBuffer,sizeof(pBuffer)-1, "SYSTEM ATTACK by %s / %s", pUser, pPasswd); Log(FATAL,"sys","%s",pBuffer); SCWrite(self->pCon, "I do not know you, I do not let you in", eError); SendGA(self->pCon); free(pPtr); return 1; } else { snprintf(pBuffer,sizeof(pBuffer)-1, "Accepted telnet connection on handle %d", SCGetSockHandle(self->pCon)); Log(INFO,"com","%s",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)) { SCSetEnd(self->pCon,1); SCClose(self->pCon); return 0; } /* check for end */ if (SCGetEnd(self->pCon)) { 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) { SCSetEnd(self->pCon,1); } } else if (iSignal == SICSBROADCAST) { pPtr = (char *) pSigData; if (pPtr) { SCWrite(self->pCon, pPtr, eWarning); } } else if (iSignal == TOKENRELEASE) { SCSetGrab(self->pCon,0); } else if (iSignal == TOKENGRAB) { SCSetGrab(self->pCon,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); NetReadInstallANETPort(pServ->pReader, taccept, iPort); } /*---------------------------------------------------------------------------*/ void KillTelnet(void) { if (pTelnet) { NETClosePort(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