/*++ 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 #include #include #include #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;iChild 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; 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 - everyone has access (use remote.exe if you want /u support) // InitializeSecurityDescriptor ( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); (VOID) SetSecurityDescriptorDacl ( &SecurityDescriptor, TRUE, NULL, FALSE ); 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= 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;iName); while(ReadFile(MyClient->rSaveFile,buffin,BUFFSIZE-1,&dread,NULL)) { if (dread==0) { WaitForSingleObject(MyClient->MoreData,INFINITE); continue; } dwrite=0; for(i=0;iCommandRcvd)) { 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;iName,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;irSaveFile=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;iCommandRcvd)) { //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