windows-nt/Source/XPSP1/NT/sdktools/wsremote/server.c

2391 lines
62 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) Microsoft Corporation, 1992 - 1999
Module Name:
Server.c
Abstract:
The server component of Remote. It spawns a child process
and redirects the stdin/stdout/stderr of child to itself.
Waits for connections from clients - passing the
output of child process to client and the input from clients
to child process.
Author:
Rajivendra Nath (rajnath) 2-Jan-1992
Environment:
Console App. User mode.
Revision History:
--*/
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include "Remote.h"
#define MAX_SESSION 10
#define COMMANDFORMAT TEXT("%c%-15s [%-15s %s]\n%c")
#define LOCALNAME TEXT("Local")
#define LOCALCLIENT(x) (strcmp((char *)(x->Name),LOCALNAME)==0)
#define RemoteInfo(prt,flg) {if (!(flg&&0x80000000)) prt;}
#define CMDSTRING(OutBuff,InpBuff,Client,szTime) { \
_stprintf \
( \
&OutBuff[0],COMMANDFORMAT,\
BEGINMARK,InpBuff, \
Client->Name,szTime, \
ENDMARK \
); \
} \
#ifdef UNICODE
int MakeCommandString(
TCHAR * pszOutput,
TCHAR * pszInput,
TCHAR * pszName,
TCHAR * pszTime);
#endif
#define BUFFSIZE 256
#ifdef INTERNALUSECOMPONENT
VOID InitAd(BOOL IsAdvertise);
VOID ShutAd(BOOL IsAdvertise);
#endif
static SOCKET listenSocket;
SESSION_TYPE ClientList[MAX_SESSION];
HANDLE ChildStdInp; //Server Writes to it
HANDLE ChildStdOut; //Server Reads from it
HANDLE ChildStdErr; //Server Reads from it
HANDLE SaveFile; //File containing all that was
//output by child process.
//Each connection opens a handle to this file
//and is sent through PipeWriteH.
TCHAR SaveFileName[MAX_PATH+1]; //Name of above file - all new sessions need
HANDLE ChldProc;
HANDLE ListenThreadH;
HANDLE SockListenThreadH;
// GetFormattedTime -- returns pointer to formatted time
//
// returns pointer to static buffer which should be OK.
//
TCHAR * GetFormattedTime(VOID)
{
static TCHAR szTime[30];
//
// Get time and format to characters
//
GetTimeFormat( LOCALE_USER_DEFAULT,
TIME_NOSECONDS | TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
NULL, // use current time
NULL, // use default format
szTime,
30 );
return( (TCHAR *)&szTime );
}
HANDLE
ForkChildProcess( // Creates a new process
TCHAR *cmd, // Redirects its stdin,stdout
PHANDLE in, // and stderr - returns the
PHANDLE out, // corresponding pipe ends.
PHANDLE err
);
HANDLE
OldForkChildProcess( //Same as above except different
TCHAR *cmd, //method for redirection...for
PHANDLE in, //compatibility with.
PHANDLE out,
PHANDLE err
);
DWORD
ListenForSession( //THREAD:Listens for new connections and
TCHAR * pipe //spawns of new seesions - Updates the
); //Status in Client DataStructure.
DWORD
NewSession( //Manages the session with a client.
SESSION_TYPE* Client
);
DWORD //2 THREAD:Each reads either
GetChldOutput( //StdOut or StdErr of child and
HANDLE rhandle //writes to SaveFile.
);
DWORD
TransferFileToClient( //X THREADS:Reads the save
SESSION_TYPE* Client //file and sendsoutput to a client.
);
DWORD
GetClientInput( //X THREADS:Gets input from Child pipe
SESSION_TYPE* Client //and sends to childs StdIn.
);
BOOL
FilterCommand( //Filters input from client
SESSION_TYPE *cl, //for commands intended for REMOTE
TCHAR *buff,
int dread
);
DWORD
LocalSession(
PVOID noarg
);
DWORD
RemoteSession(
SESSION_TYPE* Client
);
BOOL
SrvCtrlHand(
DWORD event
);
VOID
SendStatus(
HANDLE hClientPipe
);
VOID
SockSendStatus(
SOCKET MySocket
);
DWORD
ShowPopup(
TCHAR *mssg
);
VOID
RemoveInpMark(
TCHAR* Buff,
DWORD Size
);
VOID
CloseClient(
SESSION_TYPE *Client
);
VOID
InitClientList(
);
/*************************************************************/
/*************************************************************/
DWORD
SockListenForSession( //THREAD:Listens for new connections and
TCHAR* pipe //spawns of new seesions - Updates the
); //Status in Client DataStructure.
DWORD
SockNewSession( //Manages the session with a client.
SESSION_TYPE* Client
);
DWORD
SockTransferFileToClient( //X THREADS:Reads the save
SESSION_TYPE* Client //file and sendsoutput to a client.
);
DWORD
SockRemoteSession(
SESSION_TYPE* Client
);
DWORD
SockGetClientInput( //X THREADS:Gets input from Child pipe
SESSION_TYPE* Client //and sends to childs StdIn.
);
BOOL
SockAuthenticate(
SOCKET MySocket
);
/*************************************************************/
/*************************************************************/
/*************************************************************/
VOID
Server( //Main routine for server.
TCHAR* ChildCmd,
TCHAR* PipeName
)
{
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
DWORD ThreadID ;//No use
HANDLE WaitH[3];
DWORD WaitObj;
TCHAR tmpdir[MAX_PATH+1];
int nRet;
_tprintf(TEXT("**************************************\n")
TEXT("*********** WSREMOTE ************\n")
TEXT("*********** SERVER ************\n")
TEXT("**************************************\n")
TEXT("To Connect: WSRemote /C %s %s\n\n"),HostName,PipeName);
InitClientList();
//
// Initialize WinSock
//
nRet = WSAStartup(wVersionRequested, &wsaData);
if (nRet)
{
_tprintf(TEXT("Initialize WinSock Failed"));
return ;
}
// Check version
if (wsaData.wVersion != wVersionRequested)
{
_tprintf(TEXT("Wrong WinSock Version"));
return;
}
//
// set environment variable
//
SetEnvironmentVariable(TEXT("_REMOTE"), PipeName);
//
//Start the command as a child process
//
ChldProc=ForkChildProcess(ChildCmd,&ChildStdInp,&ChildStdOut,&ChildStdErr);
//
//Create a tempfile for storing Child process output.
//
{
DWORD rc = GetTempPath(sizeof(tmpdir),tmpdir);
if (!rc || rc > sizeof(tmpdir))
{
_stprintf(tmpdir,TEXT("%s"),TEXT("."));
}
if (!GetTempFileName(tmpdir,TEXT("REMOTE"),0,SaveFileName))
GetTempFileName(TEXT("."),TEXT("REMOTE"),0,SaveFileName);
}
if ((SaveFile=CreateFile(
(LPCTSTR)SaveFileName, /* address of name of the file */ \
GENERIC_READ|GENERIC_WRITE, /* access (read/write) mode */ \
FILE_SHARE_READ|FILE_SHARE_WRITE,/* share mode */ \
(LPSECURITY_ATTRIBUTES)NULL, /* security descriptor */ \
CREATE_ALWAYS, /* how to create */ \
FILE_ATTRIBUTE_NORMAL, /* File Attribute */ /* file attributes */ \
(HANDLE)NULL))==NULL)
{
TerminateProcess(ChldProc,0);
ErrorExit(TEXT("Could not Create Output File"));
}
//
//Start 2 threads to save the output from stdout and stderr of cmd to savefile.
//
if ((WaitH[0]=CreateThread(
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)GetChldOutput, // Thread procedure.
(LPVOID)ChildStdErr, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
TerminateProcess(ChldProc,0);
ErrorExit(TEXT("Failed to Create GetGhldOutput#1 Thread"));
}
if ((WaitH[1]=CreateThread(
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)GetChldOutput, // Thread procedure.
(LPVOID)ChildStdOut, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
TerminateProcess(ChldProc,0);
ErrorExit(TEXT("Failed to Create GetGhldOutput#2 Thread"));
}
//
//Start Thread to listen for new Connections
//
if ((ListenThreadH=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)ListenForSession, // Thread procedure.
(LPVOID)PipeName, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
TerminateProcess(ChldProc,0);
ErrorExit(TEXT("Failed To Create ListenForSession Thread"));
}
//
//Start Thread to listen for new Connections
//
if ((SockListenThreadH=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SockListenForSession, // Thread procedure.
(LPVOID)PipeName, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
TerminateProcess(ChldProc,0);
ErrorExit(TEXT("Failed To Create SockListenForSession Thread"));
}
//
//Start Local Thread
//
if ((ClientList[0].hThread=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)LocalSession, // Thread procedure.
(LPVOID)NULL, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
TerminateProcess(ChldProc,0);
ErrorExit(TEXT("Failed To Create ListenForSession Thread"));
}
SetConsoleCtrlHandler((PHANDLER_ROUTINE)SrvCtrlHand,TRUE);
#ifdef INTERNALUSECOMPONENT
InitAd(IsAdvertise);
#endif
WaitH[2]=ChldProc;
WaitObj=WaitForMultipleObjects(3,WaitH,FALSE,INFINITE);
switch (WaitObj-WAIT_OBJECT_0)
{
case 0: // Error Writing to savefile
case 1:
TerminateProcess(ChldProc,0);
break;
case 2: // Child Proc Terminated
break;
default: // Out of Some Resource
_tprintf(TEXT("Out of Resource Error %d..Terminating\n"),GetLastError());
break;
}
TerminateThread(ListenThreadH,0);
// SOCK:
TerminateThread(SockListenThreadH,0);
#ifdef INTERNALUSECOMPONENT
ShutAd(IsAdvertise);
#endif
CloseHandle(ChildStdInp);
CloseHandle(ChildStdOut);
CloseHandle(ChildStdErr);
//WSACleanup
WSACleanup();
_tprintf(TEXT("\nCalling WSACleanup()..\n"));
_tprintf(TEXT("\nRemote:Parent exiting. Child(%s) dead..\n"),ChildCmd);
CloseHandle(SaveFile);
{
int i;
for (i=0;i<MAX_SESSION;i++)
CloseClient(&ClientList[i]);
}
if (!DeleteFile(SaveFileName))
_tprintf(TEXT("Temp File %s not deleted..\n"),SaveFileName);
return;
}
/*************************************************************/
HANDLE
ForkChildProcess( // Creates a new process
TCHAR *cmd, // Redirects its stdin,stdout
PHANDLE inH, // and stderr - returns the
PHANDLE outH, // corresponding pipe ends.
PHANDLE errH
)
{
SECURITY_ATTRIBUTES lsa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE ChildIn;
HANDLE ChildOut;
HANDLE ChildErr;
lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
lsa.lpSecurityDescriptor=NULL;
lsa.bInheritHandle=TRUE;
//
//Create Parent_Write to ChildStdIn Pipe
//
if (!CreatePipe(&ChildIn,inH,&lsa,0))
ErrorExit(TEXT("Could Not Create Parent-->Child Pipe"));
//
//Create ChildStdOut to Parent_Read pipe
//
if (!CreatePipe(outH,&ChildOut,&lsa,0))
ErrorExit(TEXT("Could Not Create Child-->Parent Pipe"));
//
//Create ChildStdOut to Parent_Read pipe
//
if (!CreatePipe(errH,&ChildErr,&lsa,0))
ErrorExit(TEXT("Could Not Create Child-->Parent Pipe"));
//
// Lets Redirect Console StdHandles - easy enough
//
si.cb=sizeof(STARTUPINFO);
si.lpReserved=NULL;
si.lpTitle=NULL;
si.lpDesktop=NULL;
si.dwX=si.dwY=si.dwYSize=si.dwXSize=0;
si.dwFlags=STARTF_USESTDHANDLES;
si.hStdInput =ChildIn;
si.hStdOutput=ChildOut;
si.hStdError =ChildErr;
si.wShowWindow=SW_SHOW;
si.lpReserved2=NULL;
si.cbReserved2=0;
//
//Create Child Process
//
if (!CreateProcess( NULL,
cmd,
NULL,
NULL,
TRUE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&pi))
{
if (GetLastError()==2)
_tprintf(TEXT("Executable %s not found\n"),cmd);
ErrorExit(TEXT("Could Not Create Child Process"));
}
//
//Close unneccesary Handles and Restore the crt handles
//
CloseHandle(ChildIn);
CloseHandle(ChildOut);
CloseHandle(ChildErr);
return(pi.hProcess);
}
/*************************************************************/
HANDLE
OldForkChildProcess(
TCHAR *cmd,
PHANDLE inH,
PHANDLE outH,
PHANDLE errH
)
{
SECURITY_ATTRIBUTES lsa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE OldStdIn =GetStdHandle(STD_INPUT_HANDLE);
HANDLE OldStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE OldStdErr=GetStdHandle(STD_ERROR_HANDLE);
HANDLE ChildStdIn;
HANDLE ChildStdOut;
HANDLE ChildStdErr;
lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
lsa.lpSecurityDescriptor=NULL;
lsa.bInheritHandle=TRUE;
//Create Parent_Write to ChildStdIn Pipe
if (!CreatePipe(&ChildStdIn,inH,&lsa,0))
ErrorExit(TEXT("Could Not Create Parent-->Child Pipe"));
//Create ChildStdOut to Parent_Read pipe
if (!CreatePipe(outH,&ChildStdOut,&lsa,0))
ErrorExit(TEXT("Could Not Create Child-->Parent Pipe"));
//Create ChildStdOut to Parent_Read pipe
if (!CreatePipe(errH,&ChildStdErr,&lsa,0))
ErrorExit(TEXT("Could Not Create Child-->Parent Pipe"));
//Make ChildStdIn and Out as standard handles and get it inherited by child
if (!SetStdHandle(STD_INPUT_HANDLE,ChildStdIn))
ErrorExit(TEXT("Could not change StdIn"));
if (!SetStdHandle(STD_OUTPUT_HANDLE,ChildStdOut))
ErrorExit(TEXT("Could Not change StdOut"));
if (!SetStdHandle(STD_ERROR_HANDLE,ChildStdErr))
ErrorExit(TEXT("Could Not change StdErr"));
si.cb=sizeof(STARTUPINFO);
si.lpReserved=NULL;
si.lpTitle=NULL;
si.lpDesktop=NULL;
si.dwX=si.dwY=si.dwYSize=si.dwXSize=si.dwFlags=0L;
si.wShowWindow=SW_SHOW;
si.lpReserved2=NULL;
si.cbReserved2=0;
//Create Child Process
if (!CreateProcess( NULL,
cmd,
NULL,
NULL,
TRUE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&pi))
ErrorExit(TEXT("Could Not Create Child Process"));
//reset StdIn StdOut
if (!SetStdHandle(STD_INPUT_HANDLE,OldStdIn))
{
TerminateProcess(pi.hProcess,1);
ErrorExit(TEXT("Could not RESET StdIn"));
}
if (!SetStdHandle(STD_OUTPUT_HANDLE,OldStdOut))
{
TerminateProcess(pi.hProcess,1);
ErrorExit(TEXT("Could not RESET StdIn"));
}
if (!SetStdHandle(STD_ERROR_HANDLE,OldStdErr))
{
TerminateProcess(pi.hProcess,1);
ErrorExit(TEXT("Could not RESET StdIn"));
}
//Close unneccesary Handles
CloseHandle(ChildStdIn);
CloseHandle(ChildStdOut);
CloseHandle(ChildStdErr);
return(pi.hProcess);
}
/*************************************************************/
#if _MSC_FULL_VER >= 13008827
#pragma warning(push)
#pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
#endif
/*************************************************************/
DWORD
ListenForSession(
TCHAR* pipename
)
{
int i;
DWORD ThreadID;
HANDLE PipeH[2];
SECURITY_DESCRIPTOR SecurityDescriptor;
HANDLE TokenHandle;
TOKEN_DEFAULT_DACL DefaultDacl;
SECURITY_ATTRIBUTES lsa;
TCHAR fullnameIn[BUFFSIZE];
TCHAR fullnameOut[BUFFSIZE];
_stprintf(fullnameIn,SERVER_READ_PIPE ,TEXT("."),pipename);
_stprintf(fullnameOut,SERVER_WRITE_PIPE,TEXT("."),pipename);
//
// Initialize the security descriptor that we're going to
// use.
//
InitializeSecurityDescriptor
(
&SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION
);
(VOID) SetSecurityDescriptorDacl
(
&SecurityDescriptor,
TRUE,
NULL,
FALSE
);
DefaultDacl.DefaultDacl = NULL;
if (OpenProcessToken
(
GetCurrentProcess(),
TOKEN_ADJUST_DEFAULT,
&TokenHandle
))
{
//
// Remove the default DACL on the token
//
SetTokenInformation
(
TokenHandle,
TokenDefaultDacl,
&DefaultDacl,
sizeof( TOKEN_DEFAULT_DACL )
);
}
lsa.nLength=sizeof(SECURITY_ATTRIBUTES);
lsa.lpSecurityDescriptor=&SecurityDescriptor;
lsa.bInheritHandle=TRUE;
while(TRUE)
{
PipeH[0]=CreateNamedPipe
(
fullnameIn ,
PIPE_ACCESS_INBOUND ,
PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES,
0,0,0,&lsa
);
PipeH[1]=CreateNamedPipe
(
fullnameOut,
PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES,
0,0,0,&lsa
);
if (!ConnectNamedPipe(PipeH[0],NULL))
{
if (GetLastError()!=ERROR_PIPE_CONNECTED)
{
CloseHandle(PipeH[0]);
CloseHandle(PipeH[1]);
continue;
}
}
if (!ConnectNamedPipe(PipeH[1],NULL))
{
if (GetLastError()!=ERROR_PIPE_CONNECTED)
{
CloseHandle(PipeH[0]);
CloseHandle(PipeH[1]);
continue;
}
}
//
//Look For a Free Slot & if not- then terminate connection
//
for (i=1;i<MAX_SESSION;i++)
{
//
// Locate a Free Client block
//
if (!ClientList[i].Active)
break;
}
if (i<MAX_SESSION)
{
//
// Initialize the Client
//
ClientList[i].PipeReadH=PipeH[0];
ClientList[i].PipeWriteH=PipeH[1];
ClientList[i].Active=TRUE;
ClientList[i].SendOutput=TRUE;
ClientList[i].CommandRcvd=FALSE;
}
else
{
_tprintf(TEXT("Remote:Closing New Session - No more slots\n"));
CloseHandle(PipeH[0]);
CloseHandle(PipeH[1]);
continue;
}
//
//start new thread for this connection
//
if((ClientList[i].hThread=CreateThread (
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)RemoteSession, // Thread procedure.
(LPVOID)&ClientList[i], // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
CloseClient(&ClientList[i]);
continue;
}
}
return(0);
}
#if _MSC_FULL_VER >= 13008827
#pragma warning(pop)
#endif
/*************************************************************/
DWORD
RemoteSession(
SESSION_TYPE *MyClient
)
{
DWORD ReadCnt;
SESSION_STARTUPINFO ssi;
TCHAR *headerbuff;
TCHAR msg[BUFFSIZE];
DWORD tmp;
SESSION_STARTREPLY ssr;
memset((TCHAR *)&ssi,0,sizeof(ssi));
if ((MyClient->rSaveFile=CreateFile(
SaveFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL))==NULL)
{
CloseClient(MyClient);
return(1);
}
{
DWORD reply=0;
ReadFixBytes(MyClient->PipeReadH,(TCHAR *)MyClient->Name,HOSTNAMELEN-1,0);
//
//Last four Bytes contains a code
//
memcpy((TCHAR *)&reply,(TCHAR *)&(MyClient->Name[11]),4);
if (reply!=MAGICNUMBER)
{
//
// Unknown client
//
CloseClient(MyClient);
return(1);
}
ssr.MagicNumber=MAGICNUMBER;
ssr.Size=sizeof(ssr);
ssr.FileSize=GetFileSize( MyClient->rSaveFile, &tmp );
WriteFile(MyClient->PipeWriteH,(TCHAR *)&ssr,sizeof(ssr),&tmp,NULL);
}
if (ReadFixBytes(MyClient->PipeReadH,(TCHAR *)&(ssi.Size),sizeof(ssi.Size),0)!=0)
{
CloseClient(MyClient);
return(1);
}
if (ssi.Size>1024) //Sanity Check
{
_stprintf(msg,TEXT("%s"),"Server:Unknown Header..Terminating session\n");
WriteFile(MyClient->PipeWriteH,msg,_tcslen(msg),&tmp,NULL);
CloseClient(MyClient);
return(1);
}
if ((headerbuff=(TCHAR *)calloc(ssi.Size,1))==NULL)
{
_stprintf(msg,TEXT("%s"),"Server:Not Enough Memory..Terminating session\n");
WriteFile(MyClient->PipeWriteH,msg,_tcslen(msg),&tmp,NULL);
CloseClient(MyClient);
return(1);
}
ReadCnt=ssi.Size-sizeof(ssi.Size);
if (ReadFixBytes(MyClient->PipeReadH,(TCHAR *)headerbuff,ReadCnt,0)!=0)
{
CloseClient(MyClient);
return(1);
}
memcpy((TCHAR *)&ssi+sizeof(ssi.Size),headerbuff,sizeof(ssi)-sizeof(ssi.Size));
free(headerbuff);
/* Version */
if (ssi.Version!=VERSION)
{
_stprintf(msg,TEXT("WSRemote Warning:Server Version=%d Client Version=%d\n"),VERSION,ssi.Version);
WriteFile(MyClient->PipeWriteH,msg,_tcslen(msg),&tmp,NULL);
}
/* Name */
{
memcpy(MyClient->Name,ssi.ClientName,15);
MyClient->Name[14]=0;
}
/* Lines */
if (ssi.LinesToSend!=-1)
{
long PosFromEnd=ssi.LinesToSend*CHARS_PER_LINE;
DWORD BytesToSend=MINIMUM((DWORD)PosFromEnd,ssr.FileSize);
DWORD BytesRead;
TCHAR *buff=(TCHAR *)calloc(BytesToSend+1,1);
if (ssr.FileSize > (DWORD)PosFromEnd)
{
SetFilePointer( MyClient->rSaveFile,
-PosFromEnd,
(PLONG)NULL,
FILE_END
);
}
if (buff!=NULL)
{
if (!ReadFile(MyClient->rSaveFile,buff,BytesToSend,&BytesRead,NULL))
{
CloseClient(MyClient);
return(1);
}
RemoveInpMark(buff,BytesRead);
if (!WriteFile(MyClient->PipeWriteH,buff,BytesRead,&tmp,NULL))
{
CloseClient(MyClient);
return(1);
}
}
free(buff);
}
RemoteInfo(_tprintf(TEXT("\n**WSRemote:Connected To %s [%s]\n"),MyClient->Name,GetFormattedTime()),ssi.Flag);
NewSession(MyClient);
RemoteInfo(_tprintf(TEXT("\n**WSRemote:Disconnected From %s [%s]\n"),MyClient->Name,GetFormattedTime()),ssi.Flag);
CloseClient(MyClient);
return(0);
}
/*************************************************************/
DWORD
NewSession(
SESSION_TYPE* MyClient
)
{
DWORD ThreadId;
HANDLE rwThread[3];
MyClient->MoreData=CreateEvent
(
(LPSECURITY_ATTRIBUTES) NULL,/* address of security attributes */
FALSE, /* flag for manual-reset event */
TRUE, /* flag for initial state */
NULL /* address of event-object name */
);
if ((rwThread[0]=CreateThread (
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)GetClientInput, // Thread procedure.
(LPVOID)MyClient, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadId))==NULL)
{
return(GetLastError());
}
if ((rwThread[1]=CreateThread (
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)TransferFileToClient, // Thread procedure.
(LPVOID)MyClient, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadId))==NULL)
{
CloseHandle(rwThread[0]);
return(GetLastError());
}
rwThread[2]=ChldProc;
WaitForMultipleObjects(3, rwThread,FALSE, INFINITE);
TerminateThread(rwThread[0],1);
TerminateThread(rwThread[1],1);
CloseHandle(rwThread[0]);
CloseHandle(rwThread[1]);
return(0);
}
/*************************************************************/
DWORD
GetChldOutput(
HANDLE readH
)
{
TCHAR buff[BUFFSIZE];
DWORD dread;
DWORD tmp;
while(ReadFile(readH,buff,BUFFSIZE-1,&dread,NULL))
{
buff[dread]='\0';
if (!WriteFile(SaveFile,buff,dread,&tmp,NULL))
{
return(1);
}
//
// Signal Reader Thread that more data
//
{
int i;
DWORD err; //REMOVE
for (i=0;i<MAX_SESSION;i++)
{
if (ClientList[i].Active)
{
if (!SetEvent(ClientList[i].MoreData))
err=GetLastError(); //REMOVE
}
}
}
}
return(1);
}
/*************************************************************/
DWORD
TransferFileToClient(
SESSION_TYPE *MyClient
)
{
TCHAR buffin[BUFFSIZE],buffout[BUFFSIZE],cmdbuff[BUFFSIZE];
DWORD tmp;
DWORD dread=0,dwrite=0;
BOOL incmd=FALSE;
DWORD cmdP=0;
DWORD i;
TCHAR MyEchoStr[30];
_stprintf(MyEchoStr,TEXT("[%-15s"),MyClient->Name);
while(ReadFile(MyClient->rSaveFile,buffin,BUFFSIZE-1,&dread,NULL))
{
if (dread==0)
{
WaitForSingleObject(MyClient->MoreData,INFINITE);
continue;
}
dwrite=0;
for(i=0;i<dread;i++)
{
if (incmd)
{
if ((buffin[i]==ENDMARK)||(cmdP==BUFFSIZE-1))
{
incmd=FALSE;
cmdbuff[cmdP]=0;
if ((_tcsstr(cmdbuff,MyEchoStr)==NULL)||
(!MyClient->CommandRcvd))
{
if (!WriteFile(
MyClient->PipeWriteH,
cmdbuff,cmdP,&tmp,NULL))
{
return(1);
}
}
cmdP=0;
}
else
{
cmdbuff[cmdP++]=buffin[i];
}
}
else
{
if (buffin[i]==BEGINMARK)
{
if (dwrite!=0)
{
if (!WriteFile(
MyClient->PipeWriteH,
buffout,dwrite,&tmp,NULL))
{
return(1);
}
dwrite=0;
}
incmd=TRUE;
continue;
}
else
{
buffout[dwrite++]=buffin[i];
}
}
}
if (dwrite!=0)
{
if (!WriteFile(
MyClient->PipeWriteH,
buffout,dwrite,&tmp,NULL))
{
return(0);
}
}
}
return(1);
}
/*************************************************************/
DWORD
GetClientInput(
SESSION_TYPE *MyClient
)
{
TCHAR buff[BUFFSIZE];
DWORD tmp,dread;
#ifdef UNICODE
while(ReadFileW(MyClient->PipeReadH,buff,BUFFSIZE,&dread,NULL))
#else
while(ReadFile(MyClient->PipeReadH,buff,BUFFSIZE,&dread,NULL))
#endif
{
buff[dread]=0;
MyClient->CommandRcvd=TRUE;
if (FilterCommand(MyClient,buff,dread))
continue;
if (!WriteFile(ChildStdInp,buff,dread,&tmp,NULL))
{
ExitThread(0);
}
}
return(1);
}
/*************************************************************/
BOOL
FilterCommand(
SESSION_TYPE *cl,
TCHAR *buff,
int dread
)
{
TCHAR inp_buff[4096];
TCHAR tmpchar;
TCHAR ch[3];
DWORD tmp;
int len;
DWORD ThreadID; //Useless
if (dread==0)
return(FALSE);
buff[dread]=0;
if (buff[0]==COMMANDCHAR)
{
switch(buff[1])
{
case 'l':
case 'L':
if (bIPLocked == FALSE)
{
bIPLocked=TRUE;
_tprintf(TEXT("**LOCK: No IP Sessions Allowed\n"));
}
else
{
bIPLocked=FALSE;
_tprintf(TEXT("**LOCK: IP Sessions Now Allowed\n"));
}
break;
case 'o':
case 'O': cl->SendOutput=!cl->SendOutput;
break;
case 'k':
case 'K':TerminateProcess(ChldProc,1);
break;
case 's':
case 'S':
SendStatus(cl->PipeWriteH);
break;
case 'p':
case 'P':
{
TCHAR *mssg=(TCHAR *)calloc(4096,1); //Free it in called Proc
TCHAR *ack=TEXT("WSRemote:Popup Shown..\n");
if (mssg==NULL)
break;
_stprintf(mssg,TEXT("From %s [%s]\n\n%s\n"),cl->Name,GetFormattedTime(),&buff[2]);
CreateThread(
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)ShowPopup, // Thread procedure.
(LPVOID)mssg, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID
);
#ifdef UNICODE
WriteFileW(cl->PipeWriteH,ack,_tcslen(ack),&tmp,NULL);
#else
WriteFile(cl->PipeWriteH,ack,_tcslen(ack),&tmp,NULL);
#endif
break;
}
case 'm':
case 'M':
buff[dread-2]=0;
#ifdef UNICODE
MakeCommandString( inp_buff, buff, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,buff,cl,GetFormattedTime());
#endif
len=_tcslen(inp_buff);
#ifdef UNICODE
WriteFileW(SaveFile,inp_buff,len,&tmp,NULL);
#else
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
#endif
break;
case '@':
buff[dread-2]=0;
#ifdef UNICODE
MakeCommandString( inp_buff, buff, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,&buff[1],cl,GetFormattedTime());
#endif
len=_tcslen(inp_buff);
#ifdef UNICODE
WriteFileW(SaveFile,inp_buff,len,&tmp,NULL);
#else
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
#endif
//
// Remove the first @ sign
//
MoveMemory(buff,&buff[1],dread-1);
buff[dread-1]=' ';
return(FALSE); //Send it it to the chile process
break;
default :
_stprintf(inp_buff,TEXT("%s"),"** Unknown Command **\n");
#ifdef UNICODE
WriteFileW( cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
#else
WriteFile( cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
#endif
case 'h':
case 'H':
{
#ifdef UNICODE
_stprintf(inp_buff,TEXT("%cM: To Send Message\n"),COMMANDCHAR);
WriteFileW(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
_stprintf(inp_buff,TEXT("%cP: To Generate popup\n"),COMMANDCHAR);
WriteFileW(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
_stprintf(inp_buff,TEXT("%cK: To kill the server\n"),COMMANDCHAR);
WriteFileW(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
_stprintf(inp_buff,TEXT("%cH: This Help\n"),COMMANDCHAR);
WriteFileW(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
#else
_stprintf(inp_buff,TEXT("%cM: To Send Message\n"),COMMANDCHAR);
WriteFile(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
_stprintf(inp_buff,TEXT("%cP: To Generate popup\n"),COMMANDCHAR);
WriteFile(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
_stprintf(inp_buff,TEXT("%cK: To kill the server\n"),COMMANDCHAR);
WriteFile(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
_stprintf(inp_buff,TEXT("%cH: This Help\n"),COMMANDCHAR);
WriteFile(cl->PipeWriteH,inp_buff,_tcslen(inp_buff),&tmp,NULL);
#endif
break;
}
}
return(TRUE);
}
if ((buff[0]<26))
{
BOOL ret=FALSE;
#ifdef UNICODE
TCHAR * pszTime;
#endif
_stprintf(ch,TEXT("^%c"),buff[0]+64);
#ifdef UNICODE
pszTime = GetFormattedTime();
MakeCommandString( inp_buff, ch, cl->Name, pszTime);
#else
CMDSTRING(inp_buff,ch,cl,GetFormattedTime());
#endif
len=_tcslen(inp_buff);
if (buff[0]==CTRLC)
{
cl->CommandRcvd=FALSE;
GenerateConsoleCtrlEvent(CTRL_C_EVENT,0);
ret=TRUE; //Already sent to child
}
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
return(ret); //FALSE:send it to child StdIn
}
tmpchar=buff[dread-2]; //must be 13;but just incase
buff[dread-2]=0;
#ifdef UNICODE
MakeCommandString( inp_buff, buff, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,buff,cl,GetFormattedTime());
#endif
buff[dread-2]=tmpchar;
len=_tcslen(inp_buff);
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
return(FALSE);
}
/*************************************************************/
BOOL
SockFilterCommand(
SESSION_TYPE *cl,
TCHAR *buff,
int dread
)
{
TCHAR inp_buff[4096];
TCHAR tmpchar;
TCHAR ch[3];
DWORD tmp;
int len;
DWORD ThreadID; //Useless
if (dread==0)
return(FALSE);
buff[dread]=0;
if (buff[0]==COMMANDCHAR)
{
switch(buff[1])
{
case 'o':
case 'O': cl->SendOutput=!cl->SendOutput;
break;
case 'k':
case 'K':TerminateProcess(ChldProc,1);
break;
case 's':
case 'S':
SockSendStatus(cl->Socket);
break;
case 'p':
case 'P':
{
TCHAR *mssg=(TCHAR *)calloc(4096,1); //Free it in called Proc
TCHAR *ack=TEXT("WSRemote:Popup Shown..\n");
if (mssg==NULL)
break;
_stprintf(mssg,TEXT("From %s [%s]\n\n%s\n"),cl->Name,GetFormattedTime(),&buff[2]);
CreateThread(
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)ShowPopup, // Thread procedure.
(LPVOID)mssg, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID
);
WriteSocket(cl->Socket,ack,_tcslen(ack),&tmp);
break;
}
case 'm':
case 'M':
buff[dread-2]=0;
#ifdef UNICODE
MakeCommandString( inp_buff, buff, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,buff,cl,GetFormattedTime());
#endif
len=_tcslen(inp_buff);
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
break;
case '@':
buff[dread-2]=0;
#ifdef UNICODE
MakeCommandString( inp_buff, buff, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,&buff[1],cl,GetFormattedTime());
#endif
len=_tcslen(inp_buff);
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
//
// Remove the first @ sign
//
MoveMemory(buff,&buff[1],dread-1);
buff[dread-1]=' ';
return(FALSE); //Send it it to the chile process
break;
default :
_stprintf(inp_buff,TEXT("%s"),"** Unknown Command **\n");
WriteSocket(cl->Socket,inp_buff,_tcslen(inp_buff),&tmp);
case 'h':
case 'H':
_stprintf(inp_buff,TEXT("%cM: To Send Message\n"),COMMANDCHAR);
WriteSocket(cl->Socket,inp_buff,_tcslen(inp_buff),&tmp);
_stprintf(inp_buff,TEXT("%cP: To Generate popup\n"),COMMANDCHAR);
WriteSocket(cl->Socket,inp_buff,_tcslen(inp_buff),&tmp);
_stprintf(inp_buff,TEXT("%cK: To kill the server\n"),COMMANDCHAR);
WriteSocket(cl->Socket,inp_buff,_tcslen(inp_buff),&tmp);
_stprintf(inp_buff,TEXT("%cH: This Help\n"),COMMANDCHAR);
WriteSocket(cl->Socket,inp_buff,_tcslen(inp_buff),&tmp);
break;
}
return(TRUE);
}
if ((buff[0]<26))
{
BOOL ret=FALSE;
_stprintf(ch,TEXT("^%c"),buff[0]+64);
#ifdef UNICODE
MakeCommandString( inp_buff, ch, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,ch,cl,GetFormattedTime());
#endif
len=_tcslen(inp_buff);
if (buff[0]==CTRLC)
{
cl->CommandRcvd=FALSE;
GenerateConsoleCtrlEvent(CTRL_C_EVENT,0);
ret=TRUE; //Already sent to child
}
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
return(ret); //FALSE:send it to child StdIn
}
tmpchar=buff[dread-2]; //must be 13;but just incase
buff[dread-2]=0;
#ifdef UNICODE
MakeCommandString( inp_buff, buff, cl->Name, GetFormattedTime());
#else
CMDSTRING(inp_buff,buff,cl,GetFormattedTime());
#endif
buff[dread-2]=tmpchar;
len=_tcslen(inp_buff);
WriteFile(SaveFile,inp_buff,len,&tmp,NULL);
return(FALSE);
}
/*************************************************************/
VOID
SendStatus(
HANDLE hClientPipe
)
{
TCHAR buff[1024];
int i;
DWORD tmp;
TCHAR *env=(TCHAR *)GetEnvironmentStrings();
DWORD ver=GetVersion();
_stprintf(buff,TEXT("Command = %s\n"),ChildCmd);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
_stprintf(buff,TEXT("Server = %s PIPE=%s\n"),HostName,PipeName);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
_stprintf(buff,TEXT("IP Blocking= %d\n"),(DWORD)bIPLocked);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
_stprintf(buff,TEXT("Username= %s Password=%s\n"),Username,Password);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
_stprintf(buff,TEXT("Build = %d \n"),((WORD *)&ver)[1]);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
for (i=1;i<MAX_SESSION;i++)
{
if (ClientList[i].Active)
{
_stprintf(buff,TEXT("ACTIVE SESSION=%s\n"),ClientList[i].Name);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
}
}
_stprintf(buff,TEXT("====================\n"),Server,PipeName);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
_stprintf(buff,TEXT("ENVIRONMENT VARIABLES\n"),Server,PipeName);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
_stprintf(buff,TEXT("====================\n"),Server,PipeName);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
__try
{
while (*env!=0)
{
_stprintf(buff,TEXT("%s\n"),env);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
while(*(env++)!=0);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
_stprintf(buff,TEXT("Exception Generated Getting Environment Block\n"),env);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
}
_stprintf(buff,TEXT("====================\n"),Server,PipeName);
WriteFile(hClientPipe,buff,_tcslen(buff),&tmp,NULL);
return;
}
/*************************************************************/
VOID
SockSendStatus(
SOCKET MySocket
)
{
TCHAR buff[1024];
int i;
DWORD tmp;
TCHAR *env=(TCHAR *)GetEnvironmentStrings();
DWORD ver=GetVersion();
_stprintf(buff,TEXT("Command = %s\n"),ChildCmd);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
_stprintf(buff,TEXT("Server = %s Port=%s\n"),HostName,PipeName);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
_stprintf(buff,TEXT("IP Blocking= %d\n"),(DWORD)bIPLocked);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
_stprintf(buff,TEXT("Username= %s Password=%s\n"),Username,Password);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
_stprintf(buff,TEXT("Build = %d \n"),((WORD *)&ver)[1]);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
for (i=1;i<MAX_SESSION;i++)
{
if (ClientList[i].Active)
{
_stprintf(buff,TEXT("ACTIVE SESSION=%s from IP %s \n"),ClientList[i].Name, ClientList[i].szIP );
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
}
}
_stprintf(buff,TEXT("====================\n"),Server,PipeName);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
_stprintf(buff,TEXT("ENVIRONMENT VARIABLES\n"),Server,PipeName);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
_stprintf(buff,TEXT("====================\n"),Server,PipeName);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
__try
{
while (*env!=0)
{
_stprintf(buff,TEXT("%s\n"),env);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
while(*(env++)!=0);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
_stprintf(buff,TEXT("Exception Generated Getting Environment Block\n"),env);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
}
_stprintf(buff,TEXT("====================\n"),Server,PipeName);
WriteSocket(MySocket,buff,_tcslen(buff),&tmp);
return;
}
/*************************************************************/
DWORD
ShowPopup(
TCHAR *mssg
)
{
MessageBox(GetActiveWindow(),mssg,TEXT("***WSREMOTE***"),MB_OK|MB_SETFOREGROUND);
free(mssg);
return(0);
}
/*************************************************************/
BOOL SrvCtrlHand(
DWORD event
)
{
if (event==CTRL_BREAK_EVENT)
{
TerminateProcess(ChldProc,1);
return(TRUE);
}
else if (event==CTRL_C_EVENT)
return(TRUE);
return(FALSE);
}
/*************************************************************/
DWORD LocalSession(PVOID noarg)
{
//Local is ClientList[0]
TCHAR *name=(TCHAR *)ClientList[0].Name;
_tcscpy(name,LOCALNAME);
if ((ClientList[0].rSaveFile=CreateFile(SaveFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL))==NULL)
{
_tprintf(TEXT("WSRemote:Cannot open ReadHandle to Savefile:%d\n"),GetLastError());
ClientList[0].Active=FALSE;
return(1);
}
ClientList[0].PipeReadH=GetStdHandle(STD_INPUT_HANDLE);
ClientList[0].PipeWriteH=GetStdHandle(STD_OUTPUT_HANDLE);
ClientList[0].SendOutput=TRUE;
ClientList[0].Active=TRUE;
NewSession(&ClientList[0]);
CloseClient(&ClientList[0]);
return(0);
}
VOID
CloseClient(
SESSION_TYPE *Client
)
{
int nRet;
ZeroMemory(Client->Name,HOSTNAMELEN);
if (Client->PipeReadH!=INVALID_HANDLE_VALUE)
{
CloseHandle(Client->PipeReadH);
Client->PipeReadH=INVALID_HANDLE_VALUE;
}
if (Client->PipeWriteH!=INVALID_HANDLE_VALUE)
{
CloseHandle(Client->PipeWriteH);
Client->PipeWriteH=INVALID_HANDLE_VALUE;
}
if (Client->rSaveFile!=INVALID_HANDLE_VALUE)
{
CloseHandle(Client->rSaveFile);
Client->rSaveFile=INVALID_HANDLE_VALUE;
}
if (Client->MoreData!=NULL)
{
CloseHandle(Client->MoreData);
Client->MoreData=NULL;
}
if (Client->Socket!=INVALID_SOCKET)
{
nRet = shutdown(Client->Socket, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(Client->Socket);
Client->Socket=INVALID_SOCKET;
}
ZeroMemory(Client->szIP,16);
Client->Active=FALSE; //Keep it last else synch problem.
return;
}
VOID
InitClientList(
)
{
int i;
for (i=0;i<MAX_SESSION;i++)
{
ZeroMemory(ClientList[i].Name,HOSTNAMELEN);
ClientList[i].PipeReadH=INVALID_HANDLE_VALUE;
ClientList[i].PipeWriteH=INVALID_HANDLE_VALUE;
ClientList[i].rSaveFile=INVALID_HANDLE_VALUE;
ClientList[i].MoreData=NULL;
ClientList[i].Socket=INVALID_SOCKET;
ClientList[i].Active=FALSE;
ClientList[i].CommandRcvd=FALSE;
ClientList[i].SendOutput=FALSE;
ClientList[i].hThread=NULL;
ZeroMemory(ClientList[i].szIP,16);
}
return;
}
VOID
RemoveInpMark(
TCHAR* Buff,
DWORD Size
)
{
DWORD i;
for (i=0;i<Size;i++)
{
switch (Buff[i])
{
case BEGINMARK:
Buff[i]=' ';
break;
case ENDMARK:
if (i<2)
{
Buff[i]= ' ';
}
else
{
Buff[i] =Buff[i-1];
Buff[i-1]=Buff[i-2];
Buff[i-2]=' ';
}
break;
default:
break;
}
}
}
/*************************************************************/
DWORD
SockListenForSession(
TCHAR* szListenPort
)
{
// Bind and Listen
DWORD ThreadID;
SOCKADDR_IN saServer;
int nRet;
unsigned short usPort;
int i;
// Accept
SOCKET socketClient;
SOCKADDR_IN SockAddr;
int nLen;
int iWSAErr;
TCHAR * pszInetAddress = NULL;
//
// Create a TCP/IP stream socket
//
listenSocket = socket ( AF_INET,
SOCK_STREAM,
IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
_tprintf (TEXT("Could not create listen socket: %d"), WSAGetLastError() );
return FALSE;
}
//
// Get the port number
// TODO: Check szListenPort for Alpha Chars
//
usPort = (unsigned short)_ttoi( szListenPort );
if (usPort == 0)
{
_tprintf (TEXT("**Invalid Listen Port: %s\n"),szListenPort);
_tprintf (TEXT("**No Socket Connections Allowed....\n"));
nRet = shutdown(listenSocket, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(listenSocket);
return FALSE;
}
saServer.sin_port = htons(usPort);
//
// Fill in the rest of the address structure
//
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = INADDR_ANY;
//
// Bind our name to the socket
//
nRet = bind( listenSocket,
(LPSOCKADDR)&saServer,
sizeof(struct sockaddr));
if (nRet == SOCKET_ERROR)
{
_tprintf (TEXT("bind() error: %d"), WSAGetLastError() );
nRet = shutdown(listenSocket, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(listenSocket);
return FALSE;
}
//
// Set the Socket to listen
//
nRet = listen(listenSocket, SOMAXCONN);
if (nRet == SOCKET_ERROR)
{
_tprintf (TEXT("listen error() error: %d"), WSAGetLastError() );
nRet = shutdown(listenSocket, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(listenSocket);
return FALSE;
}
while (1)
{
// Block on Accept()
nLen = sizeof(SOCKADDR_IN);
socketClient = accept (listenSocket,
(LPSOCKADDR)&SockAddr,
&nLen);
if (socketClient == INVALID_SOCKET)
{
//Accept Failed
_tprintf (TEXT("accept error() error: %d"), WSAGetLastError() );
break;
}// if
#ifdef UNICODE
pszInetAddress = inet_ntoaw(SockAddr.sin_addr);
#else
pszInetAddress = inet_ntoa(SockAddr.sin_addr);
#endif
_tprintf( TEXT("\nCONNECT on socket: %d\nFROM ip: %s"),
socketClient,
pszInetAddress );
//
//Look For a Free Slot & if not- then terminate connection
//
for (i=1;i<MAX_SESSION;i++)
{
//
// Locate a Free Client block
//
if (!ClientList[i].Active)
break;
}// for
if ( (i<MAX_SESSION) && (bIPLocked == FALSE) )
{
//
// Initialize the Client
//
ClientList[i].PipeReadH=INVALID_HANDLE_VALUE;
ClientList[i].PipeWriteH=INVALID_HANDLE_VALUE;
ClientList[i].Active=TRUE;
ClientList[i].SendOutput=TRUE;
ClientList[i].CommandRcvd=FALSE;
// SOCK
ClientList[i].Socket=socketClient;
_tcscpy(ClientList[i].szIP,pszInetAddress);
#ifdef UNICODE
free( pszInetAddress );
#endif
//
//start new thread for this connection
//
if((ClientList[i].hThread=CreateThread (
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SockRemoteSession, // Thread procedure.
(LPVOID)&ClientList[i], // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadID))==NULL)
{
CloseClient(&ClientList[i]);
continue;
}// if
}
else
{
_tprintf(TEXT("WSRemote:Closing New Session - No more slots or IP is Locked Out\n"));
nRet = shutdown(socketClient, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(socketClient);
continue;
}//if
}// while
iWSAErr = WSAGetLastError();
_tprintf (TEXT("FATAL ERROR, Exiting SockListenForSession: %d"),
iWSAErr );
return 0;
}
/*************************************************************/
DWORD
SockRemoteSession(
SESSION_TYPE *MyClient
)
{
//Declare Variables
//
DWORD ReadCnt;
DWORD tmp;
SESSION_STARTUPINFO ssi;
TCHAR * headerbuff;
TCHAR msg[BUFFSIZE];
SESSION_STARTREPLY ssr;
DWORD reply =0;
BOOL bRet;
if ((MyClient->rSaveFile=CreateFile(
SaveFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL))==NULL)
{
CloseClient(MyClient);
return(1);
}
bRet = SockAuthenticate(MyClient->Socket);
if (bRet == FALSE)
{
_tprintf(TEXT("\nAuth:Bad Username or Password\n"));
CloseClient(MyClient);
return(1);
}
// ReadSocket( MyClient->Socket,
// (TCHAR *)MyClient->Name,
// HOSTNAMELEN-1,
// &dwBytesRead);
SockReadFixBytes(MyClient->Socket,(TCHAR *)MyClient->Name,HOSTNAMELEN-1,0);
//
//Last four Bytes contains a code
//
memcpy((TCHAR *)&reply,(TCHAR *)&(MyClient->Name[11]),4);
if (reply!=MAGICNUMBER)
{
//
// Unknown client
//
CloseClient(MyClient);
return(1);
}
ssr.MagicNumber=MAGICNUMBER;
ssr.Size=sizeof(ssr);
ssr.FileSize=GetFileSize( MyClient->rSaveFile, &tmp );
send(MyClient->Socket,(const char *)&ssr,sizeof(ssr),0);
if (SockReadFixBytes(MyClient->Socket,(TCHAR *)&(ssi.Size),sizeof(ssi.Size),0)!=0)
{
CloseClient(MyClient);
return(1);
}
if (ssi.Size>1024) //Sanity Check
{
_stprintf(msg,TEXT("%s"),"Server:Unknown Header..Terminating session\n");
WriteSocket(MyClient->Socket,msg,_tcslen(msg),&tmp);
CloseClient(MyClient);
return(1);
}
if ((headerbuff=(TCHAR *)calloc(ssi.Size,1))==NULL)
{
_stprintf(msg,TEXT("%s"),"Server:Not Enough Memory..Terminating session\n");
WriteSocket(MyClient->Socket,msg,_tcslen(msg),&tmp);
CloseClient(MyClient);
return(1);
}
ReadCnt=ssi.Size-sizeof(ssi.Size);
if (SockReadFixBytes(MyClient->Socket,(TCHAR *)headerbuff,ReadCnt,0)!=0)
{
CloseClient(MyClient);
return(1);
}
memcpy((TCHAR *)&ssi+sizeof(ssi.Size),headerbuff,sizeof(ssi)-sizeof(ssi.Size));
free(headerbuff);
/* Version */
if (ssi.Version!=VERSION)
{
_stprintf(msg,TEXT("WSRemote Warning:Server Version=%d Client Version=%d\n"),VERSION,ssi.Version);
WriteSocket(MyClient->Socket,msg,_tcslen(msg),&tmp);
}
/* Name */
{
memcpy(MyClient->Name,ssi.ClientName,15);
MyClient->Name[14]=0;
}
/* Lines */
if (ssi.LinesToSend!=-1)
{
long PosFromEnd=ssi.LinesToSend*CHARS_PER_LINE;
DWORD BytesToSend=MINIMUM((DWORD)PosFromEnd,ssr.FileSize);
DWORD BytesRead;
TCHAR *buff=(TCHAR *)calloc(BytesToSend+1,1);
if (ssr.FileSize > (DWORD)PosFromEnd)
{
SetFilePointer( MyClient->rSaveFile,
-PosFromEnd,
(PLONG)NULL,
FILE_END
);
}
if (buff!=NULL)
{
if (!ReadFile(MyClient->rSaveFile,buff,BytesToSend,&BytesRead,NULL))
{
CloseClient(MyClient);
return(1);
}
RemoveInpMark(buff,BytesRead);
if (!WriteSocket(MyClient->Socket,buff,BytesRead,&tmp))
{
CloseClient(MyClient);
return(1);
}
}
free(buff);
}
RemoteInfo(_tprintf(TEXT("\n**WSRemote:Connected To %s ip=%s [%s]\n"),MyClient->Name,MyClient->szIP,GetFormattedTime()),ssi.Flag);
SockNewSession(MyClient);
RemoteInfo(_tprintf(TEXT("\n**WSRemote:Disconnected From %s ip=%s [%s]\n"),MyClient->Name,MyClient->szIP,GetFormattedTime()),ssi.Flag);
CloseClient(MyClient);
return(0);
}
/*************************************************************/
DWORD
SockNewSession(
SESSION_TYPE* MyClient
)
{
DWORD ThreadId;
HANDLE rwThread[3];
MyClient->MoreData=CreateEvent
(
(LPSECURITY_ATTRIBUTES) NULL,/* address of security attributes */
FALSE, /* flag for manual-reset event */
TRUE, /* flag for initial state */
NULL /* address of event-object name */
);
if ((rwThread[0]=CreateThread (
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SockGetClientInput, // Thread procedure.
(LPVOID)MyClient, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadId))==NULL)
{
return(GetLastError());
}
if ((rwThread[1]=CreateThread (
(LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SockTransferFileToClient, // Thread procedure.
(LPVOID)MyClient, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&ThreadId))==NULL)
{
CloseHandle(rwThread[0]);
return(GetLastError());
}
rwThread[2]=ChldProc;
WaitForMultipleObjects(3, rwThread,FALSE, INFINITE);
TerminateThread(rwThread[0],1);
TerminateThread(rwThread[1],1);
CloseHandle(rwThread[0]);
CloseHandle(rwThread[1]);
return(0);
}
/*************************************************************/
DWORD
SockGetClientInput(
SESSION_TYPE *MyClient
)
{
TCHAR buf[BUFFSIZE];
DWORD tmp,
dread;
memset(buf, 0, sizeof(buf));
while(ReadSocket(MyClient->Socket,buf,BUFFSIZE,&dread))
{
buf[sizeof(buf)]=0;
MyClient->CommandRcvd=TRUE;
if (0 == buf[0] )
return(1);
if (SockFilterCommand(MyClient,buf,dread))
continue;
if (!WriteFile(ChildStdInp,buf,dread,&tmp,NULL))
{
ExitThread(0);
}
memset(buf, 0, sizeof(buf));
}
return(1);
}
/*************************************************************/
DWORD
SockTransferFileToClient(
SESSION_TYPE *MyClient
)
{
TCHAR buffin[BUFFSIZE],
buffout[BUFFSIZE],
cmdbuff[BUFFSIZE];
DWORD tmp;
DWORD dread=0,dwrite=0;
BOOL incmd=FALSE;
DWORD cmdP=0;
DWORD i;
TCHAR MyEchoStr[30];
_stprintf(MyEchoStr,TEXT("[%-15s"),MyClient->Name);
while(ReadFile(MyClient->rSaveFile,buffin,BUFFSIZE-1,&dread,NULL))
{
if (dread==0)
{
WaitForSingleObject(MyClient->MoreData,INFINITE);
continue;
}
dwrite=0;
for(i=0;i<dread;i++)
{
if (incmd)
{
if ((buffin[i]==ENDMARK)||(cmdP==BUFFSIZE-1))
{
incmd=FALSE;
cmdbuff[cmdP]=0;
if ((_tcsstr(cmdbuff,MyEchoStr)==NULL)||
(!MyClient->CommandRcvd))
{
//if (!send (MyClient->Socket, cmdbuff, cmdP, 0));
//if (!SendBuffer(MyClient, cmdbuff, cmdP))
if (!WriteSocket(MyClient->Socket, cmdbuff,cmdP,&tmp))
{
return(1);
}
}
cmdP=0;
}
else
{
cmdbuff[cmdP++]=buffin[i];
}
}
else
{
if (buffin[i]==BEGINMARK)
{
if (dwrite!=0)
{
//if (!send (MyClient->Socket, buffout, dwrite, 0));
//if (!SendBuffer(MyClient, buffout, dwrite))
if (!WriteSocket(
MyClient->Socket,
buffout,dwrite,&tmp))
{
return(1);
}
dwrite=0;
}
incmd=TRUE;
continue;
}
else
{
buffout[dwrite++]=buffin[i];
}
}
}
if (dwrite!=0)
{
//if (!send (MyClient->Socket, buffout, dwrite, 0));
//if (!SendBuffer(MyClient, buffout, dwrite))
if (!WriteSocket(
MyClient->Socket,
buffout,dwrite,&tmp))
{
return(0);
}
}
}
return(1);
}
BOOL
SockAuthenticate(
SOCKET MySocket
)
{
BOOL bRead;
DWORD dread;
int bufflen;
int iCmp;
TCHAR EncodeBuffer[1024];
TCHAR CheckEncodeBuffer[1024];
TCHAR UserBuffer[1024];
TCHAR * String = UserBuffer;
TCHAR * pEncodeBuffer;
TCHAR * pCheckEncodeBuffer;
SetLastError(0);
memset(CheckEncodeBuffer, 0, sizeof(CheckEncodeBuffer));
_stprintf(
UserBuffer, TEXT("%s:%s"),
Username,
Password);
pCheckEncodeBuffer = CheckEncodeBuffer + _tcslen(CheckEncodeBuffer);
Base64Encode(UserBuffer, _tcslen(UserBuffer), pCheckEncodeBuffer);
bufflen = _tcslen(pCheckEncodeBuffer);
memset(EncodeBuffer, 0, sizeof(EncodeBuffer));
bRead = ReadSocket(MySocket,EncodeBuffer,bufflen,&dread);
pEncodeBuffer = EncodeBuffer;
iCmp = _tcscmp(pEncodeBuffer, pCheckEncodeBuffer);
if (iCmp != 0)
return FALSE;
return TRUE;
}
#ifdef UNICODE
int MakeCommandString(
TCHAR * pszOutput,
TCHAR * pszInput,
TCHAR * pszName,
TCHAR * pszTime
)
{
int nStrLen =_stprintf( pszOutput,
TEXT("\xfe%-15s [%-15s %s]\n\xff"),
pszInput,
pszName,
pszTime );
return nStrLen;
}
#endif