292 lines
7.8 KiB
C
292 lines
7.8 KiB
C
/*--------------------------------------------------------------------------
|
|
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 <time.h>
|
|
#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
|