Compare commits
	
		
			2 commits
		
	
	
		
			4c6087fe9d
			...
			53cc2a08ce
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 53cc2a08ce | |||
| 9d71f33432 | 
					 4 changed files with 141 additions and 133 deletions
				
			
		|  | @ -12,7 +12,7 @@ endif() | |||
| project ("shell-server") | ||||
| 
 | ||||
| # Добавьте источник в исполняемый файл этого проекта. | ||||
| add_executable (shell-server "main.c" "server.c" "server.h") | ||||
| add_executable (shell-server "main.c" "server.c" "server.h" "client.c" "client.h") | ||||
| 
 | ||||
| if (CMAKE_VERSION VERSION_GREATER 3.12) | ||||
|   set_property(TARGET shell-server PROPERTY CXX_STANDARD 20) | ||||
|  |  | |||
							
								
								
									
										35
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								main.c
									
										
									
									
									
								
							|  | @ -3,31 +3,38 @@ | |||
| 
 | ||||
| #include "server.h" | ||||
| 
 | ||||
| void PrintHelpMessage() { | ||||
|     printf("Usage error: I know 3 arguments \n\t\"install\"\n\t\"delete\"\n\t\"app\"\n"); | ||||
| } | ||||
| 
 | ||||
| int _tmain(int argc, TCHAR *argv[]) { | ||||
|     printf("\n->Start of parent execution.\n"); | ||||
| int _tmain(int argc, char *argv[]) { | ||||
|     if (argc == 2) { | ||||
|         if (lstrcmpi(argv[1], TEXT("-c")) == 0) { | ||||
|             return 0; | ||||
|         } | ||||
|         else if (lstrcmpi(argv[1], TEXT("-s")) == 0) { | ||||
|         if (lstrcmpi(argv[1], TEXT("-s")) == 0) { | ||||
|             StartShellServer(); | ||||
|             return 0; | ||||
|         } | ||||
|         else { | ||||
|             PrintHelpMessage(); | ||||
|             return -1; | ||||
|             goto help_message; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|     else if (argc == 3) { | ||||
|         if (lstrcmpi(argv[1], TEXT("-c")) == 0) { | ||||
|             StartShellClient(argv[2]); | ||||
|             return 0; | ||||
|         } | ||||
|         // TODO: implement service
 | ||||
|         else if (lstrcmpi(argv[1], TEXT("-s")) == 0 && lstrcmpi(argv[2], TEXT("-service")) == 0) { | ||||
|             // CreateService
 | ||||
|             return 0; | ||||
|         } | ||||
|         else { | ||||
|             goto help_message; | ||||
|         } | ||||
|     } | ||||
|     else { | ||||
|         PrintHelpMessage(); | ||||
|         return -1; | ||||
|         goto help_message; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| help_message: | ||||
|     printf("Wrong usage\nUsage: %s [-c {remote ip} | -s [-service]]\n", argv[0]); | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										227
									
								
								server.c
									
										
									
									
									
								
							
							
						
						
									
										227
									
								
								server.c
									
										
									
									
									
								
							|  | @ -1,77 +1,32 @@ | |||
| #include "server.h" | ||||
| 
 | ||||
| #define BUFSIZE 4096 | ||||
| #define DEFAULT_PORT "50113" | ||||
| #define DEFAULT_BUFLEN 512 | ||||
| 
 | ||||
| // Handles for child process STDIN and STDOUT
 | ||||
| HANDLE g_hChildStd_IN_Rd = NULL; | ||||
| HANDLE g_hChildStd_IN_Wr = NULL; | ||||
| HANDLE g_hChildStd_OUT_Rd = NULL; | ||||
| HANDLE g_hChildStd_OUT_Wr = NULL; | ||||
| typedef struct PipeThreadInfo_t { | ||||
|     HANDLE Pipe; | ||||
|     SOCKET ClientSocket; | ||||
| } PipeThreadInfo; | ||||
| 
 | ||||
| SOCKET ClientSocket = INVALID_SOCKET; | ||||
| 
 | ||||
| //HANDLE g_hInputFile = NULL;
 | ||||
| void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr); | ||||
| DWORD WINAPI WorkWithClient(LPVOID lpParam); | ||||
| DWORD WINAPI WriteToPipe(LPVOID lpParam); | ||||
| DWORD WINAPI ReadFromPipe(LPVOID lpParam); | ||||
| void ErrorExit(PCTSTR); | ||||
| 
 | ||||
| void StartShellServer() { | ||||
|     printf("\n->Start of shell server execution.\n"); | ||||
| 
 | ||||
|     CreatePipes(); | ||||
|     CreateSocket(); | ||||
| 
 | ||||
|     // Create the child process. 
 | ||||
|     CreateChildProcess(); | ||||
| 
 | ||||
|     // TODO: split into threads
 | ||||
|     WriteToPipe(); | ||||
|     // Read from pipe that is the standard output for child process. 
 | ||||
|     ReadFromPipe(); | ||||
| 
 | ||||
|     printf("\n->End of shell server execution.\n"); | ||||
| 
 | ||||
|     // The remaining open handles are cleaned up when this process terminates. 
 | ||||
|     // To avoid resource leaks in a larger application, close handles explicitly. 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void CreatePipes() { | ||||
|     SECURITY_ATTRIBUTES saAttr; | ||||
| 
 | ||||
|     // Set the bInheritHandle flag so pipe handles are inherited. 
 | ||||
| 
 | ||||
|     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | ||||
|     saAttr.bInheritHandle = TRUE; | ||||
|     saAttr.lpSecurityDescriptor = NULL; | ||||
| 
 | ||||
|     // Create a pipe for the child process's STDOUT. 
 | ||||
| 
 | ||||
|     if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) | ||||
|         ErrorExit(TEXT("StdoutRd CreatePipe")); | ||||
| 
 | ||||
|     // Ensure the read handle to the pipe for STDOUT is not inherited.
 | ||||
| 
 | ||||
|     if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) | ||||
|         ErrorExit(TEXT("Stdout SetHandleInformation")); | ||||
| 
 | ||||
|     // Create a pipe for the child process's STDIN. 
 | ||||
| 
 | ||||
|     if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) | ||||
|         ErrorExit(TEXT("Stdin CreatePipe")); | ||||
| 
 | ||||
|     // Ensure the write handle to the pipe for STDIN is not inherited. 
 | ||||
| 
 | ||||
|     if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) | ||||
|         ErrorExit(TEXT("Stdin SetHandleInformation")); | ||||
| } | ||||
| 
 | ||||
| // TODO: to review
 | ||||
| void CreateSocket() { | ||||
|     WSADATA wsaData; | ||||
|     struct addrinfo* result = NULL, * ptr = NULL, hints; | ||||
|     int iResult; | ||||
| 
 | ||||
|     SOCKET ClientSocket = INVALID_SOCKET; | ||||
|     SOCKET ListenSocket = INVALID_SOCKET; | ||||
| 
 | ||||
|     int iResult; | ||||
|     /*
 | ||||
|     * Initialize listening socket | ||||
|     */ | ||||
| 
 | ||||
|     // Initialize Winsock
 | ||||
|     iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); | ||||
|  | @ -125,22 +80,87 @@ void CreateSocket() { | |||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     // Accepting a connection
 | ||||
|     ClientSocket = INVALID_SOCKET; | ||||
|     /*
 | ||||
|     * Process client connection | ||||
|     */ | ||||
|     for (;;) { | ||||
|         // Accepting a client connection
 | ||||
|         ClientSocket = INVALID_SOCKET; | ||||
| 
 | ||||
|     // Accept a client socket
 | ||||
|     ClientSocket = accept(ListenSocket, NULL, NULL); | ||||
|     if (ClientSocket == INVALID_SOCKET) { | ||||
|         printf("accept failed: %d\n", WSAGetLastError()); | ||||
|         closesocket(ListenSocket); | ||||
|         WSACleanup(); | ||||
|         return 1; | ||||
|         ClientSocket = accept(ListenSocket, NULL, NULL); | ||||
|         if (ClientSocket == INVALID_SOCKET) { | ||||
|             printf("accept failed: %d\n", WSAGetLastError()); | ||||
|             break; | ||||
|         } | ||||
|         printf("Client connected\n"); | ||||
|         // Create separate thread to process client connection
 | ||||
|         CreateThread(NULL, 0, WorkWithClient, ClientSocket, 0, NULL); | ||||
|     } | ||||
|     // No longer needed
 | ||||
| 
 | ||||
|     /*
 | ||||
|     * Finalization | ||||
|     */ | ||||
|     // TODO: properly close all handles
 | ||||
|     closesocket(ListenSocket); | ||||
|     WSACleanup(); | ||||
| } | ||||
| 
 | ||||
| void CreateChildProcess() | ||||
| DWORD WINAPI WorkWithClient(LPVOID lpParam) { | ||||
|     /*
 | ||||
|     * Client variables | ||||
|     */ | ||||
|     // Pipe handles for child STDIN/STDOUT
 | ||||
|     HANDLE g_hChildStd_IN_Rd = NULL; | ||||
|     HANDLE g_hChildStd_IN_Wr = NULL; | ||||
|     HANDLE g_hChildStd_OUT_Rd = NULL; | ||||
|     HANDLE g_hChildStd_OUT_Wr = NULL; | ||||
| 
 | ||||
|     SECURITY_ATTRIBUTES saAttr; | ||||
|     HANDLE PipeThreads[2]; | ||||
| 
 | ||||
|     SOCKET ClientSocket = (SOCKET)lpParam; | ||||
| 
 | ||||
|     /*
 | ||||
|     * Initialize pipes | ||||
|     */ | ||||
|     // Set the bInheritHandle flag so pipe handles are inherited. 
 | ||||
|     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | ||||
|     saAttr.bInheritHandle = TRUE; | ||||
|     saAttr.lpSecurityDescriptor = NULL; | ||||
| 
 | ||||
|     // Create a pipe for the child process's STDOUT. 
 | ||||
|     if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) | ||||
|         ErrorExit(TEXT("StdoutRd CreatePipe")); | ||||
| 
 | ||||
|     // Ensure the read handle to the pipe for STDOUT is not inherited.
 | ||||
|     if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) | ||||
|         ErrorExit(TEXT("Stdout SetHandleInformation")); | ||||
| 
 | ||||
|     // Create a pipe for the child process's STDIN. 
 | ||||
|     if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) | ||||
|         ErrorExit(TEXT("Stdin CreatePipe")); | ||||
| 
 | ||||
|     // Ensure the write handle to the pipe for STDIN is not inherited. 
 | ||||
|     if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) | ||||
|         ErrorExit(TEXT("Stdin SetHandleInformation")); | ||||
| 
 | ||||
|     /*
 | ||||
|     * Create child process cmd.exe | ||||
|     */ | ||||
|     CreateChildProcess(g_hChildStd_IN_Rd, g_hChildStd_OUT_Wr); | ||||
| 
 | ||||
|     // Create threads for STDIN/STDOUT
 | ||||
|     PipeThreadInfo WriteThreadInfo = { g_hChildStd_IN_Wr, ClientSocket }; | ||||
|     PipeThreadInfo ReadThreadInfo = { g_hChildStd_OUT_Rd, ClientSocket }; | ||||
|     PipeThreads[0] = CreateThread(NULL, 0, WriteToPipe, &WriteThreadInfo, 0, NULL); | ||||
|     PipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &ReadThreadInfo, 0, NULL); | ||||
| 
 | ||||
|     WaitForMultipleObjects(2, PipeThreads, TRUE, INFINITE); | ||||
| 
 | ||||
|     printf("\n->Client disconnected.\n"); | ||||
| } | ||||
| 
 | ||||
| void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr) | ||||
| // Create a child process that uses the previously created pipes for STDIN and STDOUT.
 | ||||
| { | ||||
|     TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe"); | ||||
|  | @ -195,36 +215,31 @@ void CreateChildProcess() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void WriteToPipe(void) | ||||
| 
 | ||||
| // Read from a file and write its contents to the pipe for the child's STDIN.
 | ||||
| // Stop when there is no more data. 
 | ||||
| DWORD WINAPI WriteToPipe(LPVOID lpParam) | ||||
| { | ||||
|     DWORD dwRead, dwWritten; | ||||
|     //CHAR chBuf[BUFSIZE] = "dir\r\n";
 | ||||
|     BOOL bSuccess = FALSE; | ||||
|     int i = 0; | ||||
| 
 | ||||
|     SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket; | ||||
|     HANDLE g_hChildStd_IN_Wr = ((PipeThreadInfo*)lpParam)->Pipe; | ||||
| 
 | ||||
|     char recvbuf[DEFAULT_BUFLEN]; | ||||
|     int iResult, iSendResult; | ||||
|     int recvbuflen = DEFAULT_BUFLEN; | ||||
|      | ||||
| 
 | ||||
|     // Change codepage to UTF-8
 | ||||
|     //CHAR chcpCommand[] = "chcp 65001\n";
 | ||||
|     //bSuccess = WriteFile(g_hChildStd_IN_Wr, chcpCommand, strlen(chcpCommand), &dwWritten, NULL);
 | ||||
|     //if (!bSuccess) goto WriteToPipe_end;
 | ||||
| 
 | ||||
|     do | ||||
|     { | ||||
|         iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); | ||||
|         if (iResult > 0) { | ||||
|             printf("Bytes received: %d\n", iResult); | ||||
| 
 | ||||
|             // Echo the buffer back to the sender
 | ||||
|             iSendResult = send(ClientSocket, recvbuf, iResult, 0); | ||||
|             if (iSendResult == SOCKET_ERROR) { | ||||
|                 printf("send failed: %d\n", WSAGetLastError()); | ||||
|                 closesocket(ClientSocket); | ||||
|                 WSACleanup(); | ||||
|                 return 1; | ||||
|             } | ||||
|             printf("Bytes sent: %d\n", iSendResult); | ||||
|             bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL); | ||||
|             if (!bSuccess) break; | ||||
|             printf("Received command: %s\n"); | ||||
|         } | ||||
|         else if (iResult == 0) | ||||
|             printf("Connection closing...\n"); | ||||
|  | @ -234,40 +249,34 @@ void WriteToPipe(void) | |||
|             WSACleanup(); | ||||
|             return 1; | ||||
|         } | ||||
| 
 | ||||
|         //dwRead = strlen(chBuf) + 1;
 | ||||
|         bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL); | ||||
|         if (!bSuccess) break; | ||||
|         //break;
 | ||||
|         //dwRead = strlen(chBuf) + 1;
 | ||||
|         //bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
 | ||||
|         //if (!bSuccess) break;
 | ||||
|         ReadFromPipe(); | ||||
|     } while (iResult > 0); | ||||
| 
 | ||||
|     // Close the pipe handle so the child process stops reading. 
 | ||||
| 
 | ||||
| WriteToPipe_end: | ||||
|     // Closing STDIN => cmd.exe exit
 | ||||
|     if (!CloseHandle(g_hChildStd_IN_Wr)) | ||||
|         ErrorExit(TEXT("StdInWr CloseHandle")); | ||||
| } | ||||
| 
 | ||||
| void ReadFromPipe(void) | ||||
| 
 | ||||
| // Read output from the child process's pipe for STDOUT
 | ||||
| // and write to the parent process's pipe for STDOUT. 
 | ||||
| // Stop when there is no more data. 
 | ||||
| DWORD WINAPI ReadFromPipe(LPVOID lpParam) | ||||
| { | ||||
|     DWORD dwRead, dwWritten; | ||||
|     CHAR chBuf[BUFSIZE]; | ||||
|     DWORD dwRead; | ||||
|     CHAR chBuf[BUFSIZE + 1]; | ||||
| 
 | ||||
|     BOOL bSuccess = FALSE; | ||||
|     HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); | ||||
|     //HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
 | ||||
|     SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket; | ||||
|     HANDLE g_hChildStd_OUT_Rd = ((PipeThreadInfo*)lpParam)->Pipe; | ||||
| 
 | ||||
|     int iSendResult; | ||||
| 
 | ||||
| 
 | ||||
|     for (;;) | ||||
|     { | ||||
|         bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); | ||||
|         if (!bSuccess || dwRead == 0) break; | ||||
|         printf("STDOUT: %s\n", chBuf); | ||||
|         | ||||
|         chBuf[dwRead] = '\0'; | ||||
| 
 | ||||
|         iSendResult = send(ClientSocket, chBuf, dwRead, 0); | ||||
|         if (iSendResult == SOCKET_ERROR) { | ||||
|  | @ -276,11 +285,7 @@ void ReadFromPipe(void) | |||
|             WSACleanup(); | ||||
|             return 1; | ||||
|         } | ||||
|         // Write to console
 | ||||
|         bSuccess = WriteFile(hParentStdOut, chBuf, | ||||
|             dwRead, &dwWritten, NULL); | ||||
|         if (!bSuccess) break; | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								server.h
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								server.h
									
										
									
									
									
								
							|  | @ -12,11 +12,7 @@ | |||
| #include <winsock2.h> | ||||
| #include <ws2tcpip.h> | ||||
| 
 | ||||
| #define DEFAULT_PORT "50113" | ||||
| 
 | ||||
| // Defined functions
 | ||||
| void StartShellServer(); | ||||
| void CreatePipes(); | ||||
| void CreateChildProcess(void); | ||||
| void WriteToPipe(void); | ||||
| void ReadFromPipe(void); | ||||
| void ErrorExit(PCTSTR); | ||||
| void CreateSocket(); | ||||
| void StartShellServer(); | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue